Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Accton][as7535-28xb] Add onlp_data_path_reset() to support chip reset #997

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
Expand Down Expand Up @@ -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 */
};

Expand All @@ -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
};
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <onlplib/file.h>
#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;
Expand Down Expand Up @@ -79,4 +81,39 @@ int get_pcb_id()
pcb_id = (atoi(data) >> 2) & 0xff;

return pcb_id;
}
}

/**
* @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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down