static KAL_INT32 eemcs_cdev_rx_callback(struct sk_buff *skb, KAL_UINT32 private_data) { CCCI_BUFF_T *p_cccih = NULL; KAL_UINT32 port_id; DEBUG_LOG_FUNCTION_ENTRY; if (skb){ p_cccih = (CCCI_BUFF_T *)skb->data; DBGLOG(CHAR, DBG, "cdev_rx_callback: CCCI_H(0x%x)(0x%x)(0x%x)(0x%x)",\ p_cccih->data[0],p_cccih->data[1],p_cccih->channel, p_cccih->reserved ); } port_id = ccci_ch_to_port(p_cccih->channel); if(CDEV_OPEN == atomic_read(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].cdev_state)){ skb_queue_tail(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_skb_list, skb); /* spin_lock_ireqsave inside, refering skbuff.c */ atomic_inc(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_pkt_cnt); /* increase rx_pkt_cnt */ eemcs_update_statistics_number(0, port_id, RX, QUEUE, \ atomic_read(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_pkt_cnt)); wake_up(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_waitq); /* wake up rx_waitq */ }else{ if(port_id != CCCI_PORT_MD_LOG) /* If port_id == CCCI_PORT_MD_LOG, skip drop info (request by ST team)*/ { DBGLOG(CHAR, ERR, "!!! PKT DROP when cdev(%d) close", port_id); } dev_kfree_skb(skb); eemcs_ccci_release_rx_skb(port_id, 1, skb); eemcs_update_statistics(0, port_id, RX, DROP); } DEBUG_LOG_FUNCTION_LEAVE; return KAL_SUCCESS ; }
static int eemcs_cdev_release(struct inode *inode, struct file *file) { int id = iminor(inode); struct sk_buff *rx_skb; DEBUG_LOG_FUNCTION_ENTRY; DBGLOG(CHAR,INF,"cdev_release: close dev(%s, %d)",\ eemcs_cdev_inst.cdev_node[PORT2IDX(id)].cdev_name, id); atomic_set(&eemcs_cdev_inst.cdev_node[PORT2IDX(id)].cdev_state, CDEV_CLOSE); while ((rx_skb = skb_dequeue(&eemcs_cdev_inst.cdev_node[PORT2IDX(id)].rx_skb_list)) != NULL) { dev_kfree_skb(rx_skb); eemcs_ccci_release_rx_skb(id, 1, rx_skb); } atomic_set(&eemcs_cdev_inst.cdev_node[PORT2IDX(id)].rx_pkt_cnt, 0); /* unregister ccci channel */ // Might casue raise condition while user close cdev //ccci_cdev_unregister(eemcs_cdev_inst.cdev_node[PORT2IDX(id)].ccci_ch.rx); if(true == eemcs_on_reset()) { if(true == eemcs_cdev_rst_port_closed()){ eemcs_boot_user_exit_notify(); } } DEBUG_LOG_FUNCTION_LEAVE; return 0; }
static KAL_INT32 eemcs_cdev_rx_callback(struct sk_buff *skb, KAL_UINT32 private_data) { CCCI_BUFF_T *p_cccih = NULL; KAL_UINT32 port_id; DEBUG_LOG_FUNCTION_ENTRY; if (skb){ p_cccih = (CCCI_BUFF_T *)skb->data; DBGLOG(CHAR, DBG, "cdev_rx_callback: CCCI_H(0x%08X, 0x%08X, %02d, 0x%08X",\ p_cccih->data[0],p_cccih->data[1],p_cccih->channel, p_cccih->reserved ); } else { DEBUG_LOG_FUNCTION_LEAVE; return KAL_SUCCESS; } port_id = ccci_ch_to_port(p_cccih->channel); //if(CDEV_OPEN == atomic_read(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].cdev_state)) { skb_queue_tail(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_skb_list, skb); /* spin_lock_ireqsave inside, refering skbuff.c */ atomic_inc(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_pkt_cnt); /* increase rx_pkt_cnt */ eemcs_update_statistics_number(0, port_id, RX, QUEUE, \ atomic_read(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_pkt_cnt)); wake_up(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_waitq); /* wake up rx_waitq */ #if 0 }else{
bool eemcs_cdev_rst_port_closed(void){ /* reset must wait for fs/muxd/rild to be terminated */ if(CDEV_OPEN == atomic_read(&eemcs_cdev_inst.cdev_node[PORT2IDX(CCCI_PORT_FS)].cdev_state)){ DBGLOG(CHAR,DEF,"FS port close fail!"); return false; } if(CDEV_OPEN == atomic_read(&eemcs_cdev_inst.cdev_node[PORT2IDX(CCCI_PORT_MUX)].cdev_state)){ DBGLOG(CHAR,DEF,"MUX port close fail!"); return false; } // if(CDEV_OPEN == atomic_read(&eemcs_cdev_inst.cdev_node[PORT2IDX(CCCI_PORT_MD_LOG)].cdev_state)){ // DBGLOG(CHAR,DEF,"MDLOG port close fail!"); // return false; // } return true; }
static int eemcs_cdev_open(struct inode *inode, struct file *file) { int id = iminor(inode); int ret = 0; struct sk_buff *rx_skb; DEBUG_LOG_FUNCTION_ENTRY; DBGLOG(CHAR,INF,"cdev_open: open dev(%s, %d)",\ eemcs_cdev_inst.cdev_node[PORT2IDX(id)].cdev_name, id); //4 <1> check multiple open if(CDEV_OPEN == atomic_read(&eemcs_cdev_inst.cdev_node[PORT2IDX(id)].cdev_state)){ DBGLOG(CHAR,ERR,"cdev_open: %s(%d) multi-open fail!", \ eemcs_cdev_inst.cdev_node[PORT2IDX(id)].cdev_name, id); return -EIO; } if(eemcs_cdev_inst.cdev_node[PORT2IDX(id)].ccci_ch.rx != CH_DUMMY){ /* CH_DUMMY should not have Rx Data */ //4 <2> clear the rx_skb_list skb_queue_purge(&eemcs_cdev_inst.cdev_node[PORT2IDX(id)].rx_skb_list); while ((rx_skb = skb_dequeue(&eemcs_cdev_inst.cdev_node[PORT2IDX(id)].rx_skb_list)) != NULL) { dev_kfree_skb(rx_skb); eemcs_ccci_release_rx_skb(id, 1, rx_skb); } atomic_set(&eemcs_cdev_inst.cdev_node[PORT2IDX(id)].rx_pkt_cnt, 0); //4 <3> register ccci channel ret = ccci_cdev_register(eemcs_cdev_inst.cdev_node[PORT2IDX(id)].ccci_ch.rx, eemcs_cdev_rx_callback, 0); if(ret != KAL_SUCCESS){ DBGLOG(CHAR,ERR,"PORT%d register cdev fail!!", id); return -EIO; } } file->private_data = &eemcs_cdev_inst.cdev_node[PORT2IDX(id)]; nonseekable_open(inode, file); atomic_set(&eemcs_cdev_inst.cdev_node[PORT2IDX(id)].cdev_state, CDEV_OPEN); DEBUG_LOG_FUNCTION_LEAVE; return ret; }
static long eemcs_cdev_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { eemcs_cdev_node_t *curr_node = (eemcs_cdev_node_t *)fp->private_data; KAL_UINT8 port_id = curr_node->eemcs_port_id; /* port_id */ int ret = 0; unsigned int sim_type; unsigned int enable_sim_type; DEBUG_LOG_FUNCTION_ENTRY; if(port_id > END_OF_CCCI_CDEV) { DBGLOG(CHAR, ERR, "ccci ioctl fail: unknown Port id=%d", port_id); ret = -ENOTTY; goto _exit; } switch(cmd) { case CCCI_IOC_GET_MD_STATE: { KAL_UINT32 eemcs_state, md_state; eemcs_state = check_device_state(); if(eemcs_state == EEMCS_BOOTING_DONE ){ md_state = MD_STATE_READY; }else if(eemcs_state == EEMCS_EXCEPTION){ md_state = MD_STATE_EXPT; }else if(eemcs_state <= EEMCS_INIT){ md_state = MD_STATE_INVALID; }else{ md_state = MD_STATE_INIT; } ret = put_user((unsigned int)md_state, (unsigned int __user *)arg); DBGLOG(CHAR, DBG, "CCCI_IOC_GET_MD_STATE(md_s=%d, eemcs_s=%d) by %s(%d)", md_state, eemcs_state, \ ccci_cdev_name[PORT2IDX(port_id)], port_id); } break; case CCCI_IOC_SET_EXCEPTION_DATA: { DBGLOG(CHAR, ERR, "CCCI_IOC_SET_EXCEPTION_DATA by %s(%d)", ccci_cdev_name[PORT2IDX(port_id)], port_id); #if 0 extern EX_LOG_T md_ex_log; void __user *argp = (void __user *)arg; if(copy_from_user(&md_ex_log,argp,MD_EX_LOG_SIZE)) { DBGLOG(PORT,ERR,"copy_from_user failed."); return -EFAULT; } md_exception(&md_ex_log); #endif } break; case CCCI_IOC_SET_HEADER: { KAL_UINT32 ori_port_flag = 0; KAL_UINT32 new_port_flag = 0; //port->control_flag |=PORT_EXPORT_CCIF_BUFFER; ori_port_flag = ccci_get_port_cflag(port_id); ccci_set_port_type(port_id, (ori_port_flag|EXPORT_CCCI_H)); new_port_flag = ccci_get_port_cflag(port_id); DBGLOG(CHAR, DBG, "CCCI_IOC_SET_HEADER(%d, %d) by %s(%d)", ori_port_flag, new_port_flag,\ ccci_cdev_name[PORT2IDX(port_id)], port_id); } break; case CCCI_IOC_CLR_HEADER: { //port->control_flag &=(~PORT_EXPORT_CCIF_BUFFER); KAL_UINT32 ori_port_flag = 0; KAL_UINT32 new_port_flag = 0; ori_port_flag = ccci_get_port_cflag(port_id); ccci_set_port_type(port_id, (ori_port_flag&(~EXPORT_CCCI_H))); new_port_flag = ccci_get_port_cflag(port_id); DBGLOG(CHAR, DBG, "CCCI_IOC_CLR_HEADER(%d, %d) by %s(%d)", ori_port_flag, new_port_flag, \ ccci_cdev_name[PORT2IDX(port_id)], port_id); } break; /* This ioctl will be issued from RILD */ case CCCI_IOC_ENTER_DEEP_FLIGHT: case CCCI_IOC_SEND_STOP_MD_REQUEST: { DBGLOG(CHAR, INF, "IOTCL CCCI_IOC_ENTER_DEEP_FLIGHT by %s(%d)", ccci_cdev_name[PORT2IDX(port_id)], port_id); change_device_state(EEMCS_GATE); eemcs_power_off_md(0, 0); /* mtlte_sys_sdio_remove */ eemcs_cdev_msg(CCCI_PORT_CTRL, CCCI_MD_MSG_ENTER_FLIGHT_MODE, 0); } break; case CCCI_IOC_LEAVE_DEEP_FLIGHT: case CCCI_IOC_SEND_START_MD_REQUEST: { DBGLOG(CHAR, INF, "CCCI_IOC_LEAVE_DEEP_FLIGHT by %s(%d)", ccci_cdev_name[PORT2IDX(port_id)], port_id); eemcs_cdev_msg(CCCI_PORT_CTRL, CCCI_MD_MSG_LEAVE_FLIGHT_MODE, 0); } break; case CCCI_IOC_FORCE_MD_ASSERT: { DBGLOG(CHAR, INF, "CCCI_IOC_FORCE_MD_ASSERT by %s(%d)", ccci_cdev_name[PORT2IDX(port_id)], port_id); /* force md assert channel is 20090215 */ eemcs_cdev_write_force_md_rst(); //CCCI_INIT_MAILBOX(&buff, 0); //ret = ccci_write_force(CCCI_FORCE_RESET_MODEM_CHANNEL, &buff); } break; case CCCI_IOC_MD_RESET: { DBGLOG(CHAR, INF, "CCCI_IOC_MD_RESET by %s(%d)", ccci_cdev_name[PORT2IDX(port_id)], port_id); eemcs_md_reset(); } break; case CCCI_IOC_CHECK_STATE: { KAL_UINT32 state; state = check_device_state(); DBGLOG(CHAR, INF, "CCCI_IOC_CHECK_STATE(%d) by %s(%d)", state, ccci_cdev_name[PORT2IDX(port_id)], port_id); ret = put_user((unsigned int)state, (unsigned int __user *)arg); } break; #ifdef IT_TESTING_PURPOSE case CCCI_IOC_PURGE_SKBQ: { struct sk_buff *skb; while ((skb = skb_dequeue(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_skb_list)) != NULL) { dev_kfree_skb(skb); eemcs_ccci_release_rx_skb(port_id, 1, skb); } atomic_set(&eemcs_cdev_inst.cdev_node[PORT2IDX(port_id)].rx_pkt_cnt, 0); DBGLOG(CHAR, INF, "CCCI_IOC_PURGE_SKBQ by %s(%d)", ccci_cdev_name[PORT2IDX(port_id)], port_id); } break; #endif case CCCI_IOC_GET_EXT_MD_POST_FIX: { eemcs_boot_get_ext_md_post_fix((char*) arg); DBGLOG(CHAR, INF, "CCCI_IOC_GET_MD_POSTFIX(%s) by %s(%d)", (char*)arg, \ ccci_cdev_name[PORT2IDX(port_id)], port_id); } break; case CCCI_IOC_SET_BOOT_STATE: { KAL_UINT32 state = 0; get_user(state, (unsigned int __user *)arg); state = eemcs_boot_reset_test(state); DBGLOG(CHAR, INF, "CCCI_IOC_SET_BOOT_STATE(%d) by %s(%d)", state, \ ccci_cdev_name[PORT2IDX(port_id)], port_id); } break; case CCCI_IOC_GET_BOOT_STATE: { KAL_UINT32 state = 0; state = eemcs_boot_get_state(); ret = put_user((unsigned int)state, (unsigned int __user *)arg); DBGLOG(CHAR, INF, "CCCI_IOC_GET_BOOT_STATE(%d) by %s(%d)", state, \ ccci_cdev_name[PORT2IDX(port_id)], port_id); } break; case CCCI_IOC_GET_MD_IMG_EXIST: { unsigned int *md_img_exist_list = eemcs_get_md_img_exist_list(); DBGLOG(CHAR, INF,"CCCI_IOC_GET_MD_IMG_EXIST by %s(%d)", ccci_cdev_name[PORT2IDX(port_id)], port_id); if (copy_to_user((void __user *)arg, md_img_exist_list,(unsigned int)eemcs_get_md_img_exist_list_size())) { DBGLOG(CHAR, ERR, "CCCI_IOC_GET_MD_IMG_EXIST: copy_to_user fail"); ret= -EFAULT; } } break; case CCCI_IOC_GET_MD_TYPE: { int md_type = get_ext_modem_support(eemcs_get_md_id()); DBGLOG(CHAR, INF, "CCCI_IOC_GET_MD_TYPE(%d) by %s(%d)", md_type, \ ccci_cdev_name[PORT2IDX(port_id)], port_id); ret = put_user((unsigned int)md_type, (unsigned int __user *)arg); } break; case CCCI_IOC_RELOAD_MD_TYPE: { int md_type = 0; if(copy_from_user(&md_type, (void __user *)arg, sizeof(unsigned int))) { DBGLOG(CHAR, ERR, "CCCI_IOC_RELOAD_MD_TYPE: copy_from_user fail!"); ret = -EFAULT; break; } if (md_type >= modem_lwg && md_type <= modem_ltg){ DBGLOG(CHAR, INF, "CCCI_IOC_RELOAD_MD_TYPE(%d) by %s(%d)", md_type, \ ccci_cdev_name[PORT2IDX(port_id)], port_id); ret = set_ext_modem_support(eemcs_get_md_id(), md_type); } else{ DBGLOG(CHAR, ERR, "CCCI_IOC_RELOAD_MD_TYPE fail: invalid md type(%d)", md_type); ret = -EFAULT; } eemcs_set_reload_image(true); } break; case CCCI_IOC_STORE_MD_TYPE: { unsigned int md_type_saving = 0; //DBGLOG(CHAR, INF, "IOC_STORE_MD_TYPE ioctl by %s!", current->comm); if(copy_from_user(&md_type_saving, (void __user *)arg, sizeof(unsigned int))) { DBGLOG(CHAR, ERR, "CCCI_IOC_STORE_MD_TYPE: copy_from_user fail!"); ret = -EFAULT; break; } DBGLOG(CHAR, DBG, "CCCI_IOC_STORE_MD_TYPE(%d) by %s(%s,%d)", md_type_saving, current->comm,\ ccci_cdev_name[PORT2IDX(port_id)], port_id); if (md_type_saving >= modem_lwg && md_type_saving <= modem_ltg){ if (md_type_saving != get_ext_modem_support(eemcs_get_md_id())){ DBGLOG(CHAR, INF, "CCCI_IOC_STORE_MD_TYPE(%d->%d)", md_type_saving, get_ext_modem_support(eemcs_get_md_id())); } //Notify md_init daemon to store md type in nvram eemcs_cdev_msg(CCCI_PORT_CTRL, CCCI_MD_MSG_STORE_NVRAM_MD_TYPE, md_type_saving); } else { DBGLOG(CHAR, ERR, "CCCI_IOC_STORE_MD_TYPE fail: invalid md type(%d)", md_type_saving); ret = -EFAULT; } } break; case CCCI_IOC_GET_MD_EX_TYPE: { int md_expt_type = get_md_expt_type(); DBGLOG(CHAR, INF, "CCCI_IOC_GET_MD_EX_TYPE(%d) by %s(%d)", md_expt_type, \ ccci_cdev_name[PORT2IDX(port_id)], port_id); ret = put_user((unsigned int)md_expt_type, (unsigned int __user *)arg); } break; case CCCI_IOC_DL_TRAFFIC_CONTROL: { unsigned int traffic_control = 0; if(copy_from_user(&traffic_control, (void __user *)arg, sizeof(unsigned int))) { DBGLOG(CHAR, ERR, "CCCI_IOC_DL_TRAFFIC_CONTROL: copy_from_user fail!"); ret = -EFAULT; break; } DBGLOG(CHAR, INF, "CCCI_IOC_DL_TRAFFIC_CONTROL(%d) by %s(%d)", traffic_control,\ ccci_cdev_name[PORT2IDX(port_id)], port_id); if(traffic_control == 1) { ccci_cdev_turn_on_dl_q(port_id); } else if(traffic_control == 0) { ccci_cdev_turn_off_dl_q(port_id); } else { DBGLOG(CHAR, ERR, "CCCI_IOC_DL_TRAFFIC_CONTROL fail: Unknown value(0x%x)", traffic_control); ret = -EFAULT; } } break; case CCCI_IOC_GET_SIM_TYPE: //for regional phone boot animation { get_sim_type(eemcs_get_md_id(), &sim_type); ret = put_user((unsigned int)sim_type, (unsigned int __user *)arg); } break; case CCCI_IOC_ENABLE_GET_SIM_TYPE: //for regional phone boot animation { if(copy_from_user(&enable_sim_type, (void __user *)arg, sizeof(unsigned int))) { DBGLOG(CHAR, ERR, "CCCI_IOC_ENABLE_GET_SIM_TYPE: copy_from_user fail!\n"); ret = -EFAULT; } else { enable_get_sim_type(eemcs_get_md_id(), enable_sim_type); } } break; default: DBGLOG(CHAR, ERR, "Unknown ioctl(0x%x) by %s(%d)", cmd, ccci_cdev_name[PORT2IDX(port_id)], port_id); ret = -EFAULT; break; } _exit: DEBUG_LOG_FUNCTION_LEAVE; return ret; }
int eemcs_cdev_msg(int port_id, unsigned int message, unsigned int reserved){ struct sk_buff *new_skb; CCCI_BUFF_T *pccci_h; ccci_port_cfg *port_cfg; DEBUG_LOG_FUNCTION_ENTRY; new_skb = dev_alloc_skb(sizeof(CCCI_BUFF_T)); if(new_skb == NULL){ DBGLOG(CHAR,ERR,"dev_alloc_skb fail(size=%d).", sizeof(CCCI_BUFF_T)); DEBUG_LOG_FUNCTION_LEAVE; return KAL_FAIL; } pccci_h = (CCCI_BUFF_T *)new_skb->data; memset(pccci_h, 0, sizeof(CCCI_BUFF_T)); port_cfg = ccci_get_port_info(port_id); pccci_h->data[0] = CCCI_MAGIC_NUM; pccci_h->data[1] = message; pccci_h->channel = port_cfg->ch.rx; pccci_h->reserved = reserved; DBGLOG(CHAR, DBG, "%s(%d) send cdev_msg: 0x%08X, 0x%08X, %02d, 0x%08X", ccci_cdev_name[PORT2IDX(port_id)],\ port_id, pccci_h->data[0], pccci_h->data[1], pccci_h->channel, pccci_h->reserved); if(port_id == CCCI_PORT_CTRL){ return eemcs_boot_rx_callback(new_skb, 0); }else{ return eemcs_cdev_rx_callback(new_skb, 0); } }