Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1736556 > unrolled thread
| Started by | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| First post | 2017-09-21 13:30 +0200 |
| Last post | 2017-09-21 13:30 +0200 |
| Articles | 17 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH net-next 00/10] Add support for DCB feature in hns3 driver Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-21 13:30 +0200
[PATCH net-next 01/10] net: hns3: Support for dynamically assigning tx buffer to TC Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-21 13:30 +0200
Re: [PATCH net-next 01/10] net: hns3: Support for dynamically assigning tx buffer to TC David Miller <davem@davemloft.net> - 2017-09-22 03:50 +0200
Re: [PATCH net-next 01/10] net: hns3: Support for dynamically assigning tx buffer to TC Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-22 04:00 +0200
Re: [PATCH net-next 01/10] net: hns3: Support for dynamically assigning tx buffer to TC David Miller <davem@davemloft.net> - 2017-09-22 05:50 +0200
[PATCH net-next 02/10] net: hns3: Add support for dynamically buffer reallocation Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-21 13:30 +0200
[PATCH net-next 06/10] net: hns3: Add some interface for the support of DCB feature Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-21 13:30 +0200
[PATCH net-next 09/10] net: hns3: Setting for fc_mode and dcb enable flag in TM module Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-21 13:30 +0200
[PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-21 13:30 +0200
Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack Jiri Pirko <jiri@resnulli.us> - 2017-09-22 15:00 +0200
Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack Jiri Pirko <jiri@resnulli.us> - 2017-09-22 18:10 +0200
Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-23 02:50 +0200
Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack Jiri Pirko <jiri@resnulli.us> - 2017-09-24 13:40 +0200
Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-25 02:50 +0200
Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack Jiri Pirko <jiri@resnulli.us> - 2017-09-25 09:00 +0200
Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-25 09:30 +0200
[PATCH net-next 08/10] net: hns3: Add dcb netlink interface for the support of DCB feature Yunsheng Lin <linyunsheng@huawei.com> - 2017-09-21 13:30 +0200
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-21 13:30 +0200 |
| Subject | [PATCH net-next 00/10] Add support for DCB feature in hns3 driver |
| Message-ID | <us7Q5-kv-3@gated-at.bofh.it> |
The patchset contains some enhancement related to DCB before
adding support for DCB feature.
This patchset depends on the following patchset:
https://patchwork.ozlabs.org/cover/815646/
https://patchwork.ozlabs.org/cover/816145/
High Level Architecture:
[ tc qdisc ] [ lldpad ]
| |
| |
| |
[ hns3_enet ] [ hns3_dcbnl ]
\ /
\ /
\ /
[ hclge_dcb ]
/ \
/ \
/ \
[ hclgc_main ] [ hclge_tm ]
Current patch-set support following functionality:
1. Use of tc qdisc to configure the tc num and prio_tc_map.
2. Use of lldptool to configure the tc schedule mode, tc
bandwidth(if schedule mode is ETS), prio_tc_map and
PFC parameter.
Yunsheng Lin (10):
net: hns3: Support for dynamically assigning tx buffer to TC
net: hns3: Add support for dynamically buffer reallocation
net: hns3: Add support for PFC setting in TM module
net: hns3: Add support for port shaper setting in TM module
net: hns3: Add tc-based TM support for sriov enabled port
net: hns3: Add some interface for the support of DCB feature
net: hns3: Add hclge_dcb module for the support of DCB feature
net: hns3: Add dcb netlink interface for the support of DCB feature
net: hns3: Setting for fc_mode and dcb enable flag in TM module
net: hns3: Add mqprio support when interacting with network stack
drivers/net/ethernet/hisilicon/Kconfig | 9 +
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 20 ++
.../net/ethernet/hisilicon/hns3/hns3pf/Makefile | 4 +
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 6 +
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 327 +++++++++++++++++++++
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h | 21 ++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 219 +++++++++-----
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 8 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 232 +++++++++++++--
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 15 +
.../ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c | 106 +++++++
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c | 137 +++++++--
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h | 7 +
13 files changed, 983 insertions(+), 128 deletions(-)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c
--
1.9.1
[toc] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-21 13:30 +0200 |
| Subject | [PATCH net-next 01/10] net: hns3: Support for dynamically assigning tx buffer to TC |
| Message-ID | <us7Q6-kv-13@gated-at.bofh.it> |
| In reply to | #1736556 |
This patch add support of dynamically assigning tx buffer to
TC when the TC is enabled.
It will save buffer for rx direction to avoid packet loss.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 1 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 69 ++++++++++++++++++----
2 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 758cf39..a81c6cb 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -311,6 +311,7 @@ struct hclge_tc_thrd {
struct hclge_priv_buf {
struct hclge_waterline wl; /* Waterline for low and high*/
u32 buf_size; /* TC private buffer size */
+ u32 tx_buf_size;
u32 enable; /* Enable TC private buffer or not */
};
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index d27618b..dfe0fd2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1324,23 +1324,28 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
return 0;
}
-static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev, u16 buf_size)
+static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev)
{
/* TX buffer size is unit by 128 byte */
#define HCLGE_BUF_SIZE_UNIT_SHIFT 7
#define HCLGE_BUF_SIZE_UPDATE_EN_MSK BIT(15)
struct hclge_tx_buff_alloc *req;
+ struct hclge_priv_buf *priv;
struct hclge_desc desc;
+ u32 buf_size;
int ret;
u8 i;
req = (struct hclge_tx_buff_alloc *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, 0);
- for (i = 0; i < HCLGE_TC_NUM; i++)
+ for (i = 0; i < HCLGE_TC_NUM; i++) {
+ priv = &hdev->priv_buf[i];
+ buf_size = priv->tx_buf_size;
req->tx_pkt_buff[i] =
cpu_to_le16((buf_size >> HCLGE_BUF_SIZE_UNIT_SHIFT) |
HCLGE_BUF_SIZE_UPDATE_EN_MSK);
+ }
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
@@ -1352,9 +1357,9 @@ static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev, u16 buf_size)
return 0;
}
-static int hclge_tx_buffer_alloc(struct hclge_dev *hdev, u32 buf_size)
+static int hclge_tx_buffer_alloc(struct hclge_dev *hdev)
{
- int ret = hclge_cmd_alloc_tx_buff(hdev, buf_size);
+ int ret = hclge_cmd_alloc_tx_buff(hdev);
if (ret) {
dev_err(&hdev->pdev->dev,
@@ -1433,6 +1438,18 @@ static u32 hclge_get_rx_priv_buff_alloced(struct hclge_dev *hdev)
return rx_priv;
}
+static u32 hclge_get_tx_buff_alloced(struct hclge_dev *hdev)
+{
+ struct hclge_priv_buf *priv;
+ u32 tx_buf = 0, i;
+
+ for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
+ priv = &hdev->priv_buf[i];
+ tx_buf += priv->tx_buf_size;
+ }
+ return tx_buf;
+}
+
static bool hclge_is_rx_buf_ok(struct hclge_dev *hdev, u32 rx_all)
{
u32 shared_buf_min, shared_buf_tc, shared_std;
@@ -1477,18 +1494,44 @@ static bool hclge_is_rx_buf_ok(struct hclge_dev *hdev, u32 rx_all)
return true;
}
+static int hclge_tx_buffer_calc(struct hclge_dev *hdev)
+{
+ struct hclge_priv_buf *priv;
+ u32 i, total_size;
+
+ total_size = hdev->pkt_buf_size;
+
+ /* alloc tx buffer for all enabled tc */
+ for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
+ priv = &hdev->priv_buf[i];
+
+ if (total_size < HCLGE_DEFAULT_TX_BUF)
+ return -ENOMEM;
+
+ if (hdev->hw_tc_map & BIT(i))
+ priv->tx_buf_size = HCLGE_DEFAULT_TX_BUF;
+ else
+ priv->tx_buf_size = 0;
+
+ total_size -= priv->tx_buf_size;
+ }
+
+ return 0;
+}
+
/* hclge_rx_buffer_calc: calculate the rx private buffer size for all TCs
* @hdev: pointer to struct hclge_dev
- * @tx_size: the allocated tx buffer for all TCs
* @return: 0: calculate sucessful, negative: fail
*/
-int hclge_rx_buffer_calc(struct hclge_dev *hdev, u32 tx_size)
+int hclge_rx_buffer_calc(struct hclge_dev *hdev)
{
- u32 rx_all = hdev->pkt_buf_size - tx_size;
+ u32 rx_all = hdev->pkt_buf_size;
int no_pfc_priv_num, pfc_priv_num;
struct hclge_priv_buf *priv;
int i;
+ rx_all -= hclge_get_tx_buff_alloced(hdev);
+
/* When DCB is not supported, rx private
* buffer is not allocated.
*/
@@ -1771,7 +1814,6 @@ static int hclge_common_wl_config(struct hclge_dev *hdev)
int hclge_buffer_alloc(struct hclge_dev *hdev)
{
- u32 tx_buf_size = HCLGE_DEFAULT_TX_BUF;
int ret;
hdev->priv_buf = devm_kmalloc_array(&hdev->pdev->dev, HCLGE_MAX_TC_NUM,
@@ -1780,14 +1822,21 @@ int hclge_buffer_alloc(struct hclge_dev *hdev)
if (!hdev->priv_buf)
return -ENOMEM;
- ret = hclge_tx_buffer_alloc(hdev, tx_buf_size);
+ ret = hclge_tx_buffer_calc(hdev);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "could not calc tx buffer size for all TCs %d\n", ret);
+ return ret;
+ }
+
+ ret = hclge_tx_buffer_alloc(hdev);
if (ret) {
dev_err(&hdev->pdev->dev,
"could not alloc tx buffers %d\n", ret);
return ret;
}
- ret = hclge_rx_buffer_calc(hdev, tx_buf_size);
+ ret = hclge_rx_buffer_calc(hdev);
if (ret) {
dev_err(&hdev->pdev->dev,
"could not calc rx priv buffer size for all TCs %d\n",
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2017-09-22 03:50 +0200 |
| Subject | Re: [PATCH net-next 01/10] net: hns3: Support for dynamically assigning tx buffer to TC |
| Message-ID | <uslgl-8oN-3@gated-at.bofh.it> |
| In reply to | #1736558 |
From: Yunsheng Lin <linyunsheng@huawei.com>
Date: Thu, 21 Sep 2017 19:21:44 +0800
> @@ -1324,23 +1324,28 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
> return 0;
> }
>
> -static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev, u16 buf_size)
> +static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev)
> {
> /* TX buffer size is unit by 128 byte */
> #define HCLGE_BUF_SIZE_UNIT_SHIFT 7
> #define HCLGE_BUF_SIZE_UPDATE_EN_MSK BIT(15)
> struct hclge_tx_buff_alloc *req;
> + struct hclge_priv_buf *priv;
> struct hclge_desc desc;
> + u32 buf_size;
> int ret;
> u8 i;
>
> req = (struct hclge_tx_buff_alloc *)desc.data;
>
> hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, 0);
> - for (i = 0; i < HCLGE_TC_NUM; i++)
> + for (i = 0; i < HCLGE_TC_NUM; i++) {
> + priv = &hdev->priv_buf[i];
> + buf_size = priv->tx_buf_size;
> req->tx_pkt_buff[i] =
> cpu_to_le16((buf_size >> HCLGE_BUF_SIZE_UNIT_SHIFT) |
> HCLGE_BUF_SIZE_UPDATE_EN_MSK);
> + }
>
> ret = hclge_cmd_send(&hdev->hw, &desc, 1);
> if (ret) {
Local variable 'buf_size' is assigned but never used in this function.
And with 'buf_size' removed, 'priv' also becomes unused.
If it gets used in a later patch, add it in that later patch.
You can also declare the variables locally in the basic block of
the for() loop.
[toc] | [prev] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-22 04:00 +0200 |
| Subject | Re: [PATCH net-next 01/10] net: hns3: Support for dynamically assigning tx buffer to TC |
| Message-ID | <uslq1-8rR-11@gated-at.bofh.it> |
| In reply to | #1737125 |
Hi, David
On 2017/9/22 9:41, David Miller wrote:
> From: Yunsheng Lin <linyunsheng@huawei.com>
> Date: Thu, 21 Sep 2017 19:21:44 +0800
>
>> @@ -1324,23 +1324,28 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
>> return 0;
>> }
>>
>> -static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev, u16 buf_size)
>> +static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev)
>> {
>> /* TX buffer size is unit by 128 byte */
>> #define HCLGE_BUF_SIZE_UNIT_SHIFT 7
>> #define HCLGE_BUF_SIZE_UPDATE_EN_MSK BIT(15)
>> struct hclge_tx_buff_alloc *req;
>> + struct hclge_priv_buf *priv;
>> struct hclge_desc desc;
>> + u32 buf_size;
>> int ret;
>> u8 i;
>>
>> req = (struct hclge_tx_buff_alloc *)desc.data;
>>
>> hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, 0);
>> - for (i = 0; i < HCLGE_TC_NUM; i++)
>> + for (i = 0; i < HCLGE_TC_NUM; i++) {
>> + priv = &hdev->priv_buf[i];
>> + buf_size = priv->tx_buf_size;
>> req->tx_pkt_buff[i] =
>> cpu_to_le16((buf_size >> HCLGE_BUF_SIZE_UNIT_SHIFT) |
buf_size is used here
>> HCLGE_BUF_SIZE_UPDATE_EN_MSK);
>> + }
>>
>> ret = hclge_cmd_send(&hdev->hw, &desc, 1);
>> if (ret) {
>
> Local variable 'buf_size' is assigned but never used in this function.
> And with 'buf_size' removed, 'priv' also becomes unused.
>
> If it gets used in a later patch, add it in that later patch.
>
> You can also declare the variables locally in the basic block of
> the for() loop.
You are right. Will do it if there is more comment coming, thanks for
reviewing .
>
> .
>
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2017-09-22 05:50 +0200 |
| Subject | Re: [PATCH net-next 01/10] net: hns3: Support for dynamically assigning tx buffer to TC |
| Message-ID | <usn8t-19x-1@gated-at.bofh.it> |
| In reply to | #1737132 |
From: Yunsheng Lin <linyunsheng@huawei.com>
Date: Fri, 22 Sep 2017 09:57:31 +0800
> Hi, David
>
> On 2017/9/22 9:41, David Miller wrote:
>> From: Yunsheng Lin <linyunsheng@huawei.com>
>> Date: Thu, 21 Sep 2017 19:21:44 +0800
>>
>>> @@ -1324,23 +1324,28 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
>>> return 0;
>>> }
>>>
>>> -static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev, u16 buf_size)
>>> +static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev)
>>> {
>>> /* TX buffer size is unit by 128 byte */
>>> #define HCLGE_BUF_SIZE_UNIT_SHIFT 7
>>> #define HCLGE_BUF_SIZE_UPDATE_EN_MSK BIT(15)
>>> struct hclge_tx_buff_alloc *req;
>>> + struct hclge_priv_buf *priv;
>>> struct hclge_desc desc;
>>> + u32 buf_size;
>>> int ret;
>>> u8 i;
>>>
>>> req = (struct hclge_tx_buff_alloc *)desc.data;
>>>
>>> hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, 0);
>>> - for (i = 0; i < HCLGE_TC_NUM; i++)
>>> + for (i = 0; i < HCLGE_TC_NUM; i++) {
>>> + priv = &hdev->priv_buf[i];
>>> + buf_size = priv->tx_buf_size;
>>> req->tx_pkt_buff[i] =
>>> cpu_to_le16((buf_size >> HCLGE_BUF_SIZE_UNIT_SHIFT) |
>
> buf_size is used here
My bad, I misread the code.
Thanks.
[toc] | [prev] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-21 13:30 +0200 |
| Subject | [PATCH net-next 02/10] net: hns3: Add support for dynamically buffer reallocation |
| Message-ID | <us7Q7-kv-27@gated-at.bofh.it> |
| In reply to | #1736556 |
Current buffer allocation can only happen at init, when
doing buffer reallocation after init, care must be taken
care of memory which priv_buf points to.
This patch fixes it by using a dynamic allocated temporary
memory. Because we only do buffer reallocation at init or
when setting up the DCB parameter, and priv_buf is only
used at buffer allocation process, so it is ok to use a
dynamic allocated temporary memory.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 5 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 150 +++++++++++----------
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 -
3 files changed, 87 insertions(+), 70 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index a81c6cb..6b6d28e 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -322,6 +322,11 @@ struct hclge_shared_buf {
u32 buf_size;
};
+struct hclge_pkt_buf_alloc {
+ struct hclge_priv_buf priv_buf[HCLGE_MAX_TC_NUM];
+ struct hclge_shared_buf s_buf;
+};
+
#define HCLGE_RX_COM_WL_EN_B 15
struct hclge_rx_com_wl_buf {
__le16 high_wl;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index dfe0fd2..c27b460 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1324,7 +1324,8 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
return 0;
}
-static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev)
+static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
/* TX buffer size is unit by 128 byte */
#define HCLGE_BUF_SIZE_UNIT_SHIFT 7
@@ -1340,7 +1341,7 @@ static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev)
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, 0);
for (i = 0; i < HCLGE_TC_NUM; i++) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
buf_size = priv->tx_buf_size;
req->tx_pkt_buff[i] =
cpu_to_le16((buf_size >> HCLGE_BUF_SIZE_UNIT_SHIFT) |
@@ -1357,9 +1358,10 @@ static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev)
return 0;
}
-static int hclge_tx_buffer_alloc(struct hclge_dev *hdev)
+static int hclge_tx_buffer_alloc(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
- int ret = hclge_cmd_alloc_tx_buff(hdev);
+ int ret = hclge_cmd_alloc_tx_buff(hdev, buf_alloc);
if (ret) {
dev_err(&hdev->pdev->dev,
@@ -1392,13 +1394,14 @@ static int hclge_get_pfc_enalbe_num(struct hclge_dev *hdev)
}
/* Get the number of pfc enabled TCs, which have private buffer */
-static int hclge_get_pfc_priv_num(struct hclge_dev *hdev)
+static int hclge_get_pfc_priv_num(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
struct hclge_priv_buf *priv;
int i, cnt = 0;
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
if ((hdev->tm_info.hw_pfc_map & BIT(i)) &&
priv->enable)
cnt++;
@@ -1408,13 +1411,14 @@ static int hclge_get_pfc_priv_num(struct hclge_dev *hdev)
}
/* Get the number of pfc disabled TCs, which have private buffer */
-static int hclge_get_no_pfc_priv_num(struct hclge_dev *hdev)
+static int hclge_get_no_pfc_priv_num(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
struct hclge_priv_buf *priv;
int i, cnt = 0;
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
if (hdev->hw_tc_map & BIT(i) &&
!(hdev->tm_info.hw_pfc_map & BIT(i)) &&
priv->enable)
@@ -1424,33 +1428,35 @@ static int hclge_get_no_pfc_priv_num(struct hclge_dev *hdev)
return cnt;
}
-static u32 hclge_get_rx_priv_buff_alloced(struct hclge_dev *hdev)
+static u32 hclge_get_rx_priv_buff_alloced(struct hclge_pkt_buf_alloc *buf_alloc)
{
struct hclge_priv_buf *priv;
u32 rx_priv = 0;
int i;
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
if (priv->enable)
rx_priv += priv->buf_size;
}
return rx_priv;
}
-static u32 hclge_get_tx_buff_alloced(struct hclge_dev *hdev)
+static u32 hclge_get_tx_buff_alloced(struct hclge_pkt_buf_alloc *buf_alloc)
{
struct hclge_priv_buf *priv;
u32 tx_buf = 0, i;
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
tx_buf += priv->tx_buf_size;
}
return tx_buf;
}
-static bool hclge_is_rx_buf_ok(struct hclge_dev *hdev, u32 rx_all)
+static bool hclge_is_rx_buf_ok(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc,
+ u32 rx_all)
{
u32 shared_buf_min, shared_buf_tc, shared_std;
int tc_num, pfc_enable_num;
@@ -1471,30 +1477,31 @@ static bool hclge_is_rx_buf_ok(struct hclge_dev *hdev, u32 rx_all)
hdev->mps;
shared_std = max_t(u32, shared_buf_min, shared_buf_tc);
- rx_priv = hclge_get_rx_priv_buff_alloced(hdev);
+ rx_priv = hclge_get_rx_priv_buff_alloced(buf_alloc);
if (rx_all <= rx_priv + shared_std)
return false;
shared_buf = rx_all - rx_priv;
- hdev->s_buf.buf_size = shared_buf;
- hdev->s_buf.self.high = shared_buf;
- hdev->s_buf.self.low = 2 * hdev->mps;
+ buf_alloc->s_buf.buf_size = shared_buf;
+ buf_alloc->s_buf.self.high = shared_buf;
+ buf_alloc->s_buf.self.low = 2 * hdev->mps;
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
if ((hdev->hw_tc_map & BIT(i)) &&
(hdev->tm_info.hw_pfc_map & BIT(i))) {
- hdev->s_buf.tc_thrd[i].low = hdev->mps;
- hdev->s_buf.tc_thrd[i].high = 2 * hdev->mps;
+ buf_alloc->s_buf.tc_thrd[i].low = hdev->mps;
+ buf_alloc->s_buf.tc_thrd[i].high = 2 * hdev->mps;
} else {
- hdev->s_buf.tc_thrd[i].low = 0;
- hdev->s_buf.tc_thrd[i].high = hdev->mps;
+ buf_alloc->s_buf.tc_thrd[i].low = 0;
+ buf_alloc->s_buf.tc_thrd[i].high = hdev->mps;
}
}
return true;
}
-static int hclge_tx_buffer_calc(struct hclge_dev *hdev)
+static int hclge_tx_buffer_calc(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
struct hclge_priv_buf *priv;
u32 i, total_size;
@@ -1503,7 +1510,7 @@ static int hclge_tx_buffer_calc(struct hclge_dev *hdev)
/* alloc tx buffer for all enabled tc */
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
if (total_size < HCLGE_DEFAULT_TX_BUF)
return -ENOMEM;
@@ -1521,22 +1528,24 @@ static int hclge_tx_buffer_calc(struct hclge_dev *hdev)
/* hclge_rx_buffer_calc: calculate the rx private buffer size for all TCs
* @hdev: pointer to struct hclge_dev
+ * @buf_alloc: pointer to buffer calculation data
* @return: 0: calculate sucessful, negative: fail
*/
-int hclge_rx_buffer_calc(struct hclge_dev *hdev)
+int hclge_rx_buffer_calc(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
u32 rx_all = hdev->pkt_buf_size;
int no_pfc_priv_num, pfc_priv_num;
struct hclge_priv_buf *priv;
int i;
- rx_all -= hclge_get_tx_buff_alloced(hdev);
+ rx_all -= hclge_get_tx_buff_alloced(buf_alloc);
/* When DCB is not supported, rx private
* buffer is not allocated.
*/
if (!hnae3_dev_dcb_supported(hdev)) {
- if (!hclge_is_rx_buf_ok(hdev, rx_all))
+ if (!hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
return -ENOMEM;
return 0;
@@ -1544,7 +1553,7 @@ int hclge_rx_buffer_calc(struct hclge_dev *hdev)
/* step 1, try to alloc private buffer for all enabled tc */
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
if (hdev->hw_tc_map & BIT(i)) {
priv->enable = 1;
if (hdev->tm_info.hw_pfc_map & BIT(i)) {
@@ -1565,14 +1574,14 @@ int hclge_rx_buffer_calc(struct hclge_dev *hdev)
}
}
- if (hclge_is_rx_buf_ok(hdev, rx_all))
+ if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
return 0;
/* step 2, try to decrease the buffer size of
* no pfc TC's private buffer
*/
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
priv->enable = 0;
priv->wl.low = 0;
@@ -1595,18 +1604,18 @@ int hclge_rx_buffer_calc(struct hclge_dev *hdev)
}
}
- if (hclge_is_rx_buf_ok(hdev, rx_all))
+ if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
return 0;
/* step 3, try to reduce the number of pfc disabled TCs,
* which have private buffer
*/
/* get the total no pfc enable TC number, which have private buffer */
- no_pfc_priv_num = hclge_get_no_pfc_priv_num(hdev);
+ no_pfc_priv_num = hclge_get_no_pfc_priv_num(hdev, buf_alloc);
/* let the last to be cleared first */
for (i = HCLGE_MAX_TC_NUM - 1; i >= 0; i--) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
if (hdev->hw_tc_map & BIT(i) &&
!(hdev->tm_info.hw_pfc_map & BIT(i))) {
@@ -1618,22 +1627,22 @@ int hclge_rx_buffer_calc(struct hclge_dev *hdev)
no_pfc_priv_num--;
}
- if (hclge_is_rx_buf_ok(hdev, rx_all) ||
+ if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all) ||
no_pfc_priv_num == 0)
break;
}
- if (hclge_is_rx_buf_ok(hdev, rx_all))
+ if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
return 0;
/* step 4, try to reduce the number of pfc enabled TCs
* which have private buffer.
*/
- pfc_priv_num = hclge_get_pfc_priv_num(hdev);
+ pfc_priv_num = hclge_get_pfc_priv_num(hdev, buf_alloc);
/* let the last to be cleared first */
for (i = HCLGE_MAX_TC_NUM - 1; i >= 0; i--) {
- priv = &hdev->priv_buf[i];
+ priv = &buf_alloc->priv_buf[i];
if (hdev->hw_tc_map & BIT(i) &&
hdev->tm_info.hw_pfc_map & BIT(i)) {
@@ -1645,17 +1654,18 @@ int hclge_rx_buffer_calc(struct hclge_dev *hdev)
pfc_priv_num--;
}
- if (hclge_is_rx_buf_ok(hdev, rx_all) ||
+ if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all) ||
pfc_priv_num == 0)
break;
}
- if (hclge_is_rx_buf_ok(hdev, rx_all))
+ if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all))
return 0;
return -ENOMEM;
}
-static int hclge_rx_priv_buf_alloc(struct hclge_dev *hdev)
+static int hclge_rx_priv_buf_alloc(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
struct hclge_rx_priv_buff *req;
struct hclge_desc desc;
@@ -1667,7 +1677,7 @@ static int hclge_rx_priv_buf_alloc(struct hclge_dev *hdev)
/* Alloc private buffer TCs */
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- struct hclge_priv_buf *priv = &hdev->priv_buf[i];
+ struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i];
req->buf_num[i] =
cpu_to_le16(priv->buf_size >> HCLGE_BUF_UNIT_S);
@@ -1676,7 +1686,7 @@ static int hclge_rx_priv_buf_alloc(struct hclge_dev *hdev)
}
req->shared_buf =
- cpu_to_le16((hdev->s_buf.buf_size >> HCLGE_BUF_UNIT_S) |
+ cpu_to_le16((buf_alloc->s_buf.buf_size >> HCLGE_BUF_UNIT_S) |
(1 << HCLGE_TC0_PRI_BUF_EN_B));
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -1691,7 +1701,8 @@ static int hclge_rx_priv_buf_alloc(struct hclge_dev *hdev)
#define HCLGE_PRIV_ENABLE(a) ((a) > 0 ? 1 : 0)
-static int hclge_rx_priv_wl_config(struct hclge_dev *hdev)
+static int hclge_rx_priv_wl_config(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
struct hclge_rx_priv_wl_buf *req;
struct hclge_priv_buf *priv;
@@ -1711,7 +1722,9 @@ static int hclge_rx_priv_wl_config(struct hclge_dev *hdev)
desc[i].flag &= ~cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
for (j = 0; j < HCLGE_TC_NUM_ONE_DESC; j++) {
- priv = &hdev->priv_buf[i * HCLGE_TC_NUM_ONE_DESC + j];
+ u32 idx = i * HCLGE_TC_NUM_ONE_DESC + j;
+
+ priv = &buf_alloc->priv_buf[idx];
req->tc_wl[j].high =
cpu_to_le16(priv->wl.high >> HCLGE_BUF_UNIT_S);
req->tc_wl[j].high |=
@@ -1736,9 +1749,10 @@ static int hclge_rx_priv_wl_config(struct hclge_dev *hdev)
return 0;
}
-static int hclge_common_thrd_config(struct hclge_dev *hdev)
+static int hclge_common_thrd_config(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
- struct hclge_shared_buf *s_buf = &hdev->s_buf;
+ struct hclge_shared_buf *s_buf = &buf_alloc->s_buf;
struct hclge_rx_com_thrd *req;
struct hclge_desc desc[2];
struct hclge_tc_thrd *tc;
@@ -1782,9 +1796,10 @@ static int hclge_common_thrd_config(struct hclge_dev *hdev)
return 0;
}
-static int hclge_common_wl_config(struct hclge_dev *hdev)
+static int hclge_common_wl_config(struct hclge_dev *hdev,
+ struct hclge_pkt_buf_alloc *buf_alloc)
{
- struct hclge_shared_buf *buf = &hdev->s_buf;
+ struct hclge_shared_buf *buf = &buf_alloc->s_buf;
struct hclge_rx_com_wl *req;
struct hclge_desc desc;
int ret;
@@ -1814,69 +1829,68 @@ static int hclge_common_wl_config(struct hclge_dev *hdev)
int hclge_buffer_alloc(struct hclge_dev *hdev)
{
+ struct hclge_pkt_buf_alloc *pkt_buf;
int ret;
- hdev->priv_buf = devm_kmalloc_array(&hdev->pdev->dev, HCLGE_MAX_TC_NUM,
- sizeof(struct hclge_priv_buf),
- GFP_KERNEL | __GFP_ZERO);
- if (!hdev->priv_buf)
+ pkt_buf = kzalloc(sizeof(*pkt_buf), GFP_KERNEL);
+ if (!pkt_buf)
return -ENOMEM;
- ret = hclge_tx_buffer_calc(hdev);
+ ret = hclge_tx_buffer_calc(hdev, pkt_buf);
if (ret) {
dev_err(&hdev->pdev->dev,
"could not calc tx buffer size for all TCs %d\n", ret);
- return ret;
+ goto out;
}
- ret = hclge_tx_buffer_alloc(hdev);
+ ret = hclge_tx_buffer_alloc(hdev, pkt_buf);
if (ret) {
dev_err(&hdev->pdev->dev,
"could not alloc tx buffers %d\n", ret);
- return ret;
+ goto out;
}
- ret = hclge_rx_buffer_calc(hdev);
+ ret = hclge_rx_buffer_calc(hdev, pkt_buf);
if (ret) {
dev_err(&hdev->pdev->dev,
"could not calc rx priv buffer size for all TCs %d\n",
ret);
- return ret;
+ goto out;
}
- ret = hclge_rx_priv_buf_alloc(hdev);
+ ret = hclge_rx_priv_buf_alloc(hdev, pkt_buf);
if (ret) {
dev_err(&hdev->pdev->dev, "could not alloc rx priv buffer %d\n",
ret);
- return ret;
+ goto out;
}
if (hnae3_dev_dcb_supported(hdev)) {
- ret = hclge_rx_priv_wl_config(hdev);
+ ret = hclge_rx_priv_wl_config(hdev, pkt_buf);
if (ret) {
dev_err(&hdev->pdev->dev,
"could not configure rx private waterline %d\n",
ret);
- return ret;
+ goto out;
}
- ret = hclge_common_thrd_config(hdev);
+ ret = hclge_common_thrd_config(hdev, pkt_buf);
if (ret) {
dev_err(&hdev->pdev->dev,
"could not configure common threshold %d\n",
ret);
- return ret;
+ goto out;
}
}
- ret = hclge_common_wl_config(hdev);
- if (ret) {
+ ret = hclge_common_wl_config(hdev, pkt_buf);
+ if (ret)
dev_err(&hdev->pdev->dev,
"could not configure common waterline %d\n", ret);
- return ret;
- }
- return 0;
+out:
+ kfree(pkt_buf);
+ return ret;
}
static int hclge_init_roce_base_info(struct hclge_vport *vport)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 9fcfd93..4fc36f0 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -463,8 +463,6 @@ struct hclge_dev {
u32 pkt_buf_size; /* Total pf buf size for tx/rx */
u32 mps; /* Max packet size */
- struct hclge_priv_buf *priv_buf;
- struct hclge_shared_buf s_buf;
enum hclge_mta_dmac_sel_type mta_mac_sel_type;
bool enable_mta; /* Mutilcast filter enable */
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-21 13:30 +0200 |
| Subject | [PATCH net-next 06/10] net: hns3: Add some interface for the support of DCB feature |
| Message-ID | <us7Q6-kv-23@gated-at.bofh.it> |
| In reply to | #1736556 |
This patch add some interface and export some interface from
hclge_tm and hclgc_main to support the upcoming DCB feature.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +-
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 3 ++
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 48 ++++++++++++++++++++--
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 6 +++
4 files changed, 55 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index c27b460..49a11d5 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -30,7 +30,6 @@
#define HCLGE_64BIT_STATS_FIELD_OFF(f) (offsetof(struct hclge_64_bit_stats, f))
#define HCLGE_32BIT_STATS_FIELD_OFF(f) (offsetof(struct hclge_32_bit_stats, f))
-static int hclge_rss_init_hw(struct hclge_dev *hdev);
static int hclge_set_mta_filter_mode(struct hclge_dev *hdev,
enum hclge_mta_dmac_sel_type mta_mac_sel,
bool enable);
@@ -2660,7 +2659,7 @@ static int hclge_get_tc_size(struct hnae3_handle *handle)
return hdev->rss_size_max;
}
-static int hclge_rss_init_hw(struct hclge_dev *hdev)
+int hclge_rss_init_hw(struct hclge_dev *hdev)
{
const u8 hfunc = HCLGE_RSS_HASH_ALGO_TOEPLITZ;
struct hclge_vport *vport = hdev->vport;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 4fc36f0..394b587 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -515,4 +515,7 @@ static inline int hclge_get_queue_id(struct hnae3_queue *queue)
int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex);
int hclge_set_vf_vlan_common(struct hclge_dev *vport, int vfid,
bool is_kill, u16 vlan, u8 qos, __be16 proto);
+
+int hclge_buffer_alloc(struct hclge_dev *hdev);
+int hclge_rss_init_hw(struct hclge_dev *hdev);
#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
index 2bc7d63c..e158e66 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -884,10 +884,14 @@ static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev)
return 0;
}
-static int hclge_tm_map_cfg(struct hclge_dev *hdev)
+int hclge_tm_map_cfg(struct hclge_dev *hdev)
{
int ret;
+ ret = hclge_up_to_tc_map(hdev);
+ if (ret)
+ return ret;
+
ret = hclge_tm_pg_to_pri_map(hdev);
if (ret)
return ret;
@@ -995,7 +999,7 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev)
return 0;
}
-static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev)
+int hclge_tm_schd_mode_hw(struct hclge_dev *hdev)
{
int ret;
@@ -1093,7 +1097,45 @@ int hclge_pause_setup_hw(struct hclge_dev *hdev)
return ret;
}
- return hclge_up_to_tc_map(hdev);
+ return 0;
+}
+
+int hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc)
+{
+ struct hclge_vport *vport = hdev->vport;
+ struct hnae3_knic_private_info *kinfo;
+ u32 i, k;
+
+ for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {
+ if (prio_tc[i] >= hdev->tm_info.num_tc)
+ return -EINVAL;
+ hdev->tm_info.prio_tc[i] = prio_tc[i];
+
+ for (k = 0; k < hdev->num_alloc_vport; k++) {
+ kinfo = &vport[k].nic.kinfo;
+ kinfo->prio_tc[i] = prio_tc[i];
+ }
+ }
+ return 0;
+}
+
+void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc)
+{
+ u8 i, bit_map = 0;
+
+ hdev->tm_info.num_tc = num_tc;
+
+ for (i = 0; i < hdev->tm_info.num_tc; i++)
+ bit_map |= BIT(i);
+
+ if (!bit_map) {
+ bit_map = 1;
+ hdev->tm_info.num_tc = 1;
+ }
+
+ hdev->hw_tc_map = bit_map;
+
+ hclge_tm_schd_info_init(hdev);
}
int hclge_tm_init_hw(struct hclge_dev *hdev)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
index 19a01e4..bf59961 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
@@ -112,4 +112,10 @@ struct hclge_port_shapping_cmd {
int hclge_tm_schd_init(struct hclge_dev *hdev);
int hclge_pause_setup_hw(struct hclge_dev *hdev);
+int hclge_tm_schd_mode_hw(struct hclge_dev *hdev);
+int hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc);
+void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc);
+int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
+int hclge_tm_map_cfg(struct hclge_dev *hdev);
+int hclge_tm_init_hw(struct hclge_dev *hdev);
#endif
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-21 13:30 +0200 |
| Subject | [PATCH net-next 09/10] net: hns3: Setting for fc_mode and dcb enable flag in TM module |
| Message-ID | <us7Q8-kv-59@gated-at.bofh.it> |
| In reply to | #1736556 |
After the DCB feature is supported, fc_mode and dcb enable flag
must be set according to the DCB parameter.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 34 +++++++++++++++++++---
1 file changed, 30 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
index e158e66..cc5efda 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -487,7 +487,11 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
hdev->tm_info.prio_tc[i] =
(i >= hdev->tm_info.num_tc) ? 0 : i;
- hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
+ /* DCB is enabled if we have more than 1 TC */
+ if (hdev->tm_info.num_tc > 1)
+ hdev->flag |= HCLGE_FLAG_DCB_ENABLE;
+ else
+ hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
}
static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
@@ -513,6 +517,24 @@ static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
}
}
+static void hclge_pfc_info_init(struct hclge_dev *hdev)
+{
+ if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) {
+ if (hdev->fc_mode_last_time == HCLGE_FC_PFC)
+ dev_warn(&hdev->pdev->dev,
+ "DCB is disable, but last mode is FC_PFC\n");
+
+ hdev->tm_info.fc_mode = hdev->fc_mode_last_time;
+ } else if (hdev->tm_info.fc_mode != HCLGE_FC_PFC) {
+ /* fc_mode_last_time record the last fc_mode when
+ * DCB is enabled, so that fc_mode can be set to
+ * the correct value when DCB is disabled.
+ */
+ hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
+ hdev->tm_info.fc_mode = HCLGE_FC_PFC;
+ }
+}
+
static int hclge_tm_schd_info_init(struct hclge_dev *hdev)
{
if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) &&
@@ -525,8 +547,7 @@ static int hclge_tm_schd_info_init(struct hclge_dev *hdev)
hclge_tm_vport_info_update(hdev);
- hdev->tm_info.fc_mode = HCLGE_FC_NONE;
- hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
+ hclge_pfc_info_init(hdev);
return 0;
}
@@ -1159,8 +1180,13 @@ int hclge_tm_init_hw(struct hclge_dev *hdev)
int hclge_tm_schd_init(struct hclge_dev *hdev)
{
- int ret = hclge_tm_schd_info_init(hdev);
+ int ret;
+
+ /* fc_mode is HCLGE_FC_FULL on reset */
+ hdev->tm_info.fc_mode = HCLGE_FC_FULL;
+ hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
+ ret = hclge_tm_schd_info_init(hdev);
if (ret)
return ret;
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-21 13:30 +0200 |
| Subject | [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack |
| Message-ID | <us7Q7-kv-49@gated-at.bofh.it> |
| In reply to | #1736556 |
When using tc qdisc to configure DCB parameter, dcb_ops->setup_tc
is used to tell hclge_dcb module to do the setup.
When using lldptool to configure DCB parameter, hclge_dcb module
call the client_ops->setup_tc to tell network stack which queue
and priority is using for specific tc.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c | 135 +++++++++++++++++----
1 file changed, 111 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
index 11dab26..31fcda4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
@@ -196,6 +196,32 @@ static void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector)
tqp_vector->tx_group.flow_level = HNS3_FLOW_LOW;
}
+static int hns3_nic_set_real_num_queue(struct net_device *netdev)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+ struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_knic_private_info *kinfo = &h->kinfo;
+ unsigned int queue_size = kinfo->rss_size * kinfo->num_tc;
+ int ret;
+
+ ret = netif_set_real_num_tx_queues(netdev, queue_size);
+ if (ret) {
+ netdev_err(netdev,
+ "netif_set_real_num_tx_queues fail, ret=%d!\n",
+ ret);
+ return ret;
+ }
+
+ ret = netif_set_real_num_rx_queues(netdev, queue_size);
+ if (ret) {
+ netdev_err(netdev,
+ "netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static int hns3_nic_net_up(struct net_device *netdev)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
@@ -232,26 +258,13 @@ static int hns3_nic_net_up(struct net_device *netdev)
static int hns3_nic_net_open(struct net_device *netdev)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
int ret;
netif_carrier_off(netdev);
- ret = netif_set_real_num_tx_queues(netdev, h->kinfo.num_tqps);
- if (ret) {
- netdev_err(netdev,
- "netif_set_real_num_tx_queues fail, ret=%d!\n",
- ret);
- return ret;
- }
-
- ret = netif_set_real_num_rx_queues(netdev, h->kinfo.num_tqps);
- if (ret) {
- netdev_err(netdev,
- "netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
+ ret = hns3_nic_set_real_num_queue(netdev);
+ if (ret)
return ret;
- }
ret = hns3_nic_net_up(netdev);
if (ret) {
@@ -1193,32 +1206,40 @@ static void hns3_nic_udp_tunnel_del(struct net_device *netdev,
}
}
-static int hns3_setup_tc(struct net_device *netdev, u8 tc)
+static int hns3_setup_tc(struct net_device *netdev, u8 tc, u8 *prio_tc)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
struct hnae3_knic_private_info *kinfo = &h->kinfo;
+ bool if_running = netif_running(netdev);
unsigned int i;
int ret;
if (tc > HNAE3_MAX_TC)
return -EINVAL;
- if (kinfo->num_tc == tc)
- return 0;
-
if (!netdev)
return -EINVAL;
- if (!tc) {
+ if (if_running) {
+ (void)hns3_nic_net_stop(netdev);
+ msleep(100);
+ }
+
+ ret = (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
+ kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP;
+ if (ret)
+ goto err_out;
+
+ if (tc <= 1) {
netdev_reset_tc(netdev);
- return 0;
+ goto out;
}
/* Set num_tc for netdev */
ret = netdev_set_num_tc(netdev, tc);
if (ret)
- return ret;
+ goto err_out;
/* Set per TC queues for the VSI */
for (i = 0; i < HNAE3_MAX_TC; i++) {
@@ -1229,7 +1250,14 @@ static int hns3_setup_tc(struct net_device *netdev, u8 tc)
kinfo->tc_info[i].tqp_offset);
}
- return 0;
+out:
+ ret = hns3_nic_set_real_num_queue(netdev);
+
+err_out:
+ if (if_running)
+ (void)hns3_nic_net_open(netdev);
+
+ return ret;
}
static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
@@ -1240,7 +1268,7 @@ static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
if (type != TC_SETUP_MQPRIO)
return -EOPNOTSUPP;
- return hns3_setup_tc(dev, mqprio->num_tc);
+ return hns3_setup_tc(dev, mqprio->num_tc, mqprio->prio_tc_map);
}
static int hns3_vlan_rx_add_vid(struct net_device *netdev,
@@ -2848,10 +2876,69 @@ static void hns3_link_status_change(struct hnae3_handle *handle, bool linkup)
}
}
+static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc)
+{
+ struct hnae3_knic_private_info *kinfo = &handle->kinfo;
+ struct net_device *ndev = kinfo->netdev;
+ bool if_running = netif_running(ndev);
+ int ret;
+ u8 i;
+
+ if (tc > HNAE3_MAX_TC)
+ return -EINVAL;
+
+ if (!ndev)
+ return -ENODEV;
+
+ ret = netdev_set_num_tc(ndev, tc);
+ if (ret)
+ return ret;
+
+ if (if_running) {
+ (void)hns3_nic_net_stop(ndev);
+ msleep(100);
+ }
+
+ ret = (kinfo->dcb_ops && kinfo->dcb_ops->map_update) ?
+ kinfo->dcb_ops->map_update(handle) : -EOPNOTSUPP;
+ if (ret)
+ goto err_out;
+
+ if (tc <= 1) {
+ netdev_reset_tc(ndev);
+ goto out;
+ }
+
+ for (i = 0; i < HNAE3_MAX_TC; i++) {
+ struct hnae3_tc_info *tc_info = &kinfo->tc_info[i];
+
+ if (tc_info->enable)
+ netdev_set_tc_queue(ndev,
+ tc_info->tc,
+ tc_info->tqp_count,
+ tc_info->tqp_offset);
+ }
+
+ for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {
+ netdev_set_prio_tc_map(ndev, i,
+ kinfo->prio_tc[i]);
+ }
+
+out:
+ ret = hns3_nic_set_real_num_queue(ndev);
+
+err_out:
+ if (if_running)
+ (void)hns3_nic_net_open(ndev);
+
+ return ret;
+}
+
const struct hnae3_client_ops client_ops = {
.init_instance = hns3_client_init,
.uninit_instance = hns3_client_uninit,
.link_status_change = hns3_link_status_change,
+ .setup_tc = hns3_client_setup_tc,
};
/* hns3_init_module - Driver registration routine
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Jiri Pirko <jiri@resnulli.us> |
|---|---|
| Date | 2017-09-22 15:00 +0200 |
| Subject | Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack |
| Message-ID | <usvIJ-6c6-3@gated-at.bofh.it> |
| In reply to | #1736575 |
Thu, Sep 21, 2017 at 01:21:53PM CEST, linyunsheng@huawei.com wrote:
>When using tc qdisc to configure DCB parameter, dcb_ops->setup_tc
>is used to tell hclge_dcb module to do the setup.
>When using lldptool to configure DCB parameter, hclge_dcb module
>call the client_ops->setup_tc to tell network stack which queue
>and priority is using for specific tc.
>
>Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
[...]
>-static int hns3_setup_tc(struct net_device *netdev, u8 tc)
>+static int hns3_setup_tc(struct net_device *netdev, u8 tc, u8 *prio_tc)
> {
> struct hns3_nic_priv *priv = netdev_priv(netdev);
> struct hnae3_handle *h = priv->ae_handle;
> struct hnae3_knic_private_info *kinfo = &h->kinfo;
>+ bool if_running = netif_running(netdev);
> unsigned int i;
> int ret;
>
> if (tc > HNAE3_MAX_TC)
> return -EINVAL;
>
>- if (kinfo->num_tc == tc)
>- return 0;
>-
> if (!netdev)
> return -EINVAL;
>
>- if (!tc) {
>+ if (if_running) {
>+ (void)hns3_nic_net_stop(netdev);
>+ msleep(100);
>+ }
>+
>+ ret = (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
>+ kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP;
This is most odd. Why do you call dcb_ops from ndo_setup_tc callback?
Why are you mixing this together? prio->tc mapping can be done
directly in dcbnl
[toc] | [prev] | [next] | [standalone]
| From | Jiri Pirko <jiri@resnulli.us> |
|---|---|
| Date | 2017-09-22 18:10 +0200 |
| Subject | Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack |
| Message-ID | <usyGC-8dH-13@gated-at.bofh.it> |
| In reply to | #1737478 |
Fri, Sep 22, 2017 at 04:11:51PM CEST, linyunsheng@huawei.com wrote:
>Hi, Jiri
>
>>>- if (!tc) {
>>>+ if (if_running) {
>>>+ (void)hns3_nic_net_stop(netdev);
>>>+ msleep(100);
>>>+ }
>>>+
>>>+ ret = (kinfo->dcb_ops && kinfo->dcb_ops->>setup_tc) ?
>>>+ kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : ->EOPNOTSUPP;
>
>>This is most odd. Why do you call dcb_ops from >ndo_setup_tc callback?
>>Why are you mixing this together? prio->tc mapping >can be done
>>directly in dcbnl
>
>Here is what we do in dcb_ops->setup_tc:
>Firstly, if current tc num is different from the tc num
>that user provide, then we setup the queues for each
>tc.
>
>Secondly, we tell hardware the pri to tc mapping that
>the stack is using. In rx direction, our hardware need
>that mapping to put different packet into different tc'
>queues according to the priority of the packet, then
>rss decides which specific queue in the tc should the
>packet goto.
>
>By mixing, I suppose you meant why we need the
>pri to tc infomation?
by mixing, I mean what I wrote. You are calling dcb_ops callback from
ndo_setup_tc callback. So you are mixing DCBNL subsystem and TC
subsystem. Why? Why do you need sch_mqprio? Why DCBNL is not enough for
all?
>I hope I did not misunderstand your question, thanks
>for your time reviewing.
[toc] | [prev] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-23 02:50 +0200 |
| Subject | Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack |
| Message-ID | <usGNP-4A1-1@gated-at.bofh.it> |
| In reply to | #1737602 |
Hi, Jiri
On 2017/9/23 0:03, Jiri Pirko wrote:
> Fri, Sep 22, 2017 at 04:11:51PM CEST, linyunsheng@huawei.com wrote:
>> Hi, Jiri
>>
>>>> - if (!tc) {
>>>> + if (if_running) {
>>>> + (void)hns3_nic_net_stop(netdev);
>>>> + msleep(100);
>>>> + }
>>>> +
>>>> + ret = (kinfo->dcb_ops && kinfo->dcb_ops->>setup_tc) ?
>>>> + kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : ->EOPNOTSUPP;
>>
>>> This is most odd. Why do you call dcb_ops from >ndo_setup_tc callback?
>>> Why are you mixing this together? prio->tc mapping >can be done
>>> directly in dcbnl
>>
>> Here is what we do in dcb_ops->setup_tc:
>> Firstly, if current tc num is different from the tc num
>> that user provide, then we setup the queues for each
>> tc.
>>
>> Secondly, we tell hardware the pri to tc mapping that
>> the stack is using. In rx direction, our hardware need
>> that mapping to put different packet into different tc'
>> queues according to the priority of the packet, then
>> rss decides which specific queue in the tc should the
>> packet goto.
>>
>> By mixing, I suppose you meant why we need the
>> pri to tc infomation?
>
> by mixing, I mean what I wrote. You are calling dcb_ops callback from
> ndo_setup_tc callback. So you are mixing DCBNL subsystem and TC
> subsystem. Why? Why do you need sch_mqprio? Why DCBNL is not enough for
> all?
When using lldptool, dcbnl is involved.
But when using tc qdisc, dcbbl is not involved, below is the a few key
call graph in the kernel when tc qdisc cmd is executed.
cmd:
tc qdisc add dev eth0 root handle 1:0 mqprio num_tc 4 map 1 2 3 3 1 3 1 1 hw 1
call graph:
rtnetlink_rcv_msg -> tc_modify_qdisc -> qdisc_create -> mqprio_init ->
hns3_nic_setup_tc
When hns3_nic_setup_tc is called, we need to know how many tc num and
prio_tc mapping from the tc_mqprio_qopt which is provided in the paramter
in the ndo_setup_tc function, and dcb_ops is the our hardware specific
method to setup the tc related parameter to the hardware, so this is why
we call dcb_ops callback in ndo_setup_tc callback.
I hope this will answer your question, thanks for your time.
>
>
>
>> I hope I did not misunderstand your question, thanks
>> for your time reviewing.
>
> .
>
[toc] | [prev] | [next] | [standalone]
| From | Jiri Pirko <jiri@resnulli.us> |
|---|---|
| Date | 2017-09-24 13:40 +0200 |
| Subject | Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack |
| Message-ID | <utdqq-87X-21@gated-at.bofh.it> |
| In reply to | #1737943 |
Sat, Sep 23, 2017 at 02:47:20AM CEST, linyunsheng@huawei.com wrote:
>Hi, Jiri
>
>On 2017/9/23 0:03, Jiri Pirko wrote:
>> Fri, Sep 22, 2017 at 04:11:51PM CEST, linyunsheng@huawei.com wrote:
>>> Hi, Jiri
>>>
>>>>> - if (!tc) {
>>>>> + if (if_running) {
>>>>> + (void)hns3_nic_net_stop(netdev);
>>>>> + msleep(100);
>>>>> + }
>>>>> +
>>>>> + ret = (kinfo->dcb_ops && kinfo->dcb_ops->>setup_tc) ?
>>>>> + kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : ->EOPNOTSUPP;
>>>
>>>> This is most odd. Why do you call dcb_ops from >ndo_setup_tc callback?
>>>> Why are you mixing this together? prio->tc mapping >can be done
>>>> directly in dcbnl
>>>
>>> Here is what we do in dcb_ops->setup_tc:
>>> Firstly, if current tc num is different from the tc num
>>> that user provide, then we setup the queues for each
>>> tc.
>>>
>>> Secondly, we tell hardware the pri to tc mapping that
>>> the stack is using. In rx direction, our hardware need
>>> that mapping to put different packet into different tc'
>>> queues according to the priority of the packet, then
>>> rss decides which specific queue in the tc should the
>>> packet goto.
>>>
>>> By mixing, I suppose you meant why we need the
>>> pri to tc infomation?
>>
>> by mixing, I mean what I wrote. You are calling dcb_ops callback from
>> ndo_setup_tc callback. So you are mixing DCBNL subsystem and TC
>> subsystem. Why? Why do you need sch_mqprio? Why DCBNL is not enough for
>> all?
>
>When using lldptool, dcbnl is involved.
>
>But when using tc qdisc, dcbbl is not involved, below is the a few key
>call graph in the kernel when tc qdisc cmd is executed.
>
>cmd:
>tc qdisc add dev eth0 root handle 1:0 mqprio num_tc 4 map 1 2 3 3 1 3 1 1 hw 1
>
>call graph:
>rtnetlink_rcv_msg -> tc_modify_qdisc -> qdisc_create -> mqprio_init ->
>hns3_nic_setup_tc
>
>When hns3_nic_setup_tc is called, we need to know how many tc num and
>prio_tc mapping from the tc_mqprio_qopt which is provided in the paramter
>in the ndo_setup_tc function, and dcb_ops is the our hardware specific
>method to setup the tc related parameter to the hardware, so this is why
>we call dcb_ops callback in ndo_setup_tc callback.
>
>I hope this will answer your question, thanks for your time.
Okay. I understand that you have a usecase for mqprio mapping offload
without lldptool being involved. Ok. I believe it is wrong to call dcb_ops
from tc callback. You should have a generic layer inside the driver and
call it from both dcb_ops and tc callbacks.
Also, what happens If I run lldptool concurrently with mqprio? Who wins
and is going to configure the mapping?
>
>>
>>
>>
>>> I hope I did not misunderstand your question, thanks
>>> for your time reviewing.
>>
>> .
>>
>
[toc] | [prev] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-25 02:50 +0200 |
| Subject | Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack |
| Message-ID | <utpKV-7gz-7@gated-at.bofh.it> |
| In reply to | #1738166 |
Hi, Jiri
On 2017/9/24 19:37, Jiri Pirko wrote:
> Sat, Sep 23, 2017 at 02:47:20AM CEST, linyunsheng@huawei.com wrote:
>> Hi, Jiri
>>
>> On 2017/9/23 0:03, Jiri Pirko wrote:
>>> Fri, Sep 22, 2017 at 04:11:51PM CEST, linyunsheng@huawei.com wrote:
>>>> Hi, Jiri
>>>>
>>>>>> - if (!tc) {
>>>>>> + if (if_running) {
>>>>>> + (void)hns3_nic_net_stop(netdev);
>>>>>> + msleep(100);
>>>>>> + }
>>>>>> +
>>>>>> + ret = (kinfo->dcb_ops && kinfo->dcb_ops->>setup_tc) ?
>>>>>> + kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : ->EOPNOTSUPP;
>>>>
>>>>> This is most odd. Why do you call dcb_ops from >ndo_setup_tc callback?
>>>>> Why are you mixing this together? prio->tc mapping >can be done
>>>>> directly in dcbnl
>>>>
>>>> Here is what we do in dcb_ops->setup_tc:
>>>> Firstly, if current tc num is different from the tc num
>>>> that user provide, then we setup the queues for each
>>>> tc.
>>>>
>>>> Secondly, we tell hardware the pri to tc mapping that
>>>> the stack is using. In rx direction, our hardware need
>>>> that mapping to put different packet into different tc'
>>>> queues according to the priority of the packet, then
>>>> rss decides which specific queue in the tc should the
>>>> packet goto.
>>>>
>>>> By mixing, I suppose you meant why we need the
>>>> pri to tc infomation?
>>>
>>> by mixing, I mean what I wrote. You are calling dcb_ops callback from
>>> ndo_setup_tc callback. So you are mixing DCBNL subsystem and TC
>>> subsystem. Why? Why do you need sch_mqprio? Why DCBNL is not enough for
>>> all?
>>
>> When using lldptool, dcbnl is involved.
>>
>> But when using tc qdisc, dcbbl is not involved, below is the a few key
>> call graph in the kernel when tc qdisc cmd is executed.
>>
>> cmd:
>> tc qdisc add dev eth0 root handle 1:0 mqprio num_tc 4 map 1 2 3 3 1 3 1 1 hw 1
>>
>> call graph:
>> rtnetlink_rcv_msg -> tc_modify_qdisc -> qdisc_create -> mqprio_init ->
>> hns3_nic_setup_tc
>>
>> When hns3_nic_setup_tc is called, we need to know how many tc num and
>> prio_tc mapping from the tc_mqprio_qopt which is provided in the paramter
>> in the ndo_setup_tc function, and dcb_ops is the our hardware specific
>> method to setup the tc related parameter to the hardware, so this is why
>> we call dcb_ops callback in ndo_setup_tc callback.
>>
>> I hope this will answer your question, thanks for your time.
>
> Okay. I understand that you have a usecase for mqprio mapping offload
> without lldptool being involved. Ok. I believe it is wrong to call dcb_ops
> from tc callback. You should have a generic layer inside the driver and
> call it from both dcb_ops and tc callbacks.
Actually, dcb_ops is our generic layer inside the driver.
Below is high level architecture:
[ tc qdisc ] [ lldpad ]
| |
| |
| |
[ hns3_enet ] [ hns3_dcbnl ]
\ /
\ /
\ /
[ hclge_dcb ]
/ \
/ \
/ \
[ hclgc_main ] [ hclge_tm ]
hns3_enet.c implements the ndo_setup_tc callback.
hns3_dcbnl.c implements the dcbnl_rtnl_ops for stack's DCBNL system.
hclge_dcb implements the dcb_ops.
So we already have a generic layer that tc and dcbnl all call from.
>
> Also, what happens If I run lldptool concurrently with mqprio? Who wins
> and is going to configure the mapping?
Both lldptool and tc qdisc cmd use rtnl interface provided by stack, so
they are both protected by rtnl_lock, so we do not have to do the locking
in the driver.
The locking is in rtnetlink_rcv_msg:
rtnl_lock();
handlers = rtnl_dereference(rtnl_msg_handlers[family]);
if (handlers) {
doit = READ_ONCE(handlers[type].doit);
if (doit)
err = doit(skb, nlh, extack);
}
rtnl_unlock();
Thanks.
>
>
>>
>>>
>>>
>>>
>>>> I hope I did not misunderstand your question, thanks
>>>> for your time reviewing.
>>>
>>> .
>>>
>>
>
> .
>
[toc] | [prev] | [next] | [standalone]
| From | Jiri Pirko <jiri@resnulli.us> |
|---|---|
| Date | 2017-09-25 09:00 +0200 |
| Subject | Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack |
| Message-ID | <utvx0-2Kk-7@gated-at.bofh.it> |
| In reply to | #1738612 |
Mon, Sep 25, 2017 at 02:45:08AM CEST, linyunsheng@huawei.com wrote:
>Hi, Jiri
>
>On 2017/9/24 19:37, Jiri Pirko wrote:
>> Sat, Sep 23, 2017 at 02:47:20AM CEST, linyunsheng@huawei.com wrote:
>>> Hi, Jiri
>>>
>>> On 2017/9/23 0:03, Jiri Pirko wrote:
>>>> Fri, Sep 22, 2017 at 04:11:51PM CEST, linyunsheng@huawei.com wrote:
>>>>> Hi, Jiri
>>>>>
>>>>>>> - if (!tc) {
>>>>>>> + if (if_running) {
>>>>>>> + (void)hns3_nic_net_stop(netdev);
>>>>>>> + msleep(100);
>>>>>>> + }
>>>>>>> +
>>>>>>> + ret = (kinfo->dcb_ops && kinfo->dcb_ops->>setup_tc) ?
>>>>>>> + kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : ->EOPNOTSUPP;
>>>>>
>>>>>> This is most odd. Why do you call dcb_ops from >ndo_setup_tc callback?
>>>>>> Why are you mixing this together? prio->tc mapping >can be done
>>>>>> directly in dcbnl
>>>>>
>>>>> Here is what we do in dcb_ops->setup_tc:
>>>>> Firstly, if current tc num is different from the tc num
>>>>> that user provide, then we setup the queues for each
>>>>> tc.
>>>>>
>>>>> Secondly, we tell hardware the pri to tc mapping that
>>>>> the stack is using. In rx direction, our hardware need
>>>>> that mapping to put different packet into different tc'
>>>>> queues according to the priority of the packet, then
>>>>> rss decides which specific queue in the tc should the
>>>>> packet goto.
>>>>>
>>>>> By mixing, I suppose you meant why we need the
>>>>> pri to tc infomation?
>>>>
>>>> by mixing, I mean what I wrote. You are calling dcb_ops callback from
>>>> ndo_setup_tc callback. So you are mixing DCBNL subsystem and TC
>>>> subsystem. Why? Why do you need sch_mqprio? Why DCBNL is not enough for
>>>> all?
>>>
>>> When using lldptool, dcbnl is involved.
>>>
>>> But when using tc qdisc, dcbbl is not involved, below is the a few key
>>> call graph in the kernel when tc qdisc cmd is executed.
>>>
>>> cmd:
>>> tc qdisc add dev eth0 root handle 1:0 mqprio num_tc 4 map 1 2 3 3 1 3 1 1 hw 1
>>>
>>> call graph:
>>> rtnetlink_rcv_msg -> tc_modify_qdisc -> qdisc_create -> mqprio_init ->
>>> hns3_nic_setup_tc
>>>
>>> When hns3_nic_setup_tc is called, we need to know how many tc num and
>>> prio_tc mapping from the tc_mqprio_qopt which is provided in the paramter
>>> in the ndo_setup_tc function, and dcb_ops is the our hardware specific
>>> method to setup the tc related parameter to the hardware, so this is why
>>> we call dcb_ops callback in ndo_setup_tc callback.
>>>
>>> I hope this will answer your question, thanks for your time.
>>
>> Okay. I understand that you have a usecase for mqprio mapping offload
>> without lldptool being involved. Ok. I believe it is wrong to call dcb_ops
>> from tc callback. You should have a generic layer inside the driver and
>> call it from both dcb_ops and tc callbacks.
>
>Actually, dcb_ops is our generic layer inside the driver.
>Below is high level architecture:
>
> [ tc qdisc ] [ lldpad ]
> | |
> | |
> | |
> [ hns3_enet ] [ hns3_dcbnl ]
> \ /
> \ /
> \ /
> [ hclge_dcb ]
> / \
> / \
> / \
> [ hclgc_main ] [ hclge_tm ]
>
>hns3_enet.c implements the ndo_setup_tc callback.
>hns3_dcbnl.c implements the dcbnl_rtnl_ops for stack's DCBNL system.
>hclge_dcb implements the dcb_ops.
>So we already have a generic layer that tc and dcbnl all call from.
>
>>
>> Also, what happens If I run lldptool concurrently with mqprio? Who wins
>> and is going to configure the mapping?
>
>Both lldptool and tc qdisc cmd use rtnl interface provided by stack, so
>they are both protected by rtnl_lock, so we do not have to do the locking
>in the driver.
I was not asking about locking, which is obvious, I was asking about the
behaviour. Like for example:
If I use tc to configure some mapping, later on I run lldptool and change
the mapping. Does the tc dump show the updated values or the original
ones?
>
>The locking is in rtnetlink_rcv_msg:
>
> rtnl_lock();
> handlers = rtnl_dereference(rtnl_msg_handlers[family]);
> if (handlers) {
> doit = READ_ONCE(handlers[type].doit);
> if (doit)
> err = doit(skb, nlh, extack);
> }
> rtnl_unlock();
>
>Thanks.
>
>>
>>
>>>
>>>>
>>>>
>>>>
>>>>> I hope I did not misunderstand your question, thanks
>>>>> for your time reviewing.
>>>>
>>>> .
>>>>
>>>
>>
>> .
>>
>
[toc] | [prev] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-25 09:30 +0200 |
| Subject | Re: [PATCH net-next 10/10] net: hns3: Add mqprio support when interacting with network stack |
| Message-ID | <utw01-3bl-11@gated-at.bofh.it> |
| In reply to | #1738774 |
Hi, Jiri
On 2017/9/25 14:57, Jiri Pirko wrote:
> Mon, Sep 25, 2017 at 02:45:08AM CEST, linyunsheng@huawei.com wrote:
>> Hi, Jiri
>>
>> On 2017/9/24 19:37, Jiri Pirko wrote:
>>> Sat, Sep 23, 2017 at 02:47:20AM CEST, linyunsheng@huawei.com wrote:
>>>> Hi, Jiri
>>>>
>>>> On 2017/9/23 0:03, Jiri Pirko wrote:
>>>>> Fri, Sep 22, 2017 at 04:11:51PM CEST, linyunsheng@huawei.com wrote:
>>>>>> Hi, Jiri
>>>>>>
>>>>>>>> - if (!tc) {
>>>>>>>> + if (if_running) {
>>>>>>>> + (void)hns3_nic_net_stop(netdev);
>>>>>>>> + msleep(100);
>>>>>>>> + }
>>>>>>>> +
>>>>>>>> + ret = (kinfo->dcb_ops && kinfo->dcb_ops->>setup_tc) ?
>>>>>>>> + kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : ->EOPNOTSUPP;
>>>>>>
>>>>>>> This is most odd. Why do you call dcb_ops from >ndo_setup_tc callback?
>>>>>>> Why are you mixing this together? prio->tc mapping >can be done
>>>>>>> directly in dcbnl
>>>>>>
>>>>>> Here is what we do in dcb_ops->setup_tc:
>>>>>> Firstly, if current tc num is different from the tc num
>>>>>> that user provide, then we setup the queues for each
>>>>>> tc.
>>>>>>
>>>>>> Secondly, we tell hardware the pri to tc mapping that
>>>>>> the stack is using. In rx direction, our hardware need
>>>>>> that mapping to put different packet into different tc'
>>>>>> queues according to the priority of the packet, then
>>>>>> rss decides which specific queue in the tc should the
>>>>>> packet goto.
>>>>>>
>>>>>> By mixing, I suppose you meant why we need the
>>>>>> pri to tc infomation?
>>>>>
>>>>> by mixing, I mean what I wrote. You are calling dcb_ops callback from
>>>>> ndo_setup_tc callback. So you are mixing DCBNL subsystem and TC
>>>>> subsystem. Why? Why do you need sch_mqprio? Why DCBNL is not enough for
>>>>> all?
>>>>
>>>> When using lldptool, dcbnl is involved.
>>>>
>>>> But when using tc qdisc, dcbbl is not involved, below is the a few key
>>>> call graph in the kernel when tc qdisc cmd is executed.
>>>>
>>>> cmd:
>>>> tc qdisc add dev eth0 root handle 1:0 mqprio num_tc 4 map 1 2 3 3 1 3 1 1 hw 1
>>>>
>>>> call graph:
>>>> rtnetlink_rcv_msg -> tc_modify_qdisc -> qdisc_create -> mqprio_init ->
>>>> hns3_nic_setup_tc
>>>>
>>>> When hns3_nic_setup_tc is called, we need to know how many tc num and
>>>> prio_tc mapping from the tc_mqprio_qopt which is provided in the paramter
>>>> in the ndo_setup_tc function, and dcb_ops is the our hardware specific
>>>> method to setup the tc related parameter to the hardware, so this is why
>>>> we call dcb_ops callback in ndo_setup_tc callback.
>>>>
>>>> I hope this will answer your question, thanks for your time.
>>>
>>> Okay. I understand that you have a usecase for mqprio mapping offload
>>> without lldptool being involved. Ok. I believe it is wrong to call dcb_ops
>>> from tc callback. You should have a generic layer inside the driver and
>>> call it from both dcb_ops and tc callbacks.
>>
>> Actually, dcb_ops is our generic layer inside the driver.
>> Below is high level architecture:
>>
>> [ tc qdisc ] [ lldpad ]
>> | |
>> | |
>> | |
>> [ hns3_enet ] [ hns3_dcbnl ]
>> \ /
>> \ /
>> \ /
>> [ hclge_dcb ]
>> / \
>> / \
>> / \
>> [ hclgc_main ] [ hclge_tm ]
>>
>> hns3_enet.c implements the ndo_setup_tc callback.
>> hns3_dcbnl.c implements the dcbnl_rtnl_ops for stack's DCBNL system.
>> hclge_dcb implements the dcb_ops.
>> So we already have a generic layer that tc and dcbnl all call from.
>>
>>>
>>> Also, what happens If I run lldptool concurrently with mqprio? Who wins
>>> and is going to configure the mapping?
>>
>> Both lldptool and tc qdisc cmd use rtnl interface provided by stack, so
>> they are both protected by rtnl_lock, so we do not have to do the locking
>> in the driver.
>
> I was not asking about locking, which is obvious, I was asking about the
> behaviour. Like for example:
> If I use tc to configure some mapping, later on I run lldptool and change
> the mapping. Does the tc dump show the updated values or the original
> ones?
If it is that case, tc dump show the updated values.
Normally, we use tc qdisc to configure the netdev to use mqprio, and
then use the lldptool the tc_prio mapping, tc schedule mode, tc bandwidth
and pfc option.
if lldptool change the tc num and tc_prio mapping, it will tell the tc
system by the following function which is called in client_ops->setup_tc:
netdev_set_tc_queue
netdev_set_prio_tc_map
So lldptool and tc qdisc can work together.
>
>>
>> The locking is in rtnetlink_rcv_msg:
>>
>> rtnl_lock();
>> handlers = rtnl_dereference(rtnl_msg_handlers[family]);
>> if (handlers) {
>> doit = READ_ONCE(handlers[type].doit);
>> if (doit)
>> err = doit(skb, nlh, extack);
>> }
>> rtnl_unlock();
>>
>> Thanks.
>>
>>>
>>>
>>>>
>>>>>
>>>>>
>>>>>
>>>>>> I hope I did not misunderstand your question, thanks
>>>>>> for your time reviewing.
>>>>>
>>>>> .
>>>>>
>>>>
>>>
>>> .
>>>
>>
>
> .
>
[toc] | [prev] | [next] | [standalone]
| From | Yunsheng Lin <linyunsheng@huawei.com> |
|---|---|
| Date | 2017-09-21 13:30 +0200 |
| Subject | [PATCH net-next 08/10] net: hns3: Add dcb netlink interface for the support of DCB feature |
| Message-ID | <us7Q7-kv-51@gated-at.bofh.it> |
| In reply to | #1736556 |
This patch add dcb netlink interface by calling the interface from
hclge_dcb module.
This patch also update Makefile in order to build hns3_dcbnl module.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3pf/Makefile | 2 +
.../ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c | 106 +++++++++++++++++++++
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c | 2 +
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h | 7 ++
4 files changed, 117 insertions(+)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
index 7023dc87..d2b20d0 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
@@ -11,3 +11,5 @@ hclge-$(CONFIG_HNS3_DCB) += hclge_dcb.o
obj-$(CONFIG_HNS3_ENET) += hns3.o
hns3-objs = hns3_enet.o hns3_ethtool.o
+
+hns3-$(CONFIG_HNS3_DCB) += hns3_dcbnl.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c
new file mode 100644
index 0000000..9832172
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016-2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "hnae3.h"
+#include "hns3_enet.h"
+
+static
+int hns3_dcbnl_ieee_getets(struct net_device *ndev, struct ieee_ets *ets)
+{
+ struct hns3_nic_priv *priv = netdev_priv(ndev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (h->kinfo.dcb_ops->ieee_getets)
+ return h->kinfo.dcb_ops->ieee_getets(h, ets);
+
+ return -EOPNOTSUPP;
+}
+
+static
+int hns3_dcbnl_ieee_setets(struct net_device *ndev, struct ieee_ets *ets)
+{
+ struct hns3_nic_priv *priv = netdev_priv(ndev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (h->kinfo.dcb_ops->ieee_setets)
+ return h->kinfo.dcb_ops->ieee_setets(h, ets);
+
+ return -EOPNOTSUPP;
+}
+
+static
+int hns3_dcbnl_ieee_getpfc(struct net_device *ndev, struct ieee_pfc *pfc)
+{
+ struct hns3_nic_priv *priv = netdev_priv(ndev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (h->kinfo.dcb_ops->ieee_getpfc)
+ return h->kinfo.dcb_ops->ieee_getpfc(h, pfc);
+
+ return -EOPNOTSUPP;
+}
+
+static
+int hns3_dcbnl_ieee_setpfc(struct net_device *ndev, struct ieee_pfc *pfc)
+{
+ struct hns3_nic_priv *priv = netdev_priv(ndev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (h->kinfo.dcb_ops->ieee_setpfc)
+ return h->kinfo.dcb_ops->ieee_setpfc(h, pfc);
+
+ return -EOPNOTSUPP;
+}
+
+/* DCBX configuration */
+static u8 hns3_dcbnl_getdcbx(struct net_device *ndev)
+{
+ struct hns3_nic_priv *priv = netdev_priv(ndev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (h->kinfo.dcb_ops->getdcbx)
+ return h->kinfo.dcb_ops->getdcbx(h);
+
+ return 0;
+}
+
+/* return 0 if successful, otherwise fail */
+static u8 hns3_dcbnl_setdcbx(struct net_device *ndev, u8 mode)
+{
+ struct hns3_nic_priv *priv = netdev_priv(ndev);
+ struct hnae3_handle *h = priv->ae_handle;
+
+ if (h->kinfo.dcb_ops->setdcbx)
+ return h->kinfo.dcb_ops->setdcbx(h, mode);
+
+ return 1;
+}
+
+static const struct dcbnl_rtnl_ops hns3_dcbnl_ops = {
+ .ieee_getets = hns3_dcbnl_ieee_getets,
+ .ieee_setets = hns3_dcbnl_ieee_setets,
+ .ieee_getpfc = hns3_dcbnl_ieee_getpfc,
+ .ieee_setpfc = hns3_dcbnl_ieee_setpfc,
+ .getdcbx = hns3_dcbnl_getdcbx,
+ .setdcbx = hns3_dcbnl_setdcbx,
+};
+
+/* hclge_dcbnl_setup - DCBNL setup
+ * @handle: the corresponding vport handle
+ * Set up DCBNL
+ */
+void hns3_dcbnl_setup(struct hnae3_handle *handle)
+{
+ struct net_device *dev = handle->kinfo.netdev;
+
+ if (!handle->kinfo.dcb_ops)
+ return;
+
+ dev->dcbnl_ops = &hns3_dcbnl_ops;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
index 35369e1..11dab26 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
@@ -2790,6 +2790,8 @@ static int hns3_client_init(struct hnae3_handle *handle)
goto out_reg_netdev_fail;
}
+ hns3_dcbnl_setup(handle);
+
/* MTU range: (ETH_MIN_MTU(kernel default) - 9706) */
netdev->max_mtu = HNS3_MAX_MTU - (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h
index 7e87461..481eada 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h
@@ -590,4 +590,11 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
void hns3_ethtool_set_ops(struct net_device *netdev);
int hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget);
+
+#ifdef CONFIG_HNS3_DCB
+void hns3_dcbnl_setup(struct hnae3_handle *handle);
+#else
+static inline void hns3_dcbnl_setup(struct hnae3_handle *handle) {}
+#endif
+
#endif
--
1.9.1
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web