Skip to content

Commit 8a86339

Browse files
Manish Chopradavem330
authored andcommitted
qede: Add build_skb() support.
This patch makes use of build_skb() throughout in driver's receieve data path [HW gro flow and non HW gro flow]. With this, driver can build skb directly from the page segments which are already mapped to the hardware instead of allocating new SKB via netdev_alloc_skb() and memcpy the data which is quite costly. This really improves performance (keeping same or slight gain in rx throughput) in terms of CPU utilization which is significantly reduced [almost half] in non HW gro flow where for every incoming MTU sized packet driver had to allocate skb, memcpy headers etc. Additionally in that flow, it also gets rid of bunch of additional overheads [eth_get_headlen() etc.] to split headers and data in the skb. Tested with: system: 2 sockets, 4 cores per socket, hyperthreading, 2x4x2=16 cores iperf [server]: iperf -s iperf [client]: iperf -c <server_ip> -t 500 -i 10 -P 32 HW GRO off – w/o build_skb(), throughput: 36.8 Gbits/sec Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle Average: all 0.59 0.00 32.93 0.00 0.00 43.07 0.00 0.00 23.42 HW GRO off - with build_skb(), throughput: 36.9 Gbits/sec Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle Average: all 0.70 0.00 31.70 0.00 0.00 25.68 0.00 0.00 41.92 HW GRO on - w/o build_skb(), throughput: 36.9 Gbits/sec Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle Average: all 0.86 0.00 24.14 0.00 0.00 6.59 0.00 0.00 68.41 HW GRO on - with build_skb(), throughput: 37.5 Gbits/sec Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle Average: all 0.87 0.00 23.75 0.00 0.00 6.19 0.00 0.00 69.19 Signed-off-by: Ariel Elior <[email protected]> Signed-off-by: Manish Chopra <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 56a9a9e commit 8a86339

File tree

4 files changed

+137
-174
lines changed

4 files changed

+137
-174
lines changed

