<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none"><!--P{margin-top:0;margin-bottom:0;} --></style>
</head>
<body dir="ltr" style="font-size:12pt;color:#000000;background-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;">
<p>Hi,</p>
<p><br>
</p>
<p>I encountered a crash in the ethercat driver when using a bus with a large number of modules (~500). The ec_master_calc_topology_rec() recursive function sometimes exhausts the kernel stack and crashes.<br>
</p>
<p><br>
</p>
<p>I fixed this issue by reimplementing this function in a non-recursive way. As I'm afraid I'm not familiar with mercurial, I will post the code directly here, with two variants:<br>
</p>
<p>- one for the main repository</p>
<p>- one for the gavinl patchset<br>
</p>
<p><br>
</p>
<p><br>
</p>
<p>/******* for main repository *************************************************************/<br>
</p>
<p><br>
/** Calculates the bus topology.<br>
 */<br>
<br>
typedef struct<br>
{<br>
   ec_slave_t *slave;<br>
   unsigned int port_index;<br>
} topology_stack_t;<br>
<br>
void ec_master_calc_topology(<br>
        ec_master_t *master /**< EtherCAT master. */<br>
        )<br>
{<br>
    unsigned int slave_position = 0;<br>
    ec_slave_t *next_slave;<br>
    void* stack_base;<br>
    topology_stack_t* stack_top;<br>
<br>
    static const unsigned int next_table[EC_MAX_PORTS] = {<br>
        3, 2, 0, 1<br>
    };<br>
<br>
    if (master->slave_count == 0)<br>
        return;<br>
<br>
    if (!(stack_base = kmalloc(sizeof(topology_stack_t) * master->slave_count, GFP_KERNEL))) {<br>
        EC_MASTER_ERR(master, "Failed to allocate stack.\n");<br>
        return;<br>
    }<br>
    stack_top = (topology_stack_t*)stack_base;<br>
<br>
    // first slave<br>
    stack_top->slave = master->slaves;<br>
    stack_top->port_index = 3;<br>
    ++stack_top;<br>
<br>
    while ( stack_top != (topology_stack_t*)stack_base )<br>
    {<br>
        topology_stack_t* cur = stack_top - 1;<br>
<br>
        if (cur->port_index == 0) {<br>
            --stack_top;<br>
            continue;<br>
        }<br>
<br>
        if (!cur->slave->ports[cur->port_index].link.loop_closed) {<br>
            slave_position += 1;<br>
            if (slave_position >= master->slave_count) {<br>
                kfree(stack_base);<br>
                EC_MASTER_ERR(master, "Failed to calculate bus topology.\n");<br>
                return;<br>
            }<br>
<br>
            next_slave = master->slaves + slave_position;<br>
            cur->slave->ports[cur->port_index].next_slave = next_slave;<br>
            next_slave->ports[0].next_slave = cur->slave;<br>
<br>
            stack_top->slave = next_slave;<br>
            stack_top->port_index = 3;<br>
            ++stack_top;<br>
        }<br>
<br>
        cur->port_index = next_table[cur->port_index];<br>
    }<br>
<br>
    kfree(stack_base);<br>
}<br>
<br>
</p>
<p><br>
</p>
<p>/******* for gavinl patchset *************************************************************/<br>
<br>
/** Calculates the bus topology.<br>
 */<br>
<br>
typedef struct<br>
{<br>
   ec_slave_t *slave;<br>
   unsigned int port_index;<br>
} topology_stack_t;<br>
<br>
void ec_master_calc_topology(<br>
        ec_master_t *master /**< EtherCAT master. */<br>
        )<br>
{<br>
    unsigned int slave_position = 0;<br>
    ec_slave_t *next_slave;<br>
    void* stack_base;<br>
    topology_stack_t* stack_top;<br>
<br>
    static const unsigned int next_table[EC_MAX_PORTS] = {<br>
        3, 2, 0, 1<br>
    };<br>
<br>
    if (master->slave_count == 0)<br>
        return;<br>
<br>
    if (!(stack_base = kmalloc(sizeof(topology_stack_t) * master->slave_count, GFP_KERNEL))) {<br>
        EC_MASTER_ERR(master, "Failed to allocate stack.\n");<br>
        return;<br>
    }<br>
    stack_top = (topology_stack_t*)stack_base;<br>
<br>
    // first slave<br>
    stack_top->slave = master->slaves;<br>
    stack_top->port_index = next_table[stack_top->slave->upstream_port];<br>
    ++stack_top;<br>
<br>
    while ( stack_top != (topology_stack_t*)stack_base )<br>
    {<br>
        topology_stack_t* cur = stack_top - 1;<br>
<br>
        if (cur->port_index == cur->slave->upstream_port) {<br>
            --stack_top;<br>
            continue;<br>
        }<br>
<br>
        if (!cur->slave->ports[cur->port_index].link.loop_closed) {<br>
            slave_position += 1;<br>
            if (slave_position >= master->slave_count) {<br>
                kfree(stack_base);<br>
                EC_MASTER_ERR(master, "Failed to calculate bus topology.\n");<br>
                return;<br>
            }<br>
<br>
            next_slave = master->slaves + slave_position;<br>
            cur->slave->ports[cur->port_index].next_slave = next_slave;<br>
            next_slave->ports[next_slave->upstream_port].next_slave = cur->slave;<br>
<br>
            stack_top->slave = next_slave;<br>
            stack_top->port_index = next_table[stack_top->slave->upstream_port];<br>
            ++stack_top;<br>
        }<br>
<br>
        cur->port_index = next_table[cur->port_index];<br>
    }<br>
<br>
    kfree(stack_base);<br>
}<br>
<br>
</p>
<p><br>
</p>
<img src="https://www.solystic.fr/data/medias/603/style/default/signature_basdemailsolysticjpg.jpg" alt="Disclaimer Solystic">
</body>
</html>