msm8994 热插拔sim卡导致modem重新启动的流程

作者:lover713814 发布于:2015-5-28 15:23

Modem侧重新激活协议栈之后会调用mcfg_utils_reset_modem

mcfg_utils_reset_modem->

     result = efs_sync ("/");

     sys_m_request_peripheral_restart_ssreq(&mcfg_utils_sys_m_ssreq_reset_cb);

          ssreq_process_request(SSREQ_PERIPHERAL_RESTART, ind_cb_fn);

               case SSREQ_PERIPHERAL_RESTART:

                    ssreq_restart_peripheral();

                         ssreq_p_restart_req.ss_client_id = SSREQ_QMI_CLIENT_INSTANCE_MPSS_V01;

                         qmi_client_send_msg_sync(ssreq_client_handle, SSREQ_PERIPHERAL_RESTART,(void*)&ssreq_p_restart_req,sizeof(ssreq_p_restart_req),

                                  (void*)&ssreq_p_restart_resp,sizeof(ssreq_p_restart_resp),0 );//QMI_SSREQ_PERIPHERAL_RESTART_REQ_V01 0x0022//1 发送复位请求给AP

 

------------------------------------------------------------------------------------------------------------------

AP 侧收到QMI_SSREQ_PERIPHERAL_RESTART_REQ_V01的处理流程

in /msm8994_c3012.2/vendor/qcom/proprietary/peripheral-manager/pm-server/PeripheralManagerServer.cpp

qmi_csi_cb_error qmiServerProcessRequest(void *__qmiClient,qmi_req_handle reqHandle,unsigned int msgId, void *reqStruct,unsigned int reqStructLen,void *__pmService)

     case QMI_SSREQ_PERIPHERAL_RESTART_REQ_V01:

          qmiServerPeripheralRestart(qmiClient, reqHandle, msgId,reqStruct, pmService);

               pmService->restartPeripheral(identifier, qmiClient);

                    peripheral = findBySubSystem(identifier);

                    started = peripheral->setRestartRequested((void *)qmiClient);

                         notifyClients(EVENT_PERIPH_GOING_OFFLINE);

                              client->eventSend(event);

                                   mClientCb->notifyCallback((int32_t)event);

                                   //pm_proxy_event_notifier ssctl_shutdown_cb app_event_notifier qmi_ril_pm_event_notifier

                                   //all thest four call back function will call below function

                                        pm_client_event_acknowledge(client_cookie, event);

                                             client->ops->acknowledge(client->id, (int64_t)event);

                                             //it should call PeripheralManagerServer::acknowledge,but I don't know how!!

                                                  peripheral->notifyClientAck(client, (enum pm_event)event);

               response.resp.result = QMI_RESULT_SUCCESS_V01;

               response.resp.error = QMI_ERR_NONE_V01;

               qmi_csi_send_resp(reqHandle, msgId, &response, sizeof(response));//2 modem侧回复复位请求的resp

 

