static void *msm_ipc_router_load_modem(void) { void *pil = NULL; int rc; /* Load GNSS for Standalone 8064 but not for Fusion 3 */ if (cpu_is_apq8064()) { if (socinfo_get_platform_subtype() == 0x0) pil = pil_get("gss"); } else { pil = pil_get("modem"); } if (IS_ERR(pil) || !pil) { pr_debug("%s: modem load failed\n", __func__); pil = NULL; } else { rc = wait_for_completion_interruptible_timeout( &msm_ipc_remote_router_up, MODEM_LOAD_TIMEOUT); if (!rc) rc = -ETIMEDOUT; if (rc < 0) { pr_err("%s: wait for remote router failed %d\n", __func__, rc); msm_ipc_router_unload_modem(pil); pil = NULL; } } return 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] %s: modem load failed\n", dev->name, __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] %s: wait for rmnet port failed %d\n", dev->name, __func__, rc); msm_rmnet_unload_modem(pil); pil = ERR_PTR(rc); } } return pil; }
static void *msm_ipc_router_load_modem(void) { void *pil; int rc; pil = pil_get("modem"); if (IS_ERR(pil)) { pr_debug("%s: modem load failed\n", __func__); pil = NULL; } else { rc = wait_for_completion_interruptible_timeout( &msm_ipc_remote_router_up, MODEM_LOAD_TIMEOUT); if (!rc) rc = -ETIMEDOUT; if (rc < 0) { pr_err("%s: wait for remote router failed %d\n", __func__, rc); msm_ipc_router_unload_modem(pil); pil = NULL; } } return pil; }
static void *msm_rmnet_load_modem(struct net_device *dev) { void *pil; int rc; struct rmnet_private *p = netdev_priv(dev); /* printk("%s() ++\n", __func__); */ pil = pil_get("modem"); if (IS_ERR(pil)) pr_err("%s: modem load failed\n", __func__); else if (msm_rmnet_modem_wait) { printk("wait_for_completion_interruptible_timeout ..\n"); rc = wait_for_completion_interruptible_timeout( &p->complete, msecs_to_jiffies(msm_rmnet_modem_wait * 1000)); printk("wait_for_completion_interruptible_timeout .. Done\n"); if (!rc){ rc = -ETIMEDOUT; printk("Modem load timeout\n"); } if (rc < 0) { pr_err("%s: wait for rmnet port failed %d\n", __func__, rc); msm_rmnet_unload_modem(pil); pil = ERR_PTR(rc); } } /* printk("%s() --\n", __func__); */ return pil; }
u32 ddl_fw_init(struct ddl_buf_addr *dram_base) { u8 *dest_addr; dest_addr = DDL_GET_ALIGNED_VITUAL(*dram_base); DDL_MSG_LOW("FW Addr / FW Size : %x/%d", (u32)vidc_video_codec_fw, vidc_video_codec_fw_size); if (res_trk_check_for_sec_session() && res_trk_is_cp_enabled()) { if (res_trk_enable_footswitch()) { pr_err("Failed to enable footswitch"); return false; } if (res_trk_enable_iommu_clocks()) { res_trk_disable_footswitch(); pr_err("Failed to enable iommu clocks\n"); return false; } dram_base->pil_cookie = pil_get("vidc"); if (res_trk_disable_iommu_clocks()) pr_err("Failed to disable iommu clocks\n"); if (IS_ERR_OR_NULL(dram_base->pil_cookie)) { res_trk_disable_footswitch(); pr_err("pil_get failed\n"); return false; } } else { if (vidc_video_codec_fw_size > dram_base->buffer_size || !vidc_video_codec_fw) return false; memcpy(dest_addr, vidc_video_codec_fw, vidc_video_codec_fw_size); } return true; }
static int adsp_loader_probe(struct platform_device *pdev) { struct adsp_loader_private *priv; int rc = 0; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; platform_set_drvdata(pdev, priv); priv->pil_h = pil_get("adsp"); if (IS_ERR(priv->pil_h)) { pr_err("%s: pil get adsp failed, error:%d\n", __func__, rc); devm_kfree(&pdev->dev, priv); goto fail; } /* Query the DSP to check if resources are available */ msleep(Q6_PIL_GET_DELAY_MS); /* Set the state of the ADSP in APR driver */ apr_set_q6_state(APR_SUBSYS_LOADED); /* Query for MMPM API */ pr_info("%s: Q6/ADSP image is loaded\n", __func__); fail: return rc; }
static int gss_open(struct inode *inode, struct file *filep) { void *ret; gss_data.pil_handle = ret = pil_get("gss"); if (!ret) pr_debug("%s - pil_get returned NULL\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; }
/** * Load DSPS Firmware. */ static int dsps_load(const char *name) { pr_debug("%s.\n", __func__); drv->pil = pil_get(name); if (IS_ERR(drv->pil)) { pr_err("%s: fail to load DSPS firmware %s.\n", __func__, name); return -ENODEV; } msleep(20); return 0; }
/** * Load DSPS Firmware. */ static int dsps_load(void) { pr_debug("%s.\n", __func__); drv->pil = pil_get("dsps"); if (IS_ERR(drv->pil)) { pr_err("%s: fail to load DSPS firmware.\n", __func__); return -ENODEV; } 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; } 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; }
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; }
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; }
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 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; }
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; }
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; }
/* 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; }
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; }
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; }