diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth.c b/drivers/net/ethernet/ti/icssm/icssm_prueth.c index 1c18106de8e9..4f544db15325 100644 --- a/drivers/net/ethernet/ti/icssm/icssm_prueth.c +++ b/drivers/net/ethernet/ti/icssm/icssm_prueth.c @@ -99,22 +99,20 @@ const struct prueth_queue_desc hsr_prp_txopt_queue_descs[][NUM_QUEUES] = { { .rd_ptr = P0_Q4_BD_OFFSET, .wr_ptr = P0_Q4_BD_OFFSET, }, }, [PRUETH_PORT_QUEUE_MII0] = { - { .rd_ptr = P1_Q1_BD_OFFSET, .wr_ptr = P1_Q1_BD_OFFSET, }, - { .rd_ptr = P1_Q2_BD_OFFSET, .wr_ptr = P1_Q2_BD_OFFSET, }, + { .rd_ptr = P0_Q3_BD_OFFSET, .wr_ptr = P0_Q3_BD_OFFSET, }, + { .rd_ptr = P0_Q4_BD_OFFSET, .wr_ptr = P0_Q4_BD_OFFSET, }, { .rd_ptr = P1_Q3_TXOPT_BD_OFFSET, .wr_ptr = P1_Q3_TXOPT_BD_OFFSET, }, - { .rd_ptr = P1_Q4_TXOPT_BD_OFFSET, - .wr_ptr = P1_Q4_TXOPT_BD_OFFSET, }, - }, - [PRUETH_PORT_QUEUE_MII1] = { { .rd_ptr = P2_Q1_TXOPT_BD_OFFSET, .wr_ptr = P2_Q1_TXOPT_BD_OFFSET, }, - { .rd_ptr = P2_Q2_TXOPT_BD_OFFSET, - .wr_ptr = P2_Q2_TXOPT_BD_OFFSET, }, + }, + [PRUETH_PORT_QUEUE_MII1] = { + { .rd_ptr = P0_Q1_BD_OFFSET, .wr_ptr = P0_Q1_BD_OFFSET, }, + { .rd_ptr = P0_Q2_BD_OFFSET, .wr_ptr = P0_Q2_BD_OFFSET, }, { .rd_ptr = P1_Q3_TXOPT_BD_OFFSET, .wr_ptr = P1_Q3_TXOPT_BD_OFFSET, }, - { .rd_ptr = P1_Q4_TXOPT_BD_OFFSET, - .wr_ptr = P1_Q4_TXOPT_BD_OFFSET, }, + { .rd_ptr = P2_Q1_TXOPT_BD_OFFSET, + .wr_ptr = P2_Q1_TXOPT_BD_OFFSET, }, } }; @@ -1185,6 +1183,12 @@ void icssm_parse_packet_info(struct prueth *prueth, u32 buffer_descriptor, pkt_info->ll_has_no_hsr_tag = (buffer_descriptor & PRUETH_LL_HAS_NO_HSRTAG_MASK); + /* HSR Rx Optimization: + * Read flag from BD to indicate packet is valid or not for HOST. + */ + pkt_info->host_recv_flag = !!(buffer_descriptor & + PRUETH_BD_HOST_RECV_MASK); + pkt_info->length = (buffer_descriptor & PRUETH_BD_LENGTH_MASK) >> PRUETH_BD_LENGTH_SHIFT; pkt_info->broadcast = !!(buffer_descriptor & PRUETH_BD_BROADCAST_MASK); @@ -1332,9 +1336,27 @@ int icssm_emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr, /* calculate new pointer in ram */ *bd_rd_ptr = rxqueue->buffer_desc_offset + (update_block * BD_SIZE); + /* HSR Rx Optimization + * If the packet need to be just forwarded, + * update read pointer(*bd_rd_ptr) and skip + * processing since this is a dummy packet for HOST. + */ + if (PRUETH_IS_HSR(emac->prueth)) { + if (!pkt_info->host_recv_flag) + return 0; + } + /* Pkt len w/ HSR tag removed, If applicable */ actual_pkt_len = pkt_info->length - start_offset; + if (PRUETH_IS_HSR(emac->prueth)) { + /* HSR RX optimization: HSR Tag Removal Handling + * Packet is sent with HSR Tag to Driver + */ + if (!start_offset && !pkt_info->timestamp) + actual_pkt_len -= ICSS_LRE_TAG_RCT_SIZE; + } + /* Need to add dummy hsr tag for PTP LL packets */ if (pkt_info->ll_has_no_hsr_tag) actual_pkt_len += ICSS_LRE_TAG_RCT_SIZE; @@ -1360,30 +1382,43 @@ int icssm_emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr, (read_block * ICSS_BLOCK_SIZE); src_addr += start_offset; + /* HSR RX optimization: HSR Tag Removal Handling + * Packet is sent with HSR Tag to Driver + */ + + /* Copy destination and source MAC address first */ + memcpy(dst_addr, src_addr, PRUETH_ETH_TYPE_OFFSET); + src_addr += PRUETH_ETH_TYPE_OFFSET; + dst_addr += PRUETH_ETH_TYPE_OFFSET; + + adjust_for_dummy_hsr_tag += PRUETH_ETH_TYPE_OFFSET; + + /* Check for VLAN tag */ + check_vlan_ptr = src_addr; + type = (*check_vlan_ptr++) << PRUETH_ETH_TYPE_UPPER_SHIFT; + type |= *check_vlan_ptr++; + + if (type == ETH_P_8021Q) { + memcpy(dst_addr, src_addr, VLAN_HLEN); + src_addr += VLAN_HLEN; + dst_addr += VLAN_HLEN; + adjust_for_dummy_hsr_tag += VLAN_HLEN; + } + if (pkt_info->ll_has_no_hsr_tag) { - /* Copy destination and source MAC address first */ - memcpy(dst_addr, src_addr, PRUETH_ETH_TYPE_OFFSET); - src_addr += PRUETH_ETH_TYPE_OFFSET; - dst_addr += PRUETH_ETH_TYPE_OFFSET; - - adjust_for_dummy_hsr_tag += PRUETH_ETH_TYPE_OFFSET; - - /* Check for VLAN tag */ - check_vlan_ptr = src_addr; - type = (*check_vlan_ptr++) << PRUETH_ETH_TYPE_UPPER_SHIFT; - type |= *check_vlan_ptr++; - - if (type == ETH_P_8021Q) { - memcpy(dst_addr, src_addr, VLAN_HLEN); - src_addr += VLAN_HLEN; - dst_addr += VLAN_HLEN; - adjust_for_dummy_hsr_tag += VLAN_HLEN; - } /* Copy dummy HSR tag */ memcpy(dst_addr, dummy_hsr_tag, ICSS_LRE_TAG_RCT_SIZE); dst_addr += ICSS_LRE_TAG_RCT_SIZE; } + /* HSR RX optimization: HSR Tag Removal Handling + * Packet is sent with HSR Tag to Driver + */ + if (PRUETH_IS_HSR(emac->prueth)) { + if (!start_offset && !pkt_info->timestamp) + src_addr += ICSS_LRE_TAG_RCT_SIZE; + } + /* Copy the data from PRU buffers(OCMC) to socket buffer(DRAM) */ if (buffer_wrapped) { /* wrapped around buffer */ int bytes = (buffer_desc_count - read_block) * ICSS_BLOCK_SIZE; @@ -1399,6 +1434,14 @@ int icssm_emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr, /* If applicable, account for the HSR tag removed */ bytes -= start_offset; + /* HSR RX optimization: HSR Tag Removal Handling + * Packet is sent with HSR Tag to Driver + */ + if (PRUETH_IS_HSR(emac->prueth)) { + if (!start_offset && !pkt_info->timestamp) + bytes -= ICSS_LRE_TAG_RCT_SIZE; + } + /* copy non-wrapped part */ memcpy(dst_addr, src_addr, bytes - adjust_for_dummy_hsr_tag); diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth.h b/drivers/net/ethernet/ti/icssm/icssm_prueth.h index d31e2044a8b4..849f655051c4 100644 --- a/drivers/net/ethernet/ti/icssm/icssm_prueth.h +++ b/drivers/net/ethernet/ti/icssm/icssm_prueth.h @@ -122,6 +122,10 @@ struct prueth_packet_info { /* indicate whether Link local packet has HSR tag or not */ bool ll_has_no_hsr_tag; bool shadow; + /* HSR RX optimization + * indicates packet has to be consumed for host. + */ + bool host_recv_flag; unsigned int port; unsigned int length; bool broadcast; diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth_common.c b/drivers/net/ethernet/ti/icssm/icssm_prueth_common.c index 65eb8453ad63..14fa7c9e04e2 100644 --- a/drivers/net/ethernet/ti/icssm/icssm_prueth_common.c +++ b/drivers/net/ethernet/ti/icssm/icssm_prueth_common.c @@ -166,11 +166,9 @@ static int prueth_common_icssm_emac_rx_packets(struct prueth_emac *emac, /* update read pointer in queue descriptor */ if (port == 0) { - writel(0, shared_ram + bd_rd_ptr); writew(update_rd_ptr, &queue_desc->rd_ptr); bd_rd_ptr = update_rd_ptr; } else { - writel(0, shared_ram + bd_rd_ptr_o); writew(update_rd_ptr, &queue_desc_o->rd_ptr); bd_rd_ptr_o = update_rd_ptr; } diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth_switch.c b/drivers/net/ethernet/ti/icssm/icssm_prueth_switch.c index 6d65e726ee89..59cbdd006a2c 100644 --- a/drivers/net/ethernet/ti/icssm/icssm_prueth_switch.c +++ b/drivers/net/ethernet/ti/icssm/icssm_prueth_switch.c @@ -227,18 +227,18 @@ const struct prueth_queue_info lre_queue_infos[][NUM_QUEUES] = { }, [PRUETH_PORT_QUEUE_MII0] = { [PRUETH_QUEUE1] = { - P1_Q1_BUFFER_OFFSET, - P1_Q1_BUFFER_OFFSET + - ((QUEUE_1_SIZE - 1) * ICSS_BLOCK_SIZE), - P1_Q1_BD_OFFSET, - P1_Q1_BD_OFFSET + ((QUEUE_1_SIZE - 1) * BD_SIZE), + P0_Q3_BUFFER_OFFSET, + P0_Q3_BUFFER_OFFSET + + ((HOST_QUEUE_3_SIZE - 1) * ICSS_BLOCK_SIZE), + P0_Q3_BD_OFFSET, + P0_Q3_BD_OFFSET + ((HOST_QUEUE_3_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE2] = { - P1_Q2_BUFFER_OFFSET, - P1_Q2_BUFFER_OFFSET + - ((QUEUE_2_SIZE - 1) * ICSS_BLOCK_SIZE), - P1_Q2_BD_OFFSET, - P1_Q2_BD_OFFSET + ((QUEUE_2_SIZE - 1) * BD_SIZE), + P0_Q4_BUFFER_OFFSET, + P0_Q4_BUFFER_OFFSET + + ((HOST_QUEUE_4_SIZE - 1) * ICSS_BLOCK_SIZE), + P0_Q4_BD_OFFSET, + P0_Q4_BD_OFFSET + ((HOST_QUEUE_4_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE3] = { P1_Q3_TXOPT_BUFFER_OFFSET, @@ -249,28 +249,30 @@ const struct prueth_queue_info lre_queue_infos[][NUM_QUEUES] = { ((QUEUE_3_TXOPT_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE4] = { - P1_Q4_TXOPT_BUFFER_OFFSET, - P1_Q4_TXOPT_BUFFER_OFFSET + + P2_Q1_TXOPT_BUFFER_OFFSET, + P2_Q1_TXOPT_BUFFER_OFFSET + ((QUEUE_4_TXOPT_SIZE - 1) * ICSS_BLOCK_SIZE), - P1_Q4_TXOPT_BD_OFFSET, - P1_Q4_TXOPT_BD_OFFSET + + P2_Q1_TXOPT_BD_OFFSET, + P2_Q1_TXOPT_BD_OFFSET + ((QUEUE_4_TXOPT_SIZE - 1) * BD_SIZE), }, }, [PRUETH_PORT_QUEUE_MII1] = { [PRUETH_QUEUE1] = { - P2_Q1_TXOPT_BUFFER_OFFSET, - P2_Q1_TXOPT_BUFFER_OFFSET + - ((QUEUE_1_SIZE - 1) * ICSS_BLOCK_SIZE), - P2_Q1_TXOPT_BD_OFFSET, - P2_Q1_TXOPT_BD_OFFSET + ((QUEUE_1_SIZE - 1) * BD_SIZE), + P0_Q1_BUFFER_OFFSET, + P0_Q1_BUFFER_OFFSET + + ((HOST_QUEUE_1_SIZE - 1) * ICSS_BLOCK_SIZE), + P0_Q1_BD_OFFSET, + P0_Q1_BD_OFFSET + + ((HOST_QUEUE_1_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE2] = { - P2_Q2_TXOPT_BUFFER_OFFSET, - P2_Q2_TXOPT_BUFFER_OFFSET + - ((QUEUE_2_SIZE - 1) * ICSS_BLOCK_SIZE), - P2_Q2_TXOPT_BD_OFFSET, - P2_Q2_TXOPT_BD_OFFSET + ((QUEUE_2_SIZE - 1) * BD_SIZE), + P0_Q2_BUFFER_OFFSET, + P0_Q2_BUFFER_OFFSET + + ((HOST_QUEUE_2_SIZE - 1) * ICSS_BLOCK_SIZE), + P0_Q2_BD_OFFSET, + P0_Q2_BD_OFFSET + + ((HOST_QUEUE_2_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE3] = { P1_Q3_TXOPT_BUFFER_OFFSET, @@ -281,11 +283,11 @@ const struct prueth_queue_info lre_queue_infos[][NUM_QUEUES] = { ((QUEUE_3_TXOPT_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE4] = { - P1_Q4_TXOPT_BUFFER_OFFSET, - P1_Q4_TXOPT_BUFFER_OFFSET + + P2_Q1_TXOPT_BUFFER_OFFSET, + P2_Q1_TXOPT_BUFFER_OFFSET + ((QUEUE_4_TXOPT_SIZE - 1) * ICSS_BLOCK_SIZE), - P1_Q4_TXOPT_BD_OFFSET, - P1_Q4_TXOPT_BD_OFFSET + + P2_Q1_TXOPT_BD_OFFSET, + P2_Q1_TXOPT_BD_OFFSET + ((QUEUE_4_TXOPT_SIZE - 1) * BD_SIZE), }, @@ -322,16 +324,16 @@ static const struct prueth_queue_info lre_rx_queue_infos[][NUM_QUEUES] = { }, [PRUETH_PORT_QUEUE_MII0] = { [PRUETH_QUEUE1] = { - P1_Q1_BUFFER_OFFSET, + P0_Q3_BUFFER_OFFSET, P1_QUEUE_DESC_OFFSET, - P1_Q1_BD_OFFSET, - P1_Q1_BD_OFFSET + ((QUEUE_1_SIZE - 1) * BD_SIZE), + P0_Q3_BD_OFFSET, + P0_Q3_BD_OFFSET + ((HOST_QUEUE_3_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE2] = { - P1_Q2_BUFFER_OFFSET, + P0_Q4_BUFFER_OFFSET, P1_QUEUE_DESC_OFFSET + 8, - P1_Q2_BD_OFFSET, - P1_Q2_BD_OFFSET + ((QUEUE_2_SIZE - 1) * BD_SIZE), + P0_Q4_BD_OFFSET, + P0_Q4_BD_OFFSET + ((HOST_QUEUE_4_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE3] = { P1_Q3_TXOPT_BUFFER_OFFSET, @@ -341,25 +343,25 @@ static const struct prueth_queue_info lre_rx_queue_infos[][NUM_QUEUES] = { ((QUEUE_3_TXOPT_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE4] = { - P1_Q4_TXOPT_BUFFER_OFFSET, + P2_Q1_TXOPT_BUFFER_OFFSET, P1_QUEUE_DESC_OFFSET + 24, - P1_Q4_TXOPT_BD_OFFSET, - P1_Q4_TXOPT_BD_OFFSET + + P2_Q1_TXOPT_BD_OFFSET, + P2_Q1_TXOPT_BD_OFFSET + ((QUEUE_4_TXOPT_SIZE - 1) * BD_SIZE), }, }, [PRUETH_PORT_QUEUE_MII1] = { [PRUETH_QUEUE1] = { - P2_Q1_TXOPT_BUFFER_OFFSET, + P0_Q1_BUFFER_OFFSET, P2_QUEUE_DESC_OFFSET, - P2_Q1_TXOPT_BD_OFFSET, - P2_Q1_TXOPT_BD_OFFSET + ((QUEUE_1_SIZE - 1) * BD_SIZE), + P0_Q1_BD_OFFSET, + P0_Q1_BD_OFFSET + ((HOST_QUEUE_1_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE2] = { - P2_Q2_TXOPT_BUFFER_OFFSET, + P0_Q2_BUFFER_OFFSET, P2_QUEUE_DESC_OFFSET + 8, - P2_Q2_TXOPT_BD_OFFSET, - P2_Q2_TXOPT_BD_OFFSET + ((QUEUE_2_SIZE - 1) * BD_SIZE), + P0_Q2_BD_OFFSET, + P0_Q2_BD_OFFSET + ((HOST_QUEUE_2_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE3] = { P1_Q3_TXOPT_BUFFER_OFFSET, @@ -369,10 +371,10 @@ static const struct prueth_queue_info lre_rx_queue_infos[][NUM_QUEUES] = { ((QUEUE_3_TXOPT_SIZE - 1) * BD_SIZE), }, [PRUETH_QUEUE4] = { - P1_Q4_TXOPT_BUFFER_OFFSET, + P2_Q1_TXOPT_BUFFER_OFFSET, P2_QUEUE_DESC_OFFSET + 24, - P1_Q4_TXOPT_BD_OFFSET, - P1_Q4_TXOPT_BD_OFFSET + + P2_Q1_TXOPT_BD_OFFSET, + P2_Q1_TXOPT_BD_OFFSET + ((QUEUE_4_TXOPT_SIZE - 1) * BD_SIZE), }, }, @@ -1192,8 +1194,8 @@ static int icssm_prueth_lre_port_config(struct prueth *prueth, /* queue size lookup table */ dram = dram_base + QUEUE_SIZE_ADDR + port_id * NUM_QUEUES * sizeof(u16); - writew(QUEUE_1_SIZE, dram); - writew(QUEUE_2_SIZE, dram + 2); + writew(HOST_QUEUE_1_SIZE, dram); + writew(HOST_QUEUE_2_SIZE, dram + 2); writew(QUEUE_3_SIZE, dram + 4); writew(QUEUE_4_SIZE, dram + 6); diff --git a/drivers/net/ethernet/ti/icssm/icssm_switch.h b/drivers/net/ethernet/ti/icssm/icssm_switch.h index b1387fd1525c..d0740d5bc746 100644 --- a/drivers/net/ethernet/ti/icssm/icssm_switch.h +++ b/drivers/net/ethernet/ti/icssm/icssm_switch.h @@ -55,6 +55,8 @@ * address found in FDB). For switch only. * 8 RED_INFO indicate whether the packet has redundancy * tag (HSR/PRP). + * 10 HostRecv indicates whether packet is consumed by host + * or not. * 13 LinkLocal indicates that Link local packet has HSR tag * or not. * 14 Shadow indicates that "index" is pointing into shadow @@ -94,6 +96,10 @@ #define PRUETH_BD_RED_PKT_MASK BIT(8) #define PRUETH_BD_RED_PKT 8 +/* Added for HSR Rx optimization */ +#define PRUETH_BD_HOST_RECV_MASK BIT(10) +#define PRUETH_BD_HOST_RECV_SHIFT 10 + #define PRUETH_LL_HAS_NO_HSRTAG_MASK BIT(13) #define PRUETH_LL_HAS_NO_HSRTAG_SHIFT 13 @@ -324,13 +330,9 @@ * Host Tx Low Priority: * Port2 Q1 and Q2 is merged and made as common queue Port1/Port2 Q4 */ -#define P1_Q3_TXOPT_BD_OFFSET (P1_Q2_BD_OFFSET + QUEUE_2_SIZE * BD_SIZE) +#define P1_Q3_TXOPT_BD_OFFSET (P0_Q4_BD_OFFSET + HOST_QUEUE_4_SIZE * BD_SIZE) #define P2_Q1_TXOPT_BD_OFFSET (P1_Q3_TXOPT_BD_OFFSET + \ QUEUE_3_TXOPT_SIZE * BD_SIZE) -#define P2_Q2_TXOPT_BD_OFFSET (P2_Q1_TXOPT_BD_OFFSET + QUEUE_1_SIZE * \ - BD_SIZE) -#define P1_Q4_TXOPT_BD_OFFSET (P2_Q2_TXOPT_BD_OFFSET + QUEUE_2_SIZE * \ - BD_SIZE) #define P0_Q1_BD_OFFSET P0_BUFFER_DESC_OFFSET #define P0_BUFFER_DESC_OFFSET SRAM_START_OFFSET @@ -369,14 +371,10 @@ * Host Tx Low Priority: * Port2 Q1 and Q2 is merged and made as common queue Port1/Port2 Q4 */ -#define P1_Q3_TXOPT_BUFFER_OFFSET (P1_Q2_BUFFER_OFFSET + QUEUE_2_SIZE * \ - ICSS_BLOCK_SIZE) +#define P1_Q3_TXOPT_BUFFER_OFFSET (P0_Q4_BUFFER_OFFSET + \ + HOST_QUEUE_4_SIZE * ICSS_BLOCK_SIZE) #define P2_Q1_TXOPT_BUFFER_OFFSET (P1_Q3_TXOPT_BUFFER_OFFSET + \ QUEUE_3_TXOPT_SIZE * ICSS_BLOCK_SIZE) -#define P2_Q2_TXOPT_BUFFER_OFFSET (P2_Q1_TXOPT_BUFFER_OFFSET + \ - QUEUE_1_SIZE * ICSS_BLOCK_SIZE) -#define P1_Q4_TXOPT_BUFFER_OFFSET (P2_Q2_TXOPT_BUFFER_OFFSET + \ - QUEUE_2_SIZE * ICSS_BLOCK_SIZE) #define P0_COL_BUFFER_OFFSET 0xEE00 #define P0_Q1_BUFFER_OFFSET 0x0000