SMSM为处理状态而非数据的共享内存,主要就电源管理、共享内存、定时器、进程状态等信息在多核之间进行通信。SMSM的实现框架和SMD数据通信的实现类似。
SMSM的状态共有: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等。
在实际应用上,SMSM主要在处理器发生状态变化,以及发生中断、重设基带处理器时运行,下面结合处理器状态变化和中断等两种情况简要介绍SMSM的处理过程。
处理处理器的变化,首先判断接入点的有效性,是应用处理器还是基带处理器等。如果接入点有效,就分配共享内存,并将相应的信息通知给其他的SMSM,下面是smsm_change_state()函数的实现:
代码1-1 SMSM改变状态的过程
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));//分配共享内存
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;
}
当INT_A9_M2A_5和INT_ADSP_A11中断发生时,会触发SMSM的中断处理函数,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));//分配内存
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));//分配内存
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响应假中断
modem_queue_start_reset_notify(); //发起重设提醒
} 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;
}