void pil_put(void *peripheral_handle)
{
	struct pil_device *pil_d, *pil = peripheral_handle;

	if (IS_ERR_OR_NULL(pil))
		return;

	printk("%s: %s(%d) for %s\n", __func__, current->comm, current->pid, pil->desc->name);
	mutex_lock(&pil->lock);
	if (WARN(!pil->count, "%s: %s: Reference count mismatch\n",
			pil->desc->name, __func__))
		goto err_out;
#ifdef CONFIG_MACH_VILLEC2
	if (pil->count == 1)
		goto unlock;
#endif
	if (!--pil->count)
		pil_shutdown(pil);
#ifdef CONFIG_MACH_VILLEC2
unlock:
#endif
	mutex_unlock(&pil->lock);

	pil_d = find_peripheral(pil->desc->depends_on);
	module_put(pil->owner);
	if (pil_d) {
		pil_put(pil_d);
		put_device(&pil_d->dev);
	}
	put_device(&pil->dev);
	return;
err_out:
	mutex_unlock(&pil->lock);
	return;
}
Example #2
0
static void smd_tty_close(struct tty_struct *tty, struct file *f)
{
	struct smd_tty_info *info = tty->driver_data;
	unsigned long flags;

	if (info == 0)
		return;

	mutex_lock(&smd_tty_lock);
	if (--info->open_count == 0) {
		spin_lock_irqsave(&info->reset_lock, flags);
		info->is_open = 0;
		spin_unlock_irqrestore(&info->reset_lock, flags);
		if (info->tty) {
			tasklet_kill(&info->tty_tsklt);
			wake_lock_destroy(&info->wake_lock);
			info->tty = 0;
		}
		tty->driver_data = 0;
		del_timer(&info->buf_req_timer);
		if (info->ch) {
			smd_close(info->ch);
			info->ch = 0;
			pil_put(info->pil);
		}
	}
	mutex_unlock(&smd_tty_lock);
}
Example #3
0
void ddl_fw_release(struct ddl_buf_addr *dram_base)
{
	void *cookie = dram_base->pil_cookie;
	if (res_trk_is_cp_enabled() &&
		res_trk_check_for_sec_session()) {
		res_trk_close_secure_session();
		if (IS_ERR_OR_NULL(cookie)) {
			pr_err("Invalid params");
		return;
	}
	if (res_trk_enable_footswitch()) {
		pr_err("Failed to enable footswitch");
		return;
	}
	if (res_trk_enable_iommu_clocks()) {
		res_trk_disable_footswitch();
		pr_err("Failed to enable iommu clocks\n");
		return;
	}
	pil_put(cookie);
	if (res_trk_disable_iommu_clocks())
		pr_err("Failed to disable iommu clocks\n");
	if (res_trk_disable_footswitch())
		pr_err("Failed to disable footswitch\n");
	} else {
	if (res_trk_check_for_sec_session())
		res_trk_close_secure_session();
		res_trk_release_fw_addr();
	}
}
/**
 * pil_put() - Inform PIL the peripheral no longer needs to be active
 * @peripheral_handle: pointer from a previous call to pil_get()
 *
 * This doesn't imply that a peripheral is shutdown or in reset since another
 * driver could be using the peripheral.
 */
void pil_put(void *peripheral_handle)
{
	struct pil_device *pil_d, *pil = peripheral_handle;

	if (IS_ERR_OR_NULL(pil))
		return;

	mutex_lock(&pil->lock);
	if (WARN(!pil->count, "%s: Reference count mismatch\n", __func__))
		goto err_out;
	if (!--pil->count)
		pil_shutdown(pil);
	mutex_unlock(&pil->lock);

	pil_d = find_peripheral(pil->desc->depends_on);
	module_put(pil->owner);
	if (pil_d) {
		pil_put(pil_d);
		put_device(&pil_d->dev);
	}
	put_device(&pil->dev);
	return;
err_out:
	mutex_unlock(&pil->lock);
	return;
}
static void msm_rmnet_unload_modem(void *pil)
{
	/* printk("%s() ++\n", __func__); */
	printk("pil: %s", ( pil? "true" : "false" ));
	if (pil)
		pil_put(pil);
	/* printk("%s() --\n", __func__); */
}
Example #6
0
static int adsp_loader_remove(struct platform_device *pdev)
{
	struct adsp_loader_private *priv;

	priv = platform_get_drvdata(pdev);
	pil_put(priv->pil_h);
	pr_info("%s: Q6/ADSP image is unloaded\n", __func__);

	return 0;
}
/**
 * pil_get() - Load a peripheral into memory and take it out of reset
 * @name: pointer to a string containing the name of the peripheral to load
 *
 * This function returns a pointer if it succeeds. If an error occurs an
 * ERR_PTR is returned.
 *
 * If PIL is not enabled in the kernel, the value %NULL will be returned.
 */
