Merge pull request #468 from brandonchuang/as5916_54xks

[as5916-54xks] Add cpld watchdog / enhance mutex protection of peripheral drivers
This commit is contained in:
Jeffrey Townsend
2018-11-27 13:17:11 -08:00
committed by GitHub
6 changed files with 399 additions and 123 deletions

View File

@@ -270,8 +270,6 @@ static struct as5916_54xks_fan_data *as5916_54xks_fan_update_device(void)
return data;
}
mutex_lock(&data->update_lock);
data->valid = 0;
status = ipmi_send_message(&data->ipmi, IPMI_FAN_READ_CMD, NULL, 0,
data->ipmi_resp, sizeof(data->ipmi_resp));
@@ -288,7 +286,6 @@ static struct as5916_54xks_fan_data *as5916_54xks_fan_update_device(void)
data->valid = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -296,14 +293,17 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *da, char *b
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR;
struct as5916_54xks_fan_data *data = NULL;
int value = 0;
int index = 0;
int present = 0;
int error = 0;
mutex_lock(&data->update_lock);
data = as5916_54xks_fan_update_device();
if (!data->valid) {
return -EIO;
error = -EIO;
goto exit;
}
index = fid * FAN_DATA_COUNT; /* base index */
@@ -336,10 +336,16 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *da, char *b
(int)data->ipmi_resp[index + FAN_SPEED1] << 8;
break;
default:
return -EINVAL;
error = -EINVAL;
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", present ? value : 0);
exit:
mutex_unlock(&data->update_lock);
return error;
}
static ssize_t set_fan(struct device *dev, struct device_attribute *da,
@@ -357,6 +363,8 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *da,
pwm = (pwm * 100) / 625 - 1; /* Convert pwm to register value */
mutex_lock(&data->update_lock);
/* Send IPMI write command */
data->ipmi_tx_data[0] = 1; /* All FANs share the same PWM register, ALWAYS set 1 for each fan */
data->ipmi_tx_data[1] = 0x02;
@@ -364,17 +372,21 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *da,
status = ipmi_send_message(&data->ipmi, IPMI_FAN_WRITE_CMD,
data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0);
if (unlikely(status != 0)) {
return status;
goto exit;
}
if (unlikely(data->ipmi.rx_result != 0)) {
return -EIO;
status = -EIO;
goto exit;
}
/* Update pwm to ipmi_resp buffer to prevent from the impact of lazy update */
data->ipmi_resp[fid * FAN_DATA_COUNT + FAN_PWM] = pwm;
status = count;
return count;
exit:
mutex_unlock(&data->update_lock);
return status;
}
static int as5916_54xks_fan_probe(struct platform_device *pdev)

View File

