get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 79663,
    "url": "http://patches.dpdk.org/api/patches/79663/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20201005120910.189343-45-jiawenwu@trustnetic.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20201005120910.189343-45-jiawenwu@trustnetic.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201005120910.189343-45-jiawenwu@trustnetic.com",
    "date": "2020-10-05T12:08:58",
    "name": "[v2,44/56] net/txgbe: add flow control support",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "e9085a427eaa85509939bf2f7fa2d254c5555233",
    "submitter": {
        "id": 1932,
        "url": "http://patches.dpdk.org/api/people/1932/?format=api",
        "name": "Jiawen Wu",
        "email": "jiawenwu@trustnetic.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20201005120910.189343-45-jiawenwu@trustnetic.com/mbox/",
    "series": [
        {
            "id": 12690,
            "url": "http://patches.dpdk.org/api/series/12690/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=12690",
            "date": "2020-10-05T12:08:14",
            "name": "net: txgbe PMD",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/12690/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/79663/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/79663/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id CC25DA04B1;\n\tMon,  5 Oct 2020 14:27:50 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id E07F41C0D0;\n\tMon,  5 Oct 2020 14:10:03 +0200 (CEST)",
            "from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166])\n by dpdk.org (Postfix) with ESMTP id F20731BEE3\n for <dev@dpdk.org>; Mon,  5 Oct 2020 14:09:37 +0200 (CEST)",
            "from localhost.localdomain.com (unknown [183.129.236.74])\n by esmtp6.qq.com (ESMTP) with\n id ; Mon, 05 Oct 2020 20:09:32 +0800 (CST)"
        ],
        "X-QQ-mid": "bizesmtp9t1601899772t51cmy4bd",
        "X-QQ-SSF": "01400000002000C0C000B00A0000000",
        "X-QQ-FEAT": "socDd1yRFi4nt1gy8usDdxOxbimjUL1AGMHsu+50sSb/LPRSiJf9dlCVTt8pw\n 0CzE+XGiHSw9Zl5k3+eXqwmdPAV+9CZNVul1rUaTe49xWS5N8WmQNqVZFxxxhdPUT4Ox/VG\n VlyHJ0OU6DEbVbtzjbu7p79ipGF+wtg2Heo2wx+3DJD45i10sKjBzQJCyHi8OsVeqyyJMUQ\n WFP8H+EF9/44dsd2y1dI8pxNZ3OrUsIdO9FhYwvIaxV/5lfmtl8v7ARTS92LlWUNAxKtmtM\n Pzfd8I4ryroyOfUlk9+oKAcb5HQ+NBRyChuqvhaeOHZ8uHa3ns2JQ/bSEEwwMbf7soSFn7X\n iYf3DZjXTU8LEOTwWM=",
        "X-QQ-GoodBg": "2",
        "From": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "To": "dev@dpdk.org",
        "Cc": "jiawenwu <jiawenwu@trustnetic.com>",
        "Date": "Mon,  5 Oct 2020 20:08:58 +0800",
        "Message-Id": "<20201005120910.189343-45-jiawenwu@trustnetic.com>",
        "X-Mailer": "git-send-email 2.18.4",
        "In-Reply-To": "<20201005120910.189343-1-jiawenwu@trustnetic.com>",
        "References": "<20201005120910.189343-1-jiawenwu@trustnetic.com>",
        "X-QQ-SENDSIZE": "520",
        "Feedback-ID": "bizesmtp:trustnetic.com:qybgforeign:qybgforeign7",
        "X-QQ-Bgrelay": "1",
        "Subject": "[dpdk-dev] [PATCH v2 44/56] net/txgbe: add flow control support",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: jiawenwu <jiawenwu@trustnetic.com>\n\nAdd flow control support.\n\nSigned-off-by: jiawenwu <jiawenwu@trustnetic.com>\n---\n doc/guides/nics/features/txgbe.ini  |   1 +\n doc/guides/nics/txgbe.rst           |   1 +\n drivers/net/txgbe/base/txgbe_hw.c   | 426 ++++++++++++++++++++++++++++\n drivers/net/txgbe/base/txgbe_hw.h   |   6 +\n drivers/net/txgbe/base/txgbe_type.h |  22 ++\n drivers/net/txgbe/txgbe_ethdev.c    | 122 +++++++-\n drivers/net/txgbe/txgbe_ethdev.h    |   7 +\n 7 files changed, 584 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/doc/guides/nics/features/txgbe.ini b/doc/guides/nics/features/txgbe.ini\nindex 6cbc3a65a..f69785787 100644\n--- a/doc/guides/nics/features/txgbe.ini\n+++ b/doc/guides/nics/features/txgbe.ini\n@@ -22,6 +22,7 @@ VMDq                 = Y\n SR-IOV               = Y\n DCB                  = Y\n VLAN filter          = Y\n+Flow control         = Y\n Rate limitation      = Y\n CRC offload          = P\n VLAN offload         = P\ndiff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst\nindex 54aebee78..95919478b 100644\n--- a/doc/guides/nics/txgbe.rst\n+++ b/doc/guides/nics/txgbe.rst\n@@ -20,6 +20,7 @@ Features\n - Port hardware statistics\n - Jumbo frames\n - Link state information\n+- Link flow control\n - Interrupt mode for RX\n - Scattered and gather for TX and RX\n - DCB\ndiff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c\nindex afc91985c..40b4f2aee 100644\n--- a/drivers/net/txgbe/base/txgbe_hw.c\n+++ b/drivers/net/txgbe/base/txgbe_hw.c\n@@ -25,6 +25,212 @@ STATIC s32 txgbe_mta_vector(struct txgbe_hw *hw, u8 *mc_addr);\n STATIC s32 txgbe_get_san_mac_addr_offset(struct txgbe_hw *hw,\n \t\t\t\t\t u16 *san_mac_offset);\n \n+/**\n+ * txgbe_device_supports_autoneg_fc - Check if device supports autonegotiation\n+ * of flow control\n+ * @hw: pointer to hardware structure\n+ *\n+ * This function returns true if the device supports flow control\n+ * autonegotiation, and false if it does not.\n+ *\n+ **/\n+bool txgbe_device_supports_autoneg_fc(struct txgbe_hw *hw)\n+{\n+\tbool supported = false;\n+\tu32 speed;\n+\tbool link_up;\n+\n+\tDEBUGFUNC(\"txgbe_device_supports_autoneg_fc\");\n+\n+\tswitch (hw->phy.media_type) {\n+\tcase txgbe_media_type_fiber_qsfp:\n+\tcase txgbe_media_type_fiber:\n+\t\thw->mac.check_link(hw, &speed, &link_up, false);\n+\t\t/* if link is down, assume supported */\n+\t\tif (link_up)\n+\t\t\tsupported = speed == TXGBE_LINK_SPEED_1GB_FULL ?\n+\t\t\ttrue : false;\n+\t\telse\n+\t\t\tsupported = true;\n+\n+\t\tbreak;\n+\tcase txgbe_media_type_backplane:\n+\t\tsupported = true;\n+\t\tbreak;\n+\tcase txgbe_media_type_copper:\n+\t\t/* only some copper devices support flow control autoneg */\n+\t\tswitch (hw->device_id) {\n+\t\tcase TXGBE_DEV_ID_RAPTOR_XAUI:\n+\t\tcase TXGBE_DEV_ID_RAPTOR_SGMII:\n+\t\t\tsupported = true;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tsupported = false;\n+\t\t}\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (!supported)\n+\t\tDEBUGOUT(\"Device %x does not support flow control autoneg\",\n+\t\t\t      hw->device_id);\n+\treturn supported;\n+}\n+\n+/**\n+ *  txgbe_setup_fc - Set up flow control\n+ *  @hw: pointer to hardware structure\n+ *\n+ *  Called at init time to set up flow control.\n+ **/\n+s32 txgbe_setup_fc(struct txgbe_hw *hw)\n+{\n+\ts32 err = 0;\n+\tu32 reg = 0;\n+\tu16 reg_cu = 0;\n+\tu32 value = 0;\n+\tu64 reg_bp = 0;\n+\tbool locked = false;\n+\n+\tDEBUGFUNC(\"txgbe_setup_fc\");\n+\n+\t/* Validate the requested mode */\n+\tif (hw->fc.strict_ieee && hw->fc.requested_mode == txgbe_fc_rx_pause) {\n+\t\tDEBUGOUT(\"txgbe_fc_rx_pause not valid in strict IEEE mode\\n\");\n+\t\terr = TXGBE_ERR_INVALID_LINK_SETTINGS;\n+\t\tgoto out;\n+\t}\n+\n+\t/*\n+\t * 10gig parts do not have a word in the EEPROM to determine the\n+\t * default flow control setting, so we explicitly set it to full.\n+\t */\n+\tif (hw->fc.requested_mode == txgbe_fc_default)\n+\t\thw->fc.requested_mode = txgbe_fc_full;\n+\n+\t/*\n+\t * Set up the 1G and 10G flow control advertisement registers so the\n+\t * HW will be able to do fc autoneg once the cable is plugged in.  If\n+\t * we link at 10G, the 1G advertisement is harmless and vice versa.\n+\t */\n+\tswitch (hw->phy.media_type) {\n+\tcase txgbe_media_type_backplane:\n+\t\t/* some MAC's need RMW protection on AUTOC */\n+\t\terr = hw->mac.prot_autoc_read(hw, &locked, &reg_bp);\n+\t\tif (err != 0)\n+\t\t\tgoto out;\n+\n+\t\t/* fall through - only backplane uses autoc */\n+\tcase txgbe_media_type_fiber_qsfp:\n+\tcase txgbe_media_type_fiber:\n+\tcase txgbe_media_type_copper:\n+\t\thw->phy.read_reg(hw, TXGBE_MD_AUTO_NEG_ADVT,\n+\t\t\t\t     TXGBE_MD_DEV_AUTO_NEG, &reg_cu);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\t/*\n+\t * The possible values of fc.requested_mode are:\n+\t * 0: Flow control is completely disabled\n+\t * 1: Rx flow control is enabled (we can receive pause frames,\n+\t *    but not send pause frames).\n+\t * 2: Tx flow control is enabled (we can send pause frames but\n+\t *    we do not support receiving pause frames).\n+\t * 3: Both Rx and Tx flow control (symmetric) are enabled.\n+\t * other: Invalid.\n+\t */\n+\tswitch (hw->fc.requested_mode) {\n+\tcase txgbe_fc_none:\n+\t\t/* Flow control completely disabled by software override. */\n+\t\treg &= ~(SR_MII_MMD_AN_ADV_PAUSE_SYM |\n+\t\t\tSR_MII_MMD_AN_ADV_PAUSE_ASM);\n+\t\tif (hw->phy.media_type == txgbe_media_type_backplane)\n+\t\t\treg_bp &= ~(TXGBE_AUTOC_SYM_PAUSE |\n+\t\t\t\t    TXGBE_AUTOC_ASM_PAUSE);\n+\t\telse if (hw->phy.media_type == txgbe_media_type_copper)\n+\t\t\treg_cu &= ~(TXGBE_TAF_SYM_PAUSE | TXGBE_TAF_ASM_PAUSE);\n+\t\tbreak;\n+\tcase txgbe_fc_tx_pause:\n+\t\t/*\n+\t\t * Tx Flow control is enabled, and Rx Flow control is\n+\t\t * disabled by software override.\n+\t\t */\n+\t\treg |= SR_MII_MMD_AN_ADV_PAUSE_ASM;\n+\t\treg &= ~SR_MII_MMD_AN_ADV_PAUSE_SYM;\n+\t\tif (hw->phy.media_type == txgbe_media_type_backplane) {\n+\t\t\treg_bp |= TXGBE_AUTOC_ASM_PAUSE;\n+\t\t\treg_bp &= ~TXGBE_AUTOC_SYM_PAUSE;\n+\t\t} else if (hw->phy.media_type == txgbe_media_type_copper) {\n+\t\t\treg_cu |= TXGBE_TAF_ASM_PAUSE;\n+\t\t\treg_cu &= ~TXGBE_TAF_SYM_PAUSE;\n+\t\t}\n+\t\treg |= SR_MII_MMD_AN_ADV_PAUSE_ASM;\n+\t\treg_bp |= SR_AN_MMD_ADV_REG1_PAUSE_ASM;\n+\t\tbreak;\n+\tcase txgbe_fc_rx_pause:\n+\t\t/*\n+\t\t * Rx Flow control is enabled and Tx Flow control is\n+\t\t * disabled by software override. Since there really\n+\t\t * isn't a way to advertise that we are capable of RX\n+\t\t * Pause ONLY, we will advertise that we support both\n+\t\t * symmetric and asymmetric Rx PAUSE, as such we fall\n+\t\t * through to the fc_full statement.  Later, we will\n+\t\t * disable the adapter's ability to send PAUSE frames.\n+\t\t */\n+\tcase txgbe_fc_full:\n+\t\t/* Flow control (both Rx and Tx) is enabled by SW override. */\n+\t\treg |= SR_MII_MMD_AN_ADV_PAUSE_SYM |\n+\t\t\tSR_MII_MMD_AN_ADV_PAUSE_ASM;\n+\t\tif (hw->phy.media_type == txgbe_media_type_backplane)\n+\t\t\treg_bp |= TXGBE_AUTOC_SYM_PAUSE |\n+\t\t\t\t  TXGBE_AUTOC_ASM_PAUSE;\n+\t\telse if (hw->phy.media_type == txgbe_media_type_copper)\n+\t\t\treg_cu |= TXGBE_TAF_SYM_PAUSE | TXGBE_TAF_ASM_PAUSE;\n+\t\treg |= SR_MII_MMD_AN_ADV_PAUSE_SYM |\n+\t\t\tSR_MII_MMD_AN_ADV_PAUSE_ASM;\n+\t\treg_bp |= SR_AN_MMD_ADV_REG1_PAUSE_SYM |\n+\t\t\tSR_AN_MMD_ADV_REG1_PAUSE_ASM;\n+\t\tbreak;\n+\tdefault:\n+\t\tDEBUGOUT(\"Flow control param set incorrectly\\n\");\n+\t\terr = TXGBE_ERR_CONFIG;\n+\t\tgoto out;\n+\t\tbreak;\n+\t}\n+\n+\t/*\n+\t * Enable auto-negotiation between the MAC & PHY;\n+\t * the MAC will advertise clause 37 flow control.\n+\t */\n+\tvalue = rd32_epcs(hw, SR_MII_MMD_AN_ADV);\n+\tvalue = (value & ~(SR_MII_MMD_AN_ADV_PAUSE_ASM |\n+\t\tSR_MII_MMD_AN_ADV_PAUSE_SYM)) | reg;\n+\twr32_epcs(hw, SR_MII_MMD_AN_ADV, value);\n+\n+\t/*\n+\t * AUTOC restart handles negotiation of 1G and 10G on backplane\n+\t * and copper. There is no need to set the PCS1GCTL register.\n+\t *\n+\t */\n+\tif (hw->phy.media_type == txgbe_media_type_backplane) {\n+\t\tvalue = rd32_epcs(hw, SR_AN_MMD_ADV_REG1);\n+\t\tvalue = (value & ~(SR_AN_MMD_ADV_REG1_PAUSE_ASM |\n+\t\t\tSR_AN_MMD_ADV_REG1_PAUSE_SYM)) |\n+\t\t\treg_bp;\n+\t\twr32_epcs(hw, SR_AN_MMD_ADV_REG1, value);\n+\t} else if ((hw->phy.media_type == txgbe_media_type_copper) &&\n+\t\t    (txgbe_device_supports_autoneg_fc(hw))) {\n+\t\thw->phy.write_reg(hw, TXGBE_MD_AUTO_NEG_ADVT,\n+\t\t\t\t      TXGBE_MD_DEV_AUTO_NEG, reg_cu);\n+\t}\n+\n+\tDEBUGOUT(\"Set up FC; reg = 0x%08X\\n\", reg);\n+out:\n+\treturn err;\n+}\n+\n /**\n  *  txgbe_start_hw - Prepare hardware for Tx/Rx\n  *  @hw: pointer to hardware structure\n@@ -36,6 +242,7 @@ STATIC s32 txgbe_get_san_mac_addr_offset(struct txgbe_hw *hw,\n  **/\n s32 txgbe_start_hw(struct txgbe_hw *hw)\n {\n+\ts32 err;\n \tu16 device_caps;\n \n \tDEBUGFUNC(\"txgbe_start_hw\");\n@@ -49,6 +256,13 @@ s32 txgbe_start_hw(struct txgbe_hw *hw)\n \t/* Clear statistics registers */\n \thw->mac.clear_hw_cntrs(hw);\n \n+\t/* Setup flow control */\n+\terr = txgbe_setup_fc(hw);\n+\tif (err != 0 && err != TXGBE_NOT_IMPLEMENTED) {\n+\t\tDEBUGOUT(\"Flow control setup failed, returning %d\\n\", err);\n+\t\treturn err;\n+\t}\n+\n \t/* Cache bit indicating need for crosstalk fix */\n \tswitch (hw->mac.type) {\n \tcase txgbe_mac_raptor:\n@@ -676,6 +890,136 @@ s32 txgbe_update_mc_addr_list(struct txgbe_hw *hw, u8 *mc_addr_list,\n \treturn 0;\n }\n \n+/**\n+ *  txgbe_fc_enable - Enable flow control\n+ *  @hw: pointer to hardware structure\n+ *\n+ *  Enable flow control according to the current settings.\n+ **/\n+s32 txgbe_fc_enable(struct txgbe_hw *hw)\n+{\n+\ts32 err = 0;\n+\tu32 mflcn_reg, fccfg_reg;\n+\tu32 pause_time;\n+\tu32 fcrtl, fcrth;\n+\tint i;\n+\n+\tDEBUGFUNC(\"txgbe_fc_enable\");\n+\n+\t/* Validate the water mark configuration */\n+\tif (!hw->fc.pause_time) {\n+\t\terr = TXGBE_ERR_INVALID_LINK_SETTINGS;\n+\t\tgoto out;\n+\t}\n+\n+\t/* Low water mark of zero causes XOFF floods */\n+\tfor (i = 0; i < TXGBE_DCB_TC_MAX; i++) {\n+\t\tif ((hw->fc.current_mode & txgbe_fc_tx_pause) &&\n+\t\t    hw->fc.high_water[i]) {\n+\t\t\tif (!hw->fc.low_water[i] ||\n+\t\t\t    hw->fc.low_water[i] >= hw->fc.high_water[i]) {\n+\t\t\t\tDEBUGOUT(\"Invalid water mark configuration\\n\");\n+\t\t\t\terr = TXGBE_ERR_INVALID_LINK_SETTINGS;\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* Negotiate the fc mode to use */\n+\thw->mac.fc_autoneg(hw);\n+\n+\t/* Disable any previous flow control settings */\n+\tmflcn_reg = rd32(hw, TXGBE_RXFCCFG);\n+\tmflcn_reg &= ~(TXGBE_RXFCCFG_FC | TXGBE_RXFCCFG_PFC);\n+\n+\tfccfg_reg = rd32(hw, TXGBE_TXFCCFG);\n+\tfccfg_reg &= ~(TXGBE_TXFCCFG_FC | TXGBE_TXFCCFG_PFC);\n+\n+\t/*\n+\t * The possible values of fc.current_mode are:\n+\t * 0: Flow control is completely disabled\n+\t * 1: Rx flow control is enabled (we can receive pause frames,\n+\t *    but not send pause frames).\n+\t * 2: Tx flow control is enabled (we can send pause frames but\n+\t *    we do not support receiving pause frames).\n+\t * 3: Both Rx and Tx flow control (symmetric) are enabled.\n+\t * other: Invalid.\n+\t */\n+\tswitch (hw->fc.current_mode) {\n+\tcase txgbe_fc_none:\n+\t\t/*\n+\t\t * Flow control is disabled by software override or autoneg.\n+\t\t * The code below will actually disable it in the HW.\n+\t\t */\n+\t\tbreak;\n+\tcase txgbe_fc_rx_pause:\n+\t\t/*\n+\t\t * Rx Flow control is enabled and Tx Flow control is\n+\t\t * disabled by software override. Since there really\n+\t\t * isn't a way to advertise that we are capable of RX\n+\t\t * Pause ONLY, we will advertise that we support both\n+\t\t * symmetric and asymmetric Rx PAUSE.  Later, we will\n+\t\t * disable the adapter's ability to send PAUSE frames.\n+\t\t */\n+\t\tmflcn_reg |= TXGBE_RXFCCFG_FC;\n+\t\tbreak;\n+\tcase txgbe_fc_tx_pause:\n+\t\t/*\n+\t\t * Tx Flow control is enabled, and Rx Flow control is\n+\t\t * disabled by software override.\n+\t\t */\n+\t\tfccfg_reg |= TXGBE_TXFCCFG_FC;\n+\t\tbreak;\n+\tcase txgbe_fc_full:\n+\t\t/* Flow control (both Rx and Tx) is enabled by SW override. */\n+\t\tmflcn_reg |= TXGBE_RXFCCFG_FC;\n+\t\tfccfg_reg |= TXGBE_TXFCCFG_FC;\n+\t\tbreak;\n+\tdefault:\n+\t\tDEBUGOUT(\"Flow control param set incorrectly\\n\");\n+\t\terr = TXGBE_ERR_CONFIG;\n+\t\tgoto out;\n+\t}\n+\n+\t/* Set 802.3x based flow control settings. */\n+\twr32(hw, TXGBE_RXFCCFG, mflcn_reg);\n+\twr32(hw, TXGBE_TXFCCFG, fccfg_reg);\n+\n+\t/* Set up and enable Rx high/low water mark thresholds, enable XON. */\n+\tfor (i = 0; i < TXGBE_DCB_TC_MAX; i++) {\n+\t\tif ((hw->fc.current_mode & txgbe_fc_tx_pause) &&\n+\t\t    hw->fc.high_water[i]) {\n+\t\t\tfcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[i]) |\n+\t\t\t\tTXGBE_FCWTRLO_XON;\n+\t\t\tfcrth = TXGBE_FCWTRHI_TH(hw->fc.high_water[i]) |\n+\t\t\t\tTXGBE_FCWTRHI_XOFF;\n+\t\t} else {\n+\t\t\t/*\n+\t\t\t * In order to prevent Tx hangs when the internal Tx\n+\t\t\t * switch is enabled we must set the high water mark\n+\t\t\t * to the Rx packet buffer size - 24KB.  This allows\n+\t\t\t * the Tx switch to function even under heavy Rx\n+\t\t\t * workloads.\n+\t\t\t */\n+\t\t\tfcrtl = 0;\n+\t\t\tfcrth = rd32(hw, TXGBE_PBRXSIZE(i)) - 24576;\n+\t\t}\n+\t\twr32(hw, TXGBE_FCWTRLO(i), fcrtl);\n+\t\twr32(hw, TXGBE_FCWTRHI(i), fcrth);\n+\t}\n+\n+\t/* Configure pause time (2 TCs per register) */\n+\tpause_time = TXGBE_RXFCFSH_TIME(hw->fc.pause_time);\n+\tfor (i = 0; i < (TXGBE_DCB_TC_MAX / 2); i++)\n+\t\twr32(hw, TXGBE_FCXOFFTM(i), pause_time * 0x00010001);\n+\n+\t/* Configure flow control refresh threshold value */\n+\twr32(hw, TXGBE_RXFCRFSH, hw->fc.pause_time / 2);\n+\n+out:\n+\treturn err;\n+}\n+\n /**\n  *  txgbe_acquire_swfw_sync - Acquire SWFW semaphore\n  *  @hw: pointer to hardware structure\n@@ -2097,6 +2441,82 @@ s32 txgbe_setup_sfp_modules(struct txgbe_hw *hw)\n \treturn err;\n }\n \n+/**\n+ *  txgbe_prot_autoc_read_raptor - Hides MAC differences needed for AUTOC read\n+ *  @hw: pointer to hardware structure\n+ *  @locked: Return the if we locked for this read.\n+ *  @value: Value we read from AUTOC\n+ *\n+ *  For this part we need to wrap read-modify-writes with a possible\n+ *  FW/SW lock.  It is assumed this lock will be freed with the next\n+ *  prot_autoc_write_raptor().\n+ */\n+s32 txgbe_prot_autoc_read_raptor(struct txgbe_hw *hw, bool *locked, u64 *value)\n+{\n+\ts32 err;\n+\tbool lock_state = false;\n+\n+\t /* If LESM is on then we need to hold the SW/FW semaphore. */\n+\tif (txgbe_verify_lesm_fw_enabled_raptor(hw)) {\n+\t\terr = hw->mac.acquire_swfw_sync(hw,\n+\t\t\t\t\tTXGBE_MNGSEM_SWPHY);\n+\t\tif (err != 0)\n+\t\t\treturn TXGBE_ERR_SWFW_SYNC;\n+\n+\t\tlock_state = true;\n+\t}\n+\n+\tif (locked)\n+\t\t*locked = lock_state;\n+\n+\t*value = txgbe_autoc_read(hw);\n+\treturn 0;\n+}\n+\n+/**\n+ * txgbe_prot_autoc_write_raptor - Hides MAC differences needed for AUTOC write\n+ * @hw: pointer to hardware structure\n+ * @autoc: value to write to AUTOC\n+ * @locked: bool to indicate whether the SW/FW lock was already taken by\n+ *           previous prot_autoc_read_raptor.\n+ *\n+ * This part may need to hold the SW/FW lock around all writes to\n+ * AUTOC. Likewise after a write we need to do a pipeline reset.\n+ */\n+s32 txgbe_prot_autoc_write_raptor(struct txgbe_hw *hw, bool locked, u64 autoc)\n+{\n+\tint err = 0;\n+\n+\t/* Blocked by MNG FW so bail */\n+\tif (txgbe_check_reset_blocked(hw))\n+\t\tgoto out;\n+\n+\t/* We only need to get the lock if:\n+\t *  - We didn't do it already (in the read part of a read-modify-write)\n+\t *  - LESM is enabled.\n+\t */\n+\tif (!locked && txgbe_verify_lesm_fw_enabled_raptor(hw)) {\n+\t\terr = hw->mac.acquire_swfw_sync(hw,\n+\t\t\t\t\tTXGBE_MNGSEM_SWPHY);\n+\t\tif (err != 0)\n+\t\t\treturn TXGBE_ERR_SWFW_SYNC;\n+\n+\t\tlocked = true;\n+\t}\n+\n+\ttxgbe_autoc_write(hw, autoc);\n+\terr = txgbe_reset_pipeline_raptor(hw);\n+\n+out:\n+\t/* Free the SW/FW semaphore as we either grabbed it here or\n+\t * already had it when this function was called.\n+\t */\n+\tif (locked)\n+\t\thw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY);\n+\n+\treturn err;\n+}\n+\n /**\n  *  txgbe_init_ops_pf - Inits func ptrs and MAC type\n  *  @hw: pointer to hardware structure\n@@ -2154,6 +2574,8 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw)\n \tmac->get_wwn_prefix = txgbe_get_wwn_prefix;\n \tmac->autoc_read = txgbe_autoc_read;\n \tmac->autoc_write = txgbe_autoc_write;\n+\tmac->prot_autoc_read = txgbe_prot_autoc_read_raptor;\n+\tmac->prot_autoc_write = txgbe_prot_autoc_write_raptor;\n \n \t/* RAR, Multicast, VLAN */\n \tmac->set_rar = txgbe_set_rar;\n@@ -2171,6 +2593,10 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw)\n \tmac->set_mac_anti_spoofing = txgbe_set_mac_anti_spoofing;\n \tmac->set_ethertype_anti_spoofing = txgbe_set_ethertype_anti_spoofing;\n \n+\t/* Flow Control */\n+\tmac->fc_enable = txgbe_fc_enable;\n+\tmac->setup_fc = txgbe_setup_fc;\n+\n \t/* Link */\n \tmac->get_link_capabilities = txgbe_get_link_capabilities_raptor;\n \tmac->check_link = txgbe_check_mac_link;\ndiff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h\nindex 00fc6c2d5..832d03305 100644\n--- a/drivers/net/txgbe/base/txgbe_hw.h\n+++ b/drivers/net/txgbe/base/txgbe_hw.h\n@@ -28,6 +28,10 @@ s32 txgbe_enable_sec_rx_path(struct txgbe_hw *hw);\n s32 txgbe_disable_sec_tx_path(struct txgbe_hw *hw);\n s32 txgbe_enable_sec_tx_path(struct txgbe_hw *hw);\n \n+s32 txgbe_fc_enable(struct txgbe_hw *hw);\n+bool txgbe_device_supports_autoneg_fc(struct txgbe_hw *hw);\n+s32 txgbe_setup_fc(struct txgbe_hw *hw);\n+\n s32 txgbe_validate_mac_addr(u8 *mac_addr);\n s32 txgbe_acquire_swfw_sync(struct txgbe_hw *hw, u32 mask);\n void txgbe_release_swfw_sync(struct txgbe_hw *hw, u32 mask);\n@@ -96,5 +100,7 @@ s32 txgbe_reset_hw(struct txgbe_hw *hw);\n s32 txgbe_start_hw_raptor(struct txgbe_hw *hw);\n s32 txgbe_init_phy_raptor(struct txgbe_hw *hw);\n s32 txgbe_enable_rx_dma_raptor(struct txgbe_hw *hw, u32 regval);\n+s32 txgbe_prot_autoc_read_raptor(struct txgbe_hw *hw, bool *locked, u64 *value);\n+s32 txgbe_prot_autoc_write_raptor(struct txgbe_hw *hw, bool locked, u64 value);\n bool txgbe_verify_lesm_fw_enabled_raptor(struct txgbe_hw *hw);\n #endif /* _TXGBE_HW_H_ */\ndiff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h\nindex 08c611488..4b1c56db0 100644\n--- a/drivers/net/txgbe/base/txgbe_type.h\n+++ b/drivers/net/txgbe/base/txgbe_type.h\n@@ -153,6 +153,14 @@ enum txgbe_media_type {\n \ttxgbe_media_type_virtual\n };\n \n+/* Flow Control Settings */\n+enum txgbe_fc_mode {\n+\ttxgbe_fc_none = 0,\n+\ttxgbe_fc_rx_pause,\n+\ttxgbe_fc_tx_pause,\n+\ttxgbe_fc_full,\n+\ttxgbe_fc_default\n+};\n \n /* Smart Speed Settings */\n #define TXGBE_SMARTSPEED_MAX_RETRIES\t3\n@@ -222,6 +230,19 @@ struct txgbe_bus_info {\n \tu16 instance_id;\n };\n \n+/* Flow control parameters */\n+struct txgbe_fc_info {\n+\tu32 high_water[TXGBE_DCB_TC_MAX]; /* Flow Ctrl High-water */\n+\tu32 low_water[TXGBE_DCB_TC_MAX]; /* Flow Ctrl Low-water */\n+\tu16 pause_time; /* Flow Control Pause timer */\n+\tbool send_xon; /* Flow control send XON */\n+\tbool strict_ieee; /* Strict IEEE mode */\n+\tbool disable_fc_autoneg; /* Do not autonegotiate FC */\n+\tbool fc_was_autonegged; /* Is current_mode the result of autonegging? */\n+\tenum txgbe_fc_mode current_mode; /* FC mode in effect */\n+\tenum txgbe_fc_mode requested_mode; /* FC mode requested by caller */\n+};\n+\n /* Statistics counters collected by the MAC */\n /* PB[] RxTx */\n struct txgbe_pb_stats {\n@@ -638,6 +659,7 @@ struct txgbe_hw {\n \tvoid *back;\n \tstruct txgbe_mac_info mac;\n \tstruct txgbe_addr_filter_info addr_ctrl;\n+\tstruct txgbe_fc_info fc;\n \tstruct txgbe_phy_info phy;\n \tstruct txgbe_link_info link;\n \tstruct txgbe_rom_info rom;\ndiff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c\nindex 8d416f82f..a91112ee6 100644\n--- a/drivers/net/txgbe/txgbe_ethdev.c\n+++ b/drivers/net/txgbe/txgbe_ethdev.c\n@@ -403,11 +403,12 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)\n \tstruct txgbe_vfta *shadow_vfta = TXGBE_DEV_VFTA(eth_dev);\n \tstruct txgbe_hwstrip *hwstrip = TXGBE_DEV_HWSTRIP(eth_dev);\n \tstruct txgbe_dcb_config *dcb_config = TXGBE_DEV_DCB_CONFIG(eth_dev);\n+\tstruct txgbe_bw_conf *bw_conf = TXGBE_DEV_BW_CONF(eth_dev);\n \tstruct rte_intr_handle *intr_handle = &pci_dev->intr_handle;\n \tconst struct rte_memzone *mz;\n \tuint32_t ctrl_ext;\n \tuint16_t csum;\n-\tint err;\n+\tint err, i;\n \n \tPMD_INIT_FUNC_TRACE();\n \n@@ -471,6 +472,16 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)\n \tmemset(dcb_config, 0, sizeof(struct txgbe_dcb_config));\n \ttxgbe_dcb_init(hw, dcb_config);\n \n+\t/* Get Hardware Flow Control setting */\n+\thw->fc.requested_mode = txgbe_fc_full;\n+\thw->fc.current_mode = txgbe_fc_full;\n+\thw->fc.pause_time = TXGBE_FC_PAUSE_TIME;\n+\tfor (i = 0; i < TXGBE_DCB_TC_MAX; i++) {\n+\t\thw->fc.low_water[i] = TXGBE_FC_XON_LOTH;\n+\t\thw->fc.high_water[i] = TXGBE_FC_XOFF_HITH;\n+\t}\n+\thw->fc.send_xon = 1;\n+\n \terr = hw->rom.init_params(hw);\n \tif (err != 0) {\n \t\tPMD_INIT_LOG(ERR, \"The EEPROM init failed: %d\", err);\n@@ -592,6 +603,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)\n \t/* enable support intr */\n \ttxgbe_enable_intr(eth_dev);\n \n+\t/* initialize bandwidth configuration info */\n+\tmemset(bw_conf, 0, sizeof(struct txgbe_bw_conf));\n+\n \treturn 0;\n }\n \n@@ -2681,6 +2695,110 @@ txgbe_dev_interrupt_handler(void *param)\n \ttxgbe_dev_interrupt_action(dev, dev->intr_handle);\n }\n \n+static int\n+txgbe_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)\n+{\n+\tstruct txgbe_hw *hw;\n+\tuint32_t mflcn_reg;\n+\tuint32_t fccfg_reg;\n+\tint rx_pause;\n+\tint tx_pause;\n+\n+\thw = TXGBE_DEV_HW(dev);\n+\n+\tfc_conf->pause_time = hw->fc.pause_time;\n+\tfc_conf->high_water = hw->fc.high_water[0];\n+\tfc_conf->low_water = hw->fc.low_water[0];\n+\tfc_conf->send_xon = hw->fc.send_xon;\n+\tfc_conf->autoneg = !hw->fc.disable_fc_autoneg;\n+\n+\t/*\n+\t * Return rx_pause status according to actual setting of\n+\t * RXFCCFG register.\n+\t */\n+\tmflcn_reg = rd32(hw, TXGBE_RXFCCFG);\n+\tif (mflcn_reg & (TXGBE_RXFCCFG_FC | TXGBE_RXFCCFG_PFC))\n+\t\trx_pause = 1;\n+\telse\n+\t\trx_pause = 0;\n+\n+\t/*\n+\t * Return tx_pause status according to actual setting of\n+\t * TXFCCFG register.\n+\t */\n+\tfccfg_reg = rd32(hw, TXGBE_TXFCCFG);\n+\tif (fccfg_reg & (TXGBE_TXFCCFG_FC | TXGBE_TXFCCFG_PFC))\n+\t\ttx_pause = 1;\n+\telse\n+\t\ttx_pause = 0;\n+\n+\tif (rx_pause && tx_pause)\n+\t\tfc_conf->mode = RTE_FC_FULL;\n+\telse if (rx_pause)\n+\t\tfc_conf->mode = RTE_FC_RX_PAUSE;\n+\telse if (tx_pause)\n+\t\tfc_conf->mode = RTE_FC_TX_PAUSE;\n+\telse\n+\t\tfc_conf->mode = RTE_FC_NONE;\n+\n+\treturn 0;\n+}\n+\n+static int\n+txgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)\n+{\n+\tstruct txgbe_hw *hw;\n+\tint err;\n+\tuint32_t rx_buf_size;\n+\tuint32_t max_high_water;\n+\tenum txgbe_fc_mode rte_fcmode_2_txgbe_fcmode[] = {\n+\t\ttxgbe_fc_none,\n+\t\ttxgbe_fc_rx_pause,\n+\t\ttxgbe_fc_tx_pause,\n+\t\ttxgbe_fc_full\n+\t};\n+\n+\tPMD_INIT_FUNC_TRACE();\n+\n+\thw = TXGBE_DEV_HW(dev);\n+\trx_buf_size = rd32(hw, TXGBE_PBRXSIZE(0));\n+\tPMD_INIT_LOG(DEBUG, \"Rx packet buffer size = 0x%x\", rx_buf_size);\n+\n+\t/*\n+\t * At least reserve one Ethernet frame for watermark\n+\t * high_water/low_water in kilo bytes for txgbe\n+\t */\n+\tmax_high_water = (rx_buf_size - RTE_ETHER_MAX_LEN) >> 10;\n+\tif ((fc_conf->high_water > max_high_water) ||\n+\t    (fc_conf->high_water < fc_conf->low_water)) {\n+\t\tPMD_INIT_LOG(ERR, \"Invalid high/low water setup value in KB\");\n+\t\tPMD_INIT_LOG(ERR, \"High_water must <= 0x%x\", max_high_water);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\thw->fc.requested_mode = rte_fcmode_2_txgbe_fcmode[fc_conf->mode];\n+\thw->fc.pause_time     = fc_conf->pause_time;\n+\thw->fc.high_water[0]  = fc_conf->high_water;\n+\thw->fc.low_water[0]   = fc_conf->low_water;\n+\thw->fc.send_xon       = fc_conf->send_xon;\n+\thw->fc.disable_fc_autoneg = !fc_conf->autoneg;\n+\n+\terr = txgbe_fc_enable(hw);\n+\n+\t/* Not negotiated is not an error case */\n+\tif ((err == 0) || (err == TXGBE_ERR_FC_NOT_NEGOTIATED)) {\n+\t\twr32m(hw, TXGBE_MACRXFLT, TXGBE_MACRXFLT_CTL_MASK,\n+\t\t      (fc_conf->mac_ctrl_frame_fwd\n+\t\t       ? TXGBE_MACRXFLT_CTL_NOPS : TXGBE_MACRXFLT_CTL_DROP));\n+\t\ttxgbe_flush(hw);\n+\n+\t\treturn 0;\n+\t}\n+\n+\tPMD_INIT_LOG(ERR, \"txgbe_fc_enable = 0x%x\", err);\n+\treturn -EIO;\n+}\n+\n int\n txgbe_dev_rss_reta_update(struct rte_eth_dev *dev,\n \t\t\t  struct rte_eth_rss_reta_entry64 *reta_conf,\n@@ -3164,6 +3282,8 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = {\n \t.rx_queue_release           = txgbe_dev_rx_queue_release,\n \t.tx_queue_setup             = txgbe_dev_tx_queue_setup,\n \t.tx_queue_release           = txgbe_dev_tx_queue_release,\n+\t.flow_ctrl_get              = txgbe_flow_ctrl_get,\n+\t.flow_ctrl_set              = txgbe_flow_ctrl_set,\n \t.mac_addr_add               = txgbe_add_rar,\n \t.mac_addr_remove            = txgbe_remove_rar,\n \t.mac_addr_set               = txgbe_set_default_mac_addr,\ndiff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h\nindex 809a1889c..22902b0fb 100644\n--- a/drivers/net/txgbe/txgbe_ethdev.h\n+++ b/drivers/net/txgbe/txgbe_ethdev.h\n@@ -326,6 +326,13 @@ txgbe_ethertype_filter_insert(struct txgbe_filter_info *filter_info,\n \treturn (i < TXGBE_ETF_ID_MAX ? i : -1);\n }\n \n+/* High threshold controlling when to start sending XOFF frames. */\n+#define TXGBE_FC_XOFF_HITH              128 /*KB*/\n+/* Low threshold controlling when to start sending XON frames. */\n+#define TXGBE_FC_XON_LOTH               64 /*KB*/\n+\n+/* Timer value included in XOFF frames. */\n+#define TXGBE_FC_PAUSE_TIME 0x680\n \n #define TXGBE_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */\n #define TXGBE_LINK_UP_CHECK_TIMEOUT   1000 /* ms */\n",
    "prefixes": [
        "v2",
        "44/56"
    ]
}