void *pil_get(const char *name)
{
	int ret;
	struct pil_device *pil;
	struct pil_device *pil_d;
	void *retval;

	if (!name)
		return NULL;

	pil = retval = find_peripheral(name);
	if (!pil)
		return ERR_PTR(-ENODEV);
	if (!try_module_get(pil->owner)) {
		put_device(&pil->dev);
		return ERR_PTR(-ENODEV);
	}

	pil_d = pil_get(pil->desc->depends_on);
	if (IS_ERR(pil_d)) {
		retval = pil_d;
		goto err_depends;
	}

	mutex_lock(&pil->lock);
	if (!pil->count) {
		ret = load_image(pil);
		if (ret) {
			retval = ERR_PTR(ret);
			goto err_load;
		}
	}
	pil->count++;
	pil_set_state(pil, PIL_ONLINE);
/* LGE_CHANGE */
#ifdef CONFIG_MACH_LGE
	//LGE_CNAHGES : Add log for debugging watchdog reset.
	//ALRAN
	//pr_err("ALRAN: %s, count %d, pid %d, %s\n", __func__, pil->count, current->pid, current->comm);
#endif

	mutex_unlock(&pil->lock);
out:
	return retval;
err_load:
	mutex_unlock(&pil->lock);
	pil_put(pil_d);
err_depends:
	put_device(&pil->dev);
	module_put(pil->owner);
	goto out;
}
/**
 * pil_get() - Load a peripheral into memory and take it out of reset
 * @name: pointer to a string containing the name of the peripheral to load
 *
 * This function returns a pointer if it succeeds. If an error occurs an
 * ERR_PTR is returned.
 *
 * If PIL is not enabled in the kernel, the value %NULL will be returned.
 */
void *pil_get(const char *name)
{
	int ret;
	struct pil_device *pil;
	struct pil_device *pil_d;
	void *retval;

	if (!name)
		return NULL;

	pil = retval = find_peripheral(name);
	if (!pil)
		return ERR_PTR(-ENODEV);
	if (!try_module_get(pil->owner)) {
		put_device(&pil->dev);
		return ERR_PTR(-ENODEV);
	}

	pil_d = pil_get(pil->desc->depends_on);
	if (IS_ERR(pil_d)) {
		retval = pil_d;
		goto err_depends;
	}

	if (pil->count <= 1) {
		printk(KERN_DEBUG "%s:%s, count:%d, pid:%d, %s\n", __func__,
				name, pil->count, current->pid, current->comm);
	}

	mutex_lock(&pil->lock);
	if (!pil->count) {
		ret = load_image(pil);
		if (ret) {
			retval = ERR_PTR(ret);
			goto err_load;
		}
	}
	pil->count++;
	pil_set_state(pil, PIL_ONLINE);
	mutex_unlock(&pil->lock);
out:
	return retval;
err_load:
	mutex_unlock(&pil->lock);
	pil_put(pil_d);
err_depends:
	put_device(&pil->dev);
	module_put(pil->owner);
	goto out;
}
Example #9
0
static void __exit wcnss_wlan_exit(void)
{
	if (penv) {
		if (penv->pil)
			pil_put(penv->pil);


		kfree(penv);
		penv = NULL;
	}

	platform_driver_unregister(&wcnss_wlan_ctrl_driver);
	platform_driver_unregister(&wcnss_wlan_driver);
}
Example #10
0
static void __exit wcnss_wlan_exit(void)
{
	if (penv) {
		if (penv->pil)
			pil_put(penv->pil);


		kfree(penv);
		penv = NULL;
	}

	platform_driver_unregister(&wcnss_wlan_ctrl_driver);
	platform_driver_unregister(&wcnss_wlan_driver);
#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
	wcnss_prealloc_deinit();
#endif
}
Example #11
0
static void __exit wcnss_wlan_exit(void)
{
	if (penv) {
		if (penv->pil)
			pil_put(penv->pil);


		kfree(penv);
		penv = NULL;
	}

	platform_driver_unregister(&wcnss_wlan_ctrl_driver);
	platform_driver_unregister(&wcnss_wlan_driver);
	
#ifdef FEATURE_PANTECH_WLAN_QCOM_PATCH  //20120726 thkim_wifi the patch to prevent memory fragmentation when the wlan host driver loads.(Case Number: 00924847)
	wcnss_prealloc_deinit();
#endif
	
}
/**
 * pil_put() - Inform PIL the peripheral no longer needs to be active
 * @peripheral_handle: pointer from a previous call to pil_get()
 *
 * This doesn't imply that a peripheral is shutdown or in reset since another
 * driver could be using the peripheral.
 */
void pil_put(void *peripheral_handle)
{
	struct pil_device *pil_d, *pil = peripheral_handle;

	if (IS_ERR_OR_NULL(pil))
		return;

	mutex_lock(&pil->lock);
	if (WARN(!pil->count, "%s: %s: Reference count mismatch\n",
			pil->desc->name, __func__))
		goto err_out;

/* LGE_CHANGE */
#if CONFIG_MACH_LGE
	//LGE_CHANES : Workaround code for pereventing watchdog reset.(QCT Patch)
	if (!--pil->count){
		if (!!strncmp("modem", pil->desc->name, 5)) //ALRAN : LG FX3 - allow pil_put only for not modem*
			pil_shutdown(pil);
		else{
			pr_err("ALRAN: pil %s shutdown, but block it\n", pil->desc->name);
			pil->count++;
		}
	}
#else
	if (!--pil->count)
		pil_shutdown(pil);
#endif

	mutex_unlock(&pil->lock);

	pil_d = find_peripheral(pil->desc->depends_on);
	module_put(pil->owner);
	if (pil_d) {
		pil_put(pil_d);
		put_device(&pil_d->dev);
	}
	put_device(&pil->dev);
	return;
err_out:
	mutex_unlock(&pil->lock);
	return;
}
/**
 * pil_put() - Inform PIL the peripheral no longer needs to be active
 * @peripheral_handle: pointer from a previous call to pil_get()
 *
 * This doesn't imply that a peripheral is shutdown or in reset since another
 * driver could be using the peripheral.
 */
void pil_put(void *peripheral_handle)
{
	struct pil_device *pil_d, *pil = peripheral_handle;

	if (IS_ERR_OR_NULL(pil))
		return;

	if (pil->count <= 1) {
		printk(KERN_DEBUG "%s:%s, count:%d, pid:%d, %s\n", __func__,
				pil->desc->name, pil->count, current->pid,
				current->comm);
	}
	mutex_lock(&pil->lock);
	if (WARN(!pil->count, "%s: %s: Reference count mismatch\n",
			pil->desc->name, __func__))
		goto err_out;
	if (!strncmp(pil->desc->name, "modem", 5)) {
		if (pil->count == 1)
			goto unlock;
	}
	if (!--pil->count) {
		pil_shutdown(pil);
		WARN_ON(1);
	}
unlock:
	mutex_unlock(&pil->lock);

	pil_d = find_peripheral(pil->desc->depends_on);
	module_put(pil->owner);
	if (pil_d) {
		pil_put(pil_d);
		put_device(&pil_d->dev);
	}
	put_device(&pil->dev);
	return;
err_out:
	mutex_unlock(&pil->lock);
	return;
}
static ssize_t msm_pil_debugfs_write(struct file *filp,
		const char __user *ubuf, size_t cnt, loff_t *ppos)
{
	struct pil_device *pil = filp->private_data;
	char buf[4];

	if (cnt > sizeof(buf))
		return -EINVAL;

	if (copy_from_user(&buf, ubuf, cnt))
		return -EFAULT;

	if (!strncmp(buf, "get", 3)) {
		if (IS_ERR(pil_get(pil->desc->name)))
			return -EIO;
	} else if (!strncmp(buf, "put", 3))
		pil_put(pil);
	else
		return -EINVAL;

	return cnt;
}
Example #15
0
static int
wcnss_trigger_config(struct platform_device *pdev)
{
	int ret;
	struct qcom_wcnss_opts *pdata;

	/* make sure we are only triggered once */
	if (penv->triggered)
		return 0;
	penv->triggered = 1;

	/* initialize the WCNSS device configuration */
	pdata = pdev->dev.platform_data;
	if (WCNSS_CONFIG_UNSPECIFIED == has_48mhz_xo)
		has_48mhz_xo = pdata->has_48mhz_xo;
	penv->wlan_config.use_48mhz_xo = has_48mhz_xo;

	penv->thermal_mitigation = 0;

	penv->gpios_5wire = platform_get_resource_byname(pdev, IORESOURCE_IO,
							"wcnss_gpios_5wire");

	/* allocate 5-wire GPIO resources */
	if (!penv->gpios_5wire) {
		dev_err(&pdev->dev, "insufficient IO resources\n");
		ret = -ENOENT;
		goto fail_gpio_res;
	}

	/* Configure 5 wire GPIOs */
	ret = wcnss_gpios_config(penv->gpios_5wire, true);
	if (ret) {
		dev_err(&pdev->dev, "WCNSS gpios config failed.\n");
		goto fail_gpio_res;
	}

	/* power up the WCNSS */
	ret = wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
					WCNSS_WLAN_SWITCH_ON);
	if (ret) {
		dev_err(&pdev->dev, "WCNSS Power-up failed.\n");
		goto fail_power;
	}

	/* trigger initialization of the WCNSS */
	penv->pil = pil_get(WCNSS_PIL_DEVICE);
	if (IS_ERR(penv->pil)) {
		dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
		ret = PTR_ERR(penv->pil);
		penv->pil = NULL;
		goto fail_pil;
	}

	/* allocate resources */
	penv->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
							"wcnss_mmio");
	penv->tx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
							"wcnss_wlantx_irq");
	penv->rx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
							"wcnss_wlanrx_irq");

	if (!(penv->mmio_res && penv->tx_irq_res && penv->rx_irq_res)) {
		dev_err(&pdev->dev, "insufficient resources\n");
		ret = -ENOENT;
		goto fail_res;
	}

	/* register sysfs entries */
	ret = wcnss_create_sysfs(&pdev->dev);
	if (ret)
		goto fail_sysfs;

	return 0;

