qcacmn: Enable TSO Stats for Lithium based products

Add support to account for TSO jumbo packets on the
Tx path and print the statistics using dumpStats 3.

Change-Id: I6cc446df5c84e3ac436d922935fcd559e0704ec5
CRs-Fixed: 2356244
Цей коміт міститься в:
Venkata Sharath Chandra Manchala
2018-10-05 13:04:18 -07:00
зафіксовано nshrivas
джерело 2b07141773
коміт 8a4812f7fc
11 змінених файлів з 544 додано та 38 видалено

Переглянути файл

@@ -1165,7 +1165,8 @@ struct cdp_peer_ops {
* @stats:
*/
struct cdp_mob_stats_ops {
void (*clear_stats)(uint16_t bitmap);
QDF_STATUS
(*clear_stats)(struct cdp_soc *soc, uint8_t bitmap);
int (*stats)(uint8_t vdev_id, char *buffer, unsigned buf_len);
};

Переглянути файл

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2017,2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -25,22 +25,23 @@
#define _CDP_TXRX_STATS_H_
#include <cdp_txrx_ops.h>
static inline void
cdp_clear_stats(ol_txrx_soc_handle soc, uint16_t bitmap)
static inline QDF_STATUS
cdp_clear_stats(ol_txrx_soc_handle soc, uint8_t bitmap)
{
if (!soc || !soc->ops) {
QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
"%s: Invalid Instance", __func__);
QDF_BUG(0);
return;
return QDF_STATUS_E_INVAL;
}
if (!soc->ops->mob_stats_ops ||
!soc->ops->mob_stats_ops->clear_stats)
return;
return QDF_STATUS_E_INVAL;
soc->ops->mob_stats_ops->clear_stats(bitmap);
return soc->ops->mob_stats_ops->clear_stats((struct cdp_soc *)soc,
bitmap);
}
static inline int

Переглянути файл

