static irqreturn_t link_pm_irq_handler(int irq, void *data) { int value; struct link_pm_data *pm_data = data; #if defined(CONFIG_SLP) pm_wakeup_event(pm_data->miscdev.this_device, 0); #endif if (!pm_data->link_pm_active) return IRQ_HANDLED; /* host wake up HIGH */ /* resume usb runtime pm start */ /* host wake up LOW */ /* slave usb enumeration end, host can send usb packet after runtime pm status changes to ACTIVE */ value = gpio_get_value(pm_data->gpio_link_hostwake); mif_debug("gpio [HWK] get [%d]\n", value); /* * igonore host wakeup interrupt at suspending kernel */ if (pm_data->dpm_suspending) { mif_info("ignore request by suspending\n"); /* Ignore HWK but AP got to L2 by suspending fail */ wake_lock(&pm_data->l2_wake); return IRQ_HANDLED; } if (value == HOSTWAKE_TRIGLEVEL) { /* move to slave wake function */ /* runtime pm goes to active */ /* if (gpio_get_value(pm_data->gpio_link_active)) { mif_err("gpio [H ACTV : %d] set 1\n", gpio_get_value(pm_data->gpio_link_active)); gpio_set_value(pm_data->gpio_link_active, 1); } */ queue_delayed_work(pm_data->wq, &pm_data->link_pm_work, 0); } else { /* notification of enumeration process from slave device * But it does not mean whole connection is in resume, so do not * notify resume completion here. if (pm_data->link_pm_active && !pm_data->active_done.done) complete(&pm_data->active_done); */ /* clear slave cpu wake up pin */ gpio_set_value(pm_data->gpio_link_slavewake, 0); mif_debug("gpio [SWK] set [0]\n"); } return IRQ_HANDLED; }
static int cbp71_on(struct modem_ctl *mc) { int RetVal = 0; int dpram_init_RetVal = 0; struct link_device *ld = get_current_link(mc->iod); struct dpram_link_device *dpram_ld = to_dpram_link_device(ld); mif_info("cbp71_on()\n"); if (!mc->gpio_cp_off || !mc->gpio_cp_reset) { mif_err("no gpio data\n"); return -ENXIO; } gpio_set_value(mc->gpio_cp_reset, 0); gpio_set_value(mc->gpio_cp_on, 1); mdelay(300); gpio_set_value(mc->gpio_cp_off, 1); mdelay(300); gpio_set_value(mc->gpio_cp_on, 0); gpio_set_value(mc->gpio_cp_reset, 1); gpio_set_value(mc->gpio_pda_active, 1); mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); /* Wait here until the PHONE is up. * Waiting as the this called from IOCTL->UM thread */ mif_debug("power control waiting for INT_MASK_CMD_PIF_INIT_DONE\n"); /* 1HZ = 1 clock tick, 100 default */ dpram_ld->dpctl->clear_intr(); dpram_init_RetVal = wait_for_completion_interruptible_timeout( &dpram_ld->dpram_init_cmd, DPRAM_INIT_TIMEOUT); if (!dpram_init_RetVal) { /*RetVal will be 0 on timeout, non zero if interrupted */ mif_err("INIT_START cmd was not arrived.\n"); mif_err("init_cmd_wait_condition is 0 and wait timeout happend\n"); return -ENXIO; } RetVal = wait_for_completion_interruptible_timeout( &dpram_ld->modem_pif_init_done, PIF_TIMEOUT); if (!RetVal) { /*RetVal will be 0 on timeout, non zero if interrupted */ mif_err("PIF init failed\n"); mif_err("pif_init_wait_condition is 0 and wait timeout happend\n"); return -ENXIO; } mif_debug("complete cbp71_on\n"); mc->iod->modem_state_changed(mc->iod, STATE_ONLINE); return 0; }
static int __devinit modem_spi_boot_probe(struct spi_device *spi) { int ret; struct modem_boot_spi *loader; struct modem_boot_spi_platform_data *pdata; mif_debug("+++\n"); loader = kzalloc(sizeof(*loader), GFP_KERNEL); if (!loader) { mif_err("failed to allocate for modem_boot_spi\n"); ret = -ENOMEM; goto err_alloc; } mutex_init(&loader->lock); spi->bits_per_word = 8; if (spi_setup(spi)) { mif_err("ERR! spi_setup fail\n"); ret = -EINVAL; goto err_setup; } loader->spi_dev = spi; if (!spi->dev.platform_data) { mif_err("ERR! no platform_data\n"); ret = -EINVAL; goto err_setup; } pdata = (struct modem_boot_spi_platform_data *)spi->dev.platform_data; loader->gpio_cp_status = pdata->gpio_cp_status; spi_set_drvdata(spi, loader); loader->dev.minor = MISC_DYNAMIC_MINOR; loader->dev.name = MODEM_BOOT_DEV_SPI; loader->dev.fops = &modem_spi_boot_fops; ret = misc_register(&loader->dev); if (ret) { mif_err("ERR! misc_register fail (err %d)\n", ret); goto err_setup; } mif_debug("---\n"); return 0; err_setup: mutex_destroy(&loader->lock); kfree(loader); err_alloc: mif_err("xxx\n"); return ret; }
static int link_pm_runtime_get_active(struct link_pm_data *pm_data) { int ret; struct usb_link_device *usb_ld = pm_data->usb_ld; struct device *dev = &usb_ld->usbdev->dev; if (!usb_ld->if_usb_connected || usb_ld->ld.com_state == COM_NONE) return -ENODEV; if (pm_data->dpm_suspending) { mif_err("Kernel in suspending try get_active later\n"); /* during dpm_suspending.. * if AP get tx data, wake up. */ #ifdef CONFIG_HAS_WAKELOCK wake_lock(&pm_data->l2_wake); #else pm_stay_awake(pm_data->miscdev.this_device); #endif return -EAGAIN; } if (dev->power.runtime_status == RPM_ACTIVE) { pm_data->resume_retry_cnt = 0; return 0; } if (!pm_data->resume_requested) { mif_debug("QW PM\n"); queue_delayed_work(pm_data->wq, &pm_data->link_pm_work, 0); } mif_debug("Wait pm\n"); INIT_COMPLETION(pm_data->active_done); ret = wait_for_completion_timeout(&pm_data->active_done, msecs_to_jiffies(500)); /* If usb link was disconnected while waiting ACTIVE State, usb device * was removed, usb_ld->usbdev->dev is invalid and below * dev->power.runtime_status is also invalid address. * It will be occured LPA L3 -> AP iniated L0 -> disconnect -> link * timeout */ if (!usb_ld->if_usb_connected || usb_ld->ld.com_state == COM_NONE) { mif_info("link disconnected after timed-out\n"); return -ENODEV; } if (dev->power.runtime_status != RPM_ACTIVE) { mif_info("link_active (%d) retry\n", dev->power.runtime_status); return -EAGAIN; } mif_debug("link_active success(%d)\n", ret); return 0; }
static void non_command_handler(struct dpram_link_device *dpld, u16 intr) { struct link_device *ld = &dpld->ld; int i = 0; int ret = 0; u16 tx_mask = 0; if (!dpram_ipc_active(dpld)) return; /* Read data from DPRAM */ for (i = 0; i < dpld->max_ipc_dev; i++) { if (dpld->use_skb) ret = dpram_ipc_recv_data_with_skb(dpld, i); else ret = dpram_ipc_recv_data_with_rxb(dpld, i); if (ret < 0) dpram_reset_rx_circ(dpld, i); /* Check and process REQ_ACK (at this time, in == out) */ if (intr & get_mask_req_ack(dpld, i)) { mif_debug("%s: send %s_RES_ACK\n", ld->name, get_dev_name(i)); tx_mask |= get_mask_res_ack(dpld, i); } } if (!dpld->use_skb) { /* Schedule soft IRQ for RX */ tasklet_hi_schedule(&dpld->rx_tsk); } /* Try TX via DPRAM */ for (i = 0; i < dpld->max_ipc_dev; i++) { if (atomic_read(&dpld->res_required[i]) > 0) { ret = dpram_try_ipc_tx(dpld, i); if (ret > 0) { atomic_set(&dpld->res_required[i], 0); tx_mask |= get_mask_send(dpld, i); } else if (ret == -ENOSPC) { tx_mask |= get_mask_req_ack(dpld, i); } } } if (tx_mask) { send_intr(dpld, INT_NON_CMD(tx_mask)); mif_debug("%s: send intr 0x%04X\n", ld->name, tx_mask); } }
static int dpram_ioctl(struct link_device *ld, struct io_device *iod, unsigned int cmd, unsigned long arg) { struct dpram_link_device *dpld = to_dpram_link_device(ld); int err = 0; mif_info("%s: cmd 0x%08X\n", ld->name, cmd); switch (cmd) { case IOCTL_DPRAM_INIT_STATUS: mif_debug("%s: get dpram init status\n", ld->name); return dpld->dpram_init_status; default: if (dpld->ext_ioctl) { err = dpld->ext_ioctl(dpld, iod, cmd, arg); } else { mif_err("%s: ERR! invalid cmd 0x%08X\n", ld->name, cmd); err = -EINVAL; } break; } return err; }
static inline int link_pm_slave_wake(struct link_pm_data *pm_data) { int spin = 20; /* when slave device is in sleep, wake up slave cpu first */ if (gpio_get_value(pm_data->gpio_link_hostwake) != HOSTWAKE_TRIGLEVEL) { if (gpio_get_value(pm_data->gpio_link_slavewake)) { gpio_set_value(pm_data->gpio_link_slavewake, 0); mif_info("gpio [SWK] set [0]\n"); mdelay(5); } gpio_set_value(pm_data->gpio_link_slavewake, 1); mif_info("gpio [SWK] set [1]\n"); mdelay(5); /* wait host wake signal*/ while (spin-- && gpio_get_value(pm_data->gpio_link_hostwake) != HOSTWAKE_TRIGLEVEL) mdelay(5); } /* runtime pm goes to active */ if (!gpio_get_value(pm_data->gpio_link_active)) { mif_debug("gpio [H ACTV : %d] set 1\n", gpio_get_value(pm_data->gpio_link_active)); gpio_set_value(pm_data->gpio_link_active, 1); } return spin; }
/* flow control CM from CP, it use in serial devices */ int link_rx_flowctl_cmd(struct link_device *ld, const char *data, size_t len) { struct modem_shared *msd = ld->msd; unsigned short *cmd, *end = (unsigned short *)(data + len); mif_debug("flow control cmd: size=%d\n", len); for (cmd = (unsigned short *)data; cmd < end; cmd++) { switch (*cmd) { case CMD_SUSPEND: iodevs_for_each(msd, iodev_netif_stop, 0); ld->raw_tx_suspended = true; mif_info("flowctl CMD_SUSPEND(%04X)\n", *cmd); break; case CMD_RESUME: iodevs_for_each(msd, iodev_netif_wake, 0); ld->raw_tx_suspended = false; complete_all(&ld->raw_tx_resumed_by_cp); mif_info("flowctl CMD_RESUME(%04X)\n", *cmd); break; default: mif_err("flowctl BAD CMD: %04X\n", *cmd); break; } } return 0; }
static int cbp72_boot_off(struct modem_ctl *mc) { int ret; struct link_device *ld = get_current_link(mc->bootd); struct dpram_link_device *dpld = to_dpram_link_device(ld); mif_debug("\n"); /* Wait here until the PHONE is up. * Waiting as the this called from IOCTL->UM thread */ mif_info("Waiting for INT_CMD_PHONE_START\n"); ret = wait_for_completion_interruptible_timeout( &dpld->dpram_init_cmd, DPRAM_INIT_TIMEOUT); if (!ret) { /* ret == 0 on timeout, ret < 0 if interrupted */ mif_err("Timeout!!! (PHONE_START was not arrived.)\n"); return -ENXIO; } mif_info("Waiting for INT_CMD_PIF_INIT_DONE\n"); ret = wait_for_completion_interruptible_timeout( &dpld->modem_pif_init_done, PIF_TIMEOUT); if (!ret) { mif_err("Timeout!!! (PIF_INIT_DONE was not arrived.)\n"); return -ENXIO; } mc->bootd->modem_state_changed(mc->bootd, STATE_ONLINE); wake_unlock(&mc->mc_wake_lock); return 0; }
static int exynos_frequency_unlock(struct device *dev) { int ret = 0; struct device *busdev = dev_get("exynos-busfreq"); if (atomic_read(&umts_link_pm_data.freqlock) == 1) { /* cpu frequency unlock */ exynos_cpufreq_lock_free(DVFS_LOCK_ID_USB_IF); /* bus frequency unlock */ ret = dev_unlock(busdev, dev); if (ret < 0) { mif_err("ERR: dev_unlock error: %d\n", ret); goto exit; } /* unlock minimum number of cpu cores */ cpufreq_pegasusq_min_cpu_unlock(); atomic_set(&umts_link_pm_data.freqlock, 0); mif_debug("success\n"); } exit: return ret; }
static int usb_init_communication(struct link_device *ld, struct io_device *iod) { int err = 0; switch (iod->format) { case IPC_BOOT: ld->com_state = COM_BOOT; skb_queue_purge(&ld->sk_fmt_tx_q); break; case IPC_RAMDUMP: ld->com_state = COM_CRASH; break; case IPC_FMT: err = start_ipc(ld, iod); break; case IPC_RFS: case IPC_RAW: default: ld->com_state = COM_ONLINE; break; } mif_debug("com_state = %d\n", ld->com_state); return err; }
static void idpram_resume_retry(struct work_struct *work) { struct idpram_link_pm_data *pm_data = container_of(work, struct idpram_link_pm_data, \ resume_work.work); mif_debug("MIF: %s\n", __func__); if (!idpram_resume_check(pm_data)) { mif_info("MIF: idpram resume ok\n"); idpram_write_lock(pm_data, 0); wake_lock_timeout(&pm_data->hold_wlock, msecs_to_jiffies(20)); return; } if (pm_data->resume_retry--) { schedule_delayed_work(&pm_data->resume_work, \ msecs_to_jiffies(200)); wake_lock_timeout(&pm_data->hold_wlock, msecs_to_jiffies(260)); } else { mif_info("MIF: idpram resume T-I-M-E-O-UT\n"); idpram_timeout_handler(pm_data); /* hold wakelock until uevnet sent to rild */ wake_lock_timeout(&pm_data->hold_wlock, HZ*7); idpram_write_lock(pm_data, 0); } }
/** @brief check whether or not TX is possible via the link @param mld the pointer to a mem_link_device instance @param dev the pointer to a mem_ipc_device instance (IPC_FMT, etc.) @param skb the pointer to an skb that will be transmitted @retval "> 0" the size of the data in @b @@skb if there is NO ERROR @retval "< 0" an error code (-EIO or -EBUSY) */ static inline int check_tx_link(struct mem_link_device *mld, struct mem_ipc_device *dev, struct sk_buff *skb) { struct link_device *ld = &mld->link_dev; struct modem_ctl *mc = ld->mc; struct sk_buff_head *skb_txq = dev->skb_txq; int ret = skb->len; if (unlikely(cp_online(mc) && !ipc_active(mld))) return -EIO; if (unlikely(skb_txq->qlen >= MAX_SKB_TXQ_DEPTH)) { #ifdef DEBUG_MODEM_IF struct io_device *iod = skbpriv(skb)->iod; mif_debug("%s: %s->%s: ERR! %s "\ "SKB_TXQ qlen %d >= limit %d\n", ld->name, iod->name, mc->name, dev->name, skb_txq->qlen, MAX_SKB_TXQ_DEPTH); #endif return -EBUSY; } return ret; }
static int exynos_frequency_lock(struct device *dev) { unsigned int level, cpufreq = 600; /* 200 ~ 1400 */ unsigned int busfreq = 400200; /* 100100 ~ 400200 */ int ret = 0, lock_id; atomic_t *freqlock; struct device *busdev = dev_get("exynos-busfreq"); if (!strcmp(dev->bus->name, "usb")) { lock_id = DVFS_LOCK_ID_USB_IF; cpufreq = 600; freqlock = &umts_link_pm_data.freq_usblock; } else if (!strcmp(dev->bus->name, "platform")) { // for dpram lock lock_id = DVFS_LOCK_ID_DPRAM_IF; cpufreq = 800; freqlock = &umts_link_pm_data.freq_dpramlock; } else { mif_err("ERR: Unkown unlock ID (%s)\n", dev->bus->name); goto exit; } if (atomic_read(freqlock) == 0) { /* cpu frequency lock */ ret = exynos_cpufreq_get_level(cpufreq * 1000, &level); if (ret < 0) { mif_err("ERR: exynos_cpufreq_get_level fail: %d\n", ret); goto exit; } ret = exynos_cpufreq_lock(lock_id, level); if (ret < 0) { mif_err("ERR: exynos_cpufreq_lock fail: %d\n", ret); goto exit; } /* bus frequncy lock */ if (!busdev) { mif_err("ERR: busdev is not exist\n"); ret = -ENODEV; goto exit; } ret = dev_lock(busdev, dev, busfreq); if (ret < 0) { mif_err("ERR: dev_lock error: %d\n", ret); goto exit; } /* lock minimum number of cpu cores */ cpufreq_pegasusq_min_cpu_lock(2); atomic_set(freqlock, 1); mif_debug("level=%d, cpufreq=%d MHz, busfreq=%06d\n", level, cpufreq, busfreq); } exit: return ret; }
static void cdc_ncm_status(struct if_usb_devdata *pipe_data, struct urb *urb) { struct cdc_ncm_ctx *ctx; struct usb_cdc_notification *event; ctx = (struct cdc_ncm_ctx *)pipe_data->sedata; if (urb->actual_length < sizeof(*event)) return; /* test for split data in 8-byte chunks */ if (test_and_clear_bit(EVENT_STS_SPLIT, &pipe_data->flags)) { cdc_ncm_speed_change(ctx, (struct usb_cdc_speed_change *)urb->transfer_buffer); return; } event = urb->transfer_buffer; mif_debug("event: %d by ep=%d\n", event->bNotificationType, usb_pipeendpoint(urb->pipe)); switch (event->bNotificationType) { case USB_CDC_NOTIFY_NETWORK_CONNECTION: /* * According to the CDC NCM specification ch.7.1 * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE. */ ctx->connected = event->wValue; pipe_data->net_connected = (event->wValue) ? true : false; printk(KERN_INFO KBUILD_MODNAME ": network connection: %s connected\n", ctx->connected ? "" : "dis"); if (ctx->connected) netif_carrier_on(pipe_data->iod->ndev); else { netif_carrier_off(pipe_data->iod->ndev); ctx->tx_speed = ctx->rx_speed = 0; } break; case USB_CDC_NOTIFY_SPEED_CHANGE: if (urb->actual_length < (sizeof(*event) + sizeof(struct usb_cdc_speed_change))) set_bit(EVENT_STS_SPLIT, &pipe_data->flags); else cdc_ncm_speed_change(ctx, (struct usb_cdc_speed_change *) &event[1]); break; default: mif_err("unexpected notification 0x%02x!\n", event->bNotificationType); break; } }
static int if_usb_reset_resume(struct usb_interface *intf) { int ret; mif_debug("\n"); ret = if_usb_resume(intf); return ret; }
static void dpram_send_ipc(struct link_device *ld, int dev, struct io_device *iod, struct sk_buff *skb) { struct dpram_link_device *dpld = to_dpram_link_device(ld); struct sk_buff_head *txq = ld->skb_txq[dev]; int ret; u16 mask; skb_queue_tail(txq, skb); if (txq->qlen > 1024) { mif_debug("%s: %s txq->qlen %d > 1024\n", ld->name, get_dev_name(dev), txq->qlen); } if (dpld->dp_type == CP_IDPRAM) { if (dpram_wake_up(dpld) < 0) { trigger_force_cp_crash(dpld); return; } } if (!dpram_ipc_active(dpld)) goto exit; if (atomic_read(&dpld->res_required[dev]) > 0) { mif_debug("%s: %s_TXQ is full\n", ld->name, get_dev_name(dev)); goto exit; } ret = dpram_try_ipc_tx(dpld, dev); if (ret > 0) { mask = get_mask_send(dpld, dev); send_intr(dpld, INT_NON_CMD(mask)); } else if (ret == -ENOSPC) { mask = get_mask_req_ack(dpld, dev); send_intr(dpld, INT_NON_CMD(mask)); mif_info("%s: Send REQ_ACK 0x%04X\n", ld->name, mask); } else { mif_info("%s: dpram_try_ipc_tx fail (err %d)\n", ld->name, ret); } exit: if (dpld->dp_type == CP_IDPRAM) dpram_allow_sleep(dpld); }
static int idpram_pm_resume(struct device *dev) { struct idpram_link_pm_data *pm_data = pm; idpram_resume_init(pm_data); gpio_set_value(pm_data->mdata->gpio_pda_active, 1); mif_debug("MIF: <%s>\n", __func__); return 0; }
/* ret < 0 : error ret == 0 : no data ret > 0 : valid data */ static int dpram_ipc_recv_data(struct dpram_link_device *dpld, int dev) { struct link_device *ld = &dpld->ld; struct dpram_rxb *rxb; u8 __iomem *src = get_rx_buff(dpld, dev); u32 qsize = get_rx_buff_size(dpld, dev); u32 in = get_rx_head(dpld, dev); u32 out = get_rx_tail(dpld, dev); u32 rcvd = 0; struct mif_irq_map map; if (in == out) return 0; if (dev == IPC_FMT) { set_dpram_map(dpld, &map); mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv")); } /* Get data length in DPRAM*/ rcvd = (in > out) ? (in - out) : (qsize - out + in); mif_debug("%s: %s qsize[%u] in[%u] out[%u] rcvd[%u]\n", ld->name, get_dev_name(dev), qsize, in, out, rcvd); /* Check each queue */ if (!dpram_circ_valid(qsize, in, out)) { mif_err("%s: ERR! %s_RXQ invalid (size:%d in:%d out:%d)\n", ld->name, get_dev_name(dev), qsize, in, out); #if 0 set_rx_head(dpld, dev, 0); set_rx_tail(dpld, dev, 0); #else dpram_trigger_force_cp_crash(dpld); #endif return -EINVAL; } /* Allocate an rxb */ rxb = rxbq_get_free_rxb(&dpld->rxbq[dev]); if (!rxb) { mif_info("%s: ERR! %s rxbq_get_free_rxb fail\n", ld->name, get_dev_name(dev)); return -ENOMEM; } /* Read data from each DPRAM buffer */ dpram_ipc_read(dpld, dev, rxb_put(rxb, rcvd), src, out, rcvd, qsize); /* Calculate and set new out */ out += rcvd; if (out >= qsize) out -= qsize; set_rx_tail(dpld, dev, out); return rcvd; }
static inline void start_hub_work(struct link_pm_data *pm_data, int delay) { if (pm_data->hub_work_running == false) { pm_data->hub_work_running = true; wake_lock(&pm_data->hub_lock); mif_debug("link_pm_hub_work is started\n"); } schedule_delayed_work(&pm_data->link_pm_hub, msecs_to_jiffies(delay)); }
static int cmc220_boot_on(struct modem_ctl *mc) { mif_debug("\n"); mif_err("<%s>\n", mc->bootd->name); mif_err("phone_state = STATE_BOOTING\n"); mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); return 0; }
static int idpram_pm_suspend(struct device *dev) { struct idpram_link_pm_data *pm_data = pm; pm_data->pm_states = IDPRAM_PM_SUSPEND_START; gpio_set_value(pm_data->mdata->gpio_pda_active, 0); mif_debug("MIF: <%s>\n", __func__); return 0; }
static void cmc221_cpufreq_unlock(struct work_struct *work) { struct modem_ctl *mc; int tp_level; mc = container_of(work, struct modem_ctl, work_cpu_unlock.work); tp_level = gpio_get_value(mc->gpio_cpufreq_lock); mif_debug("TP Level is (%d)\n", tp_level); if (tp_level) { mif_debug("maintain cpufreq lock !!!\n"); schedule_delayed_work(&mc->work_cpu_unlock, msecs_to_jiffies(5000)); } else { if (mc->mdm_data->link_pm_data->freq_unlock) { mif_debug("Call freq unlock func.\n"); mc->mdm_data->link_pm_data->freq_unlock(mc->dev); } } }
void cdc_ncm_intr_complete(struct urb *urb) { struct if_usb_devdata *pipe_data = urb->context; struct usb_link_device *usb_ld = pipe_data->usb_ld; int ret; mif_debug("status = %d\n", urb->status); switch (urb->status) { /* success */ case -ENOENT: /* urb killed by L2 suspend */ case 0: usb_ld->rx_cnt++; if (urb->actual_length) { mif_info("ep=%d\n", usb_pipeendpoint(urb->pipe)); pr_urb(__func__, urb); } cdc_ncm_status(pipe_data, urb); break; case -ESHUTDOWN: /* hardware gone */ mif_err("intr shutdown, code %d\n", urb->status); return; /* NOTE: not throttling like RX/TX, since this endpoint * already polls infrequently */ default: mif_err("intr status %d\n", urb->status); break; } if (!urb->status) { /*skip -ENOENT L2 enter status */ memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); ret = usb_submit_urb(urb, GFP_ATOMIC); mif_debug("status: usb_submit_urb ret=%d\n", ret); if (ret != 0) mif_err("intr resubmit --> %d\n", ret); } }
/** @brief forbid CP from going to sleep Wakes up a CP if it can sleep and increases the "ref_cnt" counter in the mem_link_device instance. @param mld the pointer to a mem_link_device instance @remark CAUTION!!! permit_cp_sleep() MUST be invoked after forbid_cp_sleep() success to decrease the "ref_cnt" counter. */ static void forbid_cp_sleep(struct mem_link_device *mld) { struct modem_link_pm *pm = &mld->link_dev.pm; atomic_inc(&pm->ref_cnt); mif_debug("ref_cnt %d\n", atomic_read(&pm->ref_cnt)); if (atomic_read(&pm->ref_cnt) > 1) return; if (pm->request_hold) pm->request_hold(pm); }
static void dpram_allow_sleep(struct dpram_link_device *dpld) { struct link_device *ld = &dpld->ld; if (!dpld->dpctl->sleep) return; if (atomic_dec_return(&dpld->accessing) <= 0) { dpld->dpctl->sleep(); atomic_set(&dpld->accessing, 0); mif_debug("%s: DPRAM sleep possible\n", ld->name); } }
static void handle_no_cp_crash_ack(unsigned long arg) { struct mem_link_device *mld = (struct mem_link_device *)arg; struct link_device *ld = &mld->link_dev; struct modem_ctl *mc = ld->mc; if (cp_crashed(mc)) { mif_debug("%s: STATE_CRASH_EXIT without CRASH_ACK\n", ld->name); } else { mif_err("%s: ERR! No CRASH_ACK from CP\n", ld->name); mem_handle_cp_crash(mld, STATE_CRASH_EXIT); } }
/** @brief forbid CP from going to sleep Wakes up a CP if it can sleep and increases the "ref_cnt" counter in the mem_link_device instance. @param mld the pointer to a mem_link_device instance @remark CAUTION!!! permit_cp_sleep() MUST be invoked after forbid_cp_sleep() success to decrease the "ref_cnt" counter. */ static void forbid_cp_sleep(struct mem_link_device *mld) { struct modem_link_pm *pm = &mld->link_dev.pm; int ref_cnt; ref_cnt = atomic_inc_return(&mld->ref_cnt); mif_debug("ref_cnt %d\n", ref_cnt); if (ref_cnt > 1) return; if (pm->request_hold) pm->request_hold(pm); }
/* do not switch to USB, when USB is not enumerated. */ if (!enumerated && txpath) { mc->need_switch_to_usb = true; return IRQ_HANDLED; } mc->need_switch_to_usb = false; rawdevs_set_tx_link(mc->msd, txpath ? LINKDEV_USB : LINKDEV_DPRAM); return IRQ_HANDLED; } #ifdef CONFIG_EXYNOS4_CPUFREQ /* Set cpu clock to 800MHz for high TP */ static void cmc221_cpufreq_lock(struct work_struct *work) { struct modem_ctl *mc; mc = container_of(work, struct modem_ctl, work_cpu_lock.work); if (mc->mdm_data->link_pm_data->freq_lock) { mif_debug("Call freq lock func.\n"); mc->mdm_data->link_pm_data->freq_lock(mc->dev); cancel_delayed_work(&mc->work_cpu_unlock); schedule_delayed_work(&mc->work_cpu_unlock, msecs_to_jiffies(5000)); } }
static int cbp71_off(struct modem_ctl *mc) { mif_debug("cbp71_off()\n"); if (!mc->gpio_cp_off || !mc->gpio_cp_reset) { mif_err("no gpio data\n"); return -ENXIO; } mif_err("Phone power Off. - do nothing\n"); mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE); return 0; }