target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c
static int rtl930x_route_lookup_hw(struct rtl83xx_route *rt)
{
	u32 ip4_m, v;
	struct in6_addr ip6_m;
	int i;

	if (rt->attr.type == 1 || rt->attr.type == 3) // Hardware only supports UC routes
		return -1;

	sw_w32_mask(0x3 << 19, rt->attr.type, RTL930X_L3_HW_LU_KEY_CTRL);
	if (rt->attr.type) { // IPv6
		rtl930x_net6_mask(rt->prefix_len, &ip6_m);
		for (i = 0; i < 4; i++)
			sw_w32(rt->dst_ip6.s6_addr32[0] & ip6_m.s6_addr32[0],
			       RTL930X_L3_HW_LU_KEY_IP_CTRL + (i << 2));
	} else { // IPv4
		ip4_m = inet_make_mask(rt->prefix_len);
		sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL);
		sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 4);
		sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 8);
		v = rt->dst_ip & ip4_m;
		pr_info("%s: searching for %pI4\n", __func__, &v);
		sw_w32(v, RTL930X_L3_HW_LU_KEY_IP_CTRL + 12);
	}

	// Execute CAM lookup in SoC
	sw_w32(BIT(15), RTL930X_L3_HW_LU_CTRL);

	// Wait until execute bit clears and result is ready
	do {
		v = sw_r32(RTL930X_L3_HW_LU_CTRL);
	} while (v & BIT(15));

	pr_info("%s: found: %d, index: %d\n", __func__, !!(v & BIT(14)), v & 0x1ff);

	// Test if search successful (BIT 14 set)
	if (v & BIT(14))
		return v & 0x1ff;

	return -1;
}
/*
 * Look up the index of a prefix route in the routing table CAM for unicast IPv4/6 routes
 * using hardware offload.
 */
Look up the index of a prefix route in the routing table CAM for unicast IPv4/6 routes
using hardware offload.
Look up the index of a prefix route in the routing table CAM for unicast IPv4 / 6 routes using hardware offload .
static int rtl930x_route_lookup_hw(struct rtl83xx_route *rt)
{
	u32 ip4_m, v;
	struct in6_addr ip6_m;
	int i;
	if (rt->attr.type == 1 || rt->attr.type == 3) 
		return -1;
	sw_w32_mask(0x3 << 19, rt->attr.type, RTL930X_L3_HW_LU_KEY_CTRL);
	if (rt->attr.type) { 
		rtl930x_net6_mask(rt->prefix_len, &ip6_m);
		for (i = 0; i < 4; i++)
			sw_w32(rt->dst_ip6.s6_addr32[0] & ip6_m.s6_addr32[0],
			       RTL930X_L3_HW_LU_KEY_IP_CTRL + (i << 2));
	} else { 
		ip4_m = inet_make_mask(rt->prefix_len);
		sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL);
		sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 4);
		sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 8);
		v = rt->dst_ip & ip4_m;
		pr_info("%s: searching for %pI4\n", __func__, &v);
		sw_w32(v, RTL930X_L3_HW_LU_KEY_IP_CTRL + 12);
	}
	sw_w32(BIT(15), RTL930X_L3_HW_LU_CTRL);
	do {
		v = sw_r32(RTL930X_L3_HW_LU_CTRL);
	} while (v & BIT(15));
	pr_info("%s: found: %d, index: %d\n", __func__, !!(v & BIT(14)), v & 0x1ff);
	if (v & BIT(14))
		return v & 0x1ff;
	return -1;
}
static int rtl930x_route_lookup_hw ( struct rtl83xx_route * rt ) { u32 ip4_m , v ; struct in6_addr ip6_m ; int i ; if ( rt -> attr . type == 1 || rt -> attr . type == 3 ) return -1 ; sw_w32_mask ( 0x3 << 19 , rt -> attr . type , RTL930X_L3_HW_LU_KEY_CTRL ) ; if ( rt -> attr . type ) { rtl930x_net6_mask ( rt -> prefix_len , & ip6_m ) ; for ( i = 0 ; i < 4 ; i ++ ) sw_w32 ( rt -> dst_ip6 . s6_addr32 [ 0 ] & ip6_m . s6_addr32 [ 0 ] , RTL930X_L3_HW_LU_KEY_IP_CTRL + ( i << 2 ) ) ; } else { ip4_m = inet_make_mask ( rt -> prefix_len ) ; sw_w32 ( 0 , RTL930X_L3_HW_LU_KEY_IP_CTRL ) ; sw_w32 ( 0 , RTL930X_L3_HW_LU_KEY_IP_CTRL + 4 ) ; sw_w32 ( 0 , RTL930X_L3_HW_LU_KEY_IP_CTRL + 8 ) ; v = rt -> dst_ip & ip4_m ; pr_info ( " \n " , __func__ , & v ) ; sw_w32 ( v , RTL930X_L3_HW_LU_KEY_IP_CTRL + 12 ) ; } sw_w32 ( BIT ( 15 ) , RTL930X_L3_HW_LU_CTRL ) ; do { v = sw_r32 ( RTL930X_L3_HW_LU_CTRL ) ; } while ( v & BIT ( 15 ) ) ; pr_info ( " \n " , __func__ , ! ! ( v & BIT ( 14 ) ) , v & 0x1ff ) ; if ( v & BIT ( 14 ) ) return v & 0x1ff ; return -1 ; }
Look up the index of a prefix route in the routing table CAM for unicast IPv4/6 routes
 using hardware offload.
Look up the index of a prefix route in the routing table CAM for unicast IPv4 / 6 routes using hardware offload .
// Hardware only supports UC routes // IPv6 // IPv4 // Execute CAM lookup in SoC // Wait until execute bit clears and result is ready // Test if search successful (BIT 14 set)