fail_sysfs:
fail_res:
	if (penv->pil)
		pil_put(penv->pil);
fail_pil:
	wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
				WCNSS_WLAN_SWITCH_OFF);
fail_power:
	wcnss_gpios_config(penv->gpios_5wire, false);
fail_gpio_res:
	kfree(penv);
	penv = NULL;
	return ret;
}
Example #16
0
static int gss_release(struct inode *inode, struct file *filep)
{
	pil_put(gss_data.pil_handle);
	pr_debug("%s pil_put called on GSS\n", __func__);
	return 0;
}
static int
wcnss_trigger_config(struct platform_device *pdev)
{
    int ret;
    struct qcom_wcnss_opts *pdata;


    if (penv->triggered)
        return 0;
    penv->triggered = 1;


    pdata = pdev->dev.platform_data;
    if (WCNSS_CONFIG_UNSPECIFIED == has_48mhz_xo)
        has_48mhz_xo = pdata->has_48mhz_xo;
    penv->wlan_config.use_48mhz_xo = has_48mhz_xo;

    penv->thermal_mitigation = 0;

    penv->gpios_5wire = platform_get_resource_byname(pdev, IORESOURCE_IO,
                        "wcnss_gpios_5wire");


    if (!penv->gpios_5wire) {
        dev_err(&pdev->dev, "insufficient IO resources\n");
        ret = -ENOENT;
        goto fail_gpio_res;
    }


    ret = wcnss_gpios_config(penv->gpios_5wire, true);
    if (ret) {
        dev_err(&pdev->dev, "WCNSS gpios config failed.\n");
        goto fail_gpio_res;
    }


    ret = wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
                           WCNSS_WLAN_SWITCH_ON);
    if (ret) {
        dev_err(&pdev->dev, "WCNSS Power-up failed.\n");
        goto fail_power;
    }


    penv->pil = pil_get(WCNSS_PIL_DEVICE);
    if (IS_ERR(penv->pil)) {
        dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
        ret = PTR_ERR(penv->pil);
        penv->pil = NULL;
        goto fail_pil;
    }


    penv->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                     "wcnss_mmio");
    penv->tx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
                       "wcnss_wlantx_irq");
    penv->rx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
                       "wcnss_wlanrx_irq");

    if (!(penv->mmio_res && penv->tx_irq_res && penv->rx_irq_res)) {
        dev_err(&pdev->dev, "insufficient resources\n");
        ret = -ENOENT;
        goto fail_res;
    }


    ret = wcnss_create_sysfs(&pdev->dev);
    if (ret)
        goto fail_sysfs;

    wake_lock_init(&penv->wcnss_wake_lock, WAKE_LOCK_SUSPEND, "wcnss");

    penv->msm_wcnss_base = ioremap(MSM_RIVA_PHYS, SZ_256);
    if (!penv->msm_wcnss_base) {
        pr_err("%s: ioremap wcnss physical failed\n", __func__);
        goto fail_wake;
    }

    return 0;

fail_wake:
    wake_lock_destroy(&penv->wcnss_wake_lock);

fail_sysfs:
fail_res:
    if (penv->pil)
        pil_put(penv->pil);
fail_pil:
    wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
                     WCNSS_WLAN_SWITCH_OFF);
fail_power:
    wcnss_gpios_config(penv->gpios_5wire, false);
fail_gpio_res:
    kfree(penv);
    penv = NULL;
    return ret;
}
Example #18
0
static int smd_tty_open(struct tty_struct *tty, struct file *f)
{
	int res = 0;
	unsigned int n = tty->index;
	struct smd_tty_info *info;
	const char *peripheral = NULL;


	if (n >= MAX_SMD_TTYS || !smd_tty[n].smd)
		return -ENODEV;

	info = smd_tty + n;

	mutex_lock(&smd_tty_lock);
	tty->driver_data = info;

	if (info->open_count++ == 0) {
		peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
		if (peripheral) {
			info->pil = pil_get(peripheral);
			if (IS_ERR(info->pil)) {
				res = PTR_ERR(info->pil);
				goto out;
			}

			/* Wait for the modem SMSM to be inited for the SMD
			 * Loopback channel to be allocated at the modem. Since
			 * the wait need to be done atmost once, using msleep
			 * doesn't degrade the performance.
			 */
			if (n == LOOPBACK_IDX) {
				if (!is_modem_smsm_inited())
					msleep(5000);
				smsm_change_state(SMSM_APPS_STATE,
					0, SMSM_SMD_LOOPBACK);
				msleep(100);
			}


			/*
			 * Wait for a channel to be allocated so we know
			 * the modem is ready enough.
			 */
			if (smd_tty_modem_wait) {
				res = wait_for_completion_interruptible_timeout(
					&info->ch_allocated,
					msecs_to_jiffies(smd_tty_modem_wait *
									1000));

				if (res == 0) {
					pr_err("Timed out waiting for SMD"
								" channel\n");
					res = -ETIMEDOUT;
					goto release_pil;
				} else if (res < 0) {
					pr_err("Error waiting for SMD channel:"
									" %d\n",
						res);
					goto release_pil;
				}

				res = 0;
			}
		}


		info->tty = tty;
		tasklet_init(&info->tty_tsklt, smd_tty_read,
			     (unsigned long)info);
		wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
				smd_tty[n].smd->port_name);
		if (!info->ch) {
			res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
							smd_tty[n].smd->edge,
							&info->ch, info,
							smd_tty_notify);
			if (res < 0) {
				pr_err("%s: %s open failed %d\n", __func__,
					smd_tty[n].smd->port_name, res);
				goto release_pil;
			}

			res = wait_event_interruptible_timeout(
				info->ch_opened_wait_queue,
				info->is_open, (2 * HZ));
			if (res == 0)
				res = -ETIMEDOUT;
			if (res < 0) {
				pr_err("%s: wait for %s smd_open failed %d\n",
					__func__, smd_tty[n].smd->port_name,
					res);
				goto release_pil;
			}
			res = 0;
		}
	}

