static int  __ccif_v1_write_phy_ch_data(ccif_t* ccif, unsigned int buf[], int retry_en)
{
    int             ret = 0;
    unsigned int    busy;
    unsigned long    flag;
    unsigned int    retry_count = 200;
    unsigned int    ch;
    ccif_msg_t        *tx_msg;
    int md_id = ccif->m_md_id;

    CCCI_FUNC_ENTRY(md_id);
    if(retry_en == 0)
        retry_count = 1;

    do{
        spin_lock_irqsave(&ccif->m_lock, flag);
        busy=ccci_read32(CCIF_BUSY(ccif->m_reg_base));

        ch = ccif->m_tx_idx;
        if (busy&(1<<ch)) {                
            ret = -CCCI_ERR_CCIF_NO_PHYSICAL_CHANNEL;
            if (busy != 0xff) {
                CCCI_DBG_MSG(md_id, "cci", "Wrong Busy value: 0x%X\n", busy);
            }
            spin_unlock_irqrestore(&ccif->m_lock,flag);
            
            udelay(1);
            retry_count--;
        } else {
            ccci_write32(CCIF_BUSY(ccif->m_reg_base), 1<<ch);
            ccif->m_tx_idx++;
            ccif->m_tx_idx &= (CCIF_STD_V1_MAX_CH_NUM-1);
            //spin_unlock_irqrestore(&ccif->m_lock,flag);
            
            //mb(); // Note here, make sure data has write to memory be really send
            tx_msg = (ccif_msg_t*)(CCIF_TXCHDATA(ccif->m_reg_base));
            ccci_write32(&(tx_msg[ch].data[0]), buf[0]);
            ccci_write32(&(tx_msg[ch].data[1]), buf[1]);
            ccci_write32(&(tx_msg[ch].channel), buf[2]);
            ccci_write32(&(tx_msg[ch].reserved), buf[3]);
            //mb();

            ccci_write32(CCIF_TCHNUM(ccif->m_reg_base), ch);
            
            spin_unlock_irqrestore(&ccif->m_lock,flag);

            ret = sizeof(ccif_msg_t);
            break;
        }
    }while(retry_count>0);

    if(lg_ch_tx_debug_enable[md_id] & (1<< buf[2])) 
        CCCI_MSG_INF(md_id, "cci", "[TX]: %08X, %08X, %02d, %08X (%02d)\n",
             buf[0], buf[1], buf[2], buf[3], ch);

    return ret;
}
static void __ccif_v1_dis_intr(ccif_t* ccif)
{
    unsigned long flag;
    CCCI_FUNC_ENTRY(ccif->m_md_id);

    spin_lock_irqsave(&ccif->m_lock,flag);
    if(ccif->m_irq_dis_cnt == 0) {
        disable_irq(ccif->m_irq_id);
        ccif->m_irq_dis_cnt++;
    }
    spin_unlock_irqrestore(&ccif->m_lock,flag);
}
static int __ccif_v1_en_intr(ccif_t* ccif)
{
    unsigned long flag;
    CCCI_FUNC_ENTRY(ccif->m_md_id);

    spin_lock_irqsave(&ccif->m_lock,flag);
    if(ccif->m_irq_dis_cnt) {
        enable_irq(ccif->m_irq_id);
        ccif->m_irq_dis_cnt--;
    }
    spin_unlock_irqrestore(&ccif->m_lock,flag);

    return 0;
}
int ccci_logic_ctlb_init(int md_id)
{
	int							ret = 0;
	ccif_t						*ccif;
	logic_channel_info_t		*ch_info;
	int							ch_id, ch_attr, i;
	logic_dispatch_ctl_block_t	*ctl_b;
	char						ccci_name[CCCI_WAKEUP_LOCK_NAME_LEN];
	ccif_hw_info_t				ccif_hw_inf;

	CCCI_FUNC_ENTRY(md_id);

	// Channel number check
	if((sizeof(logic_ch_static_info_tab)/sizeof(logic_channel_static_info_t)) != CCCI_MAX_CH_NUM) {
		CCCI_MSG_INF(md_id, "cci", "%s: channel max number mis-match fail\n", __FUNCTION__);
		return -CCCI_ERR_CHANNEL_NUM_MIS_MATCH;
	}

	// Allocate ctl block memory
	ctl_b = (logic_dispatch_ctl_block_t*)kzalloc(sizeof(logic_dispatch_ctl_block_t), GFP_KERNEL);
	if(ctl_b == NULL) {
		CCCI_MSG_INF(md_id, "cci", "%s: alloc memory fail for logic_dispatch_ctlb\n", __FUNCTION__);
		return -CCCI_ERR_ALLOCATE_MEMORY_FAIL;
	}
	logic_dispatch_ctlb[md_id] = ctl_b;

	// Get CCIF HW info
	if(get_ccif_hw_info(md_id, &ccif_hw_inf) < 0) {
		CCCI_MSG_INF(md_id, "cci", "%s: get ccif%d hw info fail\n", __FUNCTION__, md_id+1);
		ret = -CCCI_ERR_CCIF_GET_HW_INFO_FAIL;
		goto _ccif_instance_create_fail;
	}
	
	// Create ccif instance
	ccif = ccif_create_instance(&ccif_hw_inf, ctl_b, md_id);
	if(ccif == NULL) {
		CCCI_MSG_INF(md_id, "cci", "%s: create ccif instance fail\n", __FUNCTION__);
		ret = -CCCI_ERR_CREATE_CCIF_INSTANCE_FAIL;
		goto _ccif_instance_create_fail;
	}
	
	ccif->ccif_init(ccif);
	ctl_b->m_ccif = ccif;

	// Initialize logic channel and its kfifo///???anny
	// Step1, set all runtime channel id to CCCI_INVALID_CH_ID means default state
	// So, even if static channel table is out of order, we can make sure logic_dispatch_ctlb's channel
	// table is in order
	for(i = 0; i < CCCI_MAX_CH_NUM; i++)
	{
		ch_info = &ctl_b->m_logic_ch_table[i];
		ch_info->m_ch_id = CCCI_INVALID_CH_ID;
	}
	
	// Step2, set all runtime channel info according to static channel info, make it in order
	for(i = 0; i < CCCI_MAX_CH_NUM; i++)
	{
		ch_id = logic_ch_static_info_tab[i].m_ch_id;
		ch_info = &ctl_b->m_logic_ch_table[ch_id];
		
		if (ch_info->m_ch_id != CCCI_INVALID_CH_ID) {
			CCCI_MSG_INF(md_id, "cci", "[Error]%s: ch%d has registered\n", __FUNCTION__, ch_id);
			ret = -CCCI_ERR_REPEAT_CHANNEL_ID;
			goto _ccif_logic_channel_init_fail;
		} else {
			ch_info->m_ch_id = ch_id;
			ch_info->m_attrs = logic_ch_static_info_tab[i].m_attrs;
			ch_info->m_ch_name = logic_ch_static_info_tab[i].m_ch_name;
			ch_info->m_call_back = NULL;
			
			if(logic_ch_static_info_tab[i].m_kfifo_size) {
				if (0 != kfifo_alloc(&ch_info->m_kfifo, sizeof(ccif_msg_t)*logic_ch_static_info_tab[i].m_kfifo_size, GFP_KERNEL)) {
					CCCI_MSG_INF(md_id, "cci", "%s: alloc kfifo fail for %s(ch%d) \n", \
						__FUNCTION__, ch_info->m_ch_name, ch_id);
					
					ch_info->m_kfifo_ready = 0;
					ret = CCCI_ERR_ALLOCATE_MEMORY_FAIL;
					goto _ccif_logic_channel_init_fail;
				} else {
					ch_info->m_kfifo_ready = 1;
					ch_info->m_md_id = md_id;
				}
			} else {
				ch_info->m_kfifo_ready = 0;
			}
			
			spin_lock_init(&ch_info->m_lock);
		}

		//initial channel recording info
		if(logic_ch_static_info_tab[i].m_attrs&L_CH_ATTR_TX)
			ch_attr = CCCI_LOG_TX;
		else
			ch_attr = CCCI_LOG_RX;
		statistics_init_ch_dir(md_id, ch_id, ch_attr);
	}

	// Init logic_dispatch_ctlb
	tasklet_init(&ctl_b->m_dispatch_tasklet,__logic_layer_tasklet,(unsigned long)ctl_b);
	ctl_b->m_has_pending_data = 0;
	ctl_b->m_freezed = 0;
	ctl_b->m_running = 0;
	//ctl_b->m_privilege = MD_BOOT_STAGE_0;
	ctl_b->m_md_id = md_id;
	snprintf(ccci_name, CCCI_WAKEUP_LOCK_NAME_LEN, "ccci_wk%d", md_id); 
	wake_lock_init(&ctl_b->m_wakeup_wake_lock, WAKE_LOCK_SUSPEND, ccci_name);
	ctl_b->m_send_notify_cb = NULL;
	spin_lock_init(&ctl_b->m_lock);

	// Init CCIF now
	ccif->register_call_back_func(ccif, __logic_dispatch_push, __let_logic_dispatch_tasklet_run);
	//ccif->ccif_register_intr(ccif);
	
	// Init done
	//CCCI_DBG_MSG(md_id, "cci", "ccci_logic_ctlb_init success!\n");
	return ret;

_ccif_logic_channel_init_fail:
	for(i = 0; i < CCCI_MAX_CH_NUM; i++)
	{
		ch_info = &ctl_b->m_logic_ch_table[i];
		if(ch_info->m_kfifo_ready){
			kfifo_free(&ch_info->m_kfifo);
			ch_info->m_kfifo_ready = 0;
		}
	}

_ccif_instance_create_fail:
	kfree(ctl_b);
	logic_dispatch_ctlb[md_id] = NULL;
	
	return ret;
}
static int __ccif_v1_intr_handler(ccif_t *ccif)
{
    ccif_msg_t        phy_ch_data;
    int                re_enter_cnt = 0;
    int                r_ch_val;
    int                i;
    int                rx_ch;
    int                md_id = ccif->m_md_id;
    bool             reg_err = FALSE;
    unsigned int    msg[4];

    CCCI_FUNC_ENTRY(md_id);
    set_bit(CCIF_TOP_HALF_RUNNING,&ccif->m_status);
                            
    //CCCI_DBG_MSG(md_id, "cci", "ISR\n");
                            
    if(ccif->isr_notify)
        ccif->isr_notify(md_id);

    rx_ch = ccif->m_rx_idx;

    while( (r_ch_val = ccif->ccif_get_rx_ch(ccif)) && (re_enter_cnt<CCIF_INTR_MAX_RE_ENTER_CNT) )
    {
        for(i=0; i<CCIF_STD_V1_MAX_CH_NUM; i++)
        {
            if (r_ch_val&(1<<rx_ch)) {
                // We suppose always read success
                ccif->ccif_read_phy_ch_data(ccif, rx_ch, (unsigned int*)&phy_ch_data);
                #ifdef CCIF_DEBUG
                if (phy_ch_data.channel >= CCCI_MAX_CH_NUM) {
                    if (!reg_err) {
                        reg_err = TRUE;
                        __ccif_v1_dump_reg(ccif, NULL, 0);
                        CCCI_MSG_INF(md_id, "cci", "[CCIF Register Error]RX: %08X, %08X, %02d, %08X (%02d)\n", phy_ch_data.data[0], \
                            phy_ch_data.data[1], phy_ch_data.channel, phy_ch_data.reserved, rx_ch);
                    }
                }
                #endif

                if((lg_ch_rx_debug_enable[md_id] & ENABLE_ALL_RX_LOG) || 
                    (lg_ch_rx_debug_enable[md_id] & (1<< phy_ch_data.channel))) {
                    CCCI_DBG_MSG(md_id, "cci", "[RX]: %08X, %08X, %02d, %08X (%02d)\n", phy_ch_data.data[0], \
                        phy_ch_data.data[1], phy_ch_data.channel, phy_ch_data.reserved, rx_ch);
                }

                // push ccif message to up layer
                if (unlikely(ccif->push_msg == NULL)) {
                    CCCI_DBG_MSG(md_id, "cci", "push_msg func not registered:0x%08x, 0x%08x, %02d, 0x%08x\n", \
                            phy_ch_data.data[0], phy_ch_data.data[1], phy_ch_data.channel, phy_ch_data.reserved);
                } else {
                    if ( ccif->push_msg(&phy_ch_data, ccif->m_logic_ctl_block) != sizeof(ccif_msg_t) ) {
                        //CCCI_DBG_MSG(md_id, "cci", "push data fail(ch%d)\n", phy_ch_data.channel);
                    }
                }

                // Ack modem side ccif
                ccci_write32(CCIF_ACK(ccif->m_reg_base), (1<<rx_ch));

                r_ch_val &=~(1<<rx_ch);
            } else  {
                if (r_ch_val != 0) {
                    // We suppose rx channel usage should be fifo mode
                    CCCI_DBG_MSG(md_id, "cci", "rx channel error(rx>%02x : %d<curr)\n", r_ch_val, rx_ch);
                    __ccif_v1_dump_reg(ccif, NULL, 0);
                } else {
                    break;
                }
            }
            ++rx_ch;
            rx_ch = rx_ch&(CCIF_STD_V1_MAX_CH_NUM-1);
        }
        re_enter_cnt++;
    }
    
    if( (re_enter_cnt>=CCIF_INTR_MAX_RE_ENTER_CNT) && (r_ch_val!=0) ) {
        CCCI_DBG_MSG(md_id, "cci", "too much message to process\n");
        __ccif_v1_dump_reg(ccif, NULL, 0);
    }

    // Store latest rx channel index
    ccif->m_rx_idx = rx_ch;

    // Notify uplayer begin to process data
    if (unlikely(ccif->notify_push_done == NULL)) {
        //CCCI_DBG_MSG(md_id, "cci", "notify_push_done not registered!\n");
    } else {
        ccif->notify_push_done(ccif->m_logic_ctl_block);
    }

    clear_bit(CCIF_TOP_HALF_RUNNING,&ccif->m_status);

    
    #ifdef CCIF_DEBUG
    if (reg_err) {        
        reg_err = FALSE;
        msg[0]    = 0xFFFFFFFF;
        msg[1]    = 0x5B5B5B5B;
        msg[2]    = CCCI_FORCE_ASSERT_CH;
        msg[3]  = 0xB5B5B5B5;
        __ccif_v1_write_phy_ch_data(ccif, msg, 0);
    }
    #endif

    return 0;
}