diff options
Diffstat (limited to 'drivers/char/ipmi')
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 147 |
1 files changed, 91 insertions, 56 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index c47add8e47df..da13df46e984 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -1817,13 +1817,12 @@ static int __find_bmc_prod_dev_id(struct device *dev, void *data) | |||
1817 | struct bmc_device *bmc = dev_get_drvdata(dev); | 1817 | struct bmc_device *bmc = dev_get_drvdata(dev); |
1818 | 1818 | ||
1819 | return (bmc->id.product_id == id->product_id | 1819 | return (bmc->id.product_id == id->product_id |
1820 | && bmc->id.product_id == id->product_id | ||
1821 | && bmc->id.device_id == id->device_id); | 1820 | && bmc->id.device_id == id->device_id); |
1822 | } | 1821 | } |
1823 | 1822 | ||
1824 | static struct bmc_device *ipmi_find_bmc_prod_dev_id( | 1823 | static struct bmc_device *ipmi_find_bmc_prod_dev_id( |
1825 | struct device_driver *drv, | 1824 | struct device_driver *drv, |
1826 | unsigned char product_id, unsigned char device_id) | 1825 | unsigned int product_id, unsigned char device_id) |
1827 | { | 1826 | { |
1828 | struct prod_dev_id id = { | 1827 | struct prod_dev_id id = { |
1829 | .product_id = product_id, | 1828 | .product_id = product_id, |
@@ -1940,6 +1939,9 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr, | |||
1940 | 1939 | ||
1941 | static void remove_files(struct bmc_device *bmc) | 1940 | static void remove_files(struct bmc_device *bmc) |
1942 | { | 1941 | { |
1942 | if (!bmc->dev) | ||
1943 | return; | ||
1944 | |||
1943 | device_remove_file(&bmc->dev->dev, | 1945 | device_remove_file(&bmc->dev->dev, |
1944 | &bmc->device_id_attr); | 1946 | &bmc->device_id_attr); |
1945 | device_remove_file(&bmc->dev->dev, | 1947 | device_remove_file(&bmc->dev->dev, |
@@ -1973,7 +1975,8 @@ cleanup_bmc_device(struct kref *ref) | |||
1973 | bmc = container_of(ref, struct bmc_device, refcount); | 1975 | bmc = container_of(ref, struct bmc_device, refcount); |
1974 | 1976 | ||
1975 | remove_files(bmc); | 1977 | remove_files(bmc); |
1976 | platform_device_unregister(bmc->dev); | 1978 | if (bmc->dev) |
1979 | platform_device_unregister(bmc->dev); | ||
1977 | kfree(bmc); | 1980 | kfree(bmc); |
1978 | } | 1981 | } |
1979 | 1982 | ||
@@ -1990,6 +1993,7 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf) | |||
1990 | 1993 | ||
1991 | mutex_lock(&ipmidriver_mutex); | 1994 | mutex_lock(&ipmidriver_mutex); |
1992 | kref_put(&bmc->refcount, cleanup_bmc_device); | 1995 | kref_put(&bmc->refcount, cleanup_bmc_device); |
1996 | intf->bmc = NULL; | ||
1993 | mutex_unlock(&ipmidriver_mutex); | 1997 | mutex_unlock(&ipmidriver_mutex); |
1994 | } | 1998 | } |
1995 | 1999 | ||
@@ -1997,6 +2001,56 @@ static int create_files(struct bmc_device *bmc) | |||
1997 | { | 2001 | { |
1998 | int err; | 2002 | int err; |
1999 | 2003 | ||
2004 | bmc->device_id_attr.attr.name = "device_id"; | ||
2005 | bmc->device_id_attr.attr.owner = THIS_MODULE; | ||
2006 | bmc->device_id_attr.attr.mode = S_IRUGO; | ||
2007 | bmc->device_id_attr.show = device_id_show; | ||
2008 | |||
2009 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; | ||
2010 | bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; | ||
2011 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; | ||
2012 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; | ||
2013 | |||
2014 | bmc->revision_attr.attr.name = "revision"; | ||
2015 | bmc->revision_attr.attr.owner = THIS_MODULE; | ||
2016 | bmc->revision_attr.attr.mode = S_IRUGO; | ||
2017 | bmc->revision_attr.show = revision_show; | ||
2018 | |||
2019 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; | ||
2020 | bmc->firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2021 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; | ||
2022 | bmc->firmware_rev_attr.show = firmware_rev_show; | ||
2023 | |||
2024 | bmc->version_attr.attr.name = "ipmi_version"; | ||
2025 | bmc->version_attr.attr.owner = THIS_MODULE; | ||
2026 | bmc->version_attr.attr.mode = S_IRUGO; | ||
2027 | bmc->version_attr.show = ipmi_version_show; | ||
2028 | |||
2029 | bmc->add_dev_support_attr.attr.name = "additional_device_support"; | ||
2030 | bmc->add_dev_support_attr.attr.owner = THIS_MODULE; | ||
2031 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; | ||
2032 | bmc->add_dev_support_attr.show = add_dev_support_show; | ||
2033 | |||
2034 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; | ||
2035 | bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; | ||
2036 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; | ||
2037 | bmc->manufacturer_id_attr.show = manufacturer_id_show; | ||
2038 | |||
2039 | bmc->product_id_attr.attr.name = "product_id"; | ||
2040 | bmc->product_id_attr.attr.owner = THIS_MODULE; | ||
2041 | bmc->product_id_attr.attr.mode = S_IRUGO; | ||
2042 | bmc->product_id_attr.show = product_id_show; | ||
2043 | |||
2044 | bmc->guid_attr.attr.name = "guid"; | ||
2045 | bmc->guid_attr.attr.owner = THIS_MODULE; | ||
2046 | bmc->guid_attr.attr.mode = S_IRUGO; | ||
2047 | bmc->guid_attr.show = guid_show; | ||
2048 | |||
2049 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; | ||
2050 | bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2051 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; | ||
2052 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; | ||
2053 | |||
2000 | err = device_create_file(&bmc->dev->dev, | 2054 | err = device_create_file(&bmc->dev->dev, |
2001 | &bmc->device_id_attr); | 2055 | &bmc->device_id_attr); |
2002 | if (err) goto out; | 2056 | if (err) goto out; |
@@ -2106,9 +2160,39 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2106 | bmc->id.product_id, | 2160 | bmc->id.product_id, |
2107 | bmc->id.device_id); | 2161 | bmc->id.device_id); |
2108 | } else { | 2162 | } else { |
2109 | bmc->dev = platform_device_alloc("ipmi_bmc", | 2163 | char name[14]; |
2110 | bmc->id.device_id); | 2164 | unsigned char orig_dev_id = bmc->id.device_id; |
2165 | int warn_printed = 0; | ||
2166 | |||
2167 | snprintf(name, sizeof(name), | ||
2168 | "ipmi_bmc.%4.4x", bmc->id.product_id); | ||
2169 | |||
2170 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver, | ||
2171 | bmc->id.product_id, | ||
2172 | bmc->id.device_id)) | ||
2173 | { | ||
2174 | if (!warn_printed) { | ||
2175 | printk(KERN_WARNING PFX | ||
2176 | "This machine has two different BMCs" | ||
2177 | " with the same product id and device" | ||
2178 | " id. This is an error in the" | ||
2179 | " firmware, but incrementing the" | ||
2180 | " device id to work around the problem." | ||
2181 | " Prod ID = 0x%x, Dev ID = 0x%x\n", | ||
2182 | bmc->id.product_id, bmc->id.device_id); | ||
2183 | warn_printed = 1; | ||
2184 | } | ||
2185 | bmc->id.device_id++; /* Wraps at 255 */ | ||
2186 | if (bmc->id.device_id == orig_dev_id) { | ||
2187 | printk(KERN_ERR PFX | ||
2188 | "Out of device ids!\n"); | ||
2189 | break; | ||
2190 | } | ||
2191 | } | ||
2192 | |||
2193 | bmc->dev = platform_device_alloc(name, bmc->id.device_id); | ||
2111 | if (!bmc->dev) { | 2194 | if (!bmc->dev) { |
2195 | mutex_unlock(&ipmidriver_mutex); | ||
2112 | printk(KERN_ERR | 2196 | printk(KERN_ERR |
2113 | "ipmi_msghandler:" | 2197 | "ipmi_msghandler:" |
2114 | " Unable to allocate platform device\n"); | 2198 | " Unable to allocate platform device\n"); |
@@ -2121,6 +2205,8 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2121 | rv = platform_device_add(bmc->dev); | 2205 | rv = platform_device_add(bmc->dev); |
2122 | mutex_unlock(&ipmidriver_mutex); | 2206 | mutex_unlock(&ipmidriver_mutex); |
2123 | if (rv) { | 2207 | if (rv) { |
2208 | platform_device_put(bmc->dev); | ||
2209 | bmc->dev = NULL; | ||
2124 | printk(KERN_ERR | 2210 | printk(KERN_ERR |
2125 | "ipmi_msghandler:" | 2211 | "ipmi_msghandler:" |
2126 | " Unable to register bmc device: %d\n", | 2212 | " Unable to register bmc device: %d\n", |
@@ -2130,57 +2216,6 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2130 | return rv; | 2216 | return rv; |
2131 | } | 2217 | } |
2132 | 2218 | ||
2133 | bmc->device_id_attr.attr.name = "device_id"; | ||
2134 | bmc->device_id_attr.attr.owner = THIS_MODULE; | ||
2135 | bmc->device_id_attr.attr.mode = S_IRUGO; | ||
2136 | bmc->device_id_attr.show = device_id_show; | ||
2137 | |||
2138 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; | ||
2139 | bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; | ||
2140 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; | ||
2141 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; | ||
2142 | |||
2143 | bmc->revision_attr.attr.name = "revision"; | ||
2144 | bmc->revision_attr.attr.owner = THIS_MODULE; | ||
2145 | bmc->revision_attr.attr.mode = S_IRUGO; | ||
2146 | bmc->revision_attr.show = revision_show; | ||
2147 | |||
2148 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; | ||
2149 | bmc->firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2150 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; | ||
2151 | bmc->firmware_rev_attr.show = firmware_rev_show; | ||
2152 | |||
2153 | bmc->version_attr.attr.name = "ipmi_version"; | ||
2154 | bmc->version_attr.attr.owner = THIS_MODULE; | ||
2155 | bmc->version_attr.attr.mode = S_IRUGO; | ||
2156 | bmc->version_attr.show = ipmi_version_show; | ||
2157 | |||
2158 | bmc->add_dev_support_attr.attr.name | ||
2159 | = "additional_device_support"; | ||
2160 | bmc->add_dev_support_attr.attr.owner = THIS_MODULE; | ||
2161 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; | ||
2162 | bmc->add_dev_support_attr.show = add_dev_support_show; | ||
2163 | |||
2164 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; | ||
2165 | bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; | ||
2166 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; | ||
2167 | bmc->manufacturer_id_attr.show = manufacturer_id_show; | ||
2168 | |||
2169 | bmc->product_id_attr.attr.name = "product_id"; | ||
2170 | bmc->product_id_attr.attr.owner = THIS_MODULE; | ||
2171 | bmc->product_id_attr.attr.mode = S_IRUGO; | ||
2172 | bmc->product_id_attr.show = product_id_show; | ||
2173 | |||
2174 | bmc->guid_attr.attr.name = "guid"; | ||
2175 | bmc->guid_attr.attr.owner = THIS_MODULE; | ||
2176 | bmc->guid_attr.attr.mode = S_IRUGO; | ||
2177 | bmc->guid_attr.show = guid_show; | ||
2178 | |||
2179 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; | ||
2180 | bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2181 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; | ||
2182 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; | ||
2183 | |||
2184 | rv = create_files(bmc); | 2219 | rv = create_files(bmc); |
2185 | if (rv) { | 2220 | if (rv) { |
2186 | mutex_lock(&ipmidriver_mutex); | 2221 | mutex_lock(&ipmidriver_mutex); |