aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCurtis Menard <curtis.menard@gmail.com>2013-01-20 15:28:07 -0500
committercodeworkx <codeworkx@cyanogenmod.org>2013-01-21 16:16:57 +0000
commit76fcb2e9deea2bb578db7fc897f68312a0dea9a0 (patch)
tree744e3a1ae3f474a3f840f8a81fb395e227e549e0
parent10b2523bd76efada8f212f55b5b36889091b991a (diff)
downloadkernel_samsung_smdk4412-76fcb2e9deea2bb578db7fc897f68312a0dea9a0.zip
kernel_samsung_smdk4412-76fcb2e9deea2bb578db7fc897f68312a0dea9a0.tar.gz
kernel_samsung_smdk4412-76fcb2e9deea2bb578db7fc897f68312a0dea9a0.tar.bz2
mdm: Update mdm
This update produces less wakelocs for mdm_hsic. It also allows building without CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE. USB tethering works well this way on t0lte. Patch Set 1: Fixed typo in defconfig that was breaking the build Signed-off-by: Curtis Menard <curtis.menard@gmail.com> Change-Id: Id602ea291093a8cebbcd5ab7f7687364fab0d029
-rwxr-xr-xarch/arm/configs/cyanogenmod_t0lte_defconfig2
-rwxr-xr-xarch/arm/configs/cyanogenmod_t0ltecdma_defconfig4
-rw-r--r--arch/arm/mach-exynos/mdm_hsic_pm.c92
-rw-r--r--drivers/net/usb/rmnet_usb_ctrl.c27
-rw-r--r--drivers/net/usb/rmnet_usb_data.c5
5 files changed, 122 insertions, 8 deletions
diff --git a/arch/arm/configs/cyanogenmod_t0lte_defconfig b/arch/arm/configs/cyanogenmod_t0lte_defconfig
index 32ed90a..b09bd58 100755
--- a/arch/arm/configs/cyanogenmod_t0lte_defconfig
+++ b/arch/arm/configs/cyanogenmod_t0lte_defconfig
@@ -2629,7 +2629,7 @@ CONFIG_USB_GADGET_DUALSPEED=y
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_G_SLP is not set
CONFIG_USB_G_ANDROID=y
-CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE=y
+# CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE is not set
# CONFIG_USB_ANDROID_SAMSUNG_MTP is not set
CONFIG_USB_DUN_SUPPORT=y
# CONFIG_USB_ANDROID is not set
diff --git a/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig b/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig
index 8a90d61..721a886 100755
--- a/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig
+++ b/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig
@@ -2630,8 +2630,8 @@ CONFIG_USB_GADGET_DUALSPEED=y
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_G_SLP is not set
CONFIG_USB_G_ANDROID=y
-CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE=y
-CONFIG_USB_ANDROID_SAMSUNG_MTP=y
+# CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE is not set
+# CONFIG_USB_ANDROID_SAMSUNG_MTP is not set
CONFIG_USB_DUN_SUPPORT=y
# CONFIG_USB_ANDROID is not set
# CONFIG_USB_CDC_COMPOSITE is not set
diff --git a/arch/arm/mach-exynos/mdm_hsic_pm.c b/arch/arm/mach-exynos/mdm_hsic_pm.c
index 7d8ee80..a8dd153 100644
--- a/arch/arm/mach-exynos/mdm_hsic_pm.c
+++ b/arch/arm/mach-exynos/mdm_hsic_pm.c
@@ -35,15 +35,20 @@
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/ehci_def.h>
-
+#include <mach/mdm2.h>
#include <linux/kernel.h>
+
+#ifdef CONFIG_CPU_FREQ_TETHERING
#include <linux/netdevice.h>
-#include <mach/mdm2.h>
+#endif
+
+#ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE
#include <linux/usb/android_composite.h>
+#endif
#define EXTERNAL_MODEM "external_modem"
#define EHCI_REG_DUMP
-#define DEFAULT_RAW_WAKE_TIME (6*HZ)
+#define DEFAULT_RAW_WAKE_TIME (0*HZ)
BLOCKING_NOTIFIER_HEAD(mdm_reset_notifier_list);
@@ -85,8 +90,12 @@ struct mdm_hsic_pm_data {
/* control variables */
struct notifier_block pm_notifier;
+#ifdef CONFIG_CPU_FREQ_TETHERING
struct notifier_block netdev_notifier;
+#endif
+#ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE
struct notifier_block usb_composite_notifier;
+#endif
bool block_request;
bool state_busy;
@@ -122,6 +131,9 @@ struct mdm_hsic_pm_data {
/* indicate wakeup from lpa state */
bool lpa_handling;
+/* indicate receive hallo_packet_rx */
+int hello_packet_rx;
+
#ifdef EHCI_REG_DUMP
struct dump_ehci_regs {
unsigned caps_hc_capbase;
@@ -233,6 +245,49 @@ static struct mdm_hsic_pm_data *get_pm_data_by_dev_name(const char *name)
return NULL;
}
+/* do not call in irq context */
+int pm_dev_runtime_get_enabled(struct usb_device *udev)
+{
+ int spin = 50;
+
+ while (spin--) {
+ pr_debug("%s: rpm status: %d\n", __func__,
+ udev->dev.power.runtime_status);
+ if (udev->dev.power.runtime_status == RPM_ACTIVE ||
+ udev->dev.power.runtime_status == RPM_SUSPENDED) {
+ usb_mark_last_busy(udev);
+ break;
+ }
+ msleep(20);
+ }
+ if (spin <= 0) {
+ pr_err("%s: rpm status %d, return -EAGAIN\n", __func__,
+ udev->dev.power.runtime_status);
+ return -EAGAIN;
+ }
+ usb_mark_last_busy(udev);
+
+ return 0;
+}
+
+/* do not call in irq context */
+int pm_dev_wait_lpa_wake(void)
+{
+ int spin = 50;
+
+ while (lpa_handling && spin--) {
+ pr_debug("%s: lpa wake wait loop\n", __func__);
+ msleep(20);
+ }
+
+ if (lpa_handling) {
+ pr_err("%s: in lpa wakeup, return EAGAIN\n", __func__);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
void notify_modem_fatal(void)
{
struct mdm_hsic_pm_data *pm_data =
@@ -253,6 +308,8 @@ void notify_modem_fatal(void)
pm_runtime_get_noresume(dev);
pm_runtime_dont_use_autosuspend(dev);
+ /* if it's in going suspend, give settle time before wake up */
+ msleep(100);
wake_up_all(&dev->power.wait_queue);
pm_runtime_resume(dev);
pm_runtime_get_noresume(dev);
@@ -265,6 +322,7 @@ void request_autopm_lock(int status)
{
struct mdm_hsic_pm_data *pm_data =
get_pm_data_by_dev_name("mdm_hsic_pm0");
+ int spin = 5;
if (!pm_data || !pm_data->udev)
return;
@@ -275,6 +333,15 @@ void request_autopm_lock(int status)
if (!atomic_read(&pm_data->pmlock_cnt)) {
atomic_inc(&pm_data->pmlock_cnt);
pr_info("get lock\n");
+
+ do {
+ if (!pm_dev_runtime_get_enabled(pm_data->udev))
+ break;
+ } while (spin--);
+
+ if (spin <= 0)
+ mdm_force_fatal();
+
pm_runtime_get(&pm_data->udev->dev);
pm_runtime_forbid(&pm_data->udev->dev);
} else
@@ -287,6 +354,8 @@ void request_autopm_lock(int status)
pm_runtime_allow(&pm_data->udev->dev);
pm_runtime_put(&pm_data->udev->dev);
}
+ /* initailize hello_packet_rx */
+ hello_packet_rx = 0;
}
}
@@ -304,6 +373,7 @@ void request_active_lock_release(const char *name)
pr_info("%s\n", __func__);
if (pm_data)
wake_unlock(&pm_data->l2_wake);
+
}
void request_boot_lock_set(const char *name)
@@ -486,6 +556,9 @@ int register_udev_to_pm_dev(const char *name, struct usb_device *udev)
pm_data->udev = udev;
atomic_set(&pm_data->pmlock_cnt, 0);
usb_disable_autosuspend(udev);
+#ifdef CONFIG_SIM_DETECT
+ get_sim_state_at_boot();
+#endif
} else if (pm_data->udev && pm_data->udev != udev) {
pr_err("%s:udev mismatching: pm_data->udev(0x%p), udev(0x%p)\n",
__func__, pm_data->udev, udev);
@@ -825,6 +898,11 @@ static int mdm_hsic_pm_gpio_init(struct mdm_hsic_pm_data *pm_data,
if (ret < 0)
return ret;
gpio_direction_output(pm_data->gpio_host_ready, 1);
+ s3c_gpio_cfgpin(pm_data->gpio_host_ready, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(pm_data->gpio_host_ready, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(pm_data->gpio_host_ready,
+ S5P_GPIO_DRVSTR_LV4);
+ gpio_set_value(pm_data->gpio_host_ready, 1);
} else
return -ENXIO;
@@ -879,6 +957,7 @@ static void mdm_hsic_pm_gpio_free(struct mdm_hsic_pm_data *pm_data)
gpio_free(pm_data->gpio_host_wake);
}
+#ifdef CONFIG_CPU_FREQ_TETHERING
static int link_pm_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
@@ -907,7 +986,9 @@ static int link_pm_netdev_event(struct notifier_block *this,
}
return NOTIFY_DONE;
}
+#endif
+#ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE
static int usb_composite_notifier_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
@@ -932,6 +1013,7 @@ static int usb_composite_notifier_event(struct notifier_block *this,
return NOTIFY_DONE;
}
+#endif
static int mdm_hsic_pm_probe(struct platform_device *pdev)
{
@@ -992,12 +1074,16 @@ static int mdm_hsic_pm_probe(struct platform_device *pdev)
blocking_notifier_chain_register(&mdm_reset_notifier_list,
&mdm_reset_main_block);
+#ifdef CONFIG_CPU_FREQ_TETHERING
pm_data->netdev_notifier.notifier_call = link_pm_netdev_event;
register_netdevice_notifier(&pm_data->netdev_notifier);
+#endif
+#ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE
pm_data->usb_composite_notifier.notifier_call =
usb_composite_notifier_event;
register_usb_composite_notifier(&pm_data->usb_composite_notifier);
+#endif
wake_lock_init(&pm_data->l2_wake, WAKE_LOCK_SUSPEND, pm_data->name);
wake_lock_init(&pm_data->boot_wake, WAKE_LOCK_SUSPEND, "mdm_boot");
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index 83638a7..9fd6c74 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -424,6 +424,23 @@ static void ctrl_write_callback(struct urb *urb)
usb_autopm_put_interface_async(dev->intf);
}
+static int usb_anchor_len(struct usb_anchor *anchor)
+{
+ unsigned long flags;
+ struct urb *urb;
+ int len = 0;
+
+ spin_lock_irqsave(&anchor->lock, flags);
+ list_for_each_entry(urb, &anchor->urb_list, anchor_list) {
+ len++;
+ }
+ spin_unlock_irqrestore(&anchor->lock, flags);
+
+ pr_debug("%s:%d", __func__, len);
+
+ return len;
+}
+
static int rmnet_usb_ctrl_write(struct rmnet_ctrl_dev *dev, char *buf,
size_t size)
{
@@ -889,6 +906,9 @@ int rmnet_usb_ctrl_probe(struct usb_interface *intf,
dev->tx_ctrl_in_req_cnt = 0;
dev->tx_block = false;
+ /* give margin before send DTR high */
+ msleep(20);
+ pr_info("%s: send DTR high to Modem\n", __func__);
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
USB_CDC_REQ_SET_CONTROL_LINE_STATE,
(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE),
@@ -941,9 +961,12 @@ int rmnet_usb_ctrl_probe(struct usb_interface *intf,
ctl_msg_dbg_mask = MSM_USB_CTL_DUMP_BUFFER;
- dev->reset_notifier_block.notifier_call = rmnet_ctrl_reset_notifier;
- blocking_notifier_chain_register(&mdm_reset_notifier_list,
+ if (!ret) {
+ dev->reset_notifier_block.notifier_call =
+ rmnet_ctrl_reset_notifier;
+ blocking_notifier_chain_register(&mdm_reset_notifier_list,
&dev->reset_notifier_block);
+ }
return ret;
}
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index 6333dd0..0b30618 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -575,6 +575,11 @@ static int rmnet_usb_probe(struct usb_interface *iface,
/* allow modem to wake up suspended system */
device_set_wakeup_enable(&udev->dev, 1);
out:
+#ifdef CONFIG_MDM_HSIC_PM
+ /* make reset or dump at 2nd enumeration fail */
+ if (status < 0)
+ mdm_force_fatal();
+#endif
return status;
}