Merge changes I0e3776c7,I630cc47b into msm-3.0
* changes:
msm_fb: display: add dcs read parser
msm_fb: display: configure dsi control as free run
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e070f1c..b2dbee3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1359,7 +1359,7 @@
ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
MSM_SMP || ARCH_SHMOBILE
select USE_GENERIC_SMP_HELPERS
- select HAVE_ARM_SCU if !MSM_SMP
+ select HAVE_ARM_SCU
help
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index fc67689..2acc8e0 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -896,13 +896,6 @@
prompt "Package 4"
endchoice
-config MSM_IPC_ROUTER_SMD_XPRT
- depends on MSM_SMD
- default n
- bool "MSM SMD XPRT Layer"
- help
- SMD Transport Layer for IPC Router
-
config MSM_RPC_SDIO_XPRT
depends on MSM_SDIO_AL
default y
@@ -1064,13 +1057,21 @@
the ARM9 and ARM11
config MSM_IPC_ROUTER
- depends on MSM_IPC_ROUTER_SMD_XPRT
+ depends on NET
default n
bool "MSM IPC Router support"
help
Support for the MSM IPC Router for communication between
the APPs and the MODEM
+config MSM_IPC_ROUTER_SMD_XPRT
+ depends on MSM_SMD
+ depends on MSM_IPC_ROUTER
+ default n
+ bool "MSM SMD XPRT Layer"
+ help
+ SMD Transport Layer for IPC Router
+
config MSM_ONCRPCROUTER_DEBUG
depends on MSM_ONCRPCROUTER
default y
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 307bd60..1d0e1a8 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -223,8 +223,6 @@
static struct l2_level *l2_freq_tbl;
static struct acpu_level *acpu_freq_tbl;
static int l2_freq_tbl_size;
-static int cpu_boot_idx;
-static int l2_boot_idx;
/* Instantaneous bandwidth requests in MB/s. */
#define BW_MBPS(_bw) \
@@ -871,9 +869,11 @@
static void __init per_cpu_init(void *data)
{
+ struct acpu_level *max_acpu_level = data;
int cpu = smp_processor_id();
- init_clock_sources(&scalable[cpu], &acpu_freq_tbl[cpu_boot_idx].speed);
- scalable[cpu].l2_vote = &l2_freq_tbl[l2_boot_idx];
+
+ init_clock_sources(&scalable[cpu], &max_acpu_level->speed);
+ scalable[cpu].l2_vote = max_acpu_level->l2_level;
}
/* Register with bus driver. */
@@ -984,6 +984,35 @@
.notifier_call = acpuclock_cpu_callback,
};
+static struct acpu_level * __init select_freq_plan(void)
+{
+ struct acpu_level *l, *max_acpu_level = NULL;
+
+ /* Select frequency tables. */
+ if (cpu_is_msm8960()) {
+ scalable = scalable_8960;
+ acpu_freq_tbl = acpu_freq_tbl_8960;
+ l2_freq_tbl = l2_freq_tbl_8960;
+ l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960);
+ } else if (cpu_is_apq8064()) {
+ scalable = scalable_8064;
+ acpu_freq_tbl = acpu_freq_tbl_8064;
+ l2_freq_tbl = l2_freq_tbl_8064;
+ l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8064);
+ } else {
+ BUG();
+ }
+
+ /* Find the max supported scaling frequency. */
+ for (l = acpu_freq_tbl; l->speed.khz != 0; l++)
+ if (l->use_for_scaling)
+ max_acpu_level = l;
+ BUG_ON(!max_acpu_level);
+ pr_info("Max ACPU freq: %u KHz\n", max_acpu_level->speed.khz);
+
+ return max_acpu_level;
+}
+
static struct acpuclk_data acpuclk_8960_data = {
.set_rate = acpuclk_8960_set_rate,
.get_rate = acpuclk_8960_get_rate,
@@ -993,24 +1022,9 @@
static int __init acpuclk_8960_init(struct acpuclk_soc_data *soc_data)
{
- if (cpu_is_msm8960()) {
- scalable = scalable_8960;
- acpu_freq_tbl = acpu_freq_tbl_8960;
- l2_freq_tbl = l2_freq_tbl_8960;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960);
- l2_boot_idx = 11;
- cpu_boot_idx = 11;
- } else if (cpu_is_apq8064()) {
- scalable = scalable_8064;
- acpu_freq_tbl = acpu_freq_tbl_8064;
- l2_freq_tbl = l2_freq_tbl_8064;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8064);
- l2_boot_idx = 11;
- cpu_boot_idx = 11;
- }
-
- init_clock_sources(&scalable[L2], &l2_freq_tbl[l2_boot_idx].speed);
- on_each_cpu(per_cpu_init, NULL, true);
+ struct acpu_level *max_acpu_level = select_freq_plan();
+ init_clock_sources(&scalable[L2], &max_acpu_level->l2_level->speed);
+ on_each_cpu(per_cpu_init, max_acpu_level, true);
regulator_init();
bus_init();
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 653afc6..67b1dcc 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -638,65 +638,80 @@
goto reg_disable;
}
+ rc = on ? regulator_set_voltage(bt_vregs[i].reg,
+ bt_vregs[i].level, bt_vregs[i].level) : 0;
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not set voltage for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_disable;
+ }
+
+ rc = on ? regulator_enable(bt_vregs[i].reg) : 0;
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not %sable regulator %s: %d\n",
+ __func__, "en", bt_vregs[i].name, rc);
+ goto reg_disable;
+ }
+
if (bt_vregs[i].is_pin_controlled) {
- rc = pmapp_vreg_pincntrl_vote(id,
+ rc = pmapp_vreg_lpm_pincntrl_vote(id,
bt_vregs[i].pmapp_id,
PMAPP_CLOCK_ID_D1,
on ? PMAPP_CLOCK_VOTE_ON :
PMAPP_CLOCK_VOTE_OFF);
- } else {
- rc = on ? regulator_enable(bt_vregs[i].reg) :
- regulator_disable(bt_vregs[i].reg);
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: pin control failed for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto pin_cnt_fail;
+ }
}
+ rc = on ? 0 : regulator_disable(bt_vregs[i].reg);
if (rc) {
dev_err(&msm_bt_power_device.dev,
"%s: could not %sable regulator %s: %d\n",
- __func__, on ? "en" : "dis",
- bt_vregs[i].name, rc);
- i++;
+ __func__, "dis", bt_vregs[i].name, rc);
goto reg_disable;
}
}
return rc;
-
+pin_cnt_fail:
+ if (on)
+ regulator_disable(bt_vregs[i].reg);
reg_disable:
- while (i--) {
- if (bt_vregs[i].is_pin_controlled) {
- pmapp_vreg_pincntrl_vote(id, bt_vregs[i].pmapp_id,
- PMAPP_CLOCK_ID_D1,
- on ? PMAPP_CLOCK_VOTE_OFF :
- PMAPP_CLOCK_VOTE_ON);
- } else {
- if (on)
- regulator_disable(bt_vregs[i].reg);
- else
- regulator_enable(bt_vregs[i].reg);
+ while (i) {
+ if (on) {
+ i--;
+ regulator_disable(bt_vregs[i].reg);
+ regulator_put(bt_vregs[i].reg);
}
}
return rc;
}
-static struct regulator *reg_bahama;
+static struct regulator *reg_s3;
static unsigned int msm_bahama_setup_power(void)
{
int rc = 0;
- reg_bahama = regulator_get(NULL, "msme1");
- if (IS_ERR(reg_bahama)) {
- rc = PTR_ERR(reg_bahama);
+ reg_s3 = regulator_get(NULL, "msme1");
+ if (IS_ERR(reg_s3)) {
+ rc = PTR_ERR(reg_s3);
pr_err("%s: could not get regulator: %d\n", __func__, rc);
goto out;
}
- rc = regulator_set_voltage(reg_bahama, 1800000, 1800000);
+ rc = regulator_set_voltage(reg_s3, 1800000, 1800000);
if (rc) {
pr_err("%s: could not set voltage: %d\n", __func__, rc);
goto reg_fail;
}
- rc = regulator_enable(reg_bahama);
+ rc = regulator_enable(reg_s3);
if (rc < 0) {
pr_err("%s: could not enable regulator: %d\n", __func__, rc);
goto reg_fail;
@@ -722,11 +737,11 @@
gpio_fail:
gpio_free(GPIO_BT_SYS_REST_EN);
reg_disable:
- regulator_disable(reg_bahama);
+ regulator_disable(reg_s3);
reg_fail:
- regulator_put(reg_bahama);
+ regulator_put(reg_s3);
out:
- reg_bahama = NULL;
+ reg_s3 = NULL;
return rc;
}
@@ -734,12 +749,12 @@
{
int rc = 0;
- if (IS_ERR_OR_NULL(reg_bahama)) {
- rc = reg_bahama ? PTR_ERR(reg_bahama) : -ENODEV;
+ if (IS_ERR_OR_NULL(reg_s3)) {
+ rc = reg_s3 ? PTR_ERR(reg_s3) : -ENODEV;
goto out;
}
- rc = regulator_disable(reg_bahama);
+ rc = regulator_disable(reg_s3);
if (rc) {
pr_err("%s: could not disable regulator: %d\n", __func__, rc);
goto out;
@@ -750,18 +765,15 @@
if (rc) {
pr_err("%s: bt_set_gpio = %d\n",
__func__, rc);
- goto reg_enable;
}
gpio_free(GPIO_BT_SYS_REST_EN);
}
- regulator_put(reg_bahama);
- reg_bahama = NULL;
+ regulator_put(reg_s3);
+ reg_s3 = NULL;
return 0;
-reg_enable:
- regulator_enable(reg_bahama);
out:
return rc;
}
@@ -933,21 +945,12 @@
__func__, bt_vregs[i].name, rc);
goto reg_get_fail;
}
- rc = regulator_set_voltage(bt_vregs[i].reg,
- bt_vregs[i].level, bt_vregs[i].level);
- if (rc) {
- dev_err(dev, "%s: could not set voltage for %s: %d\n",
- __func__, bt_vregs[i].name, rc);
- goto reg_set_fail;
- }
}
dev->platform_data = &bluetooth_power;
return rc;
-reg_set_fail:
- i++;
reg_get_fail:
while (i--) {
regulator_put(bt_vregs[i].reg);
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 6024757..2cf0a70 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -2678,8 +2678,18 @@
static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
{TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_DOWN},
- {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_DOWN}
+ /*
+ * SDC3 CMD line should be PULLed UP otherwise fluid platform will
+ * see transitions (1 -> 0 and 0 -> 1) on card detection line,
+ * which would result in false card detection interrupts.
+ */
+ {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+ /*
+ * Keeping DATA lines status to PULL UP will make sure that
+ * there is no current leak during sleep if external pull up
+ * is connected to DATA lines.
+ */
+ {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
};
struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
@@ -3647,7 +3657,7 @@
static void __init msm8960_gfx_init(void)
{
- uint32_t soc_platform_version = socinfo_get_platform_version();
+ uint32_t soc_platform_version = socinfo_get_version();
if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
struct kgsl_device_platform_data *kgsl_3d0_pdata =
msm_kgsl_3d0.dev.platform_data;
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index ea9d246..3d34a30 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -176,6 +176,8 @@
static DEFINE_MUTEX(xprt_info_list_lock);
DECLARE_COMPLETION(msm_ipc_remote_router_up);
+static DECLARE_COMPLETION(msm_ipc_local_router_up);
+#define IPC_ROUTER_INIT_TIMEOUT (10 * HZ)
static uint32_t next_port_id;
static DEFINE_MUTEX(next_port_id_lock);
@@ -2399,8 +2401,16 @@
struct msm_ipc_router_xprt_info *xprt_info = xprt->priv;
struct msm_ipc_router_xprt_work *xprt_work;
struct rr_packet *pkt;
+ unsigned long ret;
- BUG_ON(!msm_ipc_router_workqueue);
+ if (!msm_ipc_router_workqueue) {
+ ret = wait_for_completion_timeout(&msm_ipc_local_router_up,
+ IPC_ROUTER_INIT_TIMEOUT);
+ if (!ret || !msm_ipc_router_workqueue) {
+ pr_err("%s: IPC Router not initialized\n", __func__);
+ return;
+ }
+ }
switch (event) {
case IPC_ROUTER_XPRT_EVENT_OPEN:
@@ -2515,6 +2525,7 @@
if (ret < 0)
pr_err("%s: Init sockets failed\n", __func__);
+ complete_all(&msm_ipc_local_router_up);
return ret;
}
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index 5987752..997d4b5 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -46,7 +46,14 @@
static struct msm_ipc_router_smd_xprt smd_remote_xprt;
+struct msm_ipc_router_smd_xprt_work {
+ struct msm_ipc_router_xprt *xprt;
+ struct work_struct work;
+};
+
static void smd_xprt_read_data(struct work_struct *work);
+static void smd_xprt_open_event(struct work_struct *work);
+static void smd_xprt_close_event(struct work_struct *work);
static DECLARE_DELAYED_WORK(work_read_data, smd_xprt_read_data);
static struct workqueue_struct *smd_xprt_workqueue;
@@ -201,8 +208,10 @@
D("%s: Allocated rr_packet\n", __func__);
}
- if ((pkt_size >= MIN_FRAG_SZ) &&
- (smd_read_avail(smd_remote_xprt.channel) < MIN_FRAG_SZ))
+ if (((pkt_size >= MIN_FRAG_SZ) &&
+ (smd_read_avail(smd_remote_xprt.channel) < MIN_FRAG_SZ)) ||
+ ((pkt_size < MIN_FRAG_SZ) &&
+ (smd_read_avail(smd_remote_xprt.channel) < pkt_size)))
return;
sz = smd_read_avail(smd_remote_xprt.channel);
@@ -249,9 +258,32 @@
}
}
+static void smd_xprt_open_event(struct work_struct *work)
+{
+ struct msm_ipc_router_smd_xprt_work *xprt_work =
+ container_of(work, struct msm_ipc_router_smd_xprt_work, work);
+
+ msm_ipc_router_xprt_notify(xprt_work->xprt,
+ IPC_ROUTER_XPRT_EVENT_OPEN, NULL);
+ D("%s: Notified IPC Router of OPEN Event\n", __func__);
+ kfree(xprt_work);
+}
+
+static void smd_xprt_close_event(struct work_struct *work)
+{
+ struct msm_ipc_router_smd_xprt_work *xprt_work =
+ container_of(work, struct msm_ipc_router_smd_xprt_work, work);
+
+ msm_ipc_router_xprt_notify(xprt_work->xprt,
+ IPC_ROUTER_XPRT_EVENT_CLOSE, NULL);
+ D("%s: Notified IPC Router of CLOSE Event\n", __func__);
+ kfree(xprt_work);
+}
+
static void msm_ipc_router_smd_remote_notify(void *_dev, unsigned event)
{
unsigned long flags;
+ struct msm_ipc_router_smd_xprt_work *xprt_work;
switch (event) {
case SMD_EVENT_DATA:
@@ -266,9 +298,16 @@
spin_lock_irqsave(&modem_reset_lock, flags);
modem_reset = 0;
spin_unlock_irqrestore(&modem_reset_lock, flags);
- msm_ipc_router_xprt_notify(&smd_remote_xprt.xprt,
- IPC_ROUTER_XPRT_EVENT_OPEN, NULL);
- D("%s: Notified IPC Router of OPEN Event\n", __func__);
+ xprt_work = kmalloc(sizeof(struct msm_ipc_router_smd_xprt_work),
+ GFP_ATOMIC);
+ if (!xprt_work) {
+ pr_err("%s: Couldn't notify %d event to IPC Router\n",
+ __func__, event);
+ return;
+ }
+ xprt_work->xprt = &smd_remote_xprt.xprt;
+ INIT_WORK(&xprt_work->work, smd_xprt_open_event);
+ queue_work(smd_xprt_workqueue, &xprt_work->work);
break;
case SMD_EVENT_CLOSE:
@@ -276,9 +315,16 @@
modem_reset = 1;
spin_unlock_irqrestore(&modem_reset_lock, flags);
wake_up(&write_avail_wait_q);
- msm_ipc_router_xprt_notify(&smd_remote_xprt.xprt,
- IPC_ROUTER_XPRT_EVENT_CLOSE, NULL);
- D("%s: Notified IPC Router of CLOSE Event\n", __func__);
+ xprt_work = kmalloc(sizeof(struct msm_ipc_router_smd_xprt_work),
+ GFP_ATOMIC);
+ if (!xprt_work) {
+ pr_err("%s: Couldn't notify %d event to IPC Router\n",
+ __func__, event);
+ return;
+ }
+ xprt_work->xprt = &smd_remote_xprt.xprt;
+ INIT_WORK(&xprt_work->work, smd_xprt_close_event);
+ queue_work(smd_xprt_workqueue, &xprt_work->work);
break;
}
}
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index c6bbb0d..00c7633 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -527,7 +527,7 @@
*/
if (rem > 1) {
struct i2c_msg *next = msg + 1;
- if (next->addr == msg->addr && (next->flags | I2C_M_RD)
+ if (next->addr == msg->addr && (next->flags & I2C_M_RD)
&& *idx == ((dev->wr_sz*2) - 4)) {
writel_relaxed(((last_entry |
msg->buf[dev->pos]) |
diff --git a/drivers/net/wireless/libra/qcomwlan7x27a_pwrif.c b/drivers/net/wireless/libra/qcomwlan7x27a_pwrif.c
index 51dd125..5da7a42 100644
--- a/drivers/net/wireless/libra/qcomwlan7x27a_pwrif.c
+++ b/drivers/net/wireless/libra/qcomwlan7x27a_pwrif.c
@@ -65,19 +65,11 @@
goto out;
}
- rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
- if (rc) {
- pr_err("%s: could not set voltages: %d\n", __func__, rc);
- goto reg_free;
- }
-
for (i = 0; i < ARRAY_SIZE(regs); i++)
vreg_info[i].reg = regs[i].consumer;
return 0;
-reg_free:
- regulator_bulk_free(ARRAY_SIZE(regs), regs);
out:
return rc;
}
@@ -134,6 +126,25 @@
for (index = 0; index < ARRAY_SIZE(vreg_info); index++) {
if (on) {
+
+ rc = regulator_set_voltage(vreg_info[index].reg,
+ vreg_info[index].vreg_level,
+ vreg_info[index].vreg_level);
+ if (rc) {
+ pr_err("%s:%s set voltage failed %d\n",
+ __func__, vreg_info[index].vreg_id, rc);
+
+ goto vreg_fail;
+ }
+
+ rc = regulator_enable(vreg_info[index].reg);
+ if (rc) {
+ pr_err("%s:%s vreg enable failed %d\n",
+ __func__, vreg_info[index].vreg_id, rc);
+
+ goto vreg_fail;
+ }
+
if (vreg_info[index].is_vreg_pin_controlled) {
rc = pmapp_vreg_lpm_pincntrl_vote(id,
vreg_info[index].pmapp_id,
@@ -143,17 +154,10 @@
" for enable failed %d\n",
__func__,
vreg_info[index].vreg_id, rc);
- goto vreg_fail;
- }
- } else {
- rc = regulator_enable(vreg_info[index].reg);
- if (rc) {
- pr_err("%s:%s vreg enable failed %d\n",
- __func__,
- vreg_info[index].vreg_id, rc);
- goto vreg_fail;
+ goto vreg_clock_vote_fail;
}
}
+
/*At this point CLK_PWR_REQ is high*/
if (WLAN_VREG_L6 == index) {
/*
@@ -182,13 +186,11 @@
__func__,
vreg_info[index].vreg_id, rc);
}
- } else {
- rc = regulator_disable(vreg_info[index].reg);
- if (rc) {
- pr_err("%s:%s vreg disable failed %d\n",
- __func__,
- vreg_info[index].vreg_id, rc);
- }
+ }
+ rc = regulator_disable(vreg_info[index].reg);
+ if (rc) {
+ pr_err("%s:%s vreg disable failed %d\n",
+ __func__, vreg_info[index].vreg_id, rc);
}
}
}
@@ -196,7 +198,7 @@
vreg_fail:
index--;
vreg_clock_vote_fail:
- while (index > 0) {
+ while (index >= 0) {
rc = regulator_disable(vreg_info[index].reg);
if (rc) {
pr_err("%s:%s vreg disable failed %d\n",
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 2a61337..ebbd1d8 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -41,6 +41,7 @@
int ifc_id;
u8 port_num;
atomic_t online;
+ atomic_t ctrl_online;
struct usb_composite_dev *cdev;
spinlock_t lock;
@@ -297,6 +298,8 @@
static void frmnet_disable(struct usb_function *f)
{
struct f_rmnet *dev = func_to_rmnet(f);
+ unsigned long flags;
+ struct rmnet_ctrl_pkt *cpkt;
pr_debug("%s: port#%d\n", __func__, dev->port_num);
@@ -304,6 +307,17 @@
atomic_set(&dev->online, 0);
+ spin_lock_irqsave(&dev->lock, flags);
+ while (!list_empty(&dev->cpkt_resp_q)) {
+ cpkt = list_first_entry(&dev->cpkt_resp_q,
+ struct rmnet_ctrl_pkt, list);
+
+ list_del(&cpkt->list);
+ rmnet_free_ctrl_pkt(cpkt);
+ }
+ atomic_set(&dev->notify_count, 0);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
gport_rmnet_disconnect(dev);
}
@@ -384,6 +398,73 @@
}
}
+static void frmnet_connect(struct grmnet *gr)
+{
+ struct f_rmnet *dev;
+
+ if (!gr) {
+ pr_err("%s: Invalid grmnet:%p\n", __func__, gr);
+ return;
+ }
+
+ dev = port_to_rmnet(gr);
+
+ atomic_set(&dev->ctrl_online, 1);
+}
+
+static void frmnet_disconnect(struct grmnet *gr)
+{
+ struct f_rmnet *dev;
+ unsigned long flags;
+ struct usb_cdc_notification *event;
+ int status;
+ struct rmnet_ctrl_pkt *cpkt;
+
+ if (!gr) {
+ pr_err("%s: Invalid grmnet:%p\n", __func__, gr);
+ return;
+ }
+
+ dev = port_to_rmnet(gr);
+
+ atomic_set(&dev->ctrl_online, 0);
+
+ if (!atomic_read(&dev->online)) {
+ pr_debug("%s: nothing to do\n", __func__);
+ return;
+ }
+
+ usb_ep_fifo_flush(dev->notify);
+
+ event = dev->notify_req->buf;
+ event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
+ | USB_RECIP_INTERFACE;
+ event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
+ event->wValue = cpu_to_le16(0);
+ event->wIndex = cpu_to_le16(dev->ifc_id);
+ event->wLength = cpu_to_le16(0);
+
+ status = usb_ep_queue(dev->notify, dev->notify_req, GFP_KERNEL);
+ if (status < 0) {
+ if (!atomic_read(&dev->online))
+ return;
+ pr_err("%s: rmnet notify ep enqueue error %d\n",
+ __func__, status);
+ }
+
+ spin_lock_irqsave(&dev->lock, flags);
+ while (!list_empty(&dev->cpkt_resp_q)) {
+ cpkt = list_first_entry(&dev->cpkt_resp_q,
+ struct rmnet_ctrl_pkt, list);
+
+ list_del(&cpkt->list);
+ rmnet_free_ctrl_pkt(cpkt);
+ }
+ atomic_set(&dev->notify_count, 0);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+}
+
static int
frmnet_send_cpkt_response(struct grmnet *gr, struct rmnet_ctrl_pkt *cpkt)
{
@@ -400,7 +481,7 @@
pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
- if (!atomic_read(&dev->online)) {
+ if (!atomic_read(&dev->online) || !atomic_read(&dev->ctrl_online)) {
rmnet_free_ctrl_pkt(cpkt);
return 0;
}
@@ -459,6 +540,9 @@
pr_err("rmnet notify ep error %d\n", status);
/* FALLTHROUGH */
case 0:
+ if (!atomic_read(&dev->ctrl_online))
+ break;
+
if (atomic_dec_and_test(&dev->notify_count))
break;
@@ -706,6 +790,8 @@
f->set_alt = frmnet_set_alt;
f->setup = frmnet_setup;
dev->port.send_cpkt_response = frmnet_send_cpkt_response;
+ dev->port.disconnect = frmnet_disconnect;
+ dev->port.connect = frmnet_connect;
status = usb_add_function(c, f);
if (status) {
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index aeaddee..3c21316 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -48,6 +48,9 @@
void (*send_cbits_tomodem)(struct grmnet *g,
u8 port_num,
int cbits);
+
+ void (*disconnect)(struct grmnet *g);
+ void (*connect)(struct grmnet *g);
};
int gbam_setup(unsigned int count);
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index b4d2828..fc159cc 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
@@ -273,6 +273,8 @@
{
struct rmnet_ctrl_port *port = p;
struct smd_ch_info *c = &port->ctrl_ch;
+ struct rmnet_ctrl_pkt *cpkt;
+ unsigned long flags;
pr_debug("%s: EVENT_(%s)\n", __func__, get_smd_event(event));
@@ -285,10 +287,27 @@
break;
case SMD_EVENT_OPEN:
set_bit(CH_OPENED, &c->flags);
- wake_up(&c->wait);
+
+ if (port && port->port_usb && port->port_usb->connect)
+ port->port_usb->connect(port->port_usb);
+
break;
case SMD_EVENT_CLOSE:
clear_bit(CH_OPENED, &c->flags);
+
+ if (port && port->port_usb && port->port_usb->disconnect)
+ port->port_usb->disconnect(port->port_usb);
+
+ spin_lock_irqsave(&port->port_lock, flags);
+ while (!list_empty(&c->tx_q)) {
+ cpkt = list_first_entry(&c->tx_q,
+ struct rmnet_ctrl_pkt, list);
+
+ list_del(&cpkt->list);
+ free_rmnet_ctrl_pkt(cpkt);
+ }
+ spin_unlock_irqrestore(&port->port_lock, flags);
+
break;
}
}
@@ -357,6 +376,7 @@
struct rmnet_ctrl_port *port;
unsigned long flags;
struct smd_ch_info *c;
+ struct rmnet_ctrl_pkt *cpkt;
pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num);
@@ -378,6 +398,14 @@
gr->send_cpkt_request = 0;
gr->send_cbits_tomodem = 0;
c->cbits_tomodem = 0;
+
+ while (!list_empty(&c->tx_q)) {
+ cpkt = list_first_entry(&c->tx_q, struct rmnet_ctrl_pkt, list);
+
+ list_del(&cpkt->list);
+ free_rmnet_ctrl_pkt(cpkt);
+ }
+
spin_unlock_irqrestore(&port->port_lock, flags);
if (test_bit(CH_OPENED, &c->flags)) {
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 3c130e9..4658469 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -2144,7 +2144,6 @@
static int msm_otg_pm_resume(struct device *dev)
{
struct msm_otg *motg = dev_get_drvdata(dev);
- int ret = 0;
dev_dbg(dev, "OTG PM resume\n");
@@ -2153,7 +2152,7 @@
* Do not resume hardware as part of system resume,
* rather, wait for the ASYNC INT from the h/w
*/
- return ret;
+ return 0;
#endif
return msm_otg_resume(motg);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d103bef6..dea21c1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -909,6 +909,37 @@
}
}
+/* Find socket with fixed cid with given source and destination bdaddrs.
+ * Returns closest match, locked.
+ */
+static struct sock *l2cap_get_sock_by_fixed_scid(int state,
+ __le16 cid, bdaddr_t *src, bdaddr_t *dst)
+{
+ struct sock *sk = NULL, *sk1 = NULL;
+ struct hlist_node *node;
+
+ read_lock(&l2cap_sk_list.lock);
+
+ sk_for_each(sk, node, &l2cap_sk_list.head) {
+ if (state && sk->sk_state != state)
+ continue;
+
+ if (l2cap_pi(sk)->scid == cid && !bacmp(&bt_sk(sk)->dst, dst)) {
+ /* Exact match. */
+ if (!bacmp(&bt_sk(sk)->src, src))
+ break;
+
+ /* Closest match */
+ if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
+ sk1 = sk;
+ }
+ }
+
+ read_unlock(&l2cap_sk_list.lock);
+
+ return node ? sk : sk1;
+}
+
/* Find socket with cid and source bdaddr.
* Returns closest match, locked.
*/
@@ -7051,7 +7082,7 @@
{
struct sock *sk;
- sk = l2cap_get_sock_by_scid(0, cid, conn->src);
+ sk = l2cap_get_sock_by_fixed_scid(0, cid, conn->src, conn->dst);
if (!sk)
goto drop;
diff --git a/sound/soc/codecs/wcd9310-tables.c b/sound/soc/codecs/wcd9310-tables.c
index 98a5139..a97a981 100644
--- a/sound/soc/codecs/wcd9310-tables.c
+++ b/sound/soc/codecs/wcd9310-tables.c
@@ -319,6 +319,18 @@
[TABLA_A_CDC_TX8_DMIC_CTL] = 1,
[TABLA_A_CDC_TX9_DMIC_CTL] = 1,
[TABLA_A_CDC_TX10_DMIC_CTL] = 1,
+ [TABLA_A_CDC_ANC2_CTL] = 1,
+ [TABLA_A_CDC_ANC2_SHIFT] = 1,
+ [TABLA_A_CDC_ANC2_FILT1_B1_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT1_B2_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT1_B3_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT1_B4_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT2_B1_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT2_B2_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT2_B3_CTL] = 1,
+ [TABLA_A_CDC_ANC2_SPARE] = 1,
+ [TABLA_A_CDC_ANC2_FILT3_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT4_CTL] = 1,
[TABLA_A_CDC_SRC1_PDA_CFG] = 1,
[TABLA_A_CDC_SRC2_PDA_CFG] = 1,
[TABLA_A_CDC_SRC1_FS_CTL] = 1,
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index fd00253..548b834 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1095,7 +1095,7 @@
pr_err("%s: Failed to configure gpio %d\n", __func__,
PM8921_GPIO_PM_TO_SYS(35));
else
- gpio_direction_output(PM8921_GPIO_PM_TO_SYS(35), 1);
+ gpio_direction_output(PM8921_GPIO_PM_TO_SYS(35), 0);
return 0;
}