SMSM為處理狀態(tài)而非數(shù)據(jù)的共享內(nèi)存,主要就電源管理、共享內(nèi)存、定時(shí)器、進(jìn)程狀態(tài)等信息在多核之間進(jìn)行通信。SMSM的實(shí)現(xiàn)框架和SMD數(shù)據(jù)通信的實(shí)現(xiàn)類似。
SMSM的狀態(tài)共有:SMSM_INIT、SMSM_OSENTERED、SMSM_SMDWAIT、SMSM_SMDINIT、SMSM_RPCWAIT、SMSM_RPCINIT、SMSM_RESET、SMSM_RSA、SMSM_RUN、SMSM_PWRC、SMSM_TIMEWAIT、SMSM_TIMENIT、SMSM_PWRC_ EARLY_EXIT、SMSM_WFPI、SMSM_SLEEP、SMSM_SLEEPEXIT、SMSM_OEMSBL_ RELEASE、SMSM_APPS_REBOOT、SMSM_SYSTEM_POWER_DOWN、SMSM_SYSTEM_ REBOOT、SMSM_SYSTEM_DOWNLOAD、SMSM_PWRC_SUSPEND、SMSM_APPS_ SHUTDOWN、SMSM_SMD_LOOPBACK、SMSM_RUN_QUIET、SMSM_MODEM_WAIT、SMSM_MODEM_BREAK、SMSM_MODEM_CONTINUE、SMSM_UNKNOWN等。
在實(shí)際應(yīng)用上,SMSM主要在處理器發(fā)生狀態(tài)變化,以及發(fā)生中斷、重設(shè)基帶處理器時(shí)運(yùn)行,下面結(jié)合處理器狀態(tài)變化和中斷等兩種情況簡(jiǎn)要介紹SMSM的處理過程。
處理處理器的變化,首先判斷接入點(diǎn)的有效性,是應(yīng)用處理器還是基帶處理器等。如果接入點(diǎn)有效,就分配共享內(nèi)存,并將相應(yīng)的信息通知給其他的SMSM,下面是smsm_change_state()函數(shù)的實(shí)現(xiàn):
代碼1-1 SMSM改變狀態(tài)的過程
int smsm_change_state(uint32_t smsm_entry,uint32_t clear_mask, uint32_t set_mask)
{
unsigned long flags;
uint32_t *smsm;
uint32_t old_state;
if (smsm_entry >= SMSM_NUM_ENTRIES)
{ //判斷有效性
printk(KERN_ERR "smsm_change_state: Invalid entry %d",smsm_entry);
return -EINVAL;
}
spin_lock_irqsave(&smem_lock, flags);
smsm=smem_alloc(ID_SHARED_STATE,SMSM_NUM_ENTRIES * sizeof(uint32_t));//分配共享內(nèi)存
if (smsm) {
old_state=smsm[smsm_entry];
smsm[smsm_entry]=(smsm[smsm_entry] & ~clear_mask) | set_mask;
if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
printk(KERN_INFO "smsm_change_state %x\n",smsm[smsm_entry]);
notify_other_smsm(SMSM_APPS_STATE, old_state, smsm[smsm_entry]);
} //通知其他SMSM
spin_unlock_irqrestore(&smem_lock, flags);
if (smsm==NULL) {
printk(KERN_ERR "smsm_change_state< SM NO STATE>\n");
return -EIO;
}
return 0;
}
當(dāng)INT_A9_M2A_5和INT_ADSP_A11中斷發(fā)生時(shí),會(huì)觸發(fā)SMSM的中斷處理函數(shù),SMSM處理中斷的過程如下:
代碼1-2 SMSM處理中斷的過程
static irqreturn_t smsm_irq_handler(int irq, void *data)
{
unsigned long flags;
uint32_t *smsm;
static uint32_t prev_smem_q6_apps_smsm;
if (irq==INT_ADSP_A11) {
smsm=smem_alloc(SMEM_SMD_SMSM_INTR_MUX,SMSM_NUM_INTR_MUX * sizeof(uint32_t));//分配內(nèi)存
if (!smsm ||
(smsm[SMEM_Q6_APPS_SMSM]==prev_smem_q6_apps_smsm))
return IRQ_HANDLED;
prev_smem_q6_apps_smsm=smsm[SMEM_Q6_APPS_SMSM];
}
spin_lock_irqsave(&smem_lock, flags);
smsm=smem_alloc(ID_SHARED_STATE,SMSM_NUM_ENTRIES * sizeof(uint32_t));//分配內(nèi)存
if (smsm==0) {
printk(KERN_INFO "< SM NO STATE>\n");
} else {
unsigned old_apps, apps;
unsigned modm=smsm[SMSM_MODEM_STATE];
old_apps=apps=smsm[SMSM_APPS_STATE];
if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
printk(KERN_INFO "< SM %08x %08x>\n", apps, modm);
if (apps & SMSM_RESET) {
apps &=~SMSM_RESET;
smd_fake_irq_handler(0); //讓SMD響應(yīng)假中斷
modem_queue_start_reset_notify(); //發(fā)起重設(shè)提醒
} else if (modm & SMSM_RESET) {
apps |=SMSM_RESET;
} else {
apps|=SMSM_INIT;
if (modm & SMSM_SMDINIT)
apps|=SMSM_SMDINIT;
if (modm & SMSM_RPCINIT)
apps|=SMSM_RPCINIT;
if ((apps & (SMSM_INIT|SMSM_SMDINIT|SMSM_RPCINIT))==
(SMSM_INIT|SMSM_SMDINIT|SMSM_RPCINIT))
apps|=SMSM_RUN;
}
if (smsm[SMSM_APPS_STATE]!=apps) {
if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
printk(KERN_INFO "< SM %08x NOTIFY>\n", apps);
smsm[SMSM_APPS_STATE]=apps;
do_smd_probe();
notify_other_smsm(SMSM_APPS_STATE, old_apps, apps);
//通知其他SMSM
}
}
spin_unlock_irqrestore(&smem_lock, flags);
return IRQ_HANDLED;
}