net: hns: add ACPI mode support for ethtool -p
authorJian Shen <shenjian15@huawei.com>
Fri, 29 Dec 2017 09:11:11 +0000 (17:11 +0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 2 Jan 2018 19:50:39 +0000 (14:50 -0500)
The locate operation interface of fiber port can only
work with DT mode. Add a new interface to control the
locate led for ACPI mode.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Tested-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c

index 8b5cdf490850374baba82205264967c8f12a50e5..cac86e9ae0dd92b5464308ed70ea063dd520190c 100644 (file)
@@ -1168,7 +1168,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_ctrl)
+       if (!mac_cb)
                return 0;
 
        return mac_cb->dsaf_dev->misc_op->cpld_set_led_id(mac_cb, status);
index 408b63faf9a81ac9d4bb3e78af3fbfdeb4dbc407..ca247c2cc238af00f1a400785ef21fa3b241996c 100644 (file)
@@ -18,6 +18,7 @@ enum _dsm_op_index {
        HNS_OP_LED_SET_FUNC             = 0x3,
        HNS_OP_GET_PORT_TYPE_FUNC       = 0x4,
        HNS_OP_GET_SFP_STAT_FUNC        = 0x5,
+       HNS_OP_LOCATE_LED_SET_FUNC      = 0x6,
 };
 
 enum _dsm_rst_type {
@@ -81,6 +82,33 @@ static void hns_dsaf_acpi_ledctrl_by_port(struct hns_mac_cb *mac_cb, u8 op_type,
        ACPI_FREE(obj);
 }
 
+static void hns_dsaf_acpi_locate_ledctrl_by_port(struct hns_mac_cb *mac_cb,
+                                                u8 op_type, u32 locate,
+                                                u32 port)
+{
+       union acpi_object obj_args[2], argv4;
+       union acpi_object *obj;
+
+       obj_args[0].integer.type = ACPI_TYPE_INTEGER;
+       obj_args[0].integer.value = locate;
+       obj_args[1].integer.type = ACPI_TYPE_INTEGER;
+       obj_args[1].integer.value = port;
+
+       argv4.type = ACPI_TYPE_PACKAGE;
+       argv4.package.count = 2;
+       argv4.package.elements = obj_args;
+
+       obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dev),
+                               &hns_dsaf_acpi_dsm_guid, 0, op_type, &argv4);
+       if (!obj) {
+               dev_err(mac_cb->dev, "ledctrl fail, locate:%d port:%d!\n",
+                       locate, port);
+               return;
+       }
+
+       ACPI_FREE(obj);
+}
+
 static void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status,
                             u16 speed, int data)
 {
@@ -160,6 +188,9 @@ static void cpld_led_reset_acpi(struct hns_mac_cb *mac_cb)
 static int cpld_set_led_id(struct hns_mac_cb *mac_cb,
                           enum hnae_led_state status)
 {
+       if (!mac_cb->cpld_ctrl)
+               return 0;
+
        switch (status) {
        case HNAE_LED_ACTIVE:
                mac_cb->cpld_led_value =
@@ -184,6 +215,30 @@ static int cpld_set_led_id(struct hns_mac_cb *mac_cb,
        return 0;
 }
 
+static int cpld_set_led_id_acpi(struct hns_mac_cb *mac_cb,
+                               enum hnae_led_state status)
+{
+       switch (status) {
+       case HNAE_LED_ACTIVE:
+               hns_dsaf_acpi_locate_ledctrl_by_port(mac_cb,
+                                                    HNS_OP_LOCATE_LED_SET_FUNC,
+                                                    CPLD_LED_ON_VALUE,
+                                                    mac_cb->mac_id);
+               break;
+       case HNAE_LED_INACTIVE:
+               hns_dsaf_acpi_locate_ledctrl_by_port(mac_cb,
+                                                    HNS_OP_LOCATE_LED_SET_FUNC,
+                                                    CPLD_LED_DEFAULT_VALUE,
+                                                    mac_cb->mac_id);
+               break;
+       default:
+               dev_err(mac_cb->dev, "invalid led state: %d!", status);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 #define RESET_REQ_OR_DREQ 1
 
 static void hns_dsaf_acpi_srst_by_port(struct dsaf_device *dsaf_dev, u8 op_type,
@@ -660,7 +715,7 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev)
        } else if (is_acpi_node(dsaf_dev->dev->fwnode)) {
                misc_op->cpld_set_led = hns_cpld_set_led_acpi;
                misc_op->cpld_reset_led = cpld_led_reset_acpi;
-               misc_op->cpld_set_led_id = cpld_set_led_id;
+               misc_op->cpld_set_led_id = cpld_set_led_id_acpi;
 
                misc_op->dsaf_reset = hns_dsaf_rst_acpi;
                misc_op->xge_srst = hns_dsaf_xge_srst_by_port_acpi;