diff --git a/drivers/net/ipq807x/ipq807x_edma.c b/drivers/net/ipq807x/ipq807x_edma.c index cc8ca56784..535da32892 100644 --- a/drivers/net/ipq807x/ipq807x_edma.c +++ b/drivers/net/ipq807x/ipq807x_edma.c @@ -59,6 +59,7 @@ extern void qca8075_phy_interface_set_mode(uint32_t phy_id, uint32_t mode); extern int ipq_qca8033_phy_init(struct phy_ops **ops, u32 phy_id); extern int ipq_qca_aquantia_phy_init(struct phy_ops **ops, u32 phy_id); +static int tftp_acl_our_port; /* * EDMA hardware instance @@ -469,6 +470,11 @@ static int ipq807x_eth_snd(struct eth_device *dev, void *packet, int length) txdesc_ring = ehw->txdesc_ring; + if (tftp_acl_our_port != tftp_our_port) { + /* Allowing tftp packets */ + ipq807x_ppe_acl_set(3, 0x4, 0x1, tftp_our_port, 0xffff, 0, 0); + tftp_acl_our_port = tftp_our_port; + } /* * Read TXDESC ring producer index */ diff --git a/drivers/net/ipq807x/ipq807x_ppe.c b/drivers/net/ipq807x/ipq807x_ppe.c index 549b999e7c..5eddf2c08d 100644 --- a/drivers/net/ipq807x/ipq807x_ppe.c +++ b/drivers/net/ipq807x/ipq807x_ppe.c @@ -25,7 +25,6 @@ DECLARE_GLOBAL_DATA_PTR; #define pr_info(fmt, args...) printf(fmt, ##args); - /* * ipq807x_ppe_gpio_reg_write() */ @@ -50,6 +49,74 @@ static inline void ipq807x_ppe_reg_write(u32 reg, u32 val) writel(val, (void *)(IPQ807X_PPE_BASE_ADDR + reg)); } +void ppe_ipo_rule_reg_set(union ipo_rule_reg_u *hw_reg, int rule_id) +{ + int i; + + for (i = 0; i < 3; i++) { + ipq807x_ppe_reg_write(IPO_CSR_BASE_ADDR + IPO_RULE_REG_ADDRESS + + (rule_id * IPO_RULE_REG_INC) + (i * 4), hw_reg->val[i]); + } +} + +void ppe_ipo_mask_reg_set(union ipo_mask_reg_u *hw_mask, int rule_id) +{ + int i; + + for (i = 0; i < 2; i++) { + ipq807x_ppe_reg_write((IPO_CSR_BASE_ADDR + IPO_MASK_REG_ADDRESS + + (rule_id * IPO_MASK_REG_INC) + (i * 4)), hw_mask->val[i]); + } +} + +void ppe_ipo_action_set(union ipo_action_u *hw_act, int rule_id) +{ + int i; + + for (i = 0; i < 5; i++) { + ipq807x_ppe_reg_write((IPE_L2_BASE_ADDR + IPO_ACTION_ADDRESS + + (rule_id * IPO_ACTION_INC) + (i * 4)), hw_act->val[i]); + } +} + +void ipq807x_ppe_acl_set(int rule_id, int rule_type, int pkt_type, int l4_port_no, int l4_port_mask, int permit, int deny) +{ + union ipo_rule_reg_u hw_reg = {0}; + union ipo_mask_reg_u hw_mask = {0}; + union ipo_action_u hw_act = {0}; + + memset(&hw_reg, 0, sizeof(hw_reg)); + memset(&hw_mask, 0, sizeof(hw_mask)); + memset(&hw_act, 0, sizeof(hw_act)); + + if (rule_id < MAX_RULE) { + if (rule_type == ADPT_ACL_HPPE_IPV4_DIP_RULE) { + hw_reg.bf.rule_type = ADPT_ACL_HPPE_IPV4_DIP_RULE; + hw_reg.bf.rule_field_0 = l4_port_no; + hw_reg.bf.rule_field_1 = pkt_type<<17; + hw_mask.bf.maskfield_0 = l4_port_mask; + hw_mask.bf.maskfield_1 = 7<<17; + if (permit == 0x0) { + hw_act.bf.dest_info_change_en = 1; + hw_act.bf.fwd_cmd = 0;/*forward*/ + hw_reg.bf.pri = 0x1; + } + + if (deny == 0x1) { + hw_act.bf.dest_info_change_en = 1; + hw_act.bf.fwd_cmd = 1;/*drop*/ + hw_reg.bf.pri = 0x0; + + } + hw_reg.bf.src_0 = 0x6; + hw_reg.bf.src_1 = 0x7; + ppe_ipo_rule_reg_set(&hw_reg, rule_id); + ppe_ipo_mask_reg_set(&hw_mask, rule_id); + ppe_ipo_action_set(&hw_act, rule_id); + } + } +} + /* * ipq807x_ppe_vp_port_tbl_set() */ @@ -1193,4 +1260,10 @@ void ipq807x_ppe_provision_init(void) /* Port 0-5 enable */ for (i = 0; i < 6; i++) ipq807x_gmac_port_enable(i); + + /* Allowing DHCP packets */ + ipq807x_ppe_acl_set(0, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 67, 0xffff, 0, 0); + ipq807x_ppe_acl_set(1, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 68, 0xffff, 0, 0); + /* Dropping all the UDP packets */ + ipq807x_ppe_acl_set(2, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 0, 0, 0, 1); } diff --git a/drivers/net/ipq807x/ipq807x_ppe.h b/drivers/net/ipq807x/ipq807x_ppe.h index e7983895be..f9bed8892c 100644 --- a/drivers/net/ipq807x/ipq807x_ppe.h +++ b/drivers/net/ipq807x/ipq807x_ppe.h @@ -49,6 +49,61 @@ union port_mux_ctrl_u { struct port_mux_ctrl bf; }; +enum { + TCP_PKT, + UDP_PKT, +}; + +#define ADPT_ACL_HPPE_IPV4_DIP_RULE 4 +#define MAX_RULE 512 + +struct ipo_rule_reg { + uint32_t rule_field_0:32; + uint32_t rule_field_1:20; + uint32_t fake_mac_header:1; + uint32_t range_en:1; + uint32_t inverse_en:1; + uint32_t rule_type:4; + uint32_t src_type:2; + uint32_t src_0:3; + uint32_t src_1:5; + uint32_t pri:9; + uint32_t res_chain:1; + uint32_t post_routing_en:1; + uint32_t _reserved0:16; +}; + +union ipo_rule_reg_u { + uint32_t val[3]; + struct ipo_rule_reg bf; +}; + +struct ipo_mask_reg { + uint32_t maskfield_0:32; + uint32_t maskfield_1:21; + uint32_t _reserved0:11; +}; + +union ipo_mask_reg_u { + uint32_t val[2]; + struct ipo_mask_reg bf; +}; + +struct ipo_action { + uint32_t dest_info_change_en:1; + uint32_t fwd_cmd:2; + uint32_t _reserved0:29; + uint32_t _reserved1:32; + uint32_t _reserved2:32; + uint32_t _reserved3:32; + uint32_t _reserved4:32; +}; + +union ipo_action_u { + uint32_t val[5]; + struct ipo_action bf; +}; + #define IPQ807X_PORT_MUX_CTRL 0x10 #define PORT4_PCS_SEL_GMII_FROM_PCS0 1 #define PORT4_PCS_SEL_RGMII 0 @@ -180,3 +235,13 @@ union port_mux_ctrl_u { #define PORT_BRIDGE_CTRL_INC 0x4 #define TX_MAC_EN (1 << 16) +#define IPO_CSR_BASE_ADDR 0x0b0000 + +#define IPO_RULE_REG_ADDRESS 0x0 +#define IPO_RULE_REG_INC 0x10 + +#define IPO_MASK_REG_ADDRESS 0x2000 +#define IPO_MASK_REG_INC 0x10 + +#define IPO_ACTION_ADDRESS 0x8000 +#define IPO_ACTION_INC 0x20 diff --git a/include/net.h b/include/net.h index 344f23a9a4..f7039e3acc 100644 --- a/include/net.h +++ b/include/net.h @@ -510,7 +510,7 @@ extern ushort net_our_vlan; /* Our VLAN */ extern ushort net_native_vlan; /* Our Native VLAN */ extern int net_restart_wrap; /* Tried all network devices */ - +extern int tftp_our_port; enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL diff --git a/net/tftp.c b/net/tftp.c index f8942aed28..429e00881c 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -70,7 +70,7 @@ static struct in_addr tftp_remote_ip; /* The UDP port at their end */ static int tftp_remote_port; /* The UDP port at our end */ -static int tftp_our_port; +int tftp_our_port; static int timeout_count; /* packet sequence number */ static ulong tftp_cur_block;