release_pil:
	if (res < 0)
		pil_put(info->pil);
	else
		smd_disable_read_intr(info->ch);
out:
	mutex_unlock(&smd_tty_lock);

	return res;
}
Example #19
0
static int
wcnss_trigger_config(struct platform_device *pdev)
{
	int ret;
	struct qcom_wcnss_opts *pdata;
	unsigned long wcnss_phys_addr;
	int size = 0;
	int has_pronto_hw = of_property_read_bool(pdev->dev.of_node,
									"qcom,has_pronto_hw");

	/* make sure we are only triggered once */
	if (penv->triggered)
		return 0;
	penv->triggered = 1;

	/* initialize the WCNSS device configuration */
	pdata = pdev->dev.platform_data;
	if (WCNSS_CONFIG_UNSPECIFIED == has_48mhz_xo) {
		if (has_pronto_hw) {
			has_48mhz_xo = of_property_read_bool(pdev->dev.of_node,
										"qcom,has_48mhz_xo");
			penv->wcnss_hw_type = WCNSS_PRONTO_HW;
		} else {
			penv->wcnss_hw_type = WCNSS_RIVA_HW;
			has_48mhz_xo = pdata->has_48mhz_xo;
		}
	}
	penv->wlan_config.use_48mhz_xo = has_48mhz_xo;

	penv->thermal_mitigation = 0;
	strlcpy(penv->wcnss_version, "INVALID", WCNSS_VERSION_LEN);

	/* Configure 5 wire GPIOs */
	if (!has_pronto_hw) {
		penv->gpios_5wire = platform_get_resource_byname(pdev,
					IORESOURCE_IO, "wcnss_gpios_5wire");

		/* allocate 5-wire GPIO resources */
		if (!penv->gpios_5wire) {
			dev_err(&pdev->dev, "insufficient IO resources\n");
			ret = -ENOENT;
			goto fail_gpio_res;
		}
		ret = wcnss_gpios_config(penv->gpios_5wire, true);
	} else
		ret = wcnss_pronto_gpios_config(&pdev->dev, true);

	if (ret) {
		dev_err(&pdev->dev, "WCNSS gpios config failed.\n");
		goto fail_gpio_res;
	}

	/* power up the WCNSS */
	ret = wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
					WCNSS_WLAN_SWITCH_ON);
	if (ret) {
		dev_err(&pdev->dev, "WCNSS Power-up failed.\n");
		goto fail_power;
	}

	/* trigger initialization of the WCNSS */
	penv->pil = pil_get(WCNSS_PIL_DEVICE);
	if (IS_ERR(penv->pil)) {
		dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
		ret = PTR_ERR(penv->pil);
		penv->pil = NULL;
		goto fail_pil;
	}

	/* allocate resources */
	penv->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
							"wcnss_mmio");
	penv->tx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
							"wcnss_wlantx_irq");
	penv->rx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
							"wcnss_wlanrx_irq");

	if (!(penv->mmio_res && penv->tx_irq_res && penv->rx_irq_res)) {
		dev_err(&pdev->dev, "insufficient resources\n");
		ret = -ENOENT;
		goto fail_res;
	}
	INIT_WORK(&penv->wcnssctrl_rx_work, wcnssctrl_rx_handler);
	INIT_WORK(&penv->wcnssctrl_version_work, wcnss_send_version_req);

	wake_lock_init(&penv->wcnss_wake_lock, WAKE_LOCK_SUSPEND, "wcnss");

	if (wcnss_hardware_type() == WCNSS_PRONTO_HW) {
		size = 0x3000;
		wcnss_phys_addr = MSM_PRONTO_PHYS;
	} else {
		wcnss_phys_addr = MSM_RIVA_PHYS;
		size = SZ_256;
	}

	penv->msm_wcnss_base = ioremap(wcnss_phys_addr, size);
	if (!penv->msm_wcnss_base) {
		ret = -ENOMEM;
		pr_err("%s: ioremap wcnss physical failed\n", __func__);
		goto fail_wake;
	}

	return 0;

