aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi/ipmi_si_intf.c
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2006-03-26 04:37:21 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-26 11:56:56 -0500
commit50c812b2b9513e3df34eae8c30cb2c221b79b2cb (patch)
tree565f31d3b3234e5324ba9534b752ae426b4a8c92 /drivers/char/ipmi/ipmi_si_intf.c
parentb0defcdbd2b7da7694e2645da92716cea0a3c0ff (diff)
[PATCH] ipmi: add full sysfs support
Add full driver model support for the IPMI driver. It links in the proper bus and device support. It adds an "ipmi" driver interface that has each BMC discovered by the driver (as a device). These BMCs appear in the devices/platform directory. If there are multiple interfaces to the same BMC, the driver should discover this and will only have one BMC entry. The BMC entry will have pointers to each interface device that connects to it. The device information (statistics and config information) has not yet been ported over to the driver model from proc, that will come later. This work was based on work by Yani Ioannou. I basically rewrote it using that code as a guide, but he still deserves credit :). [bunk@stusta.de: make ipmi_find_bmc_guid() static] Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Yani Ioannou <yani.ioannou@gmail.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/ipmi/ipmi_si_intf.c')
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c114
1 files changed, 80 insertions, 34 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index f3b3b23c5330..12f858dc9994 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -112,20 +112,13 @@ enum si_type {
112}; 112};
113static char *si_to_str[] = { "KCS", "SMIC", "BT" }; 113static char *si_to_str[] = { "KCS", "SMIC", "BT" };
114 114
115struct ipmi_device_id { 115#define DEVICE_NAME "ipmi_si"
116 unsigned char device_id; 116
117 unsigned char device_revision; 117static struct device_driver ipmi_driver =
118 unsigned char firmware_revision_1; 118{
119 unsigned char firmware_revision_2; 119 .name = DEVICE_NAME,
120 unsigned char ipmi_version; 120 .bus = &platform_bus_type
121 unsigned char additional_device_support; 121};
122 unsigned char manufacturer_id[3];
123 unsigned char product_id[2];
124 unsigned char aux_firmware_revision[4];
125} __attribute__((packed));
126
127#define ipmi_version_major(v) ((v)->ipmi_version & 0xf)
128#define ipmi_version_minor(v) ((v)->ipmi_version >> 4)
129 122
130struct smi_info 123struct smi_info
131{ 124{
@@ -208,8 +201,17 @@ struct smi_info
208 interrupts. */ 201 interrupts. */
209 int interrupt_disabled; 202 int interrupt_disabled;
210 203
204 /* From the get device id response... */
211 struct ipmi_device_id device_id; 205 struct ipmi_device_id device_id;
212 206
207 /* Driver model stuff. */
208 struct device *dev;
209 struct platform_device *pdev;
210
211 /* True if we allocated the device, false if it came from
212 * someplace else (like PCI). */
213 int dev_registered;
214
213 /* Slave address, could be reported from DMI. */ 215 /* Slave address, could be reported from DMI. */
214 unsigned char slave_addr; 216 unsigned char slave_addr;
215 217
@@ -987,8 +989,6 @@ static LIST_HEAD(smi_infos);
987static DECLARE_MUTEX(smi_infos_lock); 989static DECLARE_MUTEX(smi_infos_lock);
988static int smi_num; /* Used to sequence the SMIs */ 990static int smi_num; /* Used to sequence the SMIs */
989 991
990#define DEVICE_NAME "ipmi_si"
991
992#define DEFAULT_REGSPACING 1 992#define DEFAULT_REGSPACING 1
993 993
994static int si_trydefaults = 1; 994static int si_trydefaults = 1;
@@ -1164,7 +1164,6 @@ static void port_cleanup(struct smi_info *info)
1164 1164
1165 release_region (addr, mapsize); 1165 release_region (addr, mapsize);
1166 } 1166 }
1167 kfree(info);
1168} 1167}
1169 1168
1170static int port_setup(struct smi_info *info) 1169static int port_setup(struct smi_info *info)
@@ -1273,7 +1272,6 @@ static void mem_cleanup(struct smi_info *info)
1273 1272
1274 release_mem_region(addr, mapsize); 1273 release_mem_region(addr, mapsize);
1275 } 1274 }
1276 kfree(info);
1277} 1275}
1278 1276
1279static int mem_setup(struct smi_info *info) 1277static int mem_setup(struct smi_info *info)
@@ -1858,6 +1856,8 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
1858 if (info->irq) 1856 if (info->irq)
1859 info->irq_setup = std_irq_setup; 1857 info->irq_setup = std_irq_setup;
1860 1858
1859 info->dev = &pdev->dev;
1860
1861 return try_smi_init(info); 1861 return try_smi_init(info);
1862} 1862}
1863 1863
@@ -1898,11 +1898,11 @@ static struct pci_driver ipmi_pci_driver = {
1898 1898
1899static int try_get_dev_id(struct smi_info *smi_info) 1899static int try_get_dev_id(struct smi_info *smi_info)
1900{ 1900{
1901 unsigned char msg[2]; 1901 unsigned char msg[2];
1902 unsigned char *resp; 1902 unsigned char *resp;
1903 unsigned long resp_len; 1903 unsigned long resp_len;
1904 enum si_sm_result smi_result; 1904 enum si_sm_result smi_result;
1905 int rv = 0; 1905 int rv = 0;
1906 1906
1907 resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); 1907 resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
1908 if (!resp) 1908 if (!resp)
@@ -1941,7 +1941,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
1941 /* Otherwise, we got some data. */ 1941 /* Otherwise, we got some data. */
1942 resp_len = smi_info->handlers->get_result(smi_info->si_sm, 1942 resp_len = smi_info->handlers->get_result(smi_info->si_sm,
1943 resp, IPMI_MAX_MSG_LENGTH); 1943 resp, IPMI_MAX_MSG_LENGTH);
1944 if (resp_len < 6) { 1944 if (resp_len < 14) {
1945 /* That's odd, it should be longer. */ 1945 /* That's odd, it should be longer. */
1946 rv = -EINVAL; 1946 rv = -EINVAL;
1947 goto out; 1947 goto out;
@@ -1954,8 +1954,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
1954 } 1954 }
1955 1955
1956 /* Record info from the get device id, in case we need it. */ 1956 /* Record info from the get device id, in case we need it. */
1957 memcpy(&smi_info->device_id, &resp[3], 1957 ipmi_demangle_device_id(resp+3, resp_len-3, &smi_info->device_id);
1958 min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id)));
1959 1958
1960 out: 1959 out:
1961 kfree(resp); 1960 kfree(resp);
@@ -2058,15 +2057,14 @@ static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info)
2058#define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20 2057#define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20
2059#define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80 2058#define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80
2060#define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51 2059#define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51
2061#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} 2060#define DELL_IANA_MFR_ID 0x0002a2
2062static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) 2061static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info)
2063{ 2062{
2064 struct ipmi_device_id *id = &smi_info->device_id; 2063 struct ipmi_device_id *id = &smi_info->device_id;
2065 const char mfr[3]=DELL_IANA_MFR_ID; 2064 if (id->manufacturer_id == DELL_IANA_MFR_ID) {
2066 if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr))) {
2067 if (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID && 2065 if (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID &&
2068 id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV && 2066 id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV &&
2069 id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) { 2067 id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) {
2070 smi_info->oem_data_avail_handler = 2068 smi_info->oem_data_avail_handler =
2071 oem_data_avail_to_receive_msg_avail; 2069 oem_data_avail_to_receive_msg_avail;
2072 } 2070 }
@@ -2138,8 +2136,7 @@ static void
2138setup_dell_poweredge_bt_xaction_handler(struct smi_info *smi_info) 2136setup_dell_poweredge_bt_xaction_handler(struct smi_info *smi_info)
2139{ 2137{
2140 struct ipmi_device_id *id = &smi_info->device_id; 2138 struct ipmi_device_id *id = &smi_info->device_id;
2141 const char mfr[3]=DELL_IANA_MFR_ID; 2139 if (id->manufacturer_id == DELL_IANA_MFR_ID &&
2142 if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr)) &&
2143 smi_info->si_type == SI_BT) 2140 smi_info->si_type == SI_BT)
2144 register_xaction_notifier(&dell_poweredge_bt_xaction_notifier); 2141 register_xaction_notifier(&dell_poweredge_bt_xaction_notifier);
2145} 2142}
@@ -2358,10 +2355,36 @@ static int try_smi_init(struct smi_info *new_smi)
2358 new_smi->thread = kthread_run(ipmi_thread, new_smi, 2355 new_smi->thread = kthread_run(ipmi_thread, new_smi,
2359 "kipmi%d", new_smi->intf_num); 2356 "kipmi%d", new_smi->intf_num);
2360 2357
2358 if (!new_smi->dev) {
2359 /* If we don't already have a device from something
2360 * else (like PCI), then register a new one. */
2361 new_smi->pdev = platform_device_alloc("ipmi_si",
2362 new_smi->intf_num);
2363 if (rv) {
2364 printk(KERN_ERR
2365 "ipmi_si_intf:"
2366 " Unable to allocate platform device\n");
2367 goto out_err_stop_timer;
2368 }
2369 new_smi->dev = &new_smi->pdev->dev;
2370 new_smi->dev->driver = &ipmi_driver;
2371
2372 rv = platform_device_register(new_smi->pdev);
2373 if (rv) {
2374 printk(KERN_ERR
2375 "ipmi_si_intf:"
2376 " Unable to register system interface device:"
2377 " %d\n",
2378 rv);
2379 goto out_err_stop_timer;
2380 }
2381 new_smi->dev_registered = 1;
2382 }
2383
2361 rv = ipmi_register_smi(&handlers, 2384 rv = ipmi_register_smi(&handlers,
2362 new_smi, 2385 new_smi,
2363 ipmi_version_major(&new_smi->device_id), 2386 &new_smi->device_id,
2364 ipmi_version_minor(&new_smi->device_id), 2387 new_smi->dev,
2365 new_smi->slave_addr, 2388 new_smi->slave_addr,
2366 &(new_smi->intf)); 2389 &(new_smi->intf));
2367 if (rv) { 2390 if (rv) {
@@ -2425,6 +2448,11 @@ static int try_smi_init(struct smi_info *new_smi)
2425 if (new_smi->io_cleanup) 2448 if (new_smi->io_cleanup)
2426 new_smi->io_cleanup(new_smi); 2449 new_smi->io_cleanup(new_smi);
2427 2450
2451 if (new_smi->dev_registered)
2452 platform_device_unregister(new_smi->pdev);
2453
2454 kfree(new_smi);
2455
2428 up(&smi_infos_lock); 2456 up(&smi_infos_lock);
2429 2457
2430 return rv; 2458 return rv;
@@ -2434,11 +2462,22 @@ static __devinit int init_ipmi_si(void)
2434{ 2462{
2435 int i; 2463 int i;
2436 char *str; 2464 char *str;
2465 int rv;
2437 2466
2438 if (initialized) 2467 if (initialized)
2439 return 0; 2468 return 0;
2440 initialized = 1; 2469 initialized = 1;
2441 2470
2471 /* Register the device drivers. */
2472 rv = driver_register(&ipmi_driver);
2473 if (rv) {
2474 printk(KERN_ERR
2475 "init_ipmi_si: Unable to register driver: %d\n",
2476 rv);
2477 return rv;
2478 }
2479
2480
2442 /* Parse out the si_type string into its components. */ 2481 /* Parse out the si_type string into its components. */
2443 str = si_type_str; 2482 str = si_type_str;
2444 if (*str != '\0') { 2483 if (*str != '\0') {
@@ -2549,6 +2588,11 @@ static void __devexit cleanup_one_si(struct smi_info *to_clean)
2549 to_clean->addr_source_cleanup(to_clean); 2588 to_clean->addr_source_cleanup(to_clean);
2550 if (to_clean->io_cleanup) 2589 if (to_clean->io_cleanup)
2551 to_clean->io_cleanup(to_clean); 2590 to_clean->io_cleanup(to_clean);
2591
2592 if (to_clean->dev_registered)
2593 platform_device_unregister(to_clean->pdev);
2594
2595 kfree(to_clean);
2552} 2596}
2553 2597
2554static __exit void cleanup_ipmi_si(void) 2598static __exit void cleanup_ipmi_si(void)
@@ -2566,6 +2610,8 @@ static __exit void cleanup_ipmi_si(void)
2566 list_for_each_entry_safe(e, tmp_e, &smi_infos, link) 2610 list_for_each_entry_safe(e, tmp_e, &smi_infos, link)
2567 cleanup_one_si(e); 2611 cleanup_one_si(e);
2568 up(&smi_infos_lock); 2612 up(&smi_infos_lock);
2613
2614 driver_unregister(&ipmi_driver);
2569} 2615}
2570module_exit(cleanup_ipmi_si); 2616module_exit(cleanup_ipmi_si);
2571 2617