diff --git a/arch/arm/boot/dts/qcom/apq8084-camera.dtsi b/arch/arm/boot/dts/qcom/apq8084-camera.dtsi index 2d7e126c5f7f805d62c7bbda3f0195bb0ad0a0ca..abc85bf90a1a6802dc18da8e05b23f9d5b54676f 100644 --- a/arch/arm/boot/dts/qcom/apq8084-camera.dtsi +++ b/arch/arm/boot/dts/qcom/apq8084-camera.dtsi @@ -26,6 +26,8 @@ reg-names = "csiphy", "csiphy_clk_mux"; interrupts = <0 78 0>; interrupt-names = "csiphy"; + qcom,csi-vdd-voltage = <1800000>; + qcom,mipi-csi-vdd-supply = <&pma8084_l12>; }; qcom,csiphy@fda0b000 { @@ -36,6 +38,8 @@ reg-names = "csiphy", "csiphy_clk_mux"; interrupts = <0 79 0>; interrupt-names = "csiphy"; + qcom,csi-vdd-voltage = <1800000>; + qcom,mipi-csi-vdd-supply = <&pma8084_l12>; }; qcom,csiphy@fda0b400 { @@ -46,6 +50,8 @@ reg-names = "csiphy", "csiphy_clk_mux"; interrupts = <0 80 0>; interrupt-names = "csiphy"; + qcom,csi-vdd-voltage = <1800000>; + qcom,mipi-csi-vdd-supply = <&pma8084_l12>; }; qcom,csid@fda08000 { diff --git a/arch/arm/configs/shamu_defconfig b/arch/arm/configs/shamu_defconfig index 1db38398c22e62ab74d35365b2123f92aaa74477..0e8da8c7e03cae877ec6d2e4ae63b837a34fa638 100644 --- a/arch/arm/configs/shamu_defconfig +++ b/arch/arm/configs/shamu_defconfig @@ -324,6 +324,7 @@ CONFIG_INPUT_GPIO=y # CONFIG_LEGACY_PTYS is not set # CONFIG_DEVMEM is not set # CONFIG_DEVKMEM is not set +# CONFIG_DEVPORT is not set CONFIG_SERIAL_MSM_HS=y CONFIG_SERIAL_MSM_HSL=y CONFIG_SERIAL_MSM_HSL_CONSOLE=y diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 4e9262a1b7c05b9e0c21a41d25c2b6632f66eecf..5643de97bee8422d16b9f576d1b1aee8972850f1 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -594,10 +594,12 @@ config TELCLOCK controlling the behavior of this hardware. config DEVPORT - bool - depends on !M68K + bool "/dev/port character device" depends on ISA || PCI default y + help + Say Y here if you want to support the /dev/port device. The /dev/port + device is similar to /dev/mem, but for I/O ports. source "drivers/s390/char/Kconfig" diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 640e6c1e103dfb0a7344b9d5314c07c9c02d6148..57e3ea36b3e4e60bf9647a5bcfa750f56415b25e 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-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 @@ -167,8 +167,11 @@ kgsl_mem_entry_create(void) { struct kgsl_mem_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (entry) + if (entry) { kref_init(&entry->refcount); + /* put this ref in the caller functions after init */ + kref_get(&entry->refcount); + } return entry; } @@ -3019,6 +3022,9 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, trace_kgsl_mem_map(entry, param->fd); kgsl_mem_entry_commit_process(private, entry); + + /* put the extra refcount for kgsl_mem_entry_create() */ + kgsl_mem_entry_put(entry); return result; error_attach: @@ -3343,6 +3349,9 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, param->flags = entry->memdesc.flags; kgsl_mem_entry_commit_process(private, entry); + + /* put the extra refcount for kgsl_mem_entry_create() */ + kgsl_mem_entry_put(entry); return result; err: kgsl_sharedmem_free(&entry->memdesc); @@ -3382,6 +3391,9 @@ long kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, param->gpuaddr = entry->memdesc.gpuaddr; kgsl_mem_entry_commit_process(private, entry); + + /* put the extra refcount for kgsl_mem_entry_create() */ + kgsl_mem_entry_put(entry); return result; err: if (entry) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 2f1ddca6f2e0a3a4712bce434d5b29e1556e216c..700145b1508894f30a018aef278d15cfc458ef3a 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -516,13 +516,13 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, goto inval; } else if (uref->usage_index >= field->report_count) goto inval; - - else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && - (uref_multi->num_values > HID_MAX_MULTI_USAGES || - uref->usage_index + uref_multi->num_values > field->report_count)) - goto inval; } + if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && + (uref_multi->num_values > HID_MAX_MULTI_USAGES || + uref->usage_index + uref_multi->num_values > field->report_count)) + goto inval; + switch (cmd) { case HIDIOCGUSAGE: uref->value = field->value[uref->usage_index]; 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 5599ca58b96b19cd796624fe6a6d25d0ad638fee..101e344b659913769e6da7d78670816d86687e10 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c @@ -57,7 +57,7 @@ static void msm_ispif_io_dump_reg(struct ispif_device *ispif) } static inline int msm_ispif_is_intf_valid(uint32_t csid_version, - uint8_t intf_type) + enum msm_ispif_vfe_intf intf_type) { return ((csid_version <= CSID_VERSION_V22 && intf_type != VFE0) || (intf_type >= VFE_MAX)) ? false : true; @@ -234,7 +234,7 @@ static int msm_ispif_subdev_g_chip_ident(struct v4l2_subdev *sd, } static void msm_ispif_sel_csid_core(struct ispif_device *ispif, - uint8_t intftype, uint8_t csid, uint8_t vfe_intf) + uint8_t intftype, uint8_t csid, enum msm_ispif_vfe_intf vfe_intf) { uint32_t data; @@ -274,8 +274,8 @@ static void msm_ispif_sel_csid_core(struct ispif_device *ispif, } static void msm_ispif_enable_crop(struct ispif_device *ispif, - uint8_t intftype, uint8_t vfe_intf, uint16_t start_pixel, - uint16_t end_pixel) + uint8_t intftype, enum msm_ispif_vfe_intf vfe_intf, + uint16_t start_pixel, uint16_t end_pixel) { uint32_t data; BUG_ON(!ispif); @@ -306,7 +306,8 @@ static void msm_ispif_enable_crop(struct ispif_device *ispif, } static void msm_ispif_enable_intf_cids(struct ispif_device *ispif, - uint8_t intftype, uint16_t cid_mask, uint8_t vfe_intf, uint8_t enable) + uint8_t intftype, uint16_t cid_mask, enum msm_ispif_vfe_intf vfe_intf, + uint8_t enable) { uint32_t intf_addr, data; @@ -348,7 +349,7 @@ static void msm_ispif_enable_intf_cids(struct ispif_device *ispif, } static int msm_ispif_validate_intf_status(struct ispif_device *ispif, - uint8_t intftype, uint8_t vfe_intf) + uint8_t intftype, enum msm_ispif_vfe_intf vfe_intf) { int rc = 0; uint32_t data = 0; @@ -388,7 +389,7 @@ static int msm_ispif_validate_intf_status(struct ispif_device *ispif, } static void msm_ispif_select_clk_mux(struct ispif_device *ispif, - uint8_t intftype, uint8_t csid, uint8_t vfe_intf) + uint8_t intftype, uint8_t csid, enum msm_ispif_vfe_intf vfe_intf) { uint32_t data = 0; 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 2cb0c9f36a2ea11e7c214753fffc14846b4a3ac5..635dfd91b3c4afb309a29fbfebe87100c34bce19 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 @@ -313,10 +313,18 @@ static int32_t msm_cci_i2c_read(struct v4l2_subdev *sd, enum cci_i2c_queue_t queue = QUEUE_1; struct cci_device *cci_dev = NULL; struct msm_camera_cci_i2c_read_cfg *read_cfg = NULL; + CDBG("%s line %d\n", __func__, __LINE__); cci_dev = v4l2_get_subdevdata(sd); master = c_ctrl->cci_info->cci_i2c_master; read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg; + + if (master >= MASTER_MAX || master < 0) { + pr_err("%s:%d Invalid I2C master %d\n", + __func__, __LINE__, master); + return -EINVAL; + } + mutex_lock(&cci_dev->cci_master_info[master].mutex); /* diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c index 8aac9b6e67bd481586645749bd9b0e7ec063fe93..5301b33d21f99d451e39d98b04d10b8153023d2b 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 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 @@ -28,6 +28,10 @@ #define CSIPHY_VERSION_V30 0x10 #define MSM_CSIPHY_DRV_NAME "msm_csiphy" +static struct camera_vreg_t csiphy_vreg_info[] = { + {"qcom,mipi-csi-vdd", 0, 0, 12000}, +}; + #undef CDBG #ifdef CONFIG_MSMB_CAMERA_DEBUG #define CDBG(fmt, args...) pr_err(fmt, ##args) @@ -205,6 +209,21 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) } CDBG("%s:%d called\n", __func__, __LINE__); + rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 1); + if (rc < 0) { + pr_err("%s: regulator config failed\n", __func__); + goto csiphy_vreg_config_fail; + } + rc = msm_camera_enable_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 1); + if (rc < 0) { + pr_err("%s: regulator enable failed\n", __func__); + goto csiphy_vreg_enable_fail; + } + if (CSIPHY_VERSION == CSIPHY_VERSION_V22) { rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_8610_clk_info, csiphy_dev->csiphy_clk, @@ -268,6 +287,16 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) csiphy_dev->hw_version); csiphy_dev->csiphy_state = CSIPHY_POWER_UP; return 0; + +csiphy_vreg_enable_fail: + rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 0); +csiphy_vreg_config_fail: + iounmap(csiphy_dev->base); + csiphy_dev->base = NULL; + return rc; + } #else static int msm_csiphy_init(struct csiphy_device *csiphy_dev) @@ -303,6 +332,22 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) rc = -ENOMEM; return rc; } + + rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 1); + if (rc < 0) { + pr_err("%s: regulator config failed\n", __func__); + goto csiphy_vreg_config_fail; + } + rc = msm_camera_enable_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 1); + if (rc < 0) { + pr_err("%s: regulator enable failed\n", __func__); + goto csiphy_vreg_enable_fail; + } + if (CSIPHY_VERSION == CSIPHY_VERSION_V22) { rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_8610_clk_info, csiphy_dev->csiphy_clk, @@ -364,6 +409,15 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) csiphy_dev->hw_version); csiphy_dev->csiphy_state = CSIPHY_POWER_UP; return 0; + +csiphy_vreg_enable_fail: + rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 0); +csiphy_vreg_config_fail: + iounmap(csiphy_dev->base); + csiphy_dev->base = NULL; + return rc; } #endif @@ -445,6 +499,19 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) ARRAY_SIZE(csiphy_clk_info), 0); iounmap(csiphy_dev->clk_mux_base); } + + msm_camera_enable_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 0); + msm_camera_config_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 0); + + if (!IS_ERR_OR_NULL(csiphy_dev->reg_ptr)) { + regulator_disable(csiphy_dev->reg_ptr); + regulator_put(csiphy_dev->reg_ptr); + } + iounmap(csiphy_dev->base); csiphy_dev->base = NULL; csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN; @@ -527,6 +594,18 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) iounmap(csiphy_dev->clk_mux_base); } + msm_camera_enable_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 0); + msm_camera_config_vreg(&csiphy_dev->pdev->dev, + csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), + NULL, 0, &csiphy_dev->csi_vdd, 0); + + if (!IS_ERR_OR_NULL(csiphy_dev->reg_ptr)) { + regulator_disable(csiphy_dev->reg_ptr); + regulator_put(csiphy_dev->reg_ptr); + } + iounmap(csiphy_dev->base); csiphy_dev->base = NULL; csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN; @@ -630,6 +709,7 @@ static const struct v4l2_subdev_ops msm_csiphy_subdev_ops = { static int csiphy_probe(struct platform_device *pdev) { struct csiphy_device *new_csiphy_dev; + uint32_t csi_vdd_voltage = 0; int rc = 0; new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL); @@ -649,6 +729,19 @@ static int csiphy_probe(struct platform_device *pdev) "cell-index", &pdev->id); CDBG("%s: device id = %d\n", __func__, pdev->id); + rc = of_property_read_u32((&pdev->dev)->of_node, + "qcom,csi-vdd-voltage", &csi_vdd_voltage); + if (rc < 0) { + pr_err("%s:%d failed to read qcom,csi-vdd-voltage\n", + __func__, __LINE__); + return rc; + } + CDBG("%s:%d reading mipi_csi_vdd is %d\n", __func__, __LINE__, + csi_vdd_voltage); + + csiphy_vreg_info[0].min_voltage = csi_vdd_voltage; + csiphy_vreg_info[0].max_voltage = csi_vdd_voltage; + new_csiphy_dev->mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csiphy"); if (!new_csiphy_dev->mem) { diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h index ff97ab73c82c121017a318701c9a29de7b918daf..3c843a2013c3e65b9c4022590c9fa8dd0079c5f5 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h @@ -47,6 +47,8 @@ struct csiphy_device { int32_t ref_count; uint16_t lane_mask[MAX_CSIPHY]; + struct regulator *csi_vdd; + struct regulator *reg_ptr; }; #define VIDIOC_MSM_CSIPHY_RELEASE \ diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index 48f8800d541db301ab8152cc3ce57f5c193eb691..3daf7a92858b928f5a541337a88df1c05d4cc245 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -46,6 +46,7 @@ #define MIN_SUPPORTED_HEIGHT 32 #define MAX_SUPPORTED_WIDTH 3820 #define MAX_SUPPORTED_HEIGHT 2160 +#define MAX_SUPPORTED_INSTANCES_COUNT 16 #define V4L2_EVENT_VIDC_BASE 10 diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index f7f817d1c6f62868da61254687d74d473896b3d8..6891b760a1351809d864141c6f8746d7e83be4fd 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -757,16 +757,15 @@ static int venus_hfi_vote_buses(void *dev, struct vidc_bus_vote_data *data, } else if (!data) { dprintk(VIDC_ERR, "Invalid voting data\n"); return -EINVAL; + } else if (num_data > MAX_SUPPORTED_INSTANCES_COUNT) { + dprintk(VIDC_ERR, "Invalid number of instances.\n"); + return -EINVAL; } - /* (Re-)alloc memory to store the new votes (in case we internally - * re-vote after power collapse, which is transparent to client) */ - cached_vote_data = krealloc(device->bus_load.vote_data, num_data * - sizeof(*cached_vote_data), GFP_KERNEL); + cached_vote_data = device->bus_load.vote_data; if (!cached_vote_data) { - dprintk(VIDC_ERR, "Can't alloc memory to cache bus votes\n"); - rc = -ENOMEM; - goto err_no_mem; + dprintk(VIDC_ERR, "Invalid bus load vote data\n"); + return -EINVAL; } /* Alloc & init the load table */ @@ -3090,9 +3089,16 @@ static int venus_hfi_init_bus(struct venus_hfi_device *device) dprintk(VIDC_DBG, "Registered bus client %s\n", name); }); - device->bus_load.vote_data = NULL; - device->bus_load.vote_data_count = 0; + device->bus_load.vote_data = (struct vidc_bus_vote_data *) + kzalloc(sizeof(struct vidc_bus_vote_data) * + MAX_SUPPORTED_INSTANCES_COUNT, GFP_KERNEL); + if (device->bus_load.vote_data == NULL) { + dprintk(VIDC_ERR, "Failed to allocate memory for vote_data\n"); + rc = -ENOMEM; + goto err_init_bus; + } + device->bus_load.vote_data_count = 0; return rc; err_init_bus: venus_hfi_deinit_bus(device); diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 5b02661236bebe16a489c4c58935de7409029019..b7b2ae7964f300769bb83b6e572f07ea8642655a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -2078,7 +2078,7 @@ dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx) if (dhd->arp_version == 1) idx = 0; - ret = dhd_iovar(dhd, 0, "arp_table_clear", NULL, 0, NULL, 0, TRUE); + ret = dhd_iovar(dhd, idx, "arp_table_clear", NULL, 0, NULL, 0, TRUE); if (ret) DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); } @@ -2092,7 +2092,7 @@ dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx) if (dhd->arp_version == 1) idx = 0; - ret = dhd_iovar(dhd, 0, "arp_hostip_clear", NULL, 0, NULL, 0, TRUE); + ret = dhd_iovar(dhd, idx, "arp_hostip_clear", NULL, 0, NULL, 0, TRUE); if (ret) DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); } @@ -2106,7 +2106,7 @@ dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx) if (dhd->arp_version == 1) idx = 0; - ret = dhd_iovar(dhd, 0, "arp_hostip", (char *)&ipaddr, sizeof(ipaddr), + ret = dhd_iovar(dhd, idx, "arp_hostip", (char *)&ipaddr, sizeof(ipaddr), NULL, 0, TRUE); if (ret) DHD_TRACE(("%s: ARP ip addr add failed, ret = %d\n", @@ -2129,7 +2129,7 @@ dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx) if (dhd->arp_version == 1) idx = 0; - ret = dhd_iovar(dhd, 0, "arp_hostip", NULL, 0, (char *)buf, buflen, + ret = dhd_iovar(dhd, idx, "arp_hostip", NULL, 0, (char *)buf, buflen, FALSE); if (ret) { DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n", @@ -2189,7 +2189,7 @@ dhd_ndo_add_ip(dhd_pub_t *dhd, char* ipv6addr, int idx) if (dhd == NULL) return -1; - ret = dhd_iovar(dhd, 0, "nd_hostip", (char *)ipv6addr, IPV6_ADDR_LEN, + ret = dhd_iovar(dhd, idx, "nd_hostip", (char *)ipv6addr, IPV6_ADDR_LEN, NULL, 0, TRUE); if (ret) @@ -2213,7 +2213,7 @@ dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx) if (dhd == NULL) return -1; - ret = dhd_iovar(dhd, 0, "nd_hostip_clear", NULL, 0, NULL, 0, TRUE); + ret = dhd_iovar(dhd, idx, "nd_hostip_clear", NULL, 0, NULL, 0, TRUE); if (ret) DHD_ERROR(("%s: ndo ip addr remove failed, ret = %d\n", __FUNCTION__, ret)); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 9081988345f70f5aecf7c4a807e54f8c6b4b8132..a73b0309af68fbf13c3ae05e75625e2fc1902fac 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -5830,6 +5830,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev, WL_DBG(("Enter \n")); + if (len > (ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN)) { + WL_ERR(("bad length:%zu\n", len)); + return BCME_BADARG; + } dev = cfgdev_to_wlc_ndev(cfgdev, cfg); /* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE) */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c index c1e04f8caeebcf110f9114dc7923745ee15f46cd..bf2cfb946ae0b8eb398b2b3c4c94d0efc196dc54 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c @@ -1118,11 +1118,15 @@ static int wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy, const struct nlattr *outer, *inner, *iter; uint8 flush = 0; wl_pfn_significant_bssid_t *pbssid; + uint16 num_bssid = 0; + uint16 max_buf_size = sizeof(gscan_swc_params_t) + + sizeof(wl_pfn_significant_bssid_t) * (PFN_SWC_MAX_NUM_APS - 1); + + significant_params = kzalloc(max_buf_size, GFP_KERNEL); - significant_params = (gscan_swc_params_t *) kzalloc(len, GFP_KERNEL); if (!significant_params) { - WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len)); - return -1; + WL_ERR(("Cannot Malloc mem size:%d\n", len)); + return BCME_NOMEM; } @@ -1142,9 +1146,27 @@ static int wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy, case GSCAN_ATTRIBUTE_MIN_BREACHING: significant_params->swc_threshold = nla_get_u16(iter); break; + case GSCAN_ATTRIBUTE_NUM_BSSID: + num_bssid = nla_get_u16(iter); + if (num_bssid > PFN_SWC_MAX_NUM_APS) { + WL_ERR(("ovar max SWC bssids:%d\n", + num_bssid)); + err = BCME_BADARG; + goto exit; + } + break; case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS: + if (num_bssid == 0) { + WL_ERR(("num_bssid : 0\n")); + err = BCME_BADARG; + goto exit; + } pbssid = significant_params->bssid_elem_list; nla_for_each_nested(outer, iter, tmp) { + if (j >= num_bssid) { + j++; + break; + } nla_for_each_nested(inner, outer, tmp1) { switch (nla_type(inner)) { case GSCAN_ATTRIBUTE_BSSID: @@ -1167,6 +1189,12 @@ static int wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy, break; } } + if (j != num_bssid) { + WL_ERR(("swc bssids count:%d not matched to num_bssid:%d\n", + j, num_bssid)); + err = BCME_BADARG; + goto exit; + } significant_params->nbssid = j; if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg), diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index df5e961484e108312f6f01765882dd4319d584f7..02809cceceb48efb207f4f16ac47e8f94d5868f3 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1694,6 +1694,9 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) md->from_user = 0; } + if (unlikely(iov_count > UIO_MAXIOV)) + return -EINVAL; + if (iov_count) { int len, size = sizeof(struct sg_iovec) * iov_count; struct iovec *iov; diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 7fbdf65db97dea63f645ea5814be93e959776ee5..79ec3da52e4e8b74ccfd1a93001464feeecdabbf 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -32,7 +32,6 @@ #include <linux/mutex.h> #include <linux/shmem_fs.h> #include <linux/ashmem.h> -#include <asm/cacheflush.h> #define ASHMEM_NAME_PREFIX "dev/ashmem/" #define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1) @@ -704,51 +703,6 @@ done: } #endif -static int ashmem_cache_op(struct ashmem_area *asma, - void (*cache_func)(unsigned long vstart, unsigned long length, - unsigned long pstart)) -{ - int ret = 0; - struct vm_area_struct *vma; -#ifdef CONFIG_OUTER_CACHE - unsigned long vaddr; -#endif - if (!asma->vm_start) - return -EINVAL; - - down_read(¤t->mm->mmap_sem); - vma = find_vma(current->mm, asma->vm_start); - if (!vma) { - ret = -EINVAL; - goto done; - } - if (vma->vm_file != asma->file) { - ret = -EINVAL; - goto done; - } - if ((asma->vm_start + asma->size) > vma->vm_end) { - ret = -EINVAL; - goto done; - } -#ifndef CONFIG_OUTER_CACHE - cache_func(asma->vm_start, asma->size, 0); -#else - for (vaddr = asma->vm_start; vaddr < asma->vm_start + asma->size; - vaddr += PAGE_SIZE) { - unsigned long physaddr; - physaddr = virtaddr_to_physaddr(vaddr); - if (!physaddr) - return -EINVAL; - cache_func(vaddr, PAGE_SIZE, physaddr); - } -#endif -done: - up_read(¤t->mm->mmap_sem); - if (ret) - asma->vm_start = 0; - return ret; -} - static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ashmem_area *asma = file->private_data; @@ -794,15 +748,6 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ashmem_shrink(&ashmem_shrinker, &sc); } break; - case ASHMEM_CACHE_FLUSH_RANGE: - ret = ashmem_cache_op(asma, &clean_and_invalidate_caches); - break; - case ASHMEM_CACHE_CLEAN_RANGE: - ret = ashmem_cache_op(asma, &clean_caches); - break; - case ASHMEM_CACHE_INV_RANGE: - ret = ashmem_cache_op(asma, &invalidate_caches); - break; } return ret; diff --git a/fs/udf/dir.c b/fs/udf/dir.c index b3e93f5e17c367fcfd818a4e7a0a455929baf847..294c10c849225333517810c3f163515fd16b12da 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -163,7 +163,10 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation); iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); - flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); + flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, + UDF_NAME_LEN); + if (!flen) + continue; dt_type = DT_UNKNOWN; } diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 102c072c6bbfed3d76541b2c3766d89c9272d2ca..7bb813f25ad4edcadd5149ae166226c4636289b3 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -233,7 +233,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, if (!lfi) continue; - flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); + flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, + UDF_NAME_LEN); if (flen && udf_match(flen, fname, child->len, child->name)) goto out_ok; } diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index d7c6dbe4194bb33bbe37930c63cf23377e5d9343..2d0c3720e9afd3b066c8d27752c817b219bf5b04 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c @@ -30,13 +30,16 @@ #include <linux/buffer_head.h> #include "udf_i.h" -static void udf_pc_to_char(struct super_block *sb, unsigned char *from, - int fromlen, unsigned char *to) +static int udf_pc_to_char(struct super_block *sb, unsigned char *from, + int fromlen, unsigned char *to, int tolen) { struct pathComponent *pc; int elen = 0; + int comp_len; unsigned char *p = to; + /* Reserve one byte for terminating \0 */ + tolen--; while (elen < fromlen) { pc = (struct pathComponent *)(from + elen); switch (pc->componentType) { @@ -49,22 +52,37 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from, break; /* Fall through */ case 2: + if (tolen == 0) + return -ENAMETOOLONG; p = to; *p++ = '/'; + tolen--; break; case 3: + if (tolen < 3) + return -ENAMETOOLONG; memcpy(p, "../", 3); p += 3; + tolen -= 3; break; case 4: + if (tolen < 2) + return -ENAMETOOLONG; memcpy(p, "./", 2); p += 2; + tolen -= 2; /* that would be . - just ignore */ break; case 5: - p += udf_get_filename(sb, pc->componentIdent, p, - pc->lengthComponentIdent); + comp_len = udf_get_filename(sb, pc->componentIdent, + pc->lengthComponentIdent, + p, tolen); + p += comp_len; + tolen -= comp_len; + if (tolen == 0) + return -ENAMETOOLONG; *p++ = '/'; + tolen--; break; } elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; @@ -73,6 +91,7 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from, p[-1] = '\0'; else p[0] = '\0'; + return 0; } static int udf_symlink_filler(struct file *file, struct page *page) @@ -80,11 +99,17 @@ static int udf_symlink_filler(struct file *file, struct page *page) struct inode *inode = page->mapping->host; struct buffer_head *bh = NULL; unsigned char *symlink; - int err = -EIO; + int err; unsigned char *p = kmap(page); struct udf_inode_info *iinfo; uint32_t pos; + /* We don't support symlinks longer than one block */ + if (inode->i_size > inode->i_sb->s_blocksize) { + err = -ENAMETOOLONG; + goto out_unmap; + } + iinfo = UDF_I(inode); pos = udf_block_map(inode, 0); @@ -94,14 +119,18 @@ static int udf_symlink_filler(struct file *file, struct page *page) } else { bh = sb_bread(inode->i_sb, pos); - if (!bh) - goto out; + if (!bh) { + err = -EIO; + goto out_unlock_inode; + } symlink = bh->b_data; } - udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p); + err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); brelse(bh); + if (err) + goto out_unlock_inode; up_read(&iinfo->i_data_sem); SetPageUptodate(page); @@ -109,9 +138,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) unlock_page(page); return 0; -out: +out_unlock_inode: up_read(&iinfo->i_data_sem); SetPageError(page); +out_unmap: kunmap(page); unlock_page(page); return err; diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index be7dabbbcb49ef171b33e0ec2bc4a672c073282d..55d1d194d4723df0ff4f8a9a984e953d2390717d 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -201,7 +201,8 @@ udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc, } /* unicode.c */ -extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); +extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *, + int); extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, int); extern int udf_build_ustr(struct ustr *, dstring *, int); diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 44b815e57f9439116199f91b67489a98272272bc..d29c06fbf4cec196ab271921fce17d7c730d2e3f 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -28,7 +28,8 @@ #include "udf_sb.h" -static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); +static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *, + int); static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) { @@ -333,8 +334,8 @@ try_again: return u_len + 1; } -int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, - int flen) +int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, + uint8_t *dname, int dlen) { struct ustr *filename, *unifilename; int len = 0; @@ -347,7 +348,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, if (!unifilename) goto out1; - if (udf_build_ustr_exact(unifilename, sname, flen)) + if (udf_build_ustr_exact(unifilename, sname, slen)) goto out2; if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { @@ -366,7 +367,8 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, } else goto out2; - len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, + len = udf_translate_to_linux(dname, dlen, + filename->u_name, filename->u_len, unifilename->u_name, unifilename->u_len); out2: kfree(unifilename); @@ -403,10 +405,12 @@ int udf_put_filename(struct super_block *sb, const uint8_t *sname, #define EXT_MARK '.' #define CRC_MARK '#' #define EXT_SIZE 5 +/* Number of chars we need to store generated CRC to make filename unique */ +#define CRC_LEN 5 -static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, - int udfLen, uint8_t *fidName, - int fidNameLen) +static int udf_translate_to_linux(uint8_t *newName, int newLen, + uint8_t *udfName, int udfLen, + uint8_t *fidName, int fidNameLen) { int index, newIndex = 0, needsCRC = 0; int extIndex = 0, newExtIndex = 0, hasExt = 0; @@ -440,7 +444,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, newExtIndex = newIndex; } } - if (newIndex < 256) + if (newIndex < newLen) newName[newIndex++] = curr; else needsCRC = 1; @@ -468,13 +472,13 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, } ext[localExtIndex++] = curr; } - maxFilenameLen = 250 - localExtIndex; + maxFilenameLen = newLen - CRC_LEN - localExtIndex; if (newIndex > maxFilenameLen) newIndex = maxFilenameLen; else newIndex = newExtIndex; - } else if (newIndex > 250) - newIndex = 250; + } else if (newIndex > newLen - CRC_LEN) + newIndex = newLen - CRC_LEN; newName[newIndex++] = CRC_MARK; valueCRC = crc_itu_t(0, fidName, fidNameLen); newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12]; diff --git a/include/uapi/linux/ashmem.h b/include/uapi/linux/ashmem.h index 7965b39a94f5ac8a727c3455b88f4e6029220294..0a8a9aa5600346787077405c213fba14c2da5811 100644 --- a/include/uapi/linux/ashmem.h +++ b/include/uapi/linux/ashmem.h @@ -34,9 +34,6 @@ struct ashmem_pin { #define ASHMEM_UNPIN _IOW(__ASHMEMIOC, 8, struct ashmem_pin) #define ASHMEM_GET_PIN_STATUS _IO(__ASHMEMIOC, 9) #define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10) -#define ASHMEM_CACHE_FLUSH_RANGE _IO(__ASHMEMIOC, 11) -#define ASHMEM_CACHE_CLEAN_RANGE _IO(__ASHMEMIOC, 12) -#define ASHMEM_CACHE_INV_RANGE _IO(__ASHMEMIOC, 13) /* support of 32bit userspace on 64bit platforms */ #ifdef CONFIG_COMPAT diff --git a/kernel/fork.c b/kernel/fork.c index 2b11e384fef83d70f8c5d5be3d63129b040f1272..b6eecda85690ec66950b55b21bb8cedecad76622 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -725,8 +725,7 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) mm = get_task_mm(task); if (mm && mm != current->mm && - !ptrace_may_access(task, mode) && - !capable(CAP_SYS_RESOURCE)) { + !ptrace_may_access(task, mode)) { mmput(mm); mm = ERR_PTR(-EACCES); } diff --git a/net/dccp/input.c b/net/dccp/input.c index 14cdafad7a90218d91ad135e3703c21401883e05..e511ccc74a0782fa26b8aa9a98de23931485c601 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (inet_csk(sk)->icsk_af_ops->conn_request(sk, skb) < 0) return 1; - goto discard; + consume_skb(skb); + return 0; } if (dh->dccph_type == DCCP_PKT_RESET) goto discard; diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 23e6ab0a2dc0ea070b6a86548b7761f7dbda00d4..b9dcaefe115b66f7ae71ac977fa7d732d28370c8 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -1046,7 +1046,14 @@ void ipv4_pktinfo_prepare(struct sk_buff *skb) pktinfo->ipi_ifindex = 0; pktinfo->ipi_spec_dst.s_addr = 0; } - skb_dst_drop(skb); + /* We need to keep the dst for __ip_options_echo() + * We could restrict the test to opt.ts_needtime || opt.srr, + * but the following is good enough as IP options are not often used. + */ + if (unlikely(IPCB(skb)->opt.optlen)) + skb_dst_force(skb); + else + skb_dst_drop(skb); } int ip_setsockopt(struct sock *sk, int level, diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index a867351bc1992e93a6fdd23739b705243dbe09d0..2e87251cacd2b3b5c31278a346e83fd1a4b6d12f 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -565,6 +565,7 @@ static void init_prb_bdqc(struct packet_sock *po, p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov); p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv; + p1->max_frame_len = p1->kblk_size - BLK_PLUS_PRIV(p1->blk_sizeof_priv); prb_init_ft_ops(p1, req_u); prb_setup_retire_blk_timer(po, tx_ring); prb_open_block(p1, pbd); @@ -1803,6 +1804,18 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, if ((int)snaplen < 0) snaplen = 0; } + } else if (unlikely(macoff + snaplen > + GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) { + u32 nval; + + nval = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len - macoff; + pr_err_once("tpacket_rcv: packet too big, clamped from %u to %u. macoff=%u\n", + snaplen, nval, macoff); + snaplen = nval; + if (unlikely((int)snaplen < 0)) { + snaplen = 0; + macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len; + } } spin_lock(&sk->sk_receive_queue.lock); h.raw = packet_current_rx_frame(po, skb, @@ -3649,6 +3662,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, goto out; if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) goto out; + if (po->tp_version >= TPACKET_V3 && + req->tp_block_size <= + BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv)) + goto out; if (unlikely(req->tp_frame_size < po->tp_hdrlen + po->tp_reserve)) goto out; diff --git a/net/packet/internal.h b/net/packet/internal.h index 1035fa2d909c7f18c100266c85ec07bce4a73a97..ca086c0c2c085cb3f3ff00834644d05d8769e7e3 100644 --- a/net/packet/internal.h +++ b/net/packet/internal.h @@ -29,6 +29,7 @@ struct tpacket_kbdq_core { char *pkblk_start; char *pkblk_end; int kblk_size; + unsigned int max_frame_len; unsigned int knum_blocks; uint64_t knxt_seq_num; char *prev; diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index 8e16a78a4e472559331671b513097020e50e3f70..142f755aa2919800a5096f2a016489c377a94c34 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -948,6 +948,7 @@ static int msm_compr_free(struct snd_compr_stream *cstream) kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]); kfree(pdata->dec_params[soc_prtd->dai_link->be_id]); kfree(prtd); + runtime->private_data = NULL; return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c index 605e7fdcbf62bb5f85efb1a8674863b3db2c9a0a..e31c144be0536948da845ec559b2ed975c95c340 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -493,6 +493,7 @@ done: mutex_unlock(&prtd->lock); prtd->prepared--; kfree(prtd); + runtime->private_data = NULL; return 0; } static int msm_afe_prepare(struct snd_pcm_substream *substream) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c index b6866d0e8065a2dff53e72456f73fdf416175de7..4e9f677804d1d3d825c6104e70a64ed74056624a 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -490,6 +490,7 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) pr_debug("%s\n", __func__); kfree(prtd); + runtime->private_data = NULL; return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index 74ea2034f0705201ab6dfe042e43a710e8b8fe6d..232c540092a3588e48c791711320c72f0f74af66 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -618,6 +618,8 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, SNDRV_PCM_STREAM_PLAYBACK); kfree(prtd); + runtime->private_data = NULL; + return 0; } @@ -713,6 +715,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream) msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, SNDRV_PCM_STREAM_CAPTURE); kfree(prtd); + runtime->private_data = NULL; return 0; } diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 7d26648716d3681737c5825121758bfed8715bc2..02065cb7e36879cff2861ca33cea138d948a75f5 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -354,6 +354,16 @@ static int q6asm_session_alloc(struct audio_client *ac) return -ENOMEM; } +static bool q6asm_is_valid_audio_client(struct audio_client *ac) +{ + int n; + for (n = 1; n <= SESSION_MAX; n++) { + if (session[n] == ac) + return 1; + } + return 0; +} + static void q6asm_session_free(struct audio_client *ac) { pr_debug("%s: sessionid[%d]\n", __func__, ac->session); @@ -1256,6 +1266,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) pr_err("ac or priv NULL\n"); return -EINVAL; } + if (!q6asm_is_valid_audio_client(ac)) { + pr_err("%s: audio client pointer is invalid, ac = %p\n", + __func__, ac); + return -EINVAL; + } + if (ac->session <= 0 || ac->session > 8) { pr_err("%s:Session ID is invalid, session = %d\n", __func__, ac->session);