@@ -254,8 +254,6 @@ static struct as5916_54xks_led_data *as5916_54xks_led_update_device(void)
return data;
}
mutex_lock(&data->update_lock);
data->valid = 0;
status = ipmi_send_message(&data->ipmi, IPMI_LED_READ_CMD, NULL, 0,
data->ipmi_resp, sizeof(data->ipmi_resp));
@@ -272,19 +270,21 @@ static struct as5916_54xks_led_data *as5916_54xks_led_update_device(void)
data->valid = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
static ssize_t show_led(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5916_54xks_led_data *data = NULL;
int value = 0;
int error = 0;
mutex_lock(&data->update_lock);
data = as5916_54xks_led_update_device();
if (!data->valid) {
return -EIO;
error = -EIO;
goto exit;
}
switch (attr->index) {
@@ -309,10 +309,16 @@ static ssize_t show_led(struct device *dev, struct device_attribute *da, char *b
value = LED_MODE_AUTO;
break;
default:
return -EINVAL;
error = -EINVAL;
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", value);
exit:
mutex_unlock(&data->update_lock);
return error;
}
static ssize_t set_led(struct device *dev, struct device_attribute *da,
@@ -321,16 +327,18 @@ static ssize_t set_led(struct device *dev, struct device_attribute *da,
long mode;
int status;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5916_54xks_led_data *data = NULL;
status = kstrtol(buf, 10, &mode);
if (status) {
return status;
}
mutex_lock(&data->update_lock);
data = as5916_54xks_led_update_device();
if (!data->valid) {
return -EIO;
status = -EIO;
goto exit;
}
switch (attr->index) {
@@ -355,21 +363,27 @@ static ssize_t set_led(struct device *dev, struct device_attribute *da,
break;
}
default:
return -EINVAL;
status = -EINVAL;
goto exit;
}
/* Send IPMI write command */
status = ipmi_send_message(&data->ipmi, IPMI_LED_WRITE_CMD,
data->ipmi_resp, sizeof(data->ipmi_resp), NULL, 0);
if (unlikely(status != 0)) {
return status;
goto exit;
}
if (unlikely(data->ipmi.rx_result != 0)) {
return -EIO;
status = -EIO;
goto exit;
}
return count;
status = count;
exit:
mutex_unlock(&data->update_lock);
return status;
}
static int as5916_54xks_led_probe(struct platform_device *pdev)

View File

@@ -302,8 +302,6 @@ static struct as5916_54xks_psu_data *as5916_54xks_psu_update_device(struct devic
return data;
}
mutex_lock(&data->update_lock);
data->valid[pid] = 0;
/* Get status from ipmi */
@@ -349,7 +347,6 @@ static struct as5916_54xks_psu_data *as5916_54xks_psu_update_device(struct devic
data->valid[pid] = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -364,12 +361,15 @@ static ssize_t show_psu(struct device *dev, struct device_attribute *da, char *b
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR;
struct as5916_54xks_psu_data *data = NULL;
int value = 0;
int error = 0;
mutex_lock(&data->update_lock);
data = as5916_54xks_psu_update_device(da);
if (!data->valid[pid]) {
return -EIO;
error = -EIO;
goto exit;
}
switch (attr->index) {
@@ -385,50 +385,59 @@ static ssize_t show_psu(struct device *dev, struct device_attribute *da, char *b
case PSU1_VOUT:
case PSU2_VOUT:
VALIDATE_PRESENT_RETURN(pid);
value = ((int)data->ipmi_resp[pid].status[PSU_VOUT0] |
(int)data->ipmi_resp[pid].status[PSU_VOUT1] << 8) * 1000;
value = ((u32)data->ipmi_resp[pid].status[PSU_VOUT0] |
(u32)data->ipmi_resp[pid].status[PSU_VOUT1] << 8) * 1000;
break;
case PSU1_IOUT:
case PSU2_IOUT:
VALIDATE_PRESENT_RETURN(pid);
value = ((int)data->ipmi_resp[pid].status[PSU_IOUT0] |
(int)data->ipmi_resp[pid].status[PSU_IOUT1] << 8) * 1000;
value = ((u32)data->ipmi_resp[pid].status[PSU_IOUT0] |
(u32)data->ipmi_resp[pid].status[PSU_IOUT1] << 8) * 1000;
break;
case PSU1_POUT:
case PSU2_POUT:
VALIDATE_PRESENT_RETURN(pid);
value = ((int)data->ipmi_resp[pid].status[PSU_POUT0] |
(int)data->ipmi_resp[pid].status[PSU_POUT1] << 8) * 1000;
value = ((u32)data->ipmi_resp[pid].status[PSU_POUT0] |
(u32)data->ipmi_resp[pid].status[PSU_POUT1] << 8) * 1000;
break;
case PSU1_TEMP_INPUT:
case PSU2_TEMP_INPUT:
VALIDATE_PRESENT_RETURN(pid);
value = ((int)data->ipmi_resp[pid].status[PSU_TEMP0] |
(int)data->ipmi_resp[pid].status[PSU_TEMP1] << 8) * 1000;
value = ((u32)data->ipmi_resp[pid].status[PSU_TEMP0] |
(u32)data->ipmi_resp[pid].status[PSU_TEMP1] << 8) * 1000;
break;
case PSU1_FAN_INPUT:
case PSU2_FAN_INPUT:
VALIDATE_PRESENT_RETURN(pid);
value = ((int)data->ipmi_resp[pid].status[PSU_FAN0] |
(int)data->ipmi_resp[pid].status[PSU_FAN1] << 8);
value = ((u32)data->ipmi_resp[pid].status[PSU_FAN0] |
(u32)data->ipmi_resp[pid].status[PSU_FAN1] << 8);
break;
default:
return -EINVAL;
error = -EINVAL;
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", value);
exit:
mutex_unlock(&data->update_lock);
return error;
}
static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR;
struct as5916_54xks_psu_data *data;
char *str = NULL;
int error = 0;
mutex_lock(&data->update_lock);
data = as5916_54xks_psu_update_device(da);
if (!data->valid[pid]) {
return -EIO;
error = -EIO;
goto exit;
}
switch (attr->index) {
@@ -443,10 +452,16 @@ static ssize_t show_string(struct device *dev, struct device_attribute *da, char
str = data->ipmi_resp[pid].serial;
break;
default:
return -EINVAL;
error = -EINVAL;
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%s\n", str);
exit:
mutex_unlock(&data->update_lock);
return error;
}
static int as5916_54xks_psu_probe(struct platform_device *pdev)

View File

@@ -493,8 +493,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_present(void)
return data;
}
mutex_lock(&data->update_lock);
data->ipmi_resp.sfp_valid[SFP_PRESENT] = 0;
/* Get status from ipmi */
@@ -516,7 +514,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_present(void)
data->ipmi_resp.sfp_valid[SFP_PRESENT] = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -529,8 +526,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_txdisable(void)
return data;
}
mutex_lock(&data->update_lock);
data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 0;
/* Get status from ipmi */
@@ -552,7 +547,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_txdisable(void)
data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -565,8 +559,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_txfault(void)
return data;
}
mutex_lock(&data->update_lock);
data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 0;
/* Get status from ipmi */
@@ -588,7 +580,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_txfault(void)
data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -601,8 +592,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_rxlos(void)
return data;
}
mutex_lock(&data->update_lock);
data->ipmi_resp.sfp_valid[SFP_RXLOS] = 0;
/* Get status from ipmi */
@@ -624,7 +613,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_sfp_update_rxlos(void)
data->ipmi_resp.sfp_valid[SFP_RXLOS] = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -637,8 +625,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_present(void)
return data;
}
mutex_lock(&data->update_lock);
data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 0;
/* Get status from ipmi */
@@ -660,7 +646,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_present(void)
data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -673,8 +658,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_txdisable(void)
return data;
}
mutex_lock(&data->update_lock);
data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 0;
/* Get status from ipmi */
@@ -696,7 +679,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_txdisable(void)
data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -709,8 +691,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_reset(void)
return data;
}
mutex_lock(&data->update_lock);
data->ipmi_resp.qsfp_valid[QSFP_RESET] = 0;
/* Get status from ipmi */
@@ -732,7 +712,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_reset(void)
data->ipmi_resp.qsfp_valid[QSFP_RESET] = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -745,8 +724,6 @@ static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_lpmode(void)
return data;
}
mutex_lock(&data->update_lock);
data->ipmi_resp.qsfp_valid[QSFP_LPMODE] = 0;
/* Get status from ipmi */
@@ -768,27 +745,29 @@ static struct as5916_54xks_sfp_data *as5916_54xks_qsfp_update_lpmode(void)
data->ipmi_resp.qsfp_valid[QSFP_LPMODE] = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
static ssize_t show_all(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5916_54xks_sfp_data *data = NULL;
u64 values = 0;
int i;
switch (attr->index) {
case PRESENT_ALL:
{
mutex_lock(&data->update_lock);
data = as5916_54xks_sfp_update_present();
if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) {
mutex_unlock(&data->update_lock);
return -EIO;
}
data = as5916_54xks_qsfp_update_present();
if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) {
mutex_unlock(&data->update_lock);
return -EIO;
}
@@ -803,6 +782,8 @@ static ssize_t show_all(struct device *dev, struct device_attribute *da, char *b
values <<= 1;
values |= (data->ipmi_resp.sfp_resp[SFP_PRESENT][i] & 0x1);
}
mutex_unlock(&data->update_lock);
/* Return values 1 -> 54 in order */
return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
@@ -816,8 +797,11 @@ static ssize_t show_all(struct device *dev, struct device_attribute *da, char *b
}
case RXLOS_ALL:
{
mutex_lock(&data->update_lock);
data = as5916_54xks_sfp_update_rxlos();
if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) {
mutex_unlock(&data->update_lock);
return -EIO;
}
@@ -827,6 +811,8 @@ static ssize_t show_all(struct device *dev, struct device_attribute *da, char *b
values |= !(data->ipmi_resp.sfp_resp[SFP_RXLOS][i] & 0x1);
}
mutex_unlock(&data->update_lock);
/* Return values 1 -> 48 in order */
return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n",
(unsigned int)(0xFF & values),
@@ -847,8 +833,10 @@ static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *b
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */
struct as5916_54xks_sfp_data *data = NULL;
int value = 0;
int error = 0;
mutex_lock(&data->update_lock);
switch (attr->index) {
case SFP1_PRESENT:
@@ -902,7 +890,8 @@ static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *b
{
data = as5916_54xks_sfp_update_present();
if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) {
return -EIO;
error = -EIO;
goto exit;
}
value = data->ipmi_resp.sfp_resp[SFP_PRESENT][pid];
@@ -959,7 +948,8 @@ static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *b
{
data = as5916_54xks_sfp_update_txdisable();
if (!data->ipmi_resp.sfp_valid[SFP_TXDISABLE]) {
return -EIO;
error = -EIO;
goto exit;
}
value = !data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid];
@@ -1016,7 +1006,8 @@ static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *b
{
data = as5916_54xks_sfp_update_txfault();
if (!data->ipmi_resp.sfp_valid[SFP_TXFAULT]) {
return -EIO;
error = -EIO;
goto exit;
}
value = data->ipmi_resp.sfp_resp[SFP_TXFAULT][pid];
@@ -1073,17 +1064,24 @@ static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *b
{
data = as5916_54xks_sfp_update_rxlos();
if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) {
return -EIO;
error = -EIO;
goto exit;
}
value = !data->ipmi_resp.sfp_resp[SFP_RXLOS][pid];
break;
}
default:
return -EINVAL;
error = -EINVAL;
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", value);
exit:
mutex_unlock(&data->update_lock);
return error;
}
static ssize_t set_sfp(struct device *dev, struct device_attribute *da,
@@ -1101,6 +1099,8 @@ static ssize_t set_sfp(struct device *dev, struct device_attribute *da,
disable = !disable; /* the IPMI cmd is 0 for tx-disable and 1 for tx-enable */
mutex_lock(&data->update_lock);
/* Send IPMI write command */
data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */
data->ipmi_tx_data[1] = 0x01;
@@ -1108,25 +1108,31 @@ static ssize_t set_sfp(struct device *dev, struct device_attribute *da,
status = ipmi_send_message(&data->ipmi, IPMI_SFP_WRITE_CMD,
data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0);
if (unlikely(status != 0)) {
return status;
goto exit;
}
if (unlikely(data->ipmi.rx_result != 0)) {
return -EIO;
status = -EIO;
goto exit;
}
/* Update to ipmi_resp buffer to prevent from the impact of lazy update */
data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid] = disable;
status = count;
return count;
exit:
mutex_unlock(&data->update_lock);
return status;
}
static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */
struct as5916_54xks_sfp_data *data = NULL;
int value = 0;
int error = 0;
mutex_lock(&data->update_lock);
switch (attr->index) {
case QSFP49_PRESENT:
@@ -1138,7 +1144,8 @@ static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *
{
data = as5916_54xks_qsfp_update_present();
if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) {
return -EIO;
error = -EIO;
goto exit;
}
value = data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid];
@@ -1153,7 +1160,8 @@ static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *
{
data = as5916_54xks_qsfp_update_txdisable();
if (!data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE]) {
return -EIO;
error = -EIO;
goto exit;
}
value = !!data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid];
@@ -1168,7 +1176,8 @@ static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *
{
data = as5916_54xks_qsfp_update_reset();
if (!data->ipmi_resp.qsfp_valid[QSFP_RESET]) {
return -EIO;
error = -EIO;
goto exit;
}
value = !data->ipmi_resp.qsfp_resp[QSFP_RESET][pid];
@@ -1183,17 +1192,24 @@ static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *
{
data = as5916_54xks_qsfp_update_lpmode();
if (!data->ipmi_resp.qsfp_valid[QSFP_LPMODE]) {
return -EIO;
error = -EIO;
goto exit;
}
value = data->ipmi_resp.qsfp_resp[QSFP_LPMODE][pid];
break;
}
default:
return -EINVAL;
error = -EINVAL;
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", value);
exit:
mutex_unlock(&data->update_lock);
return error;
}
static ssize_t set_qsfp_txdisable(struct device *dev, struct device_attribute *da,
@@ -1203,20 +1219,23 @@ static ssize_t set_qsfp_txdisable(struct device *dev, struct device_attribute *d
int status;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */
struct as5916_54xks_sfp_data *data = NULL;
mutex_lock(&data->update_lock);
data = as5916_54xks_qsfp_update_present();
if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) {
return -EIO;
status = -EIO;
goto exit;
}
if (!data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid]) {
return -ENXIO;
status = -ENXIO;
goto exit;
}
status = kstrtol(buf, 10, &disable);
if (status) {
return status;
goto exit;
}
/* Send IPMI write command */
@@ -1226,17 +1245,21 @@ static ssize_t set_qsfp_txdisable(struct device *dev, struct device_attribute *d
status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD,
data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0);
if (unlikely(status != 0)) {
return status;
goto exit;
}
if (unlikely(data->ipmi.rx_result != 0)) {
return -EIO;
status = -EIO;
goto exit;
}
/* Update to ipmi_resp buffer to prevent from the impact of lazy update */
data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid] = disable;
status = count;
return count;
exit:
mutex_unlock(&data->update_lock);
return status;
}
static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da,
@@ -1254,6 +1277,8 @@ static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da,
reset = !reset; /* the IPMI cmd is 0 for reset and 1 for out of reset */
mutex_lock(&data->update_lock);
/* Send IPMI write command */
data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */
data->ipmi_tx_data[1] = 0x11;
@@ -1261,17 +1286,21 @@ static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da,
status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD,
data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0);
if (unlikely(status != 0)) {
return status;
goto exit;
}
if (unlikely(data->ipmi.rx_result != 0)) {
return -EIO;
status = -EIO;
goto exit;
}
/* Update to ipmi_resp buffer to prevent from the impact of lazy update */
data->ipmi_resp.qsfp_resp[QSFP_RESET][pid] = reset;
return count;
status = count;
exit:
mutex_unlock(&data->update_lock);
return status;
}
static ssize_t set_qsfp_lpmode(struct device *dev, struct device_attribute *da,
@@ -1287,6 +1316,8 @@ static ssize_t set_qsfp_lpmode(struct device *dev, struct device_attribute *da,
return status;
}
mutex_lock(&data->update_lock);
/* Send IPMI write command */
data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */
data->ipmi_tx_data[1] = 0x12;
@@ -1294,17 +1325,21 @@ static ssize_t set_qsfp_lpmode(struct device *dev, struct device_attribute *da,
status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD,
data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0);
if (unlikely(status != 0)) {
return status;
goto exit;
}
if (unlikely(data->ipmi.rx_result != 0)) {
return -EIO;
status = -EIO;
goto exit;
}
/* Update to ipmi_resp buffer to prevent from the impact of lazy update */
data->ipmi_resp.qsfp_resp[QSFP_LPMODE][pid] = lpmode;
return count;
status = count;
exit:
mutex_unlock(&data->update_lock);
return status;
}
/*************************************************************************************

View File

@@ -52,6 +52,9 @@
#define CPU_CPLD_ADDR 0x65
#define FAN_CPLD_ADDR 0x66
#define IPMI_CPLD_READ_CMD 0x22
#define IPMI_CPLD_WRITE_CMD 0x23
static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
static int as5916_54xks_sys_probe(struct platform_device *pdev);
static int as5916_54xks_sys_remove(struct platform_device *pdev);
@@ -62,6 +65,9 @@ static ssize_t show_interrupt_status_6(struct device *dev, struct device_attribu
static ssize_t set_interrupt_status_6_mask(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_watchdog(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t set_watchdog(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
struct ipmi_data {
struct completion read_complete;
@@ -132,6 +138,11 @@ enum as5916_54xks_sys_sysfs_attrs {
MB_CPLD2_VER, /* mainboard cpld2 version */
CPU_CPLD_VER, /* CPU board CPLD version */
FAN_CPLD_VER, /* FAN CPLD version */
CPU_CPLD_WDS1,/* CPU board CPLD Offset 0x02 Watch Dog Status_1 */
CPU_CPLD_WDS2,/* CPU board CPLD Offset 0x03 Watch Dog Status_2 */
CPU_CPLD_SR, /* CPU board CPLD Offset 0x04 System Reset */
CPU_CPLD_LRS, /* CPU board CPLD Offset 0x24 Last Reset Reason Register */
MB_CPLD_SR1, /* main board CPLD Offset 0x08 System Reset-1 */
};
static SENSOR_DEVICE_ATTR(tcam_rst_c, S_IWUSR | S_IRUGO, show_sys_reset_6, set_sys_reset_6, TCAM_CRST_L);
@@ -145,6 +156,12 @@ static SENSOR_DEVICE_ATTR(mb_cpld1_ver, S_IRUGO, show_cpld_version, NULL, MB_CPL
static SENSOR_DEVICE_ATTR(mb_cpld2_ver, S_IRUGO, show_cpld_version, NULL, MB_CPLD2_VER);
static SENSOR_DEVICE_ATTR(cpu_cpld_ver, S_IRUGO, show_cpld_version, NULL, CPU_CPLD_VER);
static SENSOR_DEVICE_ATTR(fan_cpld_ver, S_IRUGO, show_cpld_version, NULL, FAN_CPLD_VER);
static SENSOR_DEVICE_ATTR(cpu_cpld_wds1, S_IWUSR | S_IRUGO, show_watchdog, set_watchdog, CPU_CPLD_WDS1);
static SENSOR_DEVICE_ATTR(cpu_cpld_wds2, S_IWUSR | S_IRUGO, show_watchdog, set_watchdog, CPU_CPLD_WDS2);
static SENSOR_DEVICE_ATTR(cpu_cpld_system_reset, S_IWUSR | S_IRUGO, show_watchdog, set_watchdog, CPU_CPLD_SR);
static SENSOR_DEVICE_ATTR(cpu_cpld_last_reset_reson, S_IRUGO, show_watchdog, NULL, CPU_CPLD_LRS);
static SENSOR_DEVICE_ATTR(mb_cpld1_system_reset1, S_IWUSR | S_IRUGO, show_watchdog, set_watchdog, MB_CPLD_SR1);
static struct attribute *as5916_54xks_sys_attributes[] = {
&sensor_dev_attr_tcam_rst_c.dev_attr.attr,
@@ -158,6 +175,11 @@ static struct attribute *as5916_54xks_sys_attributes[] = {
&sensor_dev_attr_mb_cpld2_ver.dev_attr.attr,
&sensor_dev_attr_cpu_cpld_ver.dev_attr.attr,
&sensor_dev_attr_fan_cpld_ver.dev_attr.attr,
&sensor_dev_attr_cpu_cpld_wds1.dev_attr.attr,
&sensor_dev_attr_cpu_cpld_wds2.dev_attr.attr,
&sensor_dev_attr_cpu_cpld_system_reset.dev_attr.attr,
&sensor_dev_attr_cpu_cpld_last_reset_reson.dev_attr.attr,
&sensor_dev_attr_mb_cpld1_system_reset1.dev_attr.attr,
NULL
};
@@ -367,8 +389,6 @@ static struct as5916_54xks_sys_data *as5916_54xks_sys_update_tcam(unsigned char
{
int status = 0;
mutex_lock(&data->update_lock);
data->valid = 0;
data->ipmi_tx_data[0] = subcmd;
status = ipmi_send_message(&data->ipmi, IPMI_TCAM_READ_CMD, data->ipmi_tx_data, 1,
@@ -386,7 +406,6 @@ static struct as5916_54xks_sys_data *as5916_54xks_sys_update_tcam(unsigned char
data->valid = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
@@ -396,16 +415,18 @@ static ssize_t set_sys_reset_6(struct device *dev, struct device_attribute *da,
long reset; /* reset value to be set */
int status;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5916_54xks_sys_data *data = NULL;
status = kstrtol(buf, 10, &reset);
if (status) {
return status;
}
mutex_lock(&data->update_lock);
data = as5916_54xks_sys_update_tcam(IPMI_TCAM_RESET_SUBCMD);
if (!data->valid) {
return -EIO;
status = -EIO;
goto exit;
}
switch (attr->index) {
@@ -427,7 +448,8 @@ static ssize_t set_sys_reset_6(struct device *dev, struct device_attribute *da,
data->ipmi_tx_data[1] = reset;
break;
default:
return -EINVAL;
status = -EINVAL;
goto exit;
}
/* Send IPMI write command */
@@ -435,25 +457,33 @@ static ssize_t set_sys_reset_6(struct device *dev, struct device_attribute *da,
status = ipmi_send_message(&data->ipmi, IPMI_TCAM_WRITE_CMD,
data->ipmi_tx_data, 2, NULL, 0);
if (unlikely(status != 0)) {
return status;
goto exit;
}
if (unlikely(data->ipmi.rx_result != 0)) {
return -EIO;
status = -EIO;
goto exit;
}
return count;
status = count;
exit:
mutex_unlock(&data->update_lock);
return status;
}
static ssize_t show_sys_reset_6(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5916_54xks_sys_data *data = NULL;
int value = 0;
int error = 0;
mutex_lock(&data->update_lock);
data = as5916_54xks_sys_update_tcam(IPMI_TCAM_RESET_SUBCMD);
if (!data->valid) {
return -EIO;
error = -EIO;
goto exit;
}
switch (attr->index) {
@@ -474,18 +504,24 @@ static ssize_t show_sys_reset_6(struct device *dev, struct device_attribute *da,
value = data->ipmi_resp_tcam & 0xff;
break;
default:
return -EINVAL;
error = -EINVAL;
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", value);
exit:
mutex_unlock(&data->update_lock);
return error;
}
static ssize_t show_interrupt_status_6(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5916_54xks_sys_data *data = NULL;
unsigned char subcmd = 0;
int value = 0;
int error = 0;
switch (attr->index) {
case TCAM_CPLD1_GIO_L:
@@ -498,13 +534,21 @@ static ssize_t show_interrupt_status_6(struct device *dev, struct device_attribu
return -EINVAL;
}
mutex_lock(&data->update_lock);
data = as5916_54xks_sys_update_tcam(subcmd);
if (!data->valid) {
return -EIO;
error = -EIO;
goto exit;
}
value = data->ipmi_resp_tcam & 0x3;
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", value);
exit:
mutex_unlock(&data->update_lock);
return error;
}
static ssize_t set_interrupt_status_6_mask(struct device *dev, struct device_attribute *da,
@@ -512,16 +556,18 @@ static ssize_t set_interrupt_status_6_mask(struct device *dev, struct device_att
{
long mask = 0; /* mask value to be set */
int status;
struct as5916_54xks_sys_data *data = NULL;
status = kstrtol(buf, 10, &mask);
if (status) {
return status;
}
mutex_lock(&data->update_lock);
data = as5916_54xks_sys_update_tcam(IPMI_TCAM_INT_MASK_SUBCMD);
if (!data->valid) {
return -EIO;
status = -EIO;
goto exit;
}
/* Send IPMI write command */
@@ -530,22 +576,25 @@ static ssize_t set_interrupt_status_6_mask(struct device *dev, struct device_att
status = ipmi_send_message(&data->ipmi, IPMI_TCAM_WRITE_CMD,
data->ipmi_tx_data, 2, NULL, 0);
if (unlikely(status != 0)) {
return status;
goto exit;
}
if (unlikely(data->ipmi.rx_result != 0)) {
return -EIO;
status = -EIO;
goto exit;
}
return count;
status = count;
exit:
mutex_unlock(&data->update_lock);
return status;
}
static struct as5916_54xks_sys_data *as5916_54xks_sys_update_cpld_ver(unsigned char cpld_addr)
{
int status = 0;
mutex_lock(&data->update_lock);
data->valid = 0;
data->ipmi_tx_data[0] = cpld_addr;
status = ipmi_send_message(&data->ipmi, IPMI_GET_CPLD_VER_CMD, data->ipmi_tx_data, 1,
@@ -563,15 +612,14 @@ static struct as5916_54xks_sys_data *as5916_54xks_sys_update_cpld_ver(unsigned c
data->valid = 1;
exit:
mutex_unlock(&data->update_lock);
return data;
}
static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as5916_54xks_sys_data *data = NULL;
unsigned char cpld_addr = 0;
unsigned char cpld_addr = 0, value = 0;
int error = 0;
switch (attr->index) {
case MB_CPLD1_VER:
@@ -590,12 +638,165 @@ static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da
return -EINVAL;
}
mutex_lock(&data->update_lock);
data = as5916_54xks_sys_update_cpld_ver(cpld_addr);
if (!data->valid) {
return -EIO;
error = -EIO;
goto exit;
}
return sprintf(buf, "%d\n", data->ipmi_resp_cpld);
value = data->ipmi_resp_cpld;
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", value);
exit:
mutex_unlock(&data->update_lock);
return error;
}
static struct as5916_54xks_sys_data *as5916_54xks_sys_update_watchdog(unsigned char cpld_addr,
unsigned char reg)
{
int status = 0;
data->valid = 0;
data->ipmi_tx_data[0] = cpld_addr;
data->ipmi_tx_data[1] = reg;
status = ipmi_send_message(&data->ipmi, IPMI_CPLD_READ_CMD, data->ipmi_tx_data, 2,
&data->ipmi_resp_cpld, sizeof(data->ipmi_resp_cpld));
if (unlikely(status != 0)) {
goto exit;
}
if (unlikely(data->ipmi.rx_result != 0)) {
status = -EIO;
goto exit;
}
data->last_updated = jiffies;
data->valid = 1;
exit:
return data;
}
/* Get CPLD<4C><44>s Offset Value
* ipmitool raw 0x34 0x22 <I2CAddress of CPLD > <Offset>
* # ipmitool raw 0x34 0x22 0x65 0x02
* # ipmitool raw 0x34 0x22 0x65 0x03
* # ipmitool raw 0x34 0x22 0x65 0x04
* # ipmitool raw 0x34 0x22 0x65 0x24
* # ipmitool raw 0x34 0x22 0x60 0x08
*/
static ssize_t show_watchdog(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
unsigned char cpld_addr = 0, reg = 0, value = 0;
int error = 0;
switch (attr->index) {
case CPU_CPLD_WDS1:
cpld_addr = CPU_CPLD_ADDR;
reg = 0x2;
break;
case CPU_CPLD_WDS2:
cpld_addr = CPU_CPLD_ADDR;
reg = 0x3;
break;
case CPU_CPLD_SR:
cpld_addr = CPU_CPLD_ADDR;
reg = 0x4;
break;
case CPU_CPLD_LRS:
cpld_addr = CPU_CPLD_ADDR;
reg = 0x24;
break;
case MB_CPLD_SR1:
cpld_addr = MAINBOARD_CPLD1_ADDR;
reg = 0x8;
break;
default:
return -EINVAL;
}
mutex_lock(&data->update_lock);
data = as5916_54xks_sys_update_watchdog(cpld_addr, reg);
if (!data->valid) {
error = -EIO;
goto exit;
}
value = data->ipmi_resp_cpld;
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", value);
exit:
mutex_unlock(&data->update_lock);
return error;
}
/* Set CPLDValue
* # ipmitool raw 0x34 0x23 <I2CAddress of CPLD > <Offset> <Value>
* # ipmitool raw 0x34 0x23 0x65 0x03 0x08
*/
static ssize_t set_watchdog(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
long value = 0; /* cpld value to be set */
int status;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
unsigned char cpld_addr = 0, reg = 0;
status = kstrtol(buf, 10, &value);
if (status) {
return status;
}
switch (attr->index) {
case CPU_CPLD_WDS1:
cpld_addr = CPU_CPLD_ADDR;
reg = 0x2;
break;
case CPU_CPLD_WDS2:
cpld_addr = CPU_CPLD_ADDR;
reg = 0x3;
break;
case CPU_CPLD_SR:
cpld_addr = CPU_CPLD_ADDR;
reg = 0x4;
break;
case MB_CPLD_SR1:
cpld_addr = MAINBOARD_CPLD1_ADDR;
reg = 0x8;
break;
default:
return -EINVAL;
}
mutex_lock(&data->update_lock);
/* Send IPMI write command */
data->ipmi_tx_data[0] = cpld_addr;
data->ipmi_tx_data[1] = reg;
data->ipmi_tx_data[2] = value;
status = ipmi_send_message(&data->ipmi, IPMI_CPLD_WRITE_CMD,
data->ipmi_tx_data, 3, 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 int as5916_54xks_sys_probe(struct platform_device *pdev)

View File

@@ -244,8 +244,6 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *
data->valid = 1;
}
mutex_unlock(&data->update_lock);
/* Get temp fault status */
index = attr->index * TEMP_DATA_COUNT + TEMP_FAULT;
if (unlikely(data->ipmi_resp[index] == 0)) {
@@ -257,6 +255,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *
index = attr->index * TEMP_DATA_COUNT + TEMP_INPUT;
status = data->ipmi_resp[index] * 1000;
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", status);
exit: