Merge "msm: 8064: Add sleep status data for 8064 and 8930" into msm-3.0
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index f760e7b..fc89a11 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -148,7 +148,6 @@
};
VREG_CONSUMERS(S1) = {
REGULATOR_SUPPLY("8038_s1", NULL),
- REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_otg"),
REGULATOR_SUPPLY("riva_vddcx", "wcnss_wlan.0"),
};
VREG_CONSUMERS(S2) = {
@@ -192,6 +191,7 @@
};
VREG_CONSUMERS(VDD_DIG_CORNER) = {
REGULATOR_SUPPLY("vdd_dig_corner", NULL),
+ REGULATOR_SUPPLY("hsusb_vdd_dig", "msm_otg"),
};
#define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
diff --git a/arch/arm/mach-msm/board-9615-gpiomux.c b/arch/arm/mach-msm/board-9615-gpiomux.c
index c600d53..0e18918 100644
--- a/arch/arm/mach-msm/board-9615-gpiomux.c
+++ b/arch/arm/mach-msm/board-9615-gpiomux.c
@@ -105,20 +105,6 @@
};
#endif
-static struct gpiomux_setting wlan_active_config = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- .dir = GPIOMUX_OUT_LOW,
-};
-
-static struct gpiomux_setting wlan_suspend_config = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- .dir = GPIOMUX_IN,
-};
-
static struct msm_gpiomux_config msm9615_audio_codec_configs[] __initdata = {
{
.gpio = 24,
@@ -320,24 +306,6 @@
};
#endif
-static struct msm_gpiomux_config msm9615_wlan_configs[] __initdata = {
- {
- .gpio = 2, /* WLAN_PM_ENABLE */
- .settings = {
- [GPIOMUX_ACTIVE] = &wlan_active_config,
- [GPIOMUX_SUSPENDED] = &wlan_suspend_config,
- },
- },
- {
- .gpio = 21, /* WLAN_RESET_N */
- .settings = {
- [GPIOMUX_ACTIVE] = &wlan_active_config,
- [GPIOMUX_SUSPENDED] = &wlan_suspend_config,
- },
- },
-};
-
-
int __init msm9615_init_gpiomux(void)
{
int rc;
@@ -364,9 +332,6 @@
msm_gpiomux_install(msm9615_audio_codec_configs,
ARRAY_SIZE(msm9615_audio_codec_configs));
- msm_gpiomux_install(msm9615_wlan_configs,
- ARRAY_SIZE(msm9615_wlan_configs));
-
#ifdef CONFIG_FB_MSM_EBI2
msm_gpiomux_install(msm9615_ebi2_lcdc_configs,
ARRAY_SIZE(msm9615_ebi2_lcdc_configs));
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index c1e4118..6b42325 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -354,6 +354,7 @@
static void smd_fake_irq_handler(unsigned long arg);
static void smsm_cb_snapshot(uint32_t use_wakelock);
+static struct workqueue_struct *smsm_cb_wq;
static void notify_smsm_cb_clients_worker(struct work_struct *work);
static DECLARE_WORK(smsm_cb_work, notify_smsm_cb_clients_worker);
static DEFINE_MUTEX(smsm_lock);
@@ -2365,6 +2366,13 @@
return -ENOMEM;
}
+ smsm_cb_wq = create_singlethread_workqueue("smsm_cb_wq");
+ if (!smsm_cb_wq) {
+ pr_err("%s: smsm_cb_wq creation failed\n", __func__);
+ kfree(smsm_states);
+ return -EFAULT;
+ }
+
mutex_lock(&smsm_lock);
for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
state_info = &smsm_states[n];
@@ -2540,7 +2548,7 @@
goto restore_snapshot_count;
}
- schedule_work(&smsm_cb_work);
+ queue_work(smsm_cb_wq, &smsm_cb_work);
return;
restore_snapshot_count:
@@ -2832,7 +2840,6 @@
state_info->last_value = new_state;
}
}
- mutex_unlock(&smsm_lock);
/* read wakelock flag */
ret = kfifo_out(&smsm_snapshot_fifo, &use_wakelock,
@@ -2840,8 +2847,10 @@
if (ret != sizeof(use_wakelock)) {
pr_err("%s: snapshot underflow %d\n",
__func__, ret);
+ mutex_unlock(&smsm_lock);
return;
}
+ mutex_unlock(&smsm_lock);
if (use_wakelock) {
spin_lock_irqsave(&smsm_snapshot_count_lock, flags);
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index de9e2c4..84789ef 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -54,7 +54,7 @@
if (!offset) {
if ((carveout_heap->total_size -
- carveout_heap->allocated_bytes) > size)
+ carveout_heap->allocated_bytes) >= size)
pr_debug("%s: heap %s has enough memory (%lx) but"
" the allocation of size %lx still failed."
" Memory is probably fragmented.",
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index c8db702..24ea571 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -511,6 +511,8 @@
KGSL_DRV_ERR(device, "snapshot created at va %p pa %lx size %d\n",
device->snapshot, __pa(device->snapshot),
device->snapshot_size);
+ if (hang)
+ sysfs_notify(&device->snapshot_kobj, NULL, "timestamp");
return 0;
}
EXPORT_SYMBOL(kgsl_device_snapshot);
diff --git a/drivers/net/msm_rmnet_sdio.c b/drivers/net/msm_rmnet_sdio.c
index 883c649..acdffd1 100644
--- a/drivers/net/msm_rmnet_sdio.c
+++ b/drivers/net/msm_rmnet_sdio.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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
@@ -78,6 +78,7 @@
#endif
struct sk_buff *skb;
spinlock_t lock;
+ spinlock_t tx_queue_lock;
struct tasklet_struct tsklt;
u32 operation_mode; /* IOCTL specified mode (protocol, QoS header) */
uint8_t device_up;
@@ -361,6 +362,7 @@
static void sdio_write_done(void *dev, struct sk_buff *skb)
{
struct rmnet_private *p = netdev_priv(dev);
+ unsigned long flags;
if (skb)
dev_kfree_skb_any(skb);
@@ -368,12 +370,14 @@
if (!p->in_reset) {
DBG1("%s: write complete skb=%p\n", __func__, skb);
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
if (netif_queue_stopped(dev) &&
msm_sdio_dmux_is_ch_low(p->ch_id)) {
DBG0("%s: Low WM hit, waking queue=%p\n",
__func__, skb);
netif_wake_queue(dev);
}
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
} else {
DBG1("%s: write in reset skb=%p\n", __func__, skb);
}
@@ -454,6 +458,7 @@
static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rmnet_private *p = netdev_priv(dev);
+ unsigned long flags;
if (netif_queue_stopped(dev)) {
pr_err("[%s]fatal: rmnet_xmit called when "
@@ -463,10 +468,12 @@
_rmnet_xmit(skb, dev);
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
if (msm_sdio_dmux_is_ch_full(p->ch_id)) {
netif_stop_queue(dev);
DBG0("%s: High WM hit, stopping queue=%p\n", __func__, skb);
}
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
return 0;
}
@@ -667,6 +674,7 @@
p->operation_mode = RMNET_MODE_LLP_ETH;
p->ch_id = n;
spin_lock_init(&p->lock);
+ spin_lock_init(&p->tx_queue_lock);
#ifdef CONFIG_MSM_RMNET_DEBUG
p->timeout_us = timeout_us;
p->wakeups_xmit = p->wakeups_rcv = 0;
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index ae3f934..d4c2823 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -13,6 +13,8 @@
#include <linux/mii.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/usb.h>
#include <linux/usb/usbnet.h>
#include <linux/msm_rmnet.h>
@@ -416,6 +418,86 @@
dev->watchdog_timeo = 1000; /* 10 seconds? */
}
+static int rmnet_usb_data_status(struct seq_file *s, void *unused)
+{
+ struct usbnet *unet = s->private;
+
+ seq_printf(s, "RMNET_MODE_LLP_IP: %d\n",
+ test_bit(RMNET_MODE_LLP_IP, &unet->data[0]));
+ seq_printf(s, "RMNET_MODE_LLP_ETH: %d\n",
+ test_bit(RMNET_MODE_LLP_ETH, &unet->data[0]));
+ seq_printf(s, "RMNET_MODE_QOS: %d\n",
+ test_bit(RMNET_MODE_QOS, &unet->data[0]));
+ seq_printf(s, "Net MTU: %u\n", unet->net->mtu);
+ seq_printf(s, "rx_urb_size: %u\n", unet->rx_urb_size);
+ seq_printf(s, "rx skb q len: %u\n", unet->rxq.qlen);
+ seq_printf(s, "rx skb done q len: %u\n", unet->done.qlen);
+ seq_printf(s, "rx errors: %lu\n", unet->net->stats.rx_errors);
+ seq_printf(s, "rx over errors: %lu\n",
+ unet->net->stats.rx_over_errors);
+ seq_printf(s, "rx length errors: %lu\n",
+ unet->net->stats.rx_length_errors);
+ seq_printf(s, "rx packets: %lu\n", unet->net->stats.rx_packets);
+ seq_printf(s, "rx bytes: %lu\n", unet->net->stats.rx_bytes);
+ seq_printf(s, "tx skb q len: %u\n", unet->txq.qlen);
+ seq_printf(s, "tx errors: %lu\n", unet->net->stats.tx_errors);
+ seq_printf(s, "tx packets: %lu\n", unet->net->stats.tx_packets);
+ seq_printf(s, "tx bytes: %lu\n", unet->net->stats.tx_bytes);
+ seq_printf(s, "suspend count: %d\n", unet->suspend_count);
+ seq_printf(s, "EVENT_DEV_OPEN: %d\n",
+ test_bit(EVENT_DEV_OPEN, &unet->flags));
+ seq_printf(s, "EVENT_TX_HALT: %d\n",
+ test_bit(EVENT_TX_HALT, &unet->flags));
+ seq_printf(s, "EVENT_RX_HALT: %d\n",
+ test_bit(EVENT_RX_HALT, &unet->flags));
+ seq_printf(s, "EVENT_RX_MEMORY: %d\n",
+ test_bit(EVENT_RX_MEMORY, &unet->flags));
+ seq_printf(s, "EVENT_DEV_ASLEEP: %d\n",
+ test_bit(EVENT_DEV_ASLEEP, &unet->flags));
+
+ return 0;
+}
+
+static int rmnet_usb_data_status_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, rmnet_usb_data_status, inode->i_private);
+}
+
+const struct file_operations rmnet_usb_data_fops = {
+ .open = rmnet_usb_data_status_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry *rmnet_usb_data_dbg_root;
+static int rmnet_usb_data_debugfs_init(struct usbnet *unet)
+{
+ struct dentry *rmnet_usb_data_dentry;
+
+ rmnet_usb_data_dbg_root = debugfs_create_dir(unet->net->name, NULL);
+
+ if (!rmnet_usb_data_dbg_root || IS_ERR(rmnet_usb_data_dbg_root))
+ return -ENODEV;
+
+ rmnet_usb_data_dentry = debugfs_create_file("status",
+ S_IRUGO | S_IWUSR,
+ rmnet_usb_data_dbg_root, unet,
+ &rmnet_usb_data_fops);
+
+ if (!rmnet_usb_data_dentry) {
+ debugfs_remove_recursive(rmnet_usb_data_dbg_root);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void rmnet_usb_data_debugfs_cleanup(void)
+{
+ debugfs_remove_recursive(rmnet_usb_data_dbg_root);
+}
+
static int rmnet_usb_probe(struct usb_interface *iface,
const struct usb_device_id *prod)
{
@@ -469,6 +551,10 @@
if (status)
goto out;
+ status = rmnet_usb_data_debugfs_init(unet);
+ if (status)
+ dev_dbg(&udev->dev, "mode debugfs file is not available\n");
+
/* allow modem to wake up suspended system */
device_set_wakeup_enable(&udev->dev, 1);
out:
@@ -484,6 +570,8 @@
udev = interface_to_usbdev(intf);
device_set_wakeup_enable(&udev->dev, 0);
+ rmnet_usb_data_debugfs_cleanup();
+
unet = usb_get_intfdata(intf);
if (!unet) {
dev_err(&udev->dev, "%s:data device not found\n", __func__);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index b428bd2..2f7e250 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -45,6 +45,7 @@
#include <mach/clk.h>
#include <mach/msm_xo.h>
#include <mach/msm_bus.h>
+#include <mach/rpm-regulator.h>
#define MSM_USB_BASE (motg->regs)
#define DRIVER_NAME "msm_otg"
@@ -61,6 +62,7 @@
#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
+#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
@@ -104,53 +106,25 @@
#endif
}
-static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
-{
- int ret = 0;
+enum usb_vdd_value {
+ VDD_NONE = 0,
+ VDD_MIN,
+ VDD_MAX,
+ VDD_VAL_MAX,
+};
- if (init) {
- hsusb_vddcx = devm_regulator_get(motg->otg.dev, "HSUSB_VDDCX");
- if (IS_ERR(hsusb_vddcx)) {
- dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
- return PTR_ERR(hsusb_vddcx);
- }
-
- ret = regulator_set_voltage(hsusb_vddcx,
- USB_PHY_VDD_DIG_VOL_MIN,
- USB_PHY_VDD_DIG_VOL_MAX);
- if (ret) {
- dev_err(motg->otg.dev, "unable to set the voltage "
- "for hsusb vddcx\n");
- return ret;
- }
-
- ret = regulator_enable(hsusb_vddcx);
- if (ret) {
- regulator_set_voltage(hsusb_vddcx, 0,
- USB_PHY_VDD_DIG_VOL_MIN);
- dev_err(motg->otg.dev, "unable to enable the hsusb vddcx\n");
- return ret;
- }
-
- } else {
-
- ret = regulator_disable(hsusb_vddcx);
- if (ret) {
- dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
- return ret;
- }
-
- ret = regulator_set_voltage(hsusb_vddcx, 0,
- USB_PHY_VDD_DIG_VOL_MIN);
- if (ret) {
- dev_err(motg->otg.dev, "unable to set the voltage"
- "for hsusb vddcx\n");
- return ret;
- }
- }
-
- return ret;
-}
+static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
+ { /* VDD_CX CORNER Voting */
+ [VDD_NONE] = RPM_VREG_CORNER_NONE,
+ [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
+ [VDD_MAX] = RPM_VREG_CORNER_HIGH,
+ },
+ { /* VDD_CX Voltage Voting */
+ [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
+ [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
+ [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
+ },
+};
static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
{
@@ -198,15 +172,13 @@
#define USB_PHY_SUSP_DIG_VOL 500000
static int msm_hsusb_config_vddcx(int high)
{
- int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+ struct msm_otg *motg = the_msm_otg;
+ enum usb_vdd_type vdd_type = motg->vdd_type;
+ int max_vol = vdd_val[vdd_type][VDD_MAX];
int min_vol;
int ret;
- if (high)
- min_vol = USB_PHY_VDD_DIG_VOL_MIN;
- else
- min_vol = USB_PHY_SUSP_DIG_VOL;
-
+ min_vol = vdd_val[vdd_type][!!high];
ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
if (ret) {
pr_err("%s: unable to set the voltage for regulator "
@@ -3321,22 +3293,33 @@
clk_prepare_enable(motg->pclk);
- ret = msm_hsusb_init_vddcx(motg, 1);
- if (ret) {
- dev_err(&pdev->dev, "hsusb vddcx init failed\n");
- goto devote_xo_handle;
+ motg->vdd_type = VDDCX_CORNER;
+ hsusb_vddcx = devm_regulator_get(motg->otg.dev, "hsusb_vdd_dig");
+ if (IS_ERR(hsusb_vddcx)) {
+ hsusb_vddcx = devm_regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+ if (IS_ERR(hsusb_vddcx)) {
+ dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+ goto devote_xo_handle;
+ }
+ motg->vdd_type = VDDCX;
}
ret = msm_hsusb_config_vddcx(1);
if (ret) {
dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
- goto free_init_vddcx;
+ goto devote_xo_handle;
+ }
+
+ ret = regulator_enable(hsusb_vddcx);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
+ goto free_config_vddcx;
}
ret = msm_hsusb_ldo_init(motg, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
- goto free_init_vddcx;
+ goto free_hsusb_vddcx;
}
if (pdata->mhl_enable) {
@@ -3460,8 +3443,12 @@
msm_hsusb_ldo_enable(motg, 0);
free_ldo_init:
msm_hsusb_ldo_init(motg, 0);
-free_init_vddcx:
- msm_hsusb_init_vddcx(motg, 0);
+free_hsusb_vddcx:
+ regulator_disable(hsusb_vddcx);
+free_config_vddcx:
+ regulator_set_voltage(hsusb_vddcx,
+ vdd_val[motg->vdd_type][VDD_NONE],
+ vdd_val[motg->vdd_type][VDD_MAX]);
devote_xo_handle:
clk_disable_unprepare(motg->pclk);
msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
@@ -3535,7 +3522,10 @@
msm_xo_put(motg->xo_handle);
msm_hsusb_ldo_enable(motg, 0);
msm_hsusb_ldo_init(motg, 0);
- msm_hsusb_init_vddcx(motg, 0);
+ regulator_disable(hsusb_vddcx);
+ regulator_set_voltage(hsusb_vddcx,
+ vdd_val[motg->vdd_type][VDD_NONE],
+ vdd_val[motg->vdd_type][VDD_MAX]);
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index a731774..e84884c 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -149,6 +149,17 @@
};
/**
+ * Used different VDDCX voltage voting mechnism
+ * VDDCX_CORNER Vote for VDDCX Corner voltage
+ * VDDCX Vote for VDDCX Absolute voltage
+ */
+enum usb_vdd_type {
+ VDDCX_CORNER = 0,
+ VDDCX,
+ VDD_TYPE_MAX,
+};
+
+/**
* SPS Pipes direction.
*
* USB_TO_PEER_PERIPHERAL USB (as Producer) to other
@@ -342,6 +353,7 @@
unsigned long tmouts;
u8 active_tmout;
struct hrtimer timer;
+ enum usb_vdd_type vdd_type;
};
struct msm_hsic_host_platform_data {