@@ -23,6 +23,11 @@
*/
#ifndef _CDP_TXRX_STATS_STRUCT_H_
#define _CDP_TXRX_STATS_STRUCT_H_
#ifdef FEATURE_TSO_STATS
#include <qdf_types.h>
#endif /* FEATURE_TSO_STATS */
#define TXRX_STATS_LEVEL_OFF 0
#define TXRX_STATS_LEVEL_BASIC 1
#define TXRX_STATS_LEVEL_FULL 2
@@ -171,6 +176,15 @@ enum cdp_ru_index {
RU_996_INDEX,
};
#ifdef FEATURE_TSO_STATS
/* Number of TSO Packet Statistics captured */
#define CDP_MAX_TSO_PACKETS 5
/* Information for Number of Segments for a TSO Packet captured */
#define CDP_MAX_TSO_SEGMENTS 2
/* Information for Number of Fragments for a TSO Segment captured */
#define CDP_MAX_TSO_FRAGMENTS 6
#endif /* FEATURE_TSO_STATS */
/* Different Packet Types */
enum cdp_packet_type {
DOT11_A = 0,
@@ -444,6 +458,68 @@ struct cdp_tx_pkt_info {
uint32_t mpdu_tried;
};
#ifdef FEATURE_TSO_STATS
/**
* struct cdp_tso_seg_histogram - Segment histogram for TCP Packets
* @segs_1: packets with single segments
* @segs_2_5: packets with 2-5 segments
* @segs_6_10: packets with 6-10 segments
* @segs_11_15: packets with 11-15 segments
* @segs_16_20: packets with 16-20 segments
* @segs_20_plus: packets with 20 plus segments
*/
struct cdp_tso_seg_histogram {
uint64_t segs_1;
uint64_t segs_2_5;
uint64_t segs_6_10;
uint64_t segs_11_15;
uint64_t segs_16_20;
uint64_t segs_20_plus;
};
/**
* struct cdp_tso_packet_info - Stats for TSO segments within a TSO packet
* @tso_seg: TSO Segment information
* @num_seg: Number of segments
* @tso_packet_len: Size of the tso packet
* @tso_seg_idx: segment number
*/
struct cdp_tso_packet_info {
struct qdf_tso_seg_t tso_seg[CDP_MAX_TSO_SEGMENTS];
uint8_t num_seg;
size_t tso_packet_len;
uint32_t tso_seg_idx;
};
/**
* struct cdp_tso_info - stats for tso packets
* @tso_packet_info: TSO packet information
*/
struct cdp_tso_info {
struct cdp_tso_packet_info tso_packet_info[CDP_MAX_TSO_PACKETS];
};
#endif /* FEATURE_TSO_STATS */
/**
* struct cdp_tso_stats - TSO stats information
* @num_tso_pkts: Total number of TSO Packets
* @tso_comp: Total tso packet completions
* @dropped_host: TSO packets dropped by host
* @dropped_target: TSO packets_dropped by target
* @tso_info: Per TSO packet counters
* @seg_histogram: TSO histogram stats
*/
struct cdp_tso_stats {
struct cdp_pkt_info num_tso_pkts;
uint32_t tso_comp;
struct cdp_pkt_info dropped_host;
uint32_t dropped_target;
#ifdef FEATURE_TSO_STATS
struct cdp_tso_info tso_info;
struct cdp_tso_seg_histogram seg_histogram;
#endif /* FEATURE_TSO_STATS */
};
/* struct cdp_tx_stats - tx stats
* @cdp_pkt_info comp_pkt: Pkt Info for which completions were received
* @cdp_pkt_info ucast: Unicast Packet Count
@@ -771,15 +847,6 @@ struct cdp_tx_ingress_stats {
uint32_t invalid_raw_pkt_datatype;
} raw;
/* TSO packets info */
struct {
uint32_t num_seg;
struct cdp_pkt_info tso_pkt;
struct cdp_pkt_info non_tso_pkts;
struct cdp_pkt_info dropped_host;
uint32_t dropped_target;
} tso;
/* Scatter Gather packet info */
struct {
struct cdp_pkt_info sg_pkt;
@@ -821,17 +888,20 @@ struct cdp_tx_ingress_stats {
uint32_t cce_classified;
uint32_t cce_classified_raw;
struct cdp_pkt_info sniffer_rcvd;
struct cdp_tso_stats tso_stats;
};
/* struct cdp_vdev_stats - vdev stats structure
* @tx_i: ingress tx stats
* @tx: cdp tx stats
* @rx: cdp rx stats
* @tso_stats: tso stats
*/
struct cdp_vdev_stats {
struct cdp_tx_ingress_stats tx_i;
struct cdp_tx_stats tx;
struct cdp_rx_stats rx;
struct cdp_tso_stats tso_stats;
};
/* struct cdp_peer_stats - peer stats structure
@@ -1381,6 +1451,8 @@ struct cdp_pdev_stats {
uint32_t data_rx_ppdu;
uint32_t data_users[OFDMA_NUM_USERS];
} ul_ofdma;
struct cdp_tso_stats tso_stats;
};
#ifdef QCA_ENH_V3_STATS_SUPPORT

Переглянути файл

@@ -315,7 +315,6 @@ while (0)
} \
} while (0)
#else
#define DP_HIST_INIT()
#define DP_HIST_PACKET_COUNT_INC(_pdev_id)
@@ -323,7 +322,134 @@ while (0)
#define DP_RX_HISTOGRAM_UPDATE(_pdev, _p_cntrs)
#define DP_RX_HIST_STATS_PER_PDEV()
#define DP_TX_HIST_STATS_PER_PDEV()
#endif
#endif /* DISABLE_DP_STATS */
#ifdef FEATURE_TSO_STATS
/**
* dp_init_tso_stats() - Clear tso stats
* @pdev: pdev handle
*
* Return: None
*/
static inline
void dp_init_tso_stats(struct dp_pdev *pdev)
{
if (pdev) {
qdf_mem_zero(&((pdev)->stats.tso_stats),
sizeof((pdev)->stats.tso_stats));
qdf_atomic_init(&pdev->tso_idx);
}
}
/**
* dp_stats_tso_segment_histogram_update() - TSO Segment Histogram
* @pdev: pdev handle
* @_p_cntrs: number of tso segments for a tso packet
*
* Return: None
*/
void dp_stats_tso_segment_histogram_update(struct dp_pdev *pdev,
uint8_t _p_cntrs);
/**
* dp_tso_segment_update() - Collect tso segment information
* @pdev: pdev handle
* @stats_idx: tso packet number
* @idx: tso segment number
* @seg: tso segment
*
* Return: None
*/
void dp_tso_segment_update(struct dp_pdev *pdev,
uint32_t stats_idx,
uint8_t idx,
struct qdf_tso_seg_t seg);
/**
* dp_tso_packet_update() - TSO Packet information
* @pdev: pdev handle
* @stats_idx: tso packet number
* @msdu: nbuf handle
* @num_segs: tso segments
*
* Return: None
*/
void dp_tso_packet_update(struct dp_pdev *pdev, uint32_t stats_idx,
qdf_nbuf_t msdu, uint16_t num_segs);
/**
* dp_tso_segment_stats_update() - TSO Segment stats
* @pdev: pdev handle
* @stats_seg: tso segment list
* @stats_idx: tso packet number
*
* Return: None
*/
void dp_tso_segment_stats_update(struct dp_pdev *pdev,
struct qdf_tso_seg_elem_t *stats_seg,
uint32_t stats_idx);
/**
* dp_print_tso_stats() - dump tso statistics
* @soc:soc handle
* @level: verbosity level
*
* Return: None
*/
void dp_print_tso_stats(struct dp_soc *soc,
enum qdf_stats_verbosity_level level);
/**
* dp_txrx_clear_tso_stats() - clear tso stats
* @soc: soc handle
*
* Return: None
*/
void dp_txrx_clear_tso_stats(struct dp_soc *soc);
#else
static inline
void dp_init_tso_stats(struct dp_pdev *pdev)
{
}
static inline
void dp_stats_tso_segment_histogram_update(struct dp_pdev *pdev,
uint8_t _p_cntrs)
{
}
static inline
void dp_tso_segment_update(struct dp_pdev *pdev,
uint32_t stats_idx,
uint32_t idx,
struct qdf_tso_seg_t seg)
{
}
static inline
void dp_tso_packet_update(struct dp_pdev *pdev, uint32_t stats_idx,
qdf_nbuf_t msdu, uint16_t num_segs)
{
}
static inline
void dp_tso_segment_stats_update(struct dp_pdev *pdev,
struct qdf_tso_seg_elem_t *stats_seg,
uint32_t stats_idx)
{
}
static inline
void dp_print_tso_stats(struct dp_soc *soc,
enum qdf_stats_verbosity_level level)
{
}
static inline
void dp_txrx_clear_tso_stats(struct dp_soc *soc)
{
}
#endif /* FEATURE_TSO_STATS */
#define DP_HTT_T2H_HP_PIPE 5
static inline void dp_update_pdev_stats(struct dp_pdev *tgtobj,
@@ -478,9 +604,6 @@ static inline void dp_update_pdev_ingress_stats(struct dp_pdev *tgtobj,
DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.inspect_pkts);
DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.raw.raw_pkt);
DP_STATS_AGGR(tgtobj, srcobj, tx_i.raw.dma_map_error);
DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.tso.tso_pkt);
DP_STATS_AGGR(tgtobj, srcobj, tx_i.tso.dropped_host.num);
DP_STATS_AGGR(tgtobj, srcobj, tx_i.tso.dropped_target);
DP_STATS_AGGR(tgtobj, srcobj, tx_i.sg.dropped_host.num);
DP_STATS_AGGR(tgtobj, srcobj, tx_i.sg.dropped_target);
DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.sg.sg_pkt);
@@ -511,8 +634,6 @@ static inline void dp_update_pdev_ingress_stats(struct dp_pdev *tgtobj,
tgtobj->stats.tx_i.dropped.desc_na.num +
tgtobj->stats.tx_i.dropped.res_full;
tgtobj->stats.tx_i.tso.num_seg =
srcobj->stats.tx_i.tso.num_seg;
}
static inline void dp_update_vdev_stats(struct cdp_vdev_stats *tgtobj,

Переглянути файл

@@ -3598,6 +3598,8 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
pdev->num_tx_allowed = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx);
dp_init_tso_stats(pdev);
if (dp_htt_ppdu_stats_attach(pdev) != QDF_STATUS_SUCCESS)
goto fail1;
@@ -8328,7 +8330,7 @@ static QDF_STATUS dp_txrx_dump_stats(void *psoc, uint16_t value,
break;
case CDP_TXRX_TSO_STATS:
/* TODO: NOT IMPLEMENTED */
dp_print_tso_stats(soc, level);
break;
case CDP_DUMP_TX_FLOW_POOL_INFO:
@@ -8353,6 +8355,38 @@ static QDF_STATUS dp_txrx_dump_stats(void *psoc, uint16_t value,
}
/**
* dp_txrx_clear_dump_stats() - clear dumpStats
* @soc- soc handle
* @value - stats option
*
* Return: 0 - Success, non-zero - failure
*/
static
QDF_STATUS dp_txrx_clear_dump_stats(struct cdp_soc *psoc, uint8_t value)
{
struct dp_soc *soc =
(struct dp_soc *)psoc;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!soc) {
dp_err("%s: soc is NULL", __func__);
return QDF_STATUS_E_INVAL;
}
switch (value) {
case CDP_TXRX_TSO_STATS:
dp_txrx_clear_tso_stats(soc);
break;
default:
status = QDF_STATUS_E_INVAL;
break;
}
return status;
}
#ifdef QCA_LL_TX_FLOW_CONTROL_V2
/**
* dp_update_flow_control_parameters() - API to store datapath
@@ -9531,7 +9565,7 @@ static struct cdp_ocb_ops dp_ops_ocb = {
};
static struct cdp_mob_stats_ops dp_ops_mob_stats = {
/* WIFI 3.0 DP NOT IMPLEMENTED YET */
.clear_stats = dp_txrx_clear_dump_stats,
};
/*

Переглянути файл

@@ -4624,6 +4624,62 @@ dp_print_ring_stat_from_hal(struct dp_soc *soc, struct dp_srng *srng,
}
}
#ifdef FEATURE_TSO_STATS
/**
* dp_print_tso_seg_stats - tso segment stats
* @pdev: pdev handle
* @id: tso packet id
*
* Return: None
*/
static void dp_print_tso_seg_stats(struct dp_pdev *pdev, uint32_t id)
{
uint8_t num_seg;
uint32_t segid;
/* TSO LEVEL 2 - SEGMENT INFO */
num_seg = pdev->stats.tso_stats.tso_info.tso_packet_info[id].num_seg;
for (segid = 0; segid < CDP_MAX_TSO_SEGMENTS && segid < num_seg; segid++) {
DP_PRINT_STATS(
"Segment id:[%u] fragments: %u | Segment Length %u | TCP Seq no.: %u | ip_id: %u",
segid,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].num_frags,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].total_len,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.tcp_seq_num,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.ip_id);
DP_PRINT_STATS(
"fin: %u syn: %u rst: %u psh: %u ack: %u urg: %u ece: %u cwr: %u ns: %u",
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.fin,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.syn,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.rst,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.psh,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.ack,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.urg,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.ece,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.cwr,
pdev->stats.tso_stats.tso_info.tso_packet_info[id]
.tso_seg[segid].tso_flags.ns);
}
}
#else
static inline
void dp_print_tso_seg_stats(struct dp_pdev *pdev, uint32_t id)
{
}
#endif /* FEATURE_TSO_STATS */
/**
* dp_print_mon_ring_stats_from_hal() - Print stat for monitor rings based
* on target
@@ -5369,15 +5425,6 @@ dp_print_pdev_tx_stats(struct dp_pdev *pdev)
pdev->stats.tx_i.sg.dropped_host.num);
DP_PRINT_STATS(" Dropped By Target = %d",
pdev->stats.tx_i.sg.dropped_target);
DP_PRINT_STATS("TSO:");
DP_PRINT_STATS(" Number of Segments = %d",
pdev->stats.tx_i.tso.num_seg);
DP_PRINT_STATS(" Packets = %d",
pdev->stats.tx_i.tso.tso_pkt.num);
DP_PRINT_STATS(" Bytes = %llu",
pdev->stats.tx_i.tso.tso_pkt.bytes);
DP_PRINT_STATS(" Dropped By Host = %d",
pdev->stats.tx_i.tso.dropped_host.num);
DP_PRINT_STATS("Mcast Enhancement:");
DP_PRINT_STATS(" Packets = %d",
pdev->stats.tx_i.mcast_en.mcast_pkt.num);
@@ -5712,3 +5759,161 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
DP_PRINT_STATS("REO Error(0-14):%s", reo_error);
}
#ifdef FEATURE_TSO_STATS
void dp_print_tso_stats(struct dp_soc *soc,
enum qdf_stats_verbosity_level level)
{
uint8_t loop_pdev;
uint32_t id;
struct dp_pdev *pdev;
for (loop_pdev = 0; loop_pdev < soc->pdev_count; loop_pdev++) {
pdev = soc->pdev_list[loop_pdev];
DP_PRINT_STATS("TSO Statistics\n");
DP_PRINT_STATS(
"From stack: %d | Successful completions: %d | TSO Packets: %d | TSO Completions: %d",
pdev->stats.tx_i.rcvd.num,
pdev->stats.tx.tx_success.num,
pdev->stats.tso_stats.num_tso_pkts.num,
pdev->stats.tso_stats.tso_comp);
for (id = 0; id < CDP_MAX_TSO_PACKETS; id++) {
/* TSO LEVEL 1 - PACKET INFO */
DP_PRINT_STATS(
"Packet_Id:[%u]: Packet Length %lu | No. of segments: %u",
id,
pdev->stats.tso_stats.tso_info
.tso_packet_info[id].tso_packet_len,
pdev->stats.tso_stats.tso_info
.tso_packet_info[id].num_seg);
/* TSO LEVEL 2 */
if (level == QDF_STATS_VERBOSITY_LEVEL_HIGH)
dp_print_tso_seg_stats(pdev, id);
}
DP_PRINT_STATS(
"TSO Histogram: Single: %llu | 2-5 segs: %llu | 6-10: %llu segs | 11-15 segs: %llu | 16-20 segs: %llu | 20+ segs: %llu",
pdev->stats.tso_stats.seg_histogram.segs_1,
pdev->stats.tso_stats.seg_histogram.segs_2_5,
pdev->stats.tso_stats.seg_histogram.segs_6_10,
pdev->stats.tso_stats.seg_histogram.segs_11_15,
pdev->stats.tso_stats.seg_histogram.segs_16_20,
pdev->stats.tso_stats.seg_histogram.segs_20_plus);
}
}
void dp_stats_tso_segment_histogram_update(struct dp_pdev *pdev,
uint8_t _p_cntrs)
{
if (_p_cntrs == 1) {
DP_STATS_INC(pdev,
tso_stats.seg_histogram.segs_1, 1);
} else if (_p_cntrs >= 2 && _p_cntrs <= 5) {
DP_STATS_INC(pdev,
tso_stats.seg_histogram.segs_2_5, 1);
} else if (_p_cntrs > 5 && _p_cntrs <= 10) {
DP_STATS_INC(pdev,
tso_stats.seg_histogram.segs_6_10, 1);
} else if (_p_cntrs > 10 && _p_cntrs <= 15) {
DP_STATS_INC(pdev,
tso_stats.seg_histogram.segs_11_15, 1);
} else if (_p_cntrs > 15 && _p_cntrs <= 20) {
DP_STATS_INC(pdev,
tso_stats.seg_histogram.segs_16_20, 1);
} else if (_p_cntrs > 20) {
DP_STATS_INC(pdev,
tso_stats.seg_histogram.segs_20_plus, 1);
}
}
void dp_tso_segment_update(struct dp_pdev *pdev,
uint32_t stats_idx,
uint8_t idx,
struct qdf_tso_seg_t seg)
{
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].num_frags,
seg.num_frags);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].total_len,
seg.total_len);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.tso_enable,
seg.tso_flags.tso_enable);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.fin,
seg.tso_flags.fin);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.syn,
seg.tso_flags.syn);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.rst,
seg.tso_flags.rst);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.psh,
seg.tso_flags.psh);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.ack,
seg.tso_flags.ack);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.urg,
seg.tso_flags.urg);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.ece,
seg.tso_flags.ece);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.cwr,
seg.tso_flags.cwr);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.ns,
seg.tso_flags.ns);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.tcp_seq_num,
seg.tso_flags.tcp_seq_num);
DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_seg[idx].tso_flags.ip_id,
seg.tso_flags.ip_id);
}
void dp_tso_packet_update(struct dp_pdev *pdev, uint32_t stats_idx,
qdf_nbuf_t msdu, uint16_t num_segs)
{
DP_STATS_UPD(pdev,
tso_stats.tso_info.tso_packet_info[stats_idx]
.num_seg,
num_segs);
DP_STATS_UPD(pdev,
tso_stats.tso_info.tso_packet_info[stats_idx]
.tso_packet_len,
qdf_nbuf_get_tcp_payload_len(msdu));
}
void dp_tso_segment_stats_update(struct dp_pdev *pdev,
struct qdf_tso_seg_elem_t *stats_seg,
uint32_t stats_idx)
{
uint8_t tso_seg_idx = 0;
while (stats_seg && (tso_seg_idx < CDP_MAX_TSO_SEGMENTS)) {
dp_tso_segment_update(pdev, stats_idx,
tso_seg_idx,
stats_seg->seg);
++tso_seg_idx;
stats_seg = stats_seg->next;
}
}
void dp_txrx_clear_tso_stats(struct dp_soc *soc)
{
uint8_t loop_pdev;
struct dp_pdev *pdev;
for (loop_pdev = 0; loop_pdev < soc->pdev_count; loop_pdev++) {
pdev = soc->pdev_list[loop_pdev];
dp_init_tso_stats(pdev);
}
}
#endif /* FEATURE_TSO_STATS */