drivers/net/ethernet/qlogic/qede/qede.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,15 +290,12 @@ struct qede_agg_info {
290290
* aggregation.
291291
*/
292292
struct sw_rx_data buffer;
293-
dma_addr_t buffer_mapping;
294-
295293
struct sk_buff *skb;
296294

297295
/* We need some structs from the start cookie until termination */
298296
u16 vlan_tag;
299-
u16 start_cqe_bd_len;
300-
u8 start_cqe_placement_offset;
301297

298+
bool tpa_start_fail;
302299
u8 state;
303300
u8 frag_id;
304301

drivers/net/ethernet/qlogic/qede/qede_ethtool.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1508,7 +1508,8 @@ static int qede_selftest_receive_traffic(struct qede_dev *edev)
15081508
len = le16_to_cpu(fp_cqe->len_on_first_bd);
15091509
data_ptr = (u8 *)(page_address(sw_rx_data->data) +
15101510
fp_cqe->placement_offset +
1511-
sw_rx_data->page_offset);
1511+
sw_rx_data->page_offset +
1512+
rxq->rx_headroom);
15121513
if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) &&
15131514
ether_addr_equal(data_ptr + ETH_ALEN,
15141515
edev->ndev->dev_addr)) {

drivers/net/ethernet/qlogic/qede/qede_fp.c

Lines changed: 119 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,8 @@ static int qede_fill_frag_skb(struct qede_dev *edev,
660660

661661
/* Add one frag and update the appropriate fields in the skb */
662662
skb_fill_page_desc(skb, tpa_info->frag_id++,
663-
current_bd->data, current_bd->page_offset,
663+
current_bd->data,
664+
current_bd->page_offset + rxq->rx_headroom,
664665
len_on_bd);
665666

666667
if (unlikely(qede_realloc_rx_buffer(rxq, current_bd))) {
@@ -671,8 +672,7 @@ static int qede_fill_frag_skb(struct qede_dev *edev,
671672
goto out;
672673
}
673674

674-
qed_chain_consume(&rxq->rx_bd_ring);
675-
rxq->sw_rx_cons++;
675+
qede_rx_bd_ring_consume(rxq);
676676

677677
skb->data_len += len_on_bd;
678678
skb->truesize += rxq->rx_buf_seg_size;
@@ -721,64 +721,129 @@ static u8 qede_check_tunn_csum(u16 flag)
721721
return QEDE_CSUM_UNNECESSARY | tcsum;
722722
}
723723

724+
static inline struct sk_buff *
725+
qede_build_skb(struct qede_rx_queue *rxq,
726+
struct sw_rx_data *bd, u16 len, u16 pad)
727+
{
728+
struct sk_buff *skb;
729+
void *buf;
730+
731+
buf = page_address(bd->data) + bd->page_offset;
732+
skb = build_skb(buf, rxq->rx_buf_seg_size);
733+
734+
skb_reserve(skb, pad);
735+
skb_put(skb, len);
736+
737+
return skb;
738+
}
739+
740+
static struct sk_buff *
741+
qede_tpa_rx_build_skb(struct qede_dev *edev,
742+
struct qede_rx_queue *rxq,
743+
struct sw_rx_data *bd, u16 len, u16 pad,
744+
bool alloc_skb)
745+
{
746+
struct sk_buff *skb;
747+
748+
skb = qede_build_skb(rxq, bd, len, pad);
749+
bd->page_offset += rxq->rx_buf_seg_size;
750+
751+
if (bd->page_offset == PAGE_SIZE) {
752+
if (unlikely(qede_alloc_rx_buffer(rxq, true))) {
753+
DP_NOTICE(edev,
754+
"Failed to allocate RX buffer for tpa start\n");
755+
bd->page_offset -= rxq->rx_buf_seg_size;
756+
page_ref_inc(bd->data);
757+
dev_kfree_skb_any(skb);
758+
return NULL;
759+
}
760+
} else {
761+
page_ref_inc(bd->data);
762+
qede_reuse_page(rxq, bd);
763+
}
764+
765+
/* We've consumed the first BD and prepared an SKB */
766+
qede_rx_bd_ring_consume(rxq);
767+
768+
return skb;
769+
}
770+
771+
static struct sk_buff *
772+
qede_rx_build_skb(struct qede_dev *edev,
773+
struct qede_rx_queue *rxq,
774+
struct sw_rx_data *bd, u16 len, u16 pad)
775+
{
776+
struct sk_buff *skb = NULL;
777+
778+
/* For smaller frames still need to allocate skb, memcpy
779+
* data and benefit in reusing the page segment instead of
780+
* un-mapping it.
781+
*/
782+
if ((len + pad <= edev->rx_copybreak)) {
783+
unsigned int offset = bd->page_offset + pad;
784+
785+
skb = netdev_alloc_skb(edev->ndev, QEDE_RX_HDR_SIZE);
786+
if (unlikely(!skb))
787+
return NULL;
788+
789+
skb_reserve(skb, pad);
790+
memcpy(skb_put(skb, len),
791+
page_address(bd->data) + offset, len);
792+
qede_reuse_page(rxq, bd);
793+
goto out;
794+
}
795+
796+
skb = qede_build_skb(rxq, bd, len, pad);
797+
798+
if (unlikely(qede_realloc_rx_buffer(rxq, bd))) {
799+
/* Incr page ref count to reuse on allocation failure so
800+
* that it doesn't get freed while freeing SKB [as its
801+
* already mapped there].
802+
*/
803+
page_ref_inc(bd->data);
804+
dev_kfree_skb_any(skb);
805+
return NULL;
806+
}
807+
out:
808+
/* We've consumed the first BD and prepared an SKB */
809+
qede_rx_bd_ring_consume(rxq);
810+
811+
return skb;
812+
}
813+
724814
static void qede_tpa_start(struct qede_dev *edev,
725815
struct qede_rx_queue *rxq,
726816
struct eth_fast_path_rx_tpa_start_cqe *cqe)
727817
{
728818
struct qede_agg_info *tpa_info = &rxq->tpa_info[cqe->tpa_agg_index];
729-
struct eth_rx_bd *rx_bd_cons = qed_chain_consume(&rxq->rx_bd_ring);
730-
struct eth_rx_bd *rx_bd_prod = qed_chain_produce(&rxq->rx_bd_ring);
731-
struct sw_rx_data *replace_buf = &tpa_info->buffer;
732-
dma_addr_t mapping = tpa_info->buffer_mapping;
733819
struct sw_rx_data *sw_rx_data_cons;
734-
struct sw_rx_data *sw_rx_data_prod;
820+
u16 pad;
735821

736822
sw_rx_data_cons = &rxq->sw_rx_ring[rxq->sw_rx_cons & NUM_RX_BDS_MAX];
737-
sw_rx_data_prod = &rxq->sw_rx_ring[rxq->sw_rx_prod & NUM_RX_BDS_MAX];
823+
pad = cqe->placement_offset + rxq->rx_headroom;
738824

739-
/* Use pre-allocated replacement buffer - we can't release the agg.
740-
* start until its over and we don't want to risk allocation failing
741-
* here, so re-allocate when aggregation will be over.
742-
*/
743-
sw_rx_data_prod->mapping = replace_buf->mapping;
744-
745-
sw_rx_data_prod->data = replace_buf->data;
746-
rx_bd_prod->addr.hi = cpu_to_le32(upper_32_bits(mapping));
747-
rx_bd_prod->addr.lo = cpu_to_le32(lower_32_bits(mapping));
748-
sw_rx_data_prod->page_offset = replace_buf->page_offset;
749-
750-
rxq->sw_rx_prod++;
825+
tpa_info->skb = qede_tpa_rx_build_skb(edev, rxq, sw_rx_data_cons,
826+
le16_to_cpu(cqe->len_on_first_bd),
827+
pad, false);
828+
tpa_info->buffer.page_offset = sw_rx_data_cons->page_offset;
829+
tpa_info->buffer.mapping = sw_rx_data_cons->mapping;
751830

752-
/* move partial skb from cons to pool (don't unmap yet)
753-
* save mapping, incase we drop the packet later on.
754-
*/
755-
tpa_info->buffer = *sw_rx_data_cons;
756-
mapping = HILO_U64(le32_to_cpu(rx_bd_cons->addr.hi),
757-
le32_to_cpu(rx_bd_cons->addr.lo));
758-
759-
tpa_info->buffer_mapping = mapping;
760-
rxq->sw_rx_cons++;
761-
762-
/* set tpa state to start only if we are able to allocate skb
763-
* for this aggregation, otherwise mark as error and aggregation will
764-
* be dropped
765-
*/
766-
tpa_info->skb = netdev_alloc_skb(edev->ndev,
767-
le16_to_cpu(cqe->len_on_first_bd));
768831
if (unlikely(!tpa_info->skb)) {
769832
DP_NOTICE(edev, "Failed to allocate SKB for gro\n");
833+
834+
/* Consume from ring but do not produce since
835+
* this might be used by FW still, it will be re-used
836+
* at TPA end.
837+
*/
838+
tpa_info->tpa_start_fail = true;
839+
qede_rx_bd_ring_consume(rxq);
770840
tpa_info->state = QEDE_AGG_STATE_ERROR;
771841
goto cons_buf;
772842
}
773843

774-
/* Start filling in the aggregation info */
775-
skb_put(tpa_info->skb, le16_to_cpu(cqe->len_on_first_bd));
776844
tpa_info->frag_id = 0;
777845
tpa_info->state = QEDE_AGG_STATE_START;
778846

779-
/* Store some information from first CQE */
780-
tpa_info->start_cqe_placement_offset = cqe->placement_offset;
781-
tpa_info->start_cqe_bd_len = le16_to_cpu(cqe->len_on_first_bd);
782847
if ((le16_to_cpu(cqe->pars_flags.flags) >>
783848
PARSING_AND_ERR_FLAGS_TAG8021QEXIST_SHIFT) &
784849
PARSING_AND_ERR_FLAGS_TAG8021QEXIST_MASK)
@@ -899,6 +964,10 @@ static int qede_tpa_end(struct qede_dev *edev,
899964
tpa_info = &rxq->tpa_info[cqe->tpa_agg_index];
900965
skb = tpa_info->skb;
901966

967+
if (tpa_info->buffer.page_offset == PAGE_SIZE)
968+
dma_unmap_page(rxq->dev, tpa_info->buffer.mapping,
969+
PAGE_SIZE, rxq->data_direction);
970+
902971
for (i = 0; cqe->len_list[i]; i++)
903972
qede_fill_frag_skb(edev, rxq, cqe->tpa_agg_index,
904973
le16_to_cpu(cqe->len_list[i]));
@@ -919,11 +988,6 @@ static int qede_tpa_end(struct qede_dev *edev,
919988
"Strange - total packet len [cqe] is %4x but SKB has len %04x\n",
920989
le16_to_cpu(cqe->total_packet_len), skb->len);
921990

922-
memcpy(skb->data,
923-
page_address(tpa_info->buffer.data) +
924-
tpa_info->start_cqe_placement_offset +
925-
tpa_info->buffer.page_offset, tpa_info->start_cqe_bd_len);
926-
927991
/* Finalize the SKB */
928992
skb->protocol = eth_type_trans(skb, edev->ndev);
929993
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -940,6 +1004,12 @@ static int qede_tpa_end(struct qede_dev *edev,
9401004
return 1;
9411005
err:
9421006
tpa_info->state = QEDE_AGG_STATE_NONE;
1007+
1008+
if (tpa_info->tpa_start_fail) {
1009+
qede_reuse_page(rxq, &tpa_info->buffer);
1010+
tpa_info->tpa_start_fail = false;
1011+
}
1012+
9431013
dev_kfree_skb_any(tpa_info->skb);
9441014
tpa_info->skb = NULL;
9451015
return 0;
@@ -1058,65 +1128,6 @@ static bool qede_rx_xdp(struct qede_dev *edev,
10581128
return false;
10591129
}
10601130

1061-
static struct sk_buff *qede_rx_allocate_skb(struct qede_dev *edev,
1062-
struct qede_rx_queue *rxq,
1063-
struct sw_rx_data *bd, u16 len,
1064-
u16 pad)
1065-
{
1066-
unsigned int offset = bd->page_offset + pad;
1067-
struct skb_frag_struct *frag;
1068-
struct page *page = bd->data;
1069-
unsigned int pull_len;
1070-
struct sk_buff *skb;
1071-
unsigned char *va;
1072-
1073-
/* Allocate a new SKB with a sufficient large header len */
1074-
skb = netdev_alloc_skb(edev->ndev, QEDE_RX_HDR_SIZE);
1075-
if (unlikely(!skb))
1076-
return NULL;
1077-
1078-
/* Copy data into SKB - if it's small, we can simply copy it and
1079-
* re-use the already allcoated & mapped memory.
1080-
*/
1081-
if (len + pad <= edev->rx_copybreak) {
1082-
skb_put_data(skb, page_address(page) + offset, len);
1083-
qede_reuse_page(rxq, bd);
1084-
goto out;
1085-
}
1086-
1087-
frag = &skb_shinfo(skb)->frags[0];
1088-
1089-
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
1090-
page, offset, len, rxq->rx_buf_seg_size);
1091-
1092-
va = skb_frag_address(frag);
1093-
pull_len = eth_get_headlen(va, QEDE_RX_HDR_SIZE);
1094-
1095-
/* Align the pull_len to optimize memcpy */
1096-
memcpy(skb->data, va, ALIGN(pull_len, sizeof(long)));
1097-
1098-
/* Correct the skb & frag sizes offset after the pull */
1099-
skb_frag_size_sub(frag, pull_len);
1100-
frag->page_offset += pull_len;
1101-
skb->data_len -= pull_len;
1102-
skb->tail += pull_len;
1103-
1104-
if (unlikely(qede_realloc_rx_buffer(rxq, bd))) {
1105-
/* Incr page ref count to reuse on allocation failure so
1106-
* that it doesn't get freed while freeing SKB [as its
1107-
* already mapped there].
1108-
*/
1109-
page_ref_inc(page);
1110-
dev_kfree_skb_any(skb);
1111-
return NULL;
1112-
}
1113-
1114-
out:
1115-
/* We've consumed the first BD and prepared an SKB */
1116-
qede_rx_bd_ring_consume(rxq);
1117-
return skb;
1118-
}
1119-
11201131
static int qede_rx_build_jumbo(struct qede_dev *edev,
11211132
struct qede_rx_queue *rxq,
11221133
struct sk_buff *skb,
@@ -1157,7 +1168,7 @@ static int qede_rx_build_jumbo(struct qede_dev *edev,
11571168
PAGE_SIZE, DMA_FROM_DEVICE);
11581169

11591170
skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags++,
1160-
bd->data, 0, cur_size);
1171+
bd->data, rxq->rx_headroom, cur_size);
11611172

11621173
skb->truesize += PAGE_SIZE;
11631174
skb->data_len += cur_size;
@@ -1256,7 +1267,7 @@ static int qede_rx_process_cqe(struct qede_dev *edev,
12561267
/* Basic validation passed; Need to prepare an SKB. This would also
12571268
* guarantee to finally consume the first BD upon success.
12581269
*/
1259-
skb = qede_rx_allocate_skb(edev, rxq, bd, len, pad);
1270+
skb = qede_rx_build_skb(edev, rxq, bd, len, pad);
12601271
if (!skb) {
12611272
rxq->rx_alloc_errors++;
12621273
qede_recycle_rx_bd_ring(rxq, fp_cqe->bd_num);

0 commit comments

Comments
 (0)