diff --git a/target/linux/ar71xx/patches-2.6.39/910-unaligned_access_hacks.patch b/target/linux/ar71xx/patches-2.6.39/910-unaligned_access_hacks.patch new file mode 100644 index 0000000000..921cf194d6 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.39/910-unaligned_access_hacks.patch @@ -0,0 +1,117 @@ +--- a/arch/mips/include/asm/checksum.h ++++ b/arch/mips/include/asm/checksum.h +@@ -12,6 +12,7 @@ + #define _ASM_CHECKSUM_H + + #include ++#include + + #include + +@@ -104,26 +105,30 @@ static inline __sum16 ip_fast_csum(const + const unsigned int *stop = word + ihl; + unsigned int csum; + int carry; ++ unsigned int w; + +- csum = word[0]; +- csum += word[1]; +- carry = (csum < word[1]); ++ csum = __get_unaligned_cpu32(word++); ++ ++ w = __get_unaligned_cpu32(word++); ++ csum += w; ++ carry = (csum < w); + csum += carry; + +- csum += word[2]; +- carry = (csum < word[2]); ++ w = __get_unaligned_cpu32(word++); ++ csum += w; ++ carry = (csum < w); + csum += carry; + +- csum += word[3]; +- carry = (csum < word[3]); ++ w = __get_unaligned_cpu32(word++); ++ csum += w; ++ carry = (csum < w); + csum += carry; + +- word += 4; + do { +- csum += *word; +- carry = (csum < *word); ++ w = __get_unaligned_cpu32(word++); ++ csum += w; ++ carry = (csum < w); + csum += carry; +- word++; + } while (word != stop); + + return csum_fold(csum); +--- a/include/linux/ip.h ++++ b/include/linux/ip.h +@@ -102,7 +102,7 @@ struct iphdr { + __be32 saddr; + __be32 daddr; + /*The options start here. */ +-}; ++} __packed; + + #ifdef __KERNEL__ + #include +--- a/include/linux/ipv6.h ++++ b/include/linux/ipv6.h +@@ -126,7 +126,7 @@ struct ipv6hdr { + + struct in6_addr saddr; + struct in6_addr daddr; +-}; ++} __packed; + + #ifdef __KERNEL__ + /* +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -54,7 +54,7 @@ struct tcphdr { + __be16 window; + __sum16 check; + __be16 urg_ptr; +-}; ++} __packed; + + /* + * The union cast uses a gcc extension to avoid aliasing problems +--- a/include/linux/udp.h ++++ b/include/linux/udp.h +@@ -24,7 +24,7 @@ struct udphdr { + __be16 dest; + __be16 len; + __sum16 check; +-}; ++} __packed; + + /* UDP socket options */ + #define UDP_CORK 1 /* Never send partially complete segments */ +--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c ++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -44,8 +45,8 @@ static bool ipv4_pkt_to_tuple(const stru + if (ap == NULL) + return false; + +- tuple->src.u3.ip = ap[0]; +- tuple->dst.u3.ip = ap[1]; ++ tuple->src.u3.ip = __get_unaligned_cpu32(ap++); ++ tuple->dst.u3.ip = __get_unaligned_cpu32(ap); + + return true; + }