diff options
author | Len Brown <len.brown@intel.com> | 2005-09-08 01:45:47 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-09-08 01:45:47 -0400 |
commit | 64e47488c913ac704d465a6af86a26786d1412a5 (patch) | |
tree | d3b0148592963dcde26e4bb35ddfec8b1eaf8e23 /drivers/char/ipmi/ipmi_si_intf.c | |
parent | 4a35a46bf1cda4737c428380d1db5d15e2590d18 (diff) | |
parent | caf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff) |
Merge linux-2.6 with linux-acpi-2.6
Diffstat (limited to 'drivers/char/ipmi/ipmi_si_intf.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 395 |
1 files changed, 206 insertions, 189 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index adbec73b80a6..278f84104996 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -61,11 +61,11 @@ | |||
61 | # endif | 61 | # endif |
62 | static inline void add_usec_to_timer(struct timer_list *t, long v) | 62 | static inline void add_usec_to_timer(struct timer_list *t, long v) |
63 | { | 63 | { |
64 | t->sub_expires += nsec_to_arch_cycle(v * 1000); | 64 | t->arch_cycle_expires += nsec_to_arch_cycle(v * 1000); |
65 | while (t->sub_expires >= arch_cycles_per_jiffy) | 65 | while (t->arch_cycle_expires >= arch_cycles_per_jiffy) |
66 | { | 66 | { |
67 | t->expires++; | 67 | t->expires++; |
68 | t->sub_expires -= arch_cycles_per_jiffy; | 68 | t->arch_cycle_expires -= arch_cycles_per_jiffy; |
69 | } | 69 | } |
70 | } | 70 | } |
71 | #endif | 71 | #endif |
@@ -75,8 +75,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v) | |||
75 | #include <asm/io.h> | 75 | #include <asm/io.h> |
76 | #include "ipmi_si_sm.h" | 76 | #include "ipmi_si_sm.h" |
77 | #include <linux/init.h> | 77 | #include <linux/init.h> |
78 | 78 | #include <linux/dmi.h> | |
79 | #define IPMI_SI_VERSION "v33" | ||
80 | 79 | ||
81 | /* Measure times between events in the driver. */ | 80 | /* Measure times between events in the driver. */ |
82 | #undef DEBUG_TIMING | 81 | #undef DEBUG_TIMING |
@@ -109,6 +108,21 @@ enum si_type { | |||
109 | SI_KCS, SI_SMIC, SI_BT | 108 | SI_KCS, SI_SMIC, SI_BT |
110 | }; | 109 | }; |
111 | 110 | ||
111 | struct ipmi_device_id { | ||
112 | unsigned char device_id; | ||
113 | unsigned char device_revision; | ||
114 | unsigned char firmware_revision_1; | ||
115 | unsigned char firmware_revision_2; | ||
116 | unsigned char ipmi_version; | ||
117 | unsigned char additional_device_support; | ||
118 | unsigned char manufacturer_id[3]; | ||
119 | unsigned char product_id[2]; | ||
120 | unsigned char aux_firmware_revision[4]; | ||
121 | } __attribute__((packed)); | ||
122 | |||
123 | #define ipmi_version_major(v) ((v)->ipmi_version & 0xf) | ||
124 | #define ipmi_version_minor(v) ((v)->ipmi_version >> 4) | ||
125 | |||
112 | struct smi_info | 126 | struct smi_info |
113 | { | 127 | { |
114 | ipmi_smi_t intf; | 128 | ipmi_smi_t intf; |
@@ -131,12 +145,24 @@ struct smi_info | |||
131 | void (*irq_cleanup)(struct smi_info *info); | 145 | void (*irq_cleanup)(struct smi_info *info); |
132 | unsigned int io_size; | 146 | unsigned int io_size; |
133 | 147 | ||
148 | /* Per-OEM handler, called from handle_flags(). | ||
149 | Returns 1 when handle_flags() needs to be re-run | ||
150 | or 0 indicating it set si_state itself. | ||
151 | */ | ||
152 | int (*oem_data_avail_handler)(struct smi_info *smi_info); | ||
153 | |||
134 | /* Flags from the last GET_MSG_FLAGS command, used when an ATTN | 154 | /* Flags from the last GET_MSG_FLAGS command, used when an ATTN |
135 | is set to hold the flags until we are done handling everything | 155 | is set to hold the flags until we are done handling everything |
136 | from the flags. */ | 156 | from the flags. */ |
137 | #define RECEIVE_MSG_AVAIL 0x01 | 157 | #define RECEIVE_MSG_AVAIL 0x01 |
138 | #define EVENT_MSG_BUFFER_FULL 0x02 | 158 | #define EVENT_MSG_BUFFER_FULL 0x02 |
139 | #define WDT_PRE_TIMEOUT_INT 0x08 | 159 | #define WDT_PRE_TIMEOUT_INT 0x08 |
160 | #define OEM0_DATA_AVAIL 0x20 | ||
161 | #define OEM1_DATA_AVAIL 0x40 | ||
162 | #define OEM2_DATA_AVAIL 0x80 | ||
163 | #define OEM_DATA_AVAIL (OEM0_DATA_AVAIL | \ | ||
164 | OEM1_DATA_AVAIL | \ | ||
165 | OEM2_DATA_AVAIL) | ||
140 | unsigned char msg_flags; | 166 | unsigned char msg_flags; |
141 | 167 | ||
142 | /* If set to true, this will request events the next time the | 168 | /* If set to true, this will request events the next time the |
@@ -175,11 +201,7 @@ struct smi_info | |||
175 | interrupts. */ | 201 | interrupts. */ |
176 | int interrupt_disabled; | 202 | int interrupt_disabled; |
177 | 203 | ||
178 | unsigned char ipmi_si_dev_rev; | 204 | struct ipmi_device_id device_id; |
179 | unsigned char ipmi_si_fw_rev_major; | ||
180 | unsigned char ipmi_si_fw_rev_minor; | ||
181 | unsigned char ipmi_version_major; | ||
182 | unsigned char ipmi_version_minor; | ||
183 | 205 | ||
184 | /* Slave address, could be reported from DMI. */ | 206 | /* Slave address, could be reported from DMI. */ |
185 | unsigned char slave_addr; | 207 | unsigned char slave_addr; |
@@ -245,7 +267,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
245 | entry = smi_info->xmit_msgs.next; | 267 | entry = smi_info->xmit_msgs.next; |
246 | } | 268 | } |
247 | 269 | ||
248 | if (!entry) { | 270 | if (! entry) { |
249 | smi_info->curr_msg = NULL; | 271 | smi_info->curr_msg = NULL; |
250 | rv = SI_SM_IDLE; | 272 | rv = SI_SM_IDLE; |
251 | } else { | 273 | } else { |
@@ -306,7 +328,7 @@ static void start_clear_flags(struct smi_info *smi_info) | |||
306 | memory, we will re-enable the interrupt. */ | 328 | memory, we will re-enable the interrupt. */ |
307 | static inline void disable_si_irq(struct smi_info *smi_info) | 329 | static inline void disable_si_irq(struct smi_info *smi_info) |
308 | { | 330 | { |
309 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 331 | if ((smi_info->irq) && (! smi_info->interrupt_disabled)) { |
310 | disable_irq_nosync(smi_info->irq); | 332 | disable_irq_nosync(smi_info->irq); |
311 | smi_info->interrupt_disabled = 1; | 333 | smi_info->interrupt_disabled = 1; |
312 | } | 334 | } |
@@ -322,6 +344,7 @@ static inline void enable_si_irq(struct smi_info *smi_info) | |||
322 | 344 | ||
323 | static void handle_flags(struct smi_info *smi_info) | 345 | static void handle_flags(struct smi_info *smi_info) |
324 | { | 346 | { |
347 | retry: | ||
325 | if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { | 348 | if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { |
326 | /* Watchdog pre-timeout */ | 349 | /* Watchdog pre-timeout */ |
327 | spin_lock(&smi_info->count_lock); | 350 | spin_lock(&smi_info->count_lock); |
@@ -336,7 +359,7 @@ static void handle_flags(struct smi_info *smi_info) | |||
336 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { | 359 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { |
337 | /* Messages available. */ | 360 | /* Messages available. */ |
338 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 361 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
339 | if (!smi_info->curr_msg) { | 362 | if (! smi_info->curr_msg) { |
340 | disable_si_irq(smi_info); | 363 | disable_si_irq(smi_info); |
341 | smi_info->si_state = SI_NORMAL; | 364 | smi_info->si_state = SI_NORMAL; |
342 | return; | 365 | return; |
@@ -355,7 +378,7 @@ static void handle_flags(struct smi_info *smi_info) | |||
355 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { | 378 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { |
356 | /* Events available. */ | 379 | /* Events available. */ |
357 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 380 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
358 | if (!smi_info->curr_msg) { | 381 | if (! smi_info->curr_msg) { |
359 | disable_si_irq(smi_info); | 382 | disable_si_irq(smi_info); |
360 | smi_info->si_state = SI_NORMAL; | 383 | smi_info->si_state = SI_NORMAL; |
361 | return; | 384 | return; |
@@ -371,6 +394,10 @@ static void handle_flags(struct smi_info *smi_info) | |||
371 | smi_info->curr_msg->data, | 394 | smi_info->curr_msg->data, |
372 | smi_info->curr_msg->data_size); | 395 | smi_info->curr_msg->data_size); |
373 | smi_info->si_state = SI_GETTING_EVENTS; | 396 | smi_info->si_state = SI_GETTING_EVENTS; |
397 | } else if (smi_info->msg_flags & OEM_DATA_AVAIL) { | ||
398 | if (smi_info->oem_data_avail_handler) | ||
399 | if (smi_info->oem_data_avail_handler(smi_info)) | ||
400 | goto retry; | ||
374 | } else { | 401 | } else { |
375 | smi_info->si_state = SI_NORMAL; | 402 | smi_info->si_state = SI_NORMAL; |
376 | } | 403 | } |
@@ -387,7 +414,7 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
387 | #endif | 414 | #endif |
388 | switch (smi_info->si_state) { | 415 | switch (smi_info->si_state) { |
389 | case SI_NORMAL: | 416 | case SI_NORMAL: |
390 | if (!smi_info->curr_msg) | 417 | if (! smi_info->curr_msg) |
391 | break; | 418 | break; |
392 | 419 | ||
393 | smi_info->curr_msg->rsp_size | 420 | smi_info->curr_msg->rsp_size |
@@ -761,18 +788,20 @@ static void si_restart_short_timer(struct smi_info *smi_info) | |||
761 | #if defined(CONFIG_HIGH_RES_TIMERS) | 788 | #if defined(CONFIG_HIGH_RES_TIMERS) |
762 | unsigned long flags; | 789 | unsigned long flags; |
763 | unsigned long jiffies_now; | 790 | unsigned long jiffies_now; |
791 | unsigned long seq; | ||
764 | 792 | ||
765 | if (del_timer(&(smi_info->si_timer))) { | 793 | if (del_timer(&(smi_info->si_timer))) { |
766 | /* If we don't delete the timer, then it will go off | 794 | /* If we don't delete the timer, then it will go off |
767 | immediately, anyway. So we only process if we | 795 | immediately, anyway. So we only process if we |
768 | actually delete the timer. */ | 796 | actually delete the timer. */ |
769 | 797 | ||
770 | /* We already have irqsave on, so no need for it | 798 | do { |
771 | here. */ | 799 | seq = read_seqbegin_irqsave(&xtime_lock, flags); |
772 | read_lock(&xtime_lock); | 800 | jiffies_now = jiffies; |
773 | jiffies_now = jiffies; | 801 | smi_info->si_timer.expires = jiffies_now; |
774 | smi_info->si_timer.expires = jiffies_now; | 802 | smi_info->si_timer.arch_cycle_expires |
775 | smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now); | 803 | = get_arch_cycles(jiffies_now); |
804 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
776 | 805 | ||
777 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); | 806 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); |
778 | 807 | ||
@@ -826,15 +855,19 @@ static void smi_timeout(unsigned long data) | |||
826 | /* If the state machine asks for a short delay, then shorten | 855 | /* If the state machine asks for a short delay, then shorten |
827 | the timer timeout. */ | 856 | the timer timeout. */ |
828 | if (smi_result == SI_SM_CALL_WITH_DELAY) { | 857 | if (smi_result == SI_SM_CALL_WITH_DELAY) { |
858 | #if defined(CONFIG_HIGH_RES_TIMERS) | ||
859 | unsigned long seq; | ||
860 | #endif | ||
829 | spin_lock_irqsave(&smi_info->count_lock, flags); | 861 | spin_lock_irqsave(&smi_info->count_lock, flags); |
830 | smi_info->short_timeouts++; | 862 | smi_info->short_timeouts++; |
831 | spin_unlock_irqrestore(&smi_info->count_lock, flags); | 863 | spin_unlock_irqrestore(&smi_info->count_lock, flags); |
832 | #if defined(CONFIG_HIGH_RES_TIMERS) | 864 | #if defined(CONFIG_HIGH_RES_TIMERS) |
833 | read_lock(&xtime_lock); | 865 | do { |
834 | smi_info->si_timer.expires = jiffies; | 866 | seq = read_seqbegin_irqsave(&xtime_lock, flags); |
835 | smi_info->si_timer.sub_expires | 867 | smi_info->si_timer.expires = jiffies; |
836 | = get_arch_cycles(smi_info->si_timer.expires); | 868 | smi_info->si_timer.arch_cycle_expires |
837 | read_unlock(&xtime_lock); | 869 | = get_arch_cycles(smi_info->si_timer.expires); |
870 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
838 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); | 871 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); |
839 | #else | 872 | #else |
840 | smi_info->si_timer.expires = jiffies + 1; | 873 | smi_info->si_timer.expires = jiffies + 1; |
@@ -845,7 +878,7 @@ static void smi_timeout(unsigned long data) | |||
845 | spin_unlock_irqrestore(&smi_info->count_lock, flags); | 878 | spin_unlock_irqrestore(&smi_info->count_lock, flags); |
846 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 879 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; |
847 | #if defined(CONFIG_HIGH_RES_TIMERS) | 880 | #if defined(CONFIG_HIGH_RES_TIMERS) |
848 | smi_info->si_timer.sub_expires = 0; | 881 | smi_info->si_timer.arch_cycle_expires = 0; |
849 | #endif | 882 | #endif |
850 | } | 883 | } |
851 | 884 | ||
@@ -1014,7 +1047,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1014 | { | 1047 | { |
1015 | int rv; | 1048 | int rv; |
1016 | 1049 | ||
1017 | if (!info->irq) | 1050 | if (! info->irq) |
1018 | return 0; | 1051 | return 0; |
1019 | 1052 | ||
1020 | if (info->si_type == SI_BT) { | 1053 | if (info->si_type == SI_BT) { |
@@ -1023,7 +1056,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1023 | SA_INTERRUPT, | 1056 | SA_INTERRUPT, |
1024 | DEVICE_NAME, | 1057 | DEVICE_NAME, |
1025 | info); | 1058 | info); |
1026 | if (!rv) | 1059 | if (! rv) |
1027 | /* Enable the interrupt in the BT interface. */ | 1060 | /* Enable the interrupt in the BT interface. */ |
1028 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, | 1061 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, |
1029 | IPMI_BT_INTMASK_ENABLE_IRQ_BIT); | 1062 | IPMI_BT_INTMASK_ENABLE_IRQ_BIT); |
@@ -1048,7 +1081,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1048 | 1081 | ||
1049 | static void std_irq_cleanup(struct smi_info *info) | 1082 | static void std_irq_cleanup(struct smi_info *info) |
1050 | { | 1083 | { |
1051 | if (!info->irq) | 1084 | if (! info->irq) |
1052 | return; | 1085 | return; |
1053 | 1086 | ||
1054 | if (info->si_type == SI_BT) | 1087 | if (info->si_type == SI_BT) |
@@ -1121,7 +1154,7 @@ static int port_setup(struct smi_info *info) | |||
1121 | unsigned int *addr = info->io.info; | 1154 | unsigned int *addr = info->io.info; |
1122 | int mapsize; | 1155 | int mapsize; |
1123 | 1156 | ||
1124 | if (!addr || (!*addr)) | 1157 | if (! addr || (! *addr)) |
1125 | return -ENODEV; | 1158 | return -ENODEV; |
1126 | 1159 | ||
1127 | info->io_cleanup = port_cleanup; | 1160 | info->io_cleanup = port_cleanup; |
@@ -1164,15 +1197,15 @@ static int try_init_port(int intf_num, struct smi_info **new_info) | |||
1164 | { | 1197 | { |
1165 | struct smi_info *info; | 1198 | struct smi_info *info; |
1166 | 1199 | ||
1167 | if (!ports[intf_num]) | 1200 | if (! ports[intf_num]) |
1168 | return -ENODEV; | 1201 | return -ENODEV; |
1169 | 1202 | ||
1170 | if (!is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, | 1203 | if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, |
1171 | ports[intf_num])) | 1204 | ports[intf_num])) |
1172 | return -ENODEV; | 1205 | return -ENODEV; |
1173 | 1206 | ||
1174 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1207 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1175 | if (!info) { | 1208 | if (! info) { |
1176 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); | 1209 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); |
1177 | return -ENOMEM; | 1210 | return -ENOMEM; |
1178 | } | 1211 | } |
@@ -1182,10 +1215,10 @@ static int try_init_port(int intf_num, struct smi_info **new_info) | |||
1182 | info->io.info = &(ports[intf_num]); | 1215 | info->io.info = &(ports[intf_num]); |
1183 | info->io.addr = NULL; | 1216 | info->io.addr = NULL; |
1184 | info->io.regspacing = regspacings[intf_num]; | 1217 | info->io.regspacing = regspacings[intf_num]; |
1185 | if (!info->io.regspacing) | 1218 | if (! info->io.regspacing) |
1186 | info->io.regspacing = DEFAULT_REGSPACING; | 1219 | info->io.regspacing = DEFAULT_REGSPACING; |
1187 | info->io.regsize = regsizes[intf_num]; | 1220 | info->io.regsize = regsizes[intf_num]; |
1188 | if (!info->io.regsize) | 1221 | if (! info->io.regsize) |
1189 | info->io.regsize = DEFAULT_REGSPACING; | 1222 | info->io.regsize = DEFAULT_REGSPACING; |
1190 | info->io.regshift = regshifts[intf_num]; | 1223 | info->io.regshift = regshifts[intf_num]; |
1191 | info->irq = 0; | 1224 | info->irq = 0; |
@@ -1270,7 +1303,7 @@ static int mem_setup(struct smi_info *info) | |||
1270 | unsigned long *addr = info->io.info; | 1303 | unsigned long *addr = info->io.info; |
1271 | int mapsize; | 1304 | int mapsize; |
1272 | 1305 | ||
1273 | if (!addr || (!*addr)) | 1306 | if (! addr || (! *addr)) |
1274 | return -ENODEV; | 1307 | return -ENODEV; |
1275 | 1308 | ||
1276 | info->io_cleanup = mem_cleanup; | 1309 | info->io_cleanup = mem_cleanup; |
@@ -1325,15 +1358,15 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) | |||
1325 | { | 1358 | { |
1326 | struct smi_info *info; | 1359 | struct smi_info *info; |
1327 | 1360 | ||
1328 | if (!addrs[intf_num]) | 1361 | if (! addrs[intf_num]) |
1329 | return -ENODEV; | 1362 | return -ENODEV; |
1330 | 1363 | ||
1331 | if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, | 1364 | if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, |
1332 | addrs[intf_num])) | 1365 | addrs[intf_num])) |
1333 | return -ENODEV; | 1366 | return -ENODEV; |
1334 | 1367 | ||
1335 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1368 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1336 | if (!info) { | 1369 | if (! info) { |
1337 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); | 1370 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); |
1338 | return -ENOMEM; | 1371 | return -ENOMEM; |
1339 | } | 1372 | } |
@@ -1343,10 +1376,10 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) | |||
1343 | info->io.info = &addrs[intf_num]; | 1376 | info->io.info = &addrs[intf_num]; |
1344 | info->io.addr = NULL; | 1377 | info->io.addr = NULL; |
1345 | info->io.regspacing = regspacings[intf_num]; | 1378 | info->io.regspacing = regspacings[intf_num]; |
1346 | if (!info->io.regspacing) | 1379 | if (! info->io.regspacing) |
1347 | info->io.regspacing = DEFAULT_REGSPACING; | 1380 | info->io.regspacing = DEFAULT_REGSPACING; |
1348 | info->io.regsize = regsizes[intf_num]; | 1381 | info->io.regsize = regsizes[intf_num]; |
1349 | if (!info->io.regsize) | 1382 | if (! info->io.regsize) |
1350 | info->io.regsize = DEFAULT_REGSPACING; | 1383 | info->io.regsize = DEFAULT_REGSPACING; |
1351 | info->io.regshift = regshifts[intf_num]; | 1384 | info->io.regshift = regshifts[intf_num]; |
1352 | info->irq = 0; | 1385 | info->irq = 0; |
@@ -1404,7 +1437,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1404 | { | 1437 | { |
1405 | acpi_status status; | 1438 | acpi_status status; |
1406 | 1439 | ||
1407 | if (!info->irq) | 1440 | if (! info->irq) |
1408 | return 0; | 1441 | return 0; |
1409 | 1442 | ||
1410 | /* FIXME - is level triggered right? */ | 1443 | /* FIXME - is level triggered right? */ |
@@ -1428,7 +1461,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1428 | 1461 | ||
1429 | static void acpi_gpe_irq_cleanup(struct smi_info *info) | 1462 | static void acpi_gpe_irq_cleanup(struct smi_info *info) |
1430 | { | 1463 | { |
1431 | if (!info->irq) | 1464 | if (! info->irq) |
1432 | return; | 1465 | return; |
1433 | 1466 | ||
1434 | acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); | 1467 | acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); |
@@ -1507,10 +1540,10 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) | |||
1507 | addr_space = IPMI_MEM_ADDR_SPACE; | 1540 | addr_space = IPMI_MEM_ADDR_SPACE; |
1508 | else | 1541 | else |
1509 | addr_space = IPMI_IO_ADDR_SPACE; | 1542 | addr_space = IPMI_IO_ADDR_SPACE; |
1510 | if (!is_new_interface(-1, addr_space, spmi->addr.address)) | 1543 | if (! is_new_interface(-1, addr_space, spmi->addr.address)) |
1511 | return -ENODEV; | 1544 | return -ENODEV; |
1512 | 1545 | ||
1513 | if (!spmi->addr.register_bit_width) { | 1546 | if (! spmi->addr.register_bit_width) { |
1514 | acpi_failure = 1; | 1547 | acpi_failure = 1; |
1515 | return -ENODEV; | 1548 | return -ENODEV; |
1516 | } | 1549 | } |
@@ -1537,7 +1570,7 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) | |||
1537 | } | 1570 | } |
1538 | 1571 | ||
1539 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1572 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1540 | if (!info) { | 1573 | if (! info) { |
1541 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); | 1574 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); |
1542 | return -ENOMEM; | 1575 | return -ENOMEM; |
1543 | } | 1576 | } |
@@ -1613,22 +1646,15 @@ typedef struct dmi_ipmi_data | |||
1613 | static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; | 1646 | static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; |
1614 | static int dmi_data_entries; | 1647 | static int dmi_data_entries; |
1615 | 1648 | ||
1616 | typedef struct dmi_header | 1649 | static int __init decode_dmi(struct dmi_header *dm, int intf_num) |
1617 | { | ||
1618 | u8 type; | ||
1619 | u8 length; | ||
1620 | u16 handle; | ||
1621 | } dmi_header_t; | ||
1622 | |||
1623 | static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | ||
1624 | { | 1650 | { |
1625 | u8 __iomem *data = (u8 __iomem *)dm; | 1651 | u8 *data = (u8 *)dm; |
1626 | unsigned long base_addr; | 1652 | unsigned long base_addr; |
1627 | u8 reg_spacing; | 1653 | u8 reg_spacing; |
1628 | u8 len = readb(&dm->length); | 1654 | u8 len = dm->length; |
1629 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; | 1655 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; |
1630 | 1656 | ||
1631 | ipmi_data->type = readb(&data[4]); | 1657 | ipmi_data->type = data[4]; |
1632 | 1658 | ||
1633 | memcpy(&base_addr, data+8, sizeof(unsigned long)); | 1659 | memcpy(&base_addr, data+8, sizeof(unsigned long)); |
1634 | if (len >= 0x11) { | 1660 | if (len >= 0x11) { |
@@ -1643,12 +1669,12 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | |||
1643 | } | 1669 | } |
1644 | /* If bit 4 of byte 0x10 is set, then the lsb for the address | 1670 | /* If bit 4 of byte 0x10 is set, then the lsb for the address |
1645 | is odd. */ | 1671 | is odd. */ |
1646 | ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4); | 1672 | ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); |
1647 | 1673 | ||
1648 | ipmi_data->irq = readb(&data[0x11]); | 1674 | ipmi_data->irq = data[0x11]; |
1649 | 1675 | ||
1650 | /* The top two bits of byte 0x10 hold the register spacing. */ | 1676 | /* The top two bits of byte 0x10 hold the register spacing. */ |
1651 | reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6; | 1677 | reg_spacing = (data[0x10] & 0xC0) >> 6; |
1652 | switch(reg_spacing){ | 1678 | switch(reg_spacing){ |
1653 | case 0x00: /* Byte boundaries */ | 1679 | case 0x00: /* Byte boundaries */ |
1654 | ipmi_data->offset = 1; | 1680 | ipmi_data->offset = 1; |
@@ -1676,7 +1702,7 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | |||
1676 | ipmi_data->offset = 1; | 1702 | ipmi_data->offset = 1; |
1677 | } | 1703 | } |
1678 | 1704 | ||
1679 | ipmi_data->slave_addr = readb(&data[6]); | 1705 | ipmi_data->slave_addr = data[6]; |
1680 | 1706 | ||
1681 | if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { | 1707 | if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { |
1682 | dmi_data_entries++; | 1708 | dmi_data_entries++; |
@@ -1688,94 +1714,29 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | |||
1688 | return -1; | 1714 | return -1; |
1689 | } | 1715 | } |
1690 | 1716 | ||
1691 | static int dmi_table(u32 base, int len, int num) | 1717 | static void __init dmi_find_bmc(void) |
1692 | { | 1718 | { |
1693 | u8 __iomem *buf; | 1719 | struct dmi_device *dev = NULL; |
1694 | struct dmi_header __iomem *dm; | ||
1695 | u8 __iomem *data; | ||
1696 | int i=1; | ||
1697 | int status=-1; | ||
1698 | int intf_num = 0; | 1720 | int intf_num = 0; |
1699 | 1721 | ||
1700 | buf = ioremap(base, len); | 1722 | while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { |
1701 | if(buf==NULL) | 1723 | if (intf_num >= SI_MAX_DRIVERS) |
1702 | return -1; | 1724 | break; |
1703 | |||
1704 | data = buf; | ||
1705 | |||
1706 | while(i<num && (data - buf) < len) | ||
1707 | { | ||
1708 | dm=(dmi_header_t __iomem *)data; | ||
1709 | |||
1710 | if((data-buf+readb(&dm->length)) >= len) | ||
1711 | break; | ||
1712 | |||
1713 | if (readb(&dm->type) == 38) { | ||
1714 | if (decode_dmi(dm, intf_num) == 0) { | ||
1715 | intf_num++; | ||
1716 | if (intf_num >= SI_MAX_DRIVERS) | ||
1717 | break; | ||
1718 | } | ||
1719 | } | ||
1720 | |||
1721 | data+=readb(&dm->length); | ||
1722 | while((data-buf) < len && (readb(data)||readb(data+1))) | ||
1723 | data++; | ||
1724 | data+=2; | ||
1725 | i++; | ||
1726 | } | ||
1727 | iounmap(buf); | ||
1728 | |||
1729 | return status; | ||
1730 | } | ||
1731 | |||
1732 | static inline int dmi_checksum(u8 *buf) | ||
1733 | { | ||
1734 | u8 sum=0; | ||
1735 | int a; | ||
1736 | |||
1737 | for(a=0; a<15; a++) | ||
1738 | sum+=buf[a]; | ||
1739 | return (sum==0); | ||
1740 | } | ||
1741 | |||
1742 | static int dmi_decode(void) | ||
1743 | { | ||
1744 | u8 buf[15]; | ||
1745 | u32 fp=0xF0000; | ||
1746 | |||
1747 | #ifdef CONFIG_SIMNOW | ||
1748 | return -1; | ||
1749 | #endif | ||
1750 | |||
1751 | while(fp < 0xFFFFF) | ||
1752 | { | ||
1753 | isa_memcpy_fromio(buf, fp, 15); | ||
1754 | if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) | ||
1755 | { | ||
1756 | u16 num=buf[13]<<8|buf[12]; | ||
1757 | u16 len=buf[7]<<8|buf[6]; | ||
1758 | u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; | ||
1759 | 1725 | ||
1760 | if(dmi_table(base, len, num) == 0) | 1726 | decode_dmi((struct dmi_header *) dev->device_data, intf_num++); |
1761 | return 0; | ||
1762 | } | ||
1763 | fp+=16; | ||
1764 | } | 1727 | } |
1765 | |||
1766 | return -1; | ||
1767 | } | 1728 | } |
1768 | 1729 | ||
1769 | static int try_init_smbios(int intf_num, struct smi_info **new_info) | 1730 | static int try_init_smbios(int intf_num, struct smi_info **new_info) |
1770 | { | 1731 | { |
1771 | struct smi_info *info; | 1732 | struct smi_info *info; |
1772 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; | 1733 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; |
1773 | char *io_type; | 1734 | char *io_type; |
1774 | 1735 | ||
1775 | if (intf_num >= dmi_data_entries) | 1736 | if (intf_num >= dmi_data_entries) |
1776 | return -ENODEV; | 1737 | return -ENODEV; |
1777 | 1738 | ||
1778 | switch(ipmi_data->type) { | 1739 | switch (ipmi_data->type) { |
1779 | case 0x01: /* KCS */ | 1740 | case 0x01: /* KCS */ |
1780 | si_type[intf_num] = "kcs"; | 1741 | si_type[intf_num] = "kcs"; |
1781 | break; | 1742 | break; |
@@ -1790,7 +1751,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) | |||
1790 | } | 1751 | } |
1791 | 1752 | ||
1792 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1753 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1793 | if (!info) { | 1754 | if (! info) { |
1794 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); | 1755 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); |
1795 | return -ENOMEM; | 1756 | return -ENOMEM; |
1796 | } | 1757 | } |
@@ -1814,7 +1775,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) | |||
1814 | 1775 | ||
1815 | regspacings[intf_num] = ipmi_data->offset; | 1776 | regspacings[intf_num] = ipmi_data->offset; |
1816 | info->io.regspacing = regspacings[intf_num]; | 1777 | info->io.regspacing = regspacings[intf_num]; |
1817 | if (!info->io.regspacing) | 1778 | if (! info->io.regspacing) |
1818 | info->io.regspacing = DEFAULT_REGSPACING; | 1779 | info->io.regspacing = DEFAULT_REGSPACING; |
1819 | info->io.regsize = DEFAULT_REGSPACING; | 1780 | info->io.regsize = DEFAULT_REGSPACING; |
1820 | info->io.regshift = regshifts[intf_num]; | 1781 | info->io.regshift = regshifts[intf_num]; |
@@ -1856,14 +1817,14 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1856 | 1817 | ||
1857 | pci_smic_checked = 1; | 1818 | pci_smic_checked = 1; |
1858 | 1819 | ||
1859 | if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, | 1820 | pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL); |
1860 | NULL))) | 1821 | if (! pci_dev) { |
1861 | ; | 1822 | pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL); |
1862 | else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) && | 1823 | if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)) |
1863 | pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID) | 1824 | fe_rmc = 1; |
1864 | fe_rmc = 1; | 1825 | else |
1865 | else | 1826 | return -ENODEV; |
1866 | return -ENODEV; | 1827 | } |
1867 | 1828 | ||
1868 | error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); | 1829 | error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); |
1869 | if (error) | 1830 | if (error) |
@@ -1876,7 +1837,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1876 | } | 1837 | } |
1877 | 1838 | ||
1878 | /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ | 1839 | /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ |
1879 | if (!(base_addr & 0x0001)) | 1840 | if (! (base_addr & 0x0001)) |
1880 | { | 1841 | { |
1881 | pci_dev_put(pci_dev); | 1842 | pci_dev_put(pci_dev); |
1882 | printk(KERN_ERR | 1843 | printk(KERN_ERR |
@@ -1886,17 +1847,17 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1886 | } | 1847 | } |
1887 | 1848 | ||
1888 | base_addr &= 0xFFFE; | 1849 | base_addr &= 0xFFFE; |
1889 | if (!fe_rmc) | 1850 | if (! fe_rmc) |
1890 | /* Data register starts at base address + 1 in eRMC */ | 1851 | /* Data register starts at base address + 1 in eRMC */ |
1891 | ++base_addr; | 1852 | ++base_addr; |
1892 | 1853 | ||
1893 | if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { | 1854 | if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { |
1894 | pci_dev_put(pci_dev); | 1855 | pci_dev_put(pci_dev); |
1895 | return -ENODEV; | 1856 | return -ENODEV; |
1896 | } | 1857 | } |
1897 | 1858 | ||
1898 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1859 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1899 | if (!info) { | 1860 | if (! info) { |
1900 | pci_dev_put(pci_dev); | 1861 | pci_dev_put(pci_dev); |
1901 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); | 1862 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); |
1902 | return -ENOMEM; | 1863 | return -ENOMEM; |
@@ -1907,7 +1868,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1907 | ports[intf_num] = base_addr; | 1868 | ports[intf_num] = base_addr; |
1908 | info->io.info = &(ports[intf_num]); | 1869 | info->io.info = &(ports[intf_num]); |
1909 | info->io.regspacing = regspacings[intf_num]; | 1870 | info->io.regspacing = regspacings[intf_num]; |
1910 | if (!info->io.regspacing) | 1871 | if (! info->io.regspacing) |
1911 | info->io.regspacing = DEFAULT_REGSPACING; | 1872 | info->io.regspacing = DEFAULT_REGSPACING; |
1912 | info->io.regsize = DEFAULT_REGSPACING; | 1873 | info->io.regsize = DEFAULT_REGSPACING; |
1913 | info->io.regshift = regshifts[intf_num]; | 1874 | info->io.regshift = regshifts[intf_num]; |
@@ -1928,7 +1889,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1928 | static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) | 1889 | static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) |
1929 | { | 1890 | { |
1930 | #ifdef CONFIG_PCI | 1891 | #ifdef CONFIG_PCI |
1931 | if (find_pci_smic(intf_num, new_info)==0) | 1892 | if (find_pci_smic(intf_num, new_info) == 0) |
1932 | return 0; | 1893 | return 0; |
1933 | #endif | 1894 | #endif |
1934 | /* Include other methods here. */ | 1895 | /* Include other methods here. */ |
@@ -1946,7 +1907,7 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
1946 | int rv = 0; | 1907 | int rv = 0; |
1947 | 1908 | ||
1948 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); | 1909 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); |
1949 | if (!resp) | 1910 | if (! resp) |
1950 | return -ENOMEM; | 1911 | return -ENOMEM; |
1951 | 1912 | ||
1952 | /* Do a Get Device ID command, since it comes back with some | 1913 | /* Do a Get Device ID command, since it comes back with some |
@@ -1995,11 +1956,8 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
1995 | } | 1956 | } |
1996 | 1957 | ||
1997 | /* Record info from the get device id, in case we need it. */ | 1958 | /* Record info from the get device id, in case we need it. */ |
1998 | smi_info->ipmi_si_dev_rev = resp[4] & 0xf; | 1959 | memcpy(&smi_info->device_id, &resp[3], |
1999 | smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f; | 1960 | min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id))); |
2000 | smi_info->ipmi_si_fw_rev_minor = resp[6]; | ||
2001 | smi_info->ipmi_version_major = resp[7] & 0xf; | ||
2002 | smi_info->ipmi_version_minor = resp[7] >> 4; | ||
2003 | 1961 | ||
2004 | out: | 1962 | out: |
2005 | kfree(resp); | 1963 | kfree(resp); |
@@ -2031,7 +1989,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
2031 | struct smi_info *smi = data; | 1989 | struct smi_info *smi = data; |
2032 | 1990 | ||
2033 | out += sprintf(out, "interrupts_enabled: %d\n", | 1991 | out += sprintf(out, "interrupts_enabled: %d\n", |
2034 | smi->irq && !smi->interrupt_disabled); | 1992 | smi->irq && ! smi->interrupt_disabled); |
2035 | out += sprintf(out, "short_timeouts: %ld\n", | 1993 | out += sprintf(out, "short_timeouts: %ld\n", |
2036 | smi->short_timeouts); | 1994 | smi->short_timeouts); |
2037 | out += sprintf(out, "long_timeouts: %ld\n", | 1995 | out += sprintf(out, "long_timeouts: %ld\n", |
@@ -2060,6 +2018,73 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
2060 | return (out - ((char *) page)); | 2018 | return (out - ((char *) page)); |
2061 | } | 2019 | } |
2062 | 2020 | ||
2021 | /* | ||
2022 | * oem_data_avail_to_receive_msg_avail | ||
2023 | * @info - smi_info structure with msg_flags set | ||
2024 | * | ||
2025 | * Converts flags from OEM_DATA_AVAIL to RECEIVE_MSG_AVAIL | ||
2026 | * Returns 1 indicating need to re-run handle_flags(). | ||
2027 | */ | ||
2028 | static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info) | ||
2029 | { | ||
2030 | smi_info->msg_flags = ((smi_info->msg_flags & ~OEM_DATA_AVAIL) | | ||
2031 | RECEIVE_MSG_AVAIL); | ||
2032 | return 1; | ||
2033 | } | ||
2034 | |||
2035 | /* | ||
2036 | * setup_dell_poweredge_oem_data_handler | ||
2037 | * @info - smi_info.device_id must be populated | ||
2038 | * | ||
2039 | * Systems that match, but have firmware version < 1.40 may assert | ||
2040 | * OEM0_DATA_AVAIL on their own, without being told via Set Flags that | ||
2041 | * it's safe to do so. Such systems will de-assert OEM1_DATA_AVAIL | ||
2042 | * upon receipt of IPMI_GET_MSG_CMD, so we should treat these flags | ||
2043 | * as RECEIVE_MSG_AVAIL instead. | ||
2044 | * | ||
2045 | * As Dell has no plans to release IPMI 1.5 firmware that *ever* | ||
2046 | * assert the OEM[012] bits, and if it did, the driver would have to | ||
2047 | * change to handle that properly, we don't actually check for the | ||
2048 | * firmware version. | ||
2049 | * Device ID = 0x20 BMC on PowerEdge 8G servers | ||
2050 | * Device Revision = 0x80 | ||
2051 | * Firmware Revision1 = 0x01 BMC version 1.40 | ||
2052 | * Firmware Revision2 = 0x40 BCD encoded | ||
2053 | * IPMI Version = 0x51 IPMI 1.5 | ||
2054 | * Manufacturer ID = A2 02 00 Dell IANA | ||
2055 | * | ||
2056 | */ | ||
2057 | #define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20 | ||
2058 | #define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80 | ||
2059 | #define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51 | ||
2060 | #define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} | ||
2061 | static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) | ||
2062 | { | ||
2063 | struct ipmi_device_id *id = &smi_info->device_id; | ||
2064 | const char mfr[3]=DELL_IANA_MFR_ID; | ||
2065 | if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) | ||
2066 | && (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID) | ||
2067 | && (id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV) | ||
2068 | && (id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION)) | ||
2069 | { | ||
2070 | smi_info->oem_data_avail_handler = | ||
2071 | oem_data_avail_to_receive_msg_avail; | ||
2072 | } | ||
2073 | } | ||
2074 | |||
2075 | /* | ||
2076 | * setup_oem_data_handler | ||
2077 | * @info - smi_info.device_id must be filled in already | ||
2078 | * | ||
2079 | * Fills in smi_info.device_id.oem_data_available_handler | ||
2080 | * when we know what function to use there. | ||
2081 | */ | ||
2082 | |||
2083 | static void setup_oem_data_handler(struct smi_info *smi_info) | ||
2084 | { | ||
2085 | setup_dell_poweredge_oem_data_handler(smi_info); | ||
2086 | } | ||
2087 | |||
2063 | /* Returns 0 if initialized, or negative on an error. */ | 2088 | /* Returns 0 if initialized, or negative on an error. */ |
2064 | static int init_one_smi(int intf_num, struct smi_info **smi) | 2089 | static int init_one_smi(int intf_num, struct smi_info **smi) |
2065 | { | 2090 | { |
@@ -2071,19 +2096,15 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2071 | if (rv) | 2096 | if (rv) |
2072 | rv = try_init_port(intf_num, &new_smi); | 2097 | rv = try_init_port(intf_num, &new_smi); |
2073 | #ifdef CONFIG_ACPI | 2098 | #ifdef CONFIG_ACPI |
2074 | if ((rv) && (si_trydefaults)) { | 2099 | if (rv && si_trydefaults) |
2075 | rv = try_init_acpi(intf_num, &new_smi); | 2100 | rv = try_init_acpi(intf_num, &new_smi); |
2076 | } | ||
2077 | #endif | 2101 | #endif |
2078 | #ifdef CONFIG_X86 | 2102 | #ifdef CONFIG_X86 |
2079 | if ((rv) && (si_trydefaults)) { | 2103 | if (rv && si_trydefaults) |
2080 | rv = try_init_smbios(intf_num, &new_smi); | 2104 | rv = try_init_smbios(intf_num, &new_smi); |
2081 | } | ||
2082 | #endif | 2105 | #endif |
2083 | if ((rv) && (si_trydefaults)) { | 2106 | if (rv && si_trydefaults) |
2084 | rv = try_init_plug_and_play(intf_num, &new_smi); | 2107 | rv = try_init_plug_and_play(intf_num, &new_smi); |
2085 | } | ||
2086 | |||
2087 | 2108 | ||
2088 | if (rv) | 2109 | if (rv) |
2089 | return rv; | 2110 | return rv; |
@@ -2093,7 +2114,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2093 | new_smi->si_sm = NULL; | 2114 | new_smi->si_sm = NULL; |
2094 | new_smi->handlers = NULL; | 2115 | new_smi->handlers = NULL; |
2095 | 2116 | ||
2096 | if (!new_smi->irq_setup) { | 2117 | if (! new_smi->irq_setup) { |
2097 | new_smi->irq = irqs[intf_num]; | 2118 | new_smi->irq = irqs[intf_num]; |
2098 | new_smi->irq_setup = std_irq_setup; | 2119 | new_smi->irq_setup = std_irq_setup; |
2099 | new_smi->irq_cleanup = std_irq_cleanup; | 2120 | new_smi->irq_cleanup = std_irq_cleanup; |
@@ -2127,7 +2148,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2127 | 2148 | ||
2128 | /* Allocate the state machine's data and initialize it. */ | 2149 | /* Allocate the state machine's data and initialize it. */ |
2129 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); | 2150 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); |
2130 | if (!new_smi->si_sm) { | 2151 | if (! new_smi->si_sm) { |
2131 | printk(" Could not allocate state machine memory\n"); | 2152 | printk(" Could not allocate state machine memory\n"); |
2132 | rv = -ENOMEM; | 2153 | rv = -ENOMEM; |
2133 | goto out_err; | 2154 | goto out_err; |
@@ -2158,6 +2179,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2158 | if (rv) | 2179 | if (rv) |
2159 | goto out_err; | 2180 | goto out_err; |
2160 | 2181 | ||
2182 | setup_oem_data_handler(new_smi); | ||
2183 | |||
2161 | /* Try to claim any interrupts. */ | 2184 | /* Try to claim any interrupts. */ |
2162 | new_smi->irq_setup(new_smi); | 2185 | new_smi->irq_setup(new_smi); |
2163 | 2186 | ||
@@ -2191,8 +2214,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2191 | 2214 | ||
2192 | rv = ipmi_register_smi(&handlers, | 2215 | rv = ipmi_register_smi(&handlers, |
2193 | new_smi, | 2216 | new_smi, |
2194 | new_smi->ipmi_version_major, | 2217 | ipmi_version_major(&new_smi->device_id), |
2195 | new_smi->ipmi_version_minor, | 2218 | ipmi_version_minor(&new_smi->device_id), |
2196 | new_smi->slave_addr, | 2219 | new_smi->slave_addr, |
2197 | &(new_smi->intf)); | 2220 | &(new_smi->intf)); |
2198 | if (rv) { | 2221 | if (rv) { |
@@ -2233,7 +2256,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2233 | 2256 | ||
2234 | /* Wait for the timer to stop. This avoids problems with race | 2257 | /* Wait for the timer to stop. This avoids problems with race |
2235 | conditions removing the timer here. */ | 2258 | conditions removing the timer here. */ |
2236 | while (!new_smi->timer_stopped) { | 2259 | while (! new_smi->timer_stopped) { |
2237 | set_current_state(TASK_UNINTERRUPTIBLE); | 2260 | set_current_state(TASK_UNINTERRUPTIBLE); |
2238 | schedule_timeout(1); | 2261 | schedule_timeout(1); |
2239 | } | 2262 | } |
@@ -2273,7 +2296,7 @@ static __init int init_ipmi_si(void) | |||
2273 | /* Parse out the si_type string into its components. */ | 2296 | /* Parse out the si_type string into its components. */ |
2274 | str = si_type_str; | 2297 | str = si_type_str; |
2275 | if (*str != '\0') { | 2298 | if (*str != '\0') { |
2276 | for (i=0; (i<SI_MAX_PARMS) && (*str != '\0'); i++) { | 2299 | for (i = 0; (i < SI_MAX_PARMS) && (*str != '\0'); i++) { |
2277 | si_type[i] = str; | 2300 | si_type[i] = str; |
2278 | str = strchr(str, ','); | 2301 | str = strchr(str, ','); |
2279 | if (str) { | 2302 | if (str) { |
@@ -2285,22 +2308,14 @@ static __init int init_ipmi_si(void) | |||
2285 | } | 2308 | } |
2286 | } | 2309 | } |
2287 | 2310 | ||
2288 | printk(KERN_INFO "IPMI System Interface driver version " | 2311 | printk(KERN_INFO "IPMI System Interface driver.\n"); |
2289 | IPMI_SI_VERSION); | ||
2290 | if (kcs_smi_handlers.version) | ||
2291 | printk(", KCS version %s", kcs_smi_handlers.version); | ||
2292 | if (smic_smi_handlers.version) | ||
2293 | printk(", SMIC version %s", smic_smi_handlers.version); | ||
2294 | if (bt_smi_handlers.version) | ||
2295 | printk(", BT version %s", bt_smi_handlers.version); | ||
2296 | printk("\n"); | ||
2297 | 2312 | ||
2298 | #ifdef CONFIG_X86 | 2313 | #ifdef CONFIG_X86 |
2299 | dmi_decode(); | 2314 | dmi_find_bmc(); |
2300 | #endif | 2315 | #endif |
2301 | 2316 | ||
2302 | rv = init_one_smi(0, &(smi_infos[pos])); | 2317 | rv = init_one_smi(0, &(smi_infos[pos])); |
2303 | if (rv && !ports[0] && si_trydefaults) { | 2318 | if (rv && ! ports[0] && si_trydefaults) { |
2304 | /* If we are trying defaults and the initial port is | 2319 | /* If we are trying defaults and the initial port is |
2305 | not set, then set it. */ | 2320 | not set, then set it. */ |
2306 | si_type[0] = "kcs"; | 2321 | si_type[0] = "kcs"; |
@@ -2322,7 +2337,7 @@ static __init int init_ipmi_si(void) | |||
2322 | if (rv == 0) | 2337 | if (rv == 0) |
2323 | pos++; | 2338 | pos++; |
2324 | 2339 | ||
2325 | for (i=1; i < SI_MAX_PARMS; i++) { | 2340 | for (i = 1; i < SI_MAX_PARMS; i++) { |
2326 | rv = init_one_smi(i, &(smi_infos[pos])); | 2341 | rv = init_one_smi(i, &(smi_infos[pos])); |
2327 | if (rv == 0) | 2342 | if (rv == 0) |
2328 | pos++; | 2343 | pos++; |
@@ -2364,14 +2379,14 @@ static void __exit cleanup_one_si(struct smi_info *to_clean) | |||
2364 | 2379 | ||
2365 | /* Wait for the timer to stop. This avoids problems with race | 2380 | /* Wait for the timer to stop. This avoids problems with race |
2366 | conditions removing the timer here. */ | 2381 | conditions removing the timer here. */ |
2367 | while (!to_clean->timer_stopped) { | 2382 | while (! to_clean->timer_stopped) { |
2368 | set_current_state(TASK_UNINTERRUPTIBLE); | 2383 | set_current_state(TASK_UNINTERRUPTIBLE); |
2369 | schedule_timeout(1); | 2384 | schedule_timeout(1); |
2370 | } | 2385 | } |
2371 | 2386 | ||
2372 | /* Interrupts and timeouts are stopped, now make sure the | 2387 | /* Interrupts and timeouts are stopped, now make sure the |
2373 | interface is in a clean state. */ | 2388 | interface is in a clean state. */ |
2374 | while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) { | 2389 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { |
2375 | poll(to_clean); | 2390 | poll(to_clean); |
2376 | set_current_state(TASK_UNINTERRUPTIBLE); | 2391 | set_current_state(TASK_UNINTERRUPTIBLE); |
2377 | schedule_timeout(1); | 2392 | schedule_timeout(1); |
@@ -2395,13 +2410,15 @@ static __exit void cleanup_ipmi_si(void) | |||
2395 | { | 2410 | { |
2396 | int i; | 2411 | int i; |
2397 | 2412 | ||
2398 | if (!initialized) | 2413 | if (! initialized) |
2399 | return; | 2414 | return; |
2400 | 2415 | ||
2401 | for (i=0; i<SI_MAX_DRIVERS; i++) { | 2416 | for (i = 0; i < SI_MAX_DRIVERS; i++) { |
2402 | cleanup_one_si(smi_infos[i]); | 2417 | cleanup_one_si(smi_infos[i]); |
2403 | } | 2418 | } |
2404 | } | 2419 | } |
2405 | module_exit(cleanup_ipmi_si); | 2420 | module_exit(cleanup_ipmi_si); |
2406 | 2421 | ||
2407 | MODULE_LICENSE("GPL"); | 2422 | MODULE_LICENSE("GPL"); |
2423 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
2424 | MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT system interfaces."); | ||