diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh
index d702d45..f268fe4 100644
--- a/target/linux/ar71xx/base-files/etc/diag.sh
+++ b/target/linux/ar71xx/base-files/etc/diag.sh
@@ -305,6 +305,9 @@ get_status_led() {
 	wrt400n)
 		status_led="wrt400n:blue:wps"
 		;;
+	wap4410n)
+		status_led="wrt4410n:green:power"
+		;;
 	wrt160nl)
 		status_led="wrt160nl:blue:wps"
 		;;
diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
index f5c6865..7f163d6 100644
--- a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
@@ -338,6 +338,7 @@ tl-wa901nd-v3 |\
 tl-wr703n |\
 tube2h |\
 wndap360 |\
+wap4410n |\
 mynet-rext |\
 wp543)
 	ucidef_set_interface_lan "eth0"
diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
index 645c5d9..a64a3bd 100755
--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
@@ -849,6 +849,9 @@ ar71xx_board_detect() {
 	*WRT400N)
 		name="wrt400n"
 		;;
+	*WAP4410N)
+		name="wap4410n"
+		;;
 	*"WZR-450HP2")
 		name="wzr-450hp2"
 		;;
diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
index a8cec91..33d3a58 100755
--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
@@ -228,6 +228,7 @@ platform_check_image() {
 	rocket-m-xw | \
 	nanostation-m-xw | \
 	rw2458n | \
+	wap4410n | \
 	wndap360 | \
 	wzr-hp-g300nh2 | \
 	wzr-hp-g300nh | \
diff --git a/target/linux/ar71xx/config-3.18 b/target/linux/ar71xx/config-3.18
index 36b8bb6..87b8162 100644
--- a/target/linux/ar71xx/config-3.18
+++ b/target/linux/ar71xx/config-3.18
@@ -140,6 +140,7 @@ CONFIG_ATH79_MACH_WPJ344=y
 CONFIG_ATH79_MACH_WPJ558=y
 CONFIG_ATH79_MACH_WRT160NL=y
 CONFIG_ATH79_MACH_WRT400N=y
+CONFIG_ATH79_MACH_WAP4410N=y
 CONFIG_ATH79_MACH_WZR_450HP2=y
 CONFIG_ATH79_MACH_WZR_HP_AG300H=y
 CONFIG_ATH79_MACH_WZR_HP_G300NH=y
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wap4410n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wap4410n.c
new file mode 100644
index 0000000..15bd12b
--- /dev/null
+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wap4410n.c
@@ -0,0 +1,279 @@
+/*
+ *  Cisco WAP4410N board support
+ *
+ *  Copyright (C) 2014 Caleb James DeLisle <cjd@cjdns.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation, or (at your option) any later version.
+ */
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/nxp_74hc153.h>
+
+#include <asm/mach-ath79/ath79.h>
+
+#include "dev-eth.h"
+#include "dev-gpio-buttons.h"
+#include "dev-leds-gpio.h"
+#include "dev-usb.h"
+#include "dev-wmac.h"
+#include "machtypes.h"
+
+/* -------------- begin flash device -------------- */
+
+#define FLASH_BASE 0xbf000000
+
+/* where the actual art data is within the art partition. */
+#define ART_DATA_OFFSET 0x1000
+
+/* If changed, make sure to change image/Makefile too! */
+#define KERN_SIZE 0x190000
+
+/* Flash layout: u-boot/include/upgrade.h in cisco's GPL dump */
+#define FLASH_SIZE			(0x800000)
+#define BOOT_SIZE			(0x40000)
+#define NVRAM_SIZE			(0x10000)
+#define ART_SIZE			(0x10000)
+#define ENV_SIZE			(0x10000)
+
+#define NODE_INFO_OFFSET (BOOT_SIZE - 0x90)
+struct wap4410n_node_info {
+	/** Serial number written on back of device. */
+	char serial_no[16];
+
+	/** Internal to Sercomm (?), France = { domain: 0x80, country: 0x00 } */
+	uint8_t domain;
+	uint8_t country;
+
+	/** written on the board, eg: 13 */
+	uint8_t hw_ver;
+
+	uint8_t zero0[5];
+
+	/** ASCII numeric digits */
+	char wps_pin[8];
+
+	uint8_t zero1[16];
+
+	uint8_t mac_addr[6];
+
+	uint8_t zero2[3];
+
+	/** 31734572436f4d6d -> "1sErCoMm" does not seem to be checked. */
+	char magic_1sErCoMm[8];
+
+	/** 00010000 (offset 0x41, completely unaligned) */
+	uint8_t unknown0[4];
+
+	/** Used by upslug2 protocol */
+	uint8_t hardware_id[32];
+
+	/** 0000240800008000000000030000200400000008 */
+	uint8_t unknown1[20];
+
+	/** 734572436f4d6d -> "sErCoMm" */
+	uint8_t magic_sErCoMm[7];
+
+	uint8_t zero3[16];
+};
+
+#define UPGRADE_INFO_OFFSET	0x7dfff0
+struct wap4410n_upgrade_info {
+	/** Stock WAP4410: 2408 */
+	uint16_t product_id;
+
+	/** Always 8000 */
+	uint16_t protocol;
+
+	/** 2007 -> v2.0.7.x */
+	uint16_t fw_version;
+
+	/** 90f7 same value as NSLU2 */
+	uint16_t unknown0;
+
+	/** bootloader checks this and will "soft brick" if it's not correct. */
+	uint8_t eRcOmM[6];
+
+	uint8_t pad[2];
+};
+
+/*
+ * An instruction in the bootloader which checks that 0x7dfff8 == "eRcOmM" and
+ * bricks if it's not.
+ * If this instruction is overwritten with a zero, you get 64k of extra space.
+ * 2406 0006 1440 000a 8fbc 0020 <-- unpatched
+ * 2406 0006 0000 0000 8fbc 0020 <-- patched
+ */
+#define SERCOMM_CHECK_LAST_INSN   0x24060006
+#define SERCOMM_CHECK_INSN_OFFSET 0x19e08
+#define SERCOMM_CHECK_NEXT_INSN   0x8fbc0020
+
+
+/* Little bit of arithmatic on the flash layout. */
+#define NVRAM_OFFSET BOOT_SIZE
+#define KERN_OFFSET (NVRAM_OFFSET + NVRAM_SIZE)
+#define ROOT_OFFSET (KERN_OFFSET + KERN_SIZE)
+#define ART_OFFSET (FLASH_SIZE - ART_SIZE)
+#define ENV_OFFSET (ART_OFFSET - ENV_SIZE)
+/* rootfs is whatever is left. */
+#define ROOT_SIZE (ENV_OFFSET - ROOT_OFFSET)
+
+#define PART(b, s, n, f) { .name = n, .offset = b, .size = s, .mask_flags = f }
+static struct mtd_partition wap4410n_flash_partitions[] = {
+	PART(0x00000000,   BOOT_SIZE,  "u-boot",	 MTD_WRITEABLE),
+	PART(NVRAM_OFFSET, NVRAM_SIZE, "u-boot-env", MTD_WRITEABLE),
+	PART(KERN_OFFSET,  KERN_SIZE,  "kernel",	 0),
+	PART(ROOT_OFFSET,  ROOT_SIZE,  "rootfs",	 0),
+	PART(ENV_OFFSET,   ENV_SIZE,   "sercomm",	MTD_WRITEABLE),
+	PART(ART_OFFSET,   ART_SIZE,   "art",		MTD_WRITEABLE),
+
+	/* Pseudo-partition over whole upgradable space, used by sysupgrade. */
+	PART(KERN_OFFSET, KERN_SIZE + ROOT_SIZE, "firmware", 0)
+};
+#undef PART
+
+static struct physmap_flash_data wap4410n_flash_data = {
+	.width		= 2,
+	.parts		= wap4410n_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(wap4410n_flash_partitions),
+};
+
+static struct resource wap4410n_flash_resources[] = {
+	[0] = {
+		.start	= FLASH_BASE,
+		.end	= FLASH_BASE + FLASH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device wap4410n_flash_device = {
+	.name		   = "physmap-flash",
+	.id			 = -1,
+	.resource		= wap4410n_flash_resources,
+	.num_resources	= ARRAY_SIZE(wap4410n_flash_resources),
+	.dev			= { .platform_data = &wap4410n_flash_data }
+};
+
+
+static void __init wap4410n_flash_reg(void)
+{
+	uint32_t *insn = (uint32_t *) (FLASH_BASE + SERCOMM_CHECK_INSN_OFFSET);
+	int i;
+	if (SERCOMM_CHECK_LAST_INSN != insn[-1] ||
+		SERCOMM_CHECK_NEXT_INSN != insn[1]) {
+		printk(KERN_INFO "Unrecognized bootloader, costs 64k storage");
+	} else if (insn[0]) {
+		printk(KERN_INFO "eRcOmM check at %p in uboot, costs 64k storage",
+				(void *)insn);
+	} else {
+		printk(KERN_INFO "eRcOmM check at %p patched, gain 64k storage",
+				(void *)insn);
+		wap4410n_flash_partitions[3].size +=
+			wap4410n_flash_partitions[4].size;
+		wap4410n_flash_data.nr_parts--;
+		for (i = 4; i < wap4410n_flash_data.nr_parts; i++) {
+			memcpy(&wap4410n_flash_partitions[i],
+				   &wap4410n_flash_partitions[i + 1],
+				   sizeof(struct mtd_partition));
+		}
+	}
+	platform_device_register(&wap4410n_flash_device);
+}
+
+/* -------------- end flash device -------------- */
+
+
+/* -------------------- GPIO -------------------- */
+
+#define LED_WIRELESS			  0
+#define LED_POWER				 1
+#define KEYS_POLL_INTERVAL		20	/* msecs */
+#define KEYS_DEBOUNE_INTERVAL	(3 * KEYS_POLL_INTERVAL)
+
+/* 2 lights are gpio, other 2 are hardwired. */
+static struct gpio_led wap4410n_leds_gpio[] __initdata = {
+	{
+		.name		= "wrt4410n:green:power",
+		.gpio		= LED_POWER,
+		.active_low  = 1,
+	},
+	{
+		.name		= "wrt4410n:green:wireless",
+		.gpio		= LED_WIRELESS,
+		.active_low  = 1,
+	},
+};
+
+static struct gpio_keys_button wap4410n_gpio_keys[] __initdata = {
+	{
+		.desc		= "reset",
+		.type		= EV_KEY,
+		.code		= KEY_RESTART,
+		.debounce_interval = KEYS_DEBOUNE_INTERVAL,
+		.gpio		= 21,
+		.active_low  = 1,
+	}
+};
+
+static void __init wap4410n_gpio_reg(void)
+{
+	ath79_register_gpio_keys_polled(
+		-1,
+		KEYS_POLL_INTERVAL,
+		ARRAY_SIZE(wap4410n_gpio_keys),
+		wap4410n_gpio_keys
+	);
+	ath79_register_leds_gpio(
+		-1,
+		 ARRAY_SIZE(wap4410n_leds_gpio),
+		 wap4410n_leds_gpio
+	);
+}
+
+/* -------------------- end GPIO -------------------- */
+
+/** Never called, just for build time verification. */
+static void wap4410n_build_verify(void)
+{
+	BUILD_BUG_ON((KERN_SIZE / 0x10000 * 0x10000) != KERN_SIZE);
+	BUILD_BUG_ON(sizeof(struct wap4410n_upgrade_info) != 16);
+	BUILD_BUG_ON(sizeof(struct wap4410n_node_info) != 0x90);
+}
+
+static void __init wap4410n_setup(void)
+{
+	struct wap4410n_node_info *ni = (struct wap4410n_node_info *)
+		(FLASH_BASE + NODE_INFO_OFFSET);
+	uint8_t *art = (uint8_t *)
+		(FLASH_BASE + FLASH_SIZE - ART_SIZE + ART_DATA_OFFSET);
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, ni->mac_addr, 0);
+
+	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
+	/* TODO: SPEED_1000 causes a silent failure, testing needed. */
+	ath79_eth0_data.speed = SPEED_100;
+	ath79_eth0_data.duplex = DUPLEX_FULL;
+	ath79_register_eth(0);
+
+	ath79_register_usb();
+
+	wap4410n_flash_reg();
+
+	ath79_register_wmac(art, ni->mac_addr);
+
+	wap4410n_gpio_reg();
+
+	/* silence compiler warning */
+	if (0)
+		wap4410n_build_verify();
+}
+
+MIPS_MACHINE(
+	ATH79_MACH_WAP4410N,
+	"WAP4410N",
+	"Linksys WAP4410N",
+	wap4410n_setup
+);
diff --git a/target/linux/ar71xx/generic/profiles/linksys.mk b/target/linux/ar71xx/generic/profiles/linksys.mk
index bedf3a3..0a7a897 100644
--- a/target/linux/ar71xx/generic/profiles/linksys.mk
+++ b/target/linux/ar71xx/generic/profiles/linksys.mk
@@ -23,5 +23,15 @@ define Profile/WRT400N/Description
 	Package set optimized for the Linksys WRT400N.
 endef

+define Profile/WAP4410N
+	NAME:=Linksys WAP4410N
+	PACKAGES:=
+endef
+
+define Profile/WAP4410N/Description
+	Package set optimized for the Linksys WAP4410N.
+endef
+
 $(eval $(call Profile,WRT160NL))
 $(eval $(call Profile,WRT400N))
+$(eval $(call Profile,WAP4410N))
diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile
index e4f6c71..cc81a0a 100644
--- a/target/linux/ar71xx/image/Makefile
+++ b/target/linux/ar71xx/image/Makefile
@@ -538,6 +538,8 @@ define Image/Build/WRT400N
 	fi
 endef

+Image/Build/WAP4410N/buildkernel=$(call MkuImageGzip,$(2),$(3))
+Image/Build/WAP4410N=$(call Sysupgrade/KRuImage,$(1),$(2),1638400,6356992)

 define Image/Build/CameoAP94/buildkernel
 	$(call MkuImageLzma,$(2),$(3) $(4))
@@ -1551,6 +1553,7 @@ $(eval $(call SingleProfile,WHRHPG300N,64kraw,WHRHPGN,whr-hp-gn,WHR-HP-GN,ttyS0,
 $(eval $(call SingleProfile,WHRHPG300N,64kraw,WLAEAG300N,wlae-ag300n,WLAE-AG300N,ttyS0,115200,$$(whrhpg300n_mtdlayout),WLAE-AG300N))

 $(eval $(call SingleProfile,WRT400N,64k,WRT400N,wrt400n,WRT400N,ttyS0,115200))
+$(eval $(call SingleProfile,WAP4410N,64k,WAP4410N,wap4410n,WAP4410N,ttyS0,115200))

 $(eval $(call SingleProfile,WZRHP128K,128kraw,WZRHPG300NH,wzr-hp-g300nh,WZR-HP-G300NH,ttyS0,115200,WZR-HP-G300NH))
 $(eval $(call SingleProfile,WZRHP64K,64kraw,WZRHPG300NH2,wzr-hp-g300nh2,WZR-HP-G300NH2,ttyS0,115200,WZR-HP-G300NH2))
diff --git a/target/linux/ar71xx/patches-3.18/904-MIPS-ath79-linksys-wap4410n-support.patch b/target/linux/ar71xx/patches-3.18/904-MIPS-ath79-linksys-wap4410n-support.patch
new file mode 100644
index 0000000..a6fd82f
--- /dev/null
+++ b/target/linux/ar71xx/patches-3.18/904-MIPS-ath79-linksys-wap4410n-support.patch
@@ -0,0 +1,38 @@
+--- a/arch/mips/ath79/Kconfig
++++ b/arch/mips/ath79/Kconfig
+@@ -523,6 +523,15 @@ config ATH79_MACH_WRT400N
+ 	select ATH79_DEV_LEDS_GPIO
+ 	select ATH79_DEV_M25P80
+
++config ATH79_MACH_WAP4410N
++	bool "Linksys WAP4410N board support"
++	select SOC_AR913X
++	select ATH79_DEV_ETH
++	select ATH79_DEV_GPIO_BUTTONS
++	select ATH79_DEV_LEDS_GPIO
++	select ATH79_DEV_USB
++	select ATH79_DEV_WMAC
++
+ config ATH79_MACH_R6100
+ 	bool "NETGEAR R6100 board support"
+ 	select SOC_AR934X
+--- a/arch/mips/ath79/Makefile
++++ b/arch/mips/ath79/Makefile
+@@ -149,6 +149,7 @@ obj-$(CONFIG_ATH79_MACH_WPJ344)	+= mach-
+ obj-$(CONFIG_ATH79_MACH_WPJ558)	+= mach-wpj558.o
+ obj-$(CONFIG_ATH79_MACH_WRT160NL)	+= mach-wrt160nl.o
+ obj-$(CONFIG_ATH79_MACH_WRT400N)	+= mach-wrt400n.o
++obj-$(CONFIG_ATH79_MACH_WAP4410N)	+= mach-wap4410n.o
+ obj-$(CONFIG_ATH79_MACH_WZR_HP_G300NH)	+= mach-wzr-hp-g300nh.o
+ obj-$(CONFIG_ATH79_MACH_WZR_HP_G300NH2)	+= mach-wzr-hp-g300nh2.o
+ obj-$(CONFIG_ATH79_MACH_WZR_HP_AG300H)	+= mach-wzr-hp-ag300h.o
+--- a/arch/mips/ath79/machtypes.h
++++ b/arch/mips/ath79/machtypes.h
+@@ -198,6 +198,7 @@ enum ath79_mach_type {
+ 	ATH79_MACH_WPJ558,		/* Compex WPJ558 */
+ 	ATH79_MACH_WRT160NL,		/* Linksys WRT160NL */
+ 	ATH79_MACH_WRT400N,		/* Linksys WRT400N */
++	ATH79_MACH_WAP4410N,		/* Linksys WAP4410N */
+ 	ATH79_MACH_WZR_HP_AG300H,	/* Buffalo WZR-HP-AG300H */
+ 	ATH79_MACH_WZR_HP_G300NH,	/* Buffalo WZR-HP-G300NH */
+ 	ATH79_MACH_WZR_HP_G300NH2,	/* Buffalo WZR-HP-G300NH2 */
