Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1190617/?format=api
{ "id": 1190617, "url": "http://patchwork.ozlabs.org/api/patches/1190617/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20191106100541.48639-3-anthony.l.nguyen@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20191106100541.48639-3-anthony.l.nguyen@intel.com>", "list_archive_url": null, "date": "2019-11-06T10:05:29", "name": "[S32,v3,03/15] ice: Implement DCBNL support", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "8161be7b3b69d5df2618f1590c533b9bb2398976", "submitter": { "id": 68875, "url": "http://patchwork.ozlabs.org/api/people/68875/?format=api", "name": "Tony Nguyen", "email": "anthony.l.nguyen@intel.com" }, "delegate": { "id": 68, "url": "http://patchwork.ozlabs.org/api/users/68/?format=api", "username": "jtkirshe", "first_name": "Jeff", "last_name": "Kirsher", "email": "jeffrey.t.kirsher@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20191106100541.48639-3-anthony.l.nguyen@intel.com/mbox/", "series": [ { "id": 141151, "url": "http://patchwork.ozlabs.org/api/series/141151/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=141151", "date": "2019-11-06T10:05:27", "name": "[S32,v3,01/15] ice: Use ice_ena_vsi and ice_dis_vsi in DCB configuration flow", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/141151/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1190617/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1190617/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "ozlabs.org; spf=pass (sender SPF authorized)\n\tsmtp.mailfrom=osuosl.org (client-ip=140.211.166.133;\n\thelo=hemlock.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com" ], "Received": [ "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 477Zxl6yPmz9sP4\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 7 Nov 2019 05:36:43 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 90AC68A7E8;\n\tWed, 6 Nov 2019 18:36:42 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id q3C4COj1+509; Wed, 6 Nov 2019 18:36:38 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 5D8058A7F8;\n\tWed, 6 Nov 2019 18:36:38 +0000 (UTC)", "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id D8FFD1BF3FB\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 6 Nov 2019 18:36:33 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 720DB8A85B\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 6 Nov 2019 18:36:33 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id PL0X9J-ipgoc for <intel-wired-lan@lists.osuosl.org>;\n\tWed, 6 Nov 2019 18:36:29 +0000 (UTC)", "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id F3F968A7ED\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 6 Nov 2019 18:36:28 +0000 (UTC)", "from orsmga006.jf.intel.com ([10.7.209.51])\n\tby fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t06 Nov 2019 10:36:28 -0800", "from unknown (HELO localhost.jf.intel.com) ([10.166.244.174])\n\tby orsmga006.jf.intel.com with ESMTP; 06 Nov 2019 10:36:27 -0800" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.68,275,1569308400\"; d=\"scan'208\";a=\"205918151\"", "From": "Tony Nguyen <anthony.l.nguyen@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Wed, 6 Nov 2019 02:05:29 -0800", "Message-Id": "<20191106100541.48639-3-anthony.l.nguyen@intel.com>", "X-Mailer": "git-send-email 2.20.1", "In-Reply-To": "<20191106100541.48639-1-anthony.l.nguyen@intel.com>", "References": "<20191106100541.48639-1-anthony.l.nguyen@intel.com>", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [PATCH S32 v3 03/15] ice: Implement DCBNL support", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "From: Dave Ertman <david.m.ertman@intel.com>\n\nImplement interface layer for the DCBNL subsystem. These are the functions\nto support the callbacks defined in the dcbnl_rtnl_ops struct. These\ncallbacks are going to be used to interface with the DCB settings of the\ndevice. Implementation of dcb_nl set functions and supporting SW DCB\nfunctions.\n\nSigned-off-by: Dave Ertman <david.m.ertman@intel.com>\nSigned-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>\n---\n drivers/net/ethernet/intel/ice/Makefile | 2 +-\n drivers/net/ethernet/intel/ice/ice.h | 2 +\n drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 15 +-\n drivers/net/ethernet/intel/ice/ice_dcb_lib.h | 15 +-\n drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 933 ++++++++++++++++++\n drivers/net/ethernet/intel/ice/ice_dcb_nl.h | 19 +\n .../net/ethernet/intel/ice/ice_hw_autogen.h | 3 +\n drivers/net/ethernet/intel/ice/ice_lib.c | 1 +\n drivers/net/ethernet/intel/ice/ice_main.c | 6 +\n 9 files changed, 991 insertions(+), 5 deletions(-)\n create mode 100644 drivers/net/ethernet/intel/ice/ice_dcb_nl.c\n create mode 100644 drivers/net/ethernet/intel/ice/ice_dcb_nl.h", "diff": "diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile\nindex df5a9699276a..7cb829132d28 100644\n--- a/drivers/net/ethernet/intel/ice/Makefile\n+++ b/drivers/net/ethernet/intel/ice/Makefile\n@@ -20,5 +20,5 @@ ice-y := ice_main.o\t\\\n \t ice_flex_pipe.o\t\\\n \t ice_ethtool.o\n ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o\n-ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_lib.o\n+ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o\n ice-$(CONFIG_XDP_SOCKETS) += ice_xsk.o\ndiff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex 53a4870dd271..44466d4da057 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -180,6 +180,7 @@ enum ice_state {\n \t__ICE_NEEDS_RESTART,\n \t__ICE_PREPARED_FOR_RESET,\t/* set by driver when prepared */\n \t__ICE_RESET_OICR_RECV,\t\t/* set by driver after rcv reset OICR */\n+\t__ICE_DCBNL_DEVRESET,\t\t/* set by dcbnl devreset */\n \t__ICE_PFR_REQ,\t\t\t/* set by driver and peers */\n \t__ICE_CORER_REQ,\t\t/* set by driver and peers */\n \t__ICE_GLOBR_REQ,\t\t/* set by driver and peers */\n@@ -367,6 +368,7 @@ struct ice_pf {\n \tstruct work_struct serv_task;\n \tstruct mutex avail_q_mutex;\t/* protects access to avail_[rx|tx]qs */\n \tstruct mutex sw_mutex;\t\t/* lock for protecting VSI alloc flow */\n+\tstruct mutex tc_mutex;\t\t/* lock to protect TC changes */\n \tu32 msg_enable;\n \tu32 hw_csum_rx_error;\n \tu32 oicr_idx;\t\t/* Other interrupt cause MSIX vector index */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c\nindex c00c68bacadb..9448a289363d 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c\n+++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c\n@@ -2,6 +2,7 @@\n /* Copyright (c) 2019, Intel Corporation. */\n \n #include \"ice_dcb_lib.h\"\n+#include \"ice_dcb_nl.h\"\n \n static void ice_pf_dcb_recfg(struct ice_pf *pf);\n \n@@ -155,16 +156,19 @@ void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi)\n * @new_cfg: DCBX config to apply\n * @locked: is the RTNL held\n */\n-static\n int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)\n {\n-\tstruct ice_dcbx_cfg *old_cfg, *curr_cfg;\n \tstruct ice_aqc_port_ets_elem buf = { 0 };\n+\tstruct ice_dcbx_cfg *old_cfg, *curr_cfg;\n+\tint ret = ICE_DCB_NO_HW_CHG;\n \tstruct ice_vsi *pf_vsi;\n-\tint ret = 0;\n \n \tcurr_cfg = &pf->hw.port_info->local_dcbx_cfg;\n \n+\t/* FW does not care if change happened */\n+\tif (!pf->hw.port_info->is_sw_lldp)\n+\t\tret = ICE_DCB_HW_CHG_RST;\n+\n \t/* Enable DCB tagging only when more than one TC */\n \tif (ice_dcb_get_num_tc(new_cfg) > 1) {\n \t\tdev_dbg(&pf->pdev->dev, \"DCB tagging enabled (num TC > 1)\\n\");\n@@ -184,6 +188,7 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)\n \tif (!old_cfg)\n \t\treturn -ENOMEM;\n \n+\tdev_info(&pf->pdev->dev, \"Commit DCB Configuration to the hardware\\n\");\n \tpf_vsi = ice_get_main_vsi(pf);\n \tif (!pf_vsi) {\n \t\tdev_dbg(&pf->pdev->dev, \"PF VSI doesn't exist\\n\");\n@@ -200,6 +205,7 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)\n \n \tmemcpy(curr_cfg, new_cfg, sizeof(*curr_cfg));\n \tmemcpy(&curr_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));\n+\tmemcpy(&new_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));\n \n \t/* Only send new config to HW if we are in SW LLDP mode. Otherwise,\n \t * the new config came from the HW in the first place.\n@@ -559,6 +565,8 @@ static void ice_pf_dcb_recfg(struct ice_pf *pf)\n \t\t}\n \n \t\tice_vsi_map_rings_to_vectors(pf->vsi[v]);\n+\t\tif (pf->vsi[v]->type == ICE_VSI_PF)\n+\t\t\tice_dcbnl_set_all(pf->vsi[v]);\n \t}\n }\n \n@@ -770,6 +778,7 @@ ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,\n \n \tneed_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,\n \t\t\t\t\t &pi->local_dcbx_cfg);\n+\tice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->local_dcbx_cfg);\n \tif (!need_reconfig)\n \t\treturn;\n \ndiff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.h b/drivers/net/ethernet/intel/ice/ice_dcb_lib.h\nindex 59e40cf2dd73..e90e25b7da77 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.h\n+++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.h\n@@ -9,12 +9,17 @@\n #include \"ice_lib.h\"\n \n #ifdef CONFIG_DCB\n-#define ICE_TC_MAX_BW 100 /* Default Max BW percentage */\n+#define ICE_TC_MAX_BW\t\t100 /* Default Max BW percentage */\n+#define ICE_DCB_HW_CHG_RST\t0 /* DCB configuration changed with reset */\n+#define ICE_DCB_NO_HW_CHG\t1 /* DCB configuration did not change */\n+#define ICE_DCB_HW_CHG\t\t2 /* DCB configuration changed, no reset */\n \n void ice_dcb_rebuild(struct ice_pf *pf);\n u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg);\n u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg);\n u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index);\n+int\n+ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked);\n void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi);\n int ice_init_pf_dcb(struct ice_pf *pf, bool locked);\n void ice_update_dcb_stats(struct ice_pf *pf);\n@@ -57,6 +62,14 @@ ice_init_pf_dcb(struct ice_pf *pf, bool __always_unused locked)\n \treturn -EOPNOTSUPP;\n }\n \n+static inline int\n+ice_pf_dcb_cfg(struct ice_pf __always_unused *pf,\n+\t struct ice_dcbx_cfg __always_unused *new_cfg,\n+\t bool __always_unused locked)\n+{\n+\treturn -EOPNOTSUPP;\n+}\n+\n static inline int\n ice_tx_prepare_vlan_flags_dcb(struct ice_ring __always_unused *tx_ring,\n \t\t\t struct ice_tx_buf __always_unused *first)\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c\nnew file mode 100644\nindex 000000000000..717efbb7c4d1\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c\n@@ -0,0 +1,933 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/* Copyright (c) 2019, Intel Corporation. */\n+\n+#include \"ice.h\"\n+#include \"ice_dcb.h\"\n+#include \"ice_dcb_lib.h\"\n+#include \"ice_dcb_nl.h\"\n+#include <net/dcbnl.h>\n+\n+#define ICE_APP_PROT_ID_ROCE\t0x8915\n+\n+/**\n+ * ice_dcbnl_devreset - perform enough of a ifdown/ifup to sync DCBNL info\n+ * @netdev: device associated with interface that needs reset\n+ */\n+static void ice_dcbnl_devreset(struct net_device *netdev)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\n+\twhile (ice_is_reset_in_progress(pf->state))\n+\t\tusleep_range(1000, 2000);\n+\n+\tset_bit(__ICE_DCBNL_DEVRESET, pf->state);\n+\tdev_close(netdev);\n+\tnetdev_state_change(netdev);\n+\tdev_open(netdev, NULL);\n+\tnetdev_state_change(netdev);\n+\tclear_bit(__ICE_DCBNL_DEVRESET, pf->state);\n+}\n+\n+/**\n+ * ice_dcbnl_getets - retrieve local ETS configuration\n+ * @netdev: the relevant netdev\n+ * @ets: struct to hold ETS configuration\n+ */\n+static int ice_dcbnl_getets(struct net_device *netdev, struct ieee_ets *ets)\n+{\n+\tstruct ice_dcbx_cfg *dcbxcfg;\n+\tstruct ice_port_info *pi;\n+\tstruct ice_pf *pf;\n+\n+\tpf = ice_netdev_to_pf(netdev);\n+\tpi = pf->hw.port_info;\n+\tdcbxcfg = &pi->local_dcbx_cfg;\n+\n+\tets->willing = dcbxcfg->etscfg.willing;\n+\tets->ets_cap = dcbxcfg->etscfg.maxtcs;\n+\tets->cbs = dcbxcfg->etscfg.cbs;\n+\tmemcpy(ets->tc_tx_bw, dcbxcfg->etscfg.tcbwtable, sizeof(ets->tc_tx_bw));\n+\tmemcpy(ets->tc_rx_bw, dcbxcfg->etscfg.tcbwtable, sizeof(ets->tc_rx_bw));\n+\tmemcpy(ets->tc_tsa, dcbxcfg->etscfg.tsatable, sizeof(ets->tc_tsa));\n+\tmemcpy(ets->prio_tc, dcbxcfg->etscfg.prio_table, sizeof(ets->prio_tc));\n+\tmemcpy(ets->tc_reco_bw, dcbxcfg->etsrec.tcbwtable,\n+\t sizeof(ets->tc_reco_bw));\n+\tmemcpy(ets->tc_reco_tsa, dcbxcfg->etsrec.tsatable,\n+\t sizeof(ets->tc_reco_tsa));\n+\tmemcpy(ets->reco_prio_tc, dcbxcfg->etscfg.prio_table,\n+\t sizeof(ets->reco_prio_tc));\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_dcbnl_setets - set IEEE ETS configuration\n+ * @netdev: pointer to relevant netdev\n+ * @ets: struct to hold ETS configuration\n+ */\n+static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_dcbx_cfg *new_cfg;\n+\tint bwcfg = 0, bwrec = 0;\n+\tint err, i, max_tc = 0;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))\n+\t\treturn -EINVAL;\n+\n+\tnew_cfg = &pf->hw.port_info->desired_dcbx_cfg;\n+\n+\tmutex_lock(&pf->tc_mutex);\n+\n+\tnew_cfg->etscfg.willing = ets->willing;\n+\tnew_cfg->etscfg.cbs = ets->cbs;\n+\tice_for_each_traffic_class(i) {\n+\t\tnew_cfg->etscfg.tcbwtable[i] = ets->tc_tx_bw[i];\n+\t\tbwcfg += ets->tc_tx_bw[i];\n+\t\tnew_cfg->etscfg.tsatable[i] = ets->tc_tsa[i];\n+\t\tnew_cfg->etscfg.prio_table[i] = ets->prio_tc[i];\n+\t\tif (ets->prio_tc[i] > max_tc)\n+\t\t\tmax_tc = ets->prio_tc[i];\n+\t\tnew_cfg->etsrec.tcbwtable[i] = ets->tc_reco_bw[i];\n+\t\tbwrec += ets->tc_reco_bw[i];\n+\t\tnew_cfg->etsrec.tsatable[i] = ets->tc_reco_tsa[i];\n+\t\tnew_cfg->etsrec.prio_table[i] = ets->reco_prio_tc[i];\n+\t}\n+\n+\t/* max_tc is a 1-8 value count of number of TC's, not a 0-7 value\n+\t * for the TC's index number. Add one to value if not zero, and\n+\t * for zero set it to the FW's default value\n+\t */\n+\tif (max_tc)\n+\t\tmax_tc++;\n+\telse\n+\t\tmax_tc = IEEE_8021QAZ_MAX_TCS;\n+\n+\tnew_cfg->etscfg.maxtcs = max_tc;\n+\n+\tif (!bwcfg)\n+\t\tnew_cfg->etscfg.tcbwtable[0] = 100;\n+\n+\tif (!bwrec)\n+\t\tnew_cfg->etsrec.tcbwtable[0] = 100;\n+\n+\terr = ice_pf_dcb_cfg(pf, new_cfg, true);\n+\t/* return of zero indicates new cfg applied */\n+\tif (err == ICE_DCB_HW_CHG_RST)\n+\t\tice_dcbnl_devreset(netdev);\n+\tif (err == ICE_DCB_NO_HW_CHG)\n+\t\terr = ICE_DCB_HW_CHG_RST;\n+\n+\tmutex_unlock(&pf->tc_mutex);\n+\treturn err;\n+}\n+\n+/**\n+ * ice_dcbnl_getnumtcs - Get max number of traffic classes supported\n+ * @dev: pointer to netdev struct\n+ * @tcid: TC ID\n+ * @num: total number of TCs supported by the adapter\n+ *\n+ * Return the total number of TCs supported\n+ */\n+static int\n+ice_dcbnl_getnumtcs(struct net_device *dev, int __always_unused tcid, u8 *num)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(dev);\n+\n+\tif (!test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))\n+\t\treturn -EINVAL;\n+\n+\t*num = IEEE_8021QAZ_MAX_TCS;\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_dcbnl_getdcbx - retrieve current DCBX capability\n+ * @netdev: pointer to the netdev struct\n+ */\n+static u8 ice_dcbnl_getdcbx(struct net_device *netdev)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\n+\treturn pf->dcbx_cap;\n+}\n+\n+/**\n+ * ice_dcbnl_setdcbx - set required DCBX capability\n+ * @netdev: the corresponding netdev\n+ * @mode: required mode\n+ */\n+static u8 ice_dcbnl_setdcbx(struct net_device *netdev, u8 mode)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\n+\t/* No support for LLD_MANAGED modes or CEE+IEEE */\n+\tif ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) ||\n+\t !(mode & DCB_CAP_DCBX_HOST))\n+\t\treturn ICE_DCB_NO_HW_CHG;\n+\n+\t/* Already set to the given mode no change */\n+\tif (mode == pf->dcbx_cap)\n+\t\treturn ICE_DCB_NO_HW_CHG;\n+\n+\tpf->dcbx_cap = mode;\n+\tif (mode & DCB_CAP_DCBX_VER_CEE)\n+\t\tpf->hw.port_info->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_CEE;\n+\telse\n+\t\tpf->hw.port_info->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_IEEE;\n+\n+\tdev_info(&pf->pdev->dev, \"DCBx mode = 0x%x\\n\", mode);\n+\treturn ICE_DCB_HW_CHG_RST;\n+}\n+\n+/**\n+ * ice_dcbnl_get_perm_hw_addr - MAC address used by DCBX\n+ * @netdev: pointer to netdev struct\n+ * @perm_addr: buffer to return permanent MAC address\n+ */\n+static void ice_dcbnl_get_perm_hw_addr(struct net_device *netdev, u8 *perm_addr)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_port_info *pi = pf->hw.port_info;\n+\tint i, j;\n+\n+\tmemset(perm_addr, 0xff, MAX_ADDR_LEN);\n+\n+\tfor (i = 0; i < netdev->addr_len; i++)\n+\t\tperm_addr[i] = pi->mac.perm_addr[i];\n+\n+\tfor (j = 0; j < netdev->addr_len; j++, i++)\n+\t\tperm_addr[i] = pi->mac.perm_addr[j];\n+}\n+\n+/**\n+ * ice_get_pfc_delay - Retrieve PFC Link Delay\n+ * @hw: pointer to HW struct\n+ * @delay: holds the PFC Link Delay value\n+ */\n+static void ice_get_pfc_delay(struct ice_hw *hw, u16 *delay)\n+{\n+\tu32 val;\n+\n+\tval = rd32(hw, PRTDCB_GENC);\n+\t*delay = (u16)((val & PRTDCB_GENC_PFCLDA_M) >> PRTDCB_GENC_PFCLDA_S);\n+}\n+\n+/**\n+ * ice_dcbnl_getpfc - retrieve local IEEE PFC config\n+ * @netdev: pointer to netdev struct\n+ * @pfc: struct to hold PFC info\n+ */\n+static int ice_dcbnl_getpfc(struct net_device *netdev, struct ieee_pfc *pfc)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_dcbx_cfg *dcbxcfg;\n+\tstruct ice_port_info *pi = pf->hw.port_info;\n+\tint i;\n+\n+\tdcbxcfg = &pi->local_dcbx_cfg;\n+\tpfc->pfc_cap = dcbxcfg->pfc.pfccap;\n+\tpfc->pfc_en = dcbxcfg->pfc.pfcena;\n+\tpfc->mbc = dcbxcfg->pfc.mbc;\n+\tice_get_pfc_delay(&pf->hw, &pfc->delay);\n+\n+\tice_for_each_traffic_class(i) {\n+\t\tpfc->requests[i] = pf->stats.priority_xoff_tx[i];\n+\t\tpfc->indications[i] = pf->stats.priority_xoff_rx[i];\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_dcbnl_setpfc - set local IEEE PFC config\n+ * @netdev: pointer to relevant netdev\n+ * @pfc: pointer to struct holding PFC config\n+ */\n+static int ice_dcbnl_setpfc(struct net_device *netdev, struct ieee_pfc *pfc)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_dcbx_cfg *new_cfg;\n+\tint err;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))\n+\t\treturn -EINVAL;\n+\n+\tmutex_lock(&pf->tc_mutex);\n+\n+\tnew_cfg = &pf->hw.port_info->desired_dcbx_cfg;\n+\n+\tif (pfc->pfc_cap)\n+\t\tnew_cfg->pfc.pfccap = pfc->pfc_cap;\n+\telse\n+\t\tnew_cfg->pfc.pfccap = pf->hw.func_caps.common_cap.maxtc;\n+\n+\tnew_cfg->pfc.pfcena = pfc->pfc_en;\n+\n+\terr = ice_pf_dcb_cfg(pf, new_cfg, true);\n+\tif (err == ICE_DCB_HW_CHG_RST)\n+\t\tice_dcbnl_devreset(netdev);\n+\tif (err == ICE_DCB_NO_HW_CHG)\n+\t\terr = ICE_DCB_HW_CHG_RST;\n+\tmutex_unlock(&pf->tc_mutex);\n+\treturn err;\n+}\n+\n+/**\n+ * ice_dcbnl_get_pfc_cfg - Get CEE PFC config\n+ * @netdev: pointer to netdev struct\n+ * @prio: corresponding user priority\n+ * @setting: the PFC setting for given priority\n+ */\n+static void\n+ice_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio, u8 *setting)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_port_info *pi = pf->hw.port_info;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn;\n+\n+\tif (prio >= ICE_MAX_USER_PRIORITY)\n+\t\treturn;\n+\n+\t*setting = (pi->local_dcbx_cfg.pfc.pfcena >> prio) & 0x1;\n+\tdev_dbg(&pf->pdev->dev,\n+\t\t\"Get PFC Config up=%d, setting=%d, pfcenable=0x%x\\n\",\n+\t\tprio, *setting, pi->local_dcbx_cfg.pfc.pfcena);\n+}\n+\n+/**\n+ * ice_dcbnl_set_pfc_cfg - Set CEE PFC config\n+ * @netdev: the corresponding netdev\n+ * @prio: User Priority\n+ * @set: PFC setting to apply\n+ */\n+static void ice_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio, u8 set)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_dcbx_cfg *new_cfg;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn;\n+\n+\tif (prio >= ICE_MAX_USER_PRIORITY)\n+\t\treturn;\n+\n+\tnew_cfg = &pf->hw.port_info->desired_dcbx_cfg;\n+\n+\tnew_cfg->pfc.pfccap = pf->hw.func_caps.common_cap.maxtc;\n+\tif (set)\n+\t\tnew_cfg->pfc.pfcena |= BIT(prio);\n+\telse\n+\t\tnew_cfg->pfc.pfcena &= ~BIT(prio);\n+\n+\tdev_dbg(&pf->pdev->dev, \"Set PFC config UP:%d set:%d pfcena:0x%x\\n\",\n+\t\tprio, set, new_cfg->pfc.pfcena);\n+}\n+\n+/**\n+ * ice_dcbnl_getpfcstate - get CEE PFC mode\n+ * @netdev: pointer to netdev struct\n+ */\n+static u8 ice_dcbnl_getpfcstate(struct net_device *netdev)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_port_info *pi = pf->hw.port_info;\n+\n+\t/* Return enabled if any UP enabled for PFC */\n+\tif (pi->local_dcbx_cfg.pfc.pfcena)\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_dcbnl_getstate - get DCB enabled state\n+ * @netdev: pointer to netdev struct\n+ */\n+static u8 ice_dcbnl_getstate(struct net_device *netdev)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tu8 state = 0;\n+\n+\tstate = test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);\n+\n+\tdev_dbg(&pf->pdev->dev, \"DCB enabled state = %d\\n\", state);\n+\treturn state;\n+}\n+\n+/**\n+ * ice_dcbnl_setstate - Set CEE DCB state\n+ * @netdev: pointer to relevant netdev\n+ * @state: state value to set\n+ */\n+static u8 ice_dcbnl_setstate(struct net_device *netdev, u8 state)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn ICE_DCB_NO_HW_CHG;\n+\n+\t/* Nothing to do */\n+\tif (!!state == test_bit(ICE_FLAG_DCB_ENA, pf->flags))\n+\t\treturn ICE_DCB_NO_HW_CHG;\n+\n+\tif (state) {\n+\t\tset_bit(ICE_FLAG_DCB_ENA, pf->flags);\n+\t\tmemcpy(&pf->hw.port_info->desired_dcbx_cfg,\n+\t\t &pf->hw.port_info->local_dcbx_cfg,\n+\t\t sizeof(struct ice_dcbx_cfg));\n+\t} else {\n+\t\tclear_bit(ICE_FLAG_DCB_ENA, pf->flags);\n+\t}\n+\n+\treturn ICE_DCB_HW_CHG;\n+}\n+\n+/**\n+ * ice_dcbnl_get_pg_tc_cfg_tx - get CEE PG Tx config\n+ * @netdev: pointer to netdev struct\n+ * @prio: the corresponding user priority\n+ * @prio_type: traffic priority type\n+ * @pgid: the BW group ID the traffic class belongs to\n+ * @bw_pct: BW percentage for the corresponding BWG\n+ * @up_map: prio mapped to corresponding TC\n+ */\n+static void\n+ice_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int prio,\n+\t\t\t u8 __always_unused *prio_type, u8 *pgid,\n+\t\t\t u8 __always_unused *bw_pct,\n+\t\t\t u8 __always_unused *up_map)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_port_info *pi = pf->hw.port_info;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn;\n+\n+\tif (prio >= ICE_MAX_USER_PRIORITY)\n+\t\treturn;\n+\n+\t*pgid = pi->local_dcbx_cfg.etscfg.prio_table[prio];\n+\tdev_dbg(&pf->pdev->dev,\n+\t\t\"Get PG config prio=%d tc=%d\\n\", prio, *pgid);\n+}\n+\n+/**\n+ * ice_dcbnl_set_pg_tc_cfg_tx - set CEE PG Tx config\n+ * @netdev: pointer to relevant netdev\n+ * @tc: the corresponding traffic class\n+ * @prio_type: the traffic priority type\n+ * @bwg_id: the BW group ID the TC belongs to\n+ * @bw_pct: the BW perventage for the BWG\n+ * @up_map: prio mapped to corresponding TC\n+ */\n+static void\n+ice_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,\n+\t\t\t u8 __always_unused prio_type,\n+\t\t\t u8 __always_unused bwg_id,\n+\t\t\t u8 __always_unused bw_pct, u8 up_map)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_dcbx_cfg *new_cfg;\n+\tint i;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn;\n+\n+\tif (tc >= ICE_MAX_TRAFFIC_CLASS)\n+\t\treturn;\n+\n+\tnew_cfg = &pf->hw.port_info->desired_dcbx_cfg;\n+\n+\t/* prio_type, bwg_id and bw_pct per UP are not supported */\n+\n+\tice_for_each_traffic_class(i) {\n+\t\tif (up_map & BIT(i))\n+\t\t\tnew_cfg->etscfg.prio_table[i] = tc;\n+\t}\n+\tnew_cfg->etscfg.tsatable[tc] = ICE_IEEE_TSA_ETS;\n+}\n+\n+/**\n+ * ice_dcbnl_get_pg_bwg_cfg_tx - Get CEE PGBW config\n+ * @netdev: pointer to the netdev struct\n+ * @pgid: corresponding traffic class\n+ * @bw_pct: the BW percentage for the corresponding TC\n+ */\n+static void\n+ice_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, u8 *bw_pct)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_port_info *pi = pf->hw.port_info;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn;\n+\n+\tif (pgid >= ICE_MAX_TRAFFIC_CLASS)\n+\t\treturn;\n+\n+\t*bw_pct = pi->local_dcbx_cfg.etscfg.tcbwtable[pgid];\n+\tdev_dbg(&pf->pdev->dev, \"Get PG BW config tc=%d bw_pct=%d\\n\",\n+\t\tpgid, *bw_pct);\n+}\n+\n+/**\n+ * ice_dcbnl_set_pg_bwg_cfg_tx - set CEE PG Tx BW config\n+ * @netdev: the corresponding netdev\n+ * @pgid: Correspongind traffic class\n+ * @bw_pct: the BW percentage for the specified TC\n+ */\n+static void\n+ice_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, u8 bw_pct)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_dcbx_cfg *new_cfg;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn;\n+\n+\tif (pgid >= ICE_MAX_TRAFFIC_CLASS)\n+\t\treturn;\n+\n+\tnew_cfg = &pf->hw.port_info->desired_dcbx_cfg;\n+\n+\tnew_cfg->etscfg.tcbwtable[pgid] = bw_pct;\n+}\n+\n+/**\n+ * ice_dcbnl_get_pg_tc_cfg_rx - Get CEE PG Rx config\n+ * @netdev: pointer to netdev struct\n+ * @prio: the corresponding user priority\n+ * @prio_type: the traffic priority type\n+ * @pgid: the PG ID\n+ * @bw_pct: the BW percentage for the corresponding BWG\n+ * @up_map: prio mapped to corresponding TC\n+ */\n+static void\n+ice_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int prio,\n+\t\t\t u8 __always_unused *prio_type, u8 *pgid,\n+\t\t\t u8 __always_unused *bw_pct,\n+\t\t\t u8 __always_unused *up_map)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_port_info *pi = pf->hw.port_info;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn;\n+\n+\tif (prio >= ICE_MAX_USER_PRIORITY)\n+\t\treturn;\n+\n+\t*pgid = pi->local_dcbx_cfg.etscfg.prio_table[prio];\n+}\n+\n+/**\n+ * ice_dcbnl_get_pg_bwg_cfg_rx - Get CEE PG BW Rx config\n+ * @netdev: pointer to netdev struct\n+ * @pgid: the corresponding traffic class\n+ * @bw_pct: the BW percentage for the corresponding TC\n+ */\n+static void\n+ice_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int __always_unused pgid,\n+\t\t\t u8 *bw_pct)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn;\n+\n+\t*bw_pct = 0;\n+}\n+\n+/**\n+ * ice_dcbnl_get_cap - Get DCBX capabilities of adapter\n+ * @netdev: pointer to netdev struct\n+ * @capid: the capability type\n+ * @cap: the capability value\n+ */\n+static u8 ice_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\n+\tif (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))\n+\t\treturn ICE_DCB_NO_HW_CHG;\n+\n+\tswitch (capid) {\n+\tcase DCB_CAP_ATTR_PG:\n+\t\t*cap = true;\n+\t\tbreak;\n+\tcase DCB_CAP_ATTR_PFC:\n+\t\t*cap = true;\n+\t\tbreak;\n+\tcase DCB_CAP_ATTR_UP2TC:\n+\t\t*cap = false;\n+\t\tbreak;\n+\tcase DCB_CAP_ATTR_PG_TCS:\n+\t\t*cap = 0x80;\n+\t\tbreak;\n+\tcase DCB_CAP_ATTR_PFC_TCS:\n+\t\t*cap = 0x80;\n+\t\tbreak;\n+\tcase DCB_CAP_ATTR_GSP:\n+\t\t*cap = false;\n+\t\tbreak;\n+\tcase DCB_CAP_ATTR_BCN:\n+\t\t*cap = false;\n+\t\tbreak;\n+\tcase DCB_CAP_ATTR_DCBX:\n+\t\t*cap = pf->dcbx_cap;\n+\t\tbreak;\n+\tdefault:\n+\t\t*cap = false;\n+\t\tbreak;\n+\t}\n+\n+\tdev_dbg(&pf->pdev->dev, \"DCBX Get Capability cap=%d capval=0x%x\\n\",\n+\t\tcapid, *cap);\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_dcbnl_getapp - get CEE APP\n+ * @netdev: pointer to netdev struct\n+ * @idtype: the App selector\n+ * @id: the App ethtype or port number\n+ */\n+static int ice_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct dcb_app app = {\n+\t\t\t\t.selector = idtype,\n+\t\t\t\t.protocol = id,\n+\t\t\t };\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn -EINVAL;\n+\n+\treturn dcb_getapp(netdev, &app);\n+}\n+\n+/**\n+ * ice_dcbnl_find_app - Search for APP in given DCB config\n+ * @cfg: struct to hold DCBX config\n+ * @app: struct to hold app data to look for\n+ */\n+static bool\n+ice_dcbnl_find_app(struct ice_dcbx_cfg *cfg,\n+\t\t struct ice_dcb_app_priority_table *app)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < cfg->numapps; i++) {\n+\t\tif (app->selector == cfg->app[i].selector &&\n+\t\t app->prot_id == cfg->app[i].prot_id &&\n+\t\t app->priority == cfg->app[i].priority)\n+\t\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+\n+/**\n+ * ice_dcbnl_setapp - set local IEEE App config\n+ * @netdev: relevant netdev struct\n+ * @app: struct to hold app config info\n+ */\n+static int ice_dcbnl_setapp(struct net_device *netdev, struct dcb_app *app)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_dcb_app_priority_table new_app;\n+\tstruct ice_dcbx_cfg *old_cfg, *new_cfg;\n+\tint ret;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))\n+\t\treturn -EINVAL;\n+\n+\tmutex_lock(&pf->tc_mutex);\n+\n+\tnew_cfg = &pf->hw.port_info->desired_dcbx_cfg;\n+\n+\told_cfg = &pf->hw.port_info->local_dcbx_cfg;\n+\n+\tif (old_cfg->numapps == ICE_DCBX_MAX_APPS) {\n+\t\tret = -EINVAL;\n+\t\tgoto setapp_out;\n+\t}\n+\n+\tret = dcb_ieee_setapp(netdev, app);\n+\tif (ret)\n+\t\tgoto setapp_out;\n+\n+\tnew_app.selector = app->selector;\n+\tnew_app.prot_id = app->protocol;\n+\tnew_app.priority = app->priority;\n+\tif (ice_dcbnl_find_app(old_cfg, &new_app)) {\n+\t\tret = 0;\n+\t\tgoto setapp_out;\n+\t}\n+\n+\tnew_cfg->app[new_cfg->numapps++] = new_app;\n+\tret = ice_pf_dcb_cfg(pf, new_cfg, true);\n+\t/* return of zero indicates new cfg applied */\n+\tif (ret == ICE_DCB_HW_CHG_RST)\n+\t\tice_dcbnl_devreset(netdev);\n+\tif (ret == ICE_DCB_NO_HW_CHG)\n+\t\tret = ICE_DCB_HW_CHG_RST;\n+\n+setapp_out:\n+\tmutex_unlock(&pf->tc_mutex);\n+\treturn ret;\n+}\n+\n+/**\n+ * ice_dcbnl_delapp - Delete local IEEE App config\n+ * @netdev: relevant netdev\n+ * @app: struct to hold app too delete\n+ *\n+ * Will not delete first application required by the FW\n+ */\n+static int ice_dcbnl_delapp(struct net_device *netdev, struct dcb_app *app)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_dcbx_cfg *old_cfg, *new_cfg;\n+\tint i, j, ret = 0;\n+\n+\tif (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)\n+\t\treturn -EINVAL;\n+\n+\tmutex_lock(&pf->tc_mutex);\n+\tret = dcb_ieee_delapp(netdev, app);\n+\tif (ret)\n+\t\tgoto delapp_out;\n+\n+\told_cfg = &pf->hw.port_info->local_dcbx_cfg;\n+\n+\tif (old_cfg->numapps == 1)\n+\t\tgoto delapp_out;\n+\n+\tnew_cfg = &pf->hw.port_info->desired_dcbx_cfg;\n+\n+\tfor (i = 1; i < new_cfg->numapps; i++) {\n+\t\tif (app->selector == new_cfg->app[i].selector &&\n+\t\t app->protocol == new_cfg->app[i].prot_id &&\n+\t\t app->priority == new_cfg->app[i].priority) {\n+\t\t\tnew_cfg->app[i].selector = 0;\n+\t\t\tnew_cfg->app[i].prot_id = 0;\n+\t\t\tnew_cfg->app[i].priority = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\t/* Did not find DCB App */\n+\tif (i == new_cfg->numapps) {\n+\t\tret = -EINVAL;\n+\t\tgoto delapp_out;\n+\t}\n+\n+\tnew_cfg->numapps--;\n+\n+\tfor (j = i; j < new_cfg->numapps; j++) {\n+\t\tnew_cfg->app[i].selector = old_cfg->app[j + 1].selector;\n+\t\tnew_cfg->app[i].prot_id = old_cfg->app[j + 1].prot_id;\n+\t\tnew_cfg->app[i].priority = old_cfg->app[j + 1].priority;\n+\t}\n+\n+\tret = ice_pf_dcb_cfg(pf, new_cfg, true);\n+\t/* return of zero indicates new cfg applied */\n+\tif (ret == ICE_DCB_HW_CHG_RST)\n+\t\tice_dcbnl_devreset(netdev);\n+\tif (ret == ICE_DCB_NO_HW_CHG)\n+\t\tret = ICE_DCB_HW_CHG_RST;\n+\n+delapp_out:\n+\tmutex_unlock(&pf->tc_mutex);\n+\treturn ret;\n+}\n+\n+/**\n+ * ice_dcbnl_cee_set_all - Commit CEE DCB settings to HW\n+ * @netdev: the corresponding netdev\n+ */\n+static u8 ice_dcbnl_cee_set_all(struct net_device *netdev)\n+{\n+\tstruct ice_pf *pf = ice_netdev_to_pf(netdev);\n+\tstruct ice_dcbx_cfg *new_cfg;\n+\tint err;\n+\n+\tif ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||\n+\t !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))\n+\t\treturn ICE_DCB_NO_HW_CHG;\n+\n+\tnew_cfg = &pf->hw.port_info->desired_dcbx_cfg;\n+\n+\tmutex_lock(&pf->tc_mutex);\n+\n+\terr = ice_pf_dcb_cfg(pf, new_cfg, true);\n+\n+\tmutex_unlock(&pf->tc_mutex);\n+\treturn (err != ICE_DCB_HW_CHG_RST) ? ICE_DCB_NO_HW_CHG : err;\n+}\n+\n+static const struct dcbnl_rtnl_ops dcbnl_ops = {\n+\t/* IEEE 802.1Qaz std */\n+\t.ieee_getets = ice_dcbnl_getets,\n+\t.ieee_setets = ice_dcbnl_setets,\n+\t.ieee_getpfc = ice_dcbnl_getpfc,\n+\t.ieee_setpfc = ice_dcbnl_setpfc,\n+\t.ieee_setapp = ice_dcbnl_setapp,\n+\t.ieee_delapp = ice_dcbnl_delapp,\n+\n+\t/* CEE std */\n+\t.getstate = ice_dcbnl_getstate,\n+\t.setstate = ice_dcbnl_setstate,\n+\t.getpermhwaddr = ice_dcbnl_get_perm_hw_addr,\n+\t.setpgtccfgtx = ice_dcbnl_set_pg_tc_cfg_tx,\n+\t.setpgbwgcfgtx = ice_dcbnl_set_pg_bwg_cfg_tx,\n+\t.getpgtccfgtx = ice_dcbnl_get_pg_tc_cfg_tx,\n+\t.getpgbwgcfgtx = ice_dcbnl_get_pg_bwg_cfg_tx,\n+\t.getpgtccfgrx = ice_dcbnl_get_pg_tc_cfg_rx,\n+\t.getpgbwgcfgrx = ice_dcbnl_get_pg_bwg_cfg_rx,\n+\t.setpfccfg = ice_dcbnl_set_pfc_cfg,\n+\t.getpfccfg = ice_dcbnl_get_pfc_cfg,\n+\t.setall = ice_dcbnl_cee_set_all,\n+\t.getcap = ice_dcbnl_get_cap,\n+\t.getnumtcs = ice_dcbnl_getnumtcs,\n+\t.getpfcstate = ice_dcbnl_getpfcstate,\n+\t.getapp = ice_dcbnl_getapp,\n+\n+\t/* DCBX configuration */\n+\t.getdcbx = ice_dcbnl_getdcbx,\n+\t.setdcbx = ice_dcbnl_setdcbx,\n+};\n+\n+/**\n+ * ice_dcbnl_set_all - set all the apps and ieee data from DCBX config\n+ * @vsi: pointer to VSI struct\n+ */\n+void ice_dcbnl_set_all(struct ice_vsi *vsi)\n+{\n+\tstruct net_device *netdev = vsi->netdev;\n+\tstruct ice_dcbx_cfg *dcbxcfg;\n+\tstruct ice_port_info *pi;\n+\tstruct dcb_app sapp;\n+\tstruct ice_pf *pf;\n+\tint i;\n+\n+\tif (!netdev)\n+\t\treturn;\n+\n+\tpf = ice_netdev_to_pf(netdev);\n+\tpi = pf->hw.port_info;\n+\n+\t/* SW DCB taken care of by SW Default Config */\n+\tif (pf->dcbx_cap & DCB_CAP_DCBX_HOST)\n+\t\treturn;\n+\n+\t/* DCB not enabled */\n+\tif (!test_bit(ICE_FLAG_DCB_ENA, pf->flags))\n+\t\treturn;\n+\n+\tdcbxcfg = &pi->local_dcbx_cfg;\n+\n+\tfor (i = 0; i < dcbxcfg->numapps; i++) {\n+\t\tu8 prio, tc_map;\n+\n+\t\tprio = dcbxcfg->app[i].priority;\n+\t\ttc_map = BIT(dcbxcfg->etscfg.prio_table[prio]);\n+\n+\t\t/* Add APP only if the TC is enabled for this VSI */\n+\t\tif (tc_map & vsi->tc_cfg.ena_tc) {\n+\t\t\tsapp.selector = dcbxcfg->app[i].selector;\n+\t\t\tsapp.protocol = dcbxcfg->app[i].prot_id;\n+\t\t\tsapp.priority = prio;\n+\t\t\tdcb_ieee_setapp(netdev, &sapp);\n+\t\t}\n+\t}\n+\t/* Notify user-space of the changes */\n+\tdcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, 0, 0);\n+}\n+\n+/**\n+ * ice_dcbnl_vsi_del_app - Delete APP on all VSIs\n+ * @vsi: pointer to the main VSI\n+ * @app: APP to delete\n+ *\n+ * Delete given APP from all the VSIs for given PF\n+ */\n+static void\n+ice_dcbnl_vsi_del_app(struct ice_vsi *vsi,\n+\t\t struct ice_dcb_app_priority_table *app)\n+{\n+\tstruct dcb_app sapp;\n+\tint err;\n+\n+\tsapp.selector = app->selector;\n+\tsapp.protocol = app->prot_id;\n+\tsapp.priority = app->priority;\n+\terr = ice_dcbnl_delapp(vsi->netdev, &sapp);\n+\tdev_dbg(&vsi->back->pdev->dev,\n+\t\t\"Deleting app for VSI idx=%d err=%d sel=%d proto=0x%x, prio=%d\\n\",\n+\t\tvsi->idx, err, app->selector, app->prot_id, app->priority);\n+}\n+\n+/**\n+ * ice_dcbnl_flush_apps - Delete all removed APPs\n+ * @pf: the corresponding PF\n+ * @old_cfg: old DCBX configuration data\n+ * @new_cfg: new DCBX configuration data\n+ *\n+ * Find and delete all APPS that are not present in the passed\n+ * DCB configuration\n+ */\n+void\n+ice_dcbnl_flush_apps(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,\n+\t\t struct ice_dcbx_cfg *new_cfg)\n+{\n+\tstruct ice_vsi *main_vsi = ice_get_main_vsi(pf);\n+\tint i;\n+\n+\tif (!main_vsi)\n+\t\treturn;\n+\n+\tfor (i = 0; i < old_cfg->numapps; i++) {\n+\t\tstruct ice_dcb_app_priority_table app = old_cfg->app[i];\n+\n+\t\t/* The APP is not available anymore delete it */\n+\t\tif (!ice_dcbnl_find_app(new_cfg, &app))\n+\t\t\tice_dcbnl_vsi_del_app(main_vsi, &app);\n+\t}\n+}\n+\n+/**\n+ * ice_dcbnl_setup - setup DCBNL\n+ * @vsi: VSI to get associated netdev from\n+ */\n+void ice_dcbnl_setup(struct ice_vsi *vsi)\n+{\n+\tstruct net_device *netdev = vsi->netdev;\n+\tstruct ice_pf *pf;\n+\n+\tpf = ice_netdev_to_pf(netdev);\n+\tif (!test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))\n+\t\treturn;\n+\n+\tnetdev->dcbnl_ops = &dcbnl_ops;\n+\tice_dcbnl_set_all(vsi);\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dcb_nl.h b/drivers/net/ethernet/intel/ice/ice_dcb_nl.h\nnew file mode 100644\nindex 000000000000..6c630a362293\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_dcb_nl.h\n@@ -0,0 +1,19 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/* Copyright (c) 2019, Intel Corporation. */\n+\n+#ifndef _ICE_DCB_NL_H_\n+#define _ICE_DCB_NL_H_\n+\n+#ifdef CONFIG_DCB\n+void ice_dcbnl_setup(struct ice_vsi *vsi);\n+void ice_dcbnl_set_all(struct ice_vsi *vsi);\n+void\n+ice_dcbnl_flush_apps(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,\n+\t\t struct ice_dcbx_cfg *new_cfg);\n+#else\n+#define ice_dcbnl_setup(vsi) do {} while (0)\n+#define ice_dcbnl_set_all(vsi) do {} while (0)\n+#define ice_dcbnl_flush_apps(pf, old_cfg, new_cfg) do {} while (0)\n+#endif /* CONFIG_DCB */\n+\n+#endif /* _ICE_DCB_NL_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\nindex 8abfec62a777..1aa8e850bc67 100644\n--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\n+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\n@@ -52,6 +52,9 @@\n #define PF_MBX_ATQLEN_ATQLEN_M\t\t\tICE_M(0x3FF, 0)\n #define PF_MBX_ATQLEN_ATQENABLE_M\t\tBIT(31)\n #define PF_MBX_ATQT\t\t\t\t0x0022E300\n+#define PRTDCB_GENC\t\t\t\t0x00083000\n+#define PRTDCB_GENC_PFCLDA_S\t\t\t16\n+#define PRTDCB_GENC_PFCLDA_M\t\t\tICE_M(0xFFFF, 16)\n #define PRTDCB_GENS\t\t\t\t0x00083020\n #define PRTDCB_GENS_DCBX_STATUS_S\t\t0\n #define PRTDCB_GENS_DCBX_STATUS_M\t\tICE_M(0x7, 0)\ndiff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c\nindex 8dd7f3848c59..d4e3df6544f5 100644\n--- a/drivers/net/ethernet/intel/ice/ice_lib.c\n+++ b/drivers/net/ethernet/intel/ice/ice_lib.c\n@@ -2488,6 +2488,7 @@ int ice_vsi_rebuild(struct ice_vsi *vsi)\n bool ice_is_reset_in_progress(unsigned long *state)\n {\n \treturn test_bit(__ICE_RESET_OICR_RECV, state) ||\n+\t test_bit(__ICE_DCBNL_DEVRESET, state) ||\n \t test_bit(__ICE_PFR_REQ, state) ||\n \t test_bit(__ICE_CORER_REQ, state) ||\n \t test_bit(__ICE_GLOBR_REQ, state);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex fec58433bafb..a0a04114d991 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -9,6 +9,7 @@\n #include \"ice_base.h\"\n #include \"ice_lib.h\"\n #include \"ice_dcb_lib.h\"\n+#include \"ice_dcb_nl.h\"\n \n #define DRV_VERSION_MAJOR 0\n #define DRV_VERSION_MINOR 8\n@@ -2641,6 +2642,9 @@ static int ice_setup_pf_sw(struct ice_pf *pf)\n \t/* netdev has to be configured before setting frame size */\n \tice_vsi_cfg_frame_size(vsi);\n \n+\t/* Setup DCB netlink interface */\n+\tice_dcbnl_setup(vsi);\n+\n \t/* registering the NAPI handler requires both the queues and\n \t * netdev to be created, which are done in ice_pf_vsi_setup()\n \t * and ice_cfg_netdev() respectively\n@@ -2721,6 +2725,7 @@ static void ice_deinit_pf(struct ice_pf *pf)\n {\n \tice_service_task_stop(pf);\n \tmutex_destroy(&pf->sw_mutex);\n+\tmutex_destroy(&pf->tc_mutex);\n \tmutex_destroy(&pf->avail_q_mutex);\n \n \tif (pf->avail_txqs) {\n@@ -2770,6 +2775,7 @@ static int ice_init_pf(struct ice_pf *pf)\n \tice_set_pf_caps(pf);\n \n \tmutex_init(&pf->sw_mutex);\n+\tmutex_init(&pf->tc_mutex);\n \n \t/* setup service timer and periodic service task */\n \ttimer_setup(&pf->serv_tmr, ice_service_timer, 0);\n", "prefixes": [ "S32", "v3", "03/15" ] }