get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2927/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2927,
    "url": "https://patches.dpdk.org/api/patches/2927/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1422951511-28143-6-git-send-email-danny.zhou@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1422951511-28143-6-git-send-email-danny.zhou@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1422951511-28143-6-git-send-email-danny.zhou@intel.com",
    "date": "2015-02-03T08:18:31",
    "name": "[dpdk-dev,v2,5/5] l3fwd-power: enable one-shot rx interrupt and polling/interrupt mode switch",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "a3843ac924913d70242d5fbcc80168ccc95b94d4",
    "submitter": {
        "id": 29,
        "url": "https://patches.dpdk.org/api/people/29/?format=api",
        "name": "Zhou, Danny",
        "email": "danny.zhou@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1422951511-28143-6-git-send-email-danny.zhou@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/2927/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/2927/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 561B79AE1;\n\tTue,  3 Feb 2015 09:19:10 +0100 (CET)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id 16F249AD7\n\tfor <dev@dpdk.org>; Tue,  3 Feb 2015 09:19:07 +0100 (CET)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby fmsmga103.fm.intel.com with ESMTP; 03 Feb 2015 00:12:32 -0800",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby FMSMGA003.fm.intel.com with ESMTP; 03 Feb 2015 00:04:45 -0800",
            "from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com\n\t[10.239.29.89])\n\tby shvmail01.sh.intel.com with ESMTP id t138Iot3000886;\n\tTue, 3 Feb 2015 16:18:50 +0800",
            "from shecgisg004.sh.intel.com (localhost [127.0.0.1])\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP\n\tid t138Ilk6028213; Tue, 3 Feb 2015 16:18:49 +0800",
            "(from dyzhou@localhost)\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t138Ilxg028209; \n\tTue, 3 Feb 2015 16:18:47 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"4.97,862,1389772800\"; d=\"scan'208\";a=\"449082370\"",
        "From": "Zhou Danny <danny.zhou@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Tue,  3 Feb 2015 16:18:31 +0800",
        "Message-Id": "<1422951511-28143-6-git-send-email-danny.zhou@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1422951511-28143-1-git-send-email-danny.zhou@intel.com>",
        "References": "<1422951511-28143-1-git-send-email-danny.zhou@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v2 5/5] l3fwd-power: enable one-shot rx interrupt\n\tand polling/interrupt mode switch",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "v2 change\n- Remove unused function which is for debug purpose\n\nDemonstrate how to handle per rx queue interrupt in a NAPI-like\nimplementation in usersapce. PDK polling thread mainly works in \npolling mode and switch to interrupt mode only if there is no \nany packet received in recent polls.\nUsersapce interrupt notification generally takes a lot more cycles than\nkernel, so one-shot interrupt is used here to guarantee minimum overhead\nand DPDK polling thread returns to polling mode immediately once it\nreceives an interrupt notificaiton for incoming packet.\n\nSigned-off-by: Danny Zhou <danny.zhou@intel.com>\nTested-by: Yong Liu <yong.liu@intel.com>\n---\n examples/l3fwd-power/main.c | 141 +++++++++++++++++++++++++++++++-------------\n 1 file changed, 100 insertions(+), 41 deletions(-)",
    "diff": "diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c\nindex f6b55b9..15f0a5a 100644\n--- a/examples/l3fwd-power/main.c\n+++ b/examples/l3fwd-power/main.c\n@@ -75,12 +75,13 @@\n #include <rte_string_fns.h>\n #include <rte_timer.h>\n #include <rte_power.h>\n+#include <rte_eal.h>\n \n #define RTE_LOGTYPE_L3FWD_POWER RTE_LOGTYPE_USER1\n \n #define MAX_PKT_BURST 32\n \n-#define MIN_ZERO_POLL_COUNT 5\n+#define MIN_ZERO_POLL_COUNT 10\n \n /* around 100ms at 2 Ghz */\n #define TIMER_RESOLUTION_CYCLES           200000000ULL\n@@ -188,6 +189,9 @@ struct lcore_rx_queue {\n #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS\n #define MAX_RX_QUEUE_PER_PORT 128\n \n+#define MAX_RX_QUEUE_INTERRUPT_PER_PORT 16\n+\n+\n #define MAX_LCORE_PARAMS 1024\n struct lcore_params {\n \tuint8_t port_id;\n@@ -214,7 +218,7 @@ static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) /\n \n static struct rte_eth_conf port_conf = {\n \t.rxmode = {\n-\t\t.mq_mode\t= ETH_MQ_RX_RSS,\n+\t\t.mq_mode = ETH_MQ_RX_RSS,\n \t\t.max_rx_pkt_len = ETHER_MAX_LEN,\n \t\t.split_hdr_size = 0,\n \t\t.header_split   = 0, /**< Header Split disabled */\n@@ -226,11 +230,14 @@ static struct rte_eth_conf port_conf = {\n \t.rx_adv_conf = {\n \t\t.rss_conf = {\n \t\t\t.rss_key = NULL,\n-\t\t\t.rss_hf = ETH_RSS_IP,\n+\t\t\t.rss_hf = ETH_RSS_UDP,\n \t\t},\n \t},\n \t.txmode = {\n-\t\t.mq_mode = ETH_DCB_NONE,\n+\t\t.mq_mode = ETH_MQ_TX_NONE,\n+\t},\n+\t.intr_conf = {\n+\t\t.rxq = 1, /**< rxq interrupt feature enabled */\n \t},\n };\n \n@@ -402,19 +409,22 @@ power_timer_cb(__attribute__((unused)) struct rte_timer *tim,\n \t/* accumulate total execution time in us when callback is invoked */\n \tsleep_time_ratio = (float)(stats[lcore_id].sleep_time) /\n \t\t\t\t\t(float)SCALING_PERIOD;\n-\n \t/**\n \t * check whether need to scale down frequency a step if it sleep a lot.\n \t */\n-\tif (sleep_time_ratio >= SCALING_DOWN_TIME_RATIO_THRESHOLD)\n-\t\trte_power_freq_down(lcore_id);\n+\tif (sleep_time_ratio >= SCALING_DOWN_TIME_RATIO_THRESHOLD) {\n+\t\tif (rte_power_freq_down)\n+\t\t\trte_power_freq_down(lcore_id);\n+\t}\n \telse if ( (unsigned)(stats[lcore_id].nb_rx_processed /\n-\t\tstats[lcore_id].nb_iteration_looped) < MAX_PKT_BURST)\n+\t\tstats[lcore_id].nb_iteration_looped) < MAX_PKT_BURST) {\n \t\t/**\n \t\t * scale down a step if average packet per iteration less\n \t\t * than expectation.\n \t\t */\n-\t\trte_power_freq_down(lcore_id);\n+\t\tif (rte_power_freq_down)\n+\t\t\trte_power_freq_down(lcore_id);\n+\t}\n \n \t/**\n \t * initialize another timer according to current frequency to ensure\n@@ -707,22 +717,20 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid,\n \n }\n \n-#define SLEEP_GEAR1_THRESHOLD            100\n-#define SLEEP_GEAR2_THRESHOLD            1000\n+#define MINIMUM_SLEEP_TIME         1\n+#define SUSPEND_THRESHOLD          300\n \n static inline uint32_t\n power_idle_heuristic(uint32_t zero_rx_packet_count)\n {\n-\t/* If zero count is less than 100, use it as the sleep time in us */\n-\tif (zero_rx_packet_count < SLEEP_GEAR1_THRESHOLD)\n-\t\treturn zero_rx_packet_count;\n-\t/* If zero count is less than 1000, sleep time should be 100 us */\n-\telse if ((zero_rx_packet_count >= SLEEP_GEAR1_THRESHOLD) &&\n-\t\t\t(zero_rx_packet_count < SLEEP_GEAR2_THRESHOLD))\n-\t\treturn SLEEP_GEAR1_THRESHOLD;\n-\t/* If zero count is greater than 1000, sleep time should be 1000 us */\n-\telse if (zero_rx_packet_count >= SLEEP_GEAR2_THRESHOLD)\n-\t\treturn SLEEP_GEAR2_THRESHOLD;\n+\t/* If zero count is less than 100,  sleep 1us */\n+\tif (zero_rx_packet_count < SUSPEND_THRESHOLD)\n+\t\treturn MINIMUM_SLEEP_TIME;\n+\t/* If zero count is less than 1000, sleep 100 us which is the minimum latency\n+\t    switching from C3/C6 to C0\n+\t*/\n+\telse\n+\t\treturn SUSPEND_THRESHOLD;\n \n \treturn 0;\n }\n@@ -762,6 +770,35 @@ power_freq_scaleup_heuristic(unsigned lcore_id,\n \treturn FREQ_CURRENT;\n }\n \n+/**\n+ * force polling thread sleep until one-shot rx interrupt triggers\n+ * @param port_id\n+ *  Port id.\n+ * @param queue_id\n+ *  Rx queue id.\n+ * @return\n+ *  0 on success\n+ */\n+static int\n+sleep_until_rx_interrupt(uint8_t port_id, uint8_t queue_id)\n+{\n+\t/* Enable one-shot rx interrupt */\n+\trte_eth_dev_rx_queue_intr_enable(port_id, queue_id);\n+\n+\tRTE_LOG(INFO, L3FWD_POWER,\n+\t\t\"lcore %u sleeps until interrupt on port%d,rxq%d triggers\\n\",\n+\t\trte_lcore_id(), port_id, queue_id);\n+\trte_eal_wait_rx_intr(port_id, queue_id);\n+\tRTE_LOG(INFO, L3FWD_POWER,\n+\t\t\"lcore %u is waked up from rx interrupt on port%d,rxq%d\\n\",\n+\t\trte_lcore_id(), port_id, queue_id);\n+\n+\t/* Disable one-shot rx interrupt */\n+\trte_eth_dev_rx_queue_intr_disable(port_id, queue_id);\n+\n+\treturn 0;\n+}\n+\n /* main processing loop */\n static int\n main_loop(__attribute__((unused)) void *dummy)\n@@ -775,7 +812,6 @@ main_loop(__attribute__((unused)) void *dummy)\n \tstruct lcore_conf *qconf;\n \tstruct lcore_rx_queue *rx_queue;\n \tenum freq_scale_hint_t lcore_scaleup_hint;\n-\n \tuint32_t lcore_rx_idle_count = 0;\n \tuint32_t lcore_idle_hint = 0;\n \n@@ -835,6 +871,8 @@ main_loop(__attribute__((unused)) void *dummy)\n \t\t\tprev_tsc_power = cur_tsc_power;\n \t\t}\n \n+\n+start_rx:\n \t\t/*\n \t\t * Read packet from RX queues\n \t\t */\n@@ -848,6 +886,7 @@ main_loop(__attribute__((unused)) void *dummy)\n \n \t\t\tnb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,\n \t\t\t\t\t\t\t\tMAX_PKT_BURST);\n+\n \t\t\tstats[lcore_id].nb_rx_processed += nb_rx;\n \t\t\tif (unlikely(nb_rx == 0)) {\n \t\t\t\t/**\n@@ -910,10 +949,13 @@ main_loop(__attribute__((unused)) void *dummy)\n \t\t\t\t\t\trx_queue->freq_up_hint;\n \t\t\t}\n \n-\t\t\tif (lcore_scaleup_hint == FREQ_HIGHEST)\n-\t\t\t\trte_power_freq_max(lcore_id);\n-\t\t\telse if (lcore_scaleup_hint == FREQ_HIGHER)\n-\t\t\t\trte_power_freq_up(lcore_id);\n+\t\t\tif (lcore_scaleup_hint == FREQ_HIGHEST) {\n+\t\t\t\tif (rte_power_freq_max)\n+\t\t\t\t\trte_power_freq_max(lcore_id);\n+\t\t\t} else if (lcore_scaleup_hint == FREQ_HIGHER) {\n+\t\t\t\tif (rte_power_freq_up)\n+\t\t\t\t\trte_power_freq_up(lcore_id);\n+\t\t\t}\n \t\t} else {\n \t\t\t/**\n \t\t\t * All Rx queues empty in recent consecutive polls,\n@@ -928,16 +970,21 @@ main_loop(__attribute__((unused)) void *dummy)\n \t\t\t\t\tlcore_idle_hint = rx_queue->idle_hint;\n \t\t\t}\n \n-\t\t\tif ( lcore_idle_hint < SLEEP_GEAR1_THRESHOLD)\n+\t\t\tif (lcore_idle_hint < SUSPEND_THRESHOLD)\n \t\t\t\t/**\n-\t\t\t\t * execute \"pause\" instruction to avoid context\n-\t\t\t\t * switch for short sleep.\n- \t\t\t\t */\n+\t\t\t\t* execute \"pause\" instruction to avoid context\n+\t\t\t\t* switch which generally take hundres of microsecond\n+\t\t\t\t* for short sleep.\n+\t\t\t\t*/\n \t\t\t\trte_delay_us(lcore_idle_hint);\n-\t\t\telse\n-\t\t\t\t/* long sleep force runing thread to suspend */\n-\t\t\t\tusleep(lcore_idle_hint);\n-\n+\t\t\telse {\n+\t\t\t\t/* suspend untill rx interrupt trigges */\n+\t\t\t\tsleep_until_rx_interrupt(\n+\t\t\t\t\tqconf->rx_queue_list[0].port_id,\n+\t\t\t\t\tqconf->rx_queue_list[0].queue_id);\n+\t\t\t\t/* start receiving packets immediately */\n+\t\t\t\tgoto start_rx;\n+\t\t\t}\n \t\t\tstats[lcore_id].sleep_time += lcore_idle_hint;\n \t\t}\n \t}\n@@ -1270,7 +1317,7 @@ setup_hash(int socketid)\n \tchar s[64];\n \n \t/* create ipv4 hash */\n-\tsnprintf(s, sizeof(s), \"ipv4_l3fwd_hash_%d\", socketid);\n+\trte_snprintf(s, sizeof(s), \"ipv4_l3fwd_hash_%d\", socketid);\n \tipv4_l3fwd_hash_params.name = s;\n \tipv4_l3fwd_hash_params.socket_id = socketid;\n \tipv4_l3fwd_lookup_struct[socketid] =\n@@ -1280,7 +1327,7 @@ setup_hash(int socketid)\n \t\t\t\t\"socket %d\\n\", socketid);\n \n \t/* create ipv6 hash */\n-\tsnprintf(s, sizeof(s), \"ipv6_l3fwd_hash_%d\", socketid);\n+\trte_snprintf(s, sizeof(s), \"ipv6_l3fwd_hash_%d\", socketid);\n \tipv6_l3fwd_hash_params.name = s;\n \tipv6_l3fwd_hash_params.socket_id = socketid;\n \tipv6_l3fwd_lookup_struct[socketid] =\n@@ -1476,6 +1523,7 @@ main(int argc, char **argv)\n \tunsigned lcore_id;\n \tuint64_t hz;\n \tuint32_t n_tx_queue, nb_lcores;\n+\tuint32_t dev_rxq_num, dev_txq_num;\n \tuint8_t portid, nb_rx_queue, queue, socketid;\n \n \t/* catch SIGINT and restore cpufreq governor to ondemand */\n@@ -1525,10 +1573,18 @@ main(int argc, char **argv)\n \t\tprintf(\"Initializing port %d ... \", portid );\n \t\tfflush(stdout);\n \n+\t\trte_eth_dev_info_get(portid, &dev_info);\n+\t\tdev_rxq_num = dev_info.max_rx_queues;\n+\t\tdev_txq_num = dev_info.max_tx_queues;\n+\n \t\tnb_rx_queue = get_port_n_rx_queues(portid);\n+\t\tif (nb_rx_queue > dev_rxq_num)\n+\t\t\trte_exit(EXIT_FAILURE, \"Cannot configure not existed rxq: \"\n+\t\t\t\t\t\"port=%d\\n\", portid);\n+\n \t\tn_tx_queue = nb_lcores;\n-\t\tif (n_tx_queue > MAX_TX_QUEUE_PER_PORT)\n-\t\t\tn_tx_queue = MAX_TX_QUEUE_PER_PORT;\n+\t\tif (n_tx_queue > dev_txq_num)\n+\t\t\tn_tx_queue = dev_txq_num;\n \t\tprintf(\"Creating queues: nb_rxq=%d nb_txq=%u... \",\n \t\t\tnb_rx_queue, (unsigned)n_tx_queue );\n \t\tret = rte_eth_dev_configure(portid, nb_rx_queue,\n@@ -1552,6 +1608,9 @@ main(int argc, char **argv)\n \t\t\tif (rte_lcore_is_enabled(lcore_id) == 0)\n \t\t\t\tcontinue;\n \n+\t\t\tif (queueid >= dev_txq_num)\n+\t\t\t\tcontinue;\n+\n \t\t\tif (numa_on)\n \t\t\t\tsocketid = \\\n \t\t\t\t(uint8_t)rte_lcore_to_socket_id(lcore_id);\n@@ -1586,8 +1645,9 @@ main(int argc, char **argv)\n \t\t/* init power management library */\n \t\tret = rte_power_init(lcore_id);\n \t\tif (ret)\n-\t\t\trte_exit(EXIT_FAILURE, \"Power management library \"\n-\t\t\t\t\"initialization failed on core%u\\n\", lcore_id);\n+\t\t\trte_log(RTE_LOG_ERR, RTE_LOGTYPE_POWER,\n+\t\t\t\t\"Power management library initialization \"\n+\t\t\t\t\"failed on core%u\", lcore_id);\n \n \t\t/* init timer structures for each enabled lcore */\n \t\trte_timer_init(&power_timers[lcore_id]);\n@@ -1635,7 +1695,6 @@ main(int argc, char **argv)\n \t\tif (ret < 0)\n \t\t\trte_exit(EXIT_FAILURE, \"rte_eth_dev_start: err=%d, \"\n \t\t\t\t\t\t\"port=%d\\n\", ret, portid);\n-\n \t\t/*\n \t\t * If enabled, put device in promiscuous mode.\n \t\t * This allows IO forwarding mode to forward packets\n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "5/5"
    ]
}