peripheral->notifyClientAck(client, (enum pm_event)event);

     case EVENT_PERIPH_GOING_OFFLINE:

          sendRestartIndication();

               client = (qmi_client_handle)mRestartRequestor;

               msgId = QMI_SSREQ_PERIPHERAL_RESTART_IND_V01;

               ind.status = SSREQ_QMI_REQUEST_SERVICED_V01;

               ret = qmi_csi_send_ind(client, msgId, &ind, sizeof(ind));//3发送QMI_SSREQ_PERIPHERAL_RESTART_IND_V01modem

               if (mFileDesc > 0) {

                    if (!mSimulationMode)

                         ret = close(mFileDesc);//will call subsys_device_close to ask modem do graceful reset//5 进行modem close 的流程               

mFileDesc = -1;

               mPowerOffCount++;

               notifyClients(EVENT_PERIPH_IS_OFFLINE);//6 change state to is offline

     case EVENT_PERIPH_IS_OFFLINE

          if (isRestartRequested())

               setRestartRequested(NULL);

               notifyClients(EVENT_PERIPH_GOING_ONLINE);//7 change state to going online

     case EVENT_PERIPH_GOING_ONLINE:

          if (mFileDesc < 0)

               if (!mSimulationMode)

                    mFileDesc = open(mDeviceFile, O_RDONLY);//8 will call subsys_device_open to reload and power on the modem

                mFileDesc = 1;

          if (mFileDesc > 0)

               mPowerOnCount++;

          if (mFileDesc > 0) {

               notifyClients(EVENT_PERIPH_IS_ONLINE);

 

subsys_device_close

     subsystem_put(subsys_dev);

          subsys_stop(subsys);

               subsys->desc->sysmon_shutdown_ret = sysmon_send_shutdown(subsys->desc);//5.1modem发送QMI_SSCTL_SHUTDOWN_REQ_V02,让modem自己做内部的shutdown 准备,并等待resp

 

               notify_each_subsys_device(&subsys, 1, SUBSYS_BEFORE_SHUTDOWN, NULL);//通知其他子系统

               subsys->desc->shutdown(subsys->desc, false);//5.2调用modem shutdown 函数给modem关机

               subsys_set_state(subsys, SUBSYS_OFFLINE);

               disable_all_irqs(subsys);

               notify_each_subsys_device(&subsys, 1, SUBSYS_AFTER_SHUTDOWN, NULL);

 

sysmon_send_shutdown

     req_desc.msg_id = QMI_SSCTL_SHUTDOWN_REQ_V02//同步发送给modem并等待应答表示modem已经graceful shutdown 完毕

 

-------------------------------------------------------------------------------------------------------------------

4 Modem 收到 AP发送的QMI_SSREQ_PERIPHERAL_RESTART_IND_V01后的处理

mcfg_utils_sys_m_ssreq_reset_cb

     mcfg_utils_cmd_send(MCFG_UTILS_CMD_RESET);

          utils_cmd_data = (mcfg_utils_cmd_data_s_type *) cmd->data;

          utils_cmd_data->cmd_id = utils_cmd;

          mcfg_task_cmd_send(cmd)

 

case MCFG_UTILS_CMD_RESET

     timer_set(&mcfg_utils_reset_timer, MCFG_UTILS_RESET_TIMER_TIMEOUT,0, T_SEC);

timer 超时后会调用

     mcfg_utils_cmd_reset_timer_cb 会重新调用

  mcfg_utils_reset_modem(

#ifdef MCFG_MODEM_INITITIATED_GRACEFUL_RESET_SUPPORT_W_REASON

    SSREQ_QMI_RES_MODEM_CONF_CHANGE

#endif

  );

 

-------------------------------------------------------------------------------------------------------------------

6 Modem 收到 AP发送的QMI_SSCTL_SHUTDOWN_REQ_V02后的处理

ssctl_v02_ser_process_req

     caseQMI_SSCTL_SHUTDOWN_REQ_V02:

          qmi_csi_send_resp(req_handle, msg_id, response, sizeof(qmi_ssctl_shutdown_resp_msg_v02));//7 其实modem内部还没有准备完毕就发送response
          sys_m_shutdown(SYS_M_QMI);

               sys_m_shutdown_internal();//modem 自己内部走重启流程,但是不用errfatal的方式通知AP

               rcecb_signal_name(SYS_M_SHUTDOWN);//发送SYS_M_SHUTDOWN,会触发注册了这个消息的call back 函数。

               req_count = rcevt_getcontexts_name(SYS_M_SHUTDOWN);//得到注册了SYS_M_SHUTDOWN的task的数目

               orig_ack_count = rcevt_getcount_name(SYS_M_SHUTDOWN_ACK);//得到注册了SYS_M_SHUTDOWN_ACK的task的数目

               rcevt_signal_name(SYS_M_SHUTDOWN);//发送SYS_M_SHUTDOWN,会触发注册了这个signal的task运行

               rcevt_wait_count_name(SYS_M_SHUTDOWN_ACK, req_count + orig_ack_count);//等待应答。

          err = qmi_csi_send_ind((qmi_sys_m_client.qmi_client_handle),QMI_SSCTL_SHUTDOWN_READY_IND_V02,&ind,sizeof(qmi_ssctl_shutdown_ind_msg_v02));

          HAL_dogDisable();

          qurt_exception_raise_fatal();//这个看不到代码,不知道是做什么用的,不过按理说不应走raise什么fatal

          while(1){}//死循环,等待被复位

评论:

wilson
2015-12-22 15:14
最近也在学习qualcomm的modem模块,调试就是qxdm抓log给高通,像这种qmi这种文档都看不到。楼主能不能讲下modem调试的方法呢
lover713814
2016-02-24 10:12
@wilson:@wilson 这个文档可以从高通的网站下,如果你们公司有和高通签署协议的话,但是私下高通的文档是不能随便share的,因为都盖着个人邮箱的水印呢。 我不知道你说的调试方法是指哪方面的?我是modem 和ap底层的。
lover713814
2016-05-05 11:28
@wilson:可以加我微信 zhangfan747551 聊

发表评论:

Copyright @ 2013-2015 蜗窝科技 All rights reserved. Powered by emlog