static void ext_command_handler(struct dpram_link_device *dpld, u16 cmd) { struct link_device *ld = &dpld->ld; u16 resp; switch (EXT_CMD_MASK(cmd)) { case EXT_CMD_SET_SPEED_LOW: if (dpld->dpctl->setup_speed) { dpld->dpctl->setup_speed(DPRAM_SPEED_LOW); resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_LOW); send_intr(dpld, resp); } break; case EXT_CMD_SET_SPEED_MID: if (dpld->dpctl->setup_speed) { dpld->dpctl->setup_speed(DPRAM_SPEED_MID); resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_MID); send_intr(dpld, resp); } break; case EXT_CMD_SET_SPEED_HIGH: if (dpld->dpctl->setup_speed) { dpld->dpctl->setup_speed(DPRAM_SPEED_HIGH); resp = INT_EXT_CMD(EXT_CMD_SET_SPEED_HIGH); send_intr(dpld, resp); } break; default: mif_info("%s: unknown command 0x%04X\n", ld->name, cmd); break; } }
static int dpram_trigger_force_cp_crash(struct dpram_link_device *dpld) { struct link_device *ld = &dpld->ld; int ret; int cnt = 5000; if (ld->mode == LINK_MODE_ULOAD) { mif_err("%s: CP crash is already in progress\n", ld->name); return 0; } ld->mode = LINK_MODE_ULOAD; mif_err("%s: called by %pf\n", ld->name, __builtin_return_address(0)); dpram_wake_up(dpld); send_intr(dpld, INT_CMD(INT_CMD_CRASH_EXIT)); while (cnt--) { ret = try_wait_for_completion(&dpld->crash_start_complete); if (ret) break; udelay(1000); } if (!ret) { mif_info("%s: ERR! No CRASH_EXIT ACK from CP\n", ld->name); dpram_trigger_crash(dpld); } return 0; }
static void cmd_phone_start_handler(struct dpram_link_device *dpld) { struct link_device *ld = &dpld->ld; struct io_device *iod = NULL; mif_info("%s: Recv 0xC8 (CP_START)\n", ld->name); dpram_init_ipc(dpld); iod = link_get_iod_with_format(ld, IPC_FMT); if (!iod) { mif_info("%s: ERR! no iod\n", ld->name); return; } if (dpld->ext_op && dpld->ext_op->cp_start_handler) dpld->ext_op->cp_start_handler(dpld); if (ld->mc->phone_state != STATE_ONLINE) { mif_info("%s: phone_state: %d -> ONLINE\n", ld->name, ld->mc->phone_state); iod->modem_state_changed(iod, STATE_ONLINE); } mif_info("%s: Send 0xC2 (INIT_END)\n", ld->name); send_intr(dpld, INT_CMD(INT_CMD_INIT_END)); }
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 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 void udl_command_handler(struct dpram_link_device *dpld, u16 cmd) { struct link_device *ld = &dpld->ld; if (cmd & UDL_RESULT_FAIL) { mif_info("%s: ERR! Command failed: %04x\n", ld->name, cmd); return; } switch (UDL_CMD_MASK(cmd)) { case UDL_CMD_RECEIVE_READY: mif_debug("%s: Send CP-->AP RECEIVE_READY\n", ld->name); send_intr(dpld, CMD_IMG_START_REQ); break; default: complete_all(&dpld->udl_cmd_complete); } }
static int trigger_force_cp_crash(struct dpram_link_device *dpld) { struct link_device *ld = &dpld->ld; if (ld->mode == LINK_MODE_ULOAD) { mif_err("%s: CP crash is already in progress\n", ld->mc->name); return 0; } ld->mode = LINK_MODE_ULOAD; mif_err("%s: called by %pf\n", ld->name, __builtin_return_address(0)); dpram_wake_up(dpld); send_intr(dpld, INT_CMD(INT_CMD_CRASH_EXIT)); mif_add_timer(&dpld->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT, handle_no_crash_ack, (unsigned long)dpld); return 0; }
static void cmd_req_active_handler(struct dpram_link_device *dpld) { send_intr(dpld, INT_CMD(INT_CMD_RES_ACTIVE)); }