hwmon: (ibmaem) Avoid repeated memory allocations

Preallocate a buffer for the response to sensor reads, and reuse it
for each read instead of allocating a new one each time. This should
be faster and should also avoid memory fragmentation.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Acked-by: Darrick J. Wong <djwong@us.ibm.com>
Acked-by: Guenter Roeck <guenter.roeck@ericsson.com>
This commit is contained in:
Jean Delvare 2011-11-04 12:00:46 +01:00 committed by Jean Delvare
parent 9d84c9e8b5
commit da8ebe4e09

View File

@ -147,8 +147,9 @@ struct aem_data {
int id; int id;
struct aem_ipmi_data ipmi; struct aem_ipmi_data ipmi;
/* Function to update sensors */ /* Function and buffer to update sensors */
void (*update)(struct aem_data *data); void (*update)(struct aem_data *data);
struct aem_read_sensor_resp *rs_resp;
/* /*
* AEM 1.x sensors: * AEM 1.x sensors:
@ -355,13 +356,14 @@ static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
/* Sensor support functions */ /* Sensor support functions */
/* Read a sensor value */ /* Read a sensor value; must be called with data->lock held */
static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg, static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
void *buf, size_t size) void *buf, size_t size)
{ {
int rs_size, res; int rs_size, res;
struct aem_read_sensor_req rs_req; struct aem_read_sensor_req rs_req;
struct aem_read_sensor_resp *rs_resp; /* Use preallocated rx buffer */
struct aem_read_sensor_resp *rs_resp = data->rs_resp;
struct aem_ipmi_data *ipmi = &data->ipmi; struct aem_ipmi_data *ipmi = &data->ipmi;
/* AEM registers are 1, 2, 4 or 8 bytes */ /* AEM registers are 1, 2, 4 or 8 bytes */
@ -387,10 +389,6 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
ipmi->tx_message.data_len = sizeof(rs_req); ipmi->tx_message.data_len = sizeof(rs_req);
rs_size = sizeof(*rs_resp) + size; rs_size = sizeof(*rs_resp) + size;
rs_resp = kzalloc(rs_size, GFP_KERNEL);
if (!rs_resp)
return -ENOMEM;
ipmi->rx_msg_data = rs_resp; ipmi->rx_msg_data = rs_resp;
ipmi->rx_msg_len = rs_size; ipmi->rx_msg_len = rs_size;
@ -433,7 +431,6 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
res = 0; res = 0;
out: out:
kfree(rs_resp);
return res; return res;
} }
@ -491,6 +488,7 @@ static void aem_delete(struct aem_data *data)
{ {
list_del(&data->list); list_del(&data->list);
aem_remove_sensors(data); aem_remove_sensors(data);
kfree(data->rs_resp);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
ipmi_destroy_user(data->ipmi.user); ipmi_destroy_user(data->ipmi.user);
platform_set_drvdata(data->pdev, NULL); platform_set_drvdata(data->pdev, NULL);
@ -584,6 +582,11 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
} }
data->update = update_aem1_sensors; data->update = update_aem1_sensors;
data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);
if (!data->rs_resp) {
res = -ENOMEM;
goto alloc_resp_err;
}
/* Find sensors */ /* Find sensors */
res = aem1_find_sensors(data); res = aem1_find_sensors(data);
@ -599,6 +602,8 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
return 0; return 0;
sensor_err: sensor_err:
kfree(data->rs_resp);
alloc_resp_err:
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
hwmon_reg_err: hwmon_reg_err:
ipmi_destroy_user(data->ipmi.user); ipmi_destroy_user(data->ipmi.user);
@ -717,6 +722,11 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
} }
data->update = update_aem2_sensors; data->update = update_aem2_sensors;
data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);
if (!data->rs_resp) {
res = -ENOMEM;
goto alloc_resp_err;
}
/* Find sensors */ /* Find sensors */
res = aem2_find_sensors(data); res = aem2_find_sensors(data);
@ -732,6 +742,8 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
return 0; return 0;
sensor_err: sensor_err:
kfree(data->rs_resp);
alloc_resp_err:
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
hwmon_reg_err: hwmon_reg_err:
ipmi_destroy_user(data->ipmi.user); ipmi_destroy_user(data->ipmi.user);