fail_wake:
	wake_lock_destroy(&penv->wcnss_wake_lock);
fail_res:
	if (penv->pil)
		pil_put(penv->pil);
fail_pil:
	wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
				WCNSS_WLAN_SWITCH_OFF);
fail_power:
	if (has_pronto_hw)
		wcnss_pronto_gpios_config(&pdev->dev, false);
	else
		wcnss_gpios_config(penv->gpios_5wire, false);
fail_gpio_res:
	kfree(penv);
	penv = NULL;
	return ret;
}
Example #20
0
/**
 *  Unload DSPS Firmware.
 */
static void dsps_unload(void)
{
	pr_debug("%s.\n", __func__);

	pil_put(drv->pil);
}
static int
wcnss_trigger_config(struct platform_device *pdev)
{
	int ret;
	struct qcom_wcnss_opts *pdata;

	/* make sure we are only triggered once */
	if (penv->triggered)
		return 0;
	penv->triggered = 1;

	/* initialize the WCNSS device configuration */
	pdata = pdev->dev.platform_data;
	if (WCNSS_CONFIG_UNSPECIFIED == has_48mhz_xo)
		has_48mhz_xo = pdata->has_48mhz_xo;
	penv->wlan_config.use_48mhz_xo = has_48mhz_xo;

	penv->thermal_mitigation = 0;
	strlcpy(penv->wcnss_version, "INVALID", WCNSS_VERSION_LEN);

	penv->gpios_5wire = platform_get_resource_byname(pdev, IORESOURCE_IO,
							"wcnss_gpios_5wire");

	/* allocate 5-wire GPIO resources */
	if (!penv->gpios_5wire) {
		dev_err(&pdev->dev, "insufficient IO resources\n");
		ret = -ENOENT;
		goto fail_gpio_res;
	}

	/* Configure 5 wire GPIOs */
	ret = wcnss_gpios_config(penv->gpios_5wire, true);
	if (ret) {
		dev_err(&pdev->dev, "WCNSS gpios config failed.\n");
		goto fail_gpio_res;
	}

	/* power up the WCNSS */
	ret = wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
					WCNSS_WLAN_SWITCH_ON);
	if (ret) {
		dev_err(&pdev->dev, "WCNSS Power-up failed.\n");
		goto fail_power;
	}

	/* trigger initialization of the WCNSS */
	penv->pil = pil_get(WCNSS_PIL_DEVICE);
	if (IS_ERR(penv->pil)) {
		dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
		ret = PTR_ERR(penv->pil);
		penv->pil = NULL;
		goto fail_pil;
	}

	/* allocate resources */
	penv->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
							"wcnss_mmio");
	penv->tx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
							"wcnss_wlantx_irq");
	penv->rx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
							"wcnss_wlanrx_irq");

	if (!(penv->mmio_res && penv->tx_irq_res && penv->rx_irq_res)) {
		dev_err(&pdev->dev, "insufficient resources\n");
		ret = -ENOENT;
		goto fail_res;
	}

	INIT_WORK(&penv->wcnssctrl_rx_work, wcnssctrl_rx_handler);
	INIT_WORK(&penv->wcnssctrl_version_work, wcnss_send_version_req);
	INIT_WORK(&penv->wcnssctrl_nvbin_dnld_work, wcnss_nvbin_dnld_main);

	wake_lock_init(&penv->wcnss_wake_lock, WAKE_LOCK_SUSPEND, "wcnss");

	penv->msm_wcnss_base = ioremap(MSM_RIVA_PHYS, SZ_256);
	if (!penv->msm_wcnss_base) {
		pr_err("%s: ioremap wcnss physical failed\n", __func__);
		goto fail_wake;
	}

	return 0;

fail_wake:
	wake_lock_destroy(&penv->wcnss_wake_lock);

fail_res:
	if (penv->pil)
		pil_put(penv->pil);
fail_pil:
	wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
				WCNSS_WLAN_SWITCH_OFF);
fail_power:
	wcnss_gpios_config(penv->gpios_5wire, false);
