get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 98296,
    "url": "http://patches.dpdk.org/api/patches/98296/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20210908083758.312055-16-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": "<20210908083758.312055-16-jiawenwu@trustnetic.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210908083758.312055-16-jiawenwu@trustnetic.com",
    "date": "2021-09-08T08:37:41",
    "name": "[15/32] net/ngbe: support MAC filters",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "3d4f481e6d81d850f9d69748b0544deb68905062",
    "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/20210908083758.312055-16-jiawenwu@trustnetic.com/mbox/",
    "series": [
        {
            "id": 18760,
            "url": "http://patches.dpdk.org/api/series/18760/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=18760",
            "date": "2021-09-08T08:37:26",
            "name": "net/ngbe: add many features",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/18760/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/98296/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/98296/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 2C9E9A0C56;\n\tWed,  8 Sep 2021 10:38:05 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id E2F34411D6;\n\tWed,  8 Sep 2021 10:36:55 +0200 (CEST)",
            "from smtpbgbr2.qq.com (smtpbgbr2.qq.com [54.207.22.56])\n by mails.dpdk.org (Postfix) with ESMTP id 5D646411C9\n for <dev@dpdk.org>; Wed,  8 Sep 2021 10:36:53 +0200 (CEST)",
            "from wxdbg.localdomain.com (unknown [183.129.236.74])\n by esmtp6.qq.com (ESMTP) with\n id ; Wed, 08 Sep 2021 16:36:47 +0800 (CST)"
        ],
        "X-QQ-mid": "bizesmtp47t1631090208ted8oklj",
        "X-QQ-SSF": "01400000002000E0G000B00A0000000",
        "X-QQ-FEAT": "hoArX50alxFuEuFGsLc+9QaGhgq31w4N2Ug6oCZXP5t9dmj1+KmnoiBdNfOw3\n ZrXaKWztQp84KBeHgrOd3e0NG96Xgd7HDUvB8AClDha/ieYBkfx6eNKvk++1yS+3MCwhYRL\n HLh4nrTCONwvW6vseXdYcvJeQCi0StkQonoCMr3H/WceTFs3AH4eFWvrxurnw15pnEPAhNa\n 4GF1F1F2x7y5TL3c3p88lxtnz3XE3hgymmHoBHeEQKL0B2HK2Xio0ze7AuqgcJ49rYu9xq/\n srZmvEjZZMD5M2pzYfGIZDWFwSYVUV5VuoFo5czkI1HFrURZBTmtFx21orgKHlQCSFg5Aw0\n NW76UdyG1HwfPuetqWvFQGII/pwETCrLFfNacyC",
        "X-QQ-GoodBg": "2",
        "From": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "To": "dev@dpdk.org",
        "Cc": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "Date": "Wed,  8 Sep 2021 16:37:41 +0800",
        "Message-Id": "<20210908083758.312055-16-jiawenwu@trustnetic.com>",
        "X-Mailer": "git-send-email 2.27.0",
        "In-Reply-To": "<20210908083758.312055-1-jiawenwu@trustnetic.com>",
        "References": "<20210908083758.312055-1-jiawenwu@trustnetic.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-QQ-SENDSIZE": "520",
        "Feedback-ID": "bizesmtp:trustnetic.com:qybgforeign:qybgforeign2",
        "X-QQ-Bgrelay": "1",
        "Subject": "[dpdk-dev] [PATCH 15/32] net/ngbe: support MAC filters",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "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 addresses to filter incoming packets, support to set\nmulticast addresses to filter. And support to set unicast table array.\n\nSigned-off-by: Jiawen Wu <jiawenwu@trustnetic.com>\n---\n doc/guides/nics/features/ngbe.ini  |   2 +\n doc/guides/nics/ngbe.rst           |   1 +\n drivers/net/ngbe/base/ngbe_dummy.h |   6 +\n drivers/net/ngbe/base/ngbe_hw.c    | 135 +++++++++++++++++++++-\n drivers/net/ngbe/base/ngbe_hw.h    |   4 +\n drivers/net/ngbe/base/ngbe_type.h  |  11 ++\n drivers/net/ngbe/ngbe_ethdev.c     | 175 +++++++++++++++++++++++++++++\n drivers/net/ngbe/ngbe_ethdev.h     |  13 +++\n 8 files changed, 346 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/doc/guides/nics/features/ngbe.ini b/doc/guides/nics/features/ngbe.ini\nindex d14469eb43..4b22dc683a 100644\n--- a/doc/guides/nics/features/ngbe.ini\n+++ b/doc/guides/nics/features/ngbe.ini\n@@ -15,6 +15,8 @@ Scattered Rx         = Y\n TSO                  = Y\n Promiscuous mode     = Y\n Allmulticast mode    = Y\n+Unicast MAC filter   = Y\n+Multicast MAC filter = Y\n CRC offload          = P\n VLAN offload         = P\n QinQ offload         = P\ndiff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst\nindex 2783c4a3c4..4d01c27064 100644\n--- a/doc/guides/nics/ngbe.rst\n+++ b/doc/guides/nics/ngbe.rst\n@@ -11,6 +11,7 @@ for Wangxun 1 Gigabit Ethernet NICs.\n Features\n --------\n \n+- MAC filtering\n - Packet type information\n - Checksum offload\n - VLAN/QinQ stripping and inserting\ndiff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h\nindex 689480cc9a..fe2d53f312 100644\n--- a/drivers/net/ngbe/base/ngbe_dummy.h\n+++ b/drivers/net/ngbe/base/ngbe_dummy.h\n@@ -127,6 +127,11 @@ static inline s32 ngbe_mac_init_rx_addrs_dummy(struct ngbe_hw *TUP0)\n {\n \treturn NGBE_ERR_OPS_DUMMY;\n }\n+static inline s32 ngbe_mac_update_mc_addr_list_dummy(struct ngbe_hw *TUP0,\n+\t\t\tu8 *TUP1, u32 TUP2, ngbe_mc_addr_itr TUP3, bool TUP4)\n+{\n+\treturn NGBE_ERR_OPS_DUMMY;\n+}\n static inline s32 ngbe_mac_init_thermal_ssth_dummy(struct ngbe_hw *TUP0)\n {\n \treturn NGBE_ERR_OPS_DUMMY;\n@@ -203,6 +208,7 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw)\n \thw->mac.set_vmdq = ngbe_mac_set_vmdq_dummy;\n \thw->mac.clear_vmdq = ngbe_mac_clear_vmdq_dummy;\n \thw->mac.init_rx_addrs = ngbe_mac_init_rx_addrs_dummy;\n+\thw->mac.update_mc_addr_list = ngbe_mac_update_mc_addr_list_dummy;\n \thw->mac.init_thermal_sensor_thresh = ngbe_mac_init_thermal_ssth_dummy;\n \thw->mac.check_overtemp = ngbe_mac_check_overtemp_dummy;\n \thw->phy.identify = ngbe_phy_identify_dummy;\ndiff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c\nindex 0dabb6c1c7..897baf179d 100644\n--- a/drivers/net/ngbe/base/ngbe_hw.c\n+++ b/drivers/net/ngbe/base/ngbe_hw.c\n@@ -567,6 +567,138 @@ s32 ngbe_init_rx_addrs(struct ngbe_hw *hw)\n \treturn 0;\n }\n \n+/**\n+ *  ngbe_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 ngbe_mta_vector(struct ngbe_hw *hw, u8 *mc_addr)\n+{\n+\tu32 vector = 0;\n+\n+\tDEBUGFUNC(\"ngbe_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+ *  ngbe_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 ngbe_set_mta(struct ngbe_hw *hw, u8 *mc_addr)\n+{\n+\tu32 vector;\n+\tu32 vector_bit;\n+\tu32 vector_reg;\n+\n+\tDEBUGFUNC(\"ngbe_set_mta\");\n+\n+\thw->addr_ctrl.mta_in_use++;\n+\n+\tvector = ngbe_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+ *  ngbe_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 ngbe_update_mc_addr_list(struct ngbe_hw *hw, u8 *mc_addr_list,\n+\t\t\t\t      u32 mc_addr_count, ngbe_mc_addr_itr next,\n+\t\t\t\t      bool clear)\n+{\n+\tu32 i;\n+\tu32 vmdq;\n+\n+\tDEBUGFUNC(\"ngbe_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\tngbe_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, NGBE_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, NGBE_PSRCTL);\n+\t\tpsrctl &= ~(NGBE_PSRCTL_ADHF12_MASK | NGBE_PSRCTL_MCHFENA);\n+\t\tpsrctl |= NGBE_PSRCTL_MCHFENA |\n+\t\t\t NGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type);\n+\t\twr32(hw, NGBE_PSRCTL, psrctl);\n+\t}\n+\n+\tDEBUGOUT(\"ngbe update mc addr list complete\\n\");\n+\treturn 0;\n+}\n+\n /**\n  *  ngbe_acquire_swfw_sync - Acquire SWFW semaphore\n  *  @hw: pointer to hardware structure\n@@ -1099,10 +1231,11 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw)\n \n \tmac->disable_sec_rx_path = ngbe_disable_sec_rx_path;\n \tmac->enable_sec_rx_path = ngbe_enable_sec_rx_path;\n-\t/* RAR */\n+\t/* RAR, Multicast */\n \tmac->set_rar = ngbe_set_rar;\n \tmac->clear_rar = ngbe_clear_rar;\n \tmac->init_rx_addrs = ngbe_init_rx_addrs;\n+\tmac->update_mc_addr_list = ngbe_update_mc_addr_list;\n \tmac->set_vmdq = ngbe_set_vmdq;\n \tmac->clear_vmdq = ngbe_clear_vmdq;\n \ndiff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h\nindex 6a08c02bee..f06baa4395 100644\n--- a/drivers/net/ngbe/base/ngbe_hw.h\n+++ b/drivers/net/ngbe/base/ngbe_hw.h\n@@ -35,6 +35,9 @@ s32 ngbe_set_rar(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq,\n \t\t\t  u32 enable_addr);\n s32 ngbe_clear_rar(struct ngbe_hw *hw, u32 index);\n s32 ngbe_init_rx_addrs(struct ngbe_hw *hw);\n+s32 ngbe_update_mc_addr_list(struct ngbe_hw *hw, u8 *mc_addr_list,\n+\t\t\t\t      u32 mc_addr_count,\n+\t\t\t\t      ngbe_mc_addr_itr func, bool clear);\n s32 ngbe_disable_sec_rx_path(struct ngbe_hw *hw);\n s32 ngbe_enable_sec_rx_path(struct ngbe_hw *hw);\n \n@@ -50,6 +53,7 @@ s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw);\n s32 ngbe_mac_check_overtemp(struct ngbe_hw *hw);\n void ngbe_disable_rx(struct ngbe_hw *hw);\n void ngbe_enable_rx(struct ngbe_hw *hw);\n+void ngbe_set_mta(struct ngbe_hw *hw, u8 *mc_addr);\n s32 ngbe_init_shared_code(struct ngbe_hw *hw);\n s32 ngbe_set_mac_type(struct ngbe_hw *hw);\n s32 ngbe_init_ops_pf(struct ngbe_hw *hw);\ndiff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h\nindex 2586eaf36a..3e62dde707 100644\n--- a/drivers/net/ngbe/base/ngbe_type.h\n+++ b/drivers/net/ngbe/base/ngbe_type.h\n@@ -11,6 +11,7 @@\n #define NGBE_FRAME_SIZE_MAX       (9728) /* Maximum frame size, +FCS */\n #define NGBE_FRAME_SIZE_DFT       (1522) /* Default frame size, +FCS */\n #define NGBE_MAX_QP               (8)\n+#define NGBE_MAX_UTA              128\n \n #define NGBE_ALIGN\t\t128 /* as intel did */\n #define NGBE_ISB_SIZE\t\t16\n@@ -68,6 +69,7 @@ enum ngbe_media_type {\n struct ngbe_hw;\n \n struct ngbe_addr_filter_info {\n+\tu32 num_mc_addrs;\n \tu32 mta_in_use;\n };\n \n@@ -200,6 +202,10 @@ struct ngbe_hw_stats {\n \n };\n \n+/* iterator type for walking multicast address lists */\n+typedef u8* (*ngbe_mc_addr_itr) (struct ngbe_hw *hw, u8 **mc_addr_ptr,\n+\t\t\t\t  u32 *vmdq);\n+\n struct ngbe_rom_info {\n \ts32 (*init_params)(struct ngbe_hw *hw);\n \ts32 (*read32)(struct ngbe_hw *hw, u32 addr, u32 *data);\n@@ -243,6 +249,9 @@ struct ngbe_mac_info {\n \ts32 (*set_vmdq)(struct ngbe_hw *hw, u32 rar, u32 vmdq);\n \ts32 (*clear_vmdq)(struct ngbe_hw *hw, u32 rar, u32 vmdq);\n \ts32 (*init_rx_addrs)(struct ngbe_hw *hw);\n+\ts32 (*update_mc_addr_list)(struct ngbe_hw *hw, u8 *mc_addr_list,\n+\t\t\t\t      u32 mc_addr_count,\n+\t\t\t\t      ngbe_mc_addr_itr func, bool clear);\n \n \t/* Manageability interface */\n \ts32 (*init_thermal_sensor_thresh)(struct ngbe_hw *hw);\n@@ -251,6 +260,8 @@ struct ngbe_mac_info {\n \tenum ngbe_mac_type type;\n \tu8 addr[ETH_ADDR_LEN];\n \tu8 perm_addr[ETH_ADDR_LEN];\n+#define NGBE_MAX_MTA\t\t\t128\n+\tu32 mta_shadow[NGBE_MAX_MTA];\n \ts32 mc_filter_type;\n \tu32 mcft_size;\n \tu32 num_rar_entries;\ndiff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c\nindex 52642161b7..d076ba8036 100644\n--- a/drivers/net/ngbe/ngbe_ethdev.c\n+++ b/drivers/net/ngbe/ngbe_ethdev.c\n@@ -1553,12 +1553,16 @@ ngbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)\n static int\n ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)\n {\n+\tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);\n \tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n \n \tdev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues;\n \tdev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues;\n \tdev_info->min_rx_bufsize = 1024;\n \tdev_info->max_rx_pktlen = 15872;\n+\tdev_info->max_mac_addrs = hw->mac.num_rar_entries;\n+\tdev_info->max_hash_mac_addrs = NGBE_VMDQ_NUM_UC_MAC;\n+\tdev_info->max_vfs = pci_dev->max_vfs;\n \tdev_info->rx_queue_offload_capa = ngbe_get_rx_queue_offloads(dev);\n \tdev_info->rx_offload_capa = (ngbe_get_rx_port_offloads(dev) |\n \t\t\t\t     dev_info->rx_queue_offload_capa);\n@@ -2055,6 +2059,36 @@ ngbe_dev_interrupt_handler(void *param)\n \tngbe_dev_interrupt_action(dev);\n }\n \n+static int\n+ngbe_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 ngbe_hw *hw = ngbe_dev_hw(dev);\n+\tuint32_t enable_addr = 1;\n+\n+\treturn ngbe_set_rar(hw, index, mac_addr->addr_bytes,\n+\t\t\t     pool, enable_addr);\n+}\n+\n+static void\n+ngbe_remove_rar(struct rte_eth_dev *dev, uint32_t index)\n+{\n+\tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n+\n+\tngbe_clear_rar(hw, index);\n+}\n+\n+static int\n+ngbe_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+\tngbe_remove_rar(dev, 0);\n+\tngbe_add_rar(dev, addr, 0, pci_dev->max_vfs);\n+\n+\treturn 0;\n+}\n+\n static int\n ngbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)\n {\n@@ -2095,6 +2129,116 @@ ngbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)\n \treturn 0;\n }\n \n+static uint32_t\n+ngbe_uta_vector(struct ngbe_hw *hw, struct rte_ether_addr *uc_addr)\n+{\n+\tuint32_t vector = 0;\n+\n+\tswitch (hw->mac.mc_filter_type) {\n+\tcase 0:   /* use bits [47:36] of the address */\n+\t\tvector = ((uc_addr->addr_bytes[4] >> 4) |\n+\t\t\t(((uint16_t)uc_addr->addr_bytes[5]) << 4));\n+\t\tbreak;\n+\tcase 1:   /* use bits [46:35] of the address */\n+\t\tvector = ((uc_addr->addr_bytes[4] >> 3) |\n+\t\t\t(((uint16_t)uc_addr->addr_bytes[5]) << 5));\n+\t\tbreak;\n+\tcase 2:   /* use bits [45:34] of the address */\n+\t\tvector = ((uc_addr->addr_bytes[4] >> 2) |\n+\t\t\t(((uint16_t)uc_addr->addr_bytes[5]) << 6));\n+\t\tbreak;\n+\tcase 3:   /* use bits [43:32] of the address */\n+\t\tvector = ((uc_addr->addr_bytes[4]) |\n+\t\t\t(((uint16_t)uc_addr->addr_bytes[5]) << 8));\n+\t\tbreak;\n+\tdefault:  /* Invalid mc_filter_type */\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+static int\n+ngbe_uc_hash_table_set(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_ether_addr *mac_addr, uint8_t on)\n+{\n+\tuint32_t vector;\n+\tuint32_t uta_idx;\n+\tuint32_t reg_val;\n+\tuint32_t uta_mask;\n+\tuint32_t psrctl;\n+\n+\tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n+\tstruct ngbe_uta_info *uta_info = NGBE_DEV_UTA_INFO(dev);\n+\n+\tvector = ngbe_uta_vector(hw, mac_addr);\n+\tuta_idx = (vector >> 5) & 0x7F;\n+\tuta_mask = 0x1UL << (vector & 0x1F);\n+\n+\tif (!!on == !!(uta_info->uta_shadow[uta_idx] & uta_mask))\n+\t\treturn 0;\n+\n+\treg_val = rd32(hw, NGBE_UCADDRTBL(uta_idx));\n+\tif (on) {\n+\t\tuta_info->uta_in_use++;\n+\t\treg_val |= uta_mask;\n+\t\tuta_info->uta_shadow[uta_idx] |= uta_mask;\n+\t} else {\n+\t\tuta_info->uta_in_use--;\n+\t\treg_val &= ~uta_mask;\n+\t\tuta_info->uta_shadow[uta_idx] &= ~uta_mask;\n+\t}\n+\n+\twr32(hw, NGBE_UCADDRTBL(uta_idx), reg_val);\n+\n+\tpsrctl = rd32(hw, NGBE_PSRCTL);\n+\tif (uta_info->uta_in_use > 0)\n+\t\tpsrctl |= NGBE_PSRCTL_UCHFENA;\n+\telse\n+\t\tpsrctl &= ~NGBE_PSRCTL_UCHFENA;\n+\n+\tpsrctl &= ~NGBE_PSRCTL_ADHF12_MASK;\n+\tpsrctl |= NGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type);\n+\twr32(hw, NGBE_PSRCTL, psrctl);\n+\n+\treturn 0;\n+}\n+\n+static int\n+ngbe_uc_all_hash_table_set(struct rte_eth_dev *dev, uint8_t on)\n+{\n+\tstruct ngbe_hw *hw = ngbe_dev_hw(dev);\n+\tstruct ngbe_uta_info *uta_info = NGBE_DEV_UTA_INFO(dev);\n+\tuint32_t psrctl;\n+\tint i;\n+\n+\tif (on) {\n+\t\tfor (i = 0; i < ETH_VMDQ_NUM_UC_HASH_ARRAY; i++) {\n+\t\t\tuta_info->uta_shadow[i] = ~0;\n+\t\t\twr32(hw, NGBE_UCADDRTBL(i), ~0);\n+\t\t}\n+\t} else {\n+\t\tfor (i = 0; i < ETH_VMDQ_NUM_UC_HASH_ARRAY; i++) {\n+\t\t\tuta_info->uta_shadow[i] = 0;\n+\t\t\twr32(hw, NGBE_UCADDRTBL(i), 0);\n+\t\t}\n+\t}\n+\n+\tpsrctl = rd32(hw, NGBE_PSRCTL);\n+\tif (on)\n+\t\tpsrctl |= NGBE_PSRCTL_UCHFENA;\n+\telse\n+\t\tpsrctl &= ~NGBE_PSRCTL_UCHFENA;\n+\n+\tpsrctl &= ~NGBE_PSRCTL_ADHF12_MASK;\n+\tpsrctl |= NGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type);\n+\twr32(hw, NGBE_PSRCTL, psrctl);\n+\n+\treturn 0;\n+}\n+\n static int\n ngbe_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)\n {\n@@ -2220,6 +2364,31 @@ ngbe_configure_msix(struct rte_eth_dev *dev)\n \t\t\t| NGBE_ITR_WRDSA);\n }\n \n+static u8 *\n+ngbe_dev_addr_list_itr(__rte_unused struct ngbe_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+ngbe_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 ngbe_hw *hw = ngbe_dev_hw(dev);\n+\tu8 *mc_addr_list;\n+\n+\tmc_addr_list = (u8 *)mc_addr_set;\n+\treturn hw->mac.update_mc_addr_list(hw, mc_addr_list, nb_mc_addr,\n+\t\t\t\t\t ngbe_dev_addr_list_itr, TRUE);\n+}\n+\n static const struct eth_dev_ops ngbe_eth_dev_ops = {\n \t.dev_configure              = ngbe_dev_configure,\n \t.dev_infos_get              = ngbe_dev_info_get,\n@@ -2253,6 +2422,12 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = {\n \t.rx_queue_release           = ngbe_dev_rx_queue_release,\n \t.tx_queue_setup             = ngbe_dev_tx_queue_setup,\n \t.tx_queue_release           = ngbe_dev_tx_queue_release,\n+\t.mac_addr_add               = ngbe_add_rar,\n+\t.mac_addr_remove            = ngbe_remove_rar,\n+\t.mac_addr_set               = ngbe_set_default_mac_addr,\n+\t.uc_hash_table_set          = ngbe_uc_hash_table_set,\n+\t.uc_all_hash_table_set      = ngbe_uc_all_hash_table_set,\n+\t.set_mc_addr_list           = ngbe_dev_set_mc_addr_list,\n };\n \n RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd);\ndiff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h\nindex 1527dcc022..65dad4a72b 100644\n--- a/drivers/net/ngbe/ngbe_ethdev.h\n+++ b/drivers/net/ngbe/ngbe_ethdev.h\n@@ -57,6 +57,12 @@ struct ngbe_hwstrip {\n \tuint32_t bitmap[NGBE_HWSTRIP_BITMAP_SIZE];\n };\n \n+struct ngbe_uta_info {\n+\tuint8_t  uc_filter_type;\n+\tuint16_t uta_in_use;\n+\tuint32_t uta_shadow[NGBE_MAX_UTA];\n+};\n+\n /*\n  * Structure to store private data for each driver instance (for each port).\n  */\n@@ -67,6 +73,7 @@ struct ngbe_adapter {\n \tstruct ngbe_stat_mappings  stat_mappings;\n \tstruct ngbe_vfta           shadow_vfta;\n \tstruct ngbe_hwstrip        hwstrip;\n+\tstruct ngbe_uta_info       uta_info;\n \tbool                       rx_bulk_alloc_allowed;\n };\n \n@@ -107,6 +114,9 @@ ngbe_dev_intr(struct rte_eth_dev *dev)\n \n #define NGBE_DEV_HWSTRIP(dev) \\\n \t(&((struct ngbe_adapter *)(dev)->data->dev_private)->hwstrip)\n+#define NGBE_DEV_UTA_INFO(dev) \\\n+\t(&((struct ngbe_adapter *)(dev)->data->dev_private)->uta_info)\n+\n \n /*\n  * Rx/Tx function prototypes\n@@ -209,6 +219,9 @@ struct rte_ngbe_xstats_name_off {\n };\n \n const uint32_t *ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev);\n+int ngbe_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 ngbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev,\n \t\tuint16_t queue, bool on);\n void ngbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev,\n",
    "prefixes": [
        "15/32"
    ]
}