Pass the receive buffer capacity to i2c_smbus_read_block_data() in ipmi_ssif_thread() via the i2c_size field, and update ssif_i2c_send() callers to pass the receive buffer size.
Update read_response(), do_cmd(), and test_multipart_messages() to accept the response buffer length, clamping the transfer size to I2C_SMBUS_BLOCK_MAX when reading from the device. Signed-off-by: Dmitry Torokhov <[email protected]> --- drivers/char/ipmi/ipmi_ssif.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 2361103c5edc..9c0aebec2946 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -503,7 +503,7 @@ static int ipmi_ssif_thread(void *data) } else { result = i2c_smbus_read_block_data( ssif_info->client, ssif_info->i2c_command, - ssif_info->i2c_data); + ssif_info->i2c_size, ssif_info->i2c_data); if (result < 0) ssif_info->done_handler(ssif_info, result, NULL, 0); @@ -541,7 +541,7 @@ static void start_get(struct ssif_info *ssif_info) ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ, SSIF_IPMI_RESPONSE, - ssif_info->recv, I2C_SMBUS_BLOCK_DATA); + ssif_info->recv, sizeof(ssif_info->recv)); } static void start_resend(struct ssif_info *ssif_info); @@ -669,7 +669,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ, SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE, - ssif_info->recv, I2C_SMBUS_BLOCK_DATA); + ssif_info->recv, sizeof(ssif_info->recv)); return; } else if (ssif_info->multi_pos) { /* Middle of multi-part read. Start the next transaction. */ @@ -736,7 +736,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, I2C_SMBUS_READ, SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE, ssif_info->recv, - I2C_SMBUS_BLOCK_DATA); + sizeof(ssif_info->recv)); return; } } @@ -1314,12 +1314,15 @@ static void ssif_remove(struct i2c_client *client) kfree(ssif_info); } -static int read_response(struct i2c_client *client, unsigned char *resp) +static int read_response(struct i2c_client *client, unsigned char *resp, + size_t resp_length) { int ret = -ENODEV, retry_cnt = SSIF_RECV_RETRIES; while (retry_cnt > 0) { ret = i2c_smbus_read_block_data(client, SSIF_IPMI_RESPONSE, + min_t(size_t, resp_length, + I2C_SMBUS_BLOCK_MAX), resp); if (ret > 0) break; @@ -1333,7 +1336,7 @@ static int read_response(struct i2c_client *client, unsigned char *resp) } static int do_cmd(struct i2c_client *client, int len, unsigned char *msg, - int *resp_len, unsigned char *resp) + int *resp_len, unsigned char *resp, size_t resp_length) { int retry_cnt; int ret; @@ -1350,14 +1353,14 @@ static int do_cmd(struct i2c_client *client, int len, unsigned char *msg, return -ENODEV; } - ret = read_response(client, resp); + ret = read_response(client, resp, resp_length); if (ret > 0) { /* Validate that the response is correct. */ if (ret < 3 || (resp[0] != (msg[0] | (1 << 2))) || (resp[1] != msg[1])) ret = -EINVAL; - else if (ret > IPMI_MAX_MSG_LENGTH) { + else if (ret > resp_length) { ret = -E2BIG; } else { *resp_len = ret; @@ -1382,7 +1385,7 @@ static int ssif_detect(struct i2c_client *client, struct i2c_board_info *info) /* Do a Get Device ID command, since it is required. */ msg[0] = IPMI_NETFN_APP_REQUEST << 2; msg[1] = IPMI_GET_DEVICE_ID_CMD; - rv = do_cmd(client, 2, msg, &len, resp); + rv = do_cmd(client, 2, msg, &len, resp, IPMI_MAX_MSG_LENGTH); if (rv) rv = -ENODEV; else { @@ -1523,7 +1526,7 @@ static int start_multipart_test(struct i2c_client *client, static void test_multipart_messages(struct i2c_client *client, struct ssif_info *ssif_info, - unsigned char *resp) + unsigned char *resp, size_t resp_length) { unsigned char msg[65]; int ret; @@ -1572,7 +1575,7 @@ static void test_multipart_messages(struct i2c_client *client, 1, msg + 64); if (!ret) - ret = read_response(client, resp); + ret = read_response(client, resp, resp_length); if (ret > 0) { /* End transactions work, we are good. */ @@ -1590,7 +1593,7 @@ static void test_multipart_messages(struct i2c_client *client, SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE, 0, msg + 64); if (!ret) - ret = read_response(client, resp); + ret = read_response(client, resp, resp_length); if (ret > 0) /* Zero-size end parts work, use those. */ return; @@ -1748,7 +1751,7 @@ static int ssif_probe(struct i2c_client *client) msg[0] = IPMI_NETFN_APP_REQUEST << 2; msg[1] = IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD; msg[2] = 0; /* SSIF */ - rv = do_cmd(client, 3, msg, &len, resp); + rv = do_cmd(client, 3, msg, &len, resp, IPMI_MAX_MSG_LENGTH); if (!rv && (len >= 3) && (resp[2] == 0)) { if (len < 7) { if (ssif_dbg_probe) @@ -1800,13 +1803,13 @@ static int ssif_probe(struct i2c_client *client) ssif_info->supports_pec = 0; } - test_multipart_messages(client, ssif_info, resp); + test_multipart_messages(client, ssif_info, resp, IPMI_MAX_MSG_LENGTH); /* Make sure the NMI timeout is cleared. */ msg[0] = IPMI_NETFN_APP_REQUEST << 2; msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD; msg[2] = WDT_PRE_TIMEOUT_INT; - rv = do_cmd(client, 3, msg, &len, resp); + rv = do_cmd(client, 3, msg, &len, resp, IPMI_MAX_MSG_LENGTH); if (rv || (len < 3) || (resp[2] != 0)) dev_warn(&ssif_info->client->dev, "Unable to clear message flags: %d %d %2.2x\n", @@ -1815,7 +1818,7 @@ static int ssif_probe(struct i2c_client *client) /* Attempt to enable the event buffer. */ msg[0] = IPMI_NETFN_APP_REQUEST << 2; msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; - rv = do_cmd(client, 2, msg, &len, resp); + rv = do_cmd(client, 2, msg, &len, resp, IPMI_MAX_MSG_LENGTH); if (rv || (len < 4) || (resp[2] != 0)) { dev_warn(&ssif_info->client->dev, "Error getting global enables: %d %d %2.2x\n", @@ -1835,7 +1838,7 @@ static int ssif_probe(struct i2c_client *client) msg[0] = IPMI_NETFN_APP_REQUEST << 2; msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; msg[2] = ssif_info->global_enables | IPMI_BMC_EVT_MSG_BUFF; - rv = do_cmd(client, 3, msg, &len, resp); + rv = do_cmd(client, 3, msg, &len, resp, IPMI_MAX_MSG_LENGTH); if (rv || (len < 2)) { dev_warn(&ssif_info->client->dev, "Error setting global enables: %d %d %2.2x\n", @@ -1857,7 +1860,7 @@ static int ssif_probe(struct i2c_client *client) msg[0] = IPMI_NETFN_APP_REQUEST << 2; msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; msg[2] = ssif_info->global_enables | IPMI_BMC_RCV_MSG_INTR; - rv = do_cmd(client, 3, msg, &len, resp); + rv = do_cmd(client, 3, msg, &len, resp, IPMI_MAX_MSG_LENGTH); if (rv || (len < 2)) { dev_warn(&ssif_info->client->dev, "Error setting global enables: %d %d %2.2x\n", -- 2.56.0.257.gf7497c7d27-goog _______________________________________________ Openipmi-developer mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openipmi-developer