Переглянути файл

@@ -215,6 +215,7 @@ static void dp_tx_tso_desc_release(struct dp_soc *soc,
dp_tso_num_seg_free(soc, tx_desc->pool_id,
tx_desc->tso_num_desc);
tx_desc->tso_num_desc = NULL;
DP_STATS_INC(tx_desc->pdev, tso_stats.tso_comp, 1);
}
/* Add the tso segment into the free list*/
@@ -497,6 +498,28 @@ static void dp_tx_unmap_tso_seg_list(
}
}
#ifdef FEATURE_TSO_STATS
/**
* dp_tso_get_stats_idx: Retrieve the tso packet id
* @pdev - pdev handle
*
* Return: id
*/
static uint32_t dp_tso_get_stats_idx(struct dp_pdev *pdev)
{
uint32_t stats_idx;
stats_idx = (((uint32_t)qdf_atomic_inc_return(&pdev->tso_idx))
% CDP_MAX_TSO_PACKETS);
return stats_idx;
}
#else
static int dp_tso_get_stats_idx(struct dp_pdev *pdev)
{
return 0;
}
#endif /* FEATURE_TSO_STATS */
/**
* dp_tx_free_remaining_tso_desc() - do dma unmap for tso segments if any,
* free the tso segments descriptor and
@@ -542,9 +565,9 @@ static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev,
struct qdf_tso_seg_elem_t *tso_seg;
int num_seg = qdf_nbuf_get_tso_num_seg(msdu);
struct dp_soc *soc = vdev->pdev->soc;
struct dp_pdev *pdev = vdev->pdev;
struct qdf_tso_info_t *tso_info;
struct qdf_tso_num_seg_elem_t *tso_num_seg;
tso_info = &msdu_info->u.tso_info;
tso_info->curr_seg = NULL;
tso_info->tso_seg_list = NULL;
@@ -605,6 +628,12 @@ static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev,
tso_info->curr_seg = tso_info->tso_seg_list;
tso_info->msdu_stats_idx = dp_tso_get_stats_idx(pdev);
dp_tso_packet_update(pdev, tso_info->msdu_stats_idx,
msdu, msdu_info->num_seg);
dp_tso_segment_stats_update(pdev, tso_info->tso_seg_list,
tso_info->msdu_stats_idx);
dp_stats_tso_segment_histogram_update(pdev, msdu_info->num_seg);
return QDF_STATUS_SUCCESS;
}
#else
@@ -2244,11 +2273,11 @@ qdf_nbuf_t dp_tx_send(struct cdp_vdev *vap_dev, qdf_nbuf_t nbuf)
*/
if (qdf_nbuf_is_tso(nbuf)) {
dp_verbose_debug("TSO frame %pK", vdev);
DP_STATS_INC_PKT(vdev, tx_i.tso.tso_pkt, 1,
DP_STATS_INC_PKT(vdev->pdev, tso_stats.num_tso_pkts, 1,
qdf_nbuf_len(nbuf));
if (dp_tx_prepare_tso(vdev, nbuf, &msdu_info)) {
DP_STATS_INC_PKT(vdev, tx_i.tso.dropped_host, 1,
DP_STATS_INC_PKT(vdev->pdev, tso_stats.dropped_host, 1,
qdf_nbuf_len(nbuf));
return nbuf;
}

Переглянути файл

@@ -1700,6 +1700,11 @@ struct dp_pdev {
*/
struct dp_rx_fst *rx_fst;
#endif /* WLAN_SUPPORT_RX_FLOW_TAG */
#ifdef FEATURE_TSO_STATS
/* TSO Id to index into TSO packet information */
qdf_atomic_t tso_idx;
#endif /* FEATURE_TSO_STATS */
};
struct dp_peer;

Переглянути файл

@@ -3148,6 +3148,17 @@ static inline void qdf_nbuf_unmap_tso_segment(qdf_device_t osdev,
return __qdf_nbuf_unmap_tso_segment(osdev, tso_seg, is_last_seg);
}
/**
* qdf_nbuf_get_tcp_payload_len() - function to return the tso payload len
* @nbuf: network buffer
*
* Return: size of the tso packet
*/
static inline size_t qdf_nbuf_get_tcp_payload_len(qdf_nbuf_t nbuf)
{
return __qdf_nbuf_get_tcp_payload_len(nbuf);
}
/**
* qdf_nbuf_get_tso_num_seg() - function to calculate the number
* of TCP segments within the TSO jumbo packet

Переглянути файл

@@ -1453,9 +1453,23 @@ void __qdf_nbuf_unmap_tso_segment(qdf_device_t osdev,
bool is_last_seg);
#ifdef FEATURE_TSO
/**
* __qdf_nbuf_get_tcp_payload_len() - function to return the tcp
* payload len
* @skb: buffer
*
* Return: size
*/
size_t __qdf_nbuf_get_tcp_payload_len(struct sk_buff *skb);
uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb);
#else
static inline
size_t __qdf_nbuf_get_tcp_payload_len(struct sk_buff *skb)
{
return 0;
}
static inline uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb)
{
return 0;

Переглянути файл

@@ -3138,6 +3138,19 @@ last_seg_free_first_frag:
}
qdf_export_symbol(__qdf_nbuf_unmap_tso_segment);
size_t __qdf_nbuf_get_tcp_payload_len(struct sk_buff *skb)
{
size_t packet_len;
packet_len = skb->len -
((skb_transport_header(skb) - skb_mac_header(skb)) +
tcp_hdrlen(skb));
return packet_len;
}
qdf_export_symbol(__qdf_nbuf_get_tcp_payload_len);
/**
* __qdf_nbuf_get_tso_num_seg() - function to divide a TSO nbuf
* into segments