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][as7946-30xb] Add onlp_data_path_reset() to support chip reset #998

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 @@ -36,6 +36,8 @@
#define IPMI_SYSEEPROM_READ_CMD 0x18
#define IPMI_TIMEOUT (20 * HZ)
#define IPMI_READ_MAX_LEN 128
#define IPMI_RESET_CMD 0x65
#define IPMI_RESET_CMD_LENGTH 6

#define EEPROM_NAME "eeprom"
#define EEPROM_SIZE 512 /*512 byte eeprom */
Expand All @@ -51,6 +53,10 @@ static int as7946_30xb_sys_probe(struct platform_device *pdev);
static int as7946_30xb_sys_remove(struct platform_device *pdev);
static ssize_t show_cpld_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 @@ -78,6 +84,8 @@ struct as7946_30xb_sys_data {
unsigned char ipmi_resp_eeprom[EEPROM_SIZE];
unsigned char ipmi_resp_cpld[2];
unsigned char ipmi_tx_data[3];
unsigned char ipmi_resp_rst[2];
unsigned char ipmi_tx_data_rst[IPMI_RESET_CMD_LENGTH];
struct bin_attribute eeprom; /* eeprom data */
};

Expand All @@ -96,6 +104,7 @@ enum as7946_30xb_sys_sysfs_attrs {
CPU_CPLD_VER, /* CPU board CPLD version */
SYSTEM_CPLD1_VER, /* System cpld1 version */
FAN_CPLD_VER, /* FAN CPLD version */
RESET_MAC,
};

static SENSOR_DEVICE_ATTR(cpu_cpld_ver, S_IRUGO, show_cpld_version,
Expand All @@ -104,11 +113,14 @@ static SENSOR_DEVICE_ATTR(system_cpld1_ver, S_IRUGO, show_cpld_version,
NULL, SYSTEM_CPLD1_VER);
static SENSOR_DEVICE_ATTR(fan_cpld_ver, S_IRUGO, show_cpld_version,
NULL, FAN_CPLD_VER);
static SENSOR_DEVICE_ATTR(reset_mac, S_IWUSR | S_IRUGO, \
get_reset, set_reset, RESET_MAC);

static struct attribute *as7946_30xb_sys_attributes[] = {
&sensor_dev_attr_cpu_cpld_ver.dev_attr.attr,
&sensor_dev_attr_system_cpld1_ver.dev_attr.attr,
&sensor_dev_attr_fan_cpld_ver.dev_attr.attr,
&sensor_dev_attr_reset_mac.dev_attr.attr,
NULL
};

Expand Down Expand Up @@ -225,6 +237,70 @@ 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;

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] = 1;
data->ipmi_tx_data_rst[3] = 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 @@ -62,15 +62,6 @@ enum fan_id {
{ 0 },\
}

#define AIM_FREE_IF_PTR(p) \
do \
{ \
if (p) { \
aim_free(p); \
p = NULL; \
} \
} while (0)

/* Static fan information */
onlp_fan_info_t finfo[] = {
{ }, /* Not used */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
* Platform Library
*
***********************************************************/
#include <unistd.h>
#include <onlp/onlp.h>
#include <onlplib/file.h>
#include "platform_lib.h"

#define WARM_RESET_FORMAT "/sys/devices/platform/as7946_30xb_sys/reset_%s"

/**
* @brief warm reset for mac
* @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" };

if (unit_id != 0 || reset_dev >= WARM_RESET_MAX)
return ONLP_STATUS_E_PARAM;

if (reset_dev == 0)
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 @@ -42,6 +42,15 @@
#define FAN_BOARD_PATH "/sys/devices/platform/as7946_30xb_fan/"
#define IDPROM_PATH "/sys/devices/platform/as7946_30xb_sys/eeprom"

#define AIM_FREE_IF_PTR(p) \
do \
{ \
if (p) { \
aim_free(p); \
p = NULL; \
} \
} while (0)

enum onlp_led_id {
LED_LOC = 1,
LED_DIAG,
Expand Down Expand Up @@ -70,4 +79,9 @@ enum onlp_thermal_id {
THERMAL_3_ON_PSU2,
};

enum reset_dev_type {
WARM_RESET_MAC = 1,
WARM_RESET_MAX
};

#endif /* __PLATFORM_LIB_H__ */
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,6 @@
} \
} while(0)

#define AIM_FREE_IF_PTR(p) \
do \
{ \
if (p) { \
aim_free(p); \
p = NULL; \
} \
} while (0)

int
onlp_psui_init(void)
{
Expand Down