diff options
| -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); |
