diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_msghandler.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 552 |
1 files changed, 538 insertions, 14 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index abd4c5118a1b..f553b7a86841 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -162,6 +162,28 @@ struct ipmi_proc_entry | |||
162 | }; | 162 | }; |
163 | #endif | 163 | #endif |
164 | 164 | ||
165 | struct bmc_device | ||
166 | { | ||
167 | struct platform_device *dev; | ||
168 | struct ipmi_device_id id; | ||
169 | unsigned char guid[16]; | ||
170 | int guid_set; | ||
171 | |||
172 | struct kref refcount; | ||
173 | |||
174 | /* bmc device attributes */ | ||
175 | struct device_attribute device_id_attr; | ||
176 | struct device_attribute provides_dev_sdrs_attr; | ||
177 | struct device_attribute revision_attr; | ||
178 | struct device_attribute firmware_rev_attr; | ||
179 | struct device_attribute version_attr; | ||
180 | struct device_attribute add_dev_support_attr; | ||
181 | struct device_attribute manufacturer_id_attr; | ||
182 | struct device_attribute product_id_attr; | ||
183 | struct device_attribute guid_attr; | ||
184 | struct device_attribute aux_firmware_rev_attr; | ||
185 | }; | ||
186 | |||
165 | #define IPMI_IPMB_NUM_SEQ 64 | 187 | #define IPMI_IPMB_NUM_SEQ 64 |
166 | #define IPMI_MAX_CHANNELS 16 | 188 | #define IPMI_MAX_CHANNELS 16 |
167 | struct ipmi_smi | 189 | struct ipmi_smi |
@@ -178,9 +200,8 @@ struct ipmi_smi | |||
178 | /* Used for wake ups at startup. */ | 200 | /* Used for wake ups at startup. */ |
179 | wait_queue_head_t waitq; | 201 | wait_queue_head_t waitq; |
180 | 202 | ||
181 | /* The IPMI version of the BMC on the other end. */ | 203 | struct bmc_device *bmc; |
182 | unsigned char version_major; | 204 | char *my_dev_name; |
183 | unsigned char version_minor; | ||
184 | 205 | ||
185 | /* This is the lower-layer's sender routine. */ | 206 | /* This is the lower-layer's sender routine. */ |
186 | struct ipmi_smi_handlers *handlers; | 207 | struct ipmi_smi_handlers *handlers; |
@@ -194,6 +215,9 @@ struct ipmi_smi | |||
194 | struct ipmi_proc_entry *proc_entries; | 215 | struct ipmi_proc_entry *proc_entries; |
195 | #endif | 216 | #endif |
196 | 217 | ||
218 | /* Driver-model device for the system interface. */ | ||
219 | struct device *si_dev; | ||
220 | |||
197 | /* A table of sequence numbers for this interface. We use the | 221 | /* A table of sequence numbers for this interface. We use the |
198 | sequence numbers for IPMB messages that go out of the | 222 | sequence numbers for IPMB messages that go out of the |
199 | interface to match them up with their responses. A routine | 223 | interface to match them up with their responses. A routine |
@@ -312,6 +336,7 @@ struct ipmi_smi | |||
312 | /* Events that were received with the proper format. */ | 336 | /* Events that were received with the proper format. */ |
313 | unsigned int events; | 337 | unsigned int events; |
314 | }; | 338 | }; |
339 | #define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev) | ||
315 | 340 | ||
316 | /* Used to mark an interface entry that cannot be used but is not a | 341 | /* Used to mark an interface entry that cannot be used but is not a |
317 | * free entry, either, primarily used at creation and deletion time so | 342 | * free entry, either, primarily used at creation and deletion time so |
@@ -320,6 +345,15 @@ struct ipmi_smi | |||
320 | #define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \ | 345 | #define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \ |
321 | || (i == IPMI_INVALID_INTERFACE_ENTRY)) | 346 | || (i == IPMI_INVALID_INTERFACE_ENTRY)) |
322 | 347 | ||
348 | /** | ||
349 | * The driver model view of the IPMI messaging driver. | ||
350 | */ | ||
351 | static struct device_driver ipmidriver = { | ||
352 | .name = "ipmi", | ||
353 | .bus = &platform_bus_type | ||
354 | }; | ||
355 | static DEFINE_MUTEX(ipmidriver_mutex); | ||
356 | |||
323 | #define MAX_IPMI_INTERFACES 4 | 357 | #define MAX_IPMI_INTERFACES 4 |
324 | static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; | 358 | static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; |
325 | 359 | ||
@@ -393,7 +427,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) | |||
393 | if (IPMI_INVALID_INTERFACE(intf)) | 427 | if (IPMI_INVALID_INTERFACE(intf)) |
394 | continue; | 428 | continue; |
395 | spin_unlock_irqrestore(&interfaces_lock, flags); | 429 | spin_unlock_irqrestore(&interfaces_lock, flags); |
396 | watcher->new_smi(i); | 430 | watcher->new_smi(i, intf->si_dev); |
397 | spin_lock_irqsave(&interfaces_lock, flags); | 431 | spin_lock_irqsave(&interfaces_lock, flags); |
398 | } | 432 | } |
399 | spin_unlock_irqrestore(&interfaces_lock, flags); | 433 | spin_unlock_irqrestore(&interfaces_lock, flags); |
@@ -409,14 +443,14 @@ int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher) | |||
409 | } | 443 | } |
410 | 444 | ||
411 | static void | 445 | static void |
412 | call_smi_watchers(int i) | 446 | call_smi_watchers(int i, struct device *dev) |
413 | { | 447 | { |
414 | struct ipmi_smi_watcher *w; | 448 | struct ipmi_smi_watcher *w; |
415 | 449 | ||
416 | down_read(&smi_watchers_sem); | 450 | down_read(&smi_watchers_sem); |
417 | list_for_each_entry(w, &smi_watchers, link) { | 451 | list_for_each_entry(w, &smi_watchers, link) { |
418 | if (try_module_get(w->owner)) { | 452 | if (try_module_get(w->owner)) { |
419 | w->new_smi(i); | 453 | w->new_smi(i, dev); |
420 | module_put(w->owner); | 454 | module_put(w->owner); |
421 | } | 455 | } |
422 | } | 456 | } |
@@ -844,8 +878,8 @@ void ipmi_get_version(ipmi_user_t user, | |||
844 | unsigned char *major, | 878 | unsigned char *major, |
845 | unsigned char *minor) | 879 | unsigned char *minor) |
846 | { | 880 | { |
847 | *major = user->intf->version_major; | 881 | *major = ipmi_version_major(&user->intf->bmc->id); |
848 | *minor = user->intf->version_minor; | 882 | *minor = ipmi_version_minor(&user->intf->bmc->id); |
849 | } | 883 | } |
850 | 884 | ||
851 | int ipmi_set_my_address(ipmi_user_t user, | 885 | int ipmi_set_my_address(ipmi_user_t user, |
@@ -1553,7 +1587,8 @@ static int version_file_read_proc(char *page, char **start, off_t off, | |||
1553 | ipmi_smi_t intf = data; | 1587 | ipmi_smi_t intf = data; |
1554 | 1588 | ||
1555 | return sprintf(out, "%d.%d\n", | 1589 | return sprintf(out, "%d.%d\n", |
1556 | intf->version_major, intf->version_minor); | 1590 | ipmi_version_major(&intf->bmc->id), |
1591 | ipmi_version_minor(&intf->bmc->id)); | ||
1557 | } | 1592 | } |
1558 | 1593 | ||
1559 | static int stat_file_read_proc(char *page, char **start, off_t off, | 1594 | static int stat_file_read_proc(char *page, char **start, off_t off, |
@@ -1712,6 +1747,470 @@ static void remove_proc_entries(ipmi_smi_t smi) | |||
1712 | #endif /* CONFIG_PROC_FS */ | 1747 | #endif /* CONFIG_PROC_FS */ |
1713 | } | 1748 | } |
1714 | 1749 | ||
1750 | static int __find_bmc_guid(struct device *dev, void *data) | ||
1751 | { | ||
1752 | unsigned char *id = data; | ||
1753 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1754 | return memcmp(bmc->guid, id, 16) == 0; | ||
1755 | } | ||
1756 | |||
1757 | static struct bmc_device *ipmi_find_bmc_guid(struct device_driver *drv, | ||
1758 | unsigned char *guid) | ||
1759 | { | ||
1760 | struct device *dev; | ||
1761 | |||
1762 | dev = driver_find_device(drv, NULL, guid, __find_bmc_guid); | ||
1763 | if (dev) | ||
1764 | return dev_get_drvdata(dev); | ||
1765 | else | ||
1766 | return NULL; | ||
1767 | } | ||
1768 | |||
1769 | struct prod_dev_id { | ||
1770 | unsigned int product_id; | ||
1771 | unsigned char device_id; | ||
1772 | }; | ||
1773 | |||
1774 | static int __find_bmc_prod_dev_id(struct device *dev, void *data) | ||
1775 | { | ||
1776 | struct prod_dev_id *id = data; | ||
1777 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1778 | |||
1779 | return (bmc->id.product_id == id->product_id | ||
1780 | && bmc->id.product_id == id->product_id | ||
1781 | && bmc->id.device_id == id->device_id); | ||
1782 | } | ||
1783 | |||
1784 | static struct bmc_device *ipmi_find_bmc_prod_dev_id( | ||
1785 | struct device_driver *drv, | ||
1786 | unsigned char product_id, unsigned char device_id) | ||
1787 | { | ||
1788 | struct prod_dev_id id = { | ||
1789 | .product_id = product_id, | ||
1790 | .device_id = device_id, | ||
1791 | }; | ||
1792 | struct device *dev; | ||
1793 | |||
1794 | dev = driver_find_device(drv, NULL, &id, __find_bmc_prod_dev_id); | ||
1795 | if (dev) | ||
1796 | return dev_get_drvdata(dev); | ||
1797 | else | ||
1798 | return NULL; | ||
1799 | } | ||
1800 | |||
1801 | static ssize_t device_id_show(struct device *dev, | ||
1802 | struct device_attribute *attr, | ||
1803 | char *buf) | ||
1804 | { | ||
1805 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1806 | |||
1807 | return snprintf(buf, 10, "%u\n", bmc->id.device_id); | ||
1808 | } | ||
1809 | |||
1810 | static ssize_t provides_dev_sdrs_show(struct device *dev, | ||
1811 | struct device_attribute *attr, | ||
1812 | char *buf) | ||
1813 | { | ||
1814 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1815 | |||
1816 | return snprintf(buf, 10, "%u\n", | ||
1817 | bmc->id.device_revision && 0x80 >> 7); | ||
1818 | } | ||
1819 | |||
1820 | static ssize_t revision_show(struct device *dev, struct device_attribute *attr, | ||
1821 | char *buf) | ||
1822 | { | ||
1823 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1824 | |||
1825 | return snprintf(buf, 20, "%u\n", | ||
1826 | bmc->id.device_revision && 0x0F); | ||
1827 | } | ||
1828 | |||
1829 | static ssize_t firmware_rev_show(struct device *dev, | ||
1830 | struct device_attribute *attr, | ||
1831 | char *buf) | ||
1832 | { | ||
1833 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1834 | |||
1835 | return snprintf(buf, 20, "%u.%x\n", bmc->id.firmware_revision_1, | ||
1836 | bmc->id.firmware_revision_2); | ||
1837 | } | ||
1838 | |||
1839 | static ssize_t ipmi_version_show(struct device *dev, | ||
1840 | struct device_attribute *attr, | ||
1841 | char *buf) | ||
1842 | { | ||
1843 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1844 | |||
1845 | return snprintf(buf, 20, "%u.%u\n", | ||
1846 | ipmi_version_major(&bmc->id), | ||
1847 | ipmi_version_minor(&bmc->id)); | ||
1848 | } | ||
1849 | |||
1850 | static ssize_t add_dev_support_show(struct device *dev, | ||
1851 | struct device_attribute *attr, | ||
1852 | char *buf) | ||
1853 | { | ||
1854 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1855 | |||
1856 | return snprintf(buf, 10, "0x%02x\n", | ||
1857 | bmc->id.additional_device_support); | ||
1858 | } | ||
1859 | |||
1860 | static ssize_t manufacturer_id_show(struct device *dev, | ||
1861 | struct device_attribute *attr, | ||
1862 | char *buf) | ||
1863 | { | ||
1864 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1865 | |||
1866 | return snprintf(buf, 20, "0x%6.6x\n", bmc->id.manufacturer_id); | ||
1867 | } | ||
1868 | |||
1869 | static ssize_t product_id_show(struct device *dev, | ||
1870 | struct device_attribute *attr, | ||
1871 | char *buf) | ||
1872 | { | ||
1873 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1874 | |||
1875 | return snprintf(buf, 10, "0x%4.4x\n", bmc->id.product_id); | ||
1876 | } | ||
1877 | |||
1878 | static ssize_t aux_firmware_rev_show(struct device *dev, | ||
1879 | struct device_attribute *attr, | ||
1880 | char *buf) | ||
1881 | { | ||
1882 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1883 | |||
1884 | return snprintf(buf, 21, "0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
1885 | bmc->id.aux_firmware_revision[3], | ||
1886 | bmc->id.aux_firmware_revision[2], | ||
1887 | bmc->id.aux_firmware_revision[1], | ||
1888 | bmc->id.aux_firmware_revision[0]); | ||
1889 | } | ||
1890 | |||
1891 | static ssize_t guid_show(struct device *dev, struct device_attribute *attr, | ||
1892 | char *buf) | ||
1893 | { | ||
1894 | struct bmc_device *bmc = dev_get_drvdata(dev); | ||
1895 | |||
1896 | return snprintf(buf, 100, "%Lx%Lx\n", | ||
1897 | (long long) bmc->guid[0], | ||
1898 | (long long) bmc->guid[8]); | ||
1899 | } | ||
1900 | |||
1901 | static void | ||
1902 | cleanup_bmc_device(struct kref *ref) | ||
1903 | { | ||
1904 | struct bmc_device *bmc; | ||
1905 | |||
1906 | bmc = container_of(ref, struct bmc_device, refcount); | ||
1907 | |||
1908 | device_remove_file(&bmc->dev->dev, | ||
1909 | &bmc->device_id_attr); | ||
1910 | device_remove_file(&bmc->dev->dev, | ||
1911 | &bmc->provides_dev_sdrs_attr); | ||
1912 | device_remove_file(&bmc->dev->dev, | ||
1913 | &bmc->revision_attr); | ||
1914 | device_remove_file(&bmc->dev->dev, | ||
1915 | &bmc->firmware_rev_attr); | ||
1916 | device_remove_file(&bmc->dev->dev, | ||
1917 | &bmc->version_attr); | ||
1918 | device_remove_file(&bmc->dev->dev, | ||
1919 | &bmc->add_dev_support_attr); | ||
1920 | device_remove_file(&bmc->dev->dev, | ||
1921 | &bmc->manufacturer_id_attr); | ||
1922 | device_remove_file(&bmc->dev->dev, | ||
1923 | &bmc->product_id_attr); | ||
1924 | if (bmc->id.aux_firmware_revision_set) | ||
1925 | device_remove_file(&bmc->dev->dev, | ||
1926 | &bmc->aux_firmware_rev_attr); | ||
1927 | if (bmc->guid_set) | ||
1928 | device_remove_file(&bmc->dev->dev, | ||
1929 | &bmc->guid_attr); | ||
1930 | platform_device_unregister(bmc->dev); | ||
1931 | kfree(bmc); | ||
1932 | } | ||
1933 | |||
1934 | static void ipmi_bmc_unregister(ipmi_smi_t intf) | ||
1935 | { | ||
1936 | struct bmc_device *bmc = intf->bmc; | ||
1937 | |||
1938 | sysfs_remove_link(&intf->si_dev->kobj, "bmc"); | ||
1939 | if (intf->my_dev_name) { | ||
1940 | sysfs_remove_link(&bmc->dev->dev.kobj, intf->my_dev_name); | ||
1941 | kfree(intf->my_dev_name); | ||
1942 | intf->my_dev_name = NULL; | ||
1943 | } | ||
1944 | |||
1945 | mutex_lock(&ipmidriver_mutex); | ||
1946 | kref_put(&bmc->refcount, cleanup_bmc_device); | ||
1947 | mutex_unlock(&ipmidriver_mutex); | ||
1948 | } | ||
1949 | |||
1950 | static int ipmi_bmc_register(ipmi_smi_t intf) | ||
1951 | { | ||
1952 | int rv; | ||
1953 | struct bmc_device *bmc = intf->bmc; | ||
1954 | struct bmc_device *old_bmc; | ||
1955 | int size; | ||
1956 | char dummy[1]; | ||
1957 | |||
1958 | mutex_lock(&ipmidriver_mutex); | ||
1959 | |||
1960 | /* | ||
1961 | * Try to find if there is an bmc_device struct | ||
1962 | * representing the interfaced BMC already | ||
1963 | */ | ||
1964 | if (bmc->guid_set) | ||
1965 | old_bmc = ipmi_find_bmc_guid(&ipmidriver, bmc->guid); | ||
1966 | else | ||
1967 | old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver, | ||
1968 | bmc->id.product_id, | ||
1969 | bmc->id.device_id); | ||
1970 | |||
1971 | /* | ||
1972 | * If there is already an bmc_device, free the new one, | ||
1973 | * otherwise register the new BMC device | ||
1974 | */ | ||
1975 | if (old_bmc) { | ||
1976 | kfree(bmc); | ||
1977 | intf->bmc = old_bmc; | ||
1978 | bmc = old_bmc; | ||
1979 | |||
1980 | kref_get(&bmc->refcount); | ||
1981 | mutex_unlock(&ipmidriver_mutex); | ||
1982 | |||
1983 | printk(KERN_INFO | ||
1984 | "ipmi: interfacing existing BMC (man_id: 0x%6.6x," | ||
1985 | " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", | ||
1986 | bmc->id.manufacturer_id, | ||
1987 | bmc->id.product_id, | ||
1988 | bmc->id.device_id); | ||
1989 | } else { | ||
1990 | bmc->dev = platform_device_alloc("ipmi_bmc", | ||
1991 | bmc->id.device_id); | ||
1992 | if (! bmc->dev) { | ||
1993 | printk(KERN_ERR | ||
1994 | "ipmi_msghandler:" | ||
1995 | " Unable to allocate platform device\n"); | ||
1996 | return -ENOMEM; | ||
1997 | } | ||
1998 | bmc->dev->dev.driver = &ipmidriver; | ||
1999 | dev_set_drvdata(&bmc->dev->dev, bmc); | ||
2000 | kref_init(&bmc->refcount); | ||
2001 | |||
2002 | rv = platform_device_register(bmc->dev); | ||
2003 | mutex_unlock(&ipmidriver_mutex); | ||
2004 | if (rv) { | ||
2005 | printk(KERN_ERR | ||
2006 | "ipmi_msghandler:" | ||
2007 | " Unable to register bmc device: %d\n", | ||
2008 | rv); | ||
2009 | /* Don't go to out_err, you can only do that if | ||
2010 | the device is registered already. */ | ||
2011 | return rv; | ||
2012 | } | ||
2013 | |||
2014 | bmc->device_id_attr.attr.name = "device_id"; | ||
2015 | bmc->device_id_attr.attr.owner = THIS_MODULE; | ||
2016 | bmc->device_id_attr.attr.mode = S_IRUGO; | ||
2017 | bmc->device_id_attr.show = device_id_show; | ||
2018 | |||
2019 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; | ||
2020 | bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; | ||
2021 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; | ||
2022 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; | ||
2023 | |||
2024 | |||
2025 | bmc->revision_attr.attr.name = "revision"; | ||
2026 | bmc->revision_attr.attr.owner = THIS_MODULE; | ||
2027 | bmc->revision_attr.attr.mode = S_IRUGO; | ||
2028 | bmc->revision_attr.show = revision_show; | ||
2029 | |||
2030 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; | ||
2031 | bmc->firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2032 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; | ||
2033 | bmc->firmware_rev_attr.show = firmware_rev_show; | ||
2034 | |||
2035 | bmc->version_attr.attr.name = "ipmi_version"; | ||
2036 | bmc->version_attr.attr.owner = THIS_MODULE; | ||
2037 | bmc->version_attr.attr.mode = S_IRUGO; | ||
2038 | bmc->version_attr.show = ipmi_version_show; | ||
2039 | |||
2040 | bmc->add_dev_support_attr.attr.name | ||
2041 | = "additional_device_support"; | ||
2042 | bmc->add_dev_support_attr.attr.owner = THIS_MODULE; | ||
2043 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; | ||
2044 | bmc->add_dev_support_attr.show = add_dev_support_show; | ||
2045 | |||
2046 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; | ||
2047 | bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; | ||
2048 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; | ||
2049 | bmc->manufacturer_id_attr.show = manufacturer_id_show; | ||
2050 | |||
2051 | bmc->product_id_attr.attr.name = "product_id"; | ||
2052 | bmc->product_id_attr.attr.owner = THIS_MODULE; | ||
2053 | bmc->product_id_attr.attr.mode = S_IRUGO; | ||
2054 | bmc->product_id_attr.show = product_id_show; | ||
2055 | |||
2056 | bmc->guid_attr.attr.name = "guid"; | ||
2057 | bmc->guid_attr.attr.owner = THIS_MODULE; | ||
2058 | bmc->guid_attr.attr.mode = S_IRUGO; | ||
2059 | bmc->guid_attr.show = guid_show; | ||
2060 | |||
2061 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; | ||
2062 | bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2063 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; | ||
2064 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; | ||
2065 | |||
2066 | device_create_file(&bmc->dev->dev, | ||
2067 | &bmc->device_id_attr); | ||
2068 | device_create_file(&bmc->dev->dev, | ||
2069 | &bmc->provides_dev_sdrs_attr); | ||
2070 | device_create_file(&bmc->dev->dev, | ||
2071 | &bmc->revision_attr); | ||
2072 | device_create_file(&bmc->dev->dev, | ||
2073 | &bmc->firmware_rev_attr); | ||
2074 | device_create_file(&bmc->dev->dev, | ||
2075 | &bmc->version_attr); | ||
2076 | device_create_file(&bmc->dev->dev, | ||
2077 | &bmc->add_dev_support_attr); | ||
2078 | device_create_file(&bmc->dev->dev, | ||
2079 | &bmc->manufacturer_id_attr); | ||
2080 | device_create_file(&bmc->dev->dev, | ||
2081 | &bmc->product_id_attr); | ||
2082 | if (bmc->id.aux_firmware_revision_set) | ||
2083 | device_create_file(&bmc->dev->dev, | ||
2084 | &bmc->aux_firmware_rev_attr); | ||
2085 | if (bmc->guid_set) | ||
2086 | device_create_file(&bmc->dev->dev, | ||
2087 | &bmc->guid_attr); | ||
2088 | |||
2089 | printk(KERN_INFO | ||
2090 | "ipmi: Found new BMC (man_id: 0x%6.6x, " | ||
2091 | " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", | ||
2092 | bmc->id.manufacturer_id, | ||
2093 | bmc->id.product_id, | ||
2094 | bmc->id.device_id); | ||
2095 | } | ||
2096 | |||
2097 | /* | ||
2098 | * create symlink from system interface device to bmc device | ||
2099 | * and back. | ||
2100 | */ | ||
2101 | rv = sysfs_create_link(&intf->si_dev->kobj, | ||
2102 | &bmc->dev->dev.kobj, "bmc"); | ||
2103 | if (rv) { | ||
2104 | printk(KERN_ERR | ||
2105 | "ipmi_msghandler: Unable to create bmc symlink: %d\n", | ||
2106 | rv); | ||
2107 | goto out_err; | ||
2108 | } | ||
2109 | |||
2110 | size = snprintf(dummy, 0, "ipmi%d", intf->intf_num); | ||
2111 | intf->my_dev_name = kmalloc(size+1, GFP_KERNEL); | ||
2112 | if (!intf->my_dev_name) { | ||
2113 | rv = -ENOMEM; | ||
2114 | printk(KERN_ERR | ||
2115 | "ipmi_msghandler: allocate link from BMC: %d\n", | ||
2116 | rv); | ||
2117 | goto out_err; | ||
2118 | } | ||
2119 | snprintf(intf->my_dev_name, size+1, "ipmi%d", intf->intf_num); | ||
2120 | |||
2121 | rv = sysfs_create_link(&bmc->dev->dev.kobj, &intf->si_dev->kobj, | ||
2122 | intf->my_dev_name); | ||
2123 | if (rv) { | ||
2124 | kfree(intf->my_dev_name); | ||
2125 | intf->my_dev_name = NULL; | ||
2126 | printk(KERN_ERR | ||
2127 | "ipmi_msghandler:" | ||
2128 | " Unable to create symlink to bmc: %d\n", | ||
2129 | rv); | ||
2130 | goto out_err; | ||
2131 | } | ||
2132 | |||
2133 | return 0; | ||
2134 | |||
2135 | out_err: | ||
2136 | ipmi_bmc_unregister(intf); | ||
2137 | return rv; | ||
2138 | } | ||
2139 | |||
2140 | static int | ||
2141 | send_guid_cmd(ipmi_smi_t intf, int chan) | ||
2142 | { | ||
2143 | struct kernel_ipmi_msg msg; | ||
2144 | struct ipmi_system_interface_addr si; | ||
2145 | |||
2146 | si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; | ||
2147 | si.channel = IPMI_BMC_CHANNEL; | ||
2148 | si.lun = 0; | ||
2149 | |||
2150 | msg.netfn = IPMI_NETFN_APP_REQUEST; | ||
2151 | msg.cmd = IPMI_GET_DEVICE_GUID_CMD; | ||
2152 | msg.data = NULL; | ||
2153 | msg.data_len = 0; | ||
2154 | return i_ipmi_request(NULL, | ||
2155 | intf, | ||
2156 | (struct ipmi_addr *) &si, | ||
2157 | 0, | ||
2158 | &msg, | ||
2159 | intf, | ||
2160 | NULL, | ||
2161 | NULL, | ||
2162 | 0, | ||
2163 | intf->channels[0].address, | ||
2164 | intf->channels[0].lun, | ||
2165 | -1, 0); | ||
2166 | } | ||
2167 | |||
2168 | static void | ||
2169 | guid_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) | ||
2170 | { | ||
2171 | if ((msg->addr.addr_type != IPMI_SYSTEM_INTERFACE_ADDR_TYPE) | ||
2172 | || (msg->msg.netfn != IPMI_NETFN_APP_RESPONSE) | ||
2173 | || (msg->msg.cmd != IPMI_GET_DEVICE_GUID_CMD)) | ||
2174 | /* Not for me */ | ||
2175 | return; | ||
2176 | |||
2177 | if (msg->msg.data[0] != 0) { | ||
2178 | /* Error from getting the GUID, the BMC doesn't have one. */ | ||
2179 | intf->bmc->guid_set = 0; | ||
2180 | goto out; | ||
2181 | } | ||
2182 | |||
2183 | if (msg->msg.data_len < 17) { | ||
2184 | intf->bmc->guid_set = 0; | ||
2185 | printk(KERN_WARNING PFX | ||
2186 | "guid_handler: The GUID response from the BMC was too" | ||
2187 | " short, it was %d but should have been 17. Assuming" | ||
2188 | " GUID is not available.\n", | ||
2189 | msg->msg.data_len); | ||
2190 | goto out; | ||
2191 | } | ||
2192 | |||
2193 | memcpy(intf->bmc->guid, msg->msg.data, 16); | ||
2194 | intf->bmc->guid_set = 1; | ||
2195 | out: | ||
2196 | wake_up(&intf->waitq); | ||
2197 | } | ||
2198 | |||
2199 | static void | ||
2200 | get_guid(ipmi_smi_t intf) | ||
2201 | { | ||
2202 | int rv; | ||
2203 | |||
2204 | intf->bmc->guid_set = 0x2; | ||
2205 | intf->null_user_handler = guid_handler; | ||
2206 | rv = send_guid_cmd(intf, 0); | ||
2207 | if (rv) | ||
2208 | /* Send failed, no GUID available. */ | ||
2209 | intf->bmc->guid_set = 0; | ||
2210 | wait_event(intf->waitq, intf->bmc->guid_set != 2); | ||
2211 | intf->null_user_handler = NULL; | ||
2212 | } | ||
2213 | |||
1715 | static int | 2214 | static int |
1716 | send_channel_info_cmd(ipmi_smi_t intf, int chan) | 2215 | send_channel_info_cmd(ipmi_smi_t intf, int chan) |
1717 | { | 2216 | { |
@@ -1804,8 +2303,8 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) | |||
1804 | 2303 | ||
1805 | int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | 2304 | int ipmi_register_smi(struct ipmi_smi_handlers *handlers, |
1806 | void *send_info, | 2305 | void *send_info, |
1807 | unsigned char version_major, | 2306 | struct ipmi_device_id *device_id, |
1808 | unsigned char version_minor, | 2307 | struct device *si_dev, |
1809 | unsigned char slave_addr, | 2308 | unsigned char slave_addr, |
1810 | ipmi_smi_t *new_intf) | 2309 | ipmi_smi_t *new_intf) |
1811 | { | 2310 | { |
@@ -1813,7 +2312,11 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1813 | int rv; | 2312 | int rv; |
1814 | ipmi_smi_t intf; | 2313 | ipmi_smi_t intf; |
1815 | unsigned long flags; | 2314 | unsigned long flags; |
2315 | int version_major; | ||
2316 | int version_minor; | ||
1816 | 2317 | ||
2318 | version_major = ipmi_version_major(device_id); | ||
2319 | version_minor = ipmi_version_minor(device_id); | ||
1817 | 2320 | ||
1818 | /* Make sure the driver is actually initialized, this handles | 2321 | /* Make sure the driver is actually initialized, this handles |
1819 | problems with initialization order. */ | 2322 | problems with initialization order. */ |
@@ -1831,10 +2334,15 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1831 | if (!intf) | 2334 | if (!intf) |
1832 | return -ENOMEM; | 2335 | return -ENOMEM; |
1833 | memset(intf, 0, sizeof(*intf)); | 2336 | memset(intf, 0, sizeof(*intf)); |
2337 | intf->bmc = kzalloc(sizeof(*intf->bmc), GFP_KERNEL); | ||
2338 | if (!intf->bmc) { | ||
2339 | kfree(intf); | ||
2340 | return -ENOMEM; | ||
2341 | } | ||
1834 | intf->intf_num = -1; | 2342 | intf->intf_num = -1; |
1835 | kref_init(&intf->refcount); | 2343 | kref_init(&intf->refcount); |
1836 | intf->version_major = version_major; | 2344 | intf->bmc->id = *device_id; |
1837 | intf->version_minor = version_minor; | 2345 | intf->si_dev = si_dev; |
1838 | for (j = 0; j < IPMI_MAX_CHANNELS; j++) { | 2346 | for (j = 0; j < IPMI_MAX_CHANNELS; j++) { |
1839 | intf->channels[j].address = IPMI_BMC_SLAVE_ADDR; | 2347 | intf->channels[j].address = IPMI_BMC_SLAVE_ADDR; |
1840 | intf->channels[j].lun = 2; | 2348 | intf->channels[j].lun = 2; |
@@ -1884,6 +2392,8 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1884 | caller before sending any messages with it. */ | 2392 | caller before sending any messages with it. */ |
1885 | *new_intf = intf; | 2393 | *new_intf = intf; |
1886 | 2394 | ||
2395 | get_guid(intf); | ||
2396 | |||
1887 | if ((version_major > 1) | 2397 | if ((version_major > 1) |
1888 | || ((version_major == 1) && (version_minor >= 5))) | 2398 | || ((version_major == 1) && (version_minor >= 5))) |
1889 | { | 2399 | { |
@@ -1898,6 +2408,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1898 | /* Wait for the channel info to be read. */ | 2408 | /* Wait for the channel info to be read. */ |
1899 | wait_event(intf->waitq, | 2409 | wait_event(intf->waitq, |
1900 | intf->curr_channel >= IPMI_MAX_CHANNELS); | 2410 | intf->curr_channel >= IPMI_MAX_CHANNELS); |
2411 | intf->null_user_handler = NULL; | ||
1901 | } else { | 2412 | } else { |
1902 | /* Assume a single IPMB channel at zero. */ | 2413 | /* Assume a single IPMB channel at zero. */ |
1903 | intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; | 2414 | intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; |
@@ -1907,6 +2418,8 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1907 | if (rv == 0) | 2418 | if (rv == 0) |
1908 | rv = add_proc_entries(intf, i); | 2419 | rv = add_proc_entries(intf, i); |
1909 | 2420 | ||
2421 | rv = ipmi_bmc_register(intf); | ||
2422 | |||
1910 | out: | 2423 | out: |
1911 | if (rv) { | 2424 | if (rv) { |
1912 | if (intf->proc_dir) | 2425 | if (intf->proc_dir) |
@@ -1921,7 +2434,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1921 | spin_lock_irqsave(&interfaces_lock, flags); | 2434 | spin_lock_irqsave(&interfaces_lock, flags); |
1922 | ipmi_interfaces[i] = intf; | 2435 | ipmi_interfaces[i] = intf; |
1923 | spin_unlock_irqrestore(&interfaces_lock, flags); | 2436 | spin_unlock_irqrestore(&interfaces_lock, flags); |
1924 | call_smi_watchers(i); | 2437 | call_smi_watchers(i, intf->si_dev); |
1925 | } | 2438 | } |
1926 | 2439 | ||
1927 | return rv; | 2440 | return rv; |
@@ -1933,6 +2446,8 @@ int ipmi_unregister_smi(ipmi_smi_t intf) | |||
1933 | struct ipmi_smi_watcher *w; | 2446 | struct ipmi_smi_watcher *w; |
1934 | unsigned long flags; | 2447 | unsigned long flags; |
1935 | 2448 | ||
2449 | ipmi_bmc_unregister(intf); | ||
2450 | |||
1936 | spin_lock_irqsave(&interfaces_lock, flags); | 2451 | spin_lock_irqsave(&interfaces_lock, flags); |
1937 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 2452 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
1938 | if (ipmi_interfaces[i] == intf) { | 2453 | if (ipmi_interfaces[i] == intf) { |
@@ -3196,10 +3711,17 @@ static struct notifier_block panic_block = { | |||
3196 | static int ipmi_init_msghandler(void) | 3711 | static int ipmi_init_msghandler(void) |
3197 | { | 3712 | { |
3198 | int i; | 3713 | int i; |
3714 | int rv; | ||
3199 | 3715 | ||
3200 | if (initialized) | 3716 | if (initialized) |
3201 | return 0; | 3717 | return 0; |
3202 | 3718 | ||
3719 | rv = driver_register(&ipmidriver); | ||
3720 | if (rv) { | ||
3721 | printk(KERN_ERR PFX "Could not register IPMI driver\n"); | ||
3722 | return rv; | ||
3723 | } | ||
3724 | |||
3203 | printk(KERN_INFO "ipmi message handler version " | 3725 | printk(KERN_INFO "ipmi message handler version " |
3204 | IPMI_DRIVER_VERSION "\n"); | 3726 | IPMI_DRIVER_VERSION "\n"); |
3205 | 3727 | ||
@@ -3256,6 +3778,8 @@ static __exit void cleanup_ipmi(void) | |||
3256 | remove_proc_entry(proc_ipmi_root->name, &proc_root); | 3778 | remove_proc_entry(proc_ipmi_root->name, &proc_root); |
3257 | #endif /* CONFIG_PROC_FS */ | 3779 | #endif /* CONFIG_PROC_FS */ |
3258 | 3780 | ||
3781 | driver_unregister(&ipmidriver); | ||
3782 | |||
3259 | initialized = 0; | 3783 | initialized = 0; |
3260 | 3784 | ||
3261 | /* Check for buffer leaks. */ | 3785 | /* Check for buffer leaks. */ |