Sort a linked list with merge sort in C
Merging tails effectively wastes cycles. The nodes are already linked correctly.

    if (part1 != NULL) {
        current-&gt;next = part1;
    }

    if (part2 != NULL) {
        current-&gt;next = part2;
    }


is enough.
A single most important feature of merge sort is stability: elements compared equal remain in the original order. A comparison

    if(cmp(&amp;part1-&gt;val, &amp;part2-&gt;val) &lt; 0)


makes your sort unstable. A correct comparison is either one of

    if(cmp(&amp;part2-&gt;val, &amp;part1-&gt;val) &gt; 0)
    if(cmp(&amp;part1-&gt;val, &amp;part2-&gt;val) &lt;= 0)

Less indentation is easier to follow. I recommend to invert a recursion termination condition:

    if (start == stop) {
        start-&gt;next = NULL;
        return start;
    }
    ...

Avoid naked loops. The

    for(List *node = start; node != stop; node = node-&gt;next) {
        if(i == mid) {
            midNode = node;
        }
        i++;
    }


should be factored out into a function

    List * advance(List * start, int steps);