|
@@ -10,6 +10,7 @@
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/interrupt.h>
|
|
|
#include <linux/kernel.h>
|
|
|
+#include <linux/mfd/syscon.h>
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/netdevice.h>
|
|
|
#include <linux/of.h>
|
|
@@ -168,10 +169,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 +179,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 +192,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 +232,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
|
|
@@ -651,14 +649,15 @@ free_mac_drv:
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- *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;
|
|
|
mac_cb->link = false;
|
|
|
mac_cb->half_duplex = false;
|
|
|
mac_cb->speed = mac_phy_to_speed[mac_cb->phy_if];
|
|
@@ -675,11 +674,34 @@ 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;
|
|
|
|
|
|
- /* 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;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -709,31 +731,27 @@ 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) {
|
|
|
+ if (dsaf_dev->cpld_base && !HNS_DSAF_IS_DEBUG(dsaf_dev)) {
|
|
|
mac_cb->cpld_vaddr = dsaf_dev->cpld_base +
|
|
|
mac_cb->mac_id * CPLD_ADDR_PORT_OFFSET;
|
|
|
cpld_led_reset(mac_cb);
|
|
@@ -742,7 +760,7 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx)
|
|
|
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 +776,99 @@ 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;
|
|
|
|
|
|
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;
|
|
|
|
|
|
- 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)
|
|
|
- return -ENOMEM;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
|
|
|
- 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;
|
|
|
+ /* 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;
|
|
|
+
|
|
|
+ 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,
|