Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 218afa10 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'hns-debug-dsaf'



Yisen Zhuang says:

====================
net: hns: add support of debug dsaf device

There are two kinds of dsaf device in hns, one is for service ports,
contains crossbar in it, can work under different mode. Another is for
debug port, only can work under single port mode. The current code only
declares a dsaf device for both service ports and debug ports.It is not so
readability. This patch separates it to three platform devices to make the
code more simple and readability.

The diagram of all port in one platform device(old):
                                        CPU
                                         |
                                         |        DSAF(one platform device)
    --------------------------------------------------------------      /
    |                           |                  |      |      |     /
    |                          PPE                PPE    PPE     |    /
    |                           |                  |      |      |   /
    |                           |                  |      |      |  /
    |                        crossbar              |      |      | /
    |                           |                  |      |      |/
    |    -----------------------------------       |      |      |
    |    |      |      |      |      |      |      |      |      |
    |    |      |      |      |      |      |      |      |      |
    |   MAC    MAC    MAC    MAC    MAC    MAC    MAC    MAC     |
    |    |      |      |      |      |      |      |      |      |
    --------------------------------------------------------------
         |      |      |      |      |      |      |      |
        PHY    PHY    PHY    PHY    PHY    PHY    PHY    PHY

The diagram of separating ports to three platform(new):
                                                         CPU
                                                          |
                                    -----------------------------------
                                    |                     |           |
    ----------------------------------------------    ---------   ---------
    |                         |                  |    |       |   |   |   |
    |                        PPE                 |    |  PPE  |   |  PPE  |
    |                         |                  |    |   |   |   |   |   |
    |                         |                  |    |   |   |   |   |   |
    |                      crossbar              |    |   |   |   |   |   |
    |                         |                  |    |   |   |   |   |   |
    |   ----------------------------------       |    |   |   |   |   |   |
    |   |     |     |      |      |      |       |    |   |   |   |   |   |
    |   |     |     |      |      |      |       |    |   |   |   |   |   |
    |  MAC   MAC   MAC    MAC    MAC    MAC      |    |  MAC  |   |  MAC  |
    |   |     |     |      |      |      |       |    |   |   |   |   |   |
    ----------------------------------------------    ---------   ---------
        |     |     |      |      |      |    \        /  |        /  |
       PHY   PHY   PHY    PHY    PHY    PHY    \      /  PHY      /  PHY
                                                \    /           /
                                                 \  /           /
                                             DSAF(three platform device)

We take the compatibility into consideration, and it works well by using the
old dts file(tested on d02 board).

For more details, please see individual patches.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5a5f0792 218afd68
Loading
Loading
Loading
Loading
+49 −10
Original line number Diff line number Diff line
@@ -7,19 +7,47 @@ Required properties:
- mode: dsa fabric mode string. only support one of dsaf modes like these:
		"2port-64vf",
		"6port-16rss",
		"6port-16vf".
		"6port-16vf",
		"single-port".
