Skip to content

Commit 11208dd

Browse files
yliu80lijinxia
authored andcommitted
IOC mediator: Implement state transfer framework
Implements state transfer framework to support IOC lifecycle virtualization. Four states will be involved in this framework includes INIT, ACTIVE,SUSPENDING and SUSPENDED. Signed-off-by: Liu Yuan <yuan1.liu@intel.com> Reviewed-by: Wang Yu <yu1.wang@intel.com> Reviewed-by: Liu Shuo <shuo.a.liu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 92da8f4 commit 11208dd

File tree

2 files changed

+198
-3
lines changed

2 files changed

+198
-3
lines changed

devicemodel/hw/platform/ioc.c

Lines changed: 161 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,59 @@ static int dummy1_sfd = -1;
139139
static int dummy2_sfd = -1;
140140
#endif
141141

142+
/*
143+
* IOC State Transfer
144+
*
145+
* +-----------+ RESUME EVENT +-----------+
146+
* | INIT +<---------------------------+ SUSPENDED |
147+
* +-----+-----+ +-----------+
148+
* | ^
149+
* | |
150+
* |HB ACTIVE |SHUTDOWN
151+
* |EVENT |EVENT
152+
* | |
153+
* | |
154+
* v RAM REFRESH EVENT/ |
155+
* +-----+-----+ HB INACTIVE EVENT +-----+-----+
156+
* | ACTIVE +--------------------------->+SUSPENDING |
157+
* +-----------+ +-----------+
158+
*
159+
* INIT state: The state is IOC mediator initialized IOC state, all of CBC
160+
* protocol packats are handler normally. In this state, UOS has
161+
* not yet sent active heartbeat.
162+
*
163+
* ACTIVE state: Enter this state if HB ACTIVE event is triggered that indicates
164+
* UOS state has been active and need to set the bit 23(SoC active
165+
* bit) in the wakeup reason.
166+
*
167+
* SUSPENDING state: Enter this state if RAM REFRESH event or HB INACTIVE event
168+
* is triggered, the related event handler needs to set the
169+
* suspend or shutdown to PM DM and begin to drop the queued
170+
* CBC protocol packets.
171+
*
172+
* SUSPENDED state: Enter this state if SHUTDOWN event is triggered to close all
173+
* native CBC char devices. The IOC mediator will be enter to
174+
* sleeping until RESUME event is triggered that re-opens
175+
* closed native CBC char devices and transfer to INIT state.
176+
*/
177+
static int process_hb_active_event(struct ioc_dev *ioc);
178+
static int process_ram_refresh_event(struct ioc_dev *ioc);
179+
static int process_hb_inactive_event(struct ioc_dev *ioc);
180+
static int process_shutdown_event(struct ioc_dev *ioc);
181+
static int process_resume_event(struct ioc_dev *ioc);
182+
static struct ioc_state_info ioc_state_tbl[] = {
183+
{IOC_S_INIT, IOC_S_ACTIVE, IOC_E_HB_ACTIVE,
184+
process_hb_active_event},
185+
{IOC_S_ACTIVE, IOC_S_SUSPENDING, IOC_E_RAM_REFRESH,
186+
process_ram_refresh_event},
187+
{IOC_S_ACTIVE, IOC_S_SUSPENDING, IOC_E_HB_INACTIVE,
188+
process_hb_inactive_event},
189+
{IOC_S_SUSPENDING, IOC_S_SUSPENDED, IOC_E_SHUTDOWN,
190+
process_shutdown_event},
191+
{IOC_S_SUSPENDED, IOC_S_INIT, IOC_E_RESUME,
192+
process_resume_event},
193+
};
194+
142195
/*
143196
* IOC channels definition.
144197
*/
@@ -163,6 +216,7 @@ static struct ioc_ch_info ioc_ch_tbl[] = {
163216
{IOC_INIT_FD, IOC_NP_RAW10, IOC_NATIVE_RAW10, IOC_CH_ON},
164217
{IOC_INIT_FD, IOC_NP_RAW11, IOC_NATIVE_RAW11, IOC_CH_ON},
165218
{IOC_INIT_FD, IOC_DP_NONE, IOC_VIRTUAL_UART, IOC_CH_ON},
219+
{IOC_INIT_FD, IOC_DP_NONE, IOC_LOCAL_EVENT, IOC_CH_ON}
166220
#ifdef IOC_DUMMY
167221
{IOC_INIT_FD, IOC_NP_FLF, IOC_NATIVE_DUMMY0, IOC_CH_ON},
168222
{IOC_INIT_FD, IOC_NP_FSIG, IOC_NATIVE_DUMMY1, IOC_CH_ON},
@@ -564,6 +618,7 @@ ioc_ch_init(struct ioc_dev *ioc)
564618
{
565619
int i, fd;
566620
struct ioc_ch_info *chl;
621+
int pipe_fds[2];
567622

568623
for (i = 0, chl = ioc_ch_tbl; i < ARRAY_SIZE(ioc_ch_tbl); i++, chl++) {
569624
if (chl->stat == IOC_CH_OFF)
@@ -578,6 +633,15 @@ ioc_ch_init(struct ioc_dev *ioc)
578633
case IOC_VIRTUAL_UART:
579634
fd = ioc_open_virtual_uart(virtual_uart_path);
580635
break;
636+
case IOC_LOCAL_EVENT:
637+
if (!pipe(pipe_fds)) {
638+
fd = pipe_fds[0];
639+
ioc->evt_fd = pipe_fds[1];
640+
} else {
641+
fd = IOC_INIT_FD;
642+
DPRINTF("%s", "ioc open event fd failed\r\n");
643+
}
644+
break;
581645
#ifdef IOC_DUMMY
582646
/*
583647
* TODO: check open if success for dummy fd
@@ -606,7 +670,8 @@ ioc_ch_init(struct ioc_dev *ioc)
606670
* if can not open lifecycle or virtual UART
607671
* ioc needs to exit initilization with failure
608672
*/
609-
if (fd < 0 && (i == IOC_NATIVE_LFCC || i == IOC_VIRTUAL_UART))
673+
if (fd < 0 && (i == IOC_NATIVE_LFCC || i == IOC_VIRTUAL_UART ||
674+
i == IOC_LOCAL_EVENT))
610675
return -1;
611676

612677
chl->fd = fd;
@@ -702,6 +767,85 @@ cbc_request_dequeue(struct ioc_dev *ioc, enum cbc_queue_type qtype)
702767
return free;
703768
}
704769

770+
/*
771+
* Process hb active event before transfer to next state
772+
*/
773+
static int
774+
process_hb_active_event(struct ioc_dev *ioc)
775+
{
776+
/* TODO: Need implementation */
777+
return 0;
778+
}
779+
780+
/*
781+
* Process ram refresh event before transfer to next state
782+
*/
783+
static int
784+
process_ram_refresh_event(struct ioc_dev *ioc)
785+
{
786+
/* TODO: Need implementation */
787+
return 0;
788+
}
789+
790+
/*
791+
* Process hb inactive event before transfer to next state
792+
*/
793+
static int
794+
process_hb_inactive_event(struct ioc_dev *ioc)
795+
{
796+
/* TODO: Need implementation */
797+
return 0;
798+
}
799+
800+
/*
801+
* Process shutdown reason event before transfer to next state
802+
*/
803+
static int
804+
process_shutdown_event(struct ioc_dev *ioc)
805+
{
806+
/* TODO: Need implementation */
807+
return 0;
808+
}
809+
810+
/*
811+
* Process resume event before transfer to next state
812+
*/
813+
static int
814+
process_resume_event(struct ioc_dev *ioc)
815+
{
816+
/* TODO: Need implementation */
817+
return 0;
818+
}
819+
820+
/*
821+
* Process IOC local events
822+
*/
823+
static void
824+
ioc_process_events(struct ioc_dev *ioc, enum ioc_ch_id id)
825+
{
826+
int i;
827+
uint8_t evt;
828+
829+
/* Get one event */
830+
if (ioc_ch_recv(id, &evt, sizeof(evt)) < 0) {
831+
DPRINTF("%s", "ioc state gets event failed\r\n");
832+
return;
833+
}
834+
835+
for (i = 0; i < ARRAY_SIZE(ioc_state_tbl); i++) {
836+
if (evt == ioc_state_tbl[i].evt &&
837+
ioc->state == ioc_state_tbl[i].cur_stat) {
838+
if (ioc_state_tbl[i].handler &&
839+
ioc_state_tbl[i].handler(ioc) == 0)
840+
ioc->state = ioc_state_tbl[i].next_stat;
841+
else
842+
DPRINTF("ioc state switching failed,%d->%d\r\n",
843+
ioc_state_tbl[i].cur_stat,
844+
ioc_state_tbl[i].next_stat);
845+
}
846+
}
847+
}
848+
705849
/*
706850
* Build a cbc_request with CBC link frame and add the cbc_request to
707851
* the rx queue tail.
@@ -816,6 +960,9 @@ ioc_dispatch(struct ioc_dev *ioc, struct ioc_ch_info *chl)
816960
case IOC_VIRTUAL_UART:
817961
ioc_process_rx(ioc, chl->id);
818962
break;
963+
case IOC_LOCAL_EVENT:
964+
ioc_process_events(ioc, chl->id);
965+
break;
819966
default:
820967
DPRINTF("ioc dispatch got wrong channel:%d\r\n", chl->id);
821968
break;
@@ -881,6 +1028,7 @@ ioc_rx_thread(void *arg)
8811028
memset(&packet, 0, sizeof(packet));
8821029
packet.cfg = &ioc->rx_config;
8831030
packet.boot_reason = ioc_boot_reason;
1031+
8841032
for (;;) {
8851033
pthread_mutex_lock(&ioc->rx_mtx);
8861034
while (SIMPLEQ_EMPTY(&ioc->rx_qhead)) {
@@ -933,6 +1081,7 @@ ioc_tx_thread(void *arg)
9331081
memset(&packet, 0, sizeof(packet));
9341082
packet.cfg = &ioc->tx_config;
9351083
packet.boot_reason = ioc_boot_reason;
1084+
9361085
for (;;) {
9371086
pthread_mutex_lock(&ioc->tx_mtx);
9381087
while (SIMPLEQ_EMPTY(&ioc->tx_qhead)) {
@@ -1095,12 +1244,19 @@ ioc_init(struct vmctx *ctx)
10951244
for (i = 0; i < IOC_MAX_REQUESTS; i++)
10961245
SIMPLEQ_INSERT_TAIL(&ioc->free_qhead, ioc->pool + i, me_queue);
10971246

1247+
/* Initialize IOC state */
1248+
ioc->state = IOC_S_INIT;
1249+
1250+
/* Set event fd to default value */
1251+
ioc->evt_fd = IOC_INIT_FD;
1252+
10981253
/*
10991254
* Initialize native CBC cdev and virtual UART.
11001255
*/
11011256
if (ioc_ch_init(ioc) != 0)
11021257
goto chl_err;
11031258

1259+
11041260
/* Initlialize CBC rx/tx signal and group whitelists */
11051261
wlist_init_signal(cbc_rx_signal_table, ARRAY_SIZE(cbc_rx_signal_table),
11061262
wlist_rx_signal_table,
@@ -1175,6 +1331,8 @@ ioc_init(struct vmctx *ctx)
11751331
chl_err:
11761332
ioc_ch_deinit();
11771333
pthread_mutex_destroy(&ioc->free_mtx);
1334+
if (ioc->evt_fd >= 0)
1335+
close(ioc->evt_fd);
11781336
close(ioc->epfd);
11791337
alloc_err:
11801338
free(ioc->evts);
@@ -1200,6 +1358,8 @@ ioc_deinit(struct vmctx *ctx)
12001358
}
12011359
ioc_kill_workers(ioc);
12021360
ioc_ch_deinit();
1361+
if (ioc->evt_fd >= 0)
1362+
close(ioc->evt_fd);
12031363
close(ioc->epfd);
12041364
free(ioc->evts);
12051365
free(ioc->pool);

devicemodel/include/ioc.h

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ enum ioc_ch_id {
526526
IOC_NATIVE_RAW10, /* Native /dev/cbc-raw10 */
527527
IOC_NATIVE_RAW11, /* Native /dev/cbc-raw11 */
528528
IOC_VIRTUAL_UART, /* Virtual UART */
529+
IOC_LOCAL_EVENT, /* Local channel for IOC event */
529530
IOC_NATIVE_DUMMY0, /* Native fake lifecycle channel */
530531
IOC_NATIVE_DUMMY1, /* Native fake signal channel */
531532
IOC_NATIVE_DUMMY2, /* Native Fake oem raw channel */
@@ -575,8 +576,8 @@ enum cbc_queue_type {
575576
*/
576577
enum cbc_request_type {
577578
CBC_REQ_T_PROT, /* CBC protocol request */
578-
CBC_REQ_T_VMM_S3, /* VMM suspend request */
579-
CBC_REQ_T_VMM_S5, /* VMM shutdown request */
579+
CBC_REQ_T_SUSPEND, /* CBC suspend request */
580+
CBC_REQ_T_SHUTDOWN, /* CBC shutdown request */
580581
CBC_REQ_T_SOC /* SOC state update request */
581582
};
582583

@@ -656,6 +657,28 @@ struct cbc_request {
656657
SIMPLEQ_ENTRY(cbc_request) me_queue;
657658
};
658659

660+
/*
661+
* IOC state types.
662+
*/
663+
enum ioc_state_type {
664+
IOC_S_INIT,
665+
IOC_S_ACTIVE,
666+
IOC_S_SUSPENDING,
667+
IOC_S_SUSPENDED
668+
};
669+
670+
/*
671+
* IOC event types.
672+
*/
673+
enum ioc_event_type {
674+
IOC_E_INVALID,
675+
IOC_E_HB_ACTIVE,
676+
IOC_E_RAM_REFRESH,
677+
IOC_E_HB_INACTIVE,
678+
IOC_E_SHUTDOWN,
679+
IOC_E_RESUME
680+
};
681+
659682
/*
660683
* CBC packet is mainly structure for CBC protocol process.
661684
*/
@@ -684,6 +707,8 @@ struct ioc_dev {
684707
char name[16]; /* Core thread name */
685708
int closing; /* Close IOC mediator device flag */
686709
int epfd; /* Epoll fd */
710+
int32_t evt_fd; /* Pipe write fd to trigger one event */
711+
enum ioc_state_type state; /* IOC state type */
687712
struct epoll_event *evts; /* Epoll events table */
688713
struct cbc_request *pool; /* CBC requests pool */
689714
struct cbc_ring ring; /* Ring buffer */
@@ -708,6 +733,16 @@ struct ioc_dev {
708733
void (*ioc_dev_tx)(struct cbc_pkt *pkt);
709734
};
710735

736+
/*
737+
* IOC state information.
738+
*/
739+
struct ioc_state_info {
740+
enum ioc_state_type cur_stat;
741+
enum ioc_state_type next_stat;
742+
enum ioc_event_type evt;
743+
int32_t (*handler)(struct ioc_dev *ioc);
744+
};
745+
711746
/* Parse IOC parameters */
712747
int ioc_parse(const char *opts);
713748

0 commit comments

Comments
 (0)