summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/android/binder.c2
-rw-r--r--drivers/base/power/runtime.c11
-rw-r--r--drivers/char/adsprpc.c3
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c4
-rw-r--r--drivers/cpuidle/lpm-levels.c11
-rw-r--r--drivers/firmware/qcom/tz_log.c14
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h1
-rw-r--r--drivers/gpu/drm/ast/ast_main.c157
-rw-r--r--drivers/gpu/drm/ast/ast_post.c18
-rw-r--r--drivers/gpu/drm/msm/Makefile3
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c102
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c3
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c4
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h3
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c8
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c17
-rw-r--r--drivers/gpu/drm/msm/msm_ringbuffer.h12
-rw-r--r--drivers/gpu/drm/msm/msm_trace.h98
-rw-r--r--drivers/gpu/drm/msm/msm_trace_points.c18
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c24
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.h10
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c27
-rw-r--r--drivers/gpu/drm/msm/sde/sde_formats.c179
-rw-r--r--drivers/gpu/drm/msm/sde/sde_formats.h15
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog.c5
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_cdm.c48
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_cdm.h5
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_interrupts.c17
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdss.h11
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_sspp.c9
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_util.c17
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_util.h4
-rw-r--r--drivers/gpu/drm/msm/sde_edid_parser.c73
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_usif.c3
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c6
-rw-r--r--drivers/i2c/busses/i2c-piix4.c2
-rw-r--r--drivers/iio/proximity/as3935.c6
-rw-r--r--drivers/irqchip/irq-xtensa-mx.c2
-rw-r--r--drivers/irqchip/irq-xtensa-pic.c2
-rw-r--r--drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c33
-rw-r--r--drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c5
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c16
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.c5
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c9
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c35
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c16
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-eeprom.c13
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c2
-rw-r--r--drivers/mfd/omap-usb-tll.c2
-rw-r--r--drivers/misc/c2port/c2port-duramar2150.c4
-rw-r--r--drivers/mmc/core/core.c3
-rw-r--r--drivers/mmc/core/mmc.c2
-rw-r--r--drivers/mmc/host/sdhci-msm.c27
-rw-r--r--drivers/mmc/host/sdhci.c24
-rw-r--r--drivers/net/can/usb/gs_usb.c2
-rw-r--r--drivers/net/ethernet/adaptec/starfire.c45
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/catas.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/intf.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h1
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c112
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c126
-rw-r--r--drivers/net/hamradio/mkiss.c4
-rw-r--r--drivers/net/usb/r8152.c13
-rw-r--r--drivers/net/usb/sierra_net.c111
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c3
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c14
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c31
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h11
-rw-r--r--drivers/net/wireless/cnss/Kconfig1
-rw-r--r--drivers/net/wireless/cnss_utils/Kconfig6
-rw-r--r--drivers/net/wireless/cnss_utils/Makefile1
-rw-r--r--drivers/net/wireless/cnss_utils/cnss_utils.c310
-rw-r--r--drivers/parport/parport_gsc.c8
-rw-r--r--drivers/pinctrl/berlin/berlin-bg4ct.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c3
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c3
-rw-r--r--drivers/platform/msm/ipa/test/ipa_test_mhi.c22
-rw-r--r--drivers/platform/msm/usb_bam.c81
-rw-r--r--drivers/power/supply/qcom/smb-lib.c81
-rw-r--r--drivers/soc/qcom/Kconfig1
-rw-r--r--drivers/spi/spi_qsd.c17
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ap.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c13
-rw-r--r--drivers/tty/serial/efm32-uart.c11
-rw-r--r--drivers/usb/core/hcd.c1
-rw-r--r--drivers/usb/core/hub.c8
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c4
-rw-r--r--drivers/usb/gadget/function/f_audio_source.c4
-rw-r--r--drivers/usb/gadget/legacy/inode.c5
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c19
-rw-r--r--drivers/usb/gadget/udc/net2280.c9
-rw-r--r--drivers/usb/host/r8a66597-hcd.c6
-rw-r--r--drivers/usb/host/xhci-pci.c3
-rw-r--r--drivers/usb/phy/phy-msm-qusb.c14
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c31
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c13
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c39
110 files changed, 1768 insertions, 631 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d1490be45c67..0c3cf182e351 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3778,7 +3778,9 @@ static void binder_deferred_release(struct binder_proc *proc)
page_count++;
}
kfree(proc->pages);
+ preempt_enable_no_resched();
vfree(proc->buffer);
+ preempt_disable();
}
put_task_struct(proc->tsk);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 3252429f96af..3a20dc594338 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -889,13 +889,13 @@ int __pm_runtime_idle(struct device *dev, int rpmflags)
unsigned long flags;
int retval;
- might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
-
if (rpmflags & RPM_GET_PUT) {
if (!atomic_dec_and_test(&dev->power.usage_count))
return 0;
}
+ might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
spin_lock_irqsave(&dev->power.lock, flags);
retval = rpm_idle(dev, rpmflags);
spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -921,13 +921,13 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags)
unsigned long flags;
int retval;
- might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
-
if (rpmflags & RPM_GET_PUT) {
if (!atomic_dec_and_test(&dev->power.usage_count))
return 0;
}
+ might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
spin_lock_irqsave(&dev->power.lock, flags);
retval = rpm_suspend(dev, rpmflags);
spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -952,7 +952,8 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
unsigned long flags;
int retval;
- might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+ might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&
+ dev->power.runtime_status != RPM_ACTIVE);
if (rpmflags & RPM_GET_PUT)
atomic_inc(&dev->power.usage_count);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index ed0226131b90..0c89ab992012 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1140,6 +1140,9 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
if (err)
goto bail;
}
+ if (ctx->buf->virt && metalen <= copylen)
+ memset(ctx->buf->virt, 0, metalen);
+
/* copy metadata */
rpra = ctx->buf->virt;
ctx->rpra = rpra;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 1fa1deb6e91f..c395f9198fd2 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -212,8 +212,8 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
int ret;
ret = sscanf(buf, "%u", &input);
- /* cannot be lower than 11 otherwise freq will not fall */
- if (ret != 1 || input < 11 || input > 100 ||
+ /* cannot be lower than 1 otherwise freq will not fall */
+ if (ret != 1 || input < 1 || input > 100 ||
input >= cs_tuners->up_threshold)
return -EINVAL;
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 7cd1bbbe1ee8..584a1857624a 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -694,22 +694,21 @@ static int cpu_power_select(struct cpuidle_device *dev,
int best_level = -1;
uint32_t latency_us = pm_qos_request_for_cpu(PM_QOS_CPU_DMA_LATENCY,
dev->cpu);
- uint32_t sleep_us =
- (uint32_t)(ktime_to_us(tick_nohz_get_sleep_length()));
+ s64 sleep_us = ktime_to_us(tick_nohz_get_sleep_length());
uint32_t modified_time_us = 0;
uint32_t next_event_us = 0;
int i, idx_restrict;
uint32_t lvl_latency_us = 0;
uint64_t predicted = 0;
uint32_t htime = 0, idx_restrict_time = 0;
- uint32_t next_wakeup_us = sleep_us;
+ uint32_t next_wakeup_us = (uint32_t)sleep_us;
uint32_t *min_residency = get_per_cpu_min_residency(dev->cpu);
uint32_t *max_residency = get_per_cpu_max_residency(dev->cpu);
if (!cpu)
return -EINVAL;
- if (sleep_disabled && !cpu_isolated(dev->cpu))
+ if ((sleep_disabled && !cpu_isolated(dev->cpu)) || sleep_us < 0)
return 0;
idx_restrict = cpu->nlevels + 1;
@@ -750,8 +749,8 @@ static int cpu_power_select(struct cpuidle_device *dev,
if (next_wakeup_us > max_residency[i]) {
predicted = lpm_cpuidle_predict(dev, cpu,
&idx_restrict, &idx_restrict_time);
- if (predicted < min_residency[i])
- predicted = 0;
+ if (predicted && (predicted < min_residency[i]))
+ predicted = min_residency[i];
} else
invalidate_predict_history(dev);
}
diff --git a/drivers/firmware/qcom/tz_log.c b/drivers/firmware/qcom/tz_log.c
index fa90330db93b..c893681f3bf3 100644
--- a/drivers/firmware/qcom/tz_log.c
+++ b/drivers/firmware/qcom/tz_log.c
@@ -477,10 +477,10 @@ static int _disp_tz_reset_stats(void)
static int _disp_tz_interrupt_stats(void)
{
- int i, j, int_info_size;
+ int i, j;
int len = 0;
int *num_int;
- unsigned char *ptr;
+ void *ptr;
struct tzdbg_int_t *tzdbg_ptr;
struct tzdbg_int_t_tz40 *tzdbg_ptr_tz40;
@@ -488,14 +488,12 @@ static int _disp_tz_interrupt_stats(void)
(tzdbg.diag_buf->int_info_off - sizeof(uint32_t)));
ptr = ((unsigned char *)tzdbg.diag_buf +
tzdbg.diag_buf->int_info_off);
- int_info_size = ((tzdbg.diag_buf->ring_off -
- tzdbg.diag_buf->int_info_off)/(*num_int));
pr_info("qsee_version = 0x%x\n", tzdbg.tz_version);
if (tzdbg.tz_version < QSEE_VERSION_TZ_4_X) {
+ tzdbg_ptr = ptr;
for (i = 0; i < (*num_int); i++) {
- tzdbg_ptr = (struct tzdbg_int_t *)ptr;
len += snprintf(tzdbg.disp_buf + len,
(debug_rw_buf_size - 1) - len,
" Interrupt Number : 0x%x\n"
@@ -519,11 +517,11 @@ static int _disp_tz_interrupt_stats(void)
__func__);
break;
}
- ptr += int_info_size;
+ tzdbg_ptr++;
}
} else {
+ tzdbg_ptr_tz40 = ptr;
for (i = 0; i < (*num_int); i++) {
- tzdbg_ptr_tz40 = (struct tzdbg_int_t_tz40 *)ptr;
len += snprintf(tzdbg.disp_buf + len,
(debug_rw_buf_size - 1) - len,
" Interrupt Number : 0x%x\n"
@@ -547,7 +545,7 @@ static int _disp_tz_interrupt_stats(void)
__func__);
break;
}
- ptr += int_info_size;
+ tzdbg_ptr_tz40++;
}
}
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 05f6522c0457..b92139e9b9d8 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -113,6 +113,7 @@ struct ast_private {
struct ttm_bo_kmap_obj cache_kmap;
int next_cursor;
bool support_wide_screen;
+ bool DisableP2A;
enum ast_tx_chip tx_chip_type;
u8 dp501_maxclk;
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 9b8f0b975ca6..6c021165ca67 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -124,6 +124,12 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
} else
*need_post = false;
+ /* Check P2A Access */
+ ast->DisableP2A = true;
+ data = ast_read32(ast, 0xf004);
+ if (data != 0xFFFFFFFF)
+ ast->DisableP2A = false;
+
/* Check if we support wide screen */
switch (ast->chip) {
case AST1180:
@@ -140,15 +146,17 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
ast->support_wide_screen = true;
else {
ast->support_wide_screen = false;
- /* Read SCU7c (silicon revision register) */
- ast_write32(ast, 0xf004, 0x1e6e0000);
- ast_write32(ast, 0xf000, 0x1);
- data = ast_read32(ast, 0x1207c);
- data &= 0x300;
- if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
- ast->support_wide_screen = true;
- if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
- ast->support_wide_screen = true;
+ if (ast->DisableP2A == false) {
+ /* Read SCU7c (silicon revision register) */
+ ast_write32(ast, 0xf004, 0x1e6e0000);
+ ast_write32(ast, 0xf000, 0x1);
+ data = ast_read32(ast, 0x1207c);
+ data &= 0x300;
+ if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
+ ast->support_wide_screen = true;
+ if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
+ ast->support_wide_screen = true;
+ }
}
break;
}
@@ -216,80 +224,81 @@ static int ast_get_dram_info(struct drm_device *dev)
uint32_t data, data2;
uint32_t denum, num, div, ref_pll;
- ast_write32(ast, 0xf004, 0x1e6e0000);
- ast_write32(ast, 0xf000, 0x1);
-
-
- ast_write32(ast, 0x10000, 0xfc600309);
-
- do {
- if (pci_channel_offline(dev->pdev))
- return -EIO;
- } while (ast_read32(ast, 0x10000) != 0x01);
- data = ast_read32(ast, 0x10004);
-
- if (data & 0x40)
+ if (ast->DisableP2A)
+ {
ast->dram_bus_width = 16;
+ ast->dram_type = AST_DRAM_1Gx16;
+ ast->mclk = 396;
+ }
else
- ast->dram_bus_width = 32;
+ {
+ ast_write32(ast, 0xf004, 0x1e6e0000);
+ ast_write32(ast, 0xf000, 0x1);
+ data = ast_read32(ast, 0x10004);
+
+ if (data & 0x40)
+ ast->dram_bus_width = 16;
+ else
+ ast->dram_bus_width = 32;
+
+ if (ast->chip == AST2300 || ast->chip == AST2400) {
+ switch (data & 0x03) {
+ case 0:
+ ast->dram_type = AST_DRAM_512Mx16;
+ break;
+ default:
+ case 1:
+ ast->dram_type = AST_DRAM_1Gx16;
+ break;
+ case 2:
+ ast->dram_type = AST_DRAM_2Gx16;
+ break;
+ case 3:
+ ast->dram_type = AST_DRAM_4Gx16;
+ break;
+ }
+ } else {
+ switch (data & 0x0c) {
+ case 0:
+ case 4:
+ ast->dram_type = AST_DRAM_512Mx16;
+ break;
+ case 8:
+ if (data & 0x40)
+ ast->dram_type = AST_DRAM_1Gx16;
+ else
+ ast->dram_type = AST_DRAM_512Mx32;
+ break;
+ case 0xc:
+ ast->dram_type = AST_DRAM_1Gx32;
+ break;
+ }
+ }
- if (ast->chip == AST2300 || ast->chip == AST2400) {
- switch (data & 0x03) {
- case 0:
- ast->dram_type = AST_DRAM_512Mx16;
- break;
- default:
- case 1:
- ast->dram_type = AST_DRAM_1Gx16;
- break;
- case 2:
- ast->dram_type = AST_DRAM_2Gx16;
- break;
+ data = ast_read32(ast, 0x10120);
+ data2 = ast_read32(ast, 0x10170);
+ if (data2 & 0x2000)
+ ref_pll = 14318;
+ else
+ ref_pll = 12000;
+
+ denum = data & 0x1f;
+ num = (data & 0x3fe0) >> 5;
+ data = (data & 0xc000) >> 14;
+ switch (data) {
case 3:
- ast->dram_type = AST_DRAM_4Gx16;
- break;
- }
- } else {
- switch (data & 0x0c) {
- case 0:
- case 4:
- ast->dram_type = AST_DRAM_512Mx16;
+ div = 0x4;
break;
- case 8:
- if (data & 0x40)
- ast->dram_type = AST_DRAM_1Gx16;
- else
- ast->dram_type = AST_DRAM_512Mx32;
+ case 2:
+ case 1:
+ div = 0x2;
break;
- case 0xc:
- ast->dram_type = AST_DRAM_1Gx32;
+ default:
+ div = 0x1;
break;
}
+ ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
}
-
- data = ast_read32(ast, 0x10120);
- data2 = ast_read32(ast, 0x10170);
- if (data2 & 0x2000)
- ref_pll = 14318;
- else
- ref_pll = 12000;
-
- denum = data & 0x1f;
- num = (data & 0x3fe0) >> 5;
- data = (data & 0xc000) >> 14;
- switch (data) {
- case 3:
- div = 0x4;
- break;
- case 2:
- case 1:
- div = 0x2;
- break;
- default:
- div = 0x1;
- break;
- }
- ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
return 0;
}
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 30672a3df8a9..270e8fb2803f 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -375,12 +375,20 @@ void ast_post_gpu(struct drm_device *dev)
ast_enable_mmio(dev);
ast_set_def_ext_reg(dev);
- if (ast->chip == AST2300 || ast->chip == AST2400)
- ast_init_dram_2300(dev);
- else
- ast_init_dram_reg(dev);
+ if (ast->DisableP2A == false)
+ {
+ if (ast->chip == AST2300 || ast->chip == AST2400)
+ ast_init_dram_2300(dev);
+ else
+ ast_init_dram_reg(dev);
- ast_init_3rdtx(dev);
+ ast_init_3rdtx(dev);
+ }
+ else
+ {
+ if (ast->tx_chip_type != AST_TX_NONE)
+ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */
+ }
}
/* AST 2300 DRAM settings */
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 999d5e45e5c5..84125b3d1f95 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -149,6 +149,7 @@ msm_drm-$(CONFIG_DRM_MSM) += \
msm_ringbuffer.o \
msm_prop.o \
msm_snapshot.o \
- msm_submitqueue.o
+ msm_submitqueue.o \
+ msm_trace_points.o
obj-$(CONFIG_DRM_MSM) += msm_drm.o
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index f8dbc843f852..e27ea604ac5b 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -13,6 +13,7 @@
#include "msm_gem.h"
#include "msm_iommu.h"
+#include "msm_trace.h"
#include "a5xx_gpu.h"
#define SECURE_VA_START 0xc0000000
@@ -100,12 +101,32 @@ static void a5xx_set_pagetable(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
OUT_RING(ring, 1);
}
+/* Inline PM4 code to get the current value of the 19.2 Mhz always on counter */
+static void a5xx_get_ticks(struct msm_ringbuffer *ring, uint64_t iova)
+{
+ /*
+ * Set bit[30] to make this command a 64 bit write operation.
+ * bits[18-29] is to specify number of consecutive registers
+ * to copy, so set this space with 2, since we want to copy
+ * data from REG_A5XX_RBBM_ALWAYSON_COUNTER_LO and [HI].
+ */
+
+ OUT_PKT7(ring, CP_REG_TO_MEM, 3);
+ OUT_RING(ring, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO |
+ (1 << 30) | (2 << 18));
+ OUT_RING(ring, lower_32_bits(iova));
+ OUT_RING(ring, upper_32_bits(iova));
+}
+
static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
struct msm_ringbuffer *ring = gpu->rb[submit->ring];
unsigned int i, ibs = 0;
+ unsigned long flags;
+ u64 ticks;
+ ktime_t time;
a5xx_set_pagetable(gpu, ring, submit->aspace);
@@ -139,24 +160,15 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_RING(ring, 1);
}
- /* Record the always on counter before command execution */
- if (submit->profile_buf_iova) {
- uint64_t gpuaddr = submit->profile_buf_iova +
- offsetof(struct drm_msm_gem_submit_profile_buffer,
- ticks_submitted);
+ /* Record the GPU ticks at command start for kernel side profiling */
+ a5xx_get_ticks(ring,
+ RING_TICKS_IOVA(ring, submit->tick_index, started));
- /*
- * Set bit[30] to make this command a 64 bit write operation.
- * bits[18-29] is to specify number of consecutive registers
- * to copy, so set this space with 2, since we want to copy
- * data from REG_A5XX_RBBM_ALWAYSON_COUNTER_LO and [HI].
- */
- OUT_PKT7(ring, CP_REG_TO_MEM, 3);
- OUT_RING(ring, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO |
- (1 << 30) | (2 << 18));
- OUT_RING(ring, lower_32_bits(gpuaddr));
- OUT_RING(ring, upper_32_bits(gpuaddr));
- }
+ /* And for the user profiling too if it is enabled */
+ if (submit->profile_buf_iova)
+ a5xx_get_ticks(ring, submit->profile_buf_iova +
+ offsetof(struct drm_msm_gem_submit_profile_buffer,
+ ticks_submitted));
/* Submit the commands */
for (i = 0; i < submit->nr_cmds; i++) {
@@ -190,18 +202,15 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_PKT7(ring, CP_YIELD_ENABLE, 1);
OUT_RING(ring, 0x01);
+ /* Record the GPU ticks at command retire for kernel side profiling */
+ a5xx_get_ticks(ring,
+ RING_TICKS_IOVA(ring, submit->tick_index, retired));
+
/* Record the always on counter after command execution */
- if (submit->profile_buf_iova) {
- uint64_t gpuaddr = submit->profile_buf_iova +
+ if (submit->profile_buf_iova)
+ a5xx_get_ticks(ring, submit->profile_buf_iova +
offsetof(struct drm_msm_gem_submit_profile_buffer,
- ticks_retired);
-
- OUT_PKT7(ring, CP_REG_TO_MEM, 3);
- OUT_RING(ring, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO |
- (1 << 30) | (2 << 18));
- OUT_RING(ring, lower_32_bits(gpuaddr));
- OUT_RING(ring, upper_32_bits(gpuaddr));
- }
+ ticks_retired));
/* Write the fence to the scratch register */
OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1);
@@ -237,33 +246,28 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
/* Set bit 0 to trigger an interrupt on preempt complete */
OUT_RING(ring, 0x01);
- if (submit->profile_buf_iova) {
- unsigned long flags;
- uint64_t ktime;
- struct drm_msm_gem_submit_profile_buffer *profile_buf =
- submit->profile_buf_vaddr;
-
- /*
- * With this profiling, we are trying to create closest
- * possible mapping between the CPU time domain(monotonic clock)
- * and the GPU time domain(ticks). In order to make this
- * happen, we need to briefly turn off interrupts to make sure
- * interrupts do not run between collecting these two samples.
- */
- local_irq_save(flags);
-
- profile_buf->ticks_queued = gpu_read64(gpu,
- REG_A5XX_RBBM_ALWAYSON_COUNTER_LO,
- REG_A5XX_RBBM_ALWAYSON_COUNTER_HI);
+ /*
+ * Get the current kernel time and ticks with interrupts off so we don't
+ * get interrupted between the operations and skew the numbers
+ */
- ktime = ktime_get_raw_ns();
+ local_irq_save(flags);
+ ticks = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO,
+ REG_A5XX_RBBM_ALWAYSON_COUNTER_HI);
+ time = ktime_get_raw();
+ local_irq_restore(flags);
- local_irq_restore(flags);
+ if (submit->profile_buf) {
+ struct timespec64 ts = ktime_to_timespec64(time);
- profile_buf->queue_time = ktime;
- profile_buf->submit_time = ktime;
+ /* Write the data into the user-specified profile buffer */
+ submit->profile_buf->time.tv_sec = ts.tv_sec;
+ submit->profile_buf->time.tv_nsec = ts.tv_nsec;
+ submit->profile_buf->ticks_queued = ticks;
}
+ trace_msm_submitted(submit, ticks, ktime_to_ns(time));
+
a5xx_flush(gpu, ring);
/* Check to see if we need to start preemption */
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 9f3d957499d3..2a5683e3034b 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -51,6 +51,9 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
if (adreno_gpu->funcs->get_timestamp)
return adreno_gpu->funcs->get_timestamp(gpu, value);
return -EINVAL;
+ case MSM_PARAM_NR_RINGS:
+ *value = gpu->nr_rings;
+ return 0;
default:
DBG("%s: invalid param: %u", gpu->name, param);
return -EINVAL;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 367e701b59cb..2280f8cb7183 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -316,8 +316,8 @@ static int get_mdp_ver(struct platform_device *pdev)
static const struct of_device_id match_types[] = { {
.compatible = "qcom,sde-kms",
.data = (void *)KMS_SDE,
- /* end node */
- } };
+ },
+ {} };
struct device *dev = &pdev->dev;
const struct of_device_id *match;
match = of_match_node(match_types, dev->of_node);
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index e8528892939f..df9ddadc5c5c 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -151,9 +151,10 @@ struct msm_gem_submit {
u32 flags;
bool valid;
uint64_t profile_buf_iova;
- void *profile_buf_vaddr;
+ struct drm_msm_gem_submit_profile_buffer *profile_buf;
bool secure;
struct msm_gpu_submitqueue *queue;
+ int tick_index;
unsigned int nr_cmds;
unsigned int nr_bos;
struct {
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 7ccc146f3ae1..b73379aa9ed7 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -18,6 +18,7 @@
#include "msm_drv.h"
#include "msm_gpu.h"
#include "msm_gem.h"
+#include "msm_trace.h"
/*
* Cmdstream submission:
@@ -55,7 +56,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
submit->nr_bos = 0;
submit->nr_cmds = 0;
- submit->profile_buf_vaddr = NULL;
+ submit->profile_buf = NULL;
submit->profile_buf_iova = 0;
submit->cmd = (void *)&submit->bos[nr_bos];
@@ -510,9 +511,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
if (submit_cmd.type == MSM_SUBMIT_CMD_PROFILE_BUF) {
submit->profile_buf_iova = submit->cmd[i].iova;
- submit->profile_buf_vaddr =
- msm_gem_vaddr(&msm_obj->base) +
- submit_cmd.submit_offset;
+ submit->profile_buf = msm_gem_vaddr(&msm_obj->base)
+ + submit_cmd.submit_offset;
}
if (submit->valid)
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index d896e436251f..6bac1cf6f7c5 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -18,7 +18,7 @@
#include "msm_gpu.h"
#include "msm_gem.h"
#include "msm_mmu.h"
-
+#include "msm_trace.h"
/*
* Power Management:
@@ -494,9 +494,18 @@ static void retire_submits(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
list_for_each_entry_safe(submit, tmp, &ring->submits, node) {
+ struct msm_memptr_ticks *ticks;
+
if (submit->fence > fence)
break;
+ ticks = &(ring->memptrs->ticks[submit->tick_index]);
+
+ /* Add memory barrier to ensure the timer ticks are posted */
+ rmb();
+
+ trace_msm_retired(submit, ticks->started, ticks->retired);
+
msm_gem_submit_free(submit);
}
}
@@ -578,6 +587,12 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
ring->submitted_fence = submit->fence;
+ submit->tick_index = ring->tick_index;
+ ring->tick_index = (ring->tick_index + 1) %
+ ARRAY_SIZE(ring->memptrs->ticks);
+
+ trace_msm_queued(submit);
+
update_sw_cntrs(gpu);
for (i = 0; i < submit->nr_bos; i++) {
diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h b/drivers/gpu/drm/msm/msm_ringbuffer.h
index 3eb9a86b2a2e..b19ce75a4cc9 100644
--- a/drivers/gpu/drm/msm/msm_ringbuffer.h
+++ b/drivers/gpu/drm/msm/msm_ringbuffer.h
@@ -23,13 +23,24 @@
#define rbmemptr(ring, member) \
((ring)->memptrs_iova + offsetof(struct msm_memptrs, member))
+struct msm_memptr_ticks {
+ uint64_t started;
+ uint64_t retired;
+};
+
struct msm_memptrs {
volatile uint32_t rptr;
volatile uint32_t fence;
volatile uint64_t ttbr0;
volatile unsigned int contextidr;
+ struct msm_memptr_ticks ticks[128];
};
+#define RING_TICKS_IOVA(ring, index, field) \
+ ((ring)->memptrs_iova + offsetof(struct msm_memptrs, ticks) + \
+ ((index) * sizeof(struct msm_memptr_ticks)) + \
+ offsetof(struct msm_memptr_ticks, field))
+
struct msm_ringbuffer {
struct msm_gpu *gpu;
int id;
@@ -42,6 +53,7 @@ struct msm_ringbuffer {
struct msm_memptrs *memptrs;
uint64_t memptrs_iova;
+ int tick_index;
};
struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
diff --git a/drivers/gpu/drm/msm/msm_trace.h b/drivers/gpu/drm/msm/msm_trace.h
new file mode 100644
index 000000000000..68c7ff78ffc2
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_trace.h
@@ -0,0 +1,98 @@
+/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#if !defined(_MSM_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _MSM_TRACE_H_
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM msm_drm
+#define TRACE_INCLUDE_FILE msm_trace
+
+TRACE_EVENT(msm_queued,
+ TP_PROTO(struct msm_gem_submit *submit),
+ TP_ARGS(submit),
+ TP_STRUCT__entry(
+ __field(uint32_t, queue_id)
+ __field(uint32_t, fence_id)
+ __field(int, ring)
+ ),
+ TP_fast_assign(
+ __entry->queue_id = submit->queue->id;
+ __entry->fence_id = submit->fence;
+ __entry->ring = submit->ring;
+ ),
+ TP_printk(
+ "queue=%u fence=%u ring=%d",
+ __entry->queue_id, __entry->fence_id, __entry->ring
+ )
+);
+
+TRACE_EVENT(msm_submitted,
+ TP_PROTO(struct msm_gem_submit *submit, uint64_t ticks, uint64_t nsecs),
+ TP_ARGS(submit, ticks, nsecs),
+ TP_STRUCT__entry(
+ __field(uint32_t, queue_id)
+ __field(uint32_t, fence_id)
+ __field(int, ring)
+ __field(uint64_t, ticks)
+ __field(uint64_t, nsecs)
+ ),
+ TP_fast_assign(
+ __entry->queue_id = submit->queue->id;
+ __entry->fence_id = submit->fence;
+ __entry->ring = submit->ring;
+ __entry->ticks = ticks;
+ __entry->nsecs = nsecs;
+ ),
+ TP_printk(
+ "queue=%u fence=%u ring=%d ticks=%lld nsecs=%llu",
+ __entry->queue_id, __entry->fence_id, __entry->ring,
+ __entry->ticks, __entry->nsecs
+ )
+);
+
+TRACE_EVENT(msm_retired,
+ TP_PROTO(struct msm_gem_submit *submit, uint64_t start_ticks,
+ uint64_t retire_ticks),
+ TP_ARGS(submit, start_ticks, retire_ticks),
+ TP_STRUCT__entry(
+ __field(uint32_t, queue_id)
+ __field(uint32_t, fence_id)
+ __field(int, ring)
+ __field(uint64_t, start_ticks)
+ __field(uint64_t, retire_ticks)
+ ),
+ TP_fast_assign(
+ __entry->queue_id = submit->queue->id;
+ __entry->fence_id = submit->fence;
+ __entry->ring = submit->ring;
+ __entry->start_ticks = start_ticks;
+ __entry->retire_ticks = retire_ticks;
+ ),
+ TP_printk(
+ "queue=%u fence=%u ring=%d started=%lld retired=%lld",
+ __entry->queue_id, __entry->fence_id, __entry->ring,
+ __entry->start_ticks, __entry->retire_ticks
+ )
+);
+
+
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
+
diff --git a/drivers/gpu/drm/msm/msm_trace_points.c b/drivers/gpu/drm/msm/msm_trace_points.c
new file mode 100644
index 000000000000..41d9a975ac92
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_trace_points.c
@@ -0,0 +1,18 @@
+/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_gem.h"
+#include "msm_gpu.h"
+
+#define CREATE_TRACE_POINTS
+#include "msm_trace.h"
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 238d34419bf6..7d2291dadc18 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -368,12 +368,6 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc,
cstate->is_rt = true;
}
- if (cstate->num_connectors > 0 && cstate->connectors[0]->encoder)
- cstate->intf_mode = sde_encoder_get_intf_mode(
- cstate->connectors[0]->encoder);
- else
- cstate->intf_mode = INTF_MODE_NONE;
-
/* prepare main output fence */
sde_fence_prepare(&sde_crtc->output_fence);
}
@@ -424,6 +418,22 @@ static void _sde_crtc_complete_flip(struct drm_crtc *crtc,
spin_unlock_irqrestore(&dev->event_lock, flags);
}
+enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc)
+{
+ struct drm_encoder *encoder;
+
+ if (!crtc || !crtc->dev) {
+ SDE_ERROR("invalid crtc\n");
+ return INTF_MODE_NONE;
+ }
+
+ drm_for_each_encoder(encoder, crtc->dev)
+ if (encoder->crtc == crtc)
+ return sde_encoder_get_intf_mode(encoder);
+
+ return INTF_MODE_NONE;
+}
+
static void sde_crtc_vblank_cb(void *data)
{
struct drm_crtc *crtc = (struct drm_crtc *)data;
@@ -1665,7 +1675,7 @@ static int sde_crtc_debugfs_state_show(struct seq_file *s, void *v)
seq_printf(s, "num_connectors: %d\n", cstate->num_connectors);
seq_printf(s, "is_rt: %d\n", cstate->is_rt);
- seq_printf(s, "intf_mode: %d\n", cstate->intf_mode);
+ seq_printf(s, "intf_mode: %d\n", sde_crtc_get_intf_mode(crtc));
seq_printf(s, "bw_ctl: %llu\n", cstate->cur_perf.bw_ctl);
seq_printf(s, "core_clk_rate: %u\n", cstate->cur_perf.core_clk_rate);
seq_printf(s, "max_per_pipe_ib: %llu\n",
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 97a20b987ef5..aaa815c76c4e 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -246,16 +246,10 @@ void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
bool sde_crtc_is_rt(struct drm_crtc *crtc);
/**
- * sde_crtc_get_intf_mode - get interface mode of the given crtc
+ * sde_crtc_get_intf_mode - get primary interface mode of the given crtc
* @crtc: Pointert to crtc
*/
-static inline enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc)
-{
- struct sde_crtc_state *cstate =
- crtc ? to_sde_crtc_state(crtc->state) : NULL;
-
- return cstate ? cstate->intf_mode : INTF_MODE_NONE;
-}
+enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc);
/**
* sde_core_perf_crtc_is_wb - check if writeback is primary output of this crtc
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
index 9368c4974126..a48962a2384b 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
@@ -28,6 +28,24 @@
#define WBID(wb_enc) ((wb_enc) ? wb_enc->wb_dev->wb_idx : -1)
+#define TO_S15D16(_x_) ((_x_) << 7)
+
+/**
+ * sde_rgb2yuv_601l - rgb to yuv color space conversion matrix
+ *
+ */
+static struct sde_csc_cfg sde_encoder_phys_wb_rgb2yuv_601l = {
+ {
+ TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
+ TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
+ TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
+ },
+ { 0x00, 0x00, 0x00 },
+ { 0x0040, 0x0200, 0x0200 },
+ { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
+ { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
+};
+
/**
* sde_encoder_phys_wb_is_master - report wb always as master encoder
*/
@@ -150,6 +168,15 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
cdm_cfg->h_cdwn_type,
cdm_cfg->v_cdwn_type);
+ if (hw_cdm && hw_cdm->ops.setup_csc_data) {
+ ret = hw_cdm->ops.setup_csc_data(hw_cdm,
+ &sde_encoder_phys_wb_rgb2yuv_601l);
+ if (ret < 0) {
+ SDE_ERROR("failed to setup CSC %d\n", ret);
+ return;
+ }
+ }
+
if (hw_cdm && hw_cdm->ops.setup_cdwn) {
ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
if (ret < 0) {
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.c b/drivers/gpu/drm/msm/sde/sde_formats.c
index 49b3d8e96938..2187d221a352 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.c
+++ b/drivers/gpu/drm/msm/sde/sde_formats.c
@@ -10,6 +10,8 @@
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
+
#include <uapi/drm/drm_fourcc.h>
#include <uapi/media/msm_media_info.h>
@@ -408,6 +410,82 @@ static const struct sde_format sde_format_map[] = {
};
/*
+ * A5x tile formats tables:
+ * These tables hold the A5x tile formats supported.
+ */
+static const struct sde_format sde_format_map_tile[] = {
+ INTERLEAVED_RGB_FMT(ARGB8888,
+ COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
+ true, 4, 0,
+ SDE_FETCH_UBWC, 1),
+
+ INTERLEAVED_RGB_FMT(ABGR8888,
+ COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
+ true, 4, 0,
+ SDE_FETCH_UBWC, 1),
+
+ INTERLEAVED_RGB_FMT(RGBA8888,
+ COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
+ true, 4, 0,
+ SDE_FETCH_UBWC, 1),
+
+ INTERLEAVED_RGB_FMT(BGRA8888,
+ COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
+ true, 4, 0,
+ SDE_FETCH_UBWC, 1),
+
+ INTERLEAVED_RGB_FMT(BGRX8888,
+ COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
+ false, 4, 0,
+ SDE_FETCH_UBWC, 1),
+
+ INTERLEAVED_RGB_FMT(XRGB8888,
+ COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
+ false, 4, 0,
+ SDE_FETCH_UBWC, 1),
+
+ INTERLEAVED_RGB_FMT(RGBX8888,
+ COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
+ false, 4, 0,
+ SDE_FETCH_UBWC, 1),
+
+ PSEUDO_YUV_FMT(NV12,
+ 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C2_R_Cr,
+ SDE_CHROMA_420, SDE_FORMAT_FLAG_YUV,
+ SDE_FETCH_UBWC, 2),
+
+ PSEUDO_YUV_FMT(NV21,
+ 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C2_R_Cr, C1_B_Cb,
+ SDE_CHROMA_420, SDE_FORMAT_FLAG_YUV,
+ SDE_FETCH_UBWC, 2),
+};
+
+static const struct sde_format sde_format_map_p010_tile[] = {
+ PSEUDO_YUV_FMT_LOOSE(NV12,
+ 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C2_R_Cr,
+ SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX),
+ SDE_FETCH_UBWC, 2),
+};
+
+static const struct sde_format sde_format_map_tp10_tile[] = {
+ PSEUDO_YUV_FMT(NV12,
+ 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C2_R_Cr,
+ SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX),
+ SDE_FETCH_UBWC, 2),
+};
+
+/*
* UBWC formats table:
* This table holds the UBWC formats supported.
* If a compression ratio needs to be used for this or any other format,
@@ -417,37 +495,38 @@ static const struct sde_format sde_format_map_ubwc[] = {
INTERLEAVED_RGB_FMT(BGR565,
0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
- false, 2, 0,
+ false, 2, SDE_FORMAT_FLAG_COMPRESSED,
SDE_FETCH_UBWC, 2),
INTERLEAVED_RGB_FMT(ABGR8888,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
- true, 4, 0,
+ true, 4, SDE_FORMAT_FLAG_COMPRESSED,
SDE_FETCH_UBWC, 2),
INTERLEAVED_RGB_FMT(XBGR8888,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
- false, 4, 0,
+ false, 4, SDE_FORMAT_FLAG_COMPRESSED,
SDE_FETCH_UBWC, 2),
INTERLEAVED_RGB_FMT(ABGR2101010,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
- true, 4, SDE_FORMAT_FLAG_DX,
+ true, 4, SDE_FORMAT_FLAG_DX | SDE_FORMAT_FLAG_COMPRESSED,
SDE_FETCH_UBWC, 2),
INTERLEAVED_RGB_FMT(XBGR2101010,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
- true, 4, SDE_FORMAT_FLAG_DX,
+ true, 4, SDE_FORMAT_FLAG_DX | SDE_FORMAT_FLAG_COMPRESSED,
SDE_FETCH_UBWC, 2),
PSEUDO_YUV_FMT(NV12,
0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C1_B_Cb, C2_R_Cr,
- SDE_CHROMA_420, SDE_FORMAT_FLAG_YUV,
+ SDE_CHROMA_420, SDE_FORMAT_FLAG_YUV |
+ SDE_FORMAT_FLAG_COMPRESSED,
SDE_FETCH_UBWC, 4),
};
@@ -463,7 +542,8 @@ static const struct sde_format sde_format_map_p010_ubwc[] = {
PSEUDO_YUV_FMT_LOOSE(NV12,
0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C1_B_Cb, C2_R_Cr,
- SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX),
+ SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX |
+ SDE_FORMAT_FLAG_COMPRESSED),
SDE_FETCH_UBWC, 4),
};
@@ -471,7 +551,8 @@ static const struct sde_format sde_format_map_tp10_ubwc[] = {
PSEUDO_YUV_FMT(NV12,
0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C1_B_Cb, C2_R_Cr,
- SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX),
+ SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX |
+ SDE_FORMAT_FLAG_COMPRESSED),
SDE_FETCH_UBWC, 4),
};
@@ -545,6 +626,7 @@ static int _sde_format_get_plane_sizes_ubwc(
{
int i;
int color;
+ bool meta = SDE_FORMAT_IS_UBWC(fmt);
memset(layout, 0, sizeof(struct sde_hw_fmt_layout));
layout->format = fmt;
@@ -564,7 +646,7 @@ static int _sde_format_get_plane_sizes_ubwc(
uint32_t y_meta_scanlines = 0;
uint32_t uv_meta_scanlines = 0;
- layout->num_planes = 4;
+ layout->num_planes = 2;
layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
y_sclines = VENUS_Y_SCANLINES(color, height);
layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
@@ -575,6 +657,10 @@ static int _sde_format_get_plane_sizes_ubwc(
layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
uv_sclines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
+ if (!meta)
+ goto done;
+
+ layout->num_planes += 2;
layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
@@ -588,19 +674,23 @@ static int _sde_format_get_plane_sizes_ubwc(
} else {
uint32_t rgb_scanlines, rgb_meta_scanlines;
- layout->num_planes = 3;
+ layout->num_planes = 1;
layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
rgb_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
+ if (!meta)
+ goto done;
+ layout->num_planes += 2;
layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
rgb_meta_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
}
+done:
for (i = 0; i < SDE_MAX_PLANES; i++)
layout->total_size += layout->plane_size[i];
@@ -667,7 +757,7 @@ static int _sde_format_get_plane_sizes_linear(
return 0;
}
-static int _sde_format_get_plane_sizes(
+int sde_format_get_plane_sizes(
const struct sde_format *fmt,
const uint32_t w,
const uint32_t h,
@@ -683,7 +773,7 @@ static int _sde_format_get_plane_sizes(
return -ERANGE;
}
- if (SDE_FORMAT_IS_UBWC(fmt))
+ if (SDE_FORMAT_IS_UBWC(fmt) || SDE_FORMAT_IS_TILE(fmt))
return _sde_format_get_plane_sizes_ubwc(fmt, w, h, layout);
return _sde_format_get_plane_sizes_linear(fmt, w, h, layout);
@@ -695,6 +785,7 @@ static int _sde_format_populate_addrs_ubwc(
struct sde_hw_fmt_layout *layout)
{
uint32_t base_addr;
+ bool meta;
if (!fb || !layout) {
DRM_ERROR("invalid pointers\n");
@@ -707,6 +798,8 @@ static int _sde_format_populate_addrs_ubwc(
return -EFAULT;
}
+ meta = SDE_FORMAT_IS_UBWC(layout->format);
+
/* Per-format logic for verifying active planes */
if (SDE_FORMAT_IS_YUV(layout->format)) {
/************************************************/
@@ -736,6 +829,9 @@ static int _sde_format_populate_addrs_ubwc(
layout->plane_addr[1] = base_addr + layout->plane_size[0]
+ layout->plane_size[2] + layout->plane_size[3];
+ if (!meta)
+ goto done;
+
/* configure Y metadata plane */
layout->plane_addr[2] = base_addr;
@@ -763,10 +859,14 @@ static int _sde_format_populate_addrs_ubwc(
layout->plane_addr[0] = base_addr + layout->plane_size[2];
layout->plane_addr[1] = 0;
+
+ if (!meta)
+ goto done;
+
layout->plane_addr[2] = base_addr;
layout->plane_addr[3] = 0;
}
-
+done:
return 0;
}
@@ -820,7 +920,7 @@ int sde_format_populate_layout(
layout->format = to_sde_format(msm_framebuffer_format(fb));
/* Populate the plane sizes etc via get_format */
- ret = _sde_format_get_plane_sizes(layout->format, fb->width, fb->height,
+ ret = sde_format_get_plane_sizes(layout->format, fb->width, fb->height,
layout);
if (ret)
return ret;
@@ -829,7 +929,8 @@ int sde_format_populate_layout(
plane_addr[i] = layout->plane_addr[i];
/* Populate the addresses given the fb */
- if (SDE_FORMAT_IS_UBWC(layout->format))
+ if (SDE_FORMAT_IS_UBWC(layout->format) ||
+ SDE_FORMAT_IS_TILE(layout->format))
ret = _sde_format_populate_addrs_ubwc(aspace, fb, layout);
else
ret = _sde_format_populate_addrs_linear(aspace, fb, layout);
@@ -923,7 +1024,7 @@ int sde_format_check_modified_format(
fmt = to_sde_format(msm_fmt);
num_base_fmt_planes = drm_format_num_planes(fmt->base.pixel_format);
- ret = _sde_format_get_plane_sizes(fmt, cmd->width, cmd->height,
+ ret = sde_format_get_plane_sizes(fmt, cmd->width, cmd->height,
&layout);
if (ret)
return ret;
@@ -962,14 +1063,14 @@ const struct sde_format *sde_get_sde_format_ext(
* All planes used must specify the same modifier.
*/
if (modifiers_len && !modifiers) {
- DRM_ERROR("invalid modifiers array\n");
+ SDE_ERROR("invalid modifiers array\n");
return NULL;
} else if (modifiers && modifiers_len && modifiers[0]) {
mod0 = modifiers[0];
- DBG("plane format modifier 0x%llX", mod0);
+ SDE_DEBUG("plane format modifier 0x%llX\n", mod0);
for (i = 1; i < modifiers_len; i++) {
if (modifiers[i] != mod0) {
- DRM_ERROR("bad fmt mod 0x%llX on plane %d\n",
+ SDE_ERROR("bad fmt mod 0x%llX on plane %d\n",
modifiers[i], i);
return NULL;
}
@@ -982,29 +1083,55 @@ const struct sde_format *sde_get_sde_format_ext(
map_size = ARRAY_SIZE(sde_format_map);
break;
case DRM_FORMAT_MOD_QCOM_COMPRESSED:
+ case DRM_FORMAT_MOD_QCOM_COMPRESSED | DRM_FORMAT_MOD_QCOM_TILE:
map = sde_format_map_ubwc;
map_size = ARRAY_SIZE(sde_format_map_ubwc);
- DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED", format);
+ SDE_DEBUG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED\n",
+ format);
break;
case DRM_FORMAT_MOD_QCOM_DX:
map = sde_format_map_p010;
map_size = ARRAY_SIZE(sde_format_map_p010);
- DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_DX", format);
+ SDE_DEBUG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_DX\n", format);
break;
case (DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_COMPRESSED):
+ case (DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_COMPRESSED |
+ DRM_FORMAT_MOD_QCOM_TILE):
map = sde_format_map_p010_ubwc;
map_size = ARRAY_SIZE(sde_format_map_p010_ubwc);
- DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED/DX", format);
+ SDE_DEBUG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED/DX\n",
+ format);
break;
case (DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_COMPRESSED |
DRM_FORMAT_MOD_QCOM_TIGHT):
+ case (DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_COMPRESSED |
+ DRM_FORMAT_MOD_QCOM_TIGHT | DRM_FORMAT_MOD_QCOM_TILE):
map = sde_format_map_tp10_ubwc;
map_size = ARRAY_SIZE(sde_format_map_tp10_ubwc);
- DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED/DX/TIGHT",
+ SDE_DEBUG(
+ "found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED/DX/TIGHT\n",
format);
break;
+ case DRM_FORMAT_MOD_QCOM_TILE:
+ map = sde_format_map_tile;
+ map_size = ARRAY_SIZE(sde_format_map_tile);
+ SDE_DEBUG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_TILE\n", format);
+ break;
+ case (DRM_FORMAT_MOD_QCOM_TILE | DRM_FORMAT_MOD_QCOM_DX):
+ map = sde_format_map_p010_tile;
+ map_size = ARRAY_SIZE(sde_format_map_p010_tile);
+ SDE_DEBUG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_TILE/DX\n",
+ format);
+ break;
+ case (DRM_FORMAT_MOD_QCOM_TILE | DRM_FORMAT_MOD_QCOM_DX |
+ DRM_FORMAT_MOD_QCOM_TIGHT):
+ map = sde_format_map_tp10_tile;
+ map_size = ARRAY_SIZE(sde_format_map_tp10_tile);
+ SDE_DEBUG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_TILE/DX/TIGHT\n",
+ format);
+ break;
default:
- DRM_ERROR("unsupported format modifier %llX\n", mod0);
+ SDE_ERROR("unsupported format modifier %llX\n", mod0);
return NULL;
}
@@ -1016,10 +1143,10 @@ const struct sde_format *sde_get_sde_format_ext(
}
if (fmt == NULL)
- DRM_ERROR("unsupported fmt 0x%X modifier 0x%llX\n",
+ SDE_ERROR("unsupported fmt 0x%X modifier 0x%llX\n",
format, mod0);
else
- DBG("fmt %s mod 0x%llX ubwc %d yuv %d",
+ SDE_DEBUG("fmt %s mod 0x%llX ubwc %d yuv %d\n",
drm_get_format_name(format), mod0,
SDE_FORMAT_IS_UBWC(fmt),
SDE_FORMAT_IS_YUV(fmt));
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.h b/drivers/gpu/drm/msm/sde/sde_formats.h
index 0de081d619b7..ec8f97da4a41 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.h
+++ b/drivers/gpu/drm/msm/sde/sde_formats.h
@@ -59,6 +59,21 @@ uint32_t sde_populate_formats(
uint32_t pixel_formats_max);
/**
+ * sde_format_get_plane_sizes - calculate size and layout of given buffer format
+ * @fmt: pointer to sde_format
+ * @w: width of the buffer
+ * @h: height of the buffer
+ * @layout: layout of the buffer
+ *
+ * Return: size of the buffer
+ */
+int sde_format_get_plane_sizes(
+ const struct sde_format *fmt,
+ const uint32_t w,
+ const uint32_t h,
+ struct sde_hw_fmt_layout *layout);
+
+/**
* sde_format_check_modified_format - validate format and buffers for
* sde non-standard, i.e. modified format
* @kms: kms driver
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 4f84e31db5f6..eb398fbee816 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -428,8 +428,8 @@ static uint32_t _sde_copy_formats(
return 0;
for (i = 0, cur_pos = dst_list_pos;
- (cur_pos < (dst_list_size - 1)) && src_list[i].fourcc_format
- && (i < src_list_size); ++i, ++cur_pos)
+ (cur_pos < (dst_list_size - 1)) && (i < src_list_size)
+ && src_list[i].fourcc_format; ++i, ++cur_pos)
dst_list[cur_pos] = src_list[i];
dst_list[cur_pos].fourcc_format = 0;
@@ -503,6 +503,7 @@ static int _validate_dt_entry(struct device_node *np,
rc = -EINVAL;
}
*off_count = 0;
+ memset(prop_count, 0, sizeof(int) * prop_size);
return rc;
}
}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c
index c7cbb93bece4..188649d946d6 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -88,50 +88,12 @@ static struct sde_cdm_cfg *_cdm_offset(enum sde_cdm cdm,
return ERR_PTR(-EINVAL);
}
-static void sde_hw_cdm_setup_csc_10bit(struct sde_hw_cdm *ctx,
+static int sde_hw_cdm_setup_csc_10bit(struct sde_hw_cdm *ctx,
struct sde_csc_cfg *data)
{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
- u32 csc_reg_off = CDM_CSC_10_MATRIX_COEFF_0;
- u32 val;
-
- /* matrix coeff */
- val = data->csc_mv[0] | (data->csc_mv[1] << 16);
- SDE_REG_WRITE(c, csc_reg_off, val);
- val = data->csc_mv[2] | (data->csc_mv[3] << 16);
- SDE_REG_WRITE(c, csc_reg_off + 0x4, val);
- val = data->csc_mv[4] | (data->csc_mv[5] << 16);
- SDE_REG_WRITE(c, csc_reg_off + 0x8, val);
- val = data->csc_mv[6] | (data->csc_mv[7] << 16);
- SDE_REG_WRITE(c, csc_reg_off + 0xc, val);
- val = data->csc_mv[8];
- SDE_REG_WRITE(c, csc_reg_off + 0x10, val);
-
- /* Pre clamp */
- val = (data->csc_pre_lv[0] << 16) | data->csc_pre_lv[1];
- SDE_REG_WRITE(c, csc_reg_off + 0x14, val);
- val = (data->csc_pre_lv[2] << 16) | data->csc_pre_lv[3];
- SDE_REG_WRITE(c, csc_reg_off + 0x18, val);
- val = (data->csc_pre_lv[4] << 16) | data->csc_pre_lv[5];
- SDE_REG_WRITE(c, csc_reg_off + 0x1c, val);
-
- /* Post clamp */
- val = (data->csc_post_lv[0] << 16) | data->csc_post_lv[1];
- SDE_REG_WRITE(c, csc_reg_off + 0x20, val);
- val = (data->csc_post_lv[2] << 16) | data->csc_post_lv[3];
- SDE_REG_WRITE(c, csc_reg_off + 0x24, val);
- val = (data->csc_post_lv[4] << 16) | data->csc_post_lv[5];
- SDE_REG_WRITE(c, csc_reg_off + 0x28, val);
-
- /* Pre-Bias */
- SDE_REG_WRITE(c, csc_reg_off + 0x2c, data->csc_pre_bv[0]);
- SDE_REG_WRITE(c, csc_reg_off + 0x30, data->csc_pre_bv[1]);
- SDE_REG_WRITE(c, csc_reg_off + 0x34, data->csc_pre_bv[2]);
-
- /* Post-Bias */
- SDE_REG_WRITE(c, csc_reg_off + 0x38, data->csc_post_bv[0]);
- SDE_REG_WRITE(c, csc_reg_off + 0x3c, data->csc_post_bv[1]);
- SDE_REG_WRITE(c, csc_reg_off + 0x40, data->csc_post_bv[2]);
+ sde_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
+
+ return 0;
}
static int sde_hw_cdm_setup_cdwn(struct sde_hw_cdm *ctx,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_cdm.h b/drivers/gpu/drm/msm/sde/sde_hw_cdm.h
index 264b8a418573..a0afd897e867 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_cdm.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_cdm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -65,8 +65,9 @@ struct sde_hw_cdm_ops {
* to program a different matrix than default matrix.
* @cdm: Pointer to the chroma down context structure
* @data Pointer to CSC configuration data
+ * return: 0 if success; error code otherwise
*/
- void (*setup_csc_data)(struct sde_hw_cdm *cdm,
+ int (*setup_csc_data)(struct sde_hw_cdm *cdm,
struct sde_csc_cfg *data);
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
index 49930365d989..1535d1d1ade5 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -357,37 +357,32 @@ static const struct sde_irq_type sde_irq_map[] = {
SDE_INTR_HIST_VIG_1_RSTSEQ_DONE, 2},
{ SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
{ SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- /* irq_idx: 68-71 */
+ /* irq_idx: 72-75 */
{ SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG2, SDE_INTR_HIST_VIG_2_DONE, 2},
{ SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG2,
SDE_INTR_HIST_VIG_2_RSTSEQ_DONE, 2},
{ SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG3, SDE_INTR_HIST_VIG_3_DONE, 2},
{ SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG3,
SDE_INTR_HIST_VIG_3_RSTSEQ_DONE, 2},
- /* irq_idx: 72-75 */
+ /* irq_idx: 76-79 */
{ SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_0, SDE_INTR_HIST_DSPP_0_DONE, 2},
{ SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_0,
SDE_INTR_HIST_DSPP_0_RSTSEQ_DONE, 2},
{ SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
{ SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- /* irq_idx: 76-79 */
+ /* irq_idx: 80-83 */
{ SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_1, SDE_INTR_HIST_DSPP_1_DONE, 2},
{ SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_1,
SDE_INTR_HIST_DSPP_1_RSTSEQ_DONE, 2},
{ SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
{ SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- /* irq_idx: 80-83 */
+ /* irq_idx: 84-87 */
{ SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_2, SDE_INTR_HIST_DSPP_2_DONE, 2},
{ SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_2,
SDE_INTR_HIST_DSPP_2_RSTSEQ_DONE, 2},
{ SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_3, SDE_INTR_HIST_DSPP_3_DONE, 2},
{ SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_3,
SDE_INTR_HIST_DSPP_3_RSTSEQ_DONE, 2},
- /* irq_idx: 84-87 */
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
- { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
/* irq_idx: 88-91 */
{ SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
{ SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
@@ -905,7 +900,7 @@ static u32 sde_hw_intr_get_interrupt_status(struct sde_hw_intr *intr,
sde_intr_set[reg_idx].status_off) &
sde_irq_map[irq_idx].irq_mask;
if (intr_status && clear)
- SDE_REG_WRITE(&intr->hw, sde_intr_set[irq_idx].clr_off,
+ SDE_REG_WRITE(&intr->hw, sde_intr_set[reg_idx].clr_off,
intr_status);
spin_unlock_irqrestore(&intr->mask_lock, irq_flags);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
index 7a5e7ad79f0f..2592fe26cb38 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -44,17 +44,24 @@
enum sde_format_flags {
SDE_FORMAT_FLAG_YUV_BIT,
SDE_FORMAT_FLAG_DX_BIT,
+ SDE_FORMAT_FLAG_COMPRESSED_BIT,
SDE_FORMAT_FLAG_BIT_MAX,
};
#define SDE_FORMAT_FLAG_YUV BIT(SDE_FORMAT_FLAG_YUV_BIT)
#define SDE_FORMAT_FLAG_DX BIT(SDE_FORMAT_FLAG_DX_BIT)
+#define SDE_FORMAT_FLAG_COMPRESSED BIT(SDE_FORMAT_FLAG_COMPRESSED_BIT)
#define SDE_FORMAT_IS_YUV(X) \
(test_bit(SDE_FORMAT_FLAG_YUV_BIT, (X)->flag))
#define SDE_FORMAT_IS_DX(X) \
(test_bit(SDE_FORMAT_FLAG_DX_BIT, (X)->flag))
#define SDE_FORMAT_IS_LINEAR(X) ((X)->fetch_mode == SDE_FETCH_LINEAR)
-#define SDE_FORMAT_IS_UBWC(X) ((X)->fetch_mode == SDE_FETCH_UBWC)
+#define SDE_FORMAT_IS_TILE(X) \
+ (((X)->fetch_mode == SDE_FETCH_UBWC) && \
+ !test_bit(SDE_FORMAT_FLAG_COMPRESSED_BIT, (X)->flag))
+#define SDE_FORMAT_IS_UBWC(X) \
+ (((X)->fetch_mode == SDE_FETCH_UBWC) && \
+ test_bit(SDE_FORMAT_FLAG_COMPRESSED_BIT, (X)->flag))
#define SDE_BLEND_FG_ALPHA_FG_CONST (0 << 0)
#define SDE_BLEND_FG_ALPHA_BG_CONST (1 << 0)
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index 882a1c84e9a2..ea2890d776ae 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -755,14 +755,17 @@ static void sde_hw_sspp_setup_csc(struct sde_hw_pipe *ctx,
struct sde_csc_cfg *data)
{
u32 idx;
+ bool csc10 = false;
if (_sspp_subblk_offset(ctx, SDE_SSPP_CSC, &idx) || !data)
return;
- if (test_bit(SDE_SSPP_CSC_10BIT, &ctx->cap->features))
+ if (test_bit(SDE_SSPP_CSC_10BIT, &ctx->cap->features)) {
idx += CSC_10BIT_OFFSET;
+ csc10 = true;
+ }
- sde_hw_csc_setup(&ctx->hw, idx, data);
+ sde_hw_csc_setup(&ctx->hw, idx, data, csc10);
}
static void sde_hw_sspp_setup_sharpening(struct sde_hw_pipe *ctx,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_util.c b/drivers/gpu/drm/msm/sde/sde_hw_util.c
index 6f52f31a7569..b899f0c2f71c 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_util.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -42,9 +42,10 @@ u32 *sde_hw_util_get_log_mask_ptr(void)
void sde_hw_csc_setup(struct sde_hw_blk_reg_map *c,
u32 csc_reg_off,
- struct sde_csc_cfg *data)
+ struct sde_csc_cfg *data, bool csc10)
{
static const u32 matrix_shift = 7;
+ u32 clamp_shift = csc10 ? 16 : 8;
u32 val;
/* matrix coeff - convert S15.16 to S4.9 */
@@ -64,19 +65,19 @@ void sde_hw_csc_setup(struct sde_hw_blk_reg_map *c,
SDE_REG_WRITE(c, csc_reg_off + 0x10, val);
/* Pre clamp */
- val = (data->csc_pre_lv[0] << 8) | data->csc_pre_lv[1];
+ val = (data->csc_pre_lv[0] << clamp_shift) | data->csc_pre_lv[1];
SDE_REG_WRITE(c, csc_reg_off + 0x14, val);
- val = (data->csc_pre_lv[2] << 8) | data->csc_pre_lv[3];
+ val = (data->csc_pre_lv[2] << clamp_shift) | data->csc_pre_lv[3];
SDE_REG_WRITE(c, csc_reg_off + 0x18, val);
- val = (data->csc_pre_lv[4] << 8) | data->csc_pre_lv[5];
+ val = (data->csc_pre_lv[4] << clamp_shift) | data->csc_pre_lv[5];
SDE_REG_WRITE(c, csc_reg_off + 0x1c, val);
/* Post clamp */
- val = (data->csc_post_lv[0] << 8) | data->csc_post_lv[1];
+ val = (data->csc_post_lv[0] << clamp_shift) | data->csc_post_lv[1];
SDE_REG_WRITE(c, csc_reg_off + 0x20, val);
- val = (data->csc_post_lv[2] << 8) | data->csc_post_lv[3];
+ val = (data->csc_post_lv[2] << clamp_shift) | data->csc_post_lv[3];
SDE_REG_WRITE(c, csc_reg_off + 0x24, val);
- val = (data->csc_post_lv[4] << 8) | data->csc_post_lv[5];
+ val = (data->csc_post_lv[4] << clamp_shift) | data->csc_post_lv[5];
SDE_REG_WRITE(c, csc_reg_off + 0x28, val);
/* Pre-Bias */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_util.h b/drivers/gpu/drm/msm/sde/sde_hw_util.h
index a4d8be9de907..c38c22237a57 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_util.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -49,7 +49,7 @@ void *sde_hw_util_get_dir(void);
void sde_hw_csc_setup(struct sde_hw_blk_reg_map *c,
u32 csc_reg_off,
- struct sde_csc_cfg *data);
+ struct sde_csc_cfg *data, bool csc10);
#endif /* _SDE_HW_UTIL_H */
diff --git a/drivers/gpu/drm/msm/sde_edid_parser.c b/drivers/gpu/drm/msm/sde_edid_parser.c
index 69ab367307ea..ca9229ede251 100644
--- a/drivers/gpu/drm/msm/sde_edid_parser.c
+++ b/drivers/gpu/drm/msm/sde_edid_parser.c
@@ -93,6 +93,21 @@ for ((i) = (start); \
(i) < (end) && (i) + sde_cea_db_payload_len(&(cea)[(i)]) < (end); \
(i) += sde_cea_db_payload_len(&(cea)[(i)]) + 1)
+static bool sde_cea_db_is_hdmi_hf_vsdb(const u8 *db)
+{
+ int hdmi_id;
+
+ if (sde_cea_db_tag(db) != VENDOR_SPECIFIC_DATA_BLOCK)
+ return false;
+
+ if (sde_cea_db_payload_len(db) < 7)
+ return false;
+
+ hdmi_id = db[1] | (db[2] << 8) | (db[3] << 16);
+
+ return hdmi_id == HDMI_IEEE_OUI_HF;
+}
+
static u8 *sde_edid_find_extended_tag_block(struct edid *edid, int blk_id)
{
u8 *db = NULL;
@@ -339,6 +354,63 @@ struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl)
SDE_EDID_DEBUG("%s -\n", __func__);
}
+static void _sde_edid_update_dc_modes(
+struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl)
+{
+ int i, start, end;
+ u8 *edid_ext, *hdmi;
+ struct drm_display_info *disp_info;
+ u32 hdmi_dc_yuv_modes = 0;
+
+ SDE_EDID_DEBUG("%s +\n", __func__);
+
+ if (!connector || !edid_ctrl) {
+ SDE_ERROR("invalid input\n");
+ return;
+ }
+
+ disp_info = &connector->display_info;
+
+ edid_ext = sde_find_cea_extension(edid_ctrl->edid);
+
+ if (!edid_ext) {
+ SDE_ERROR("no cea extension\n");
+ return;
+ }
+
+ if (sde_cea_db_offsets(edid_ext, &start, &end))
+ return;
+
+ sde_for_each_cea_db(edid_ext, i, start, end) {
+ if (sde_cea_db_is_hdmi_hf_vsdb(&edid_ext[i])) {
+
+ hdmi = &edid_ext[i];
+
+ if (sde_cea_db_payload_len(hdmi) < 7)
+ continue;
+
+ if (hdmi[7] & DRM_EDID_YCBCR420_DC_30) {
+ hdmi_dc_yuv_modes |= DRM_EDID_YCBCR420_DC_30;
+ SDE_EDID_DEBUG("Y420 30-bit supported\n");
+ }
+
+ if (hdmi[7] & DRM_EDID_YCBCR420_DC_36) {
+ hdmi_dc_yuv_modes |= DRM_EDID_YCBCR420_DC_36;
+ SDE_EDID_DEBUG("Y420 36-bit supported\n");
+ }
+
+ if (hdmi[7] & DRM_EDID_YCBCR420_DC_48) {
+ hdmi_dc_yuv_modes |= DRM_EDID_YCBCR420_DC_36;
+ SDE_EDID_DEBUG("Y420 48-bit supported\n");
+ }
+ }
+ }
+
+ disp_info->edid_hdmi_dc_modes |= hdmi_dc_yuv_modes;
+
+ SDE_EDID_DEBUG("%s -\n", __func__);
+}
+
static void _sde_edid_extract_audio_data_blocks(
struct sde_edid_ctrl *edid_ctrl)
{
@@ -476,6 +548,7 @@ int _sde_edid_update_modes(struct drm_connector *connector,
rc = drm_add_edid_modes(connector, edid_ctrl->edid);
sde_edid_set_mode_format(connector, edid_ctrl);
+ _sde_edid_update_dc_modes(connector, edid_ctrl);
SDE_EDID_DEBUG("%s -", __func__);
return rc;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 58a3f7cf2fb3..00de1bf81519 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -370,7 +370,8 @@ nouveau_display_init(struct drm_device *dev)
return ret;
/* enable polling for external displays */
- drm_kms_helper_poll_enable(dev);
+ if (!dev->mode_config.poll_enabled)
+ drm_kms_helper_poll_enable(dev);
/* enable hotplug interrupts */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index d236fc7c425b..91a61d2cca88 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -743,7 +743,10 @@ nouveau_pmops_runtime_resume(struct device *dev)
pci_set_master(pdev);
ret = nouveau_do_resume(drm_dev, true);
- drm_kms_helper_poll_enable(drm_dev);
+
+ if (!drm_dev->mode_config.poll_enabled)
+ drm_kms_helper_poll_enable(drm_dev);
+
/* do magic */
nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25));
vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index 2e3a62d38fe9..1621c8ae0fa0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -99,6 +99,7 @@ struct nv84_fence_priv {
struct nouveau_bo *bo;
struct nouveau_bo *bo_gart;
u32 *suspend;
+ struct mutex mutex;
};
u64 nv84_fence_crtc(struct nouveau_channel *, int);
diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c
index 6ae1b3494bcd..b7b961233949 100644
--- a/drivers/gpu/drm/nouveau/nouveau_usif.c
+++ b/drivers/gpu/drm/nouveau/nouveau_usif.c
@@ -313,7 +313,8 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
if (nvif_unpack(argv->v0, 0, 0, true)) {
/* block access to objects not created via this interface */
owner = argv->v0.owner;
- if (argv->v0.object == 0ULL)
+ if (argv->v0.object == 0ULL &&
+ argv->v0.type != NVIF_IOCTL_V0_DEL)
argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */
else
argv->v0.owner = NVDRM_OBJECT_USIF;
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index 412c5be5a9ca..7bc26eceda66 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -121,8 +121,10 @@ nv84_fence_context_del(struct nouveau_channel *chan)
}
nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
+ mutex_lock(&priv->mutex);
nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
nouveau_bo_vma_del(priv->bo, &fctx->vma);
+ mutex_unlock(&priv->mutex);
nouveau_fence_context_del(&fctx->base);
chan->fence = NULL;
nouveau_fence_context_free(&fctx->base);
@@ -148,11 +150,13 @@ nv84_fence_context_new(struct nouveau_channel *chan)
fctx->base.sync32 = nv84_fence_sync32;
fctx->base.sequence = nv84_fence_read(chan);
+ mutex_lock(&priv->mutex);
ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
if (ret == 0) {
ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
&fctx->vma_gart);
}
+ mutex_unlock(&priv->mutex);
/* map display semaphore buffers into channel's vm */
for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
@@ -232,6 +236,8 @@ nv84_fence_create(struct nouveau_drm *drm)
priv->base.context_base = fence_context_alloc(priv->base.contexts);
priv->base.uevent = true;
+ mutex_init(&priv->mutex);
+
/* Use VRAM if there is any ; otherwise fallback to system memory */
domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
/*
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 630bce68bf38..b61db9db3ca5 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -54,7 +54,7 @@
#define SMBSLVDAT (0xC + piix4_smba)
/* count for request_region */
-#define SMBIOSIZE 8
+#define SMBIOSIZE 9
/* PCI Address Constants */
#define SMBBA 0x090
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
index 9e6d1cdb7fcd..420478924a0c 100644
--- a/drivers/iio/proximity/as3935.c
+++ b/drivers/iio/proximity/as3935.c
@@ -263,8 +263,6 @@ static irqreturn_t as3935_interrupt_handler(int irq, void *private)
static void calibrate_as3935(struct as3935_state *st)
{
- mutex_lock(&st->lock);
-
/* mask disturber interrupt bit */
as3935_write(st, AS3935_INT, BIT(5));
@@ -274,8 +272,6 @@ static void calibrate_as3935(struct as3935_state *st)
mdelay(2);
as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV));
-
- mutex_unlock(&st->lock);
}
#ifdef CONFIG_PM_SLEEP
@@ -312,6 +308,8 @@ static int as3935_resume(struct device *dev)
val &= ~AS3935_AFE_PWR_BIT;
ret = as3935_write(st, AS3935_AFE_GAIN, val);
+ calibrate_as3935(st);
+
err_resume:
mutex_unlock(&st->lock);
diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c
index bb3ac5fe5846..72a391e01011 100644
--- a/drivers/irqchip/irq-xtensa-mx.c
+++ b/drivers/irqchip/irq-xtensa-mx.c
@@ -142,7 +142,7 @@ static struct irq_chip xtensa_mx_irq_chip = {
int __init xtensa_mx_init_legacy(struct device_node *interrupt_parent)
{
struct irq_domain *root_domain =
- irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+ irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
&xtensa_mx_irq_domain_ops,
&xtensa_mx_irq_chip);
irq_set_default_host(root_domain);
diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c
index 472ae1770964..f728755fa292 100644
--- a/drivers/irqchip/irq-xtensa-pic.c
+++ b/drivers/irqchip/irq-xtensa-pic.c
@@ -89,7 +89,7 @@ static struct irq_chip xtensa_irq_chip = {
int __init xtensa_pic_init_legacy(struct device_node *interrupt_parent)
{
struct irq_domain *root_domain =
- irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+ irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
&xtensa_irq_domain_ops, &xtensa_irq_chip);
irq_set_default_host(root_domain);
return 0;
diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c
index 373a963f75aa..a85ee30769c4 100644
--- a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c
@@ -3889,6 +3889,12 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg)
case UPDATE_STREAM_REQUEST_FRAMES_VER2: {
struct msm_vfe_axi_stream_cfg_update_info_req_frm *req_frm =
&update_cmd->req_frm_ver2;
+ if (HANDLE_TO_IDX(req_frm->stream_handle) >= VFE_AXI_SRC_MAX) {
+ pr_err("%s: Invalid stream handle\n", __func__);
+ rc = -EINVAL;
+ break;
+ }
+
stream_info = &axi_data->stream_info[HANDLE_TO_IDX(
req_frm->stream_handle)];
rc = msm_isp_request_frame(vfe_dev, stream_info,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index d64cee834bea..1f1435fe282e 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -456,7 +456,7 @@ struct msm_vfe_axi_stream {
uint32_t runtime_output_format;
enum msm_stream_rdi_input_type rdi_input_type;
struct msm_isp_sw_framskip sw_skip;
- uint8_t sw_ping_pong_bit;
+ int8_t sw_ping_pong_bit;
struct vfe_device *vfe_dev[MAX_VFE];
int num_isp;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 0352ae9cb595..0e0f10e7fbb5 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -1699,6 +1699,9 @@ static int msm_isp_update_deliver_count(struct vfe_device *vfe_dev,
rc = -EINVAL;
goto done;
} else {
+ /*After wm reload, we get bufdone for ping buffer*/
+ if (stream_info->sw_ping_pong_bit == -1)
+ stream_info->sw_ping_pong_bit = 0;
stream_info->undelivered_request_cnt--;
if (pingpong_bit != stream_info->sw_ping_pong_bit) {
pr_err("%s:%d ping pong bit actual %d sw %d\n",
@@ -3479,7 +3482,14 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
spin_lock_irqsave(&stream_info->lock, flags);
vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev, stream_info);
- if (stream_info->undelivered_request_cnt == 1) {
+ /*
+ * When wm reloaded, pingpong status register would be stale, pingpong
+ * status would be updated only after AXI_DONE interrupt processed.
+ * So, we should avoid reading value from pingpong status register
+ * until buf_done happens for ping buffer.
+ */
+ if ((stream_info->undelivered_request_cnt == 1) &&
+ (stream_info->sw_ping_pong_bit != -1)) {
pingpong_status =
vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status(
vfe_dev);
@@ -3552,10 +3562,25 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
stream_info->vfe_dev[k]->vfe_base, wm_mask);
}
- stream_info->sw_ping_pong_bit = 0;
+ /*
+ * sw_ping_pong_bit is updated only when AXI_DONE.
+ * so now reset this bit to -1.
+ */
+ stream_info->sw_ping_pong_bit = -1;
} else if (stream_info->undelivered_request_cnt == 2) {
- rc = msm_isp_cfg_ping_pong_address(
- stream_info, pingpong_status);
+ if (stream_info->sw_ping_pong_bit == -1) {
+ /*
+ * This means wm is reloaded & ping buffer is
+ * already configured. And AXI_DONE for ping
+ * is still pending. So, config pong buffer
+ * now.
+ */
+ rc = msm_isp_cfg_ping_pong_address(stream_info,
+ VFE_PONG_FLAG);
+ } else {
+ rc = msm_isp_cfg_ping_pong_address(
+ stream_info, pingpong_status);
+ }
if (rc) {
stream_info->undelivered_request_cnt--;
spin_unlock_irqrestore(&stream_info->lock,
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index ab981f762dd2..3f900ded090a 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -86,6 +86,12 @@ static void msm_ispif_io_dump_reg(struct ispif_device *ispif)
{
if (!ispif->enb_dump_reg)
return;
+
+ if (!ispif->base) {
+ pr_err("%s: null pointer for the ispif base\n", __func__);
+ return;
+ }
+
msm_camera_io_dump(ispif->base, 0x250, 0);
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index cd48f871eb79..bc844bb87db5 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -573,7 +573,10 @@ static int32_t msm_actuator_move_focus(
CDBG("called, dir %d, num_steps %d\n", dir, num_steps);
- if (dest_step_pos == a_ctrl->curr_step_pos)
+ if ((dest_step_pos == a_ctrl->curr_step_pos) ||
+ ((dest_step_pos <= a_ctrl->total_steps) &&
+ (a_ctrl->step_position_table[dest_step_pos] ==
+ a_ctrl->step_position_table[a_ctrl->curr_step_pos])))
return rc;
if ((sign_dir > MSM_ACTUATOR_MOVE_SIGNED_NEAR) ||
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 75043e1b0427..7dda92510879 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -1602,6 +1602,12 @@ static int32_t msm_cci_write(struct v4l2_subdev *sd,
return rc;
}
+ if (cci_dev->cci_state != CCI_STATE_ENABLED) {
+ pr_err("%s invalid cci state %d\n",
+ __func__, cci_dev->cci_state);
+ return -EINVAL;
+ }
+
if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
|| c_ctrl->cci_info->cci_i2c_master < 0) {
pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index e1143c356721..fcef05374098 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -584,7 +584,12 @@ static int msm_sensor_config32(struct msm_sensor_ctrl_t *s_ctrl,
pr_err("%s:%d: i2c_read failed\n", __func__, __LINE__);
break;
}
- read_config_ptr->data = local_data;
+ if (copy_to_user(&read_config_ptr->data,
+ &local_data, sizeof(local_data))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
break;
}
case CFG_SLAVE_WRITE_I2C_ARRAY: {
@@ -1098,7 +1103,12 @@ int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp)
pr_err("%s:%d: i2c_read failed\n", __func__, __LINE__);
break;
}
- read_config_ptr->data = local_data;
+ if (copy_to_user(&read_config_ptr->data,
+ &local_data, sizeof(local_data))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
break;
}
case CFG_SLAVE_WRITE_I2C_ARRAY: {
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index 42519be35aa9..abf20aef1256 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -621,9 +621,10 @@ static int sde_rotator_secure_session_ctrl(bool enable)
if (mdata->wait_for_transition && mdata->secure_session_ctrl &&
mdata->callback_request) {
ret = mdata->wait_for_transition(mdata->sec_cam_en, enable);
- if (ret) {
+ if (ret < 0) {
SDEROT_ERR("failed Secure wait for transition %d\n",
ret);
+ ret = -EPERM;
} else {
if (mdata->sec_cam_en ^ enable) {
mdata->sec_cam_en = enable;
@@ -1114,6 +1115,8 @@ static int sde_rotator_assign_queue(struct sde_rot_mgr *mgr,
if (IS_ERR_OR_NULL(hw)) {
SDEROT_ERR("fail to allocate hw\n");
ret = PTR_ERR(hw);
+ if (!ret)
+ ret = -EINVAL;
} else {
queue->hw = hw;
}
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index f41382b5b20c..1966fa9805c0 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -1023,6 +1023,9 @@ static ssize_t sde_rotator_debug_base_offset_write(struct file *file,
if (sscanf(buf, "%5x %x", &off, &cnt) < 2)
return -EINVAL;
+ if (off % sizeof(u32))
+ return -EINVAL;
+
if (off > dbg->max_offset)
return -EINVAL;
@@ -1091,6 +1094,9 @@ static ssize_t sde_rotator_debug_base_reg_write(struct file *file,
if (cnt < 2)
return -EFAULT;
+ if (off % sizeof(u32))
+ return -EFAULT;
+
if (off >= dbg->max_offset)
return -EFAULT;
@@ -1139,6 +1145,9 @@ static ssize_t sde_rotator_debug_base_reg_read(struct file *file,
goto debug_read_error;
}
+ if (dbg->off % sizeof(u32))
+ return -EFAULT;
+
ptr = dbg->base + dbg->off;
tot = 0;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 4298163e37d5..08bbed147c86 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -1785,6 +1785,7 @@ static long sde_rotator_private_ioctl(struct file *file, void *fh,
struct msm_sde_rotator_fence *fence = arg;
struct msm_sde_rotator_comp_ratio *comp_ratio = arg;
struct sde_rotator_vbinfo *vbinfo;
+ int ret;
switch (cmd) {
case VIDIOC_S_SDE_ROTATOR_FENCE:
@@ -1843,19 +1844,39 @@ static long sde_rotator_private_ioctl(struct file *file, void *fh,
vbinfo = &ctx->vbinfo_cap[fence->index];
- if (vbinfo->fence == NULL) {
- vbinfo->fd = -1;
- } else {
- vbinfo->fd =
- sde_rotator_get_sync_fence_fd(vbinfo->fence);
- if (vbinfo->fd < 0) {
+ if (!vbinfo)
+ return -EINVAL;
+
+ if (vbinfo->fence) {
+ ret = sde_rotator_get_sync_fence_fd(vbinfo->fence);
+ if (ret < 0) {
SDEDEV_ERR(rot_dev->dev,
"fail get fence fd s:%d\n",
ctx->session_id);
- return vbinfo->fd;
+ return ret;
}
+
+ /*
+ * Loose any reference to sync fence once we pass
+ * it to user. Driver does not clean up user
+ * unclosed fence descriptors.
+ */
vbinfo->fence = NULL;
+
+ /*
+ * Cache fence descriptor in case user calls this
+ * ioctl multiple times. Cached value would be stale
+ * if user duplicated and closed old descriptor.
+ */
+ vbinfo->fd = ret;
+ } else if (!sde_rotator_get_fd_sync_fence(vbinfo->fd)) {
+ /*
+ * User has closed cached fence descriptor.
+ * Invalidate descriptor cache.
+ */
+ vbinfo->fd = -1;
}
+
fence->fd = vbinfo->fd;
SDEDEV_DBG(rot_dev->dev,
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index 8157e8641e60..acb697946e18 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -1257,6 +1257,7 @@ err_put:
data->srcp_dma_buf = NULL;
imap_err:
ion_free(rot->iclient, handle);
+ sde_smmu_ctrl(0);
return rc;
}
@@ -1270,8 +1271,19 @@ static int sde_hw_rotator_swts_map(struct sde_hw_rotator *rot)
{
int rc = 0;
struct sde_mdp_img_data *data = &rot->swts_buf;
+ struct sde_rot_data_type *mdata = sde_rot_get_mdata();
sde_smmu_ctrl(1);
+ if (mdata->wait_for_transition) {
+ rc = mdata->wait_for_transition(0, 0);
+ if (rc < 0) {
+ SDEROT_ERR("failed Secure wait for transition %d\n",
+ rc);
+ rc = -EPERM;
+ goto error;
+ }
+ }
+
rc = sde_smmu_map_dma_buf(data->srcp_dma_buf, data->srcp_table,
SDE_IOMMU_DOMAIN_ROT_UNSECURE, &data->addr,
&data->len, DMA_BIDIRECTIONAL);
@@ -1291,7 +1303,7 @@ static int sde_hw_rotator_swts_map(struct sde_hw_rotator *rot)
data->mapped = true;
SDEROT_DBG("swts buffer mapped: %pad/%lx va:%p\n", &data->addr,
- data->len, rot->swts_buffer);
+ data->len, rot->swts_buffer);
sde_smmu_ctrl(0);
return rc;
@@ -1301,6 +1313,8 @@ kmap_err:
err_unmap:
dma_buf_unmap_attachment(data->srcp_attachment, data->srcp_table,
DMA_FROM_DEVICE);
+error:
+ sde_smmu_ctrl(0);
return rc;
}
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
index e1907cd0c3b7..7613d1fee104 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
@@ -123,15 +123,10 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
memset(&tvdata,0,sizeof(tvdata));
eeprom = pvr2_eeprom_fetch(hdw);
- if (!eeprom) return -EINVAL;
-
- {
- struct i2c_client fake_client;
- /* Newer version expects a useless client interface */
- fake_client.addr = hdw->eeprom_addr;
- fake_client.adapter = &hdw->i2c_adap;
- tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom);
- }
+ if (!eeprom)
+ return -EINVAL;
+
+ tveeprom_hauppauge_analog(NULL, &tvdata, eeprom);
trace_eeprom("eeprom assumed v4l tveeprom module");
trace_eeprom("eeprom direct call results:");
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 47f37683893a..3dc9ed2e0774 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -793,7 +793,7 @@ EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
*/
void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
{
- if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
+ if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
return NULL;
return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv);
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index c30290f33430..fe51e9709210 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -375,8 +375,8 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata)
* and use SDR Mode
*/
reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
- | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
+ reg |= OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF;
} else if (pdata->port_mode[i] ==
OMAP_EHCI_PORT_MODE_HSIC) {
/*
diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c
index 5484301d57d9..3dc61ea7dc64 100644
--- a/drivers/misc/c2port/c2port-duramar2150.c
+++ b/drivers/misc/c2port/c2port-duramar2150.c
@@ -129,8 +129,8 @@ static int __init duramar2150_c2port_init(void)
duramar2150_c2port_dev = c2port_device_register("uc",
&duramar2150_c2port_ops, NULL);
- if (!duramar2150_c2port_dev) {
- ret = -ENODEV;
+ if (IS_ERR(duramar2150_c2port_dev)) {
+ ret = PTR_ERR(duramar2150_c2port_dev);
goto free_region;
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 2cb0ea03a338..79b5b3504ccd 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1735,7 +1735,6 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
struct mmc_async_req *areq, int *error)
{
int err = 0;
- int start_err = 0;
struct mmc_async_req *data = host->areq;
/* Prepare a new request */
@@ -1784,7 +1783,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
trace_mmc_blk_rw_start(areq->mrq->cmd->opcode,
areq->mrq->cmd->arg,
areq->mrq->data);
- start_err = __mmc_start_data_req(host, areq->mrq);
+ __mmc_start_data_req(host, areq->mrq);
}
if (host->areq)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index df60774b02af..7173bf56c2c5 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2849,6 +2849,7 @@ static int mmc_runtime_suspend(struct mmc_host *host)
return -EBUSY;
}
+ MMC_TRACE(host, "%s\n", __func__);
err = _mmc_suspend(host, true);
if (err)
pr_err("%s: error %d doing aggressive suspend\n",
@@ -2870,6 +2871,7 @@ static int mmc_runtime_resume(struct mmc_host *host)
if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME)))
return 0;
+ MMC_TRACE(host, "%s\n", __func__);
err = _mmc_resume(host);
if (err)
pr_err("%s: error %d doing aggressive resume\n",
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index d908c3fed7c9..7aefeb037ef4 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2494,15 +2494,30 @@ void sdhci_msm_dump_pwr_ctrl_regs(struct sdhci_host *host)
struct sdhci_msm_host *msm_host = pltfm_host->priv;
const struct sdhci_msm_offset *msm_host_offset =
msm_host->offset;
+ unsigned int irq_flags = 0;
+ struct irq_desc *pwr_irq_desc = irq_to_desc(msm_host->pwr_irq);
- pr_err("%s: PWRCTL_STATUS: 0x%08x | PWRCTL_MASK: 0x%08x | PWRCTL_CTL: 0x%08x\n",
+ if (pwr_irq_desc)
+ irq_flags = pwr_irq_desc->irq_data.common->state_use_accessors;
+
+ pr_err("%s: PWRCTL_STATUS: 0x%08x | PWRCTL_MASK: 0x%08x | PWRCTL_CTL: 0x%08x, pwr isr state=0x%x\n",
mmc_hostname(host->mmc),
sdhci_msm_readl_relaxed(host,
msm_host_offset->CORE_PWRCTL_STATUS),
sdhci_msm_readl_relaxed(host,
msm_host_offset->CORE_PWRCTL_MASK),
sdhci_msm_readl_relaxed(host,
- msm_host_offset->CORE_PWRCTL_CTL));
+ msm_host_offset->CORE_PWRCTL_CTL), irq_flags);
+
+ MMC_TRACE(host->mmc,
+ "%s: Sts: 0x%08x | Mask: 0x%08x | Ctrl: 0x%08x, pwr isr state=0x%x\n",
+ __func__,
+ sdhci_msm_readb_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_STATUS),
+ sdhci_msm_readb_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_MASK),
+ sdhci_msm_readb_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_CTL), irq_flags);
}
static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
@@ -2775,10 +2790,14 @@ static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
if (done)
init_completion(&msm_host->pwr_irq_completion);
else if (!wait_for_completion_timeout(&msm_host->pwr_irq_completion,
- msecs_to_jiffies(MSM_PWR_IRQ_TIMEOUT_MS)))
+ msecs_to_jiffies(MSM_PWR_IRQ_TIMEOUT_MS))) {
__WARN_printf("%s: request(%d) timed out waiting for pwr_irq\n",
mmc_hostname(host->mmc), req_type);
-
+ MMC_TRACE(host->mmc,
+ "%s: request(%d) timed out waiting for pwr_irq\n",
+ __func__, req_type);
+ sdhci_msm_dump_pwr_ctrl_regs(host);
+ }
pr_debug("%s: %s: request %d done\n", mmc_hostname(host->mmc),
__func__, req_type);
}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index ddb9947ce298..a5ff9f73dfbc 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -255,6 +255,8 @@ retry_reset:
if (timeout == 0) {
pr_err("%s: Reset 0x%x never completed.\n",
mmc_hostname(host->mmc), (int)mask);
+ MMC_TRACE(host->mmc, "%s: Reset 0x%x never completed\n",
+ __func__, (int)mask);
if ((host->quirks2 & SDHCI_QUIRK2_USE_RESET_WORKAROUND)
&& host->ops->reset_workaround) {
if (!host->reset_wa_applied) {
@@ -1178,6 +1180,9 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
if (timeout == 0) {
pr_err("%s: Controller never released "
"inhibit bit(s).\n", mmc_hostname(host->mmc));
+ MMC_TRACE(host->mmc,
+ "%s :Controller never released inhibit bit(s)\n",
+ __func__);
sdhci_dumpregs(host);
cmd->error = -EIO;
tasklet_schedule(&host->finish_tasklet);
@@ -1233,12 +1238,12 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
if (cmd->data)
host->data_start_time = ktime_get();
trace_mmc_cmd_rw_start(cmd->opcode, cmd->arg, cmd->flags);
+ sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
MMC_TRACE(host->mmc,
"%s: updated 0x8=0x%08x 0xC=0x%08x 0xE=0x%08x\n", __func__,
sdhci_readl(host, SDHCI_ARGUMENT),
sdhci_readw(host, SDHCI_TRANSFER_MODE),
sdhci_readw(host, SDHCI_COMMAND));
- sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
}
EXPORT_SYMBOL_GPL(sdhci_send_command);
@@ -1434,6 +1439,8 @@ clock_set:
if (timeout == 0) {
pr_err("%s: Internal clock never "
"stabilised.\n", mmc_hostname(host->mmc));
+ MMC_TRACE(host->mmc,
+ "%s: Internal clock never stabilised.\n", __func__);
sdhci_dumpregs(host);
return;
}
@@ -1777,6 +1784,7 @@ end_req:
if (mrq->data)
mrq->data->error = -EIO;
host->mrq = NULL;
+ MMC_TRACE(host->mmc, "Request failed due to ice config\n");
sdhci_dumpregs(host);
mmc_request_done(host->mmc, mrq);
sdhci_runtime_pm_put(host);
@@ -2846,6 +2854,7 @@ static void sdhci_timeout_timer(unsigned long data)
if (host->mrq) {
pr_err("%s: Timeout waiting for hardware "
"interrupt.\n", mmc_hostname(host->mmc));
+ MMC_TRACE(host->mmc, "Timeout waiting for h/w interrupt\n");
sdhci_dumpregs(host);
if (host->data) {
@@ -2885,6 +2894,9 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
pr_err("%s: Got command interrupt 0x%08x even "
"though no command operation was in progress.\n",
mmc_hostname(host->mmc), (unsigned)intmask);
+ MMC_TRACE(host->mmc,
+ "Got command interrupt 0x%08x even though no command operation was in progress.\n",
+ (unsigned)intmask);
sdhci_dumpregs(host);
return;
}
@@ -3054,6 +3066,9 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
pr_err("%s: Got data interrupt 0x%08x even "
"though no data operation was in progress.\n",
mmc_hostname(host->mmc), (unsigned)intmask);
+ MMC_TRACE(host->mmc,
+ "Got data interrupt 0x%08x even though no data operation was in progress.\n",
+ (unsigned)intmask);
sdhci_dumpregs(host);
return;
@@ -3089,6 +3104,11 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
mmc_hostname(host->mmc), intmask,
host->data->error, ktime_to_ms(ktime_sub(
ktime_get(), host->data_start_time)));
+ MMC_TRACE(host->mmc,
+ "data txfr (0x%08x) error: %d after %lld ms\n",
+ intmask, host->data->error,
+ ktime_to_ms(ktime_sub(ktime_get(),
+ host->data_start_time)));
if (!host->mmc->sdr104_wa ||
(host->mmc->ios.timing != MMC_TIMING_UHS_SDR104))
@@ -3340,6 +3360,8 @@ out:
if (unexpected) {
pr_err("%s: Unexpected interrupt 0x%08x.\n",
mmc_hostname(host->mmc), unexpected);
+ MMC_TRACE(host->mmc, "Unexpected interrupt 0x%08x.\n",
+ unexpected);
sdhci_dumpregs(host);
}
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index cbc99d5649af..ae5709354546 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -246,6 +246,8 @@ static int gs_cmd_reset(struct gs_usb *gsusb, struct gs_can *gsdev)
sizeof(*dm),
1000);
+ kfree(dm);
+
return rc;
}
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index ac7288240d55..f089fa954f42 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -1153,6 +1153,12 @@ static void init_ring(struct net_device *dev)
if (skb == NULL)
break;
np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(np->pci_dev,
+ np->rx_info[i].mapping)) {
+ dev_kfree_skb(skb);
+ np->rx_info[i].skb = NULL;
+ break;
+ }
/* Grrr, we cannot offset to correctly align the IP header. */
np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
}
@@ -1183,8 +1189,9 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
unsigned int entry;
+ unsigned int prev_tx;
u32 status;
- int i;
+ int i, j;
/*
* be cautious here, wrapping the queue has weird semantics
@@ -1202,6 +1209,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
}
#endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
+ prev_tx = np->cur_tx;
entry = np->cur_tx % TX_RING_SIZE;
for (i = 0; i < skb_num_frags(skb); i++) {
int wrap_ring = 0;
@@ -1235,6 +1243,11 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
skb_frag_size(this_frag),
PCI_DMA_TODEVICE);
}
+ if (pci_dma_mapping_error(np->pci_dev,
+ np->tx_info[entry].mapping)) {
+ dev->stats.tx_dropped++;
+ goto err_out;
+ }
np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
np->tx_ring[entry].status = cpu_to_le32(status);
@@ -1269,8 +1282,30 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
return NETDEV_TX_OK;
-}
+err_out:
+ entry = prev_tx % TX_RING_SIZE;
+ np->tx_info[entry].skb = NULL;
+ if (i > 0) {
+ pci_unmap_single(np->pci_dev,
+ np->tx_info[entry].mapping,
+ skb_first_frag_len(skb),
+ PCI_DMA_TODEVICE);
+ np->tx_info[entry].mapping = 0;
+ entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
+ for (j = 1; j < i; j++) {
+ pci_unmap_single(np->pci_dev,
+ np->tx_info[entry].mapping,
+ skb_frag_size(
+ &skb_shinfo(skb)->frags[j-1]),
+ PCI_DMA_TODEVICE);
+ entry++;
+ }
+ }
+ dev_kfree_skb_any(skb);
+ np->cur_tx = prev_tx;
+ return NETDEV_TX_OK;
+}
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
@@ -1570,6 +1605,12 @@ static void refill_rx_ring(struct net_device *dev)
break; /* Better luck next round. */
np->rx_info[entry].mapping =
pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(np->pci_dev,
+ np->rx_info[entry].mapping)) {
+ dev_kfree_skb(skb);
+ np->rx_info[entry].skb = NULL;
+ break;
+ }
np->rx_ring[entry].rxaddr =
cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
}
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 3e233d924cce..6a061f17a44f 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -1999,8 +1999,8 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
if (!rxb->page)
continue;
- dma_unmap_single(rx_queue->dev, rxb->dma,
- PAGE_SIZE, DMA_FROM_DEVICE);
+ dma_unmap_page(rx_queue->dev, rxb->dma,
+ PAGE_SIZE, DMA_FROM_DEVICE);
__free_page(rxb->page);
rxb->page = NULL;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 08cef0dfb5db..2fa54b0b0679 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -105,8 +105,8 @@ int hns_nic_net_xmit_hw(struct net_device *ndev,
struct hns_nic_ring_data *ring_data)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
- struct device *dev = priv->dev;
struct hnae_ring *ring = ring_data->ring;
+ struct device *dev = ring_to_dev(ring);
struct netdev_queue *dev_queue;
struct skb_frag_struct *frag;
int buf_num;
diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c
index 715de8affcc9..e203d0c4e5a3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/catas.c
+++ b/drivers/net/ethernet/mellanox/mlx4/catas.c
@@ -158,7 +158,7 @@ static int mlx4_reset_slave(struct mlx4_dev *dev)
return -ETIMEDOUT;
}
-static int mlx4_comm_internal_err(u32 slave_read)
+int mlx4_comm_internal_err(u32 slave_read)
{
return (u32)COMM_CHAN_EVENT_INTERNAL_ERR ==
(slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0;
diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c
index 0472941af820..1a134e08f010 100644
--- a/drivers/net/ethernet/mellanox/mlx4/intf.c
+++ b/drivers/net/ethernet/mellanox/mlx4/intf.c
@@ -218,6 +218,18 @@ void mlx4_unregister_device(struct mlx4_dev *dev)
struct mlx4_interface *intf;
mlx4_stop_catas_poll(dev);
+ if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION &&
+ mlx4_is_slave(dev)) {
+ /* In mlx4_remove_one on a VF */
+ u32 slave_read =
+ swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read));
+
+ if (mlx4_comm_internal_err(slave_read)) {
+ mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n",
+ __func__);
+ mlx4_enter_error_state(dev->persist);
+ }
+ }
mutex_lock(&intf_mutex);
list_for_each_entry(intf, &intf_list, list)
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index e1cf9036af22..f5fdbd53d052 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -1205,6 +1205,7 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type);
void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
void mlx4_enter_error_state(struct mlx4_dev_persistent *persist);
+int mlx4_comm_internal_err(u32 slave_read);
int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
enum mlx4_port_type *type);
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 549ad2018e7f..1e61d4da72db 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -171,6 +171,49 @@ static struct mdiobb_ops bb_ops = {
.get_mdio_data = ravb_get_mdio_data,
};
+/* Free TX skb function for AVB-IP */
+static int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only)
+{
+ struct ravb_private *priv = netdev_priv(ndev);
+ struct net_device_stats *stats = &priv->stats[q];
+ struct ravb_tx_desc *desc;
+ int free_num = 0;
+ int entry;
+ u32 size;
+
+ for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) {
+ bool txed;
+
+ entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] *
+ NUM_TX_DESC);
+ desc = &priv->tx_ring[q][entry];
+ txed = desc->die_dt == DT_FEMPTY;
+ if (free_txed_only && !txed)
+ break;
+ /* Descriptor type must be checked before all other reads */
+ dma_rmb();
+ size = le16_to_cpu(desc->ds_tagl) & TX_DS;
+ /* Free the original skb. */
+ if (priv->tx_skb[q][entry / NUM_TX_DESC]) {
+ dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
+ size, DMA_TO_DEVICE);
+ /* Last packet descriptor? */
+ if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) {
+ entry /= NUM_TX_DESC;
+ dev_kfree_skb_any(priv->tx_skb[q][entry]);
+ priv->tx_skb[q][entry] = NULL;
+ if (txed)
+ stats->tx_packets++;
+ }
+ free_num++;
+ }
+ if (txed)
+ stats->tx_bytes += size;
+ desc->die_dt = DT_EEMPTY;
+ }
+ return free_num;
+}
+
/* Free skb's and DMA buffers for Ethernet AVB */
static void ravb_ring_free(struct net_device *ndev, int q)
{
@@ -186,19 +229,21 @@ static void ravb_ring_free(struct net_device *ndev, int q)
kfree(priv->rx_skb[q]);
priv->rx_skb[q] = NULL;
- /* Free TX skb ringbuffer */
- if (priv->tx_skb[q]) {
- for (i = 0; i < priv->num_tx_ring[q]; i++)
- dev_kfree_skb(priv->tx_skb[q][i]);
- }
- kfree(priv->tx_skb[q]);
- priv->tx_skb[q] = NULL;
-
/* Free aligned TX buffers */
kfree(priv->tx_align[q]);
priv->tx_align[q] = NULL;
if (priv->rx_ring[q]) {
+ for (i = 0; i < priv->num_rx_ring[q]; i++) {
+ struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
+
+ if (!dma_mapping_error(ndev->dev.parent,
+ le32_to_cpu(desc->dptr)))
+ dma_unmap_single(ndev->dev.parent,
+ le32_to_cpu(desc->dptr),
+ PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
+ }
ring_size = sizeof(struct ravb_ex_rx_desc) *
(priv->num_rx_ring[q] + 1);
dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
@@ -207,12 +252,20 @@ static void ravb_ring_free(struct net_device *ndev, int q)
}
if (priv->tx_ring[q]) {
+ ravb_tx_free(ndev, q, false);
+
ring_size = sizeof(struct ravb_tx_desc) *
(priv->num_tx_ring[q] * NUM_TX_DESC + 1);
dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q],
priv->tx_desc_dma[q]);
priv->tx_ring[q] = NULL;
}
+
+ /* Free TX skb ringbuffer.
+ * SKBs are freed by ravb_tx_free() call above.
+ */
+ kfree(priv->tx_skb[q]);
+ priv->tx_skb[q] = NULL;
}
/* Format skb and descriptor buffer for Ethernet AVB */
@@ -420,44 +473,6 @@ static int ravb_dmac_init(struct net_device *ndev)
return 0;
}
-/* Free TX skb function for AVB-IP */
-static int ravb_tx_free(struct net_device *ndev, int q)
-{
- struct ravb_private *priv = netdev_priv(ndev);
- struct net_device_stats *stats = &priv->stats[q];
- struct ravb_tx_desc *desc;
- int free_num = 0;
- int entry;
- u32 size;
-
- for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) {
- entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] *
- NUM_TX_DESC);
- desc = &priv->tx_ring[q][entry];
- if (desc->die_dt != DT_FEMPTY)
- break;
- /* Descriptor type must be checked before all other reads */
- dma_rmb();
- size = le16_to_cpu(desc->ds_tagl) & TX_DS;
- /* Free the original skb. */
- if (priv->tx_skb[q][entry / NUM_TX_DESC]) {
- dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
- size, DMA_TO_DEVICE);
- /* Last packet descriptor? */
- if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) {
- entry /= NUM_TX_DESC;
- dev_kfree_skb_any(priv->tx_skb[q][entry]);
- priv->tx_skb[q][entry] = NULL;
- stats->tx_packets++;
- }
- free_num++;
- }
- stats->tx_bytes += size;
- desc->die_dt = DT_EEMPTY;
- }
- return free_num;
-}
-
static void ravb_get_tx_tstamp(struct net_device *ndev)
{
struct ravb_private *priv = netdev_priv(ndev);
@@ -797,7 +812,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
spin_lock_irqsave(&priv->lock, flags);
/* Clear TX interrupt */
ravb_write(ndev, ~mask, TIS);
- ravb_tx_free(ndev, q);
+ ravb_tx_free(ndev, q, true);
netif_wake_subqueue(ndev, q);
mmiowb();
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1393,7 +1408,8 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
priv->cur_tx[q] += NUM_TX_DESC;
if (priv->cur_tx[q] - priv->dirty_tx[q] >
- (priv->num_tx_ring[q] - 1) * NUM_TX_DESC && !ravb_tx_free(ndev, q))
+ (priv->num_tx_ring[q] - 1) * NUM_TX_DESC &&
+ !ravb_tx_free(ndev, q, true))
netif_stop_subqueue(ndev, q);
exit:
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index cf468c87ce57..4cb8b85cbf2c 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -100,6 +100,14 @@
/* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
#define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT)
+#ifdef __BIG_ENDIAN
+#define xemaclite_readl ioread32be
+#define xemaclite_writel iowrite32be
+#else
+#define xemaclite_readl ioread32
+#define xemaclite_writel iowrite32
+#endif
+
/**
* struct net_local - Our private per device data
* @ndev: instance of the network device
@@ -158,15 +166,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
u32 reg_data;
/* Enable the Tx interrupts for the first Buffer */
- reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
- __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
- drvdata->base_addr + XEL_TSR_OFFSET);
+ reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+ xemaclite_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
+ drvdata->base_addr + XEL_TSR_OFFSET);
/* Enable the Rx interrupts for the first buffer */
- __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
+ xemaclite_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
/* Enable the Global Interrupt Enable */
- __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
+ xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
}
/**
@@ -181,17 +189,17 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata)
u32 reg_data;
/* Disable the Global Interrupt Enable */
- __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
+ xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
/* Disable the Tx interrupts for the first buffer */
- reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
- __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
- drvdata->base_addr + XEL_TSR_OFFSET);
+ reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+ xemaclite_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
+ drvdata->base_addr + XEL_TSR_OFFSET);
/* Disable the Rx interrupts for the first buffer */
- reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
- __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
- drvdata->base_addr + XEL_RSR_OFFSET);
+ reg_data = xemaclite_readl(drvdata->base_addr + XEL_RSR_OFFSET);
+ xemaclite_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
+ drvdata->base_addr + XEL_RSR_OFFSET);
}
/**
@@ -323,7 +331,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
byte_count = ETH_FRAME_LEN;
/* Check if the expected buffer is available */
- reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
@@ -336,7 +344,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
addr = (void __iomem __force *)((u32 __force)addr ^
XEL_BUFFER_OFFSET);
- reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
@@ -347,16 +355,16 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
/* Write the frame to the buffer */
xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
- __raw_writel((byte_count & XEL_TPLR_LENGTH_MASK),
- addr + XEL_TPLR_OFFSET);
+ xemaclite_writel((byte_count & XEL_TPLR_LENGTH_MASK),
+ addr + XEL_TPLR_OFFSET);
/* Update the Tx Status Register to indicate that there is a
* frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
* is used by the interrupt handler to check whether a frame
* has been transmitted */
- reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
- __raw_writel(reg_data, addr + XEL_TSR_OFFSET);
+ xemaclite_writel(reg_data, addr + XEL_TSR_OFFSET);
return 0;
}
@@ -371,7 +379,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
*
* Return: Total number of bytes received
*/
-static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
+static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
{
void __iomem *addr;
u16 length, proto_type;
@@ -381,7 +389,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use);
/* Verify which buffer has valid data */
- reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
+ reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
if (drvdata->rx_ping_pong != 0)
@@ -398,27 +406,28 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
return 0; /* No data was available */
/* Verify that buffer has valid data */
- reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
+ reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
if ((reg_data & XEL_RSR_RECV_DONE_MASK) !=
XEL_RSR_RECV_DONE_MASK)
return 0; /* No data was available */
}
/* Get the protocol type of the ethernet frame that arrived */
- proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET +
+ proto_type = ((ntohl(xemaclite_readl(addr + XEL_HEADER_OFFSET +
XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
XEL_RPLR_LENGTH_MASK);
/* Check if received ethernet frame is a raw ethernet frame
* or an IP packet or an ARP packet */
- if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
+ if (proto_type > ETH_DATA_LEN) {
if (proto_type == ETH_P_IP) {
- length = ((ntohl(__raw_readl(addr +
+ length = ((ntohl(xemaclite_readl(addr +
XEL_HEADER_IP_LENGTH_OFFSET +
XEL_RXBUFF_OFFSET)) >>
XEL_HEADER_SHIFT) &
XEL_RPLR_LENGTH_MASK);
+ length = min_t(u16, length, ETH_DATA_LEN);
length += ETH_HLEN + ETH_FCS_LEN;
} else if (proto_type == ETH_P_ARP)
@@ -431,14 +440,17 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
/* Use the length in the frame, plus the header and trailer */
length = proto_type + ETH_HLEN + ETH_FCS_LEN;
+ if (WARN_ON(length > maxlen))
+ length = maxlen;
+
/* Read from the EmacLite device */
xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
data, length);
/* Acknowledge the frame */
- reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
+ reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
reg_data &= ~XEL_RSR_RECV_DONE_MASK;
- __raw_writel(reg_data, addr + XEL_RSR_OFFSET);
+ xemaclite_writel(reg_data, addr + XEL_RSR_OFFSET);
return length;
}
@@ -465,14 +477,14 @@ static void xemaclite_update_address(struct net_local *drvdata,
xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
- __raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
+ xemaclite_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
/* Update the MAC address in the EmacLite */
- reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
- __raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
+ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
+ xemaclite_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
/* Wait for EmacLite to finish with the MAC address update */
- while ((__raw_readl(addr + XEL_TSR_OFFSET) &
+ while ((xemaclite_readl(addr + XEL_TSR_OFFSET) &
XEL_TSR_PROG_MAC_ADDR) != 0)
;
}
@@ -605,7 +617,7 @@ static void xemaclite_rx_handler(struct net_device *dev)
skb_reserve(skb, 2);
- len = xemaclite_recv_data(lp, (u8 *) skb->data);
+ len = xemaclite_recv_data(lp, (u8 *) skb->data, len);
if (!len) {
dev->stats.rx_errors++;
@@ -642,32 +654,32 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
u32 tx_status;
/* Check if there is Rx Data available */
- if ((__raw_readl(base_addr + XEL_RSR_OFFSET) &
+ if ((xemaclite_readl(base_addr + XEL_RSR_OFFSET) &
XEL_RSR_RECV_DONE_MASK) ||
- (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
+ (xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
& XEL_RSR_RECV_DONE_MASK))
xemaclite_rx_handler(dev);
/* Check if the Transmission for the first buffer is completed */
- tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET);
+ tx_status = xemaclite_readl(base_addr + XEL_TSR_OFFSET);
if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
- __raw_writel(tx_status, base_addr + XEL_TSR_OFFSET);
+ xemaclite_writel(tx_status, base_addr + XEL_TSR_OFFSET);
tx_complete = true;
}
/* Check if the Transmission for the second buffer is completed */
- tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+ tx_status = xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
- __raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
- XEL_TSR_OFFSET);
+ xemaclite_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
+ XEL_TSR_OFFSET);
tx_complete = true;
}
@@ -700,7 +712,7 @@ static int xemaclite_mdio_wait(struct net_local *lp)
/* wait for the MDIO interface to not be busy or timeout
after some time.
*/
- while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
+ while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
XEL_MDIOCTRL_MDIOSTS_MASK) {
if (time_before_eq(end, jiffies)) {
WARN_ON(1);
@@ -736,17 +748,17 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg)
* MDIO Address register. Set the Status bit in the MDIO Control
* register to start a MDIO read transaction.
*/
- ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
- __raw_writel(XEL_MDIOADDR_OP_MASK |
- ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
- lp->base_addr + XEL_MDIOADDR_OFFSET);
- __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
- lp->base_addr + XEL_MDIOCTRL_OFFSET);
+ ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+ xemaclite_writel(XEL_MDIOADDR_OP_MASK |
+ ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+ lp->base_addr + XEL_MDIOADDR_OFFSET);
+ xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+ lp->base_addr + XEL_MDIOCTRL_OFFSET);
if (xemaclite_mdio_wait(lp))
return -ETIMEDOUT;
- rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET);
+ rc = xemaclite_readl(lp->base_addr + XEL_MDIORD_OFFSET);
dev_dbg(&lp->ndev->dev,
"xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
@@ -783,13 +795,13 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
* Data register. Finally, set the Status bit in the MDIO Control
* register to start a MDIO write transaction.
*/
- ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
- __raw_writel(~XEL_MDIOADDR_OP_MASK &
- ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
- lp->base_addr + XEL_MDIOADDR_OFFSET);
- __raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
- __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
- lp->base_addr + XEL_MDIOCTRL_OFFSET);
+ ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+ xemaclite_writel(~XEL_MDIOADDR_OP_MASK &
+ ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+ lp->base_addr + XEL_MDIOADDR_OFFSET);
+ xemaclite_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
+ xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+ lp->base_addr + XEL_MDIOCTRL_OFFSET);
return 0;
}
@@ -836,8 +848,8 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
/* Enable the MDIO bus by asserting the enable bit in MDIO Control
* register.
*/
- __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK,
- lp->base_addr + XEL_MDIOCTRL_OFFSET);
+ xemaclite_writel(XEL_MDIOCTRL_MDIOEN_MASK,
+ lp->base_addr + XEL_MDIOCTRL_OFFSET);
bus = mdiobus_alloc();
if (!bus) {
@@ -1141,8 +1153,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
dev_warn(dev, "No MAC address found\n");
/* Clear the Tx CSR's in case this is a restart */
- __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET);
- __raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+ xemaclite_writel(0, lp->base_addr + XEL_TSR_OFFSET);
+ xemaclite_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
/* Set the MAC address in the EmacLite device */
xemaclite_update_address(lp, ndev->dev_addr);
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 85828f153445..0758d0816840 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -648,8 +648,8 @@ static void ax_setup(struct net_device *dev)
{
/* Finish setting up the DEVICE info. */
dev->mtu = AX_MTU;
- dev->hard_header_len = 0;
- dev->addr_len = 0;
+ dev->hard_header_len = AX25_MAX_HEADER_LEN;
+ dev->addr_len = AX25_ADDR_LEN;
dev->type = ARPHRD_AX25;
dev->tx_queue_len = 10;
dev->header_ops = &ax25_header_ops;
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index fbb1867ff25c..1c27e6fb99f9 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -1851,6 +1851,9 @@ static int r8152_poll(struct napi_struct *napi, int budget)
napi_complete(napi);
if (!list_empty(&tp->rx_done))
napi_schedule(napi);
+ else if (!skb_queue_empty(&tp->tx_queue) &&
+ !list_empty(&tp->tx_free))
+ napi_schedule(napi);
}
return work_done;
@@ -2990,10 +2993,13 @@ static void set_carrier(struct r8152 *tp)
if (!netif_carrier_ok(netdev)) {
tp->rtl_ops.enable(tp);
set_bit(RTL8152_SET_RX_MODE, &tp->flags);
+ netif_stop_queue(netdev);
napi_disable(&tp->napi);
netif_carrier_on(netdev);
rtl_start_rx(tp);
napi_enable(&tp->napi);
+ netif_wake_queue(netdev);
+ netif_info(tp, link, netdev, "carrier on\n");
}
} else {
if (netif_carrier_ok(netdev)) {
@@ -3001,6 +3007,7 @@ static void set_carrier(struct r8152 *tp)
napi_disable(&tp->napi);
tp->rtl_ops.disable(tp);
napi_enable(&tp->napi);
+ netif_info(tp, link, netdev, "carrier off\n");
}
}
}
@@ -3385,12 +3392,12 @@ static int rtl8152_pre_reset(struct usb_interface *intf)
if (!netif_running(netdev))
return 0;
+ netif_stop_queue(netdev);
napi_disable(&tp->napi);
clear_bit(WORK_ENABLE, &tp->flags);
usb_kill_urb(tp->intr_urb);
cancel_delayed_work_sync(&tp->schedule);
if (netif_carrier_ok(netdev)) {
- netif_stop_queue(netdev);
mutex_lock(&tp->control);
tp->rtl_ops.disable(tp);
mutex_unlock(&tp->control);
@@ -3415,12 +3422,14 @@ static int rtl8152_post_reset(struct usb_interface *intf)
if (netif_carrier_ok(netdev)) {
mutex_lock(&tp->control);
tp->rtl_ops.enable(tp);
+ rtl_start_rx(tp);
rtl8152_set_rx_mode(netdev);
mutex_unlock(&tp->control);
- netif_wake_queue(netdev);
}
napi_enable(&tp->napi);
+ netif_wake_queue(netdev);
+ usb_submit_urb(tp->intr_urb, GFP_KERNEL);
return 0;
}
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index a251588762ec..0b5a84c9022c 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -73,8 +73,6 @@ static atomic_t iface_counter = ATOMIC_INIT(0);
/* Private data structure */
struct sierra_net_data {
- u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */
-
u16 link_up; /* air link up or down */
u8 tx_hdr_template[4]; /* part of HIP hdr for tx'd packets */
@@ -122,6 +120,7 @@ struct param {
/* LSI Protocol types */
#define SIERRA_NET_PROTOCOL_UMTS 0x01
+#define SIERRA_NET_PROTOCOL_UMTS_DS 0x04
/* LSI Coverage */
#define SIERRA_NET_COVERAGE_NONE 0x00
#define SIERRA_NET_COVERAGE_NOPACKET 0x01
@@ -129,7 +128,8 @@ struct param {
/* LSI Session */
#define SIERRA_NET_SESSION_IDLE 0x00
/* LSI Link types */
-#define SIERRA_NET_AS_LINK_TYPE_IPv4 0x00
+#define SIERRA_NET_AS_LINK_TYPE_IPV4 0x00
+#define SIERRA_NET_AS_LINK_TYPE_IPV6 0x02
struct lsi_umts {
u8 protocol;
@@ -137,9 +137,14 @@ struct lsi_umts {
__be16 length;
/* eventually use a union for the rest - assume umts for now */
u8 coverage;
- u8 unused2[41];
+ u8 network_len; /* network name len */
+ u8 network[40]; /* network name (UCS2, bigendian) */
u8 session_state;
u8 unused3[33];
+} __packed;
+
+struct lsi_umts_single {
+ struct lsi_umts lsi;
u8 link_type;
u8 pdp_addr_len; /* NW-supplied PDP address len */
u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */
@@ -158,10 +163,31 @@ struct lsi_umts {
u8 reserved[8];
} __packed;
+struct lsi_umts_dual {
+ struct lsi_umts lsi;
+ u8 pdp_addr4_len; /* NW-supplied PDP IPv4 address len */
+ u8 pdp_addr4[4]; /* NW-supplied PDP IPv4 address (bigendian)) */
+ u8 pdp_addr6_len; /* NW-supplied PDP IPv6 address len */
+ u8 pdp_addr6[16]; /* NW-supplied PDP IPv6 address (bigendian)) */
+ u8 unused4[23];
+ u8 dns1_addr4_len; /* NW-supplied 1st DNS v4 address len (bigendian) */
+ u8 dns1_addr4[4]; /* NW-supplied 1st DNS v4 address */
+ u8 dns1_addr6_len; /* NW-supplied 1st DNS v6 address len */
+ u8 dns1_addr6[16]; /* NW-supplied 1st DNS v6 address (bigendian)*/
+ u8 dns2_addr4_len; /* NW-supplied 2nd DNS v4 address len (bigendian) */
+ u8 dns2_addr4[4]; /* NW-supplied 2nd DNS v4 address */
+ u8 dns2_addr6_len; /* NW-supplied 2nd DNS v6 address len */
+ u8 dns2_addr6[16]; /* NW-supplied 2nd DNS v6 address (bigendian)*/
+ u8 unused5[68];
+} __packed;
+
#define SIERRA_NET_LSI_COMMON_LEN 4
-#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts))
+#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts_single))
#define SIERRA_NET_LSI_UMTS_STATUS_LEN \
(SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN)
+#define SIERRA_NET_LSI_UMTS_DS_LEN (sizeof(struct lsi_umts_dual))
+#define SIERRA_NET_LSI_UMTS_DS_STATUS_LEN \
+ (SIERRA_NET_LSI_UMTS_DS_LEN - SIERRA_NET_LSI_COMMON_LEN)
/* Forward definitions */
static void sierra_sync_timer(unsigned long syncdata);
@@ -191,10 +217,11 @@ static inline void sierra_net_set_private(struct usbnet *dev,
dev->data[0] = (unsigned long)priv;
}
-/* is packet IPv4 */
+/* is packet IPv4/IPv6 */
static inline int is_ip(struct sk_buff *skb)
{
- return skb->protocol == cpu_to_be16(ETH_P_IP);
+ return skb->protocol == cpu_to_be16(ETH_P_IP) ||
+ skb->protocol == cpu_to_be16(ETH_P_IPV6);
}
/*
@@ -350,49 +377,54 @@ static inline int sierra_net_is_valid_addrlen(u8 len)
static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
{
struct lsi_umts *lsi = (struct lsi_umts *)data;
+ u32 expected_length;
- if (datalen < sizeof(struct lsi_umts)) {
- netdev_err(dev->net, "%s: Data length %d, exp %Zu\n",
- __func__, datalen,
- sizeof(struct lsi_umts));
+ if (datalen < sizeof(struct lsi_umts_single)) {
+ netdev_err(dev->net, "%s: Data length %d, exp >= %Zu\n",
+ __func__, datalen, sizeof(struct lsi_umts_single));
return -1;
}
- if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) {
- netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n",
- __func__, be16_to_cpu(lsi->length),
- (u32)SIERRA_NET_LSI_UMTS_STATUS_LEN);
- return -1;
+ /* Validate the session state */
+ if (lsi->session_state == SIERRA_NET_SESSION_IDLE) {
+ netdev_err(dev->net, "Session idle, 0x%02x\n",
+ lsi->session_state);
+ return 0;
}
/* Validate the protocol - only support UMTS for now */
- if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) {
+ if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS) {
+ struct lsi_umts_single *single = (struct lsi_umts_single *)lsi;
+
+ /* Validate the link type */
+ if (single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV4 &&
+ single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV6) {
+ netdev_err(dev->net, "Link type unsupported: 0x%02x\n",
+ single->link_type);
+ return -1;
+ }
+ expected_length = SIERRA_NET_LSI_UMTS_STATUS_LEN;
+ } else if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS_DS) {
+ expected_length = SIERRA_NET_LSI_UMTS_DS_STATUS_LEN;
+ } else {
netdev_err(dev->net, "Protocol unsupported, 0x%02x\n",
- lsi->protocol);
+ lsi->protocol);
return -1;
}
- /* Validate the link type */
- if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) {
- netdev_err(dev->net, "Link type unsupported: 0x%02x\n",
- lsi->link_type);
+ if (be16_to_cpu(lsi->length) != expected_length) {
+ netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n",
+ __func__, be16_to_cpu(lsi->length), expected_length);
return -1;
}
/* Validate the coverage */
- if (lsi->coverage == SIERRA_NET_COVERAGE_NONE
- || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
+ if (lsi->coverage == SIERRA_NET_COVERAGE_NONE ||
+ lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage);
return 0;
}
- /* Validate the session state */
- if (lsi->session_state == SIERRA_NET_SESSION_IDLE) {
- netdev_err(dev->net, "Session idle, 0x%02x\n",
- lsi->session_state);
- return 0;
- }
-
/* Set link_sense true */
return 1;
}
@@ -662,7 +694,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
u8 numendpoints;
u16 fwattr = 0;
int status;
- struct ethhdr *eth;
struct sierra_net_data *priv;
static const u8 sync_tmplate[sizeof(priv->sync_msg)] = {
0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00};
@@ -700,11 +731,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter);
dev->net->dev_addr[ETH_ALEN-1] = ifacenum;
- /* we will have to manufacture ethernet headers, prepare template */
- eth = (struct ethhdr *)priv->ethr_hdr_tmpl;
- memcpy(&eth->h_dest, dev->net->dev_addr, ETH_ALEN);
- eth->h_proto = cpu_to_be16(ETH_P_IP);
-
/* prepare shutdown message template */
memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg));
/* set context index initially to 0 - prepares tx hdr template */
@@ -833,9 +859,14 @@ static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
skb_pull(skb, hh.hdrlen);
- /* We are going to accept this packet, prepare it */
- memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl,
- ETH_HLEN);
+ /* We are going to accept this packet, prepare it.
+ * In case protocol is IPv6, keep it, otherwise force IPv4.
+ */
+ skb_reset_mac_header(skb);
+ if (eth_hdr(skb)->h_proto != cpu_to_be16(ETH_P_IPV6))
+ eth_hdr(skb)->h_proto = cpu_to_be16(ETH_P_IP);
+ eth_zero_addr(eth_hdr(skb)->h_source);
+ memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
/* Last packet in batch handled by usbnet */
if (hh.payload_len.word == skb->len)
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 486af5dac5df..2217e0cae4da 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -333,5 +333,6 @@ source "drivers/net/wireless/cw1200/Kconfig"
source "drivers/net/wireless/rsi/Kconfig"
source "drivers/net/wireless/cnss/Kconfig"
source "drivers/net/wireless/cnss_genl/Kconfig"
+source "drivers/net/wireless/cnss_utils/Kconfig"
endif # WLAN
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 0204fc00f0c5..704a976bdfb5 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -67,3 +67,4 @@ obj-$(CONFIG_CNSS) += cnss/
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/
obj-$(CONFIG_CNSS_CRYPTO) += cnss_crypto/
obj-$(CONFIG_CNSS_GENL) += cnss_genl/
+obj-$(CONFIG_CNSS_UTILS) += cnss_utils/
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 24485466704b..e430bab869a8 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6633,7 +6633,8 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
goto exit;
}
- ath10k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
+ if (!QCA_REV_WCN3990(ar))
+ ath10k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
spin_lock_bh(&ar->data_lock);
memcpy(survey, ar_survey, sizeof(*survey));
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 1544eb175c7f..888ab5ad37f1 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -684,6 +684,13 @@ static int ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k *ar,
arg->noise_floor = ev->noise_floor;
arg->rx_clear_count = ev->rx_clear_count;
arg->cycle_count = ev->cycle_count;
+ arg->chan_tx_pwr_range = ev->chan_tx_pwr_range;
+ arg->chan_tx_pwr_tp = ev->chan_tx_pwr_tp;
+ arg->rx_frame_count = ev->rx_frame_count;
+ arg->my_bss_rx_cycle_count = ev->my_bss_rx_cycle_count;
+ arg->rx_11b_mode_data_duration = ev->rx_11b_mode_data_duration;
+ arg->tx_frame_cnt = ev->tx_frame_cnt;
+ arg->mac_clk_mhz = ev->mac_clk_mhz;
kfree(tb);
return 0;
@@ -1527,11 +1534,14 @@ ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
cmd->ie_len = __cpu_to_le32(arg->ie_len);
cmd->num_probes = __cpu_to_le32(3);
- if (QCA_REV_WCN3990(ar))
+ if (QCA_REV_WCN3990(ar)) {
cmd->common.scan_ctrl_flags = ar->fw_flags->flags;
- else
+ cmd->common.scan_ctrl_flags |=
+ __cpu_to_le32(WMI_SCAN_CHAN_STAT_EVENT);
+ } else {
cmd->common.scan_ctrl_flags ^=
__cpu_to_le32(WMI_SCAN_FILTER_PROBE_REQ);
+ }
ptr += sizeof(*tlv);
ptr += sizeof(*cmd);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index c36b0fc435d4..d60e7fbb7e74 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2446,6 +2446,31 @@ static int ath10k_wmi_10_4_op_pull_ch_info_ev(struct ath10k *ar,
return 0;
}
+static void wlan_fill_survey_result(struct ath10k *ar,
+ struct survey_info *survey,
+ struct wmi_ch_info_ev_arg arg)
+{
+ u64 clock_freq;
+
+ if (!arg.mac_clk_mhz || !survey)
+ return;
+
+ clock_freq = arg.mac_clk_mhz * 1000;
+
+ memset(survey, 0, sizeof(*survey));
+
+ survey->noise = __le32_to_cpu(arg.noise_floor);
+ survey->time = __le32_to_cpu(arg.cycle_count) / clock_freq;
+ survey->time_busy = __le32_to_cpu(arg.rx_clear_count) / clock_freq;
+ survey->time_tx = __le32_to_cpu(arg.rx_clear_count) / clock_freq;
+
+ survey->filled = SURVEY_INFO_NOISE_DBM;
+ ar->ch_info_can_report_survey = true;
+
+ survey->filled |= (SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY |
+ SURVEY_INFO_TIME_TX);
+}
+
void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_ch_info_ev_arg arg = {};
@@ -2490,6 +2515,12 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
goto exit;
}
+ if (QCA_REV_WCN3990(ar)) {
+ survey = &ar->survey[idx];
+ wlan_fill_survey_result(ar, survey, arg);
+ goto exit;
+ }
+
if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) {
if (ar->ch_info_can_report_survey) {
survey = &ar->survey[idx];
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 13cac69581d6..9bd374910379 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6034,6 +6034,13 @@ struct wmi_chan_info_event {
__le32 noise_floor;
__le32 rx_clear_count;
__le32 cycle_count;
+ __le32 chan_tx_pwr_range;
+ __le32 chan_tx_pwr_tp;
+ __le32 rx_frame_count;
+ __le32 my_bss_rx_cycle_count;
+ __le32 rx_11b_mode_data_duration;
+ __le32 tx_frame_cnt;
+ __le32 mac_clk_mhz;
} __packed;
struct wmi_10_4_chan_info_event {
@@ -6247,6 +6254,10 @@ struct wmi_ch_info_ev_arg {
__le32 chan_tx_pwr_range;
__le32 chan_tx_pwr_tp;
__le32 rx_frame_count;
+ __le32 my_bss_rx_cycle_count;
+ __le32 rx_11b_mode_data_duration;
+ __le32 tx_frame_cnt;
+ __le32 mac_clk_mhz;
};
struct wmi_vdev_start_ev_arg {
diff --git a/drivers/net/wireless/cnss/Kconfig b/drivers/net/wireless/cnss/Kconfig
index 8e69a2b469b9..8946f65df716 100644
--- a/drivers/net/wireless/cnss/Kconfig
+++ b/drivers/net/wireless/cnss/Kconfig
@@ -1,5 +1,6 @@
config CNSS
tristate "CNSS driver for wifi module"
+ select CNSS_UTILS
select CRYPTO
select CRYPTO_HASH
select CRYPTO_BLKCIPHER
diff --git a/drivers/net/wireless/cnss_utils/Kconfig b/drivers/net/wireless/cnss_utils/Kconfig
new file mode 100644
index 000000000000..5f43e4872d65
--- /dev/null
+++ b/drivers/net/wireless/cnss_utils/Kconfig
@@ -0,0 +1,6 @@
+config CNSS_UTILS
+ bool "CNSS utilities support"
+ ---help---
+ Add CNSS utilities support for the WLAN driver module.
+ This feature enable wlan driver to use CNSS utilities APIs to set
+ and get wlan related information. \ No newline at end of file
diff --git a/drivers/net/wireless/cnss_utils/Makefile b/drivers/net/wireless/cnss_utils/Makefile
new file mode 100644
index 000000000000..0d1ed7ae939e
--- /dev/null
+++ b/drivers/net/wireless/cnss_utils/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_CNSS_UTILS) += cnss_utils.o
diff --git a/drivers/net/wireless/cnss_utils/cnss_utils.c b/drivers/net/wireless/cnss_utils/cnss_utils.c
new file mode 100644
index 000000000000..a452900868c4
--- /dev/null
+++ b/drivers/net/wireless/cnss_utils/cnss_utils.c
@@ -0,0 +1,310 @@
+/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "cnss_utils: " fmt
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/etherdevice.h>
+#include <net/cnss_utils.h>
+
+#define CNSS_MAX_CH_NUM 45
+struct cnss_unsafe_channel_list {
+ u16 unsafe_ch_count;
+ u16 unsafe_ch_list[CNSS_MAX_CH_NUM];
+};
+
+struct cnss_dfs_nol_info {
+ void *dfs_nol_info;
+ u16 dfs_nol_info_len;
+};
+
+#define MAX_NO_OF_MAC_ADDR 4
+struct cnss_wlan_mac_addr {
+ u8 mac_addr[MAX_NO_OF_MAC_ADDR][ETH_ALEN];
+ u32 no_of_mac_addr_set;
+};
+
+static struct cnss_utils_priv {
+ struct cnss_unsafe_channel_list unsafe_channel_list;
+ struct cnss_dfs_nol_info dfs_nol_info;
+ /* generic mutex for unsafe channel */
+ struct mutex unsafe_channel_list_lock;
+ /* generic spin-lock for dfs_nol info */
+ spinlock_t dfs_nol_info_lock;
+ int driver_load_cnt;
+ bool is_wlan_mac_set;
+ struct cnss_wlan_mac_addr wlan_mac_addr;
+ enum cnss_utils_cc_src cc_source;
+} *cnss_utils_priv;
+
+int cnss_utils_set_wlan_unsafe_channel(struct device *dev,
+ u16 *unsafe_ch_list, u16 ch_count)
+{
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+
+ if (!priv)
+ return -EINVAL;
+
+ mutex_lock(&priv->unsafe_channel_list_lock);
+ if ((!unsafe_ch_list) || (ch_count > CNSS_MAX_CH_NUM)) {
+ mutex_unlock(&priv->unsafe_channel_list_lock);
+ return -EINVAL;
+ }
+
+ priv->unsafe_channel_list.unsafe_ch_count = ch_count;
+
+ if (ch_count == 0)
+ goto end;
+
+ memcpy(priv->unsafe_channel_list.unsafe_ch_list,
+ unsafe_ch_list, ch_count * sizeof(u16));
+
+end:
+ mutex_unlock(&priv->unsafe_channel_list_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_utils_set_wlan_unsafe_channel);
+
+int cnss_utils_get_wlan_unsafe_channel(struct device *dev,
+ u16 *unsafe_ch_list,
+ u16 *ch_count, u16 buf_len)
+{
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+
+ if (!priv)
+ return -EINVAL;
+
+ mutex_lock(&priv->unsafe_channel_list_lock);
+ if (!unsafe_ch_list || !ch_count) {
+ mutex_unlock(&priv->unsafe_channel_list_lock);
+ return -EINVAL;
+ }
+
+ if (buf_len <
+ (priv->unsafe_channel_list.unsafe_ch_count * sizeof(u16))) {
+ mutex_unlock(&priv->unsafe_channel_list_lock);
+ return -ENOMEM;
+ }
+
+ *ch_count = priv->unsafe_channel_list.unsafe_ch_count;
+ memcpy(unsafe_ch_list, priv->unsafe_channel_list.unsafe_ch_list,
+ priv->unsafe_channel_list.unsafe_ch_count * sizeof(u16));
+ mutex_unlock(&priv->unsafe_channel_list_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_utils_get_wlan_unsafe_channel);
+
+int cnss_utils_wlan_set_dfs_nol(struct device *dev,
+ const void *info, u16 info_len)
+{
+ void *temp;
+ void *old_nol_info;
+ struct cnss_dfs_nol_info *dfs_info;
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+
+ if (!priv)
+ return -EINVAL;
+
+ if (!info || !info_len)
+ return -EINVAL;
+
+ temp = kmalloc(info_len, GFP_ATOMIC);
+ if (!temp)
+ return -ENOMEM;
+
+ memcpy(temp, info, info_len);
+ spin_lock_bh(&priv->dfs_nol_info_lock);
+ dfs_info = &priv->dfs_nol_info;
+ old_nol_info = dfs_info->dfs_nol_info;
+ dfs_info->dfs_nol_info = temp;
+ dfs_info->dfs_nol_info_len = info_len;
+ spin_unlock_bh(&priv->dfs_nol_info_lock);
+ kfree(old_nol_info);
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_utils_wlan_set_dfs_nol);
+
+int cnss_utils_wlan_get_dfs_nol(struct device *dev,
+ void *info, u16 info_len)
+{
+ int len;
+ struct cnss_dfs_nol_info *dfs_info;
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+
+ if (!priv)
+ return -EINVAL;
+
+ if (!info || !info_len)
+ return -EINVAL;
+
+ spin_lock_bh(&priv->dfs_nol_info_lock);
+
+ dfs_info = &priv->dfs_nol_info;
+ if (!dfs_info->dfs_nol_info ||
+ dfs_info->dfs_nol_info_len == 0) {
+ spin_unlock_bh(&priv->dfs_nol_info_lock);
+ return -ENOENT;
+ }
+
+ len = min(info_len, dfs_info->dfs_nol_info_len);
+ memcpy(info, dfs_info->dfs_nol_info, len);
+ spin_unlock_bh(&priv->dfs_nol_info_lock);
+
+ return len;
+}
+EXPORT_SYMBOL(cnss_utils_wlan_get_dfs_nol);
+
+void cnss_utils_increment_driver_load_cnt(struct device *dev)
+{
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+
+ if (!priv)
+ return;
+
+ ++(priv->driver_load_cnt);
+}
+EXPORT_SYMBOL(cnss_utils_increment_driver_load_cnt);
+
+int cnss_utils_get_driver_load_cnt(struct device *dev)
+{
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+
+ if (!priv)
+ return -EINVAL;
+
+ return priv->driver_load_cnt;
+}
+EXPORT_SYMBOL(cnss_utils_get_driver_load_cnt);
+
+int cnss_utils_set_wlan_mac_address(const u8 *in, const uint32_t len)
+{
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+ u32 no_of_mac_addr;
+ struct cnss_wlan_mac_addr *addr = NULL;
+ int iter;
+ u8 *temp = NULL;
+
+ if (!priv)
+ return -EINVAL;
+
+ if (priv->is_wlan_mac_set) {
+ pr_debug("WLAN MAC address is already set\n");
+ return 0;
+ }
+
+ if (len == 0 || (len % ETH_ALEN) != 0) {
+ pr_err("Invalid length %d\n", len);
+ return -EINVAL;
+ }
+
+ no_of_mac_addr = len / ETH_ALEN;
+ if (no_of_mac_addr > MAX_NO_OF_MAC_ADDR) {
+ pr_err("Exceed maximum supported MAC address %u %u\n",
+ MAX_NO_OF_MAC_ADDR, no_of_mac_addr);
+ return -EINVAL;
+ }
+
+ priv->is_wlan_mac_set = true;
+ addr = &priv->wlan_mac_addr;
+ addr->no_of_mac_addr_set = no_of_mac_addr;
+ temp = &addr->mac_addr[0][0];
+
+ for (iter = 0; iter < no_of_mac_addr;
+ ++iter, temp += ETH_ALEN, in += ETH_ALEN) {
+ ether_addr_copy(temp, in);
+ pr_debug("MAC_ADDR:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ temp[0], temp[1], temp[2],
+ temp[3], temp[4], temp[5]);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_utils_set_wlan_mac_address);
+
+u8 *cnss_utils_get_wlan_mac_address(struct device *dev, uint32_t *num)
+{
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+ struct cnss_wlan_mac_addr *addr = NULL;
+
+ if (!priv)
+ goto out;
+
+ if (!priv->is_wlan_mac_set) {
+ pr_debug("WLAN MAC address is not set\n");
+ goto out;
+ }
+
+ addr = &priv->wlan_mac_addr;
+ *num = addr->no_of_mac_addr_set;
+ return &addr->mac_addr[0][0];
+out:
+ *num = 0;
+ return NULL;
+}
+EXPORT_SYMBOL(cnss_utils_get_wlan_mac_address);
+
+void cnss_utils_set_cc_source(struct device *dev,
+ enum cnss_utils_cc_src cc_source)
+{
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+
+ if (!priv)
+ return;
+
+ priv->cc_source = cc_source;
+}
+EXPORT_SYMBOL(cnss_utils_set_cc_source);
+
+enum cnss_utils_cc_src cnss_utils_get_cc_source(struct device *dev)
+{
+ struct cnss_utils_priv *priv = cnss_utils_priv;
+
+ if (!priv)
+ return -EINVAL;
+
+ return priv->cc_source;
+}
+EXPORT_SYMBOL(cnss_utils_get_cc_source);
+
+static int __init cnss_utils_init(void)
+{
+ struct cnss_utils_priv *priv = NULL;
+
+ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->cc_source = CNSS_UTILS_SOURCE_CORE;
+
+ mutex_init(&priv->unsafe_channel_list_lock);
+ spin_lock_init(&priv->dfs_nol_info_lock);
+
+ cnss_utils_priv = priv;
+
+ return 0;
+}
+
+static void __exit cnss_utils_exit(void)
+{
+ kfree(cnss_utils_priv);
+ cnss_utils_priv = NULL;
+}
+
+module_init(cnss_utils_init);
+module_exit(cnss_utils_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(DEVICE "CNSS Utilities Driver");
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 6e3a60c78873..50f3bb0dd1f1 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -293,7 +293,7 @@ struct parport *parport_gsc_probe_port(unsigned long base,
p->irq = PARPORT_IRQ_NONE;
}
if (p->irq != PARPORT_IRQ_NONE) {
- printk(", irq %d", p->irq);
+ pr_cont(", irq %d", p->irq);
if (p->dma == PARPORT_DMA_AUTO) {
p->dma = PARPORT_DMA_NONE;
@@ -303,8 +303,8 @@ struct parport *parport_gsc_probe_port(unsigned long base,
is mandatory (see above) */
p->dma = PARPORT_DMA_NONE;
- printk(" [");
-#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}}
+ pr_cont(" [");
+#define printmode(x) {if(p->modes&PARPORT_MODE_##x){pr_cont("%s%s",f?",":"",#x);f++;}}
{
int f = 0;
printmode(PCSPP);
@@ -315,7 +315,7 @@ struct parport *parport_gsc_probe_port(unsigned long base,
// printmode(DMA);
}
#undef printmode
- printk("]\n");
+ pr_cont("]\n");
if (p->irq != PARPORT_IRQ_NONE) {
if (request_irq (p->irq, parport_irq_handler,
diff --git a/drivers/pinctrl/berlin/berlin-bg4ct.c b/drivers/pinctrl/berlin/berlin-bg4ct.c
index 09172043d589..c617ec49e9ed 100644
--- a/drivers/pinctrl/berlin/berlin-bg4ct.c
+++ b/drivers/pinctrl/berlin/berlin-bg4ct.c
@@ -217,7 +217,7 @@ static const struct berlin_desc_group berlin4ct_soc_pinctrl_groups[] = {
BERLIN_PINCTRL_GROUP("SCRD0_CRD_PRES", 0xc, 0x3, 0x15,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO20 */
BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* crd pres */
- BERLIN_PINCTRL_FUNCTION(0x1, "sd1a")), /* DAT3 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* DAT3 */
BERLIN_PINCTRL_GROUP("SPI1_SS0n", 0xc, 0x3, 0x18,
BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS0n */
BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO37 */
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index 5aa39b699bd6..9b3b53dcba68 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -2046,6 +2046,8 @@ static int ipa_mhi_suspend_dl(bool force)
if (ipa_get_transport_type() == IPA_TRANSPORT_TYPE_GSI)
ipa_mhi_update_host_ch_state(true);
+ return 0;
+
fail_stop_event_update_dl_channel:
ipa_mhi_resume_channels(true,
ipa_mhi_client_ctx->dl_channels);
diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
index c59c597f39bf..834712a71ac6 100644
--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
@@ -2618,6 +2618,9 @@ static int rmnet_ipa_set_data_quota_modem(struct wan_ioctl_set_data_quota *data)
if (!data->set_quota)
ipa_qmi_stop_data_qouta();
+ /* prevent string buffer overflows */
+ data->interface_name[IFNAMSIZ-1] = '\0';
+
index = find_vchannel_name_index(data->interface_name);
IPAWANERR("iface name %s, quota %lu\n",
data->interface_name,
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 5397b6c39419..039bc7da5153 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -2746,6 +2746,9 @@ static int rmnet_ipa3_set_data_quota_modem(
if (!data->set_quota)
ipa3_qmi_stop_data_qouta();
+ /* prevent string buffer overflows */
+ data->interface_name[IFNAMSIZ-1] = '\0';
+
index = find_vchannel_name_index(data->interface_name);
IPAWANERR("iface name %s, quota %lu\n",
data->interface_name,
diff --git a/drivers/platform/msm/ipa/test/ipa_test_mhi.c b/drivers/platform/msm/ipa/test/ipa_test_mhi.c
index 5a41d641de4f..3a89c7dffdb0 100644
--- a/drivers/platform/msm/ipa/test/ipa_test_mhi.c
+++ b/drivers/platform/msm/ipa/test/ipa_test_mhi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -326,6 +326,7 @@ struct ipa_test_mhi_context {
struct ipa_mem_buffer out_buffer;
u32 prod_hdl;
u32 cons_hdl;
+ u32 test_prod_hdl;
};
static struct ipa_test_mhi_context *test_mhi_ctx;
@@ -774,6 +775,7 @@ fail_destroy_out_ch_ctx:
static int ipa_test_mhi_suite_setup(void **ppriv)
{
int rc = 0;
+ struct ipa_sys_connect_params sys_in;
IPA_UT_DBG("Start Setup\n");
@@ -815,9 +817,22 @@ static int ipa_test_mhi_suite_setup(void **ppriv)
goto fail_free_mmio_spc;
}
+ /* connect PROD pipe for remote wakeup */
+ memset(&sys_in, 0, sizeof(struct ipa_sys_connect_params));
+ sys_in.client = IPA_CLIENT_TEST_PROD;
+ sys_in.desc_fifo_sz = IPA_SYS_DESC_FIFO_SZ;
+ sys_in.ipa_ep_cfg.mode.mode = IPA_DMA;
+ sys_in.ipa_ep_cfg.mode.dst = IPA_CLIENT_MHI_CONS;
+ if (ipa_setup_sys_pipe(&sys_in, &test_mhi_ctx->test_prod_hdl)) {
+ IPA_UT_ERR("setup sys pipe failed.\n");
+ goto fail_destroy_data_structures;
+ }
+
*ppriv = test_mhi_ctx;
return 0;
+fail_destroy_data_structures:
+ ipa_mhi_test_destroy_data_structures();
fail_free_mmio_spc:
ipa_test_mhi_free_mmio_space();
fail_iounmap:
@@ -838,6 +853,7 @@ static int ipa_test_mhi_suite_teardown(void *priv)
if (!test_mhi_ctx)
return 0;
+ ipa_teardown_sys_pipe(test_mhi_ctx->test_prod_hdl);
ipa_mhi_test_destroy_data_structures();
ipa_test_mhi_free_mmio_space();
iounmap(test_mhi_ctx->gsi_mmio);
@@ -1811,7 +1827,7 @@ static int ipa_mhi_test_create_aggr_open_frame(void)
memset(test_mhi_ctx->out_buffer.base + i, i & 0xFF, 1);
}
- rc = ipa_tx_dp(IPA_CLIENT_MHI_CONS, skb, NULL);
+ rc = ipa_tx_dp(IPA_CLIENT_TEST_PROD, skb, NULL);
if (rc) {
IPA_UT_LOG("ipa_tx_dp failed %d\n", rc);
IPA_UT_TEST_FAIL_REPORT("ipa tx dp fail");
@@ -1982,7 +1998,7 @@ static int ipa_mhi_test_suspend_host_wakeup(void)
memset(test_mhi_ctx->out_buffer.base + i, i & 0xFF, 1);
}
- rc = ipa_tx_dp(IPA_CLIENT_MHI_CONS, skb, NULL);
+ rc = ipa_tx_dp(IPA_CLIENT_TEST_PROD, skb, NULL);
if (rc) {
IPA_UT_LOG("ipa_tx_dp failed %d\n", rc);
IPA_UT_TEST_FAIL_REPORT("ipa tx dp fail");
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 5cb017fdf2d3..a151d0c7a770 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -3100,79 +3100,6 @@ static int enable_usb_bam(struct platform_device *pdev)
return 0;
}
-static ssize_t
-usb_bam_show_inactivity_timer(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- char *buff = buf;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bam_enable_strings); i++) {
- buff += snprintf(buff, PAGE_SIZE, "%s: %dms\n",
- bam_enable_strings[i],
- msm_usb_bam[i].inactivity_timer_ms);
- }
-
- return buff - buf;
-}
-
-static ssize_t usb_bam_store_inactivity_timer(struct device *dev,
- struct device_attribute *attr,
- const char *buff, size_t count)
-{
- char buf[USB_BAM_MAX_STR_LEN];
- char *trimmed_buf, *bam_str, *bam_name, *timer;
- int timer_d;
- int bam;
-
- if (strnstr(buff, "help", USB_BAM_MAX_STR_LEN)) {
- pr_info("Usage: <bam_name> <ms>,<bam_name> <ms>,...\n");
- pr_info("\tbam_name: [%s, %s, %s]\n",
- bam_enable_strings[DWC3_CTRL],
- bam_enable_strings[CI_CTRL],
- bam_enable_strings[HSIC_CTRL]);
- pr_info("\tms: time in ms. Use 0 to disable timer\n");
- return count;
- }
-
- strlcpy(buf, buff, sizeof(buf));
- trimmed_buf = strim(buf);
-
- while (trimmed_buf) {
- bam_str = strsep(&trimmed_buf, ",");
- if (bam_str) {
- bam_name = strsep(&bam_str, " ");
- bam = get_bam_type_from_core_name(bam_name);
- if (bam < 0 || bam >= MAX_BAMS) {
- log_event_err("%s: Invalid bam, type=%d ,name=%s\n",
- __func__, bam, bam_name);
- return -EINVAL;
- }
-
- timer = strsep(&bam_str, " ");
-
- if (!timer)
- continue;
-
- sscanf(timer, "%d", &timer_d);
-
- /* Apply new timer setting if bam has running pipes */
- if (msm_usb_bam[bam].inactivity_timer_ms != timer_d) {
- msm_usb_bam[bam].inactivity_timer_ms = timer_d;
- if (msm_usb_bam[bam].pipes_enabled_per_bam > 0
- && !info[bam].in_lpm)
- usb_bam_set_inactivity_timer(bam);
- }
- }
- }
-
- return count;
-}
-
-static DEVICE_ATTR(inactivity_timer, S_IWUSR | S_IRUSR,
- usb_bam_show_inactivity_timer,
- usb_bam_store_inactivity_timer);
-
static int usb_bam_panic_notifier(struct notifier_block *this,
unsigned long event, void *ptr)
{
@@ -3221,12 +3148,6 @@ static int usb_bam_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "usb_bam_probe\n");
- ret = device_create_file(&pdev->dev, &dev_attr_inactivity_timer);
- if (ret) {
- dev_err(&pdev->dev, "failed to create fs node\n");
- return ret;
- }
-
io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!io_res) {
dev_err(&pdev->dev, "missing BAM memory resource\n");
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 19be40bb4785..16db425514c3 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -2861,13 +2861,13 @@ int smblib_get_prop_fcc_delta(struct smb_charger *chg,
* USB MAIN PSY SETTERS *
*************************/
-#define SDP_CURRENT_MA 500000
-#define CDP_CURRENT_MA 1500000
-#define DCP_CURRENT_MA 1500000
-#define HVDCP_CURRENT_MA 3000000
-#define TYPEC_DEFAULT_CURRENT_MA 900000
-#define TYPEC_MEDIUM_CURRENT_MA 1500000
-#define TYPEC_HIGH_CURRENT_MA 3000000
+#define SDP_CURRENT_UA 500000
+#define CDP_CURRENT_UA 1500000
+#define DCP_CURRENT_UA 1500000
+#define HVDCP_CURRENT_UA 3000000
+#define TYPEC_DEFAULT_CURRENT_UA 900000
+#define TYPEC_MEDIUM_CURRENT_UA 1500000
+#define TYPEC_HIGH_CURRENT_UA 3000000
int smblib_get_charge_current(struct smb_charger *chg,
int *total_current_ua)
{
@@ -2901,19 +2901,19 @@ int smblib_get_charge_current(struct smb_charger *chg,
/* QC 2.0/3.0 adapter */
if (apsd_result->bit & (QC_3P0_BIT | QC_2P0_BIT)) {
- *total_current_ua = HVDCP_CURRENT_MA;
+ *total_current_ua = HVDCP_CURRENT_UA;
return 0;
}
if (non_compliant) {
switch (apsd_result->bit) {
case CDP_CHARGER_BIT:
- current_ua = CDP_CURRENT_MA;
+ current_ua = CDP_CURRENT_UA;
break;
case DCP_CHARGER_BIT:
case OCP_CHARGER_BIT:
case FLOAT_CHARGER_BIT:
- current_ua = DCP_CURRENT_MA;
+ current_ua = DCP_CURRENT_UA;
break;
default:
current_ua = 0;
@@ -2928,7 +2928,7 @@ int smblib_get_charge_current(struct smb_charger *chg,
case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
switch (apsd_result->bit) {
case CDP_CHARGER_BIT:
- current_ua = CDP_CURRENT_MA;
+ current_ua = CDP_CURRENT_UA;
break;
case DCP_CHARGER_BIT:
case OCP_CHARGER_BIT:
@@ -2941,10 +2941,10 @@ int smblib_get_charge_current(struct smb_charger *chg,
}
break;
case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
- current_ua = TYPEC_MEDIUM_CURRENT_MA;
+ current_ua = TYPEC_MEDIUM_CURRENT_UA;
break;
case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
- current_ua = TYPEC_HIGH_CURRENT_MA;
+ current_ua = TYPEC_HIGH_CURRENT_UA;
break;
case POWER_SUPPLY_TYPEC_NON_COMPLIANT:
case POWER_SUPPLY_TYPEC_NONE:
@@ -3466,8 +3466,29 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg,
rising ? "rising" : "falling");
}
+static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode)
+{
+ int rp_ua;
+
+ switch (typec_mode) {
+ case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
+ rp_ua = TYPEC_HIGH_CURRENT_UA;
+ break;
+ case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
+ case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
+ /* fall through */
+ default:
+ rp_ua = DCP_CURRENT_UA;
+ }
+
+ return rp_ua;
+}
+
static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
{
+ int typec_mode;
+ int rp_ua;
+
/* while PD is active it should have complete ICL control */
if (chg->pd_active)
return;
@@ -3489,7 +3510,9 @@ static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
break;
case POWER_SUPPLY_TYPE_USB_DCP:
case POWER_SUPPLY_TYPE_USB_FLOAT:
- vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
+ typec_mode = smblib_get_prop_typec_mode(chg);
+ rp_ua = get_rp_based_dcp_current(chg, typec_mode);
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua);
break;
case POWER_SUPPLY_TYPE_USB_HVDCP:
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
@@ -3770,12 +3793,40 @@ static void smblib_handle_typec_insertion(struct smb_charger *chg)
typec_sink_removal(chg);
}
+static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode)
+{
+ int rp_ua;
+ const struct apsd_result *apsd = smblib_get_apsd_result(chg);
+
+ if ((apsd->pst != POWER_SUPPLY_TYPE_USB_DCP)
+ && (apsd->pst != POWER_SUPPLY_TYPE_USB_FLOAT))
+ return;
+
+ /*
+ * handle Rp change for DCP/FLOAT/OCP.
+ * Update the current only if the Rp is different from
+ * the last Rp value.
+ */
+ smblib_dbg(chg, PR_MISC, "CC change old_mode=%d new_mode=%d\n",
+ chg->typec_mode, typec_mode);
+
+ rp_ua = get_rp_based_dcp_current(chg, typec_mode);
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua);
+}
+
static void smblib_handle_typec_cc_state_change(struct smb_charger *chg)
{
+ int typec_mode;
+
if (chg->pr_swap_in_progress)
return;
- chg->typec_mode = smblib_get_prop_typec_mode(chg);
+ typec_mode = smblib_get_prop_typec_mode(chg);
+ if (chg->typec_present && (typec_mode != chg->typec_mode))
+ smblib_handle_rp_change(chg, typec_mode);
+
+ chg->typec_mode = typec_mode;
+
if (!chg->typec_present && chg->typec_mode != POWER_SUPPLY_TYPEC_NONE) {
chg->typec_present = true;
smblib_dbg(chg, PR_MISC, "TypeC %s insertion\n",
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index ea008ffbc856..0c4414d27eeb 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -468,6 +468,7 @@ config MINIDUMP_MAX_ENTRIES
config ICNSS
tristate "Platform driver for Q6 integrated connectivity"
+ select CNSS_UTILS
---help---
This module adds support for Q6 integrated WLAN connectivity
subsystem. This module is responsible for communicating WLAN on/off
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 548efd11e856..4499dd35f2dd 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1494,11 +1494,11 @@ static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag)
struct msm_spi *dd = spi_master_get_devdata(spi->master);
u32 spi_ioc;
u32 spi_ioc_orig;
- int rc;
+ int rc = 0;
rc = pm_runtime_get_sync(dd->dev);
if (rc < 0) {
- dev_err(dd->dev, "Failure during runtime get");
+ dev_err(dd->dev, "Failure during runtime get,rc=%d", rc);
return;
}
@@ -1513,6 +1513,15 @@ static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag)
if (!(spi->mode & SPI_CS_HIGH))
set_flag = !set_flag;
+ /* Serve only under mutex lock as RT suspend may cause a race */
+ mutex_lock(&dd->core_lock);
+ if (dd->suspended) {
+ dev_err(dd->dev, "%s: SPI operational state=%d Invalid\n",
+ __func__, dd->suspended);
+ mutex_unlock(&dd->core_lock);
+ return;
+ }
+
spi_ioc = readl_relaxed(dd->base + SPI_IO_CONTROL);
spi_ioc_orig = spi_ioc;
if (set_flag)
@@ -1524,6 +1533,8 @@ static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag)
writel_relaxed(spi_ioc, dd->base + SPI_IO_CONTROL);
if (dd->pdata->is_shared)
put_local_resources(dd);
+ mutex_unlock(&dd->core_lock);
+
pm_runtime_mark_last_busy(dd->dev);
pm_runtime_put_autosuspend(dd->dev);
}
@@ -2616,6 +2627,7 @@ static int msm_spi_pm_suspend_runtime(struct device *device)
wait_event_interruptible(dd->continue_suspend,
!dd->transfer_pending);
+ mutex_lock(&dd->core_lock);
if (dd->pdata && !dd->pdata->is_shared && dd->use_dma) {
msm_spi_bam_pipe_disconnect(dd, &dd->bam.prod);
msm_spi_bam_pipe_disconnect(dd, &dd->bam.cons);
@@ -2625,6 +2637,7 @@ static int msm_spi_pm_suspend_runtime(struct device *device)
if (dd->pdata)
msm_spi_clk_path_vote(dd, 0);
+ mutex_unlock(&dd->core_lock);
suspend_exit:
return 0;
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 3cdb40fea5ee..f5cedbbc552a 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -894,7 +894,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
return _FAIL;
- if (len > MAX_IE_SZ)
+ if (len < 0 || len > MAX_IE_SZ)
return _FAIL;
pbss_network->IELength = len;
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index 79bf13f5c0d1..7a8ceb961bb6 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -1185,8 +1185,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
struct cb_desc *cb_desc, struct sk_buff *skb)
{
struct r8192_priv *priv = rtllib_priv(dev);
- dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
- PCI_DMA_TODEVICE);
+ dma_addr_t mapping;
struct tx_fwinfo_8190pci *pTxFwInfo = NULL;
pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data;
@@ -1197,8 +1196,6 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
pTxFwInfo->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT,
pTxFwInfo->TxRate, cb_desc);
- if (pci_dma_mapping_error(priv->pdev, mapping))
- netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
if (cb_desc->bAMPDUEnable) {
pTxFwInfo->AllowAggregation = 1;
pTxFwInfo->RxMF = cb_desc->ampdu_factor;
@@ -1233,6 +1230,14 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
}
memset((u8 *)pdesc, 0, 12);
+
+ mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(priv->pdev, mapping)) {
+ netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
+ return;
+ }
+
pdesc->LINIP = 0;
pdesc->CmdInit = 1;
pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8;
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
index 195acc868763..5d476916191b 100644
--- a/drivers/tty/serial/efm32-uart.c
+++ b/drivers/tty/serial/efm32-uart.c
@@ -27,6 +27,7 @@
#define UARTn_FRAME 0x04
#define UARTn_FRAME_DATABITS__MASK 0x000f
#define UARTn_FRAME_DATABITS(n) ((n) - 3)
+#define UARTn_FRAME_PARITY__MASK 0x0300
#define UARTn_FRAME_PARITY_NONE 0x0000
#define UARTn_FRAME_PARITY_EVEN 0x0200
#define UARTn_FRAME_PARITY_ODD 0x0300
@@ -572,12 +573,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port,
16 * (4 + (clkdiv >> 6)));
frame = efm32_uart_read32(efm_port, UARTn_FRAME);
- if (frame & UARTn_FRAME_PARITY_ODD)
+ switch (frame & UARTn_FRAME_PARITY__MASK) {
+ case UARTn_FRAME_PARITY_ODD:
*parity = 'o';
- else if (frame & UARTn_FRAME_PARITY_EVEN)
+ break;
+ case UARTn_FRAME_PARITY_EVEN:
*parity = 'e';
- else
+ break;
+ default:
*parity = 'n';
+ }
*bits = (frame & UARTn_FRAME_DATABITS__MASK) -
UARTn_FRAME_DATABITS(4) + 4;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index aa00bb51940b..bc5a6966dda9 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2569,6 +2569,7 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex),
GFP_KERNEL);
if (!hcd->bandwidth_mutex) {
+ kfree(hcd->address0_mutex);
kfree(hcd);
dev_dbg(dev, "hcd bandwidth mutex alloc failed\n");
return NULL;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a4efaecf85ef..5de22f4892cd 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1329,7 +1329,13 @@ static int hub_configure(struct usb_hub *hub,
if (ret < 0) {
message = "can't read hub descriptor";
goto fail;
- } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) {
+ }
+
+ maxchild = USB_MAXCHILDREN;
+ if (hub_is_superspeed(hdev))
+ maxchild = min_t(unsigned, maxchild, USB_SS_MAXPORTS);
+
+ if (hub->descriptor->bNbrPorts > maxchild) {
message = "hub has too many ports!";
ret = -ENODEV;
goto fail;
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 2f1fb7e7aa54..9eba51b92f72 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -148,7 +148,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
if (IS_ERR(exynos->axius_clk)) {
dev_err(dev, "no AXI UpScaler clk specified\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto axius_clk_err;
}
clk_prepare_enable(exynos->axius_clk);
} else {
@@ -206,6 +207,7 @@ err3:
regulator_disable(exynos->vdd33);
err2:
clk_disable_unprepare(exynos->axius_clk);
+axius_clk_err:
clk_disable_unprepare(exynos->susp_clk);
clk_disable_unprepare(exynos->clk);
return ret;
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index 46be62b737f1..ec73b67096c5 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -776,11 +776,11 @@ static int audio_pcm_close(struct snd_pcm_substream *substream)
struct audio_dev *audio = substream->private_data;
unsigned long flags;
- spin_lock_irqsave(&audio->lock, flags);
-
/* Remove the QoS request */
pm_qos_remove_request(&audio->pm_qos);
+ spin_lock_irqsave(&audio->lock, flags);
+
audio->substream = NULL;
spin_unlock_irqrestore(&audio->lock, flags);
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index de014436fb22..43ce2cfcdb4d 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -1676,9 +1676,10 @@ static void
gadgetfs_suspend (struct usb_gadget *gadget)
{
struct dev_data *dev = get_gadget_data (gadget);
+ unsigned long flags;
INFO (dev, "suspended from state %d\n", dev->state);
- spin_lock (&dev->lock);
+ spin_lock_irqsave(&dev->lock, flags);
switch (dev->state) {
case STATE_DEV_SETUP: // VERY odd... host died??
case STATE_DEV_CONNECTED:
@@ -1689,7 +1690,7 @@ gadgetfs_suspend (struct usb_gadget *gadget)
default:
break;
}
- spin_unlock (&dev->lock);
+ spin_unlock_irqrestore(&dev->lock, flags);
}
static struct usb_gadget_driver gadgetfs_driver = {
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 6610f7a023d3..64f404a1a072 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -442,23 +442,16 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
/* Report reset and disconnect events to the driver */
if (dum->driver && (disconnect || reset)) {
stop_activity(dum);
- spin_unlock(&dum->lock);
if (reset)
usb_gadget_udc_reset(&dum->gadget, dum->driver);
else
dum->driver->disconnect(&dum->gadget);
- spin_lock(&dum->lock);
}
} else if (dum_hcd->active != dum_hcd->old_active) {
- if (dum_hcd->old_active && dum->driver->suspend) {
- spin_unlock(&dum->lock);
+ if (dum_hcd->old_active && dum->driver->suspend)
dum->driver->suspend(&dum->gadget);
- spin_lock(&dum->lock);
- } else if (!dum_hcd->old_active && dum->driver->resume) {
- spin_unlock(&dum->lock);
+ else if (!dum_hcd->old_active && dum->driver->resume)
dum->driver->resume(&dum->gadget);
- spin_lock(&dum->lock);
- }
}
dum_hcd->old_status = dum_hcd->port_status;
@@ -985,7 +978,9 @@ static int dummy_udc_stop(struct usb_gadget *g)
struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g);
struct dummy *dum = dum_hcd->dum;
+ spin_lock_irq(&dum->lock);
dum->driver = NULL;
+ spin_unlock_irq(&dum->lock);
return 0;
}
@@ -2011,7 +2006,7 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc)
HUB_CHAR_COMMON_OCPM);
desc->bNbrPorts = 1;
desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
- desc->u.ss.DeviceRemovable = 0xffff;
+ desc->u.ss.DeviceRemovable = 0;
}
static inline void hub_descriptor(struct usb_hub_descriptor *desc)
@@ -2023,8 +2018,8 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc)
HUB_CHAR_INDV_PORT_LPSM |
HUB_CHAR_COMMON_OCPM);
desc->bNbrPorts = 1;
- desc->u.hs.DeviceRemovable[0] = 0xff;
- desc->u.hs.DeviceRemovable[1] = 0xff;
+ desc->u.hs.DeviceRemovable[0] = 0;
+ desc->u.hs.DeviceRemovable[1] = 0xff; /* PortPwrCtrlMask */
}
static int dummy_hub_control(
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index 6706aef907f4..a47de8c31ce9 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -2425,11 +2425,8 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
nuke(&dev->ep[i]);
/* report disconnect; the driver is already quiesced */
- if (driver) {
- spin_unlock(&dev->lock);
+ if (driver)
driver->disconnect(&dev->gadget);
- spin_lock(&dev->lock);
- }
usb_reinit(dev);
}
@@ -3275,8 +3272,6 @@ next_endpoints:
BIT(PCI_RETRY_ABORT_INTERRUPT))
static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
-__releases(dev->lock)
-__acquires(dev->lock)
{
struct net2280_ep *ep;
u32 tmp, num, mask, scratch;
@@ -3317,14 +3312,12 @@ __acquires(dev->lock)
if (disconnect || reset) {
stop_activity(dev, dev->driver);
ep0_start(dev);
- spin_unlock(&dev->lock);
if (reset)
usb_gadget_udc_reset
(&dev->gadget, dev->driver);
else
(dev->driver->disconnect)
(&dev->gadget);
- spin_lock(&dev->lock);
return;
}
}
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 4cbd0633c5c2..a11c2c8bda53 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -1269,7 +1269,7 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
time = 30;
break;
default:
- time = 300;
+ time = 50;
break;
}
@@ -1785,6 +1785,7 @@ static void r8a66597_td_timer(unsigned long _r8a66597)
pipe = td->pipe;
pipe_stop(r8a66597, pipe);
+ /* Select a different address or endpoint */
new_td = td;
do {
list_move_tail(&new_td->queue,
@@ -1794,7 +1795,8 @@ static void r8a66597_td_timer(unsigned long _r8a66597)
new_td = td;
break;
}
- } while (td != new_td && td->address == new_td->address);
+ } while (td != new_td && td->address == new_td->address &&
+ td->pipe->info.epnum == new_td->pipe->info.epnum);
start_transfer(r8a66597, new_td);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 30c4ae80c8f9..e8f990642281 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -198,6 +198,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
pdev->device == 0x1042)
xhci->quirks |= XHCI_BROKEN_STREAMS;
+ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+ pdev->device == 0x1142)
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
if (xhci->quirks & XHCI_RESET_ON_RESUME)
xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c
index 6a2529ec1511..bd2722e8fc48 100644
--- a/drivers/usb/phy/phy-msm-qusb.c
+++ b/drivers/usb/phy/phy-msm-qusb.c
@@ -730,13 +730,15 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
writel_relaxed(intr_mask,
qphy->base + QUSB2PHY_PORT_INTR_CTRL);
- /* enable phy auto-resume */
- writel_relaxed(0x0C,
+ if (linestate & (LINESTATE_DP | LINESTATE_DM)) {
+ /* enable phy auto-resume */
+ writel_relaxed(0x0C,
qphy->base + QUSB2PHY_PORT_TEST_CTRL);
- /* flush the previous write before next write */
- wmb();
- writel_relaxed(0x04,
- qphy->base + QUSB2PHY_PORT_TEST_CTRL);
+ /* flush the previous write before next write */
+ wmb();
+ writel_relaxed(0x04,
+ qphy->base + QUSB2PHY_PORT_TEST_CTRL);
+ }
dev_dbg(phy->dev, "%s: intr_mask = %x\n",
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 31cba148ad28..fe1289633291 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -1192,11 +1192,24 @@ static int mdss_fb_init_panel_modes(struct msm_fb_data_type *mfd,
if (pdata->next) {
spt = mdss_panel_get_timing_by_name(pdata->next,
modedb[i].name);
- if (!IS_ERR_OR_NULL(spt))
+ /* for split config, recalculate xres and pixel clock */
+ if (!IS_ERR_OR_NULL(spt)) {
+ unsigned long pclk, h_total, v_total;
modedb[i].xres += spt->xres;
- else
+ h_total = modedb[i].xres +
+ modedb[i].left_margin +
+ modedb[i].right_margin +
+ modedb[i].hsync_len;
+ v_total = modedb[i].yres +
+ modedb[i].lower_margin +
+ modedb[i].upper_margin +
+ modedb[i].vsync_len;
+ pclk = h_total * v_total * modedb[i].refresh;
+ modedb[i].pixclock = KHZ2PICOS(pclk / 1000);
+ } else {
pr_debug("no matching split config for %s\n",
modedb[i].name);
+ }
/*
* if no panel timing found for current, need to
@@ -4921,6 +4934,15 @@ static int __ioctl_wait_idle(struct msm_fb_data_type *mfd, u32 cmd)
return ret;
}
+static bool check_not_supported_ioctl(u32 cmd)
+{
+ return((cmd == MSMFB_OVERLAY_SET) || (cmd == MSMFB_OVERLAY_UNSET) ||
+ (cmd == MSMFB_OVERLAY_GET) || (cmd == MSMFB_OVERLAY_PREPARE) ||
+ (cmd == MSMFB_DISPLAY_COMMIT) || (cmd == MSMFB_OVERLAY_PLAY) ||
+ (cmd == MSMFB_BUFFER_SYNC) || (cmd == MSMFB_OVERLAY_QUEUE) ||
+ (cmd == MSMFB_NOTIFY_UPDATE));
+}
+
/*
* mdss_fb_do_ioctl() - MDSS Framebuffer ioctl function
* @info: pointer to framebuffer info
@@ -4955,6 +4977,11 @@ int mdss_fb_do_ioctl(struct fb_info *info, unsigned int cmd,
if (!pdata || pdata->panel_info.dynamic_switch_pending)
return -EPERM;
+ if (check_not_supported_ioctl(cmd)) {
+ pr_err("Unsupported ioctl\n");
+ return -EINVAL;
+ }
+
atomic_inc(&mfd->ioctl_ref_cnt);
mdss_fb_power_setting_idle(mfd);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index d9aaac4526ea..c31c0149866a 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -1996,8 +1996,9 @@ static void mdss_mdp_handoff_programmable_fetch(struct mdss_mdp_ctl *ctl,
MDSS_MDP_REG_INTF_HSYNC_CTL) >> 16;
v_total_handoff = mdp_video_read(ctx,
MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0)/h_total_handoff;
- pinfo->prg_fet = v_total_handoff -
- ((fetch_start_handoff - 1)/h_total_handoff);
+ if (h_total_handoff)
+ pinfo->prg_fet = v_total_handoff -
+ ((fetch_start_handoff - 1)/h_total_handoff);
pr_debug("programmable fetch lines %d start:%d\n",
pinfo->prg_fet, fetch_start_handoff);
MDSS_XLOG(pinfo->prg_fet, fetch_start_handoff,
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index b048f356c965..e44edb8fbea7 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -1692,11 +1692,24 @@ static struct mdss_mdp_pipe *__find_and_move_cleanup_pipe(
enum mdss_mdp_pipe_rect rect_num)
{
struct mdss_mdp_pipe *pipe = NULL;
+ struct mdss_mdp_data *buf, *tmpbuf;
if (__find_pipe_in_list(&mdp5_data->pipes_destroy,
pipe_ndx, &pipe, rect_num)) {
pr_debug("reuse destroy pipe id:%d ndx:%d rect:%d\n",
pipe->num, pipe_ndx, rect_num);
+ /*
+ * Pipe is being moved from destroy list to used list.
+ * It is possible that the buffer which was attached to a pipe
+ * in destroy list hasn't been cleaned up yet. Mark the buffers
+ * as cleanup to make sure that they will be freed before the
+ * pipe is reused.
+ */
+ list_for_each_entry_safe(buf, tmpbuf, &pipe->buf_queue,
+ pipe_list) {
+ buf->state = MDP_BUF_STATE_CLEANUP;
+ list_del_init(&buf->pipe_list);
+ }
list_move(&pipe->list, &mdp5_data->pipes_used);
} else if (__find_pipe_in_list(&mdp5_data->pipes_cleanup,
pipe_ndx, &pipe, rect_num)) {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 91816611d24f..953aeb95332b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2318,6 +2318,31 @@ set_roi:
}
/*
+ * For the pipe which is being used for Secure Display,
+ * cleanup the previously queued buffers.
+ */
+static void __overlay_cleanup_secure_pipe(struct msm_fb_data_type *mfd)
+{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_pipe *pipe;
+ struct mdss_mdp_data *buf, *tmpbuf;
+
+ list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {
+ if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) {
+ list_for_each_entry_safe(buf, tmpbuf, &pipe->buf_queue,
+ pipe_list) {
+ if (buf->state == MDP_BUF_STATE_ACTIVE) {
+ __pipe_buf_mark_cleanup(mfd, buf);
+ list_move(&buf->buf_list,
+ &mdp5_data->bufs_freelist);
+ mdss_mdp_overlay_buf_free(mfd, buf);
+ }
+ }
+ }
+ }
+}
+
+/*
* Check if there is any change in secure state and store it.
*/
static void __overlay_set_secure_transition_state(struct msm_fb_data_type *mfd)
@@ -2393,9 +2418,19 @@ static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd)
if (mdp5_data->secure_transition_state == SD_NON_SECURE_TO_SECURE) {
if (!mdss_get_sd_client_cnt()) {
MDSS_XLOG(0x11);
- /*wait for ping pong done */
- if (ctl->ops.wait_pingpong)
+ /* wait for ping pong done */
+ if (ctl->ops.wait_pingpong) {
mdss_mdp_display_wait4pingpong(ctl, true);
+
+ /*
+ * For command mode panels, there will not be
+ * a NULL commit preceding secure display. If
+ * a pipe is reused for secure display,
+ * cleanup buffers in the secure pipe before
+ * detaching IOMMU.
+ */
+ __overlay_cleanup_secure_pipe(mfd);
+ }
/*
* unmap the previous commit buffers before
* transitioning to secure state