inet: fix state transitions in driver receipt code
This resolves a problem with ioctl(NIOCGETHSTAT) hanging forever as identified by Erik van der Kouwe, and possibly many other corner cases. Change-Id: I2350c882dc6a0862e16454ec6b6c320d78780bcd
This commit is contained in:
parent
86e41e22cf
commit
85fb986ba7
|
@ -177,14 +177,9 @@ acc_t *pack;
|
||||||
|
|
||||||
void eth_rec(message *m)
|
void eth_rec(message *m)
|
||||||
{
|
{
|
||||||
int i, r, m_type, flags;
|
int i, r, flags;
|
||||||
eth_port_t *loc_port, *vlan_port;
|
eth_port_t *loc_port, *vlan_port;
|
||||||
|
|
||||||
m_type= m->m_type;
|
|
||||||
|
|
||||||
assert(m_type == DL_CONF_REPLY || m_type == DL_TASK_REPLY ||
|
|
||||||
m_type == DL_STAT_REPLY);
|
|
||||||
|
|
||||||
for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
|
for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
|
||||||
{
|
{
|
||||||
if (loc_port->etp_osdep.etp_task == m->m_source)
|
if (loc_port->etp_osdep.etp_task == m->m_source)
|
||||||
|
@ -193,28 +188,16 @@ void eth_rec(message *m)
|
||||||
if (i >= eth_conf_nr)
|
if (i >= eth_conf_nr)
|
||||||
{
|
{
|
||||||
printf("eth_rec: message 0x%x from unknown driver %d\n",
|
printf("eth_rec: message 0x%x from unknown driver %d\n",
|
||||||
m_type, m->m_source);
|
m->m_type, m->m_source);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loc_port->etp_osdep.etp_state == OEPS_CONF_SENT)
|
switch (m->m_type) {
|
||||||
{
|
case DL_CONF_REPLY:
|
||||||
if (m_type == DL_TASK_REPLY)
|
if (loc_port->etp_osdep.etp_state != OEPS_CONF_SENT) {
|
||||||
{
|
printf("eth_rec: got DL_CONF_REPLY from %d while in "
|
||||||
flags= m->m_netdrv_net_dl_task.flags;
|
"state %d (ignoring)\n", m->m_source,
|
||||||
|
loc_port->etp_osdep.etp_state);
|
||||||
if (flags & DL_PACK_SEND)
|
|
||||||
write_int(loc_port);
|
|
||||||
if (flags & DL_PACK_RECV)
|
|
||||||
read_int(loc_port, m->m_netdrv_net_dl_task.count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_type != DL_CONF_REPLY)
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"eth_rec: got bad message type 0x%x from %d in CONF state\n",
|
|
||||||
m_type, m->m_source);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,44 +240,17 @@ void eth_rec(message *m)
|
||||||
eth_restart_ioctl(vlan_port);
|
eth_restart_ioctl(vlan_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(loc_port->etp_flags & EPF_READ_IP))
|
if (!(loc_port->etp_flags & EPF_READ_IP))
|
||||||
setup_read (loc_port);
|
loc_port->etp_osdep.etp_flags |= OEPF_NEED_RECV;
|
||||||
|
|
||||||
#if 0
|
break;
|
||||||
if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
|
|
||||||
{
|
|
||||||
printf("eth_rec(conf): OEPF_NEED_SEND is set\n");
|
|
||||||
}
|
|
||||||
if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
|
|
||||||
{
|
|
||||||
printf("eth_rec(conf): OEPF_NEED_RECV is set\n");
|
|
||||||
}
|
|
||||||
if (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
|
|
||||||
{
|
|
||||||
printf("eth_rec(conf): OEPF_NEED_STAT is set\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return;
|
case DL_STAT_REPLY:
|
||||||
}
|
if (loc_port->etp_osdep.etp_state != OEPS_GETSTAT_SENT) {
|
||||||
if (loc_port->etp_osdep.etp_state == OEPS_GETSTAT_SENT)
|
printf("eth_rec: got DL_STAT_REPLY from %d while in "
|
||||||
{
|
"state %d (ignoring)\n", m->m_source,
|
||||||
if (m_type == DL_TASK_REPLY)
|
loc_port->etp_osdep.etp_state);
|
||||||
{
|
|
||||||
flags= m->m_netdrv_net_dl_task.flags;
|
|
||||||
|
|
||||||
if (flags & DL_PACK_SEND)
|
|
||||||
write_int(loc_port);
|
|
||||||
if (flags & DL_PACK_RECV)
|
|
||||||
read_int(loc_port, m->m_netdrv_net_dl_task.count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_type != DL_STAT_REPLY)
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"eth_rec: got bad message type 0x%x from %d in GETSTAT state\n",
|
|
||||||
m_type, m->m_source);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,43 +266,25 @@ void eth_rec(message *m)
|
||||||
assert(loc_port->etp_flags & EPF_GOT_ADDR);
|
assert(loc_port->etp_flags & EPF_GOT_ADDR);
|
||||||
eth_restart_ioctl(loc_port);
|
eth_restart_ioctl(loc_port);
|
||||||
|
|
||||||
#if 0
|
break;
|
||||||
if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
|
|
||||||
{
|
|
||||||
printf("eth_rec(stat): OEPF_NEED_SEND is set\n");
|
|
||||||
}
|
|
||||||
if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
|
|
||||||
{
|
|
||||||
printf("eth_rec(stat): OEPF_NEED_RECV is set\n");
|
|
||||||
}
|
|
||||||
if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
|
|
||||||
{
|
|
||||||
printf("eth_rec(stat): OEPF_NEED_CONF is set\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
case DL_TASK_REPLY:
|
||||||
if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
|
if (loc_port->etp_osdep.etp_state == OEPS_RECV_SENT ||
|
||||||
(loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF))
|
loc_port->etp_osdep.etp_state == OEPS_SEND_SENT)
|
||||||
{
|
loc_port->etp_osdep.etp_state= OEPS_IDLE;
|
||||||
eth_set_rec_conf(loc_port,
|
|
||||||
loc_port->etp_osdep.etp_recvconf);
|
flags= m->m_netdrv_net_dl_task.flags;
|
||||||
}
|
|
||||||
#endif
|
if (flags & DL_PACK_SEND)
|
||||||
return;
|
write_int(loc_port);
|
||||||
|
if (flags & DL_PACK_RECV)
|
||||||
|
read_int(loc_port, m->m_netdrv_net_dl_task.count);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("invalid ethernet reply %d", m->m_type);
|
||||||
}
|
}
|
||||||
assert(loc_port->etp_osdep.etp_state == OEPS_IDLE ||
|
|
||||||
loc_port->etp_osdep.etp_state == OEPS_RECV_SENT ||
|
|
||||||
loc_port->etp_osdep.etp_state == OEPS_SEND_SENT ||
|
|
||||||
(printf("etp_state = %d\n", loc_port->etp_osdep.etp_state), 0));
|
|
||||||
loc_port->etp_osdep.etp_state= OEPS_IDLE;
|
|
||||||
|
|
||||||
flags= m->m_netdrv_net_dl_task.flags;
|
|
||||||
|
|
||||||
if (flags & DL_PACK_SEND)
|
|
||||||
write_int(loc_port);
|
|
||||||
if (flags & DL_PACK_RECV)
|
|
||||||
read_int(loc_port, m->m_netdrv_net_dl_task.count);
|
|
||||||
|
|
||||||
if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
|
if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
|
||||||
loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
|
loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
|
||||||
|
@ -362,11 +300,11 @@ void eth_rec(message *m)
|
||||||
if (!(loc_port->etp_flags & EPF_READ_IP))
|
if (!(loc_port->etp_flags & EPF_READ_IP))
|
||||||
setup_read (loc_port);
|
setup_read (loc_port);
|
||||||
}
|
}
|
||||||
if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
|
if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
|
||||||
|
(loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF))
|
||||||
{
|
{
|
||||||
#if 0
|
eth_set_rec_conf(loc_port,
|
||||||
printf("eth_rec: OEPF_NEED_CONF is set\n");
|
loc_port->etp_osdep.etp_recvconf);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
|
if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
|
||||||
(loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT))
|
(loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT))
|
||||||
|
|
Loading…
Reference in a new issue