Port FEATURE_CONF_DESC_LENGTH from the grx500 variant of the driver. This also reduces the default length of some descriptors, resulting in significantly lower latencies when the line is saturated. --- a/dcdp/inc/tc_common.h +++ b/dcdp/inc/tc_common.h @@ -27,7 +27,11 @@ #define UMT_DEF_PERIOD 400 /* microseconds */ #define MAX_MTU (DMA_PACKET_SZ - ETH_HLEN - HD_RSRV_SZ) +#ifdef FEATURE_CONF_DESC_LENGTH +#define QOSQ_NUM 8 +#else #define QOSQ_NUM 2 +#endif #define FW_STOP_TIMEOUT 20 /* millisecond */ #define QOS_DISPATCH_OWN 0 #define ACA_TXIN_POLL_INTVAL 10 /* millisecond */ --- a/dcdp/inc/tc_main.h +++ b/dcdp/inc/tc_main.h @@ -30,6 +30,7 @@ #define TCPRIV_ALIGN 32 #define DMA_PACKET_SZ 2048 +#define FEATURE_CONF_DESC_LENGTH 1 #define FEATURE_POWER_DOWN 1 enum { @@ -157,6 +158,25 @@ struct tc_param { unsigned int txout_dnum; unsigned int rxin_dnum; unsigned int rxout_dnum; + +#ifdef FEATURE_CONF_DESC_LENGTH + /* __US_FAST_PATH_DES_LIST_NUM:64 + * __ACA_TX_IN_PD_LIST_NUM + * __ACA_TX_OUT_PD_LIST_NUM + * */ + u32 conf_us_fp_desq_len; + /* + * Number of queue per QoS queue: QOS_DES_NUM / QOSQ_NUM + * */ + u32 conf_us_qos_queue_len; + /* __US_OUTQ0_DES_LIST_NUM: 32 + * __US_OUTQ1_DES_LIST_NUM: 32 + * OUTQ_DESC_PER_Q + * */ + u32 conf_us_outq_len; + /**/ + u32 conf_us_local_q0_desq_len; +#endif }; struct cdma { --- a/dcdp/ptm_tc.c +++ b/dcdp/ptm_tc.c @@ -75,7 +75,11 @@ static const u32 tx_kvec[] = { 0x30B1B233, 0xB43536B7, 0xB8393ABB, 0x3CBDBE3F, 0xC04142C3, 0x44C5C647, 0x48C9CA4B, 0xCC4D4ECF }; +#ifndef FEATURE_CONF_DESC_LENGTH static const u32 def_outq_map[OUTQ_PNUM] = {0x1, 0xFE}; +#else +static const u32 def_outq_map[OUTQ_PNUM] = {0x0, 0xFF}; +#endif static const char ptm_drv_name[] = "PTM SL"; static const char ptm_bond_name[][IFNAMSIZ] = {"PTM US BOND", "PTM DS BOND"}; @@ -1005,6 +1009,10 @@ static void us_fp_desq_cfg_ctxt_init(str int i; u32 desc_addr; rx_descriptor_t desc; +#ifdef FEATURE_CONF_DESC_LENGTH + struct tc_priv *tc_priv; + tc_priv = priv->tc_priv; +#endif memset(&desq_cfg, 0, sizeof(desq_cfg)); /* Initialize US Fast-Path Descriptor Queue Config/Context */ @@ -1012,7 +1020,11 @@ static void us_fp_desq_cfg_ctxt_init(str desq_cfg.fast_path = 1; desq_cfg.mbox_int_en = 0; desq_cfg.des_sync_needed = 0; +#ifndef FEATURE_CONF_DESC_LENGTH desq_cfg.des_num = __US_FAST_PATH_DES_LIST_NUM; +#else + desq_cfg.des_num = tc_priv->param.conf_us_fp_desq_len; +#endif desq_cfg.des_base_addr = __US_FAST_PATH_DES_LIST_BASE; tc_mem_write(priv, fpi_addr(__US_FP_INQ_DES_CFG_CTXT), @@ -1036,12 +1048,20 @@ static void us_qos_desq_cfg_ctxt_init(st int offset, i; rx_descriptor_t desc; u32 phy_addr; +#ifdef FEATURE_CONF_DESC_LENGTH + struct tc_priv *tc_priv; + tc_priv = priv->tc_priv; +#endif /* Setup QoSQ_CFG_CTXT */ memset(&qosq_cfg_ctxt, 0, sizeof(qosq_cfg_ctxt)); qosq_cfg_ctxt.threshold = 8; +#ifdef FEATURE_CONF_DESC_LENGTH + qosq_cfg_ctxt.des_num = tc_priv->param.conf_us_qos_queue_len; +#else qosq_cfg_ctxt.des_num = QOS_DES_NUM / QOSQ_NUM; +#endif offset = 0; for (i = 0; i < QOSQ_NUM; i++) { @@ -1080,6 +1100,10 @@ static void us_outq_desq_cfg_ctxt_init(s u32 phy_addr; int i; u32 offset; +#ifdef FEATURE_CONF_DESC_LENGTH + struct tc_priv *tc_priv; + tc_priv = priv->tc_priv; +#endif /* Setup OUTQ_QoS_CFG_CTXT */ /* NOTE: By default, Shaping & WFQ both are DISABLED!! */ @@ -1108,7 +1132,11 @@ static void us_outq_desq_cfg_ctxt_init(s desq_cfg.des_in_own_val = US_OUTQ_DES_OWN; desq_cfg.mbox_int_en = 0; desq_cfg.des_sync_needed = 0; - desq_cfg.des_num = 32; +#ifndef FEATURE_CONF_DESC_LENGTH + desq_cfg.des_num = OUTQ_DESC_PER_Q; +#else + desq_cfg.des_num = tc_priv->param.conf_us_outq_len; +#endif /** * Only BC0 is used in VRX518 */ @@ -1174,7 +1202,11 @@ static void us_qos_cfg_init(struct ptm_e /* Set QoS NO DROP */ sb_w32(1, __QOSQ_NO_DROP); /* Enable Preemption function/Disable QoS by default */ +#ifdef FEATURE_CONF_DESC_LENGTH + sb_w32(0, _CHK_PREEMP_MAP); +#else sb_w32(1, _CHK_PREEMP_MAP); +#endif /* By default, all qid mappint to non-preemption queue */ sb_w32(0x0, _QID2PREEMP_MAP); @@ -1376,6 +1408,11 @@ static void ptm_local_desq_cfg_ctxt_init u32 dcnt, addr, pdbram_base; unsigned int us_des_alloc[] = { __US_TC_LOCAL_Q0_DES_LIST_NUM, __US_TC_LOCAL_Q1_DES_LIST_NUM}; +#ifdef FEATURE_CONF_DESC_LENGTH + struct tc_priv *tc_priv; + tc_priv = priv->tc_priv; + us_des_alloc[0] = tc_priv->param.conf_us_local_q0_desq_len; +#endif /* Setup the Local DESQ Configuration/Context for UpStream Queues */ memset(&desq_cfg, 0, sizeof(desq_cfg)); @@ -2321,6 +2358,10 @@ static void ptm_aca_init(struct ptm_ep_p u32 phybase = priv->ep->phy_membase; u32 start; u32 type; +#ifdef FEATURE_CONF_DESC_LENGTH + struct tc_priv *tc_priv; + tc_priv = priv->tc_priv; +#endif priv->tc_priv->tc_ops.soc_cfg_get(&priv->tc_priv->cfg, ptm_id(priv)); memset(¶m, 0, sizeof(param)); @@ -2334,7 +2375,11 @@ static void ptm_aca_init(struct ptm_ep_p #endif txin->hd_size_in_dw = cfg->txin.soc_desc_dwsz; txin->pd_desc_base = SB_XBAR_ADDR(__ACA_TX_IN_PD_LIST_BASE); +#ifndef FEATURE_CONF_DESC_LENGTH txin->pd_desc_num = __ACA_TX_IN_PD_LIST_NUM; +#else + txin->pd_desc_num = tc_priv->param.conf_us_fp_desq_len; +#endif txin->pd_size_in_dw = DESC_DWSZ; txin->soc_desc_base = cfg->txin.soc_phydbase; txin->soc_desc_num = cfg->txin.soc_dnum; --- a/dcdp/tc_main.c +++ b/dcdp/tc_main.c @@ -182,6 +182,12 @@ static inline void init_local_param(stru priv->param.txout_dnum = txout_num; priv->param.rxin_dnum = rxin_num; priv->param.rxout_dnum = rxout_num; +#ifdef FEATURE_CONF_DESC_LENGTH + priv->param.conf_us_fp_desq_len = 32; + priv->param.conf_us_qos_queue_len = 32; + priv->param.conf_us_outq_len = 32; + priv->param.conf_us_local_q0_desq_len = 16; +#endif priv->tc_mode = TC_NONE_MODE; priv->tc_stat = NO_TC; --- a/dcdp/tc_proc.c +++ b/dcdp/tc_proc.c @@ -1114,6 +1114,9 @@ static int proc_read_ver(struct seq_file (date >> 16) & 0xff, (date & 0xffff)); +#ifdef FEATURE_CONF_DESC_LENGTH + seq_puts(seq, " + Support QoS and Configurable descriptor length\n"); +#endif #ifdef FEATURE_POWER_DOWN seq_puts(seq, " + Support Power Down enhancement feature\n"); #endif @@ -1166,6 +1169,113 @@ static const struct proc_ops tc_soc_proc .proc_release = single_release, }; +#ifdef FEATURE_CONF_DESC_LENGTH +static ssize_t proc_write_desc_conf(struct file *file, const char __user *buf, + size_t count, loff_t *data) +{ + struct tc_priv *priv; + char str[32]; + int len, rlen, temp; + int num, temp_num; + char *param_list[20]; + len = count < sizeof(str) ? count : sizeof(str) - 1; + rlen = len - copy_from_user(str, buf, len); + str[rlen] = 0; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + priv = (struct tc_priv *)PDE_DATA(file_inode(file)); + if (priv == NULL) + return count; + + num = vrx_split_buffer(str, param_list, ARRAY_SIZE(param_list)); + if (num < 1 || num > 4) + goto proc_dbg_desc_conf; + + temp_num = num; + if (num-- != 0) { + temp = vrx_atoi(param_list[0]); + if (temp < 1 || temp > 128) { + pr_info("Fastpath valid range: 1 -> 128\n"); + goto proc_dbg_desc_conf; + } + } + if (num-- != 0) { + temp = vrx_atoi(param_list[1]); + if (temp < 1 || temp > 63) { + pr_info("QoS valid range: 1 -> 63\n"); + goto proc_dbg_desc_conf; + } + } + if (num-- != 0) { + temp = vrx_atoi(param_list[2]); + if (temp < 1 || temp > 128) { + pr_info("OutQ valid range: 1 -> 128\n"); + goto proc_dbg_desc_conf; + } + } + if (num-- != 0) { + temp = vrx_atoi(param_list[3]); + if (temp < 4 || temp > 16) { + pr_info("Local Q0 valid range: 4 -> 16\n"); + goto proc_dbg_desc_conf; + } + } + num = temp_num; + if (num-- != 0) { + priv->param.conf_us_fp_desq_len = vrx_atoi(param_list[0]); + } + if (num-- != 0) { + priv->param.conf_us_qos_queue_len = vrx_atoi(param_list[1]); + } + if (num-- != 0) { + priv->param.conf_us_outq_len = vrx_atoi(param_list[2]); + } + if (num-- != 0) { + priv->param.conf_us_local_q0_desq_len = vrx_atoi(param_list[3]); + } + + return count; + +proc_dbg_desc_conf: + pr_info("echo [FP] [QoS] [OutQ] [LocalQ0]> desc_conf\n"); + return count; +} + +static int proc_read_desc_conf(struct seq_file *seq, void *v) +{ + struct tc_priv *priv; + priv = (struct tc_priv *)seq->private; + if (priv == NULL) + return -1; + seq_puts(seq, "Upstream descriptor length information:\n"); + seq_printf(seq, " - Fastpath: %d\n", + priv->param.conf_us_fp_desq_len); + seq_printf(seq, " - QoS: %d\n", + priv->param.conf_us_qos_queue_len); + seq_printf(seq, " - OutQ: %d\n", + priv->param.conf_us_outq_len); + seq_printf(seq, " - Local Q0: %d\n", + priv->param.conf_us_local_q0_desq_len); + seq_puts(seq, "\n"); + return 0; +} + +static int proc_read_desc_conf_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_read_desc_conf, PDE_DATA(inode)); +} +#endif + +static const struct proc_ops tc_desc_conf_proc_fops = { + .proc_open = proc_read_desc_conf_seq_open, + .proc_read = seq_read, + .proc_write = proc_write_desc_conf, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; + static struct tc_proc_list tc_procs[] = { {TC_PROC_DIR, 0, NULL, 1}, {"cfg", 0644, &tc_cfg_proc_fops, 0}, @@ -1174,6 +1284,9 @@ static struct tc_proc_list tc_procs[] = {"showtime", 0200, &tc_show_time_proc_fops, 0}, {"ver", 0644, &tc_ver_proc_fops, 0}, {"soc", 0644, &tc_soc_proc_fops, 0}, +#ifdef FEATURE_CONF_DESC_LENGTH + {"desc_conf", 0644, &tc_desc_conf_proc_fops, 0}, +#endif }; int tc_proc_init(struct tc_priv *priv) @@ -1333,7 +1446,6 @@ proc_ptm_cfg_help: return count; } - static const struct proc_ops ptm_cfg_proc_fops = { .proc_open = proc_read_cfg_seq_open, .proc_read = seq_read,