powerpc/pci/rpadlpar: Fix device reference leaks
[pandora-kernel.git] / drivers / hwmon / ibmaem.c
index 783d0c1..6a967d7 100644 (file)
@@ -147,8 +147,9 @@ struct aem_data {
        int                     id;
        struct aem_ipmi_data    ipmi;
 
-       /* Function to update sensors */
+       /* Function and buffer to update sensors */
        void (*update)(struct aem_data *data);
+       struct aem_read_sensor_resp *rs_resp;
 
        /*
         * AEM 1.x sensors:
@@ -245,8 +246,6 @@ static void aem_bmc_gone(int iface);
 static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
 
 static void aem_remove_sensors(struct aem_data *data);
-static int aem_init_aem1(struct aem_ipmi_data *probe);
-static int aem_init_aem2(struct aem_ipmi_data *probe);
 static int aem1_find_sensors(struct aem_data *data);
 static int aem2_find_sensors(struct aem_data *data);
 static void update_aem1_sensors(struct aem_data *data);
@@ -357,13 +356,14 @@ static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
 
 /* 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,
                           void *buf, size_t size)
 {
        int rs_size, res;
        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;
 
        /* AEM registers are 1, 2, 4 or 8 bytes */
@@ -389,10 +389,6 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
        ipmi->tx_message.data_len = sizeof(rs_req);
 
        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_len = rs_size;
 
@@ -435,7 +431,6 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
        res = 0;
 
 out:
-       kfree(rs_resp);
        return res;
 }
 
@@ -493,6 +488,7 @@ static void aem_delete(struct aem_data *data)
 {
        list_del(&data->list);
        aem_remove_sensors(data);
+       kfree(data->rs_resp);
        hwmon_device_unregister(data->hwmon_dev);
        ipmi_destroy_user(data->ipmi.user);
        platform_set_drvdata(data->pdev, NULL);
@@ -570,24 +566,31 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
        platform_set_drvdata(data->pdev, data);
 
        /* Set up IPMI interface */
-       if (aem_init_ipmi_data(&data->ipmi, probe->interface,
-                              probe->bmc_device))
+       res = aem_init_ipmi_data(&data->ipmi, probe->interface,
+                                probe->bmc_device);
+       if (res)
                goto ipmi_err;
 
        /* Register with hwmon */
        data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
-
        if (IS_ERR(data->hwmon_dev)) {
                dev_err(&data->pdev->dev, "Unable to register hwmon "
                        "device for IPMI interface %d\n",
                        probe->interface);
+               res = PTR_ERR(data->hwmon_dev);
                goto hwmon_reg_err;
        }
 
        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 */
-       if (aem1_find_sensors(data))
+       res = aem1_find_sensors(data);
+       if (res)
                goto sensor_err;
 
        /* Add to our list of AEM devices */
@@ -599,6 +602,8 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
        return 0;
 
 sensor_err:
+       kfree(data->rs_resp);
+alloc_resp_err:
        hwmon_device_unregister(data->hwmon_dev);
 hwmon_reg_err:
        ipmi_destroy_user(data->ipmi.user);
@@ -614,7 +619,7 @@ id_err:
 }
 
 /* Find and initialize all AEM1 instances */
-static int aem_init_aem1(struct aem_ipmi_data *probe)
+static void aem_init_aem1(struct aem_ipmi_data *probe)
 {
        int num, i, err;
 
@@ -625,11 +630,8 @@ static int aem_init_aem1(struct aem_ipmi_data *probe)
                        dev_err(probe->bmc_device,
                                "Error %d initializing AEM1 0x%X\n",
                                err, i);
-                       return err;
                }
        }
-
-       return 0;
 }
 
 /* Probe functions for AEM2 devices */
@@ -704,24 +706,31 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
        platform_set_drvdata(data->pdev, data);
 
        /* Set up IPMI interface */
-       if (aem_init_ipmi_data(&data->ipmi, probe->interface,
-                              probe->bmc_device))
+       res = aem_init_ipmi_data(&data->ipmi, probe->interface,
+                                probe->bmc_device);
+       if (res)
                goto ipmi_err;
 
        /* Register with hwmon */
        data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
-
        if (IS_ERR(data->hwmon_dev)) {
                dev_err(&data->pdev->dev, "Unable to register hwmon "
                        "device for IPMI interface %d\n",
                        probe->interface);
+               res = PTR_ERR(data->hwmon_dev);
                goto hwmon_reg_err;
        }
 
        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 */
-       if (aem2_find_sensors(data))
+       res = aem2_find_sensors(data);
+       if (res)
                goto sensor_err;
 
        /* Add to our list of AEM devices */
@@ -733,6 +742,8 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
        return 0;
 
 sensor_err:
+       kfree(data->rs_resp);
+alloc_resp_err:
        hwmon_device_unregister(data->hwmon_dev);
 hwmon_reg_err:
        ipmi_destroy_user(data->ipmi.user);
@@ -748,7 +759,7 @@ id_err:
 }
 
 /* Find and initialize all AEM2 instances */
-static int aem_init_aem2(struct aem_ipmi_data *probe)
+static void aem_init_aem2(struct aem_ipmi_data *probe)
 {
        struct aem_find_instance_resp fi_resp;
        int err;
@@ -767,12 +778,9 @@ static int aem_init_aem2(struct aem_ipmi_data *probe)
                        dev_err(probe->bmc_device,
                                "Error %d initializing AEM2 0x%X\n",
                                err, fi_resp.module_handle);
-                       return err;
                }
                i++;
        }
-
-       return 0;
 }
 
 /* Probe a BMC for AEM firmware instances */