Merge "arm/dt: msm9625: Fix compilation errors"
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index d7290e0..10732cf 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -24,14 +24,14 @@
Optional properties for WLED:
- qcom,num-strings: number of wled strings supported
-- qcom,ovp_val: over voltage protection threshold,
+- qcom,ovp-val: over voltage protection threshold,
follows enum wled_ovp_threshold
-- qcom,boost_curr_lim: boot currnet limit, follows enum wled_current_bost_limit
-- qcom,ctrl_delay_us: delay in activation of led
-- qcom,dig_mod_gen_en: digital module generator
-- qcom,cs_out_en: current sink output enable
-- qcom,op_fdbck: selection of output as feedback for the boost
-- qcom,cp_select: high pole capacitance
+- qcom,boost-curr-lim: boot currnet limit, follows enum wled_current_bost_limit
+- qcom,ctrl-delay-us: delay in activation of led
+- qcom,dig-mod-gen-en: digital module generator
+- qcom,cs-out-en: current sink output enable
+- qcom,op-fdbck: selection of output as feedback for the boost
+- qcom,cp-select: high pole capacitance
- linux,default-trigger: trigger the led from external modules such as display
- qcom,default-state: default state of the led, should be "on" or "off"
diff --git a/Documentation/devicetree/bindings/prng/msm-rng.txt b/Documentation/devicetree/bindings/prng/msm-rng.txt
index 3d55808..28dfe50 100644
--- a/Documentation/devicetree/bindings/prng/msm-rng.txt
+++ b/Documentation/devicetree/bindings/prng/msm-rng.txt
@@ -4,9 +4,13 @@
- compatible : Should be "qcom,msm-rng"
- reg : Offset and length of the register set for the device
+Optional property:
+- qcom,msm-rng-iface-clk : If the device uses iface-clk.
+
Example:
- qcom,msm-rng@f9bff000 {
- compatible = "qcom,msm-rng";
- reg = <0xf9bff000 0x200>;
- };
+ qcom,msm-rng@f9bff000 {
+ compatible = "qcom,msm-rng";
+ reg = <0xf9bff000 0x200>;
+ qcom,msm-rng-iface-clk;
+ };
diff --git a/arch/arm/boot/dts/msm8910.dtsi b/arch/arm/boot/dts/msm8910.dtsi
index 1f3c1d8..2a2e764 100644
--- a/arch/arm/boot/dts/msm8910.dtsi
+++ b/arch/arm/boot/dts/msm8910.dtsi
@@ -73,13 +73,25 @@
interrupts = <0 123 0>;
interrupt-names = "core_irq";
+ vdd-supply = <&pm8110_l17>;
+ qcom,vdd-always-on;
+ qcom,vdd-lpm-sup;
+ qcom,vdd-voltage-level = <2900000 2900000>;
+ qcom,vdd-current-level = <9000 400000>;
+
+ vdd-io-supply = <&pm8110_l6>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <9000 60000>;
+
qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
- qcom,sup-voltages = <2950 2950>;
+ qcom,sup-voltages = <2900 2900>;
qcom,bus-width = <8>;
qcom,nonremovable;
qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
@@ -93,6 +105,14 @@
interrupts = <0 125 0>;
interrupt-names = "core_irq";
+ vdd-supply = <&pm8110_l18>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <9000 400000>;
+
+ vdd-io-supply = <&pm8110_l21>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <9000 50000>;
+
qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 68207af..1134dde 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -176,6 +176,7 @@
compatible = "regulator-fixed";
regulator-name = "ext_5v";
gpio = <&pm8941_mpps 2 0>;
+ startup-delay-us = <12000>;
enable-active-high;
};
};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 8e67e2f..a4bec1b 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -98,25 +98,26 @@
interrupt-names = "bam_irq";
};
- spi@f9928000 {
+ spi@f9924000 {
+ cell-index = <0>;
compatible = "qcom,spi-qup-v2";
- reg = <0xf9928000 0x1000>;
- interrupts = <0 100 0>;
- spi-max-frequency = <24000000>;
+ reg = <0xf9924000 0x1000>;
+ interrupts = <0 96 0>;
+ spi-max-frequency = <25000000>;
#address-cells = <1>;
#size-cells = <0>;
- gpios = <&msmgpio 23 0>, /* CLK */
- <&msmgpio 21 0>, /* MISO */
- <&msmgpio 20 0>; /* MOSI */
+ gpios = <&msmgpio 7 0>, /* CLK */
+ <&msmgpio 5 0>, /* MISO */
+ <&msmgpio 4 0>; /* MOSI */
- cs-gpios = <&msmgpio 69 0>;
+ cs-gpios = <&msmgpio 6 0>;
ethernet-switch@0 {
compatible = "simtec,ks8851";
reg = <0>;
interrupt-parent = <&msmgpio>;
interrupts = <75 0>;
- spi-max-frequency = <5000000>;
+ spi-max-frequency = <4800000>;
};
};
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 4b84923..b9add04 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -121,6 +121,7 @@
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
@@ -203,3 +204,50 @@
CONFIG_LIBCRC32C=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_MSM_QDSS=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_IP_SET=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 314bfd0..371288e 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -693,12 +693,6 @@
static struct msm_bus_vectors hsic_init_vectors[] = {
{
.src = MSM_BUS_MASTER_SPS,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
- {
- .src = MSM_BUS_MASTER_SPS,
.dst = MSM_BUS_SLAVE_SPS,
.ab = 0,
.ib = 0,
@@ -709,15 +703,9 @@
static struct msm_bus_vectors hsic_max_vectors[] = {
{
.src = MSM_BUS_MASTER_SPS,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 60000000, /* At least 480Mbps on bus. */
- .ib = 960000000, /* MAX bursts rate */
- },
- {
- .src = MSM_BUS_MASTER_SPS,
.dst = MSM_BUS_SLAVE_SPS,
.ab = 0,
- .ib = 512000000, /*vote for 64Mhz dfab clk rate*/
+ .ib = 256000000, /*vote for 32Mhz dfab clk rate*/
},
};
@@ -3406,6 +3394,7 @@
static void __init apq8064_common_init(void)
{
u32 platform_version = socinfo_get_platform_version();
+ struct msm_rpmrs_level rpmrs_level;
if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
apq8064_pm8917_pdata_fixup();
@@ -3482,8 +3471,12 @@
}
enable_ddr3_regulator();
- msm_hsic_pdata.swfi_latency =
- msm_rpmrs_levels[0].latency_us;
+ rpmrs_level =
+ msm_rpmrs_levels[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT];
+ msm_hsic_pdata.swfi_latency = rpmrs_level.latency_us;
+ rpmrs_level =
+ msm_rpmrs_levels[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE];
+ msm_hsic_pdata.standalone_latency = rpmrs_level.latency_us;
if (machine_is_apq8064_mtp()) {
msm_hsic_pdata.log2_irq_thresh = 5,
apq8064_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
diff --git a/arch/arm/mach-msm/board-9625-gpiomux.c b/arch/arm/mach-msm/board-9625-gpiomux.c
index 6f36ef2..8f07ff0 100644
--- a/arch/arm/mach-msm/board-9625-gpiomux.c
+++ b/arch/arm/mach-msm/board-9625-gpiomux.c
@@ -25,13 +25,13 @@
};
static struct gpiomux_setting gpio_spi_cs_config = {
- .func = GPIOMUX_FUNC_9,
+ .func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_12MA,
.pull = GPIOMUX_PULL_NONE,
};
static struct gpiomux_setting gpio_spi_config = {
- .func = GPIOMUX_FUNC_2,
+ .func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_12MA,
.pull = GPIOMUX_PULL_NONE,
};
@@ -44,6 +44,30 @@
static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
{
+ .gpio = 4, /* BLSP1 QUP2 SPI_DATA_MOSI */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 5, /* BLSP1 QUP2 SPI_DATA_MISO */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 6, /* BLSP1 QUP2 SPI_CS_N */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+ },
+ },
+ {
+ .gpio = 7, /* BLSP1 QUP2 SPI_CLK */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
.gpio = 8, /* BLSP1 UART TX */
.settings = {
[GPIOMUX_SUSPENDED] = &gpio_uart_config,
@@ -67,31 +91,6 @@
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
- {
- .gpio = 69, /* BLSP6 QUP SPI_CS_N */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
- },
- },
- {
- .gpio = 20, /* BLSP6 QUP SPI_DATA_MOSI */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_config,
- },
- },
- {
- .gpio = 21, /* BLSP6 QUP SPI_DATA_MISO */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_config,
- },
- },
- {
- .gpio = 23, /* BLSP6 QUP SPI_CLK */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_config,
- },
- },
-
};
static struct gpiomux_setting sdc3_clk_active_cfg = {
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 3e5fc9d..8e8d3e7 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -101,8 +101,6 @@
static struct of_dev_auxdata msm9625_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
"msm_serial_hsl.0", NULL),
- OF_DEV_AUXDATA("qcom,spi-qup-v2", 0xF9928000, \
- "spi_qsd.1", NULL),
OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
"spmi-pmic-arb.0", NULL),
OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 0b8919b..0f6eb82 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -2027,13 +2027,13 @@
CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "msm_sps"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "msm_serial_hsl.0"),
- CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "spi_qsd.1"),
+ CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9924000.spi"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9925000.i2c"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp1_qup1_i2c_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, "spi_qsd.1"),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp1_qup2_i2c_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, "f9924000.spi"),
CLK_LOOKUP("core_clk", gcc_blsp1_qup3_i2c_apps_clk.c, "f9925000.i2c"),
CLK_LOOKUP("core_clk", gcc_blsp1_qup3_spi_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp1_qup4_i2c_apps_clk.c, ""),
@@ -2058,6 +2058,7 @@
CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_prng_ahb_clk.c, "f9bff000.qcom,msm-rng"),
CLK_LOOKUP("core_src_clk", ipa_clk_src.c, "fd4c0000.qcom,ipa"),
CLK_LOOKUP("core_clk", gcc_ipa_clk.c, "fd4c0000.qcom,ipa"),
CLK_LOOKUP("bus_clk", gcc_sys_noc_ipa_axi_clk.c, "fd4c0000.qcom,ipa"),
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 091a8e8..983b13e 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -360,25 +360,25 @@
static struct msm_iommu_dev gfx3d_iommu = {
.name = "gfx3d",
.ncb = 3,
- .ttbr_split = 1,
+ .ttbr_split = 0,
};
static struct msm_iommu_dev gfx3d1_iommu = {
.name = "gfx3d1",
.ncb = 3,
- .ttbr_split = 1,
+ .ttbr_split = 0,
};
static struct msm_iommu_dev gfx2d0_iommu = {
.name = "gfx2d0",
.ncb = 2,
- .ttbr_split = 1,
+ .ttbr_split = 0,
};
static struct msm_iommu_dev gfx2d1_iommu = {
.name = "gfx2d1",
.ncb = 2,
- .ttbr_split = 1,
+ .ttbr_split = 0,
};
static struct msm_iommu_dev vcap_iommu = {
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index fe61d2d..19c6ed2 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -380,6 +380,22 @@
(*count_entries)++;
}
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+uint16_t diag_get_remote_device_mask(void)
+{
+ uint16_t remote_dev = 0;
+
+ if (driver->hsic_inited)
+ remote_dev |= (1 << 0);
+ if (driver->diag_smux_enabled)
+ remote_dev |= (1 << 1);
+
+ return remote_dev;
+}
+#else
+inline uint16_t diag_get_remote_device_mask(void) { return 0; }
+#endif
+
long diagchar_ioctl(struct file *filp,
unsigned int iocmd, unsigned long ioarg)
{
@@ -583,6 +599,10 @@
}
}
}
+ if (driver->logging_mode == SOCKET_MODE)
+ driver->socket_process = current;
+ if (driver->logging_mode == CALLBACK_MODE)
+ driver->callback_process = current;
if (driver->logging_mode == UART_MODE ||
driver->logging_mode == SOCKET_MODE ||
driver->logging_mode == CALLBACK_MODE) {
@@ -590,10 +610,6 @@
driver->mask_check = 0;
driver->logging_mode = MEMORY_DEVICE_MODE;
}
- if (driver->logging_mode == SOCKET_MODE)
- driver->socket_process = current;
- if (driver->logging_mode == CALLBACK_MODE)
- driver->callback_process = current;
driver->logging_process_id = current->tgid;
mutex_unlock(&driver->diagchar_mutex);
if (temp == MEMORY_DEVICE_MODE && driver->logging_mode
@@ -695,6 +711,13 @@
}
#endif /* DIAG over USB */
success = 1;
+ } else if (iocmd == DIAG_IOCTL_REMOTE_DEV) {
+ uint16_t remote_dev = diag_get_remote_device_mask();
+
+ if (copy_to_user((void *)ioarg, &remote_dev, sizeof(uint16_t)))
+ success = -EFAULT;
+ else
+ success = 1;
}
return success;
@@ -1206,8 +1229,9 @@
if (err) {
/*Free the buffer right away if write failed */
diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
+ if (driver->logging_mode == USB_MODE)
+ diagmem_free(driver, (unsigned char *)driver->
+ write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
ret = -EIO;
goto fail_free_hdlc;
}
@@ -1234,8 +1258,9 @@
if (err) {
/*Free the buffer right away if write failed */
diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
+ if (driver->logging_mode == USB_MODE)
+ diagmem_free(driver, (unsigned char *)driver->
+ write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
ret = -EIO;
goto fail_free_hdlc;
}
@@ -1259,8 +1284,9 @@
if (err) {
/*Free the buffer right away if write failed */
diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
+ if (driver->logging_mode == USB_MODE)
+ diagmem_free(driver, (unsigned char *)driver->
+ write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
ret = -EIO;
goto fail_free_hdlc;
}
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index 56f2fae..7aef01f 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -195,7 +195,7 @@
if (actual_size < 0)
pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
- if (driver->usb_mdm_connected)
+ if (driver->usb_mdm_connected && (driver->logging_mode == USB_MODE))
queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);
}
@@ -462,7 +462,7 @@
* If there is no write of the usb mdm data on the
* hsic channel
*/
- if (!driver->in_busy_hsic_write)
+ if (!driver->in_busy_hsic_write && (driver->logging_mode == USB_MODE))
queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);
return 0;
@@ -552,9 +552,9 @@
* If for some reason there was no mdm channel read initiated,
* queue up the reading of data from the mdm channel
*/
- if (!driver->in_busy_hsic_read_on_device)
- queue_work(driver->diag_bridge_wq,
- &driver->diag_read_mdm_work);
+ if (!driver->in_busy_hsic_read_on_device &&
+ (driver->logging_mode == USB_MODE))
+ queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);
}
static int diag_hsic_probe(struct platform_device *pdev)
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index 60ca44f..f2e5439 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -181,7 +181,12 @@
msm_rng_dev->base = base;
/* create a handle for clock control */
- msm_rng_dev->prng_clk = clk_get(&pdev->dev, "core_clk");
+ if ((pdev->dev.of_node) && (of_property_read_bool(pdev->dev.of_node,
+ "qcom,msm-rng-iface-clk")))
+ msm_rng_dev->prng_clk = clk_get(&pdev->dev,
+ "iface_clk");
+ else
+ msm_rng_dev->prng_clk = clk_get(&pdev->dev, "core_clk");
if (IS_ERR(msm_rng_dev->prng_clk)) {
dev_err(&pdev->dev, "failed to register clock source\n");
error = -EPERM;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 67cb34a..0109d26 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -253,6 +253,13 @@
if (result)
goto unmap_memstore_desc;
+ /*
+ * Set the mpu end to the last "normal" global memory we use.
+ * For the IOMMU, this will be used to restrict access to the
+ * mapped registers.
+ */
+ device->mh.mpu_range = device->mmu.setstate_memory.gpuaddr +
+ device->mmu.setstate_memory.size;
return result;
unmap_memstore_desc:
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index b8adbe67..ca2ad19 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -853,13 +853,6 @@
dev_priv->device = device;
filep->private_data = dev_priv;
- /* Get file (per process) private struct */
- dev_priv->process_priv = kgsl_get_process_private(dev_priv);
- if (dev_priv->process_priv == NULL) {
- result = -ENOMEM;
- goto err_freedevpriv;
- }
-
mutex_lock(&device->mutex);
kgsl_check_suspended(device);
@@ -871,21 +864,38 @@
if (result) {
mutex_unlock(&device->mutex);
- goto err_putprocess;
+ goto err_freedevpriv;
}
kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
}
device->open_count++;
mutex_unlock(&device->mutex);
+ /*
+ * Get file (per process) private struct. This must be done
+ * after the first start so that the global pagetable mappings
+ * are set up before we create the per-process pagetable.
+ */
+ dev_priv->process_priv = kgsl_get_process_private(dev_priv);
+ if (dev_priv->process_priv == NULL) {
+ result = -ENOMEM;
+ goto err_stop;
+ }
+
KGSL_DRV_INFO(device, "Initialized %s: mmu=%s pagetable_count=%d\n",
device->name, kgsl_mmu_enabled() ? "on" : "off",
kgsl_pagetable_count);
return result;
-err_putprocess:
- kgsl_put_process_private(device, dev_priv->process_priv);
+err_stop:
+ mutex_lock(&device->mutex);
+ device->open_count--;
+ if (device->open_count == 0) {
+ result = device->ftbl->stop(device);
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
+ }
+ mutex_unlock(&device->mutex);
err_freedevpriv:
filep->private_data = NULL;
kfree(dev_priv);
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 52097dc..f731cfc 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -190,7 +190,7 @@
entry = rb_entry(node, struct kgsl_mem_entry, node);
m = &entry->memdesc;
- flags[0] = m->priv & KGSL_MEMDESC_GLOBAL ? 'g' : '-';
+ flags[0] = kgsl_memdesc_is_global(m) ? 'g' : '-';
flags[1] = m->flags & KGSL_MEMFLAGS_GPUREADONLY ? 'r' : '-';
flags[2] = get_alignflag(m);
flags[3] = '\0';
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 07ea48e..1bccd4d 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -702,6 +702,70 @@
}
}
+/*
+ * kgsl_iommu_setup_regs - map iommu registers into a pagetable
+ * @mmu: Pointer to mmu structure
+ * @pt: the pagetable
+ *
+ * To do pagetable switches from the GPU command stream, the IOMMU
+ * registers need to be mapped into the GPU's pagetable. This function
+ * is used differently on different targets. On 8960, the registers
+ * are mapped into every pagetable during kgsl_setup_pt(). On
+ * all other targets, the registers are mapped only into the second
+ * context bank.
+ *
+ * Return - 0 on success else error code
+ */
+static int kgsl_iommu_setup_regs(struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt)
+{
+ int status;
+ int i = 0;
+ struct kgsl_iommu *iommu = mmu->priv;
+
+ if (!msm_soc_version_supports_iommu_v1())
+ return 0;
+
+ for (i = 0; i < iommu->unit_count; i++) {
+ iommu->iommu_units[i].reg_map.priv |= KGSL_MEMDESC_GLOBAL;
+ status = kgsl_mmu_map(pt,
+ &(iommu->iommu_units[i].reg_map),
+ GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ if (status) {
+ iommu->iommu_units[i].reg_map.priv &=
+ ~KGSL_MEMDESC_GLOBAL;
+ goto err;
+ }
+ }
+ return 0;
+err:
+ for (i--; i >= 0; i--) {
+ kgsl_mmu_unmap(pt,
+ &(iommu->iommu_units[i].reg_map));
+ iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMDESC_GLOBAL;
+ }
+ return status;
+}
+
+/*
+ * kgsl_iommu_cleanup_regs - unmap iommu registers from a pagetable
+ * @mmu: Pointer to mmu structure
+ * @pt: the pagetable
+ *
+ * Removes mappings created by kgsl_iommu_setup_regs().
+ *
+ * Return - 0 on success else error code
+ */
+static void kgsl_iommu_cleanup_regs(struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt)
+{
+ struct kgsl_iommu *iommu = mmu->priv;
+ int i;
+ for (i = 0; i < iommu->unit_count; i++)
+ kgsl_mmu_unmap(pt, &(iommu->iommu_units[i].reg_map));
+}
+
+
static int kgsl_iommu_init(struct kgsl_mmu *mmu)
{
/*
@@ -744,6 +808,15 @@
KGSL_IOMMU_SETSTATE_NOP_OFFSET,
cp_nop_packet(1));
+ if (cpu_is_msm8960()) {
+ /*
+ * 8960 doesn't have a second context bank, so the IOMMU
+ * registers must be mapped into every pagetable.
+ */
+ iommu_ops.mmu_setup_pt = kgsl_iommu_setup_regs;
+ iommu_ops.mmu_cleanup_pt = kgsl_iommu_cleanup_regs;
+ }
+
dev_info(mmu->device->dev, "|%s| MMU type set for device is IOMMU\n",
__func__);
done:
@@ -766,9 +839,6 @@
static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu)
{
int status = 0;
- int i = 0;
- struct kgsl_iommu *iommu = mmu->priv;
- struct kgsl_pagetable *pagetable = NULL;
/* If chip is not 8960 then we use the 2nd context bank for pagetable
* switching on the 3D side for which a separate table is allocated */
@@ -779,6 +849,9 @@
status = -ENOMEM;
goto err;
}
+ status = kgsl_iommu_setup_regs(mmu, mmu->priv_bank_table);
+ if (status)
+ goto err;
}
mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
/* Return error if the default pagetable doesn't exist */
@@ -786,31 +859,10 @@
status = -ENOMEM;
goto err;
}
- pagetable = mmu->priv_bank_table ? mmu->priv_bank_table :
- mmu->defaultpagetable;
- /* Map the IOMMU regsiters to only defaultpagetable */
- if (msm_soc_version_supports_iommu_v1()) {
- for (i = 0; i < iommu->unit_count; i++) {
- iommu->iommu_units[i].reg_map.priv |=
- KGSL_MEMDESC_GLOBAL;
- status = kgsl_mmu_map(pagetable,
- &(iommu->iommu_units[i].reg_map),
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
- if (status) {
- iommu->iommu_units[i].reg_map.priv &=
- ~KGSL_MEMDESC_GLOBAL;
- goto err;
- }
- }
- }
return status;
err:
- for (i--; i >= 0; i--) {
- kgsl_mmu_unmap(pagetable,
- &(iommu->iommu_units[i].reg_map));
- iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMDESC_GLOBAL;
- }
if (mmu->priv_bank_table) {
+ kgsl_iommu_cleanup_regs(mmu, mmu->priv_bank_table);
kgsl_mmu_putpagetable(mmu->priv_bank_table);
mmu->priv_bank_table = NULL;
}
@@ -839,10 +891,12 @@
* a225, hence we still keep the MMU active on 8960 */
if (cpu_is_msm8960()) {
struct kgsl_mh *mh = &(mmu->device->mh);
+ BUG_ON(iommu->iommu_units[0].reg_map.gpuaddr != 0 &&
+ mh->mpu_base > iommu->iommu_units[0].reg_map.gpuaddr);
kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000001);
+
kgsl_regwrite(mmu->device, MH_MMU_MPU_END,
- mh->mpu_base +
- iommu->iommu_units[0].reg_map.gpuaddr);
+ mh->mpu_base + mh->mpu_range);
} else {
kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
}
@@ -915,14 +969,12 @@
"with err: %d\n", iommu_pt->domain, gpuaddr,
range, ret);
-#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
/*
* Flushing only required if per process pagetables are used. With
* global case, flushing will happen inside iommu_map function
*/
- if (!ret && msm_soc_version_supports_iommu_v1())
+ if (!ret && kgsl_mmu_is_perprocess())
*tlb_flags = UINT_MAX;
-#endif
return 0;
}
@@ -1003,22 +1055,23 @@
{
struct kgsl_iommu *iommu = mmu->priv;
int i;
- for (i = 0; i < iommu->unit_count; i++) {
- struct kgsl_pagetable *pagetable = (mmu->priv_bank_table ?
- mmu->priv_bank_table : mmu->defaultpagetable);
- if (iommu->iommu_units[i].reg_map.gpuaddr)
- kgsl_mmu_unmap(pagetable,
- &(iommu->iommu_units[i].reg_map));
- if (iommu->iommu_units[i].reg_map.hostptr)
- iounmap(iommu->iommu_units[i].reg_map.hostptr);
- kgsl_sg_free(iommu->iommu_units[i].reg_map.sg,
- iommu->iommu_units[i].reg_map.sglen);
+
+ if (mmu->priv_bank_table != NULL) {
+ kgsl_iommu_cleanup_regs(mmu, mmu->priv_bank_table);
+ kgsl_mmu_putpagetable(mmu->priv_bank_table);
}
- if (mmu->priv_bank_table)
- kgsl_mmu_putpagetable(mmu->priv_bank_table);
- if (mmu->defaultpagetable)
+ if (mmu->defaultpagetable != NULL)
kgsl_mmu_putpagetable(mmu->defaultpagetable);
+
+ for (i = 0; i < iommu->unit_count; i++) {
+ struct kgsl_memdesc *reg_map = &iommu->iommu_units[i].reg_map;
+
+ if (reg_map->hostptr)
+ iounmap(reg_map->hostptr);
+ kgsl_sg_free(reg_map->sg, reg_map->sglen);
+ }
+
kfree(iommu);
return 0;
@@ -1149,6 +1202,9 @@
.mmu_get_num_iommu_units = kgsl_iommu_get_num_iommu_units,
.mmu_pt_equal = kgsl_iommu_pt_equal,
.mmu_get_pt_base_addr = kgsl_iommu_get_pt_base_addr,
+ /* These callbacks will be set on some chipsets */
+ .mmu_setup_pt = NULL,
+ .mmu_cleanup_pt = NULL,
};
struct kgsl_mmu_pt_ops iommu_pt_ops = {
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 68cd167..6fe119d 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -36,17 +36,18 @@
static int kgsl_cleanup_pt(struct kgsl_pagetable *pt)
{
int i;
- /* For IOMMU only unmap the global structures to global pt */
- if ((KGSL_MMU_TYPE_NONE != kgsl_mmu_type) &&
- (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
- (KGSL_MMU_GLOBAL_PT != pt->name) &&
- (KGSL_MMU_PRIV_BANK_TABLE_NAME != pt->name))
- return 0;
+ struct kgsl_device *device;
+
for (i = 0; i < KGSL_DEVICE_MAX; i++) {
- struct kgsl_device *device = kgsl_driver.devp[i];
+ device = kgsl_driver.devp[i];
if (device)
device->ftbl->cleanup_pt(device, pt);
}
+ /* Only the 3d device needs mmu specific pt entries */
+ device = kgsl_driver.devp[KGSL_DEVICE_3D0];
+ if (device->mmu.mmu_ops->mmu_cleanup_pt != NULL)
+ device->mmu.mmu_ops->mmu_cleanup_pt(&device->mmu, pt);
+
return 0;
}
@@ -55,21 +56,23 @@
{
int i = 0;
int status = 0;
+ struct kgsl_device *device;
- /* For IOMMU only map the global structures to global pt */
- if ((KGSL_MMU_TYPE_NONE != kgsl_mmu_type) &&
- (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
- (KGSL_MMU_GLOBAL_PT != pt->name) &&
- (KGSL_MMU_PRIV_BANK_TABLE_NAME != pt->name))
- return 0;
for (i = 0; i < KGSL_DEVICE_MAX; i++) {
- struct kgsl_device *device = kgsl_driver.devp[i];
+ device = kgsl_driver.devp[i];
if (device) {
status = device->ftbl->setup_pt(device, pt);
if (status)
goto error_pt;
}
}
+ /* Only the 3d device needs mmu specific pt entries */
+ device = kgsl_driver.devp[KGSL_DEVICE_3D0];
+ if (device->mmu.mmu_ops->mmu_setup_pt != NULL) {
+ status = device->mmu.mmu_ops->mmu_setup_pt(&device->mmu, pt);
+ if (status)
+ goto error_pt;
+ }
return status;
error_pt:
while (i >= 0) {
@@ -309,22 +312,6 @@
return ret;
}
-unsigned int kgsl_mmu_get_ptsize(void)
-{
- /*
- * For IOMMU, we could do up to 4G virtual range if we wanted to, but
- * it makes more sense to return a smaller range and leave the rest of
- * the virtual range for future improvements
- */
-
- if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
- return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
- else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type)
- return SZ_2G - KGSL_PAGETABLE_BASE;
- else
- return 0;
-}
-
int
kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, unsigned int pt_base)
{
@@ -480,7 +467,7 @@
goto err_kgsl_pool;
}
- if (gen_pool_add(pagetable->pool, KGSL_PAGETABLE_BASE,
+ if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(),
ptsize, -1)) {
KGSL_CORE_ERR("gen_pool_add failed\n");
goto err_pool;
@@ -528,11 +515,7 @@
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return (void *)(-1);
-#ifndef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
- name = KGSL_MMU_GLOBAL_PT;
-#endif
- /* We presently do not support per-process for IOMMU-v2 */
- if (!msm_soc_version_supports_iommu_v1())
+ if (!kgsl_mmu_is_perprocess())
name = KGSL_MMU_GLOBAL_PT;
pt = kgsl_get_pagetable(name);
@@ -589,15 +572,6 @@
*/
}
-static inline struct gen_pool *
-_get_pool(struct kgsl_pagetable *pagetable, unsigned int flags)
-{
- if (pagetable->kgsl_pool &&
- (KGSL_MEMDESC_GLOBAL & flags))
- return pagetable->kgsl_pool;
- return pagetable->pool;
-}
-
int
kgsl_mmu_map(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc,
@@ -628,28 +602,48 @@
size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
- /* Allocate from kgsl pool if it exists for global mappings */
- pool = _get_pool(pagetable, memdesc->priv);
+ pool = pagetable->pool;
- /* Allocate aligned virtual addresses for iommu. This allows
- * more efficient pagetable entries if the physical memory
- * is also aligned. Don't do this for GPUMMU, because
- * the address space is so small.
- */
- if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype() &&
- kgsl_memdesc_get_align(memdesc) > 0)
- page_align = kgsl_memdesc_get_align(memdesc);
-
- memdesc->gpuaddr = gen_pool_alloc_aligned(pool, size, page_align);
- if (memdesc->gpuaddr == 0) {
- KGSL_CORE_ERR("gen_pool_alloc(%d) failed from pool: %s\n",
- size,
- (pool == pagetable->kgsl_pool) ?
- "kgsl_pool" : "general_pool");
- KGSL_CORE_ERR(" [%d] allocated=%d, entries=%d\n",
- pagetable->name, pagetable->stats.mapped,
- pagetable->stats.entries);
- return -ENOMEM;
+ if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
+ /* Allocate aligned virtual addresses for iommu. This allows
+ * more efficient pagetable entries if the physical memory
+ * is also aligned. Don't do this for GPUMMU, because
+ * the address space is so small.
+ */
+ if (kgsl_memdesc_get_align(memdesc) > 0)
+ page_align = kgsl_memdesc_get_align(memdesc);
+ if (kgsl_memdesc_is_global(memdesc)) {
+ /*
+ * Only the default pagetable has a kgsl_pool, and
+ * it is responsible for creating the mapping for
+ * each global buffer. The mapping will be reused
+ * in all other pagetables and it must already exist
+ * when we're creating other pagetables which do not
+ * have a kgsl_pool.
+ */
+ pool = pagetable->kgsl_pool;
+ if (pool == NULL && memdesc->gpuaddr == 0) {
+ KGSL_CORE_ERR(
+ "No address for global mapping into pt %d\n",
+ pagetable->name);
+ return -EINVAL;
+ }
+ }
+ }
+ if (pool) {
+ memdesc->gpuaddr = gen_pool_alloc_aligned(pool, size,
+ page_align);
+ if (memdesc->gpuaddr == 0) {
+ KGSL_CORE_ERR("gen_pool_alloc(%d) failed, pool: %s\n",
+ size,
+ (pool == pagetable->kgsl_pool) ?
+ "kgsl_pool" : "general_pool");
+ KGSL_CORE_ERR(" [%d] allocated=%d, entries=%d\n",
+ pagetable->name,
+ pagetable->stats.mapped,
+ pagetable->stats.entries);
+ return -ENOMEM;
+ }
}
if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
@@ -676,7 +670,8 @@
err_free_gpuaddr:
spin_unlock(&pagetable->lock);
- gen_pool_free(pool, memdesc->gpuaddr, size);
+ if (pool)
+ gen_pool_free(pool, memdesc->gpuaddr, size);
memdesc->gpuaddr = 0;
return ret;
}
@@ -711,14 +706,20 @@
spin_unlock(&pagetable->lock);
- pool = _get_pool(pagetable, memdesc->priv);
- gen_pool_free(pool, memdesc->gpuaddr, size);
+ pool = pagetable->pool;
+
+ if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()
+ && kgsl_memdesc_is_global(memdesc)) {
+ pool = pagetable->kgsl_pool;
+ }
+ if (pool)
+ gen_pool_free(pool, memdesc->gpuaddr, size);
/*
* Don't clear the gpuaddr on global mappings because they
* may be in use by other pagetables
*/
- if (!(memdesc->priv & KGSL_MEMDESC_GLOBAL))
+ if (!kgsl_memdesc_is_global(memdesc))
memdesc->gpuaddr = 0;
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index b8b9149..b8eff60 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -13,13 +13,14 @@
#ifndef __KGSL_MMU_H
#define __KGSL_MMU_H
+#include <mach/iommu.h>
+
/*
- * These defines control the split between ttbr1 and ttbr0 pagetables of IOMMU
- * and what ranges of memory we map to them
+ * These defines control the address range for allocations that
+ * are mapped into all pagetables.
*/
#define KGSL_IOMMU_GLOBAL_MEM_BASE 0xC0000000
#define KGSL_IOMMU_GLOBAL_MEM_SIZE SZ_4M
-#define KGSL_IOMMU_TTBR1_SPLIT 2
#define KGSL_MMU_ALIGN_SHIFT 13
#define KGSL_MMU_ALIGN_MASK (~((1 << KGSL_MMU_ALIGN_SHIFT) - 1))
@@ -148,6 +149,10 @@
unsigned int (*mmu_get_pt_base_addr)
(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pt);
+ int (*mmu_setup_pt) (struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt);
+ void (*mmu_cleanup_pt) (struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt);
};
struct kgsl_mmu_pt_ops {
@@ -209,7 +214,6 @@
int kgsl_mmu_enabled(void);
void kgsl_mmu_set_mmutype(char *mmutype);
enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
-unsigned int kgsl_mmu_get_ptsize(void);
int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr);
/*
@@ -321,4 +325,58 @@
return 0;
}
+/*
+ * kgsl_mmu_is_perprocess() - Runtime check for per-process
+ * pagetables.
+ *
+ * Returns non-zero if per-process pagetables are enabled,
+ * 0 if not.
+ */
+#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
+static inline int kgsl_mmu_is_perprocess(void)
+{
+
+ /* We presently do not support per-process for IOMMU-v2 */
+ return (kgsl_mmu_get_mmutype() != KGSL_MMU_TYPE_IOMMU)
+ || msm_soc_version_supports_iommu_v1();
+}
+#else
+static inline int kgsl_mmu_is_perprocess(void)
+{
+ return 0;
+}
+#endif
+
+/*
+ * kgsl_mmu_base_addr() - Get gpu virtual address base.
+ *
+ * Returns the start address of the gpu
+ * virtual address space.
+ */
+static inline unsigned int kgsl_mmu_get_base_addr(void)
+{
+ return KGSL_PAGETABLE_BASE;
+}
+
+/*
+ * kgsl_mmu_get_ptsize() - Get gpu pagetable size
+ *
+ * Returns the usable size of the gpu address space.
+ */
+static inline unsigned int kgsl_mmu_get_ptsize(void)
+{
+ /*
+ * For IOMMU, we could do up to 4G virtual range if we wanted to, but
+ * it makes more sense to return a smaller range and leave the rest of
+ * the virtual range for future improvements
+ */
+ enum kgsl_mmutype mmu_type = kgsl_mmu_get_mmutype();
+
+ if (KGSL_MMU_TYPE_GPU == mmu_type)
+ return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
+ else if (KGSL_MMU_TYPE_IOMMU == mmu_type)
+ return SZ_2G;
+ return 0;
+}
+
#endif /* __KGSL_MMU_H */
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 92a6f27..53e88be 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -157,6 +157,17 @@
return 0;
}
+/*
+ * kgsl_memdesc_is_global - is this a globally mapped buffer?
+ * @memdesc: the memdesc
+ *
+ * Returns nonzero if this is a global mapping, 0 otherwise
+ */
+static inline int kgsl_memdesc_is_global(const struct kgsl_memdesc *memdesc)
+{
+ return (memdesc->priv & KGSL_MEMDESC_GLOBAL) != 0;
+}
+
static inline int
kgsl_allocate(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable, size_t size)
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 712bc60..258dcfa 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -260,6 +260,13 @@
GSL_PT_PAGE_RV);
if (result)
goto error_unmap_memstore;
+ /*
+ * Set the mpu end to the last "normal" global memory we use.
+ * For the IOMMU, this will be used to restrict access to the
+ * mapped registers.
+ */
+ device->mh.mpu_range = z180_dev->ringbuffer.cmdbufdesc.gpuaddr +
+ z180_dev->ringbuffer.cmdbufdesc.size;
return result;
error_unmap_dummy:
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 7190af8..b7ace53 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -336,6 +336,8 @@
void* priv; /* Pointer to private data of the API client */
struct data_buffer dvr_input; /* DVR input buffer */
+ struct dentry *debugfs_demux_dir; /* debugfs dir */
+
int (*open) (struct dmx_demux* demux);
int (*close) (struct dmx_demux* demux);
int (*write) (struct dmx_demux *demux, const char *buf, size_t count);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 625eb78..71642a5 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -32,6 +32,8 @@
#include <linux/wait.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include "dmxdev.h"
static int debug;
@@ -3164,6 +3166,73 @@
.fops = &dvb_dvr_fops
};
+
+/**
+ * debugfs service to print active filters information.
+ */
+static int dvb_dmxdev_dbgfs_print(struct seq_file *s, void *p)
+{
+ int i;
+ struct dmxdev *dmxdev = s->private;
+ struct dmxdev_filter *filter;
+ int active_count = 0;
+ struct dmx_buffer_status buffer_status;
+ const char *pes_feeds[] = {"DEC", "PES", "DVR", "REC"};
+
+ if (!dmxdev)
+ return 0;
+
+ for (i = 0; i < dmxdev->filternum; i++) {
+ filter = &dmxdev->filter[i];
+ if (filter->state >= DMXDEV_STATE_GO) {
+ active_count++;
+
+ seq_printf(s, "filter_%02d - ", i);
+
+ if (filter->type == DMXDEV_TYPE_SEC) {
+ seq_printf(s, "type: SEC, ");
+ seq_printf(s, "PID %04d ",
+ filter->params.sec.pid);
+ } else {
+ seq_printf(s, "type: %s, ",
+ pes_feeds[filter->params.pes.output]);
+ seq_printf(s, "PID: %04d ",
+ filter->params.pes.pid);
+ }
+
+ if (0 == dvb_dmxdev_get_buffer_status(
+ filter, &buffer_status)) {
+ seq_printf(s, "buffer size: %08d, ",
+ buffer_status.size);
+ seq_printf(s, "buffer fullness: %08d\n",
+ buffer_status.fullness);
+ seq_printf(s, "buffer error: %08d\n",
+ buffer_status.error);
+ }
+ }
+ }
+
+ if (!active_count)
+ seq_printf(s, "No active filters\n");
+
+ seq_printf(s, "\n");
+
+ return 0;
+}
+
+static int dvb_dmxdev_dbgfs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dvb_dmxdev_dbgfs_print, inode->i_private);
+}
+
+static const struct file_operations dbgfs_filters_fops = {
+ .open = dvb_dmxdev_dbgfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
{
int i;
@@ -3206,6 +3275,11 @@
INIT_WORK(&dmxdev->dvr_input_work,
dvr_input_work_func);
+ if (dmxdev->demux->debugfs_demux_dir)
+ debugfs_create_file("filters", S_IRUGO,
+ dmxdev->demux->debugfs_demux_dir, dmxdev,
+ &dbgfs_filters_fops);
+
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index de7b28d..2c5294f 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1732,19 +1732,20 @@
"demux%d",
dvb_demux_index++);
- dvbdemux->debugfs_demux_dir = debugfs_create_dir(dvbdemux->alias, NULL);
+ dvbdemux->dmx.debugfs_demux_dir =
+ debugfs_create_dir(dvbdemux->alias, NULL);
- if (dvbdemux->debugfs_demux_dir != NULL) {
+ if (dvbdemux->dmx.debugfs_demux_dir != NULL) {
debugfs_create_u32(
"total_processing_time",
S_IRUGO|S_IWUGO,
- dvbdemux->debugfs_demux_dir,
+ dvbdemux->dmx.debugfs_demux_dir,
&dvbdemux->total_process_time);
debugfs_create_u32(
"total_crc_time",
S_IRUGO|S_IWUGO,
- dvbdemux->debugfs_demux_dir,
+ dvbdemux->dmx.debugfs_demux_dir,
&dvbdemux->total_crc_time);
}
@@ -1817,9 +1818,10 @@
void dvb_dmx_release(struct dvb_demux *dvbdemux)
{
- if (dvbdemux->debugfs_demux_dir != NULL)
- debugfs_remove_recursive(dvbdemux->debugfs_demux_dir);
+ if (dvbdemux->dmx.debugfs_demux_dir != NULL)
+ debugfs_remove_recursive(dvbdemux->dmx.debugfs_demux_dir);
+ dvb_demux_index--;
vfree(dvbdemux->cnt_storage);
vfree(dvbdemux->filter);
vfree(dvbdemux->feed);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 5a32363..706cd0c 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -174,7 +174,6 @@
u32 total_process_time;
u32 total_crc_time;
- struct dentry *debugfs_demux_dir;
};
int dvb_dmx_init(struct dvb_demux *dvbdemux);
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
index 18c3767..51d66cd 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
@@ -477,29 +477,29 @@
mpq_demux->hw_notification_size = 0;
mpq_demux->decoder_tsp_drop_count = 0;
- if (mpq_demux->demux.debugfs_demux_dir != NULL) {
+ if (mpq_demux->demux.dmx.debugfs_demux_dir != NULL) {
debugfs_create_u32(
"hw_notification_rate",
S_IRUGO|S_IWUGO,
- mpq_demux->demux.debugfs_demux_dir,
+ mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_rate);
debugfs_create_u32(
"hw_notification_count",
S_IRUGO|S_IWUGO,
- mpq_demux->demux.debugfs_demux_dir,
+ mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_count);
debugfs_create_u32(
"hw_notification_size",
S_IRUGO|S_IWUGO,
- mpq_demux->demux.debugfs_demux_dir,
+ mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_size);
debugfs_create_u32(
"decoder_tsp_drop_count",
S_IRUGO|S_IWUGO,
- mpq_demux->demux.debugfs_demux_dir,
+ mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_tsp_drop_count);
}
}
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index ddb562e..84a26a1 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -186,6 +186,46 @@
DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set,
"%llu\n");
+static int mmc_max_clock_get(void *data, u64 *val)
+{
+ struct mmc_host *host = data;
+
+ if (!host)
+ return -EINVAL;
+
+ *val = host->f_max;
+
+ return 0;
+}
+
+static int mmc_max_clock_set(void *data, u64 val)
+{
+ struct mmc_host *host = data;
+ int err = -EINVAL;
+ unsigned long freq = val;
+ unsigned int old_freq;
+
+ if (!host || (val < host->f_min))
+ goto out;
+
+ mmc_claim_host(host);
+ if (host->bus_ops && host->bus_ops->change_bus_speed) {
+ old_freq = host->f_max;
+ host->f_max = freq;
+
+ err = host->bus_ops->change_bus_speed(host, &freq);
+
+ if (err)
+ host->f_max = old_freq;
+ }
+ mmc_release_host(host);
+out:
+ return err;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(mmc_max_clock_fops, mmc_max_clock_get,
+ mmc_max_clock_set, "%llu\n");
+
void mmc_add_host_debugfs(struct mmc_host *host)
{
struct dentry *root;
@@ -208,6 +248,10 @@
&mmc_clock_fops))
goto err_node;
+ if (!debugfs_create_file("max_clock", S_IRUSR | S_IWUSR, root, host,
+ &mmc_max_clock_fops))
+ goto err_node;
+
#ifdef CONFIG_MMC_CLKGATE
if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR),
root, &host->clk_delay))
diff --git a/drivers/usb/gadget/u_smd.c b/drivers/usb/gadget/u_smd.c
index ce285a3..effe418 100644
--- a/drivers/usb/gadget/u_smd.c
+++ b/drivers/usb/gadget/u_smd.c
@@ -72,6 +72,7 @@
struct smd_port_info *pi;
struct delayed_work connect_work;
+ struct work_struct disconnect_work;
/* At present, smd does not notify
* control bit change info from modem
@@ -589,6 +590,20 @@
}
}
+static void gsmd_disconnect_work(struct work_struct *w)
+{
+ struct gsmd_port *port;
+ struct smd_port_info *pi;
+
+ port = container_of(w, struct gsmd_port, disconnect_work);
+ pi = port->pi;
+
+ pr_debug("%s: port:%p port#%d\n", __func__, port, port->port_num);
+
+ smd_close(port->pi->ch);
+ port->pi->ch = NULL;
+}
+
static void gsmd_notify_modem(void *gptr, u8 portno, int ctrl_bits)
{
struct gsmd_port *port;
@@ -731,10 +746,8 @@
~port->cbits_to_modem);
}
- if (port->pi->ch) {
- smd_close(port->pi->ch);
- port->pi->ch = NULL;
- }
+ if (port->pi->ch)
+ queue_work(gsmd_wq, &port->disconnect_work);
}
#define SMD_CH_MAX_LEN 20
@@ -819,6 +832,7 @@
INIT_WORK(&port->pull, gsmd_tx_pull);
INIT_DELAYED_WORK(&port->connect_work, gsmd_connect_work);
+ INIT_WORK(&port->disconnect_work, gsmd_disconnect_work);
smd_ports[portno].port = port;
pdrv = &smd_ports[portno].pdrv;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 7b616e4..2d69a98 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -324,7 +324,7 @@
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
-#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MIN 945000 /* uV */
#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
#define HSIC_DBG1_REG 0x38
@@ -641,6 +641,7 @@
int cnt = 0, ret;
u32 val;
int none_vol, max_vol;
+ struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
if (atomic_read(&mehci->in_lpm)) {
dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
@@ -719,6 +720,10 @@
enable_irq_wake(mehci->wakeup_irq);
enable_irq(mehci->wakeup_irq);
+ if (pdata && pdata->standalone_latency)
+ pm_qos_update_request(&mehci->pm_qos_req_dma,
+ PM_QOS_DEFAULT_VALUE);
+
wake_unlock(&mehci->wlock);
dev_info(mehci->dev, "HSIC-USB in low power mode\n");
@@ -733,12 +738,17 @@
unsigned temp;
int min_vol, max_vol;
unsigned long flags;
+ struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
if (!atomic_read(&mehci->in_lpm)) {
dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
return 0;
}
+ if (pdata && pdata->standalone_latency)
+ pm_qos_update_request(&mehci->pm_qos_req_dma,
+ pdata->standalone_latency + 1);
+
spin_lock_irqsave(&mehci->wakeup_lock, flags);
if (mehci->wakeup_irq_enabled) {
disable_irq_wake(mehci->wakeup_irq);
@@ -1031,9 +1041,9 @@
pm_qos_update_request(&mehci->pm_qos_req_dma,
pdata->swfi_latency + 1);
wait_for_completion(&mehci->gpt0_completion);
- if (pdata && pdata->swfi_latency)
+ if (pdata && pdata->standalone_latency)
pm_qos_update_request(&mehci->pm_qos_req_dma,
- PM_QOS_DEFAULT_VALUE);
+ pdata->standalone_latency + 1);
spin_lock_irq(&ehci->lock);
} else {
dbg_log_event(NULL, "FPR: Tightloop", 0);
@@ -1680,9 +1690,9 @@
__mehci = mehci;
- if (pdata && pdata->swfi_latency)
+ if (pdata && pdata->standalone_latency)
pm_qos_add_request(&mehci->pm_qos_req_dma,
- PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
+ PM_QOS_CPU_DMA_LATENCY, pdata->standalone_latency + 1);
/*
* This pdev->dev is assigned parent of root-hub by USB core,
@@ -1721,7 +1731,7 @@
struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
- if (pdata && pdata->swfi_latency)
+ if (pdata && pdata->standalone_latency)
pm_qos_remove_request(&mehci->pm_qos_req_dma);
if (mehci->peripheral_status_irq)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index d04c234..23a9499 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1137,11 +1137,20 @@
if (legacy_power_supply) {
/* legacy support */
- if (host_mode)
+ if (host_mode) {
power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_SYSTEM);
- else
+ } else {
power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_DEVICE);
- return;
+ /*
+ * VBUS comparator is disabled by PMIC charging driver
+ * when SYSTEM scope is selected. For ID_GND->ID_A
+ * transition, give 50 msec delay so that PMIC charger
+ * driver detect the VBUS and ready for accepting
+ * charging current value from USB.
+ */
+ if (test_bit(ID_A, &motg->inputs))
+ msleep(50);
+ }
} else {
motg->host_mode = host_mode;
power_supply_changed(psy);
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index bb5f394..45d7a3e 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -43,6 +43,7 @@
#define DIAG_IOCTL_DCI_REG 23
#define DIAG_IOCTL_DCI_STREAM_INIT 24
#define DIAG_IOCTL_DCI_HEALTH_STATS 25
+#define DIAG_IOCTL_REMOTE_DEV 32
/* PC Tools IDs */
#define APQ8060_TOOLS_ID 4062
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 89a8421..e0d9072 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -548,6 +548,14 @@
* @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether
* No Acknowledgement Policy should be applied.
*
+ * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition
+ * Information Element to the WLAN driver
+ *
+ * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver
+ * to the supplicant. This will carry the target AP's MAC address along
+ * with the relevant Information Elements. This event to report received
+ * FT IEs( MDIE, FTIE,RSN IE, TIE, RICIE).
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -689,6 +697,9 @@
NL80211_CMD_SET_NOACK_MAP,
+ NL80211_CMD_UPDATE_FT_IES,
+ NL80211_CMD_FT_EVENT,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1264,6 +1275,10 @@
* @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds
* or 0 to disable background scan.
*
+ * @NL80211_ATTR_MDID: Mobility Domain Identifier
+ *
+ * @NL80211_ATTR_IE_RIC: Resource Information Container Information Element
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1515,6 +1530,9 @@
NL80211_ATTR_BG_SCAN_PERIOD,
+ NL80211_ATTR_MDID,
+ NL80211_ATTR_IE_RIC,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 578b9f9..d6fbc64 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -397,7 +397,12 @@
unsigned data;
struct msm_bus_scale_pdata *bus_scale_table;
unsigned log2_irq_thresh;
+
+ /*swfi latency is required while driving resume on to the bus */
u32 swfi_latency;
+
+ /*standalone latency is required when HSCI is active*/
+ u32 standalone_latency;
};
struct msm_usb_host_platform_data {
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a57c9f9..5c1daf3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1318,6 +1318,21 @@
};
/**
+ * struct cfg80211_update_ft_ies_params - FT IE Information
+ *
+ * This structure provides information needed to update the fast transition IE
+ *
+ * @md: The Mobility Domain ID, 2 Octet value
+ * @ie: Fast Transition IEs
+ * @ie_len: Length of ft_ie in octets
+ */
+struct cfg80211_update_ft_ies_params {
+ u16 md;
+ u8 *ie;
+ size_t ie_len;
+};
+
+/**
* struct cfg80211_ops - backend description for wireless configuration
*
* This struct is registered by fullmac card drivers and/or wireless stacks
@@ -1697,6 +1712,8 @@
u16 noack_map);
struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy);
+ int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_update_ft_ies_params *ftie);
};
/*
@@ -3348,6 +3365,32 @@
*/
u16 cfg80211_calculate_bitrate(struct rate_info *rate);
+/**
+ * struct cfg80211_ft_event - FT Information Elements
+ * @dev: network device
+ * @ies: FT IEs
+ * @ies_len: length of the FT IE in bytes
+ * @target_ap: target AP's MAC address
+ * @ric_ies: RIC IE
+ * @ric_ies_len: length of the RIC IE in bytes
+ */
+struct cfg80211_ft_event_params {
+ u8 *ies;
+ size_t ies_len;
+ u8 target_ap[ETH_ALEN];
+ u8 *ric_ies;
+ size_t ric_ies_len;
+};
+
+/**
+ * cfg80211_ft_event - notify userspace about FT IE and RIC IE
+ * @dev: network device
+ * @cfg80211_ft_event_params: IE information
+ */
+int cfg80211_ft_event(struct net_device *dev,
+ struct cfg80211_ft_event_params ft_event);
+
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 22a4dbe..fa2469e 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1426,6 +1426,11 @@
} else {
u16 flags;
+ if (!(pi->conn)) {
+ kfree_skb(skb);
+ return;
+ }
+
bt_cb(skb)->force_active = pi->force_active;
BT_DBG("Sending on BR/EDR connection %p", pi->conn->hcon);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index f5a7ac3..dd99041 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -954,3 +954,16 @@
return nl80211_unexpected_4addr_frame(dev, addr, gfp);
}
EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
+
+int cfg80211_ft_event(struct net_device *dev,
+ struct cfg80211_ft_event_params ft_event)
+{
+ int err = 0;
+ struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ nl80211_ft_event(rdev, dev, ft_event);
+
+ return err;
+}
+EXPORT_SYMBOL(cfg80211_ft_event);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e322d4d..0410707 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -206,6 +206,9 @@
[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
+ [NL80211_ATTR_MDID] = { .type = NLA_U16 },
+ [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
+ .len = IEEE80211_MAX_DATA_LEN },
};
/* policy for the key attributes */
@@ -6299,6 +6302,26 @@
return 0;
}
+static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct cfg80211_update_ft_ies_params ft_params;
+ struct net_device *dev = info->user_ptr[1];
+
+ if (!info->attrs[NL80211_ATTR_MDID])
+ return -EINVAL;
+
+ ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
+
+ if (!info->attrs[NL80211_ATTR_IE])
+ return -EINVAL;
+
+ ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+ ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+
+ return rdev->ops->update_ft_ies(&rdev->wiphy, dev, &ft_params);
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -6887,6 +6910,14 @@
.internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_UPDATE_FT_IES,
+ .doit = nl80211_update_ft_ies,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
};
@@ -8080,6 +8111,47 @@
.notifier_call = nl80211_netlink_notify,
};
+void nl80211_ft_event(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, struct cfg80211_ft_event_params ft_event)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+ if (ft_event.target_ap)
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event.target_ap);
+ if (ft_event.ies)
+ NLA_PUT(msg, NL80211_ATTR_IE, ft_event.ies_len, ft_event.ies);
+ if (ft_event.ric_ies)
+ NLA_PUT(msg, NL80211_ATTR_IE_RIC, ft_event.ric_ies_len,
+ ft_event.ric_ies);
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, GFP_KERNEL);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+}
+
+
/* initialisation/exit functions */
int nl80211_init(void)
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 4ffe50d..ffd4c8a 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -123,4 +123,8 @@
bool nl80211_unexpected_4addr_frame(struct net_device *dev,
const u8 *addr, gfp_t gfp);
+void nl80211_ft_event(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ struct cfg80211_ft_event_params ft_event);
+
#endif /* __NET_WIRELESS_NL80211_H */