get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 81306,
    "url": "http://patches.dpdk.org/api/patches/81306/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20201019085415.82207-19-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": "<20201019085415.82207-19-jiawenwu@trustnetic.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201019085415.82207-19-jiawenwu@trustnetic.com",
    "date": "2020-10-19T08:53:35",
    "name": "[v4,18/58] net/txgbe: add MAC address operations",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "0df47804776242c53c344decd336ab585dc93e66",
    "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/20201019085415.82207-19-jiawenwu@trustnetic.com/mbox/",
    "series": [
        {
            "id": 13094,
            "url": "http://patches.dpdk.org/api/series/13094/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=13094",
            "date": "2020-10-19T08:53:17",
            "name": "net: txgbe PMD",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/13094/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/81306/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/81306/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 073A6A04DC;\n\tMon, 19 Oct 2020 11:01:48 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 22AD9C9E4;\n\tMon, 19 Oct 2020 10:53:29 +0200 (CEST)",
            "from smtpbguseast2.qq.com (smtpbguseast2.qq.com [54.204.34.130])\n by dpdk.org (Postfix) with ESMTP id C6824C846\n for <dev@dpdk.org>; Mon, 19 Oct 2020 10:52:56 +0200 (CEST)",
            "from localhost.localdomain.com (unknown [183.129.236.74])\n by esmtp6.qq.com (ESMTP) with\n id ; Mon, 19 Oct 2020 16:52:50 +0800 (CST)"
        ],
        "X-QQ-mid": "bizesmtp6t1603097570trhm1rlam",
        "X-QQ-SSF": "01400000002000C0C000B00A0000000",
        "X-QQ-FEAT": "1WyLoCoLasin29ZJEhMso5eEFDmThjmDy5DJ17K33/15RQzFUfe4hd2ZCCuVn\n IWVvwEMIPVe23aseOoUcUtz14AGk3ZClpinUgUZgVVp3+lezlnw86kB0OmeNc1STDNq1PLn\n Xv7hUiegwnYdPUcXmnpoGOtOvoYVu1AKjpYC1NuzikncDIqu0gmGbSEzrcHuuaugOI3g1H/\n Wkrejmi+Kn4msCupQyxsFnmF91xK78XVM/YiPj37cZyoO7N3yRX00VYETzU4RMdvHMA0RKm\n +gqFWwkHvdwPQLhAFVFYQ+1EzfrZXfKeLpdBRckkON5iBFbS05bZBvngyeXENna9lhSAgNd\n HpNEk/R0FnobsAjvCBCbzQbDZTqmw==",
        "X-QQ-GoodBg": "2",
        "From": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "To": "dev@dpdk.org",
        "Cc": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "Date": "Mon, 19 Oct 2020 16:53:35 +0800",
        "Message-Id": "<20201019085415.82207-19-jiawenwu@trustnetic.com>",
        "X-Mailer": "git-send-email 2.18.4",
        "In-Reply-To": "<20201019085415.82207-1-jiawenwu@trustnetic.com>",
        "References": "<20201019085415.82207-1-jiawenwu@trustnetic.com>",
        "X-QQ-SENDSIZE": "520",
        "Feedback-ID": "bizesmtp:trustnetic.com:qybgforeign:qybgforeign6",
        "X-QQ-Bgrelay": "1",
        "Subject": "[dpdk-dev] [PATCH v4 18/58] net/txgbe: add MAC address operations",
        "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": "Add MAC address related operations.\n\nSigned-off-by: Jiawen Wu <jiawenwu@trustnetic.com>\n---\n doc/guides/nics/features/txgbe.ini    |   2 +\n doc/guides/nics/txgbe.rst             |   1 +\n drivers/net/txgbe/base/txgbe_eeprom.h |   2 +\n drivers/net/txgbe/base/txgbe_hw.c     | 476 ++++++++++++++++++++++++++\n drivers/net/txgbe/base/txgbe_hw.h     |  14 +\n drivers/net/txgbe/base/txgbe_type.h   |  15 +-\n drivers/net/txgbe/txgbe_ethdev.c      |  62 ++++\n drivers/net/txgbe/txgbe_ethdev.h      |   3 +\n 8 files changed, 574 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/doc/guides/nics/features/txgbe.ini b/doc/guides/nics/features/txgbe.ini\nindex d7c3bbfb6..115a8699b 100644\n--- a/doc/guides/nics/features/txgbe.ini\n+++ b/doc/guides/nics/features/txgbe.ini\n@@ -7,6 +7,8 @@\n Speed capabilities   = Y\n Link status          = Y\n Link status event    = Y\n+Unicast MAC filter   = Y\n+Multicast MAC filter = Y\n Linux UIO            = Y\n Linux VFIO           = Y\n ARMv8                = Y\ndiff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst\nindex 78cb611c2..0ec4148e2 100644\n--- a/doc/guides/nics/txgbe.rst\n+++ b/doc/guides/nics/txgbe.rst\n@@ -11,6 +11,7 @@ Features\n --------\n \n - Multiple queues for TX and RX\n+- MAC filtering\n - Link state information\n \n Prerequisites\ndiff --git a/drivers/net/txgbe/base/txgbe_eeprom.h b/drivers/net/txgbe/base/txgbe_eeprom.h\nindex 26cf08495..e50dfe4f6 100644\n--- a/drivers/net/txgbe/base/txgbe_eeprom.h\n+++ b/drivers/net/txgbe/base/txgbe_eeprom.h\n@@ -23,6 +23,8 @@\n #define TXGBE_EEPROM_VERSION_H          0x1E\n #define TXGBE_ISCSI_BOOT_CONFIG         0x07\n \n+#define TXGBE_SAN_MAC_ADDR_PORT0_OFFSET\t\t0x0\n+#define TXGBE_SAN_MAC_ADDR_PORT1_OFFSET\t\t0x3\n #define TXGBE_DEVICE_CAPS_ALLOW_ANY_SFP\t\t0x1\n #define TXGBE_FW_LESM_PARAMETERS_PTR\t\t0x2\n #define TXGBE_FW_LESM_STATE_1\t\t\t0x1\ndiff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c\nindex 3ba2e233c..a4bb44c92 100644\n--- a/drivers/net/txgbe/base/txgbe_hw.c\n+++ b/drivers/net/txgbe/base/txgbe_hw.c\n@@ -11,11 +11,16 @@\n #define TXGBE_RAPTOR_MAX_TX_QUEUES 128\n #define TXGBE_RAPTOR_MAX_RX_QUEUES 128\n #define TXGBE_RAPTOR_RAR_ENTRIES   128\n+#define TXGBE_RAPTOR_MC_TBL_SIZE   128\n \n static s32 txgbe_setup_copper_link_raptor(struct txgbe_hw *hw,\n \t\t\t\t\t u32 speed,\n \t\t\t\t\t bool autoneg_wait_to_complete);\n \n+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_init_hw - Generic hardware initialization\n  *  @hw: pointer to hardware structure\n@@ -45,6 +50,35 @@ s32 txgbe_init_hw(struct txgbe_hw *hw)\n \treturn status;\n }\n \n+/**\n+ *  txgbe_get_mac_addr - Generic get MAC address\n+ *  @hw: pointer to hardware structure\n+ *  @mac_addr: Adapter MAC address\n+ *\n+ *  Reads the adapter's MAC address from first Receive Address Register (RAR0)\n+ *  A reset of the adapter must be performed prior to calling this function\n+ *  in order for the MAC address to have been loaded from the EEPROM into RAR0\n+ **/\n+s32 txgbe_get_mac_addr(struct txgbe_hw *hw, u8 *mac_addr)\n+{\n+\tu32 rar_high;\n+\tu32 rar_low;\n+\tu16 i;\n+\n+\tDEBUGFUNC(\"txgbe_get_mac_addr\");\n+\n+\twr32(hw, TXGBE_ETHADDRIDX, 0);\n+\trar_high = rd32(hw, TXGBE_ETHADDRH);\n+\trar_low = rd32(hw, TXGBE_ETHADDRL);\n+\n+\tfor (i = 0; i < 2; i++)\n+\t\tmac_addr[i] = (u8)(rar_high >> (1 - i) * 8);\n+\n+\tfor (i = 0; i < 4; i++)\n+\t\tmac_addr[i + 2] = (u8)(rar_low >> (3 - i) * 8);\n+\n+\treturn 0;\n+}\n \n /**\n  *  txgbe_set_lan_id_multi_port - Set LAN id for PCIe multiple port devices\n@@ -97,6 +131,440 @@ s32 txgbe_validate_mac_addr(u8 *mac_addr)\n \treturn status;\n }\n \n+/**\n+ *  txgbe_set_rar - Set Rx address register\n+ *  @hw: pointer to hardware structure\n+ *  @index: Receive address register to write\n+ *  @addr: Address to put into receive address register\n+ *  @vmdq: VMDq \"set\" or \"pool\" index\n+ *  @enable_addr: set flag that address is active\n+ *\n+ *  Puts an ethernet address into a receive address register.\n+ **/\n+s32 txgbe_set_rar(struct txgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,\n+\t\t\t  u32 enable_addr)\n+{\n+\tu32 rar_low, rar_high;\n+\tu32 rar_entries = hw->mac.num_rar_entries;\n+\n+\tDEBUGFUNC(\"txgbe_set_rar\");\n+\n+\t/* Make sure we are using a valid rar index range */\n+\tif (index >= rar_entries) {\n+\t\tDEBUGOUT(\"RAR index %d is out of range.\\n\", index);\n+\t\treturn TXGBE_ERR_INVALID_ARGUMENT;\n+\t}\n+\n+\t/* setup VMDq pool selection before this RAR gets enabled */\n+\thw->mac.set_vmdq(hw, index, vmdq);\n+\n+\t/*\n+\t * HW expects these in little endian so we reverse the byte\n+\t * order from network order (big endian) to little endian\n+\t */\n+\trar_low = TXGBE_ETHADDRL_AD0(addr[5]) |\n+\t\t  TXGBE_ETHADDRL_AD1(addr[4]) |\n+\t\t  TXGBE_ETHADDRL_AD2(addr[3]) |\n+\t\t  TXGBE_ETHADDRL_AD3(addr[2]);\n+\t/*\n+\t * Some parts put the VMDq setting in the extra RAH bits,\n+\t * so save everything except the lower 16 bits that hold part\n+\t * of the address and the address valid bit.\n+\t */\n+\trar_high = rd32(hw, TXGBE_ETHADDRH);\n+\trar_high &= ~TXGBE_ETHADDRH_AD_MASK;\n+\trar_high |= (TXGBE_ETHADDRH_AD4(addr[1]) |\n+\t\t     TXGBE_ETHADDRH_AD5(addr[0]));\n+\n+\trar_high &= ~TXGBE_ETHADDRH_VLD;\n+\tif (enable_addr != 0)\n+\t\trar_high |= TXGBE_ETHADDRH_VLD;\n+\n+\twr32(hw, TXGBE_ETHADDRIDX, index);\n+\twr32(hw, TXGBE_ETHADDRL, rar_low);\n+\twr32(hw, TXGBE_ETHADDRH, rar_high);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ *  txgbe_clear_rar - Remove Rx address register\n+ *  @hw: pointer to hardware structure\n+ *  @index: Receive address register to write\n+ *\n+ *  Clears an ethernet address from a receive address register.\n+ **/\n+s32 txgbe_clear_rar(struct txgbe_hw *hw, u32 index)\n+{\n+\tu32 rar_high;\n+\tu32 rar_entries = hw->mac.num_rar_entries;\n+\n+\tDEBUGFUNC(\"txgbe_clear_rar\");\n+\n+\t/* Make sure we are using a valid rar index range */\n+\tif (index >= rar_entries) {\n+\t\tDEBUGOUT(\"RAR index %d is out of range.\\n\", index);\n+\t\treturn TXGBE_ERR_INVALID_ARGUMENT;\n+\t}\n+\n+\t/*\n+\t * Some parts put the VMDq setting in the extra RAH bits,\n+\t * so save everything except the lower 16 bits that hold part\n+\t * of the address and the address valid bit.\n+\t */\n+\twr32(hw, TXGBE_ETHADDRIDX, index);\n+\trar_high = rd32(hw, TXGBE_ETHADDRH);\n+\trar_high &= ~(TXGBE_ETHADDRH_AD_MASK | TXGBE_ETHADDRH_VLD);\n+\n+\twr32(hw, TXGBE_ETHADDRL, 0);\n+\twr32(hw, TXGBE_ETHADDRH, rar_high);\n+\n+\t/* clear VMDq pool/queue selection for this RAR */\n+\thw->mac.clear_vmdq(hw, index, BIT_MASK32);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ *  txgbe_init_rx_addrs - Initializes receive address filters.\n+ *  @hw: pointer to hardware structure\n+ *\n+ *  Places the MAC address in receive address register 0 and clears the rest\n+ *  of the receive address registers. Clears the multicast table. Assumes\n+ *  the receiver is in reset when the routine is called.\n+ **/\n+s32 txgbe_init_rx_addrs(struct txgbe_hw *hw)\n+{\n+\tu32 i;\n+\tu32 psrctl;\n+\tu32 rar_entries = hw->mac.num_rar_entries;\n+\n+\tDEBUGFUNC(\"txgbe_init_rx_addrs\");\n+\n+\t/*\n+\t * If the current mac address is valid, assume it is a software override\n+\t * to the permanent address.\n+\t * Otherwise, use the permanent address from the eeprom.\n+\t */\n+\tif (txgbe_validate_mac_addr(hw->mac.addr) ==\n+\t    TXGBE_ERR_INVALID_MAC_ADDR) {\n+\t\t/* Get the MAC address from the RAR0 for later reference */\n+\t\thw->mac.get_mac_addr(hw, hw->mac.addr);\n+\n+\t\tDEBUGOUT(\" Keeping Current RAR0 Addr =%.2X %.2X %.2X \",\n+\t\t\t  hw->mac.addr[0], hw->mac.addr[1],\n+\t\t\t  hw->mac.addr[2]);\n+\t\tDEBUGOUT(\"%.2X %.2X %.2X\\n\", hw->mac.addr[3],\n+\t\t\t  hw->mac.addr[4], hw->mac.addr[5]);\n+\t} else {\n+\t\t/* Setup the receive address. */\n+\t\tDEBUGOUT(\"Overriding MAC Address in RAR[0]\\n\");\n+\t\tDEBUGOUT(\" New MAC Addr =%.2X %.2X %.2X \",\n+\t\t\t  hw->mac.addr[0], hw->mac.addr[1],\n+\t\t\t  hw->mac.addr[2]);\n+\t\tDEBUGOUT(\"%.2X %.2X %.2X\\n\", hw->mac.addr[3],\n+\t\t\t  hw->mac.addr[4], hw->mac.addr[5]);\n+\n+\t\thw->mac.set_rar(hw, 0, hw->mac.addr, 0, true);\n+\t}\n+\n+\t/* clear VMDq pool/queue selection for RAR 0 */\n+\thw->mac.clear_vmdq(hw, 0, BIT_MASK32);\n+\n+\thw->addr_ctrl.overflow_promisc = 0;\n+\n+\thw->addr_ctrl.rar_used_count = 1;\n+\n+\t/* Zero out the other receive addresses. */\n+\tDEBUGOUT(\"Clearing RAR[1-%d]\\n\", rar_entries - 1);\n+\tfor (i = 1; i < rar_entries; i++) {\n+\t\twr32(hw, TXGBE_ETHADDRIDX, i);\n+\t\twr32(hw, TXGBE_ETHADDRL, 0);\n+\t\twr32(hw, TXGBE_ETHADDRH, 0);\n+\t}\n+\n+\t/* Clear the MTA */\n+\thw->addr_ctrl.mta_in_use = 0;\n+\tpsrctl = rd32(hw, TXGBE_PSRCTL);\n+\tpsrctl &= ~(TXGBE_PSRCTL_ADHF12_MASK | TXGBE_PSRCTL_MCHFENA);\n+\tpsrctl |= TXGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type);\n+\twr32(hw, TXGBE_PSRCTL, psrctl);\n+\n+\tDEBUGOUT(\" Clearing MTA\\n\");\n+\tfor (i = 0; i < hw->mac.mcft_size; i++)\n+\t\twr32(hw, TXGBE_MCADDRTBL(i), 0);\n+\n+\ttxgbe_init_uta_tables(hw);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ *  txgbe_mta_vector - Determines bit-vector in multicast table to set\n+ *  @hw: pointer to hardware structure\n+ *  @mc_addr: the multicast address\n+ *\n+ *  Extracts the 12 bits, from a multicast address, to determine which\n+ *  bit-vector to set in the multicast table. The hardware uses 12 bits, from\n+ *  incoming rx multicast addresses, to determine the bit-vector to check in\n+ *  the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set\n+ *  by the MO field of the PSRCTRL. The MO field is set during initialization\n+ *  to mc_filter_type.\n+ **/\n+static s32 txgbe_mta_vector(struct txgbe_hw *hw, u8 *mc_addr)\n+{\n+\tu32 vector = 0;\n+\n+\tDEBUGFUNC(\"txgbe_mta_vector\");\n+\n+\tswitch (hw->mac.mc_filter_type) {\n+\tcase 0:   /* use bits [47:36] of the address */\n+\t\tvector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));\n+\t\tbreak;\n+\tcase 1:   /* use bits [46:35] of the address */\n+\t\tvector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));\n+\t\tbreak;\n+\tcase 2:   /* use bits [45:34] of the address */\n+\t\tvector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));\n+\t\tbreak;\n+\tcase 3:   /* use bits [43:32] of the address */\n+\t\tvector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));\n+\t\tbreak;\n+\tdefault:  /* Invalid mc_filter_type */\n+\t\tDEBUGOUT(\"MC filter type param set incorrectly\\n\");\n+\t\tASSERT(0);\n+\t\tbreak;\n+\t}\n+\n+\t/* vector can only be 12-bits or boundary will be exceeded */\n+\tvector &= 0xFFF;\n+\treturn vector;\n+}\n+\n+/**\n+ *  txgbe_set_mta - Set bit-vector in multicast table\n+ *  @hw: pointer to hardware structure\n+ *  @mc_addr: Multicast address\n+ *\n+ *  Sets the bit-vector in the multicast table.\n+ **/\n+void txgbe_set_mta(struct txgbe_hw *hw, u8 *mc_addr)\n+{\n+\tu32 vector;\n+\tu32 vector_bit;\n+\tu32 vector_reg;\n+\n+\tDEBUGFUNC(\"txgbe_set_mta\");\n+\n+\thw->addr_ctrl.mta_in_use++;\n+\n+\tvector = txgbe_mta_vector(hw, mc_addr);\n+\tDEBUGOUT(\" bit-vector = 0x%03X\\n\", vector);\n+\n+\t/*\n+\t * The MTA is a register array of 128 32-bit registers. It is treated\n+\t * like an array of 4096 bits.  We want to set bit\n+\t * BitArray[vector_value]. So we figure out what register the bit is\n+\t * in, read it, OR in the new bit, then write back the new value.  The\n+\t * register is determined by the upper 7 bits of the vector value and\n+\t * the bit within that register are determined by the lower 5 bits of\n+\t * the value.\n+\t */\n+\tvector_reg = (vector >> 5) & 0x7F;\n+\tvector_bit = vector & 0x1F;\n+\thw->mac.mta_shadow[vector_reg] |= (1 << vector_bit);\n+}\n+\n+/**\n+ *  txgbe_update_mc_addr_list - Updates MAC list of multicast addresses\n+ *  @hw: pointer to hardware structure\n+ *  @mc_addr_list: the list of new multicast addresses\n+ *  @mc_addr_count: number of addresses\n+ *  @next: iterator function to walk the multicast address list\n+ *  @clear: flag, when set clears the table beforehand\n+ *\n+ *  When the clear flag is set, the given list replaces any existing list.\n+ *  Hashes the given addresses into the multicast table.\n+ **/\n+s32 txgbe_update_mc_addr_list(struct txgbe_hw *hw, u8 *mc_addr_list,\n+\t\t\t\t      u32 mc_addr_count, txgbe_mc_addr_itr next,\n+\t\t\t\t      bool clear)\n+{\n+\tu32 i;\n+\tu32 vmdq;\n+\n+\tDEBUGFUNC(\"txgbe_update_mc_addr_list\");\n+\n+\t/*\n+\t * Set the new number of MC addresses that we are being requested to\n+\t * use.\n+\t */\n+\thw->addr_ctrl.num_mc_addrs = mc_addr_count;\n+\thw->addr_ctrl.mta_in_use = 0;\n+\n+\t/* Clear mta_shadow */\n+\tif (clear) {\n+\t\tDEBUGOUT(\" Clearing MTA\\n\");\n+\t\tmemset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));\n+\t}\n+\n+\t/* Update mta_shadow */\n+\tfor (i = 0; i < mc_addr_count; i++) {\n+\t\tDEBUGOUT(\" Adding the multicast addresses:\\n\");\n+\t\ttxgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq));\n+\t}\n+\n+\t/* Enable mta */\n+\tfor (i = 0; i < hw->mac.mcft_size; i++)\n+\t\twr32a(hw, TXGBE_MCADDRTBL(0), i,\n+\t\t\t\t      hw->mac.mta_shadow[i]);\n+\n+\tif (hw->addr_ctrl.mta_in_use > 0) {\n+\t\tu32 psrctl = rd32(hw, TXGBE_PSRCTL);\n+\t\tpsrctl &= ~(TXGBE_PSRCTL_ADHF12_MASK | TXGBE_PSRCTL_MCHFENA);\n+\t\tpsrctl |= TXGBE_PSRCTL_MCHFENA |\n+\t\t\t TXGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type);\n+\t\twr32(hw, TXGBE_PSRCTL, psrctl);\n+\t}\n+\n+\tDEBUGOUT(\"txgbe update mc addr list complete\\n\");\n+\treturn 0;\n+}\n+\n+/**\n+ *  txgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM\n+ *  @hw: pointer to hardware structure\n+ *  @san_mac_offset: SAN MAC address offset\n+ *\n+ *  This function will read the EEPROM location for the SAN MAC address\n+ *  pointer, and returns the value at that location.  This is used in both\n+ *  get and set mac_addr routines.\n+ **/\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+\ts32 err;\n+\n+\tDEBUGFUNC(\"txgbe_get_san_mac_addr_offset\");\n+\n+\t/*\n+\t * First read the EEPROM pointer to see if the MAC addresses are\n+\t * available.\n+\t */\n+\terr = hw->rom.readw_sw(hw, TXGBE_SAN_MAC_ADDR_PTR,\n+\t\t\t\t      san_mac_offset);\n+\tif (err) {\n+\t\tDEBUGOUT(\"eeprom at offset %d failed\",\n+\t\t\t TXGBE_SAN_MAC_ADDR_PTR);\n+\t}\n+\n+\treturn err;\n+}\n+\n+/**\n+ *  txgbe_get_san_mac_addr - SAN MAC address retrieval from the EEPROM\n+ *  @hw: pointer to hardware structure\n+ *  @san_mac_addr: SAN MAC address\n+ *\n+ *  Reads the SAN MAC address from the EEPROM, if it's available.  This is\n+ *  per-port, so set_lan_id() must be called before reading the addresses.\n+ *  set_lan_id() is called by identify_sfp(), but this cannot be relied\n+ *  upon for non-SFP connections, so we must call it here.\n+ **/\n+s32 txgbe_get_san_mac_addr(struct txgbe_hw *hw, u8 *san_mac_addr)\n+{\n+\tu16 san_mac_data, san_mac_offset;\n+\tu8 i;\n+\ts32 err;\n+\n+\tDEBUGFUNC(\"txgbe_get_san_mac_addr\");\n+\n+\t/*\n+\t * First read the EEPROM pointer to see if the MAC addresses are\n+\t * available. If they're not, no point in calling set_lan_id() here.\n+\t */\n+\terr = txgbe_get_san_mac_addr_offset(hw, &san_mac_offset);\n+\tif (err || san_mac_offset == 0 || san_mac_offset == 0xFFFF)\n+\t\tgoto san_mac_addr_out;\n+\n+\t/* apply the port offset to the address offset */\n+\t(hw->bus.func) ? (san_mac_offset += TXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :\n+\t\t\t (san_mac_offset += TXGBE_SAN_MAC_ADDR_PORT0_OFFSET);\n+\tfor (i = 0; i < 3; i++) {\n+\t\terr = hw->rom.read16(hw, san_mac_offset,\n+\t\t\t\t\t      &san_mac_data);\n+\t\tif (err) {\n+\t\t\tDEBUGOUT(\"eeprom read at offset %d failed\",\n+\t\t\t\t san_mac_offset);\n+\t\t\tgoto san_mac_addr_out;\n+\t\t}\n+\t\tsan_mac_addr[i * 2] = (u8)(san_mac_data);\n+\t\tsan_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);\n+\t\tsan_mac_offset++;\n+\t}\n+\treturn 0;\n+\n+san_mac_addr_out:\n+\t/*\n+\t * No addresses available in this EEPROM.  It's not an\n+\t * error though, so just wipe the local address and return.\n+\t */\n+\tfor (i = 0; i < 6; i++)\n+\t\tsan_mac_addr[i] = 0xFF;\n+\treturn 0;\n+}\n+\n+/**\n+ *  txgbe_set_san_mac_addr - Write the SAN MAC address to the EEPROM\n+ *  @hw: pointer to hardware structure\n+ *  @san_mac_addr: SAN MAC address\n+ *\n+ *  Write a SAN MAC address to the EEPROM.\n+ **/\n+s32 txgbe_set_san_mac_addr(struct txgbe_hw *hw, u8 *san_mac_addr)\n+{\n+\ts32 err;\n+\tu16 san_mac_data, san_mac_offset;\n+\tu8 i;\n+\n+\tDEBUGFUNC(\"txgbe_set_san_mac_addr\");\n+\n+\t/* Look for SAN mac address pointer.  If not defined, return */\n+\terr = txgbe_get_san_mac_addr_offset(hw, &san_mac_offset);\n+\tif (err || san_mac_offset == 0 || san_mac_offset == 0xFFFF)\n+\t\treturn TXGBE_ERR_NO_SAN_ADDR_PTR;\n+\n+\t/* Apply the port offset to the address offset */\n+\t(hw->bus.func) ? (san_mac_offset += TXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :\n+\t\t\t (san_mac_offset += TXGBE_SAN_MAC_ADDR_PORT0_OFFSET);\n+\n+\tfor (i = 0; i < 3; i++) {\n+\t\tsan_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8);\n+\t\tsan_mac_data |= (u16)(san_mac_addr[i * 2]);\n+\t\thw->rom.write16(hw, san_mac_offset, san_mac_data);\n+\t\tsan_mac_offset++;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ *  txgbe_init_uta_tables - Initialize the Unicast Table Array\n+ *  @hw: pointer to hardware structure\n+ **/\n+s32 txgbe_init_uta_tables(struct txgbe_hw *hw)\n+{\n+\tint i;\n+\n+\tDEBUGFUNC(\"txgbe_init_uta_tables\");\n+\tDEBUGOUT(\" Clearing UTA\\n\");\n+\n+\tfor (i = 0; i < 128; i++)\n+\t\twr32(hw, TXGBE_UCADDRTBL(i), 0);\n+\n+\treturn 0;\n+}\n+\n /**\n  *  txgbe_need_crosstalk_fix - Determine if we need to do cross talk fix\n  *  @hw: pointer to hardware structure\n@@ -614,10 +1082,17 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw)\n \n \t/* MAC */\n \tmac->init_hw = txgbe_init_hw;\n+\tmac->get_mac_addr = txgbe_get_mac_addr;\n \tmac->reset_hw = txgbe_reset_hw;\n+\tmac->get_san_mac_addr = txgbe_get_san_mac_addr;\n+\tmac->set_san_mac_addr = txgbe_set_san_mac_addr;\n \tmac->autoc_read = txgbe_autoc_read;\n \tmac->autoc_write = txgbe_autoc_write;\n \n+\tmac->set_rar = txgbe_set_rar;\n+\tmac->clear_rar = txgbe_clear_rar;\n+\tmac->init_rx_addrs = txgbe_init_rx_addrs;\n+\tmac->init_uta_tables = txgbe_init_uta_tables;\n \t/* Link */\n \tmac->get_link_capabilities = txgbe_get_link_capabilities_raptor;\n \tmac->check_link = txgbe_check_mac_link;\n@@ -636,6 +1111,7 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw)\n \trom->update_checksum = txgbe_update_eeprom_checksum;\n \trom->calc_checksum = txgbe_calc_eeprom_checksum;\n \n+\tmac->mcft_size\t\t= TXGBE_RAPTOR_MC_TBL_SIZE;\n \tmac->num_rar_entries\t= TXGBE_RAPTOR_RAR_ENTRIES;\n \tmac->max_rx_queues\t= TXGBE_RAPTOR_MAX_RX_QUEUES;\n \tmac->max_tx_queues\t= TXGBE_RAPTOR_MAX_TX_QUEUES;\ndiff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h\nindex 5a64bceeb..510de5cbe 100644\n--- a/drivers/net/txgbe/base/txgbe_hw.h\n+++ b/drivers/net/txgbe/base/txgbe_hw.h\n@@ -8,11 +8,24 @@\n #include \"txgbe_type.h\"\n \n s32 txgbe_init_hw(struct txgbe_hw *hw);\n+s32 txgbe_get_mac_addr(struct txgbe_hw *hw, u8 *mac_addr);\n \n void txgbe_set_lan_id_multi_port(struct txgbe_hw *hw);\n \n+s32 txgbe_set_rar(struct txgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,\n+\t\t\t  u32 enable_addr);\n+s32 txgbe_clear_rar(struct txgbe_hw *hw, u32 index);\n+s32 txgbe_init_rx_addrs(struct txgbe_hw *hw);\n+s32 txgbe_update_mc_addr_list(struct txgbe_hw *hw, u8 *mc_addr_list,\n+\t\t\t\t      u32 mc_addr_count,\n+\t\t\t\t      txgbe_mc_addr_itr func, bool clear);\n+\n s32 txgbe_validate_mac_addr(u8 *mac_addr);\n \n+s32 txgbe_get_san_mac_addr(struct txgbe_hw *hw, u8 *san_mac_addr);\n+s32 txgbe_set_san_mac_addr(struct txgbe_hw *hw, u8 *san_mac_addr);\n+\n+s32 txgbe_init_uta_tables(struct txgbe_hw *hw);\n s32 txgbe_check_mac_link(struct txgbe_hw *hw,\n \t\t\t       u32 *speed,\n \t\t\t       bool *link_up, bool link_up_wait_to_complete);\n@@ -24,6 +37,7 @@ s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw);\n s32 txgbe_setup_mac_link_multispeed_fiber(struct txgbe_hw *hw,\n \t\t\t\t\t  u32 speed,\n \t\t\t\t\t  bool autoneg_wait_to_complete);\n+void txgbe_set_mta(struct txgbe_hw *hw, u8 *mc_addr);\n s32 txgbe_init_shared_code(struct txgbe_hw *hw);\n s32 txgbe_set_mac_type(struct txgbe_hw *hw);\n s32 txgbe_init_ops_pf(struct txgbe_hw *hw);\ndiff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h\nindex 46b9a42f9..ac3aae906 100644\n--- a/drivers/net/txgbe/base/txgbe_type.h\n+++ b/drivers/net/txgbe/base/txgbe_type.h\n@@ -168,6 +168,14 @@ enum txgbe_bus_width {\n \n struct txgbe_hw;\n \n+struct txgbe_addr_filter_info {\n+\tu32 num_mc_addrs;\n+\tu32 rar_used_count;\n+\tu32 mta_in_use;\n+\tu32 overflow_promisc;\n+\tbool user_set_promisc;\n+};\n+\n /* Bus parameters */\n struct txgbe_bus_info {\n \ts32 (*get_bus_info)(struct txgbe_hw *hw);\n@@ -325,13 +333,17 @@ struct txgbe_mac_info {\n \ts32 (*setup_eee)(struct txgbe_hw *hw, bool enable_eee);\n \n \tenum txgbe_mac_type type;\n+\tu8 addr[ETH_ADDR_LEN];\n \tu8 perm_addr[ETH_ADDR_LEN];\n \tu8 san_addr[ETH_ADDR_LEN];\n \t/* prefix for World Wide Node Name (WWNN) */\n \tu16 wwnn_prefix;\n \t/* prefix for World Wide Port Name (WWPN) */\n \tu16 wwpn_prefix;\n-\n+#define TXGBE_MAX_MTA\t\t\t128\n+\tu32 mta_shadow[TXGBE_MAX_MTA];\n+\ts32 mc_filter_type;\n+\tu32 mcft_size;\n \tu32 num_rar_entries;\n \tu32 max_tx_queues;\n \tu32 max_rx_queues;\n@@ -426,6 +438,7 @@ struct txgbe_hw {\n \tvoid IOMEM *hw_addr;\n \tvoid *back;\n \tstruct txgbe_mac_info mac;\n+\tstruct txgbe_addr_filter_info addr_ctrl;\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 15f83d36b..294ba543e 100644\n--- a/drivers/net/txgbe/txgbe_ethdev.c\n+++ b/drivers/net/txgbe/txgbe_ethdev.c\n@@ -10,6 +10,8 @@\n #include <rte_ethdev_pci.h>\n \n #include <rte_interrupts.h>\n+#include <rte_log.h>\n+#include <rte_debug.h>\n #include <rte_pci.h>\n #include <rte_memory.h>\n #include <rte_eal.h>\n@@ -1050,6 +1052,36 @@ txgbe_dev_interrupt_handler(void *param)\n \ttxgbe_dev_interrupt_action(dev, dev->intr_handle);\n }\n \n+static int\n+txgbe_add_rar(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,\n+\t\t\t\tuint32_t index, uint32_t pool)\n+{\n+\tstruct txgbe_hw *hw = TXGBE_DEV_HW(dev);\n+\tuint32_t enable_addr = 1;\n+\n+\treturn txgbe_set_rar(hw, index, mac_addr->addr_bytes,\n+\t\t\t     pool, enable_addr);\n+}\n+\n+static void\n+txgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index)\n+{\n+\tstruct txgbe_hw *hw = TXGBE_DEV_HW(dev);\n+\n+\ttxgbe_clear_rar(hw, index);\n+}\n+\n+static int\n+txgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *addr)\n+{\n+\tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);\n+\n+\ttxgbe_remove_rar(dev, 0);\n+\ttxgbe_add_rar(dev, addr, 0, pci_dev->max_vfs);\n+\n+\treturn 0;\n+}\n+\n /**\n  * set the IVAR registers, mapping interrupt causes to vectors\n  * @param hw\n@@ -1141,11 +1173,41 @@ txgbe_configure_msix(struct rte_eth_dev *dev)\n \t\t\t| TXGBE_ITR_WRDSA);\n }\n \n+static u8 *\n+txgbe_dev_addr_list_itr(__rte_unused struct txgbe_hw *hw,\n+\t\t\tu8 **mc_addr_ptr, u32 *vmdq)\n+{\n+\tu8 *mc_addr;\n+\n+\t*vmdq = 0;\n+\tmc_addr = *mc_addr_ptr;\n+\t*mc_addr_ptr = (mc_addr + sizeof(struct rte_ether_addr));\n+\treturn mc_addr;\n+}\n+\n+int\n+txgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,\n+\t\t\t  struct rte_ether_addr *mc_addr_set,\n+\t\t\t  uint32_t nb_mc_addr)\n+{\n+\tstruct txgbe_hw *hw;\n+\tu8 *mc_addr_list;\n+\n+\thw = TXGBE_DEV_HW(dev);\n+\tmc_addr_list = (u8 *)mc_addr_set;\n+\treturn txgbe_update_mc_addr_list(hw, mc_addr_list, nb_mc_addr,\n+\t\t\t\t\t txgbe_dev_addr_list_itr, TRUE);\n+}\n+\n static const struct eth_dev_ops txgbe_eth_dev_ops = {\n \t.dev_configure              = txgbe_dev_configure,\n \t.dev_infos_get              = txgbe_dev_info_get,\n \t.dev_set_link_up            = txgbe_dev_set_link_up,\n \t.dev_set_link_down          = txgbe_dev_set_link_down,\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,\n+\t.set_mc_addr_list           = txgbe_dev_set_mc_addr_list,\n };\n \n RTE_PMD_REGISTER_PCI(net_txgbe, rte_txgbe_pmd);\ndiff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h\nindex ec8eaaf19..9dd5d4727 100644\n--- a/drivers/net/txgbe/txgbe_ethdev.h\n+++ b/drivers/net/txgbe/txgbe_ethdev.h\n@@ -90,6 +90,9 @@ txgbe_dev_link_update_share(struct rte_eth_dev *dev,\n #define TXGBE_DEFAULT_TX_HTHRESH      0\n #define TXGBE_DEFAULT_TX_WTHRESH      0\n \n+int txgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,\n+\t\t\t\t      struct rte_ether_addr *mc_addr_set,\n+\t\t\t\t      uint32_t nb_mc_addr);\n void txgbe_dev_setup_link_alarm_handler(void *param);\n \n #endif /* _TXGBE_ETHDEV_H_ */\n",
    "prefixes": [
        "v4",
        "18/58"
    ]
}