From: Philip Homburg Date: Fri, 21 Oct 2005 11:51:45 +0000 (+0000) Subject: Prelim commit for ethernet driver crash recovery. X-Git-Tag: v3.1.2a~569 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=724813fdce621384e433c437bef14ad84337479e;p=minix.git Prelim commit for ethernet driver crash recovery. --- diff --git a/drivers/fxp/fxp.c b/drivers/fxp/fxp.c index bd2ad6791..cea26046d 100644 --- a/drivers/fxp/fxp.c +++ b/drivers/fxp/fxp.c @@ -201,6 +201,7 @@ static fxp_t fxp_table[FXP_PORT_NR]; static int fxp_tasknr= ANY; static u16_t eth_ign_proto; static tmra_ut fxp_watchdog; +static char *progname; extern int errno; @@ -231,6 +232,7 @@ _PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd, phys_bytes bus_addr, int check_idle) ); _PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) ); _PROTOTYPE( static void fxp_getstat, (message *mp) ); +_PROTOTYPE( static void fxp_getname, (message *mp) ); _PROTOTYPE( static int fxp_handler, (fxp_t *fp) ); _PROTOTYPE( static void fxp_check_ints, (fxp_t *fp) ); _PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp) ); @@ -255,16 +257,20 @@ _PROTOTYPE( static void do_outl, (port_t port, u32_t v) ); /*===========================================================================* * main * *===========================================================================*/ -int main(void) +int main(int argc, char *argv[]) { message m; - int i, r; + int i, r, tasknr; fxp_t *fp; long v; if ((fxp_tasknr= getprocnr())<0) panic("FXP", "couldn't get proc nr", errno); + if (argc < 1) + panic("FXP", "A head which at this time has no name", NO_NUM); + (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); + v= 0; #if 0 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL); @@ -277,6 +283,13 @@ int main(void) fxp_init_buf(fp); #endif + /* Try to notify inet that we are present (again) */ + r = findproc("inet", &tasknr); + if (r == OK) + notify(tasknr); + else + printf("fxp: cannot find proc number for inet: %d\n", r); + while (TRUE) { if ((r= receive(ANY, &m)) != OK) @@ -292,6 +305,7 @@ int main(void) case DL_READV: fxp_readv(&m, FALSE, TRUE); break; case DL_INIT: fxp_init(&m); break; case DL_GETSTAT: fxp_getstat(&m); break; + case DL_GETNAME: fxp_getname(&m); break; case HARD_INT: for (i= 0, fp= &fxp_table[0]; iDL_NAME, progname, sizeof(mp->DL_NAME)); + mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0'; + mp->m_type= DL_NAME_REPLY; + r= send(mp->m_source, mp); + if (r != OK) + panic("FXP", "fxp_getname: send failed: %d\n", r); +} + /*===========================================================================* * fxp_handler * *===========================================================================*/ @@ -2417,7 +2448,7 @@ static void micro_delay(unsigned long usecs) static u8_t do_inb(port_t port) { int r; - u8_t value; + u32_t value; r= sys_inb(port, &value); if (r != OK) diff --git a/include/minix/com.h b/include/minix/com.h index 41a37d38d..a56517426 100755 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -150,10 +150,12 @@ #define DL_INIT (DL_RQ_BASE + 7) #define DL_STOP (DL_RQ_BASE + 8) #define DL_GETSTAT (DL_RQ_BASE + 9) +#define DL_GETNAME (DL_RQ_BASE +10) /* Message type for data link layer replies. */ #define DL_INIT_REPLY (DL_RS_BASE + 20) #define DL_TASK_REPLY (DL_RS_BASE + 21) +#define DL_NAME_REPLY (DL_RS_BASE + 22) /* Field names for data link layer messages. */ #define DL_PORT m2_i1 @@ -163,6 +165,7 @@ #define DL_CLCK m2_l2 #define DL_ADDR m2_p1 #define DL_STAT m2_l1 +#define DL_NAME m3_ca1 /* Bits in 'DL_STAT' field of DL replies. */ # define DL_PACK_SEND 0x01 diff --git a/servers/inet/inet.c b/servers/inet/inet.c index 4c9f38762..9f650ba27 100644 --- a/servers/inet/inet.c +++ b/servers/inet/inet.c @@ -242,15 +242,21 @@ PUBLIC void main() #else /* Minix 3 */ else if (mq->mq_mess.m_type == SYN_ALARM) { - clck_tick(&mq->mq_mess); - mq_free(mq); + clck_tick(&mq->mq_mess); + mq_free(mq); } else if (mq->mq_mess.m_type == SYS_SIG) { - /* signaled */ - /* probably SIGTERM */ - mq_free(mq); + /* signaled */ + /* probably SIGTERM */ + mq_free(mq); } + else if (mq->mq_mess.m_type & NOTIFY_MESSAGE) + { + /* A driver is (re)started. */ + eth_check_drivers(&mq->mq_mess); + mq_free(mq); + } #endif else { diff --git a/servers/inet/mnx_eth.c b/servers/inet/mnx_eth.c index 6466cb042..463c2ebf4 100644 --- a/servers/inet/mnx_eth.c +++ b/servers/inet/mnx_eth.c @@ -28,6 +28,7 @@ FORWARD _PROTOTYPE( void write_int, (eth_port_t *eth_port) ); FORWARD _PROTOTYPE( void eth_recvev, (event_t *ev, ev_arg_t ev_arg) ); FORWARD _PROTOTYPE( void eth_sendev, (event_t *ev, ev_arg_t ev_arg) ); FORWARD _PROTOTYPE( eth_port_t *find_port, (message *m) ); +FORWARD _PROTOTYPE( void eth_restart, (eth_port_t *eth_port, int tasknr) ); PUBLIC void osdep_eth_init() { @@ -344,6 +345,53 @@ message *m; } } +PUBLIC void eth_check_drivers(m) +message *m; +{ + int i, r, tasknr; + struct eth_conf *ecp; + eth_port_t *eth_port; + char *drivername; + + tasknr= m->m_source; + printf("eth_check_drivers: got a notification from %d\n", tasknr); + + m->m_type= DL_GETNAME; + r= sendrec(tasknr, m); + if (r != OK) + { + printf("eth_check_drivers: sendrec to %d failed: %d\n", + tasknr, r); + return; + } + if (m->m_type != DL_NAME_REPLY) + { + printf( + "eth_check_drivers: got bad getname reply (%d) from %d\n", + m->m_type, tasknr); + return; + } + + drivername= m->m3_ca1; + printf("eth_check_drivers: got name: %s\n", drivername); + + /* Re-init ethernet interfaces */ + for (i= 0, ecp= eth_conf, eth_port= eth_port_table; + iec_task, drivername) != 0) + { + /* Wrong driver */ + continue; + } + + eth_restart(eth_port, tasknr); + } +} + PUBLIC int eth_get_stat(eth_port, eth_stat) eth_port_t *eth_port; eth_stat_t *eth_stat; @@ -410,6 +458,7 @@ u32_t flags; mess.DL_PORT= eth_port->etp_osdep.etp_port; mess.DL_PROC= this_proc; mess.DL_MODE= dl_flags; + eth_port->etp_osdep.etp_dl_flags= dl_flags; do { @@ -683,6 +732,70 @@ message *m; return loc_port; } +static void eth_restart(eth_port, tasknr) +eth_port_t *eth_port; +int tasknr; +{ + int r; + message mess; +#if 0 + int i, r, rport; + struct eth_conf *ecp; + eth_port_t *rep; +#endif + + printf("eth_restart: restarting eth%d, task %d, port %d\n", + eth_port-eth_port_table, tasknr, + eth_port->etp_osdep.etp_port); + + eth_port->etp_osdep.etp_task= tasknr; + + mess.m_type= DL_INIT; + mess.DL_PORT= eth_port->etp_osdep.etp_port; + mess.DL_PROC= this_proc; + mess.DL_MODE= eth_port->etp_osdep.etp_dl_flags; + + r= send(eth_port->etp_osdep.etp_task, &mess); + if (r<0) + { + printf( + "osdep_eth_init: unable to send to ethernet task, error= %d\n", + r); + return; + } + + if (receive(eth_port->etp_osdep.etp_task, &mess)<0) + ip_panic(("unable to receive")); + + if (mess.m3_i1 == ENXIO) + { + printf( + "osdep_eth_init: no ethernet device at task=%d,port=%d\n", + eth_port->etp_osdep.etp_task, + eth_port->etp_osdep.etp_port); + return; + } + if (mess.m3_i1 < 0) + ip_panic(("osdep_eth_init: DL_INIT returned error %d\n", + mess.m3_i1)); + + if (mess.m3_i1 != eth_port->etp_osdep.etp_port) + { + ip_panic(( +"osdep_eth_init: got reply for wrong port (got %d, expected %d)\n", + mess.m3_i1, eth_port->etp_osdep.etp_port)); + } + + eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1; + + eth_port->etp_flags |= EPF_ENABLED; + if (eth_port->etp_wr_pack) + ip_panic(("eth_restart: should clear etp_wr_pack\n")); + if (eth_port->etp_rd_pack) + ip_panic(("eth_restart: should clear etp_rd_pack\n")); + setup_read (eth_port); +} + /* * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $ */ diff --git a/servers/inet/osdep_eth.h b/servers/inet/osdep_eth.h index f6742f85f..a1304fe2b 100644 --- a/servers/inet/osdep_eth.h +++ b/servers/inet/osdep_eth.h @@ -19,6 +19,7 @@ typedef struct osdep_eth_port int etp_task; int etp_port; int etp_recvconf; + unsigned etp_dl_flags; iovec_t etp_wr_iovec[IOVEC_NR]; iovec_t etp_rd_iovec[RD_IOVEC]; event_t etp_recvev; diff --git a/servers/inet/proto.h b/servers/inet/proto.h index be2977a78..cfbecca51 100644 --- a/servers/inet/proto.h +++ b/servers/inet/proto.h @@ -13,6 +13,7 @@ _PROTOTYPE( void clck_tick, (message *mess) ); /* mnx_eth.c */ _PROTOTYPE( void eth_rec, (message *m) ); +_PROTOTYPE( void eth_check_drivers, (message *m) ); /* sr.c */