From c7d2940c2778b1f25809259487537d2622ba333f Mon Sep 17 00:00:00 2001 From: Brandon Chuang Date: Thu, 19 Sep 2024 17:12:39 +0800 Subject: [PATCH] [Accton][as7535-28xb] Add onlp_data_path_reset() to support chip reset functionality * Implements warm reset for MAC, MUX. * @param unit_id: The warm reset device unit ID, should be 0. * @param reset_dev: The warm reset device ID, should be 1 to (WARM_RESET_MAX-1). * @param ret: Return value. Signed-off-by: Brandon Chuang --- .../builds/x86-64-accton-as7535-28xb-sys.c | 87 +++++++++++++++++++ .../module/src/platform_lib.c | 39 ++++++++- .../module/src/platform_lib.h | 7 ++ 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/packages/platforms/accton/x86-64/as7535-28xb/modules/builds/x86-64-accton-as7535-28xb-sys.c b/packages/platforms/accton/x86-64/as7535-28xb/modules/builds/x86-64-accton-as7535-28xb-sys.c index fb9fb65923..897cc5b464 100644 --- a/packages/platforms/accton/x86-64/as7535-28xb/modules/builds/x86-64-accton-as7535-28xb-sys.c +++ b/packages/platforms/accton/x86-64/as7535-28xb/modules/builds/x86-64-accton-as7535-28xb-sys.c @@ -37,6 +37,8 @@ #define IPMI_TIMEOUT (5 * HZ) #define IPMI_ERR_RETRY_TIMES 1 #define IPMI_READ_MAX_LEN 128 +#define IPMI_RESET_CMD 0x65 +#define IPMI_RESET_CMD_LENGTH 6 #define EEPROM_NAME "eeprom" #define EEPROM_SIZE 256 /* 256 byte eeprom */ @@ -49,6 +51,10 @@ static int as7535_28xb_sys_probe(struct platform_device *pdev); static int as7535_28xb_sys_remove(struct platform_device *pdev); static ssize_t show_version(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t get_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); struct ipmi_data { struct completion read_complete; @@ -76,6 +82,8 @@ struct as7535_28xb_sys_data { unsigned char ipmi_resp_eeprom[EEPROM_SIZE]; unsigned char ipmi_resp_cpld; unsigned char ipmi_tx_data[2]; + unsigned char ipmi_resp_rst[2]; + unsigned char ipmi_tx_data_rst[IPMI_RESET_CMD_LENGTH]; struct bin_attribute eeprom; /* eeprom data */ }; @@ -91,12 +99,26 @@ static struct platform_driver as7535_28xb_sys_driver = { }; enum as7535_28xb_sys_sysfs_attrs { + RESET_MUX, + RESET_MAC, FPGA_VER, /* FPGA version */ }; +#define DECLARE_RESET_SENSOR_DEVICE_ATTR() \ + static SENSOR_DEVICE_ATTR(reset_mac, S_IWUSR | S_IRUGO, \ + get_reset, set_reset, RESET_MAC); \ + static SENSOR_DEVICE_ATTR(reset_mux, S_IWUSR | S_IRUGO, \ + get_reset, set_reset, RESET_MUX) +#define DECLARE_RESET_ATTR() \ + &sensor_dev_attr_reset_mac.dev_attr.attr, \ + &sensor_dev_attr_reset_mux.dev_attr.attr + +DECLARE_RESET_SENSOR_DEVICE_ATTR(); static SENSOR_DEVICE_ATTR(fpga_version, S_IRUGO, show_version, NULL, FPGA_VER); static struct attribute *as7535_28xb_sys_attributes[] = { + /* sysfs attributes */ + DECLARE_RESET_ATTR(), &sensor_dev_attr_fpga_version.dev_attr.attr, NULL }; @@ -245,6 +267,71 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) complete(&ipmi->read_complete); } +static ssize_t get_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status = 0; + + mutex_lock(&data->update_lock); + status = ipmi_send_message(&data->ipmi, IPMI_RESET_CMD, NULL, 0, + data->ipmi_resp_rst, sizeof(data->ipmi_resp_rst)); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "0x%x 0x%x", data->ipmi_resp_rst[0], data->ipmi_resp_rst[1]); + + exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + u32 magic[2]; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (sscanf(buf, "0x%x 0x%x", &magic[0], &magic[1]) != 2) + return -EINVAL; + + if (magic[0] > 0xFF || magic[1] > 0xFF) + return -EINVAL; + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data_rst[0] = 0; + data->ipmi_tx_data_rst[1] = 0; + data->ipmi_tx_data_rst[2] = (attr->index == RESET_MUX) ? 0 : (attr->index); + data->ipmi_tx_data_rst[3] = (attr->index == RESET_MUX) ? 2 : 1; + data->ipmi_tx_data_rst[4] = magic[0]; + data->ipmi_tx_data_rst[5] = magic[1]; + + status = ipmi_send_message(&data->ipmi, IPMI_RESET_CMD, + data->ipmi_tx_data_rst, + sizeof(data->ipmi_tx_data_rst), NULL, 0); + if (unlikely(status != 0)) + goto exit; + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = count; + + exit: + mutex_unlock(&data->update_lock); + return status; +} + static ssize_t sys_eeprom_read(loff_t off, char *buf, size_t count) { int status = 0; diff --git a/packages/platforms/accton/x86-64/as7535-28xb/onlp/builds/x86_64_accton_as7535_28xb/module/src/platform_lib.c b/packages/platforms/accton/x86-64/as7535-28xb/onlp/builds/x86_64_accton_as7535_28xb/module/src/platform_lib.c index 57d05d7608..46bee4ffa5 100644 --- a/packages/platforms/accton/x86-64/as7535-28xb/onlp/builds/x86_64_accton_as7535_28xb/module/src/platform_lib.c +++ b/packages/platforms/accton/x86-64/as7535-28xb/onlp/builds/x86_64_accton_as7535_28xb/module/src/platform_lib.c @@ -27,6 +27,8 @@ #include #include "platform_lib.h" +#define WARM_RESET_FORMAT "/sys/devices/platform/as7535_28xb_sys/reset_%s" + enum onlp_fan_dir onlp_get_fan_dir(int fid) { int len = 0; @@ -79,4 +81,39 @@ int get_pcb_id() pcb_id = (atoi(data) >> 2) & 0xff; return pcb_id; -} \ No newline at end of file +} + +/** + * @brief warm reset for mac, mux + * @param unit_id The warm reset device unit id, should be 0 + * @param reset_dev The warm reset device id, should be 1 ~ (WARM_RESET_MAX-1) + * @param ret return value. + */ +int onlp_data_path_reset(uint8_t unit_id, uint8_t reset_dev) +{ + int len = 0; + int ret = ONLP_STATUS_OK; + char *magic_num = NULL; + char *device_id[] = { NULL, "mac", NULL, "mux" }; + + if (unit_id != 0 || reset_dev >= WARM_RESET_MAX) + return ONLP_STATUS_E_PARAM; + + if (reset_dev == 0 || reset_dev == WARM_RESET_PHY) + return ONLP_STATUS_E_UNSUPPORTED; + + /* Reset device */ + len = onlp_file_read_str(&magic_num, WARM_RESET_FORMAT, device_id[reset_dev]); + if (magic_num && len) { + ret = onlp_file_write_str(magic_num, WARM_RESET_FORMAT, device_id[reset_dev]); + if (ret < 0) { + AIM_LOG_ERROR("Reset device-%d:(%s) failed.", reset_dev, device_id[reset_dev]); + } + } + else { + ret = ONLP_STATUS_E_INTERNAL; + } + + AIM_FREE_IF_PTR(magic_num); + return ret; +} diff --git a/packages/platforms/accton/x86-64/as7535-28xb/onlp/builds/x86_64_accton_as7535_28xb/module/src/platform_lib.h b/packages/platforms/accton/x86-64/as7535-28xb/onlp/builds/x86_64_accton_as7535_28xb/module/src/platform_lib.h index a0a324bd17..f9e17371be 100644 --- a/packages/platforms/accton/x86-64/as7535-28xb/onlp/builds/x86_64_accton_as7535_28xb/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/as7535-28xb/onlp/builds/x86_64_accton_as7535_28xb/module/src/platform_lib.h @@ -65,6 +65,13 @@ enum onlp_thermal_id { THERMAL_COUNT }; +enum reset_dev_type { + WARM_RESET_MAC = 1, + WARM_RESET_PHY, /* Not supported */ + WARM_RESET_MUX, + WARM_RESET_MAX +}; + enum onlp_led_id { LED_LOC = 1, LED_DIAG,