- interrupt-parent: the interrupt parent of this device.
- interrupts: should contain the DSA Fabric and rcb interrupt.
- reg: specifies base physical address(es) and size of the device registers.
  The first region is external interface control register base and size.
  The second region is SerDes base register and size.
  The first region is external interface control register base and size(optional,
  only be used when subctrl-syscon is not exists). It is recommended using
  subctrl-syscon rather than this address.
  The second region is SerDes base register and size(optional, only be used when
  serdes-syscon in port node is not exists. It is recommended using
  serdes-syscon rather than this address.
  The third region is the PPE register base and size.
  The fourth region is dsa fabric base register and size.
  The fifth region is cpld base register and size, it is not required if do not use cpld.
- phy-handle: phy handle of physicl port, 0 if not any phy device. see ethernet.txt [1].
  The fourth region is dsa fabric base register and size. It is not required for
  single-port mode.
- reg-names: may be ppe-base and(or) dsaf-base. It is used to find the
  corresponding reg's index.

- phy-handle: phy handle of physicl port, 0 if not any phy device. It is optional
  attribute. If port node is exists, phy-handle in each port node will be used.
  see ethernet.txt [1].
- subctrl-syscon: is syscon handle for external interface control register.
- reset-field-offset: is offset of reset field. Its value depends on the hardware
  user manual.
- buf-size: rx buffer size, should be 16-1024.
- desc-num: number of description in TX and RX queue, should be 512, 1024, 2048 or 4096.

- port: subnodes of dsaf. A dsaf node may contain several port nodes(Depending
  on mode of dsaf). Port node contain some attributes listed below:
- port-id: is physical port index in one dsaf.
- phy-handle: phy handle of physicl port. It is not required if there isn't
  phy device. see ethernet.txt [1].
- serdes-syscon: is syscon handle for SerDes register.
- cpld-syscon: is syscon handle for cpld register. It is not required if there
  isn't cpld device.
- cpld-ctrl-reg: is cpld register offset. It is not required if there isn't
  cpld-syscon.
- port-rst-offset: is offset of reset field for each port in dsaf. Its value
  depends on the hardware user manual.
- port-mode-offset: is offset of port mode field for each port in dsaf. Its
  value depends on the hardware user manual.

[1] Documentation/devicetree/bindings/net/phy.txt

Example:
@@ -28,11 +56,11 @@ dsaf0: dsa@c7000000 {
	compatible = "hisilicon,hns-dsaf-v1";
	mode = "6port-16rss";
	interrupt-parent = <&mbigen_dsa>;
	reg = <0x0 0xC0000000 0x0 0x420000
	       0x0 0xC2000000 0x0 0x300000
	       0x0 0xc5000000 0x0 0x890000
	reg = <0x0 0xc5000000 0x0 0x890000
	       0x0 0xc7000000 0x0 0x60000>;
	phy-handle = <0 0 0 0 &soc0_phy4 &soc0_phy5 0 0>;
	reg-names = "ppe-base", "dsaf-base";
	subctrl-syscon = <&subctrl>;
	reset-field-offset = 0;
	interrupts = <131 4>,<132 4>, <133 4>,<134 4>,
		     <135 4>,<136 4>, <137 4>,<138 4>,
		     <139 4>,<140 4>, <141 4>,<142 4>,
@@ -43,4 +71,15 @@ dsaf0: dsa@c7000000 {
	buf-size = <4096>;
	desc-num = <1024>;
	dma-coherent;

	prot@0 {
		port-id = 0;
		phy-handle = <&phy0>;
		serdes-syscon = <&serdes>;
	};

	prot@1 {
                port-id = 1;
                serdes-syscon = <&serdes>;
        };
};
+29 −1
Original line number Diff line number Diff line
@@ -36,6 +36,34 @@ Required properties:
                       | | | | | |
                      external port

  This attribute is remained for compatible purpose. It is not recommended to
  use it in new code.

- port-idx-in-ae: is the index of port provided by AE.
  In NIC mode of DSAF, all 6 PHYs of service DSAF are taken as ethernet ports
  to the CPU. The port-idx-in-ae can be 0 to 5. Here is the diagram:
            +-----+---------------+
            |            CPU      |
            +-+-+-+---+-+-+-+-+-+-+
              |    |   | | | | | |
           debug debug   service
           port  port     port
           (0)   (0)     (0-5)

  In Switch mode of DSAF, all 6 PHYs of service DSAF are taken as physical
  ports connected to a LAN Switch while the CPU side assume itself have one
  single NIC connected to this switch. In this case, the port-idx-in-ae
  will be 0 only.
            +-----+-----+------+------+
            |                CPU      |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+
              |    |     service| port(0)
            debug debug  +------------+
            port  port   |   switch   |
            (0)   (0)    +-+-+-+-+-+-++
                          | | | | | |
                         external port

- local-mac-address: mac addr of the ethernet interface

Example:
@@ -43,6 +71,6 @@ Example:
	ethernet@0{
		compatible = "hisilicon,hns-nic-v1";
		ae-handle = <&dsaf0>;
		port-id = <0>;
		port-idx-in-ae = <0>;
		local-mac-address = [a2 14 e4 4b 56 76];
	};
+30 −42
Original line number Diff line number Diff line
@@ -28,13 +28,13 @@ soc0: soc@000000000 {
		mode = "6port-16rss";
		interrupt-parent = <&mbigen_dsa>;

		reg = <0x0 0xC0000000 0x0 0x420000
		       0x0 0xC2000000 0x0 0x300000
		       0x0 0xc5000000 0x0 0x890000
		reg = <0x0 0xc5000000 0x0 0x890000
		       0x0 0xc7000000 0x0 0x60000
		       >;

		phy-handle = <0 0 0 0 &soc0_phy0 &soc0_phy1 0 0>;
		reg-names = "ppe-base","dsaf-base";
		subctrl-syscon = <&dsaf_subctrl>;
		reset-field-offset = <0>;
		interrupts = <
			/* [14] ge fifo err 8 / xge 6**/
			149 0x4 150 0x4 151 0x4 152 0x4
@@ -122,68 +122,56 @@ soc0: soc@000000000 {
		buf-size = <4096>;
		desc-num = <1024>;
		dma-coherent;
	};

	eth0: ethernet@0{
		compatible = "hisilicon,hns-nic-v1";
		ae-handle = <&dsaf0>;
		port@0 {
			port-id = <0>;
		local-mac-address = [00 00 00 01 00 58];
		status = "disabled";
		dma-coherent;
			serdes-syscon = <&serdes_ctrl0>;
		};
	eth1: ethernet@1{
		compatible = "hisilicon,hns-nic-v1";
		ae-handle = <&dsaf0>;
		port@1 {
			port-id = <1>;
		status = "disabled";
		dma-coherent;
			serdes-syscon = <&serdes_ctrl0>;
		};
	eth2: ethernet@2{
		compatible = "hisilicon,hns-nic-v1";
		ae-handle = <&dsaf0>;
		port-id = <2>;
		local-mac-address = [00 00 00 01 00 5a];
		status = "disabled";
		dma-coherent;
		port@4 {
			port-id = <4>;
			phy-handle = <&soc0_phy0>;
			serdes-syscon = <&serdes_ctrl1>;
		};
		port@5 {
			port-id = <5>;
			phy-handle = <&soc0_phy1>;
			serdes-syscon = <&serdes_ctrl1>;
		};
	eth3: ethernet@3{
		compatible = "hisilicon,hns-nic-v1";
		ae-handle = <&dsaf0>;
		port-id = <3>;
		local-mac-address = [00 00 00 01 00 5b];
		status = "disabled";
		dma-coherent;
	};
	eth4: ethernet@4{

	eth0: ethernet@0{
		compatible = "hisilicon,hns-nic-v1";
		ae-handle = <&dsaf0>;
		port-id = <4>;
		local-mac-address = [00 00 00 01 00 5c];
		port-idx-in-ae = <0>;
		local-mac-address = [00 00 00 01 00 58];
		status = "disabled";
		dma-coherent;
	};
	eth5: ethernet@5{
	eth1: ethernet@1{
		compatible = "hisilicon,hns-nic-v1";
		ae-handle = <&dsaf0>;
		port-id = <5>;
		local-mac-address = [00 00 00 01 00 5d];
		port-idx-in-ae = <1>;
		local-mac-address = [00 00 00 01 00 59];
		status = "disabled";
		dma-coherent;
	};
	eth6: ethernet@6{
	eth2: ethernet@4{
		compatible = "hisilicon,hns-nic-v1";
		ae-handle = <&dsaf0>;
		port-id = <6>;
		local-mac-address = [00 00 00 01 00 5e];
		port-idx-in-ae = <4>;
		local-mac-address = [00 00 00 01 00 5a];
		status = "disabled";
		dma-coherent;
	};
	eth7: ethernet@7{
	eth3: ethernet@5{
		compatible = "hisilicon,hns-nic-v1";
		ae-handle = <&dsaf0>;
		port-id = <7>;
		local-mac-address = [00 00 00 01 00 5f];
		port-idx-in-ae = <5>;
		local-mac-address = [00 00 00 01 00 5b];
		status = "disabled";
		dma-coherent;
	};
+16 −57
Original line number Diff line number Diff line
@@ -29,25 +29,6 @@ static struct hns_mac_cb *hns_get_mac_cb(struct hnae_handle *handle)
	return vf_cb->mac_cb;
}

/**
 * hns_ae_map_eport_to_dport - translate enet port id to dsaf port id
 * @port_id: enet port id
 *: debug port 0-1, service port 2 -7 (dsaf mode only 2)
 * return: dsaf port id
 *: service ports 0 - 5, debug port 6-7
 **/
static int hns_ae_map_eport_to_dport(u32 port_id)
{
	int port_index;

	if (port_id < DSAF_DEBUG_NW_NUM)
		port_index = port_id + DSAF_SERVICE_PORT_NUM_PER_DSAF;
	else
		port_index = port_id - DSAF_DEBUG_NW_NUM;

	return port_index;
}

static struct dsaf_device *hns_ae_get_dsaf_dev(struct hnae_ae_dev *dev)
{
	return container_of(dev, struct dsaf_device, ae_dev);
@@ -56,50 +37,35 @@ static struct dsaf_device *hns_ae_get_dsaf_dev(struct hnae_ae_dev *dev)
static struct hns_ppe_cb *hns_get_ppe_cb(struct hnae_handle *handle)
{
	int ppe_index;
	int ppe_common_index;
	struct ppe_common_cb *ppe_comm;
	struct  hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);

	if (vf_cb->port_index < DSAF_SERVICE_PORT_NUM_PER_DSAF) {
	ppe_comm = vf_cb->dsaf_dev->ppe_common[0];
	ppe_index = vf_cb->port_index;
		ppe_common_index = 0;
	} else {
		ppe_index = 0;
		ppe_common_index =
			vf_cb->port_index - DSAF_SERVICE_PORT_NUM_PER_DSAF + 1;
	}
	ppe_comm = vf_cb->dsaf_dev->ppe_common[ppe_common_index];

	return &ppe_comm->ppe_cb[ppe_index];
}

static int hns_ae_get_q_num_per_vf(
	struct dsaf_device *dsaf_dev, int port)
{
	int common_idx = hns_dsaf_get_comm_idx_by_port(port);

	return dsaf_dev->rcb_common[common_idx]->max_q_per_vf;
	return dsaf_dev->rcb_common[0]->max_q_per_vf;
}

static int hns_ae_get_vf_num_per_port(
	struct dsaf_device *dsaf_dev, int port)
{
	int common_idx = hns_dsaf_get_comm_idx_by_port(port);

	return dsaf_dev->rcb_common[common_idx]->max_vfn;
	return dsaf_dev->rcb_common[0]->max_vfn;
}

static struct ring_pair_cb *hns_ae_get_base_ring_pair(
	struct dsaf_device *dsaf_dev, int port)
{
	int common_idx = hns_dsaf_get_comm_idx_by_port(port);
	struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[common_idx];
	struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[0];
	int q_num = rcb_comm->max_q_per_vf;
	int vf_num = rcb_comm->max_vfn;

	if (common_idx == HNS_DSAF_COMM_SERVICE_NW_IDX)
	return &rcb_comm->ring_pair_cb[port * q_num * vf_num];
	else
		return &rcb_comm->ring_pair_cb[0];
}

static struct ring_pair_cb *hns_ae_get_ring_pair(struct hnae_queue *q)
@@ -110,7 +76,6 @@ static struct ring_pair_cb *hns_ae_get_ring_pair(struct hnae_queue *q)
struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev,
				      u32 port_id)
{
	int port_idx;
	int vfnum_per_port;
	int qnum_per_vf;
	int i;
@@ -120,11 +85,10 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev,
	struct hnae_vf_cb *vf_cb;

	dsaf_dev = hns_ae_get_dsaf_dev(dev);
	port_idx = hns_ae_map_eport_to_dport(port_id);

	ring_pair_cb = hns_ae_get_base_ring_pair(dsaf_dev, port_idx);
	vfnum_per_port = hns_ae_get_vf_num_per_port(dsaf_dev, port_idx);
	qnum_per_vf = hns_ae_get_q_num_per_vf(dsaf_dev, port_idx);
	ring_pair_cb = hns_ae_get_base_ring_pair(dsaf_dev, port_id);
	vfnum_per_port = hns_ae_get_vf_num_per_port(dsaf_dev, port_id);
	qnum_per_vf = hns_ae_get_q_num_per_vf(dsaf_dev, port_id);

	vf_cb = kzalloc(sizeof(*vf_cb) +
			qnum_per_vf * sizeof(struct hnae_queue *), GFP_KERNEL);
@@ -163,14 +127,14 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev,
	}

	vf_cb->dsaf_dev = dsaf_dev;
	vf_cb->port_index = port_idx;
	vf_cb->mac_cb = &dsaf_dev->mac_cb[port_idx];
	vf_cb->port_index = port_id;
	vf_cb->mac_cb = dsaf_dev->mac_cb[port_id];

	ae_handle->phy_if = vf_cb->mac_cb->phy_if;
	ae_handle->phy_node = vf_cb->mac_cb->phy_node;
	ae_handle->if_support = vf_cb->mac_cb->if_support;
	ae_handle->port_type = vf_cb->mac_cb->mac_type;
	ae_handle->dport_id = port_idx;
	ae_handle->dport_id = port_id;

	return ae_handle;
vf_id_err:
@@ -320,11 +284,8 @@ static void hns_ae_reset(struct hnae_handle *handle)
	struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);

	if (vf_cb->mac_cb->mac_type == HNAE_PORT_DEBUG) {
		u8 ppe_common_index =
			vf_cb->port_index - DSAF_SERVICE_PORT_NUM_PER_DSAF + 1;

		hns_mac_reset(vf_cb->mac_cb);
		hns_ppe_reset_common(vf_cb->dsaf_dev, ppe_common_index);
		hns_ppe_reset_common(vf_cb->dsaf_dev, 0);
	}
}

@@ -703,7 +664,7 @@ void hns_ae_update_led_status(struct hnae_handle *handle)

	assert(handle);
	mac_cb = hns_get_mac_cb(handle);
	if (!mac_cb->cpld_vaddr)
	if (!mac_cb->cpld_ctrl)
		return;
	hns_set_led_opt(mac_cb);
}
@@ -723,7 +684,6 @@ int hns_ae_cpld_set_led_id(struct hnae_handle *handle,
void hns_ae_get_regs(struct hnae_handle *handle, void *data)
{
	u32 *p = data;
	u32 rcb_com_idx;
	int i;
	struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
	struct hns_ppe_cb *ppe_cb = hns_get_ppe_cb(handle);
@@ -731,8 +691,7 @@ void hns_ae_get_regs(struct hnae_handle *handle, void *data)
	hns_ppe_get_regs(ppe_cb, p);
	p += hns_ppe_get_regs_count();

	rcb_com_idx = hns_dsaf_get_comm_idx_by_port(vf_cb->port_index);
	hns_rcb_get_common_regs(vf_cb->dsaf_dev->rcb_common[rcb_com_idx], p);
	hns_rcb_get_common_regs(vf_cb->dsaf_dev->rcb_common[0], p);
	p += hns_rcb_get_common_regs_count();

	for (i = 0; i < handle->q_num; i++) {
+159 −71
Original line number Diff line number Diff line
@@ -7,18 +7,19 @@
 * (at your option) any later version.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/phy_fixed.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/phy_fixed.h>
#include <linux/platform_device.h>

#include "hns_dsaf_misc.h"
#include "hns_dsaf_main.h"
#include "hns_dsaf_misc.h"
#include "hns_dsaf_rcb.h"

#define MAC_EN_FLAG_V		0xada0328
@@ -81,17 +82,6 @@ static enum mac_mode hns_get_enet_interface(const struct hns_mac_cb *mac_cb)
	}
}

int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt)
{
	if (!mac_cb->cpld_vaddr)
		return -ENODEV;

	*sfp_prsnt = !dsaf_read_b((u8 *)mac_cb->cpld_vaddr
					+ MAC_SFP_PORT_OFFSET);

	return 0;
}

void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status)
{
	struct mac_driver *mac_ctrl_drv;
@@ -168,10 +158,9 @@ static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb,
				      u8 vmid, u8 *port_num)
{
	u8 tmp_port;
	u32 comm_idx;

	if (mac_cb->dsaf_dev->dsaf_mode <= DSAF_MODE_ENABLE) {
		if (mac_cb->mac_id != DSAF_MAX_PORT_NUM_PER_CHIP) {
		if (mac_cb->mac_id != DSAF_MAX_PORT_NUM) {
			dev_err(mac_cb->dev,
				"input invalid,%s mac%d vmid%d !\n",
				mac_cb->dsaf_dev->ae_dev.name,
@@ -179,7 +168,7 @@ static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb,
			return -EINVAL;
		}
	} else if (mac_cb->dsaf_dev->dsaf_mode < DSAF_MODE_MAX) {
		if (mac_cb->mac_id >= DSAF_MAX_PORT_NUM_PER_CHIP) {
		if (mac_cb->mac_id >= DSAF_MAX_PORT_NUM) {
			dev_err(mac_cb->dev,
				"input invalid,%s mac%d vmid%d!\n",
				mac_cb->dsaf_dev->ae_dev.name,
@@ -192,9 +181,7 @@ static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb,
		return -EINVAL;
	}

	comm_idx = hns_dsaf_get_comm_idx_by_port(mac_cb->mac_id);

	if (vmid >= mac_cb->dsaf_dev->rcb_common[comm_idx]->max_vfn) {
	if (vmid >= mac_cb->dsaf_dev->rcb_common[0]->max_vfn) {
		dev_err(mac_cb->dev, "input invalid,%s mac%d vmid%d !\n",
			mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vmid);
		return -EINVAL;
@@ -234,7 +221,7 @@ static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb,
}

/**
 *hns_mac_get_inner_port_num - change vf mac address
 *hns_mac_change_vf_addr - change vf mac address
 *@mac_cb: mac device
 *@vmid: vmid
 *@addr:mac address
@@ -249,7 +236,7 @@ int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb,
	struct mac_entry_idx *old_entry;

	old_entry = &mac_cb->addr_entry_idx[vmid];
	if (dsaf_dev) {
	if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) {
		memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
		mac_entry.in_vlan_id = old_entry->vlan_id;
		mac_entry.in_port_num = mac_cb->mac_id;
@@ -289,7 +276,7 @@ int hns_mac_set_multi(struct hns_mac_cb *mac_cb,
	struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
	struct dsaf_drv_mac_single_dest_entry mac_entry;

	if (dsaf_dev && addr) {
	if (!HNS_DSAF_IS_DEBUG(dsaf_dev) && addr) {
		memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
		mac_entry.in_vlan_id = 0;/*vlan_id;*/
		mac_entry.in_port_num = mac_cb->mac_id;
@@ -380,7 +367,7 @@ static int hns_mac_port_config_bc_en(struct hns_mac_cb *mac_cb,
	if (mac_cb->mac_type == HNAE_PORT_DEBUG)
		return 0;

	if (dsaf_dev) {
	if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) {
		memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
		mac_entry.in_vlan_id = vlan_id;
		mac_entry.in_port_num = mac_cb->mac_id;
@@ -418,7 +405,7 @@ int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable)

	uc_mac_entry = &mac_cb->addr_entry_idx[vmid];

	if (dsaf_dev)  {
	if (!HNS_DSAF_IS_DEBUG(dsaf_dev))  {
		memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
		mac_entry.in_vlan_id = uc_mac_entry->vlan_id;
		mac_entry.in_port_num = mac_cb->mac_id;
@@ -651,14 +638,17 @@ static int hns_mac_init_ex(struct hns_mac_cb *mac_cb)
}

/**
 *mac_free_dev  - get mac information from device node
 *hns_mac_get_info  - get mac information from device node
 *@mac_cb: mac device
 *@np:device node
 *@mac_mode_idx:mac mode index
 * return: 0 --success, negative --fail
 */
static void hns_mac_get_info(struct hns_mac_cb *mac_cb,
			     struct device_node *np, u32 mac_mode_idx)
static int  hns_mac_get_info(struct hns_mac_cb *mac_cb)
{
	struct device_node *np = mac_cb->dev->of_node;
	struct regmap *syscon;
	u32 ret;

	mac_cb->link = false;
	mac_cb->half_duplex = false;
	mac_cb->speed = mac_phy_to_speed[mac_cb->phy_if];
@@ -674,12 +664,72 @@ static void hns_mac_get_info(struct hns_mac_cb *mac_cb,

	mac_cb->max_frm = MAC_DEFAULT_MTU;
	mac_cb->tx_pause_frm_time = MAC_DEFAULT_PAUSE_TIME;
	mac_cb->port_rst_off = mac_cb->mac_id;
	mac_cb->port_mode_off = 0;

	/* Get the rest of the PHY information */
	mac_cb->phy_node = of_parse_phandle(np, "phy-handle", mac_cb->mac_id);
	/* if the dsaf node doesn't contain a port subnode, get phy-handle
	 * from dsaf node
	 */
	if (!mac_cb->fw_port) {
		mac_cb->phy_node = of_parse_phandle(np, "phy-handle",
						    mac_cb->mac_id);
		if (mac_cb->phy_node)
			dev_dbg(mac_cb->dev, "mac%d phy_node: %s\n",
				mac_cb->mac_id, mac_cb->phy_node->name);
		return 0;
	}
	if (!is_of_node(mac_cb->fw_port))
		return -EINVAL;
	/* parse property from port subnode in dsaf */
	mac_cb->phy_node = of_parse_phandle(to_of_node(mac_cb->fw_port),
					    "phy-handle", 0);
	if (mac_cb->phy_node)
		dev_dbg(mac_cb->dev, "mac%d phy_node: %s\n",
			mac_cb->mac_id, mac_cb->phy_node->name);
	syscon = syscon_node_to_regmap(
			of_parse_phandle(to_of_node(mac_cb->fw_port),
					 "serdes-syscon", 0));
	if (IS_ERR_OR_NULL(syscon)) {
		dev_err(mac_cb->dev, "serdes-syscon is needed!\n");
		return -EINVAL;
	}
	mac_cb->serdes_ctrl = syscon;

	ret = fwnode_property_read_u32(mac_cb->fw_port,
				       "port-rst-offset",
				       &mac_cb->port_rst_off);
	if (ret) {
		dev_dbg(mac_cb->dev,
			"mac%d port-rst-offset not found, use default value.\n",
			mac_cb->mac_id);
	}

	ret = fwnode_property_read_u32(mac_cb->fw_port,
				       "port-mode-offset",
				       &mac_cb->port_mode_off);
	if (ret) {
		dev_dbg(mac_cb->dev,
			"mac%d port-mode-offset not found, use default value.\n",
			mac_cb->mac_id);
	}

	syscon = syscon_node_to_regmap(
			of_parse_phandle(to_of_node(mac_cb->fw_port),
					 "cpld-syscon", 0));
	if (IS_ERR_OR_NULL(syscon)) {
		dev_dbg(mac_cb->dev, "no cpld-syscon found!\n");
		mac_cb->cpld_ctrl = NULL;
	} else {
		mac_cb->cpld_ctrl = syscon;
		ret = fwnode_property_read_u32(mac_cb->fw_port,
					       "cpld-ctrl-reg",
					       &mac_cb->cpld_ctrl_reg);
		if (ret) {
			dev_err(mac_cb->dev, "get cpld-ctrl-reg fail!\n");
			return ret;
		}
	}
	return 0;
}

/**
@@ -709,40 +759,31 @@ u8 __iomem *hns_mac_get_vaddr(struct dsaf_device *dsaf_dev,
		return base + 0x40000 + mac_id * 0x4000 -
				mac_mode_idx * 0x20000;
	else
		return mac_cb->serdes_vaddr + 0x1000
			+ (mac_id - DSAF_SERVICE_PORT_NUM_PER_DSAF) * 0x100000;
		return dsaf_dev->ppe_base + 0x1000;
}

/**
 * hns_mac_get_cfg - get mac cfg from dtb or acpi table
 * @dsaf_dev: dsa fabric device struct pointer
 * @mac_idx: mac index
 * retuen 0 - success , negative --fail
 * @mac_cb: mac control block
 * return 0 - success , negative --fail
 */
int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx)
int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, struct hns_mac_cb *mac_cb)
{
	int ret;
	u32 mac_mode_idx;
	struct hns_mac_cb *mac_cb = &dsaf_dev->mac_cb[mac_idx];

	mac_cb->dsaf_dev = dsaf_dev;
	mac_cb->dev = dsaf_dev->dev;
	mac_cb->mac_id = mac_idx;

	mac_cb->sys_ctl_vaddr =	dsaf_dev->sc_base;
	mac_cb->serdes_vaddr = dsaf_dev->sds_base;

	if (dsaf_dev->cpld_base &&
	    mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) {
		mac_cb->cpld_vaddr = dsaf_dev->cpld_base +
			mac_cb->mac_id * CPLD_ADDR_PORT_OFFSET;
		cpld_led_reset(mac_cb);
	}
	mac_cb->sfp_prsnt = 0;
	mac_cb->txpkt_for_led = 0;
	mac_cb->rxpkt_for_led = 0;

	if (mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF)
	if (!HNS_DSAF_IS_DEBUG(dsaf_dev))
		mac_cb->mac_type = HNAE_PORT_SERVICE;
	else
		mac_cb->mac_type = HNAE_PORT_DEBUG;
@@ -758,53 +799,100 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx)
	}
	mac_mode_idx = (u32)ret;

	hns_mac_get_info(mac_cb, mac_cb->dev->of_node, mac_mode_idx);
	ret  = hns_mac_get_info(mac_cb);
	if (ret)
		return ret;

	cpld_led_reset(mac_cb);
	mac_cb->vaddr = hns_mac_get_vaddr(dsaf_dev, mac_cb, mac_mode_idx);

	return 0;
}

static int hns_mac_get_max_port_num(struct dsaf_device *dsaf_dev)
{
	if (HNS_DSAF_IS_DEBUG(dsaf_dev))
		return 1;
	else
		return  DSAF_MAX_PORT_NUM;
}

/**
 * hns_mac_init - init mac
 * @dsaf_dev: dsa fabric device struct pointer
 * retuen 0 - success , negative --fail
 * return 0 - success , negative --fail
 */
int hns_mac_init(struct dsaf_device *dsaf_dev)
{
	int i;
	bool found = false;
	int ret;
	size_t size;
	u32 port_id;
	int max_port_num = hns_mac_get_max_port_num(dsaf_dev);
	struct hns_mac_cb *mac_cb;
	struct fwnode_handle *child;

	device_for_each_child_node(dsaf_dev->dev, child) {
		ret = fwnode_property_read_u32(child, "port-id", &port_id);
		if (ret) {
			dev_err(dsaf_dev->dev,
				"get port-id fail, ret=%d!\n", ret);
			return ret;
		}
		if (port_id >= max_port_num) {
			dev_err(dsaf_dev->dev,
				"port-id(%u) out of range!\n", port_id);
			return -EINVAL;
		}
		mac_cb = devm_kzalloc(dsaf_dev->dev, sizeof(*mac_cb),
				      GFP_KERNEL);
		if (!mac_cb)
			return -ENOMEM;
		mac_cb->fw_port = child;
		mac_cb->mac_id = (u8)port_id;
		dsaf_dev->mac_cb[port_id] = mac_cb;
		found = true;
	}

	size = sizeof(struct hns_mac_cb) * DSAF_MAX_PORT_NUM_PER_CHIP;
	dsaf_dev->mac_cb = devm_kzalloc(dsaf_dev->dev, size, GFP_KERNEL);
	if (!dsaf_dev->mac_cb)
	/* if don't get any port subnode from dsaf node
	 * will init all port then, this is compatible with the old dts
	 */
	if (!found) {
		for (port_id = 0; port_id < max_port_num; port_id++) {
			mac_cb = devm_kzalloc(dsaf_dev->dev, sizeof(*mac_cb),
					      GFP_KERNEL);
			if (!mac_cb)
				return -ENOMEM;

	for (i = 0; i < DSAF_MAX_PORT_NUM_PER_CHIP; i++) {
		ret = hns_mac_get_cfg(dsaf_dev, i);
		if (ret)
			goto free_mac_cb;
			mac_cb->mac_id = port_id;
			dsaf_dev->mac_cb[port_id] = mac_cb;
		}
	}
	/* init mac_cb for all port */
	for (port_id = 0; port_id < max_port_num; port_id++) {
		mac_cb = dsaf_dev->mac_cb[port_id];
		if (!mac_cb)
			continue;

		mac_cb = &dsaf_dev->mac_cb[i];
		ret = hns_mac_get_cfg(dsaf_dev, mac_cb);
		if (ret)
			return ret;
		ret = hns_mac_init_ex(mac_cb);
		if (ret)
			goto free_mac_cb;
			return ret;
	}

	return 0;

free_mac_cb:
	dsaf_dev->mac_cb = NULL;

	return ret;
}

void hns_mac_uninit(struct dsaf_device *dsaf_dev)
{
	cpld_led_reset(dsaf_dev->mac_cb);
	dsaf_dev->mac_cb = NULL;
	int i;
	int max_port_num = hns_mac_get_max_port_num(dsaf_dev);

	for (i = 0; i < max_port_num; i++) {
		cpld_led_reset(dsaf_dev->mac_cb[i]);
		dsaf_dev->mac_cb[i] = NULL;
	}
}

int hns_mac_config_mac_loopback(struct hns_mac_cb *mac_cb,
@@ -892,7 +980,7 @@ void hns_set_led_opt(struct hns_mac_cb *mac_cb)
int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb,
			enum hnae_led_state status)
{
	if (!mac_cb || !mac_cb->cpld_vaddr)
	if (!mac_cb || !mac_cb->cpld_ctrl)
		return 0;

	return cpld_set_led_id(mac_cb, status);
Loading