[OpenWrt-Devel] [Patch][(kernel|generic)] Add port ingress rate limit function for AR8337N switch

luny at codeaurora.org luny at codeaurora.org
Wed Jul 2 03:22:27 EDT 2014


hi, all:
    now we want to add AR8337 switch feature into openwrt, can you give me
some suggestion about how to add these features. So I give one
example, hope your feedback.


> hi, all:
> we will try to add one feature for AR8337 switch: port ingress rate limit.
> we can use swconfig extension command to implement it as below example:
> swconfig dev eth0 set extension_switch "port_rate_limit set port 1 rate
> 100000"
> Note: in this example, 100000 means 100000Kbps.
> 1. We use one special communication command in swconfig "extension_switch"
> to transfer the extension command for AR8337 switch enhanced feature.
>
>
> Signed-off-by: Yue Lun <luny at codeaurora.org>
>
> ---
>  .../linux/generic/files/drivers/net/phy/ar8216.c   |  10 +
>  .../generic/files/drivers/net/phy/ar8216_ext.c     | 792
> +++++++++++++++++++++
>  .../generic/files/drivers/net/phy/ar8216_ext.h     | 269 +++++++
>  .../generic/patches-3.10/724-phy_ar8216.patch      |   2 +-
>  .../generic/patches-3.10/725-phy_rtl8306.patch     |   2 +-
>  .../generic/patches-3.10/726-phy_rtl8366.patch     |   2 +-
>  .../generic/patches-3.14/724-phy_ar8216.patch      |   2 +-
>  7 files changed, 1075 insertions(+), 4 deletions(-)
>  mode change 100644 => 100755
> target/linux/generic/files/drivers/net/phy/ar8216.c
>  create mode 100755
> target/linux/generic/files/drivers/net/phy/ar8216_ext.c
>  create mode 100755
> target/linux/generic/files/drivers/net/phy/ar8216_ext.h
>  mode change 100644 => 100755
> target/linux/generic/patches-3.10/724-phy_ar8216.patch
>  mode change 100644 => 100755
> target/linux/generic/patches-3.10/725-phy_rtl8306.patch
>  mode change 100644 => 100755
> target/linux/generic/patches-3.10/726-phy_rtl8366.patch
>  mode change 100644 => 100755
> target/linux/generic/patches-3.14/724-phy_ar8216.patch
>
> diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c
> b/target/linux/generic/files/drivers/net/phy/ar8216.c
> old mode 100644
> new mode 100755
> index 3f60878..bf5a078
> --- a/target/linux/generic/files/drivers/net/phy/ar8216.c
> +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c
> @@ -38,6 +38,7 @@
>  #include <linux/gpio.h>
>
>  #include "ar8216.h"
> +#include "ar8216_ext.h"
>
>  /* size of the vlan table */
>  #define AR8X16_MAX_VLANS	128
> @@ -2389,6 +2390,12 @@ static struct switch_attr ar8327_sw_attr_globals[]
> = {
>  		.get = ar8xxx_sw_get_mirror_source_port,
>  		.max = AR8327_NUM_PORTS - 1
>   	},
> + 	{
> +		.type = SWITCH_TYPE_STRING,
> +		.name = "extension_switch",
> +		.description = "Enhanced switch feature",
> +		.set = ar8xxx_sw_set_extension_switch,
> + 	},
>  };
>
>  static struct switch_attr ar8xxx_sw_attr_port[] = {
> @@ -2669,6 +2676,7 @@ ar8xxx_probe_switch(struct ar8xxx_priv *priv)
>  	return 0;
>  }
>
> +extern int ar8216_ext_init(struct ar8xxx_priv *priv);
>  static int
>  ar8xxx_start(struct ar8xxx_priv *priv)
>  {
> @@ -2688,6 +2696,8 @@ ar8xxx_start(struct ar8xxx_priv *priv)
>
>  	ar8xxx_mib_start(priv);
>
> +	ar8216_ext_init(priv);
> +
>  	return 0;
>  }
>
> diff --git a/target/linux/generic/files/drivers/net/phy/ar8216_ext.c
> b/target/linux/generic/files/drivers/net/phy/ar8216_ext.c
> new file mode 100755
> index 0000000..e31868f
> --- /dev/null
> +++ b/target/linux/generic/files/drivers/net/phy/ar8216_ext.c
> @@ -0,0 +1,792 @@
> +/*
> + * ar8216_ext.c: AR8216 switch driver enhanced feature
> + *
> + * Copyright (C) 2014 Zou Shunxiang <shunxian at qti.qualcomm.com>
> + *
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/if.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/if_ether.h>
> +#include <linux/skbuff.h>
> +#include <linux/netdevice.h>
> +#include <linux/netlink.h>
> +#include <linux/bitops.h>
> +#include <net/genetlink.h>
> +#include <linux/switch.h>
> +#include <linux/delay.h>
> +#include <linux/phy.h>
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/lockdep.h>
> +#include <linux/ar8216_platform.h>
> +#include <linux/workqueue.h>
> +#include <linux/of_device.h>
> +#include <linux/leds.h>
> +#include <linux/gpio.h>
> +
> +#include "ar8216_ext.h"
> +#include "ar8216.h"
> +
> +/* size of the vlan table */
> +#define AR8X16_MAX_VLANS	128
> +#define AR8X16_PROBE_RETRIES	10
> +#define AR8X16_MAX_PORTS	8
> +struct ar8xxx_mib_desc {
> +	unsigned int size;
> +	unsigned int offset;
> +	const char *name;
> +};
> +
> +struct ar8xxx_chip {
> +	unsigned long caps;
> +
> +	int (*hw_init)(struct ar8xxx_priv *priv);
> +	void (*cleanup)(struct ar8xxx_priv *priv);
> +
> +	void (*init_globals)(struct ar8xxx_priv *priv);
> +	void (*init_port)(struct ar8xxx_priv *priv, int port);
> +	void (*setup_port)(struct ar8xxx_priv *priv, int port, u32 egress,
> +			   u32 ingress, u32 members, u32 pvid);
> +	u32 (*read_port_status)(struct ar8xxx_priv *priv, int port);
> +	int (*atu_flush)(struct ar8xxx_priv *priv);
> +	void (*vtu_flush)(struct ar8xxx_priv *priv);
> +	void (*vtu_load_vlan)(struct ar8xxx_priv *priv, u32 vid, u32 port_mask);
> +
> +	const struct ar8xxx_mib_desc *mib_decs;
> +	unsigned num_mibs;
> +};
> +
> +enum ar8327_led_pattern {
> +	AR8327_LED_PATTERN_OFF = 0,
> +	AR8327_LED_PATTERN_BLINK,
> +	AR8327_LED_PATTERN_ON,
> +	AR8327_LED_PATTERN_RULE,
> +};
> +
> +struct ar8327_led {
> +	struct led_classdev cdev;
> +	struct ar8xxx_priv *sw_priv;
> +
> +	char *name;
> +	bool active_low;
> +	u8 led_num;
> +	enum ar8327_led_mode mode;
> +
> +	struct mutex mutex;
> +	spinlock_t lock;
> +	struct work_struct led_work;
> +	bool enable_hw_mode;
> +	enum ar8327_led_pattern pattern;
> +};
> +
> +struct ar8327_data {
> +	u32 port0_status;
> +	u32 port6_status;
> +
> +	struct ar8327_led **leds;
> +	unsigned int num_leds;
> +};
> +
> +struct ar8xxx_priv {
> +	struct switch_dev dev;
> +	struct mii_bus *mii_bus;
> +	struct phy_device *phy;
> +
> +	u32 (*read)(struct ar8xxx_priv *priv, int reg);
> +	void (*write)(struct ar8xxx_priv *priv, int reg, u32 val);
> +	u32 (*rmw)(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val);
> +
> +	int (*get_port_link)(unsigned port);
> +
> +	const struct net_device_ops *ndo_old;
> +	struct net_device_ops ndo;
> +	struct mutex reg_mutex;
> +	u8 chip_ver;
> +	u8 chip_rev;
> +	const struct ar8xxx_chip *chip;
> +	union {
> +		struct ar8327_data ar8327;
> +	} chip_data;
> +	bool initialized;
> +	bool port4_phy;
> +	char buf[2048];
> +
> +	bool init;
> +	bool mii_lo_first;
> +
> +	struct mutex mib_lock;
> +	struct delayed_work mib_work;
> +	int mib_next_port;
> +	u64 *mib_stats;
> +
> +	struct list_head list;
> +	unsigned int use_count;
> +
> +	/* all fields below are cleared on reset */
> +	bool vlan;
> +	u16 vlan_id[AR8X16_MAX_VLANS];
> +	u8 vlan_table[AR8X16_MAX_VLANS];
> +	u8 vlan_tagged;
> +	u16 pvid[AR8X16_MAX_PORTS];
> +
> +	/* mirroring */
> +	bool mirror_rx;
> +	bool mirror_tx;
> +	int source_port;
> +	int monitor_port;
> +};
> +
> +static u8 ar8xxx_chip_version = 0xff;
> +struct ar8xxx_priv *ext_priv;
> +static hsl_api_t hsl_api_table;
> +
> +/* register functions */
> +#define SW_BIT_MASK_U32(nr) (~(0xFFFFFFFF << (nr)))
> +
> +#define SW_FIELD_MASK_U32(offset, len) \
> +	((SW_BIT_MASK_U32(len) << (offset)))
> +
> +#define SW_FIELD_MASK_NOT_U32(offset,len) \
> +	(~(SW_BIT_MASK_U32(len) << (offset)))
> +
> +#define SW_FIELD_2_REG(field_val, bit_offset) \
> +	(field_val << (bit_offset) )
> +
> +#define SW_REG_2_FIELD(reg_val, bit_offset, field_len) \
> +	(((reg_val) >> (bit_offset)) & ((1 << (field_len)) - 1))
> +
> +#define SW_REG_SET_BY_FIELD_U32(reg_value, field_value, bit_offset,
> field_len)\
> +	do { \
> +		(reg_value) = \
> +		(((reg_value) & SW_FIELD_MASK_NOT_U32((bit_offset),(field_len))) \
> +		| (((field_value) & SW_BIT_MASK_U32(field_len)) << (bit_offset)));\
> +	} while (0)
> +
> +#define SW_FIELD_GET_BY_REG_U32(reg_value, field_value, bit_offset,
> field_len)\
> +	do { \
> +		(field_value) = \
> +		(((reg_value) >> (bit_offset)) & SW_BIT_MASK_U32(field_len)); \
> +	} while (0)
> +
> +#define SW_SET_REG_BY_FIELD(reg, field, field_value, reg_value) \
> +	SW_REG_SET_BY_FIELD_U32(reg_value, field_value, reg##_##field##_BOFFSET,
> \
> +							reg##_##field##_BLEN)
> +
> +#define SW_GET_FIELD_BY_REG(reg, field, field_value, reg_value) \
> +	SW_FIELD_GET_BY_REG_U32(reg_value, field_value, reg##_##field##_BOFFSET,
> \
> +							reg##_##field##_BLEN)
> +
> +static inline void
> +split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page)
> +{
> +	regaddr >>= 1;
> +	*r1 = regaddr & 0x1e;
> +
> +	regaddr >>= 5;
> +	*r2 = regaddr & 0x7;
> +
> +	regaddr >>= 3;
> +	*page = regaddr & 0x1ff;
> +}
> +
> +static u32
> +ar8xxx_mii_read(struct ar8xxx_priv *priv, int reg)
> +{
> +	struct mii_bus *bus = priv->mii_bus;
> +	u16 r1, r2, page;
> +	u16 lo, hi;
> +
> +	split_addr((u32) reg, &r1, &r2, &page);
> +
> +	mutex_lock(&bus->mdio_lock);
> +
> +	bus->write(bus, 0x18, 0, page);
> +	usleep_range(1000, 2000); /* wait for the page switch to propagate */
> +	lo = bus->read(bus, 0x10 | r2, r1);
> +	hi = bus->read(bus, 0x10 | r2, r1 + 1);
> +
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	return (hi << 16) | lo;
> +}
> +
> +static void
> +ar8xxx_mii_write(struct ar8xxx_priv *priv, int reg, u32 val)
> +{
> +	struct mii_bus *bus = priv->mii_bus;
> +	u16 r1, r2, r3;
> +	u16 lo, hi;
> +
> +	split_addr((u32) reg, &r1, &r2, &r3);
> +	lo = val & 0xffff;
> +	hi = (u16) (val >> 16);
> +
> +	mutex_lock(&bus->mdio_lock);
> +
> +	bus->write(bus, 0x18, 0, r3);
> +	usleep_range(1000, 2000); /* wait for the page switch to propagate */
> +	if (priv->mii_lo_first) {
> +		bus->write(bus, 0x10 | r2, r1, lo);
> +		bus->write(bus, 0x10 | r2, r1 + 1, hi);
> +	} else {
> +		bus->write(bus, 0x10 | r2, r1 + 1, hi);
> +		bus->write(bus, 0x10 | r2, r1, lo);
> +	}
> +
> +	mutex_unlock(&bus->mdio_lock);
> +}
> +
> +static int
> +_isisc_mdio_reg_get(u32 reg_addr,
> +                   u8 value[], u32 value_len)
> +{
> +	u32 reg_val;
> +
> +	if (value_len != sizeof (u32))
> +		return -3;
> +
> +	reg_val = ar8xxx_mii_read(ext_priv, reg_addr);
> +	memcpy(value, &reg_val, sizeof (u32));
> +
> +	return 0;
> +}
> +
> +static int
> +_isisc_mdio_reg_set(u32 reg_addr, u8 value[], u32 value_len)
> +{
> +	u32 reg_val;
> +
> +	if (value_len != sizeof (u32))
> +		return -3;
> +
> +	memcpy(&reg_val, value, sizeof (u32));
> +
> +	ar8xxx_mii_write(ext_priv, reg_addr, reg_val);
> +
> +	return 0;
> +}
> +
> +int
> +isisc_reg_get(u32 reg_addr, u8 value[],
> +             u32 value_len)
> +{
> +	int rv;
> +	unsigned long flags;
> +
> +	local_irq_save(flags);
> +	rv = _isisc_mdio_reg_get(reg_addr, value, value_len);
> +	local_irq_restore(flags);
> +
> +	return rv;
> +}
> +
> +int
> +isisc_reg_set(u32 reg_addr, u8 value[], u32 value_len)
> +{
> +	int rv;
> +	unsigned long flags;
> +
> +	u32 rt_value = 0;
> +
> +	/*get MODULE_EN reg rsv */
> +	if (isisc_reg_get(0x30,(void *)&rt_value,4) != 0)
> +		return -1;
> +
> +	local_irq_save(flags);
> +	rv = _isisc_mdio_reg_set(reg_addr, value, value_len);
> +	local_irq_restore(flags);
> +
> +	return rv;
> +}
> +
> +int
> +isisc_reg_field_get(u32 reg_addr,
> +					u32 bit_offset, u32 field_len,
> +					u8 value[], u32 value_len)
> +{
> +	u32 reg_val = 0;
> +
> +	if ((bit_offset >= 32 || (field_len > 32)) || (field_len == 0))
> +		return -4;
> +
> +	if (value_len != sizeof (u32))
> +		return -3;
> +
> +	if (isisc_reg_get(reg_addr, (u8 *) & reg_val, sizeof (u32)) != 0)
> +		return -1;
> +
> +	if(32 == field_len) {
> +		*((u32 *) value) = reg_val;
> +	} else {
> +		*((u32 *) value) = SW_REG_2_FIELD(reg_val, bit_offset, field_len);
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +isisc_reg_field_set(u32 reg_addr,
> +					u32 bit_offset, u32 field_len,
> +					const u8 value[], u32 value_len)
> +{
> +	u32 reg_val;
> +	u32 field_val = *((u32 *) value);
> +
> +	if ((bit_offset >= 32 || (field_len > 32)) || (field_len == 0))
> +		return -4;
> +
> +	if (value_len != sizeof (u32))
> +		return -3;
> +
> +	if (isisc_reg_get(reg_addr, (u8 *) & reg_val, sizeof (u32)) != 0)
> +		return -1;
> +
> +	if(32 == field_len) {
> +		reg_val = field_val;
> +	} else {
> +		SW_REG_SET_BY_FIELD_U32(reg_val, field_val, bit_offset, field_len);
> +	}
> +
> +	if (isisc_reg_set(reg_addr, (u8 *) & reg_val, sizeof (u32)) != 0)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +#define HSL_REG_ENTRY_GET(rv, reg, index, value, val_len) \
> +	do { \
> +		rv = hsl_api_table.reg_get(reg##_OFFSET + ((u32)index) *
> reg##_E_OFFSET,\
> +								(u8*)value, (u8)val_len); \
> +	} while (0);
> +
> +#define HSL_REG_ENTRY_SET(rv, reg, index, value, val_len) \
> +	do { \
> +		rv = hsl_api_table.reg_set (reg##_OFFSET + ((u32)index) *
> reg##_E_OFFSET,\
> +								(u8*)value, (u8)val_len); \
> +	} while (0);
> +
> +
> +static void
> +_isisc_ingress_bs_byte_sw_to_hw(u32 sw_bs, u32 * hw_bs)
> +{
> +	u32 i;
> +	u32 data[8] = {
> +	0, 4 * 1024, 32 * 1024, 128 * 1024, 512 * 1024, 2 * 1024 * 1024,
> +	8 * 1024 * 1024, 32 * 1024 * 1024
> +	};
> +
> +	for (i = 7; i >= 0; i--) {
> +		if (sw_bs >= data[i]) {
> +			*hw_bs = i;
> +			break;
> +		}
> +	}
> +
> +	return;
> +}
> +
> +static void
> +_isisc_ingress_bs_byte_hw_to_sw(u32 hw_bs, u32 * sw_bs)
> +{
> +	u32 data[8] = {
> +		0, 4 * 1024, 32 * 1024, 128 * 1024, 512 * 1024, 2 * 1024 * 1024,
> +		8 * 1024 * 1024, 32 * 1024 * 1024
> +	};
> +
> +	*sw_bs = data[hw_bs & 0x7];
> +
> +	return;
> +}
> +
> +static void
> +_isisc_ingress_bs_frame_sw_to_hw(u32 sw_bs, u32 * hw_bs)
> +{
> +	u32 data[8] = { 0, 4, 16, 64, 256, 1024, 4096, 16384 };
> +	u32 i;
> +
> +	for (i = 7; i >= 0; i--) {
> +		if (sw_bs >= data[i]) {
> +			*hw_bs = i;
> +			break;
> +		}
> +	}
> +
> +	return;
> +}
> +
> +static void
> +_isisc_ingress_bs_frame_hw_to_sw(u32 hw_bs, u32 * sw_bs)
> +{
> +	u32 data[8] = { 0, 4, 16, 64, 256, 1024, 4096, 16384 };
> +
> +	*sw_bs = data[hw_bs & 0x7];
> +
> +	return;
> +}
> +
> +static void
> +_isisc_rate_flag_parse(u32 sw_flag, u32 * hw_flag)
> +{
> +	*hw_flag = 0;
> +
> +	if (FAL_INGRESS_POLICING_TCP_CTRL & sw_flag) {
> +		*hw_flag |= (0x1 << 1);
> +	}
> +
> +	if (FAL_INGRESS_POLICING_MANAGEMENT & sw_flag) {
> +		*hw_flag |= (0x1 << 2);
> +	}
> +
> +	if (FAL_INGRESS_POLICING_BROAD & sw_flag) {
> +		*hw_flag |= (0x1 << 3);
> +	}
> +
> +	if (FAL_INGRESS_POLICING_UNK_UNI & sw_flag) {
> +		*hw_flag |= (0x1 << 4);
> +	}
> +
> +	if (FAL_INGRESS_POLICING_UNK_MUL & sw_flag) {
> +		*hw_flag |= (0x1 << 5);
> +	}
> +
> +	if (FAL_INGRESS_POLICING_UNI & sw_flag) {
> +		*hw_flag |= (0x1 << 6);
> +	}
> +
> +	if (FAL_INGRESS_POLICING_MUL & sw_flag) {
> +		*hw_flag |= (0x1 << 7);
> +	}
> +
> +	return;
> +}
> +
> +static void
> +_isisc_rate_ts_parse(fal_rate_mt_t sw, u32 * hw)
> +{
> +	if (FAL_RATE_MI_100US == sw) {
> +		*hw = 0;
> +	} else if (FAL_RATE_MI_1MS == sw) {
> +		*hw = 1;
> +	} else if (FAL_RATE_MI_10MS == sw) {
> +		*hw = 2;
> +	} else if (FAL_RATE_MI_100MS) {
> +		*hw = 3;
> +	} else {
> +		*hw = 0;
> +	}
> +
> +	return;
> +}
> +
> +static int
> +isisc_rate_port_policer_set(u32 port_id,
> +                            fal_port_policer_t * policer)
> +{
> +	int rv;
> +	u32 cir = 0x7fff, eir = 0x7fff, cbs = 0, ebs = 0, tmp, data[3] = { 0 };
> +
> +	data[0] = 0x18000000;
> +	if (FAL_BYTE_BASED == policer->meter_unit) {
> +		if (true == policer->c_enable) {
> +			cir = policer->cir >> 5;
> +			policer->cir = cir << 5;
> +			_isisc_ingress_bs_byte_sw_to_hw(policer->cbs, &cbs);
> +			_isisc_ingress_bs_byte_hw_to_sw(cbs, &(policer->cbs));
> +		}
> +
> +		if (false == policer->e_enable) {
> +			eir = policer->eir >> 5;
> +			policer->eir = eir << 5;
> +			_isisc_ingress_bs_byte_sw_to_hw(policer->ebs, &ebs);
> +			_isisc_ingress_bs_byte_hw_to_sw(ebs, &(policer->ebs));
> +		}
> +
> +		SW_SET_REG_BY_FIELD(INGRESS_POLICER1, INGRESS_UNIT, 0, data[1]);
> +	} else if (FAL_FRAME_BASED == policer->meter_unit) {
> +		if (true == policer->c_enable) {
> +			cir = (policer->cir * 2) / 125;
> +			policer->cir = cir / 2 * 125 + cir % 2 * 63;
> +			_isisc_ingress_bs_frame_sw_to_hw(policer->cbs, &cbs);
> +			_isisc_ingress_bs_frame_hw_to_sw(cbs, &(policer->cbs));
> +		}
> +
> +		if (true == policer->c_enable) {
> +			eir = (policer->eir * 2) / 125;
> +			policer->eir = eir / 2 * 125 + eir % 2 * 63;
> +			_isisc_ingress_bs_frame_sw_to_hw(policer->ebs, &ebs);
> +			_isisc_ingress_bs_frame_hw_to_sw(ebs, &(policer->ebs));
> +		}
> +
> +		SW_SET_REG_BY_FIELD(INGRESS_POLICER1, INGRESS_UNIT, 1, data[1]);
> +	} else {
> +		return -6;
> +	}
> +
> +	SW_SET_REG_BY_FIELD(INGRESS_POLICER0, INGRESS_CIR, cir, data[0]);
> +	SW_SET_REG_BY_FIELD(INGRESS_POLICER0, INGRESS_CBS, cbs, data[0]);
> +	SW_SET_REG_BY_FIELD(INGRESS_POLICER1, INGRESS_EIR, eir, data[1]);
> +	SW_SET_REG_BY_FIELD(INGRESS_POLICER1, INGRESS_EBS, ebs, data[1]);
> +
> +	if (true == policer->combine_mode) {
> +		SW_SET_REG_BY_FIELD(INGRESS_POLICER0, RATE_MODE, 1, data[0]);
> +	}
> +
> +	if (true == policer->deficit_en) {
> +		SW_SET_REG_BY_FIELD(INGRESS_POLICER1, INGRESS_BORROW, 1, data[1]);
> +	}
> +
> +	if (true == policer->color_mode) {
> +		SW_SET_REG_BY_FIELD(INGRESS_POLICER1, INGRESS_CM, 1, data[1]);
> +	}
> +
> +	if (true == policer->couple_flag) {
> +		SW_SET_REG_BY_FIELD(INGRESS_POLICER1, INGRESS_CF, 1, data[1]);
> +	}
> +
> +	_isisc_rate_ts_parse(policer->c_meter_interval, &tmp);
> +	SW_SET_REG_BY_FIELD(INGRESS_POLICER0, C_ING_TS, tmp, data[0]);
> +
> +	_isisc_rate_ts_parse(policer->e_meter_interval, &tmp);
> +	SW_SET_REG_BY_FIELD(INGRESS_POLICER1, E_ING_TS, tmp, data[1]);
> +
> +	_isisc_rate_flag_parse(policer->c_rate_flag, &tmp);
> +	data[2] = (tmp << 8) & 0xff00;
> +
> +	_isisc_rate_flag_parse(policer->e_rate_flag, &tmp);
> +	data[2] |= (tmp & 0xff);
> +
> +	HSL_REG_ENTRY_SET(rv, INGRESS_POLICER0, port_id,
> +					(u8 *) (&data[0]), sizeof (u32));
> +
> +	HSL_REG_ENTRY_SET(rv, INGRESS_POLICER1, port_id,
> +					(u8 *) (&data[1]), sizeof (u32));
> +
> +	HSL_REG_ENTRY_SET(rv, INGRESS_POLICER2, port_id,
> +					(u8 *) (&data[2]), sizeof (u32));
> +
> +	return rv;
> +}
> +
> +int isisc_rate_init()
> +{
> +	hsl_api_table.rate_port_policer_set = isisc_rate_port_policer_set;
> +
> +	return 0;
> +}
> +
> +int isisc_init()
> +{
> +	hsl_api_table.reg_get = isisc_reg_get;
> +	hsl_api_table.reg_set = isisc_reg_set;
> +	hsl_api_table.reg_field_get = isisc_reg_field_get;
> +	hsl_api_table.reg_field_set = isisc_reg_field_set;
> +
> +	isisc_rate_init();
> +
> +	return 0;
> +}
> +
> +int fal_init(u8 chip_type)
> +{
> +	int rv = 0;
> +
> +	memset(&hsl_api_table, 0, sizeof (hsl_api_t));
> +
> +	ar8xxx_chip_version = chip_type;
> +
> +	switch (ar8xxx_chip_version) {
> +		case 0x13:
> +			rv = isisc_init();
> +			break;
> +
> +		default:
> +			return -2;
> +	}
> +
> +	return rv;
> +}
> +
> +int ar8216_ext_init(struct ar8xxx_priv *priv)
> +{
> +	ext_priv = priv;
> +	fal_init(priv->chip_ver);
> +
> +	return 0;
> +}
> +
> +/*fal api for externel calling*/
> +int
> +fal_rate_port_policer_set(u32 port_id,
> +                           fal_port_policer_t * policer)
> +{
> +	int rv;
> +
> +	if (NULL == hsl_api_table.rate_port_policer_set)
> +		return -26;
> +
> +	rv = hsl_api_table.rate_port_policer_set(port_id, policer);
> +
> +	return rv;
> +}
> +
> +#define EXT_CMD_STR_MAX   128
> +#define EXT_CMD_WORDS_MAX  16
> +#define EXT_CMD_WORDS_LENGTH_MAX  32
> +/*
> + at cmd_str   [in]
> + at cmd_words [out]
> +*/
> +static int
> +ext_cmd_words_get(char *cmd_str,
> +	char cmd_words[EXT_CMD_WORDS_MAX][EXT_CMD_WORDS_LENGTH_MAX])
> +{
> +	int nr = 0;
> +	char *s = cmd_str, *tok;
> +	char delim[] = " ";
> +
> +	for (tok = strsep(&s, delim); tok; tok = strsep(&s, delim)) {
> +		strcpy(cmd_words[nr], tok);
> +		nr++;
> +	}
> +
> +	return nr;
> +}
> +
> +/*
> + at cmd_str  [in]
> + at val [out]
> +*/
> +static int
> +ext_cmd_uint32_get(char *cmd_word, unsigned int *val)
> +{
> +	int rv=0;
> +
> +	if (NULL == cmd_word) {
> +		return -EINVAL;
> +	}
> +
> +	if (0 == cmd_word[0]) {
> +		return -EINVAL;
> +	}
> +
> +	if (cmd_word[0] == '0' && (cmd_word[1] == 'x' || cmd_word[1] == 'X')) {
> +		rv = sscanf(cmd_word, "%x", val);
> +	} else {
> +		rv = sscanf(cmd_word, "%d", val);
> +	}
> +
> +	if (1 != rv) {
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +#define to_ar8xxx(_dev) container_of(_dev, struct ar8xxx_priv, dev)
> +void
> +ar8xxx_sw_ext_help()
> +{
> +	printk("ext cmd help:\n");
> +	printk("\"port_rate_limit set port <port_id> rate <rate(Kpbs)>\"\n");
> +}
> +
> +static int
> +ar8xxx_sw_port_rate_limit(struct switch_dev *dev,
> +	char cmd_words[EXT_CMD_WORDS_MAX][EXT_CMD_WORDS_LENGTH_MAX])
> +{
> +	int port = 0;
> +	u32 rate = 0;
> +	fal_port_policer_t port_policer;
> +
> +	if (NULL == cmd_words[1])
> +		return -EINVAL;
> +
> +	if (0 == strcmp(cmd_words[1], "set")) {
> +		/*port_rate_limit get/set port <port_it> rate <rate(Kpbs)>*/
> +		/*        0                 1         2       3          4
> 5*/
> +		if (NULL == cmd_words[2] || NULL == cmd_words[3] ||
> +			NULL == cmd_words[4] ||NULL == cmd_words[5])
> +			return -EINVAL;
> +		if (0 != strcmp(cmd_words[2], "port"))
> +			return -EINVAL;
> +		if (0 != strcmp(cmd_words[4], "rate"))
> +			return -EINVAL;
> +
> +		if ((-EINVAL) == ext_cmd_uint32_get(cmd_words[3], &port))
> +			return -EINVAL;
> +		if ((-EINVAL) == ext_cmd_uint32_get(cmd_words[5], &rate))
> +			return -EINVAL;
> +
> +		port_policer.combine_mode = 0;
> +		port_policer.meter_unit= 0;
> +		port_policer.couple_flag = 0;
> +		port_policer.color_mode = 0;
> +		port_policer.deficit_en = 0;
> +		port_policer.c_enable = 1;
> +		port_policer.cir = (rate/32)*32;
> +		port_policer.cbs = 32768; //32kbps
> +		port_policer.c_rate_flag = 0xfe;
> +		port_policer.c_meter_interval = 1; // 1ms
> +		port_policer.e_enable = 0;
> +		port_policer.eir = 0;
> +		port_policer.ebs = 0;
> +		port_policer.e_rate_flag = 0;
> +		port_policer.e_meter_interval = 1;
> +		fal_rate_port_policer_set(port, &port_policer);
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +ar8xxx_sw_set_extension_switch(struct switch_dev *dev,
> +				 const struct switch_attr *attr,
> +				 struct switch_val *val)
> +{
> +	int ret = 0;
> +	char cmd_str[EXT_CMD_STR_MAX] = {0};
> +	char cmd_words[EXT_CMD_WORDS_MAX][EXT_CMD_WORDS_LENGTH_MAX] = {0};
> +	struct ar8xxx_priv *priv = to_ar8xxx(dev);
> +
> +	if (NULL == val->value.s)
> +		return -EINVAL;
> +
> +	if (EXT_CMD_STR_MAX <=strlen(val->value.s)) {
> +		return -EINVAL;
> +	}
> +
> +	strcpy(cmd_str, val->value.s);
> +
> +	if (0 == ext_cmd_words_get(cmd_str, cmd_words)) {
> +		return -EINVAL;
> +	}
> +
> +	if (NULL == cmd_words[0] || NULL == cmd_words[1])
> +		return -EINVAL;
> +
> +	mutex_lock(&priv->reg_mutex);
> +	if (0 == strcmp(cmd_words[0], "port_rate_limit")) {
> +		ret = ar8xxx_sw_port_rate_limit(dev, cmd_words);
> +	} else {
> +		ar8xxx_sw_ext_help();
> +	}
> +	mutex_unlock(&priv->reg_mutex);
> +
> +	return ret;
> +}
> +
> diff --git a/target/linux/generic/files/drivers/net/phy/ar8216_ext.h
> b/target/linux/generic/files/drivers/net/phy/ar8216_ext.h
> new file mode 100755
> index 0000000..d560f5a
> --- /dev/null
> +++ b/target/linux/generic/files/drivers/net/phy/ar8216_ext.h
> @@ -0,0 +1,269 @@
> +/*
> + * ar8216_ext.c: AR8216 switch driver enhanced feature
> + *
> + * Copyright (C) 2014 Zou Shunxiang <shunxian at qti.qualcomm.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __AR8216_EXT_H
> +#define __AR8216_EXT_H
> +
> +#define HSL_RW 1
> +#define HSL_RO 0
> +/* INGRESS Policer Register0 */
> +#define INGRESS_POLICER0
> +#define INGRESS_POLICER0_OFFSET         0x0b00
> +#define INGRESS_POLICER0_E_LENGTH       4
> +#define INGRESS_POLICER0_E_OFFSET       0x0010
> +#define INGRESS_POLICER0_NR_E           7
> +
> +#define ADD_RATE_BYTE
> +#define INGRESS_POLICER0_ADD_RATE_BYTE_BOFFSET 24
> +#define INGRESS_POLICER0_ADD_RATE_BYTE_BLEN 8
> +#define INGRESS_POLICER0_ADD_RATE_BYTE_FLAG HSL_RW
> +
> +#define C_ING_TS
> +#define INGRESS_POLICER0_C_ING_TS_BOFFSET          22
> +#define INGRESS_POLICER0_C_ING_TS_BLEN             2
> +#define INGRESS_POLICER0_C_ING_TS_FLAG             HSL_RW
> +
> +#define RATE_MODE
> +#define INGRESS_POLICER0_RATE_MODE_BOFFSET          20
> +#define INGRESS_POLICER0_RATE_MODE_BLEN             1
> +#define INGRESS_POLICER0_RATE_MODE_FLAG             HSL_RW
> +
> +#define INGRESS_CBS
> +#define INGRESS_POLICER0_INGRESS_CBS_BOFFSET          15
> +#define INGRESS_POLICER0_INGRESS_CBS_BLEN             3
> +#define INGRESS_POLICER0_INGRESS_CBS_FLAG             HSL_RW
> +
> +#define INGRESS_CIR
> +#define INGRESS_POLICER0_INGRESS_CIR_BOFFSET          0
> +#define INGRESS_POLICER0_INGRESS_CIR_BLEN             15
> +#define INGRESS_POLICER0_INGRESS_CIR_FLAG             HSL_RW
> +
> +
> +/* INGRESS Policer Register1 */
> +#define INGRESS_POLICER1
> +#define INGRESS_POLICER1_OFFSET         0x0b04
> +#define INGRESS_POLICER1_E_LENGTH       4
> +#define INGRESS_POLICER1_E_OFFSET       0x0010
> +#define INGRESS_POLICER1_NR_E           7
> +
> +#define INGRESS_BORROW
> +#define INGRESS_POLICER1_INGRESS_BORROW_BOFFSET          23
> +#define INGRESS_POLICER1_INGRESS_BORROW_BLEN             1
> +#define INGRESS_POLICER1_INGRESS_BORROW_FLAG             HSL_RW
> +
> +#define INGRESS_UNIT
> +#define INGRESS_POLICER1_INGRESS_UNIT_BOFFSET          22
> +#define INGRESS_POLICER1_INGRESS_UNIT_BLEN             1
> +#define INGRESS_POLICER1_INGRESS_UNIT_FLAG             HSL_RW
> +
> +#define INGRESS_CF
> +#define INGRESS_POLICER1_INGRESS_CF_BOFFSET          21
> +#define INGRESS_POLICER1_INGRESS_CF_BLEN             1
> +#define INGRESS_POLICER1_INGRESS_CF_FLAG             HSL_RW
> +
> +#define INGRESS_CM
> +#define INGRESS_POLICER1_INGRESS_CM_BOFFSET          20
> +#define INGRESS_POLICER1_INGRESS_CM_BLEN             1
> +#define INGRESS_POLICER1_INGRESS_CM_FLAG             HSL_RW
> +
> +#define E_ING_TS
> +#define INGRESS_POLICER1_E_ING_TS_BOFFSET          18
> +#define INGRESS_POLICER1_E_ING_TS_BLEN             2
> +#define INGRESS_POLICER1_E_ING_TS_FLAG             HSL_RW
> +
> +#define INGRESS_EBS
> +#define INGRESS_POLICER1_INGRESS_EBS_BOFFSET          15
> +#define INGRESS_POLICER1_INGRESS_EBS_BLEN             3
> +#define INGRESS_POLICER1_INGRESS_EBS_FLAG             HSL_RW
> +
> +#define INGRESS_EIR
> +#define INGRESS_POLICER1_INGRESS_EIR_BOFFSET          0
> +#define INGRESS_POLICER1_INGRESS_EIR_BLEN             15
> +#define INGRESS_POLICER1_INGRESS_EIR_FLAG             HSL_RW
> +
> +
> +/* INGRESS Policer Register2 */
> +#define INGRESS_POLICER2
> +#define INGRESS_POLICER2_OFFSET                 0x0b08
> +#define INGRESS_POLICER2_E_LENGTH               4
> +#define INGRESS_POLICER2_E_OFFSET               0x0010
> +#define INGRESS_POLICER2_NR_E                   7
> +
> +#define C_MUL
> +#define INGRESS_POLICER2_C_MUL_BOFFSET          15
> +#define INGRESS_POLICER2_C_MUL_BLEN             1
> +#define INGRESS_POLICER2_C_UNK_MUL_FLAG         HSL_RW
> +
> +#define C_UNI
> +#define INGRESS_POLICER2_C_UNI_BOFFSET          14
> +#define INGRESS_POLICER2_C_UNI_BLEN             1
> +#define INGRESS_POLICER2_C_UNI_FLAG             HSL_RW
> +
> +#define C_UNK_MUL
> +#define INGRESS_POLICER2_C_UNK_MUL_BOFFSET      13
> +#define INGRESS_POLICER2_C_UNK_MUL_BLEN         1
> +#define INGRESS_POLICER2_C_UNK_MUL_FLAG         HSL_RW
> +
> +#define C_UNK_UNI
> +#define INGRESS_POLICER2_C_UNK_UNI_BOFFSET      12
> +#define INGRESS_POLICER2_C_UNK_UNI_BLEN         1
> +#define INGRESS_POLICER2_C_UNK_UNI_FLAG         HSL_RW
> +
> +#define C_BROAD
> +#define INGRESS_POLICER2_C_BROAD_BOFFSET        11
> +#define INGRESS_POLICER2_C_BROAD_BLEN           1
> +#define INGRESS_POLICER2_C_BROAD_FLAG           HSL_RW
> +
> +#define C_MANAGE
> +#define INGRESS_POLICER2_C_MANAGC_BOFFSET       10
> +#define INGRESS_POLICER2_C_MANAGC_BLEN          1
> +#define INGRESS_POLICER2_C_MANAGC_FLAG          HSL_RW
> +
> +#define C_TCP
> +#define INGRESS_POLICER2_C_TCP_BOFFSET          9
> +#define INGRESS_POLICER2_C_TCP_BLEN             1
> +#define INGRESS_POLICER2_C_TCP_FLAG             HSL_RW
> +
> +#define C_MIRR
> +#define INGRESS_POLICER2_C_MIRR_BOFFSET         8
> +#define INGRESS_POLICER2_C_MIRR_BLEN            1
> +#define INGRESS_POLICER2_C_MIRR_FLAG            HSL_RW
> +
> +#define E_MUL
> +#define INGRESS_POLICER2_E_MUL_BOFFSET          7
> +#define INGRESS_POLICER2_E_MUL_BLEN             1
> +#define INGRESS_POLICER2_E_UNK_MUL_FLAG         HSL_RW
> +
> +#define E_UNI
> +#define INGRESS_POLICER2_E_UNI_BOFFSET          6
> +#define INGRESS_POLICER2_E_UNI_BLEN             1
> +#define INGRESS_POLICER2_E_UNI_FLAG             HSL_RW
> +
> +#define E_UNK_MUL
> +#define INGRESS_POLICER2_E_UNK_MUL_BOFFSET      5
> +#define INGRESS_POLICER2_E_UNK_MUL_BLEN         1
> +#define INGRESS_POLICER2_E_UNK_MUL_FLAG         HSL_RW
> +
> +#define E_UNK_UNI
> +#define INGRESS_POLICER2_E_UNK_UNI_BOFFSET      4
> +#define INGRESS_POLICER2_E_UNK_UNI_BLEN         1
> +#define INGRESS_POLICER2_E_UNK_UNI_FLAG         HSL_RW
> +
> +#define E_BROAD
> +#define INGRESS_POLICER2_E_BROAD_BOFFSET        3
> +#define INGRESS_POLICER2_E_BROAD_BLEN           1
> +#define INGRESS_POLICER2_E_BROAD_FLAG           HSL_RW
> +
> +#define E_MANAGE
> +#define INGRESS_POLICER2_E_MANAGE_BOFFSET       2
> +#define INGRESS_POLICER2_E_MANAGE_BLEN          1
> +#define INGRESS_POLICER2_E_MANAGE_FLAG          HSL_RW
> +
> +#define E_TCP
> +#define INGRESS_POLICER2_E_TCP_BOFFSET          1
> +#define INGRESS_POLICER2_E_TCP_BLEN             1
> +#define INGRESS_POLICER2_E_TCP_FLAG             HSL_RW
> +
> +#define E_MIRR
> +#define INGRESS_POLICER2_E_MIRR_BOFFSET         0
> +#define INGRESS_POLICER2_E_MIRR_BLEN            1
> +#define INGRESS_POLICER2_E_MIRR_FLAG            HSL_RW
> +
> +
> +#define FAL_INGRESS_POLICING_TCP_CTRL     0x2
> +#define FAL_INGRESS_POLICING_MANAGEMENT   0x4
> +#define FAL_INGRESS_POLICING_BROAD        0x8
> +#define FAL_INGRESS_POLICING_UNK_UNI      0x10
> +#define FAL_INGRESS_POLICING_UNK_MUL      0x20
> +#define FAL_INGRESS_POLICING_UNI          0x40
> +#define FAL_INGRESS_POLICING_MUL          0x80
> +
> +typedef enum {
> +	FAL_BYTE_BASED = 0,
> +	FAL_FRAME_BASED,
> +	FAL_RATE_MODE_BUTT
> +} fal_traffic_unit_t;
> +
> +typedef enum {
> +	FAL_RATE_MI_100US = 0,
> +	FAL_RATE_MI_1MS,
> +	FAL_RATE_MI_10MS,
> +	FAL_RATE_MI_100MS,
> +} fal_rate_mt_t;
> +
> +typedef struct {
> +	bool c_enable;
> +	bool e_enable;
> +	bool combine_mode;
> +	fal_traffic_unit_t meter_unit;
> +	bool color_mode;
> +	bool couple_flag;
> +	bool deficit_en;
> +	bool cir;
> +	bool eir;
> +	bool cbs;
> +	bool ebs;
> +	bool c_rate_flag;
> +	bool e_rate_flag;
> +	fal_rate_mt_t c_meter_interval;
> +	fal_rate_mt_t e_meter_interval;
> +} fal_port_policer_t;
> +
> +
> +typedef int
> +	(*hsl_rate_port_policer_set)(u32 port_id,
> +								fal_port_policer_t * policer);
> +/* REG */
> +typedef int
> +	(*hsl_reg_get) (u32 reg_addr,
> +					u8 value[], u32 value_len);
> +
> +typedef int
> +	(*hsl_reg_set) (u32 reg_addr,
> +					u8 value[], u32 value_len);
> +
> +typedef int
> +	(*hsl_reg_field_get) (u32 reg_addr,
> +						u32 bit_offset, u32 field_len,
> +						u8 value[], u32 value_len);
> +
> +typedef int
> +	(*hsl_reg_field_set) (u32 reg_addr,
> +						u32 bit_offset, u32 field_len,
> +						const u8 value[], u32 value_len);
> +
> +typedef struct {
> +	hsl_rate_port_policer_set rate_port_policer_set;
> +
> +	/* REG Access */
> +	hsl_reg_get reg_get;
> +	hsl_reg_set reg_set;
> +	hsl_reg_field_get reg_field_get;
> +	hsl_reg_field_set reg_field_set;
> +} hsl_api_t;
> +
> +extern int fal_rate_port_policer_set(u32 port_id,
> +									fal_port_policer_t * policer);
> +
> +extern int fal_init(u8 chip_type);
> +
> +extern int
> +ar8xxx_sw_set_extension_switch(struct switch_dev *dev,
> +				 const struct switch_attr *attr,
> +				 struct switch_val *val);
> +
> +
> +#endif
> diff --git a/target/linux/generic/patches-3.10/724-phy_ar8216.patch
> b/target/linux/generic/patches-3.10/724-phy_ar8216.patch
> old mode 100644
> new mode 100755
> index d3b238e..58c6244
> --- a/target/linux/generic/patches-3.10/724-phy_ar8216.patch
> +++ b/target/linux/generic/patches-3.10/724-phy_ar8216.patch
> @@ -18,7 +18,7 @@
>   obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o
>   obj-$(CONFIG_IP17XX_PHY)	+= ip17xx.o
>   obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
> -+obj-$(CONFIG_AR8216_PHY)	+= ar8216.o
> ++obj-$(CONFIG_AR8216_PHY)	+= ar8216.o ar8216_ext.o
>   obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
>   obj-$(CONFIG_FIXED_PHY)		+= fixed.o
>   obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o
> diff --git a/target/linux/generic/patches-3.10/725-phy_rtl8306.patch
> b/target/linux/generic/patches-3.10/725-phy_rtl8306.patch
> old mode 100644
> new mode 100755
> index 56899a7..43cbb8a
> --- a/target/linux/generic/patches-3.10/725-phy_rtl8306.patch
> +++ b/target/linux/generic/patches-3.10/725-phy_rtl8306.patch
> @@ -16,7 +16,7 @@
>  @@ -22,6 +22,7 @@ obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o
>   obj-$(CONFIG_IP17XX_PHY)	+= ip17xx.o
>   obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
> - obj-$(CONFIG_AR8216_PHY)	+= ar8216.o
> + obj-$(CONFIG_AR8216_PHY)	+= ar8216.o ar8216_ext.o
>  +obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o
>   obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
>   obj-$(CONFIG_FIXED_PHY)		+= fixed.o
> diff --git a/target/linux/generic/patches-3.10/726-phy_rtl8366.patch
> b/target/linux/generic/patches-3.10/726-phy_rtl8366.patch
> old mode 100644
> new mode 100755
> index cbb5ce1..d190a38
> --- a/target/linux/generic/patches-3.10/726-phy_rtl8366.patch
> +++ b/target/linux/generic/patches-3.10/726-phy_rtl8366.patch
> @@ -35,7 +35,7 @@
>  +++ b/drivers/net/phy/Makefile
>  @@ -23,6 +23,9 @@ obj-$(CONFIG_IP17XX_PHY)	+= ip17xx.o
>   obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
> - obj-$(CONFIG_AR8216_PHY)	+= ar8216.o
> + obj-$(CONFIG_AR8216_PHY)	+= ar8216.o ar8216_ext.o
>   obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o
>  +obj-$(CONFIG_RTL8366_SMI)	+= rtl8366_smi.o
>  +obj-$(CONFIG_RTL8366S_PHY)	+= rtl8366s.o
> diff --git a/target/linux/generic/patches-3.14/724-phy_ar8216.patch
> b/target/linux/generic/patches-3.14/724-phy_ar8216.patch
> old mode 100644
> new mode 100755
> index d3b238e..58c6244
> --- a/target/linux/generic/patches-3.14/724-phy_ar8216.patch
> +++ b/target/linux/generic/patches-3.14/724-phy_ar8216.patch
> @@ -18,7 +18,7 @@
>   obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o
>   obj-$(CONFIG_IP17XX_PHY)	+= ip17xx.o
>   obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
> -+obj-$(CONFIG_AR8216_PHY)	+= ar8216.o
> ++obj-$(CONFIG_AR8216_PHY)	+= ar8216.o ar8216_ext.o
>   obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
>   obj-$(CONFIG_FIXED_PHY)		+= fixed.o
>   obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o
> --
> 1.8.2.1
>
>
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list