fail_gpio_res:
	kfree(penv);
	penv = NULL;
	return ret;
}
Example #22
0
/* Called in soft-irq context */
static void smd_net_data_handler(unsigned long arg)
{
    struct net_device *dev = (struct net_device *) arg;
    struct rmnet_private *p = netdev_priv(dev);
    struct sk_buff *skb;
    void *ptr = 0;
    int sz;
    u32 opmode = p->operation_mode;
//	unsigned long flags;
//   int max_package_size;
    for (;;) {
        sz = smd_cur_packet_size(p->ch);
        if (sz == 0) break;
        if (smd_read_avail(p->ch) < sz) break;
//ZTE_RIL_WANGCHENG_20110425 start
#ifdef CONFIG_ZTE_PLATFORM

        if (RMNET_IS_MODE_IP(opmode) ? (sz > ((dev->mtu > RMNET_DEFAULT_MTU_LEN)? dev->mtu:RMNET_DEFAULT_MTU_LEN)) :
                (sz > (((dev->mtu > RMNET_DEFAULT_MTU_LEN)? dev->mtu:RMNET_DEFAULT_MTU_LEN) + ETH_HLEN))) {
#else
        if (RMNET_IS_MODE_IP(opmode) ? (sz > dev->mtu) :
                (sz > (dev->mtu + ETH_HLEN))) {

#endif

            pr_err("rmnet_recv() discarding %d len (%d mtu)\n",
                   sz, RMNET_IS_MODE_IP(opmode) ?
                   dev->mtu : (dev->mtu + ETH_HLEN));
            ptr = 0;
        } else {
            skb = dev_alloc_skb(sz + NET_IP_ALIGN);
            if (skb == NULL) {
                pr_err("rmnet_recv() cannot allocate skb\n");
            } else {
                skb->dev = dev;
                skb_reserve(skb, NET_IP_ALIGN);
                ptr = skb_put(skb, sz);
                wake_lock_timeout(&p->wake_lock, HZ / 2);
                if (smd_read(p->ch, ptr, sz) != sz) {
                    pr_err("rmnet_recv() smd lied about avail?!");
                    ptr = 0;
                    dev_kfree_skb_irq(skb);
                } else {
                    /* Handle Rx frame format */
                    //spin_lock_irqsave(&p->lock, flags);
                    //opmode = p->operation_mode;
                    //spin_unlock_irqrestore(&p->lock, flags);

                    if (RMNET_IS_MODE_IP(opmode)) {
                        /* Driver in IP mode */
                        skb->protocol =
                            rmnet_ip_type_trans(skb, dev);
                    } else {
                        /* Driver in Ethernet mode */
                        skb->protocol =
                            eth_type_trans(skb, dev);
                    }
                    if (RMNET_IS_MODE_IP(opmode) ||
                            count_this_packet(ptr, skb->len)) {
#ifdef CONFIG_MSM_RMNET_DEBUG
                        p->wakeups_rcv +=
                            rmnet_cause_wakeup(p);
#endif
                        p->stats.rx_packets++;
                        p->stats.rx_bytes += skb->len;
                    }
                    netif_rx(skb);
                }
                continue;
            }
        }
        if (smd_read(p->ch, ptr, sz) != sz)
            pr_err("rmnet_recv() smd lied about avail?!");
    }
}

//ZTE_RIL_RJG_20101103 end

static DECLARE_TASKLET(smd_net_data_tasklet, smd_net_data_handler, 0);

static int _rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
    struct rmnet_private *p = netdev_priv(dev);
    smd_channel_t *ch = p->ch;
    int smd_ret;
    struct QMI_QOS_HDR_S *qmih;
    u32 opmode;
    unsigned long flags;

    /* For QoS mode, prepend QMI header and assign flow ID from skb->mark */
    spin_lock_irqsave(&p->lock, flags);
    opmode = p->operation_mode;
    spin_unlock_irqrestore(&p->lock, flags);

    if (RMNET_IS_MODE_QOS(opmode)) {
        qmih = (struct QMI_QOS_HDR_S *)
               skb_push(skb, sizeof(struct QMI_QOS_HDR_S));
        qmih->version = 1;
        qmih->flags = 0;
        qmih->flow_id = skb->mark;
    }

    dev->trans_start = jiffies;
    smd_ret = smd_write(ch, skb->data, skb->len);
    if (smd_ret != skb->len) {
        pr_err("%s: smd_write returned error %d", __func__, smd_ret);
        goto xmit_out;
    }

    if (RMNET_IS_MODE_IP(opmode) ||
            count_this_packet(skb->data, skb->len)) {
        p->stats.tx_packets++;
        p->stats.tx_bytes += skb->len;
#ifdef CONFIG_MSM_RMNET_DEBUG
        p->wakeups_xmit += rmnet_cause_wakeup(p);
#endif
    }

xmit_out:
    /* data xmited, safe to release skb */
    dev_kfree_skb_irq(skb);
    return 0;
}

static void _rmnet_resume_flow(unsigned long param)
{
    struct net_device *dev = (struct net_device *)param;
    struct rmnet_private *p = netdev_priv(dev);
    struct sk_buff *skb = NULL;
    unsigned long flags;

    /* xmit and enable the flow only once even if
       multiple tasklets were scheduled by smd_net_notify */
    spin_lock_irqsave(&p->lock, flags);
    if (p->skb && (smd_write_avail(p->ch) >= p->skb->len)) {
        skb = p->skb;
        p->skb = NULL;
        spin_unlock_irqrestore(&p->lock, flags);
        _rmnet_xmit(skb, dev);
        netif_wake_queue(dev);
    } else
        spin_unlock_irqrestore(&p->lock, flags);
}

static void msm_rmnet_unload_modem(void *pil)
{
    if (pil)
        pil_put(pil);
}

