/* 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; }
void mif_netif_stop(struct link_device *ld) { struct io_device *iod; if (ld->ipc_version < SIPC_VER_50) iod = link_get_iod_with_channel(ld, 0x20 | RMNET0_CH_ID); else iod = link_get_iod_with_channel(ld, RMNET0_CH_ID); if (iod) iodevs_for_each(iod->msd, iodev_netif_stop, 0); }
static ssize_t show_txlink(struct device *dev, struct device_attribute *attr, char *buf) { struct miscdevice *miscdev = dev_get_drvdata(dev); struct modem_shared *msd = container_of(miscdev, struct io_device, miscdev)->msd; char *p = buf; iodevs_for_each(msd, iodev_showtxlink, &p); return p - buf; }
void resume_net_ifaces(struct link_device *ld) { struct io_device *iod; unsigned long flags; spin_lock_irqsave(&ld->netif_lock, flags); if (atomic_read(&ld->netif_stopped) == 0) goto exit; iod = link_get_iod_with_channel(ld, SIPC_CH_ID_PDP_0); if (iod) iodevs_for_each(iod->msd, iodev_netif_wake, 0); atomic_set(&ld->netif_stopped, 0); exit: spin_unlock_irqrestore(&ld->netif_lock, flags); }
static void dpram_trigger_crash(struct dpram_link_device *dpld) { struct link_device *ld = &dpld->ld; struct io_device *iod; int i; for (i = 0; i < dpld->max_ipc_dev; i++) { mif_info("%s: purging %s_skb_txq\b", ld->name, get_dev_name(i)); skb_queue_purge(ld->skb_txq[i]); } iod = link_get_iod_with_format(ld, IPC_FMT); iod->modem_state_changed(iod, STATE_CRASH_EXIT); iod = link_get_iod_with_format(ld, IPC_BOOT); iod->modem_state_changed(iod, STATE_CRASH_EXIT); iod = link_get_iod_with_channel(ld, PS_DATA_CH_0); if (iod) iodevs_for_each(iod->msd, iodev_netif_stop, 0); }
void mif_netif_wake(struct link_device *ld) { struct io_device *iod; /** * If ld->suspend_netif_tx is true, this means that there was a SUSPEND * flow control command from CP so MIF must wait for a RESUME command * from CP. */ if (ld->suspend_netif_tx) { mif_info("%s: waiting for FLOW_CTRL_RESUME\n", ld->name); return; } if (ld->ipc_version < SIPC_VER_50) iod = link_get_iod_with_channel(ld, 0x20 | RMNET0_CH_ID); else iod = link_get_iod_with_channel(ld, RMNET0_CH_ID); if (iod) iodevs_for_each(iod->msd, iodev_netif_wake, 0); }
void rawdevs_set_tx_link(struct modem_shared *msd, enum modem_link link_type) { struct link_device *ld = find_linkdev(msd, link_type); if (ld) iodevs_for_each(msd, iodev_set_tx_link, ld); }