[PATCH net-next 3/9] net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd Interface Support

2017-06-09 Thread Salil Mehta
This patch adds the support of IMP (Integrated Management Processor)
command interface to the HNS3 driver.

Each PF/VF has support of CQP(Command Queue Pair) ring interface.
Each CQP consis of send queue CSQ and receive queue CRQ.
There are various commands a PF/VF may support, like for Flow Table
manipulation, Device management, Packet buffer allocation, Forwarding,
VLANs config, Tunneling/Overlays etc.

This patch contains code to initialize the command queue, manage the
command queue descriptors and Rx/Tx protocol with the command processor
in the form of various commands/results and acknowledgements.

Signed-off-by: Daode Huang 
Signed-off-by: lipeng 
Signed-off-by: Salil Mehta 
Signed-off-by: Yisen Zhuang 
---
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 347 ++
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 742 +
 2 files changed, 1089 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
new file mode 100644
index 000..ec20ec4
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -0,0 +1,347 @@
+/*
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "hclge_cmd.h"
+#include "hnae3.h"
+#include "hclge_main.h"
+
+#define hclge_is_csq(ring) ((ring)->flag & HCLGE_TYPE_CSQ)
+#define hclge_ring_to_dma_dir(ring) (hclge_is_csq(ring) ? \
+   DMA_TO_DEVICE : DMA_FROM_DEVICE)
+#define cmq_ring_to_dev(ring)   (&(ring)->dev->pdev->dev)
+
+static int hclge_ring_space(struct hclge_cmq_ring *ring)
+{
+   int ntu = ring->next_to_use;
+   int ntc = ring->next_to_clean;
+   int used = (ntu - ntc + ring->desc_num) % ring->desc_num;
+
+   return ring->desc_num - used - 1;
+}
+
+static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
+{
+   int size  = ring->desc_num * sizeof(struct hclge_desc);
+
+   ring->desc = kzalloc(size, GFP_KERNEL);
+   if (!ring->desc)
+   return -ENOMEM;
+
+   ring->desc_dma_addr = dma_map_single(cmq_ring_to_dev(ring), ring->desc,
+size, DMA_BIDIRECTIONAL);
+   if (dma_mapping_error(cmq_ring_to_dev(ring), ring->desc_dma_addr)) {
+   ring->desc_dma_addr = 0;
+   kfree(ring->desc);
+   ring->desc = NULL;
+   return -ENOMEM;
+   }
+
+   return 0;
+}
+
+static void hclge_free_cmd_desc(struct hclge_cmq_ring *ring)
+{
+   dma_unmap_single(cmq_ring_to_dev(ring), ring->desc_dma_addr,
+ring->desc_num * sizeof(ring->desc[0]),
+DMA_BIDIRECTIONAL);
+
+   ring->desc_dma_addr = 0;
+   kfree(ring->desc);
+   ring->desc = NULL;
+}
+
+static int hclge_init_cmd_queue(struct hclge_dev *hdev, int ring_type)
+{
+   struct hclge_hw *hw = >hw;
+   struct hclge_cmq_ring *ring =
+   (ring_type == HCLGE_TYPE_CSQ) ? >cmq.csq : >cmq.crq;
+   int ret;
+
+   ring->flag = ring_type;
+   ring->dev = hdev;
+
+   ret = hclge_alloc_cmd_desc(ring);
+   if (ret) {
+   dev_err(>pdev->dev, "descriptor %s alloc error %d\n",
+   (ring_type == HCLGE_TYPE_CSQ) ? "CSQ" : "CRQ", ret);
+   return ret;
+   }
+
+   ring->next_to_clean = 0;
+   ring->next_to_use = 0;
+
+   return 0;
+}
+
+void hclge_cmd_reuse_desc(struct hclge_desc *desc, bool is_read)
+{
+   desc->flag = cpu_to_le16(HCLGE_CMD_FLAG_NO_INTR | HCLGE_CMD_FLAG_IN);
+   if (is_read)
+   desc->flag |= cpu_to_le16(HCLGE_CMD_FLAG_WR);
+   else
+   desc->flag &= cpu_to_le16(~HCLGE_CMD_FLAG_WR);
+}
+
+void hclge_cmd_setup_basic_desc(struct hclge_desc *desc,
+   enum hclge_opcode_type opcode, bool is_read)
+{
+   memset((void *)desc, 0, sizeof(struct hclge_desc));
+   desc->opcode = cpu_to_le16(opcode);
+   desc->flag = cpu_to_le16(HCLGE_CMD_FLAG_NO_INTR | HCLGE_CMD_FLAG_IN);
+
+   if (is_read)
+   desc->flag |= cpu_to_le16(HCLGE_CMD_FLAG_WR);
+   else
+   desc->flag &= cpu_to_le16(~HCLGE_CMD_FLAG_WR);
+}
+
+static void hclge_cmd_config_regs(struct hclge_cmq_ring *ring)
+{
+   dma_addr_t dma = ring->desc_dma_addr;
+   struct hclge_dev *hdev = ring->dev;
+   struct hclge_hw *hw = >hw;
+
+   if (ring->flag == 

[PATCH net-next 3/9] net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd Interface Support

2017-06-09 Thread Salil Mehta
This patch adds the support of IMP (Integrated Management Processor)
command interface to the HNS3 driver.

Each PF/VF has support of CQP(Command Queue Pair) ring interface.
Each CQP consis of send queue CSQ and receive queue CRQ.
There are various commands a PF/VF may support, like for Flow Table
manipulation, Device management, Packet buffer allocation, Forwarding,
VLANs config, Tunneling/Overlays etc.

This patch contains code to initialize the command queue, manage the
command queue descriptors and Rx/Tx protocol with the command processor
in the form of various commands/results and acknowledgements.

Signed-off-by: Daode Huang 
Signed-off-by: lipeng 
Signed-off-by: Salil Mehta 
Signed-off-by: Yisen Zhuang 
---
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 347 ++
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 742 +
 2 files changed, 1089 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
new file mode 100644
index 000..ec20ec4
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -0,0 +1,347 @@
+/*
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "hclge_cmd.h"
+#include "hnae3.h"
+#include "hclge_main.h"
+
+#define hclge_is_csq(ring) ((ring)->flag & HCLGE_TYPE_CSQ)
+#define hclge_ring_to_dma_dir(ring) (hclge_is_csq(ring) ? \
+   DMA_TO_DEVICE : DMA_FROM_DEVICE)
+#define cmq_ring_to_dev(ring)   (&(ring)->dev->pdev->dev)
+
+static int hclge_ring_space(struct hclge_cmq_ring *ring)
+{
+   int ntu = ring->next_to_use;
+   int ntc = ring->next_to_clean;
+   int used = (ntu - ntc + ring->desc_num) % ring->desc_num;
+
+   return ring->desc_num - used - 1;
+}
+
+static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
+{
+   int size  = ring->desc_num * sizeof(struct hclge_desc);
+
+   ring->desc = kzalloc(size, GFP_KERNEL);
+   if (!ring->desc)
+   return -ENOMEM;
+
+   ring->desc_dma_addr = dma_map_single(cmq_ring_to_dev(ring), ring->desc,
+size, DMA_BIDIRECTIONAL);
+   if (dma_mapping_error(cmq_ring_to_dev(ring), ring->desc_dma_addr)) {
+   ring->desc_dma_addr = 0;
+   kfree(ring->desc);
+   ring->desc = NULL;
+   return -ENOMEM;
+   }
+
+   return 0;
+}
+
+static void hclge_free_cmd_desc(struct hclge_cmq_ring *ring)
+{
+   dma_unmap_single(cmq_ring_to_dev(ring), ring->desc_dma_addr,
+ring->desc_num * sizeof(ring->desc[0]),
+DMA_BIDIRECTIONAL);
+
+   ring->desc_dma_addr = 0;
+   kfree(ring->desc);
+   ring->desc = NULL;
+}
+
+static int hclge_init_cmd_queue(struct hclge_dev *hdev, int ring_type)
+{
+   struct hclge_hw *hw = >hw;
+   struct hclge_cmq_ring *ring =
+   (ring_type == HCLGE_TYPE_CSQ) ? >cmq.csq : >cmq.crq;
+   int ret;
+
+   ring->flag = ring_type;
+   ring->dev = hdev;
+
+   ret = hclge_alloc_cmd_desc(ring);
+   if (ret) {
+   dev_err(>pdev->dev, "descriptor %s alloc error %d\n",
+   (ring_type == HCLGE_TYPE_CSQ) ? "CSQ" : "CRQ", ret);
+   return ret;
+   }
+
+   ring->next_to_clean = 0;
+   ring->next_to_use = 0;
+
+   return 0;
+}
+
+void hclge_cmd_reuse_desc(struct hclge_desc *desc, bool is_read)
+{
+   desc->flag = cpu_to_le16(HCLGE_CMD_FLAG_NO_INTR | HCLGE_CMD_FLAG_IN);
+   if (is_read)
+   desc->flag |= cpu_to_le16(HCLGE_CMD_FLAG_WR);
+   else
+   desc->flag &= cpu_to_le16(~HCLGE_CMD_FLAG_WR);
+}
+
+void hclge_cmd_setup_basic_desc(struct hclge_desc *desc,
+   enum hclge_opcode_type opcode, bool is_read)
+{
+   memset((void *)desc, 0, sizeof(struct hclge_desc));
+   desc->opcode = cpu_to_le16(opcode);
+   desc->flag = cpu_to_le16(HCLGE_CMD_FLAG_NO_INTR | HCLGE_CMD_FLAG_IN);
+
+   if (is_read)
+   desc->flag |= cpu_to_le16(HCLGE_CMD_FLAG_WR);
+   else
+   desc->flag &= cpu_to_le16(~HCLGE_CMD_FLAG_WR);
+}
+
+static void hclge_cmd_config_regs(struct hclge_cmq_ring *ring)
+{
+   dma_addr_t dma = ring->desc_dma_addr;
+   struct hclge_dev *hdev = ring->dev;
+   struct hclge_hw *hw = >hw;
+
+   if (ring->flag == HCLGE_TYPE_CSQ) {
+   hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_L_REG,
+