static void *msm_rmnet_load_modem(struct net_device *dev)
{
    void *pil;
    int rc;
    struct rmnet_private *p = netdev_priv(dev);

    pil = pil_get("modem");
    if (IS_ERR(pil))
        pr_err("%s: modem load failed\n", __func__);
    else if (msm_rmnet_modem_wait) {
        rc = wait_for_completion_interruptible_timeout(
                 &p->complete,
                 msecs_to_jiffies(msm_rmnet_modem_wait * 1000));
        if (!rc)
            rc = -ETIMEDOUT;
        if (rc < 0) {
            pr_err("%s: wait for rmnet port failed %d\n",
                   __func__, rc);
            msm_rmnet_unload_modem(pil);
            pil = ERR_PTR(rc);
        }
    }

    return pil;
}
static void msm_rpcrouter_unload_modem(void *pil)
{
	if (pil)
		pil_put(pil);
}
void *pil_get(const char *name)
{
	int ret;
	struct pil_device *pil;
	struct pil_device *pil_d;
	void *retval;
	static int modem_initialized = 0;
	int loop_count = 0;

	if (!name)
		return NULL;
	
	printk("%s: %s(%d) for %s\n", __func__, current->comm, current->pid, name);

	pil = retval = find_peripheral(name);
	if (!pil)
		return ERR_PTR(-ENODEV);
	if (!try_module_get(pil->owner)) {
		put_device(&pil->dev);
		return ERR_PTR(-ENODEV);
	}

	pil_d = pil_get(pil->desc->depends_on);
	if (IS_ERR(pil_d)) {
		retval = pil_d;
		goto err_depends;
	}

	
	printk("%s: pil_get %s sucessfully, pil->count:%d\n", __func__, name, pil->count);

	if (!strcmp("modem", name)) {
		while (unlikely(!modem_initialized && strcmp("rmt_storage", current->comm) && loop_count++ < 10)) {
			
			printk("%s: %s(%d) waiting for rmt_storage %d\n", __func__, current->comm, current->pid, loop_count);
			msleep(500);
		}
	}
	mutex_lock(&pil->lock);
	if (!pil->count) {
		if (!strcmp("modem", name)) {
			printk("%s: %s(%d) for %s\n", __func__, current->comm, current->pid, name);
			modem_initialized = 1;
		}
		ret = load_image(pil);
		if (ret) {
			retval = ERR_PTR(ret);
			goto err_load;
		}
	}
	pil->count++;
	pil_set_state(pil, PIL_ONLINE);
	mutex_unlock(&pil->lock);
out:
	return retval;
err_load:
	mutex_unlock(&pil->lock);
	pil_put(pil_d);
err_depends:
	put_device(&pil->dev);
	module_put(pil->owner);
	goto out;
}
static void msm_rmnet_unload_modem(void *pil)
{
	if (pil)
		pil_put(pil);
}
void *pil_get(const char *name)
{
	int ret;
	struct pil_device *pil;
	struct pil_device *pil_d;
	void *retval;
#ifdef CONFIG_MSM8960_ONLY
	static int modem_initialized = 0;
	int loop_count = 0;
#endif

	if (!name)
		return NULL;

	pil = retval = find_peripheral(name);
	if (!pil)
		return ERR_PTR(-ENODEV);
	if (!try_module_get(pil->owner)) {
		put_device(&pil->dev);
		return ERR_PTR(-ENODEV);
	}

	pil_d = pil_get(pil->desc->depends_on);
	if (IS_ERR(pil_d)) {
		retval = pil_d;
		goto err_depends;
	}

#ifdef CONFIG_MSM8960_ONLY
	if (!strcmp("modem", name)) {
		while (unlikely(!modem_initialized && strcmp("rmt_storage", current->comm) && loop_count++ < 10)) {
			
			printk("%s: %s(%d) waiting for rmt_storage %d\n", __func__, current->comm, current->pid, loop_count);
			msleep(500);
		}
	}
#endif
	mutex_lock(&pil->lock);
	if (!pil->count) {
		if (!strcmp("modem", name)) {
			printk("%s: %s(%d) for %s\n", __func__, current->comm, current->pid, name);
#ifdef CONFIG_MSM8960_ONLY
			modem_initialized = 1;
#endif
		}
		ret = load_image(pil);
		if (ret) {
			retval = ERR_PTR(ret);
			goto err_load;
		}
	}
	pil->count++;
	pil_set_state(pil, PIL_ONLINE);
	mutex_unlock(&pil->lock);
#if defined(CONFIG_MSM8930_ONLY)
	if (!strcmp("modem", name)) {
		complete_all(&pil_work_finished);
	}
#elif defined(CONFIG_ARCH_APQ8064)
		complete_all(&pil_work_finished);
#endif
out:
	return retval;
err_load:
	mutex_unlock(&pil->lock);
	pil_put(pil_d);
err_depends:
	put_device(&pil->dev);
	module_put(pil->owner);
	goto out;
}