diff options
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 947 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_sm.h | 3 |
2 files changed, 496 insertions, 454 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e59b638766ef..f3b3b23c5330 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/pci.h> | 52 | #include <linux/pci.h> |
53 | #include <linux/ioport.h> | 53 | #include <linux/ioport.h> |
54 | #include <linux/notifier.h> | 54 | #include <linux/notifier.h> |
55 | #include <linux/mutex.h> | ||
55 | #include <linux/kthread.h> | 56 | #include <linux/kthread.h> |
56 | #include <asm/irq.h> | 57 | #include <asm/irq.h> |
57 | #ifdef CONFIG_HIGH_RES_TIMERS | 58 | #ifdef CONFIG_HIGH_RES_TIMERS |
@@ -109,6 +110,7 @@ enum si_intf_state { | |||
109 | enum si_type { | 110 | enum si_type { |
110 | SI_KCS, SI_SMIC, SI_BT | 111 | SI_KCS, SI_SMIC, SI_BT |
111 | }; | 112 | }; |
113 | static char *si_to_str[] = { "KCS", "SMIC", "BT" }; | ||
112 | 114 | ||
113 | struct ipmi_device_id { | 115 | struct ipmi_device_id { |
114 | unsigned char device_id; | 116 | unsigned char device_id; |
@@ -147,6 +149,9 @@ struct smi_info | |||
147 | int (*irq_setup)(struct smi_info *info); | 149 | int (*irq_setup)(struct smi_info *info); |
148 | void (*irq_cleanup)(struct smi_info *info); | 150 | void (*irq_cleanup)(struct smi_info *info); |
149 | unsigned int io_size; | 151 | unsigned int io_size; |
152 | char *addr_source; /* ACPI, PCI, SMBIOS, hardcode, default. */ | ||
153 | void (*addr_source_cleanup)(struct smi_info *info); | ||
154 | void *addr_source_data; | ||
150 | 155 | ||
151 | /* Per-OEM handler, called from handle_flags(). | 156 | /* Per-OEM handler, called from handle_flags(). |
152 | Returns 1 when handle_flags() needs to be re-run | 157 | Returns 1 when handle_flags() needs to be re-run |
@@ -224,8 +229,12 @@ struct smi_info | |||
224 | unsigned long incoming_messages; | 229 | unsigned long incoming_messages; |
225 | 230 | ||
226 | struct task_struct *thread; | 231 | struct task_struct *thread; |
232 | |||
233 | struct list_head link; | ||
227 | }; | 234 | }; |
228 | 235 | ||
236 | static int try_smi_init(struct smi_info *smi); | ||
237 | |||
229 | static struct notifier_block *xaction_notifier_list; | 238 | static struct notifier_block *xaction_notifier_list; |
230 | static int register_xaction_notifier(struct notifier_block * nb) | 239 | static int register_xaction_notifier(struct notifier_block * nb) |
231 | { | 240 | { |
@@ -271,13 +280,13 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
271 | spin_lock(&(smi_info->msg_lock)); | 280 | spin_lock(&(smi_info->msg_lock)); |
272 | 281 | ||
273 | /* Pick the high priority queue first. */ | 282 | /* Pick the high priority queue first. */ |
274 | if (! list_empty(&(smi_info->hp_xmit_msgs))) { | 283 | if (!list_empty(&(smi_info->hp_xmit_msgs))) { |
275 | entry = smi_info->hp_xmit_msgs.next; | 284 | entry = smi_info->hp_xmit_msgs.next; |
276 | } else if (! list_empty(&(smi_info->xmit_msgs))) { | 285 | } else if (!list_empty(&(smi_info->xmit_msgs))) { |
277 | entry = smi_info->xmit_msgs.next; | 286 | entry = smi_info->xmit_msgs.next; |
278 | } | 287 | } |
279 | 288 | ||
280 | if (! entry) { | 289 | if (!entry) { |
281 | smi_info->curr_msg = NULL; | 290 | smi_info->curr_msg = NULL; |
282 | rv = SI_SM_IDLE; | 291 | rv = SI_SM_IDLE; |
283 | } else { | 292 | } else { |
@@ -344,7 +353,7 @@ static void start_clear_flags(struct smi_info *smi_info) | |||
344 | memory, we will re-enable the interrupt. */ | 353 | memory, we will re-enable the interrupt. */ |
345 | static inline void disable_si_irq(struct smi_info *smi_info) | 354 | static inline void disable_si_irq(struct smi_info *smi_info) |
346 | { | 355 | { |
347 | if ((smi_info->irq) && (! smi_info->interrupt_disabled)) { | 356 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { |
348 | disable_irq_nosync(smi_info->irq); | 357 | disable_irq_nosync(smi_info->irq); |
349 | smi_info->interrupt_disabled = 1; | 358 | smi_info->interrupt_disabled = 1; |
350 | } | 359 | } |
@@ -375,7 +384,7 @@ static void handle_flags(struct smi_info *smi_info) | |||
375 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { | 384 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { |
376 | /* Messages available. */ | 385 | /* Messages available. */ |
377 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 386 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
378 | if (! smi_info->curr_msg) { | 387 | if (!smi_info->curr_msg) { |
379 | disable_si_irq(smi_info); | 388 | disable_si_irq(smi_info); |
380 | smi_info->si_state = SI_NORMAL; | 389 | smi_info->si_state = SI_NORMAL; |
381 | return; | 390 | return; |
@@ -394,7 +403,7 @@ static void handle_flags(struct smi_info *smi_info) | |||
394 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { | 403 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { |
395 | /* Events available. */ | 404 | /* Events available. */ |
396 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 405 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
397 | if (! smi_info->curr_msg) { | 406 | if (!smi_info->curr_msg) { |
398 | disable_si_irq(smi_info); | 407 | disable_si_irq(smi_info); |
399 | smi_info->si_state = SI_NORMAL; | 408 | smi_info->si_state = SI_NORMAL; |
400 | return; | 409 | return; |
@@ -430,7 +439,7 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
430 | #endif | 439 | #endif |
431 | switch (smi_info->si_state) { | 440 | switch (smi_info->si_state) { |
432 | case SI_NORMAL: | 441 | case SI_NORMAL: |
433 | if (! smi_info->curr_msg) | 442 | if (!smi_info->curr_msg) |
434 | break; | 443 | break; |
435 | 444 | ||
436 | smi_info->curr_msg->rsp_size | 445 | smi_info->curr_msg->rsp_size |
@@ -880,7 +889,7 @@ static void smi_timeout(unsigned long data) | |||
880 | 889 | ||
881 | smi_info->last_timeout_jiffies = jiffies_now; | 890 | smi_info->last_timeout_jiffies = jiffies_now; |
882 | 891 | ||
883 | if ((smi_info->irq) && (! smi_info->interrupt_disabled)) { | 892 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { |
884 | /* Running with interrupts, only do long timeouts. */ | 893 | /* Running with interrupts, only do long timeouts. */ |
885 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 894 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; |
886 | spin_lock_irqsave(&smi_info->count_lock, flags); | 895 | spin_lock_irqsave(&smi_info->count_lock, flags); |
@@ -974,15 +983,12 @@ static struct ipmi_smi_handlers handlers = | |||
974 | a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS */ | 983 | a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS */ |
975 | 984 | ||
976 | #define SI_MAX_PARMS 4 | 985 | #define SI_MAX_PARMS 4 |
977 | #define SI_MAX_DRIVERS ((SI_MAX_PARMS * 2) + 2) | 986 | static LIST_HEAD(smi_infos); |
978 | static struct smi_info *smi_infos[SI_MAX_DRIVERS] = | 987 | static DECLARE_MUTEX(smi_infos_lock); |
979 | { NULL, NULL, NULL, NULL }; | 988 | static int smi_num; /* Used to sequence the SMIs */ |
980 | 989 | ||
981 | #define DEVICE_NAME "ipmi_si" | 990 | #define DEVICE_NAME "ipmi_si" |
982 | 991 | ||
983 | #define DEFAULT_KCS_IO_PORT 0xca2 | ||
984 | #define DEFAULT_SMIC_IO_PORT 0xca9 | ||
985 | #define DEFAULT_BT_IO_PORT 0xe4 | ||
986 | #define DEFAULT_REGSPACING 1 | 992 | #define DEFAULT_REGSPACING 1 |
987 | 993 | ||
988 | static int si_trydefaults = 1; | 994 | static int si_trydefaults = 1; |
@@ -1053,38 +1059,23 @@ MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for" | |||
1053 | " by interface number."); | 1059 | " by interface number."); |
1054 | 1060 | ||
1055 | 1061 | ||
1062 | #define IPMI_IO_ADDR_SPACE 0 | ||
1056 | #define IPMI_MEM_ADDR_SPACE 1 | 1063 | #define IPMI_MEM_ADDR_SPACE 1 |
1057 | #define IPMI_IO_ADDR_SPACE 2 | 1064 | static char *addr_space_to_str[] = { "I/O", "memory" }; |
1058 | 1065 | ||
1059 | #if defined(CONFIG_ACPI) || defined(CONFIG_DMI) || defined(CONFIG_PCI) | 1066 | static void std_irq_cleanup(struct smi_info *info) |
1060 | static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr) | ||
1061 | { | 1067 | { |
1062 | int i; | 1068 | if (info->si_type == SI_BT) |
1063 | 1069 | /* Disable the interrupt in the BT interface. */ | |
1064 | for (i = 0; i < SI_MAX_PARMS; ++i) { | 1070 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, 0); |
1065 | /* Don't check our address. */ | 1071 | free_irq(info->irq, info); |
1066 | if (i == intf) | ||
1067 | continue; | ||
1068 | if (si_type[i] != NULL) { | ||
1069 | if ((addr_space == IPMI_MEM_ADDR_SPACE && | ||
1070 | base_addr == addrs[i]) || | ||
1071 | (addr_space == IPMI_IO_ADDR_SPACE && | ||
1072 | base_addr == ports[i])) | ||
1073 | return 0; | ||
1074 | } | ||
1075 | else | ||
1076 | break; | ||
1077 | } | ||
1078 | |||
1079 | return 1; | ||
1080 | } | 1072 | } |
1081 | #endif | ||
1082 | 1073 | ||
1083 | static int std_irq_setup(struct smi_info *info) | 1074 | static int std_irq_setup(struct smi_info *info) |
1084 | { | 1075 | { |
1085 | int rv; | 1076 | int rv; |
1086 | 1077 | ||
1087 | if (! info->irq) | 1078 | if (!info->irq) |
1088 | return 0; | 1079 | return 0; |
1089 | 1080 | ||
1090 | if (info->si_type == SI_BT) { | 1081 | if (info->si_type == SI_BT) { |
@@ -1093,7 +1084,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1093 | SA_INTERRUPT, | 1084 | SA_INTERRUPT, |
1094 | DEVICE_NAME, | 1085 | DEVICE_NAME, |
1095 | info); | 1086 | info); |
1096 | if (! rv) | 1087 | if (!rv) |
1097 | /* Enable the interrupt in the BT interface. */ | 1088 | /* Enable the interrupt in the BT interface. */ |
1098 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, | 1089 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, |
1099 | IPMI_BT_INTMASK_ENABLE_IRQ_BIT); | 1090 | IPMI_BT_INTMASK_ENABLE_IRQ_BIT); |
@@ -1110,88 +1101,78 @@ static int std_irq_setup(struct smi_info *info) | |||
1110 | DEVICE_NAME, info->irq); | 1101 | DEVICE_NAME, info->irq); |
1111 | info->irq = 0; | 1102 | info->irq = 0; |
1112 | } else { | 1103 | } else { |
1104 | info->irq_cleanup = std_irq_cleanup; | ||
1113 | printk(" Using irq %d\n", info->irq); | 1105 | printk(" Using irq %d\n", info->irq); |
1114 | } | 1106 | } |
1115 | 1107 | ||
1116 | return rv; | 1108 | return rv; |
1117 | } | 1109 | } |
1118 | 1110 | ||
1119 | static void std_irq_cleanup(struct smi_info *info) | ||
1120 | { | ||
1121 | if (! info->irq) | ||
1122 | return; | ||
1123 | |||
1124 | if (info->si_type == SI_BT) | ||
1125 | /* Disable the interrupt in the BT interface. */ | ||
1126 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, 0); | ||
1127 | free_irq(info->irq, info); | ||
1128 | } | ||
1129 | |||
1130 | static unsigned char port_inb(struct si_sm_io *io, unsigned int offset) | 1111 | static unsigned char port_inb(struct si_sm_io *io, unsigned int offset) |
1131 | { | 1112 | { |
1132 | unsigned int *addr = io->info; | 1113 | unsigned int addr = io->addr_data; |
1133 | 1114 | ||
1134 | return inb((*addr)+(offset*io->regspacing)); | 1115 | return inb(addr + (offset * io->regspacing)); |
1135 | } | 1116 | } |
1136 | 1117 | ||
1137 | static void port_outb(struct si_sm_io *io, unsigned int offset, | 1118 | static void port_outb(struct si_sm_io *io, unsigned int offset, |
1138 | unsigned char b) | 1119 | unsigned char b) |
1139 | { | 1120 | { |
1140 | unsigned int *addr = io->info; | 1121 | unsigned int addr = io->addr_data; |
1141 | 1122 | ||
1142 | outb(b, (*addr)+(offset * io->regspacing)); | 1123 | outb(b, addr + (offset * io->regspacing)); |
1143 | } | 1124 | } |
1144 | 1125 | ||
1145 | static unsigned char port_inw(struct si_sm_io *io, unsigned int offset) | 1126 | static unsigned char port_inw(struct si_sm_io *io, unsigned int offset) |
1146 | { | 1127 | { |
1147 | unsigned int *addr = io->info; | 1128 | unsigned int addr = io->addr_data; |
1148 | 1129 | ||
1149 | return (inw((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff; | 1130 | return (inw(addr + (offset * io->regspacing)) >> io->regshift) & 0xff; |
1150 | } | 1131 | } |
1151 | 1132 | ||
1152 | static void port_outw(struct si_sm_io *io, unsigned int offset, | 1133 | static void port_outw(struct si_sm_io *io, unsigned int offset, |
1153 | unsigned char b) | 1134 | unsigned char b) |
1154 | { | 1135 | { |
1155 | unsigned int *addr = io->info; | 1136 | unsigned int addr = io->addr_data; |
1156 | 1137 | ||
1157 | outw(b << io->regshift, (*addr)+(offset * io->regspacing)); | 1138 | outw(b << io->regshift, addr + (offset * io->regspacing)); |
1158 | } | 1139 | } |
1159 | 1140 | ||
1160 | static unsigned char port_inl(struct si_sm_io *io, unsigned int offset) | 1141 | static unsigned char port_inl(struct si_sm_io *io, unsigned int offset) |
1161 | { | 1142 | { |
1162 | unsigned int *addr = io->info; | 1143 | unsigned int addr = io->addr_data; |
1163 | 1144 | ||
1164 | return (inl((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff; | 1145 | return (inl(addr + (offset * io->regspacing)) >> io->regshift) & 0xff; |
1165 | } | 1146 | } |
1166 | 1147 | ||
1167 | static void port_outl(struct si_sm_io *io, unsigned int offset, | 1148 | static void port_outl(struct si_sm_io *io, unsigned int offset, |
1168 | unsigned char b) | 1149 | unsigned char b) |
1169 | { | 1150 | { |
1170 | unsigned int *addr = io->info; | 1151 | unsigned int addr = io->addr_data; |
1171 | 1152 | ||
1172 | outl(b << io->regshift, (*addr)+(offset * io->regspacing)); | 1153 | outl(b << io->regshift, addr+(offset * io->regspacing)); |
1173 | } | 1154 | } |
1174 | 1155 | ||
1175 | static void port_cleanup(struct smi_info *info) | 1156 | static void port_cleanup(struct smi_info *info) |
1176 | { | 1157 | { |
1177 | unsigned int *addr = info->io.info; | 1158 | unsigned int addr = info->io.addr_data; |
1178 | int mapsize; | 1159 | int mapsize; |
1179 | 1160 | ||
1180 | if (addr && (*addr)) { | 1161 | if (addr) { |
1181 | mapsize = ((info->io_size * info->io.regspacing) | 1162 | mapsize = ((info->io_size * info->io.regspacing) |
1182 | - (info->io.regspacing - info->io.regsize)); | 1163 | - (info->io.regspacing - info->io.regsize)); |
1183 | 1164 | ||
1184 | release_region (*addr, mapsize); | 1165 | release_region (addr, mapsize); |
1185 | } | 1166 | } |
1186 | kfree(info); | 1167 | kfree(info); |
1187 | } | 1168 | } |
1188 | 1169 | ||
1189 | static int port_setup(struct smi_info *info) | 1170 | static int port_setup(struct smi_info *info) |
1190 | { | 1171 | { |
1191 | unsigned int *addr = info->io.info; | 1172 | unsigned int addr = info->io.addr_data; |
1192 | int mapsize; | 1173 | int mapsize; |
1193 | 1174 | ||
1194 | if (! addr || (! *addr)) | 1175 | if (!addr) |
1195 | return -ENODEV; | 1176 | return -ENODEV; |
1196 | 1177 | ||
1197 | info->io_cleanup = port_cleanup; | 1178 | info->io_cleanup = port_cleanup; |
@@ -1225,51 +1206,11 @@ static int port_setup(struct smi_info *info) | |||
1225 | mapsize = ((info->io_size * info->io.regspacing) | 1206 | mapsize = ((info->io_size * info->io.regspacing) |
1226 | - (info->io.regspacing - info->io.regsize)); | 1207 | - (info->io.regspacing - info->io.regsize)); |
1227 | 1208 | ||
1228 | if (request_region(*addr, mapsize, DEVICE_NAME) == NULL) | 1209 | if (request_region(addr, mapsize, DEVICE_NAME) == NULL) |
1229 | return -EIO; | 1210 | return -EIO; |
1230 | return 0; | 1211 | return 0; |
1231 | } | 1212 | } |
1232 | 1213 | ||
1233 | static int try_init_port(int intf_num, struct smi_info **new_info) | ||
1234 | { | ||
1235 | struct smi_info *info; | ||
1236 | |||
1237 | if (! ports[intf_num]) | ||
1238 | return -ENODEV; | ||
1239 | |||
1240 | if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, | ||
1241 | ports[intf_num])) | ||
1242 | return -ENODEV; | ||
1243 | |||
1244 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
1245 | if (! info) { | ||
1246 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); | ||
1247 | return -ENOMEM; | ||
1248 | } | ||
1249 | memset(info, 0, sizeof(*info)); | ||
1250 | |||
1251 | info->io_setup = port_setup; | ||
1252 | info->io.info = &(ports[intf_num]); | ||
1253 | info->io.addr = NULL; | ||
1254 | info->io.regspacing = regspacings[intf_num]; | ||
1255 | if (! info->io.regspacing) | ||
1256 | info->io.regspacing = DEFAULT_REGSPACING; | ||
1257 | info->io.regsize = regsizes[intf_num]; | ||
1258 | if (! info->io.regsize) | ||
1259 | info->io.regsize = DEFAULT_REGSPACING; | ||
1260 | info->io.regshift = regshifts[intf_num]; | ||
1261 | info->irq = 0; | ||
1262 | info->irq_setup = NULL; | ||
1263 | *new_info = info; | ||
1264 | |||
1265 | if (si_type[intf_num] == NULL) | ||
1266 | si_type[intf_num] = "kcs"; | ||
1267 | |||
1268 | printk("ipmi_si: Trying \"%s\" at I/O port 0x%x\n", | ||
1269 | si_type[intf_num], ports[intf_num]); | ||
1270 | return 0; | ||
1271 | } | ||
1272 | |||
1273 | static unsigned char intf_mem_inb(struct si_sm_io *io, unsigned int offset) | 1214 | static unsigned char intf_mem_inb(struct si_sm_io *io, unsigned int offset) |
1274 | { | 1215 | { |
1275 | return readb((io->addr)+(offset * io->regspacing)); | 1216 | return readb((io->addr)+(offset * io->regspacing)); |
@@ -1321,7 +1262,7 @@ static void mem_outq(struct si_sm_io *io, unsigned int offset, | |||
1321 | 1262 | ||
1322 | static void mem_cleanup(struct smi_info *info) | 1263 | static void mem_cleanup(struct smi_info *info) |
1323 | { | 1264 | { |
1324 | unsigned long *addr = info->io.info; | 1265 | unsigned long addr = info->io.addr_data; |
1325 | int mapsize; | 1266 | int mapsize; |
1326 | 1267 | ||
1327 | if (info->io.addr) { | 1268 | if (info->io.addr) { |
@@ -1330,17 +1271,17 @@ static void mem_cleanup(struct smi_info *info) | |||
1330 | mapsize = ((info->io_size * info->io.regspacing) | 1271 | mapsize = ((info->io_size * info->io.regspacing) |
1331 | - (info->io.regspacing - info->io.regsize)); | 1272 | - (info->io.regspacing - info->io.regsize)); |
1332 | 1273 | ||
1333 | release_mem_region(*addr, mapsize); | 1274 | release_mem_region(addr, mapsize); |
1334 | } | 1275 | } |
1335 | kfree(info); | 1276 | kfree(info); |
1336 | } | 1277 | } |
1337 | 1278 | ||
1338 | static int mem_setup(struct smi_info *info) | 1279 | static int mem_setup(struct smi_info *info) |
1339 | { | 1280 | { |
1340 | unsigned long *addr = info->io.info; | 1281 | unsigned long addr = info->io.addr_data; |
1341 | int mapsize; | 1282 | int mapsize; |
1342 | 1283 | ||
1343 | if (! addr || (! *addr)) | 1284 | if (!addr) |
1344 | return -ENODEV; | 1285 | return -ENODEV; |
1345 | 1286 | ||
1346 | info->io_cleanup = mem_cleanup; | 1287 | info->io_cleanup = mem_cleanup; |
@@ -1380,57 +1321,83 @@ static int mem_setup(struct smi_info *info) | |||
1380 | mapsize = ((info->io_size * info->io.regspacing) | 1321 | mapsize = ((info->io_size * info->io.regspacing) |
1381 | - (info->io.regspacing - info->io.regsize)); | 1322 | - (info->io.regspacing - info->io.regsize)); |
1382 | 1323 | ||
1383 | if (request_mem_region(*addr, mapsize, DEVICE_NAME) == NULL) | 1324 | if (request_mem_region(addr, mapsize, DEVICE_NAME) == NULL) |
1384 | return -EIO; | 1325 | return -EIO; |
1385 | 1326 | ||
1386 | info->io.addr = ioremap(*addr, mapsize); | 1327 | info->io.addr = ioremap(addr, mapsize); |
1387 | if (info->io.addr == NULL) { | 1328 | if (info->io.addr == NULL) { |
1388 | release_mem_region(*addr, mapsize); | 1329 | release_mem_region(addr, mapsize); |
1389 | return -EIO; | 1330 | return -EIO; |
1390 | } | 1331 | } |
1391 | return 0; | 1332 | return 0; |
1392 | } | 1333 | } |
1393 | 1334 | ||
1394 | static int try_init_mem(int intf_num, struct smi_info **new_info) | 1335 | |
1336 | static __devinit void hardcode_find_bmc(void) | ||
1395 | { | 1337 | { |
1338 | int i; | ||
1396 | struct smi_info *info; | 1339 | struct smi_info *info; |
1397 | 1340 | ||
1398 | if (! addrs[intf_num]) | 1341 | for (i = 0; i < SI_MAX_PARMS; i++) { |
1399 | return -ENODEV; | 1342 | if (!ports[i] && !addrs[i]) |
1343 | continue; | ||
1400 | 1344 | ||
1401 | if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, | 1345 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
1402 | addrs[intf_num])) | 1346 | if (!info) |
1403 | return -ENODEV; | 1347 | return; |
1404 | 1348 | ||
1405 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1349 | info->addr_source = "hardcoded"; |
1406 | if (! info) { | ||
1407 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); | ||
1408 | return -ENOMEM; | ||
1409 | } | ||
1410 | memset(info, 0, sizeof(*info)); | ||
1411 | 1350 | ||
1412 | info->io_setup = mem_setup; | 1351 | if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { |
1413 | info->io.info = &addrs[intf_num]; | 1352 | info->si_type = SI_KCS; |
1414 | info->io.addr = NULL; | 1353 | } else if (strcmp(si_type[i], "smic") == 0) { |
1415 | info->io.regspacing = regspacings[intf_num]; | 1354 | info->si_type = SI_SMIC; |
1416 | if (! info->io.regspacing) | 1355 | } else if (strcmp(si_type[i], "bt") == 0) { |
1417 | info->io.regspacing = DEFAULT_REGSPACING; | 1356 | info->si_type = SI_BT; |
1418 | info->io.regsize = regsizes[intf_num]; | 1357 | } else { |
1419 | if (! info->io.regsize) | 1358 | printk(KERN_WARNING |
1420 | info->io.regsize = DEFAULT_REGSPACING; | 1359 | "ipmi_si: Interface type specified " |
1421 | info->io.regshift = regshifts[intf_num]; | 1360 | "for interface %d, was invalid: %s\n", |
1422 | info->irq = 0; | 1361 | i, si_type[i]); |
1423 | info->irq_setup = NULL; | 1362 | kfree(info); |
1424 | *new_info = info; | 1363 | continue; |
1364 | } | ||
1425 | 1365 | ||
1426 | if (si_type[intf_num] == NULL) | 1366 | if (ports[i]) { |
1427 | si_type[intf_num] = "kcs"; | 1367 | /* An I/O port */ |
1368 | info->io_setup = port_setup; | ||
1369 | info->io.addr_data = ports[i]; | ||
1370 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | ||
1371 | } else if (addrs[i]) { | ||
1372 | /* A memory port */ | ||
1373 | info->io_setup = mem_setup; | ||
1374 | info->io.addr_data = addrs[i]; | ||
1375 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | ||
1376 | } else { | ||
1377 | printk(KERN_WARNING | ||
1378 | "ipmi_si: Interface type specified " | ||
1379 | "for interface %d, " | ||
1380 | "but port and address were not set or " | ||
1381 | "set to zero.\n", i); | ||
1382 | kfree(info); | ||
1383 | continue; | ||
1384 | } | ||
1428 | 1385 | ||
1429 | printk("ipmi_si: Trying \"%s\" at memory address 0x%lx\n", | 1386 | info->io.addr = NULL; |
1430 | si_type[intf_num], addrs[intf_num]); | 1387 | info->io.regspacing = regspacings[i]; |
1431 | return 0; | 1388 | if (!info->io.regspacing) |
1432 | } | 1389 | info->io.regspacing = DEFAULT_REGSPACING; |
1390 | info->io.regsize = regsizes[i]; | ||
1391 | if (!info->io.regsize) | ||
1392 | info->io.regsize = DEFAULT_REGSPACING; | ||
1393 | info->io.regshift = regshifts[i]; | ||
1394 | info->irq = irqs[i]; | ||
1395 | if (info->irq) | ||
1396 | info->irq_setup = std_irq_setup; | ||
1433 | 1397 | ||
1398 | try_smi_init(info); | ||
1399 | } | ||
1400 | } | ||
1434 | 1401 | ||
1435 | #ifdef CONFIG_ACPI | 1402 | #ifdef CONFIG_ACPI |
1436 | 1403 | ||
@@ -1470,11 +1437,19 @@ static u32 ipmi_acpi_gpe(void *context) | |||
1470 | return ACPI_INTERRUPT_HANDLED; | 1437 | return ACPI_INTERRUPT_HANDLED; |
1471 | } | 1438 | } |
1472 | 1439 | ||
1440 | static void acpi_gpe_irq_cleanup(struct smi_info *info) | ||
1441 | { | ||
1442 | if (!info->irq) | ||
1443 | return; | ||
1444 | |||
1445 | acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); | ||
1446 | } | ||
1447 | |||
1473 | static int acpi_gpe_irq_setup(struct smi_info *info) | 1448 | static int acpi_gpe_irq_setup(struct smi_info *info) |
1474 | { | 1449 | { |
1475 | acpi_status status; | 1450 | acpi_status status; |
1476 | 1451 | ||
1477 | if (! info->irq) | 1452 | if (!info->irq) |
1478 | return 0; | 1453 | return 0; |
1479 | 1454 | ||
1480 | /* FIXME - is level triggered right? */ | 1455 | /* FIXME - is level triggered right? */ |
@@ -1491,19 +1466,12 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1491 | info->irq = 0; | 1466 | info->irq = 0; |
1492 | return -EINVAL; | 1467 | return -EINVAL; |
1493 | } else { | 1468 | } else { |
1469 | info->irq_cleanup = acpi_gpe_irq_cleanup; | ||
1494 | printk(" Using ACPI GPE %d\n", info->irq); | 1470 | printk(" Using ACPI GPE %d\n", info->irq); |
1495 | return 0; | 1471 | return 0; |
1496 | } | 1472 | } |
1497 | } | 1473 | } |
1498 | 1474 | ||
1499 | static void acpi_gpe_irq_cleanup(struct smi_info *info) | ||
1500 | { | ||
1501 | if (! info->irq) | ||
1502 | return; | ||
1503 | |||
1504 | acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); | ||
1505 | } | ||
1506 | |||
1507 | /* | 1475 | /* |
1508 | * Defined at | 1476 | * Defined at |
1509 | * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf | 1477 | * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf |
@@ -1546,28 +1514,12 @@ struct SPMITable { | |||
1546 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ | 1514 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ |
1547 | }; | 1515 | }; |
1548 | 1516 | ||
1549 | static int try_init_acpi(int intf_num, struct smi_info **new_info) | 1517 | static __devinit int try_init_acpi(struct SPMITable *spmi) |
1550 | { | 1518 | { |
1551 | struct smi_info *info; | 1519 | struct smi_info *info; |
1552 | acpi_status status; | ||
1553 | struct SPMITable *spmi; | ||
1554 | char *io_type; | 1520 | char *io_type; |
1555 | u8 addr_space; | 1521 | u8 addr_space; |
1556 | 1522 | ||
1557 | if (acpi_disabled) | ||
1558 | return -ENODEV; | ||
1559 | |||
1560 | if (acpi_failure) | ||
1561 | return -ENODEV; | ||
1562 | |||
1563 | status = acpi_get_firmware_table("SPMI", intf_num+1, | ||
1564 | ACPI_LOGICAL_ADDRESSING, | ||
1565 | (struct acpi_table_header **) &spmi); | ||
1566 | if (status != AE_OK) { | ||
1567 | acpi_failure = 1; | ||
1568 | return -ENODEV; | ||
1569 | } | ||
1570 | |||
1571 | if (spmi->IPMIlegacy != 1) { | 1523 | if (spmi->IPMIlegacy != 1) { |
1572 | printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy); | 1524 | printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy); |
1573 | return -ENODEV; | 1525 | return -ENODEV; |
@@ -1577,47 +1529,42 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) | |||
1577 | addr_space = IPMI_MEM_ADDR_SPACE; | 1529 | addr_space = IPMI_MEM_ADDR_SPACE; |
1578 | else | 1530 | else |
1579 | addr_space = IPMI_IO_ADDR_SPACE; | 1531 | addr_space = IPMI_IO_ADDR_SPACE; |
1580 | if (! is_new_interface(-1, addr_space, spmi->addr.address)) | 1532 | |
1581 | return -ENODEV; | 1533 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
1534 | if (!info) { | ||
1535 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); | ||
1536 | return -ENOMEM; | ||
1537 | } | ||
1538 | |||
1539 | info->addr_source = "ACPI"; | ||
1582 | 1540 | ||
1583 | /* Figure out the interface type. */ | 1541 | /* Figure out the interface type. */ |
1584 | switch (spmi->InterfaceType) | 1542 | switch (spmi->InterfaceType) |
1585 | { | 1543 | { |
1586 | case 1: /* KCS */ | 1544 | case 1: /* KCS */ |
1587 | si_type[intf_num] = "kcs"; | 1545 | info->si_type = SI_KCS; |
1588 | break; | 1546 | break; |
1589 | |||
1590 | case 2: /* SMIC */ | 1547 | case 2: /* SMIC */ |
1591 | si_type[intf_num] = "smic"; | 1548 | info->si_type = SI_SMIC; |
1592 | break; | 1549 | break; |
1593 | |||
1594 | case 3: /* BT */ | 1550 | case 3: /* BT */ |
1595 | si_type[intf_num] = "bt"; | 1551 | info->si_type = SI_BT; |
1596 | break; | 1552 | break; |
1597 | |||
1598 | default: | 1553 | default: |
1599 | printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n", | 1554 | printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n", |
1600 | spmi->InterfaceType); | 1555 | spmi->InterfaceType); |
1556 | kfree(info); | ||
1601 | return -EIO; | 1557 | return -EIO; |
1602 | } | 1558 | } |
1603 | 1559 | ||
1604 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
1605 | if (! info) { | ||
1606 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); | ||
1607 | return -ENOMEM; | ||
1608 | } | ||
1609 | memset(info, 0, sizeof(*info)); | ||
1610 | |||
1611 | if (spmi->InterruptType & 1) { | 1560 | if (spmi->InterruptType & 1) { |
1612 | /* We've got a GPE interrupt. */ | 1561 | /* We've got a GPE interrupt. */ |
1613 | info->irq = spmi->GPE; | 1562 | info->irq = spmi->GPE; |
1614 | info->irq_setup = acpi_gpe_irq_setup; | 1563 | info->irq_setup = acpi_gpe_irq_setup; |
1615 | info->irq_cleanup = acpi_gpe_irq_cleanup; | ||
1616 | } else if (spmi->InterruptType & 2) { | 1564 | } else if (spmi->InterruptType & 2) { |
1617 | /* We've got an APIC/SAPIC interrupt. */ | 1565 | /* We've got an APIC/SAPIC interrupt. */ |
1618 | info->irq = spmi->GlobalSystemInterrupt; | 1566 | info->irq = spmi->GlobalSystemInterrupt; |
1619 | info->irq_setup = std_irq_setup; | 1567 | info->irq_setup = std_irq_setup; |
1620 | info->irq_cleanup = std_irq_cleanup; | ||
1621 | } else { | 1568 | } else { |
1622 | /* Use the default interrupt setting. */ | 1569 | /* Use the default interrupt setting. */ |
1623 | info->irq = 0; | 1570 | info->irq = 0; |
@@ -1626,43 +1573,60 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) | |||
1626 | 1573 | ||
1627 | if (spmi->addr.register_bit_width) { | 1574 | if (spmi->addr.register_bit_width) { |
1628 | /* A (hopefully) properly formed register bit width. */ | 1575 | /* A (hopefully) properly formed register bit width. */ |
1629 | regspacings[intf_num] = spmi->addr.register_bit_width / 8; | ||
1630 | info->io.regspacing = spmi->addr.register_bit_width / 8; | 1576 | info->io.regspacing = spmi->addr.register_bit_width / 8; |
1631 | } else { | 1577 | } else { |
1632 | regspacings[intf_num] = DEFAULT_REGSPACING; | ||
1633 | info->io.regspacing = DEFAULT_REGSPACING; | 1578 | info->io.regspacing = DEFAULT_REGSPACING; |
1634 | } | 1579 | } |
1635 | regsizes[intf_num] = regspacings[intf_num]; | 1580 | info->io.regsize = info->io.regspacing; |
1636 | info->io.regsize = regsizes[intf_num]; | 1581 | info->io.regshift = spmi->addr.register_bit_offset; |
1637 | regshifts[intf_num] = spmi->addr.register_bit_offset; | ||
1638 | info->io.regshift = regshifts[intf_num]; | ||
1639 | 1582 | ||
1640 | if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | 1583 | if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
1641 | io_type = "memory"; | 1584 | io_type = "memory"; |
1642 | info->io_setup = mem_setup; | 1585 | info->io_setup = mem_setup; |
1643 | addrs[intf_num] = spmi->addr.address; | 1586 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
1644 | info->io.info = &(addrs[intf_num]); | ||
1645 | } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { | 1587 | } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { |
1646 | io_type = "I/O"; | 1588 | io_type = "I/O"; |
1647 | info->io_setup = port_setup; | 1589 | info->io_setup = port_setup; |
1648 | ports[intf_num] = spmi->addr.address; | 1590 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; |
1649 | info->io.info = &(ports[intf_num]); | ||
1650 | } else { | 1591 | } else { |
1651 | kfree(info); | 1592 | kfree(info); |
1652 | printk("ipmi_si: Unknown ACPI I/O Address type\n"); | 1593 | printk("ipmi_si: Unknown ACPI I/O Address type\n"); |
1653 | return -EIO; | 1594 | return -EIO; |
1654 | } | 1595 | } |
1596 | info->io.addr_data = spmi->addr.address; | ||
1655 | 1597 | ||
1656 | *new_info = info; | 1598 | try_smi_init(info); |
1657 | 1599 | ||
1658 | printk("ipmi_si: ACPI/SPMI specifies \"%s\" %s SI @ 0x%lx\n", | ||
1659 | si_type[intf_num], io_type, (unsigned long) spmi->addr.address); | ||
1660 | return 0; | 1600 | return 0; |
1661 | } | 1601 | } |
1602 | |||
1603 | static __devinit void acpi_find_bmc(void) | ||
1604 | { | ||
1605 | acpi_status status; | ||
1606 | struct SPMITable *spmi; | ||
1607 | int i; | ||
1608 | |||
1609 | if (acpi_disabled) | ||
1610 | return; | ||
1611 | |||
1612 | if (acpi_failure) | ||
1613 | return; | ||
1614 | |||
1615 | for (i = 0; ; i++) { | ||
1616 | status = acpi_get_firmware_table("SPMI", i+1, | ||
1617 | ACPI_LOGICAL_ADDRESSING, | ||
1618 | (struct acpi_table_header **) | ||
1619 | &spmi); | ||
1620 | if (status != AE_OK) | ||
1621 | return; | ||
1622 | |||
1623 | try_init_acpi(spmi); | ||
1624 | } | ||
1625 | } | ||
1662 | #endif | 1626 | #endif |
1663 | 1627 | ||
1664 | #ifdef CONFIG_DMI | 1628 | #ifdef CONFIG_DMI |
1665 | typedef struct dmi_ipmi_data | 1629 | struct dmi_ipmi_data |
1666 | { | 1630 | { |
1667 | u8 type; | 1631 | u8 type; |
1668 | u8 addr_space; | 1632 | u8 addr_space; |
@@ -1670,49 +1634,46 @@ typedef struct dmi_ipmi_data | |||
1670 | u8 irq; | 1634 | u8 irq; |
1671 | u8 offset; | 1635 | u8 offset; |
1672 | u8 slave_addr; | 1636 | u8 slave_addr; |
1673 | } dmi_ipmi_data_t; | 1637 | }; |
1674 | |||
1675 | static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; | ||
1676 | static int dmi_data_entries; | ||
1677 | 1638 | ||
1678 | static int __init decode_dmi(struct dmi_header *dm, int intf_num) | 1639 | static int __devinit decode_dmi(struct dmi_header *dm, |
1640 | struct dmi_ipmi_data *dmi) | ||
1679 | { | 1641 | { |
1680 | u8 *data = (u8 *)dm; | 1642 | u8 *data = (u8 *)dm; |
1681 | unsigned long base_addr; | 1643 | unsigned long base_addr; |
1682 | u8 reg_spacing; | 1644 | u8 reg_spacing; |
1683 | u8 len = dm->length; | 1645 | u8 len = dm->length; |
1684 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; | ||
1685 | 1646 | ||
1686 | ipmi_data->type = data[4]; | 1647 | dmi->type = data[4]; |
1687 | 1648 | ||
1688 | memcpy(&base_addr, data+8, sizeof(unsigned long)); | 1649 | memcpy(&base_addr, data+8, sizeof(unsigned long)); |
1689 | if (len >= 0x11) { | 1650 | if (len >= 0x11) { |
1690 | if (base_addr & 1) { | 1651 | if (base_addr & 1) { |
1691 | /* I/O */ | 1652 | /* I/O */ |
1692 | base_addr &= 0xFFFE; | 1653 | base_addr &= 0xFFFE; |
1693 | ipmi_data->addr_space = IPMI_IO_ADDR_SPACE; | 1654 | dmi->addr_space = IPMI_IO_ADDR_SPACE; |
1694 | } | 1655 | } |
1695 | else { | 1656 | else { |
1696 | /* Memory */ | 1657 | /* Memory */ |
1697 | ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE; | 1658 | dmi->addr_space = IPMI_MEM_ADDR_SPACE; |
1698 | } | 1659 | } |
1699 | /* If bit 4 of byte 0x10 is set, then the lsb for the address | 1660 | /* If bit 4 of byte 0x10 is set, then the lsb for the address |
1700 | is odd. */ | 1661 | is odd. */ |
1701 | ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); | 1662 | dmi->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); |
1702 | 1663 | ||
1703 | ipmi_data->irq = data[0x11]; | 1664 | dmi->irq = data[0x11]; |
1704 | 1665 | ||
1705 | /* The top two bits of byte 0x10 hold the register spacing. */ | 1666 | /* The top two bits of byte 0x10 hold the register spacing. */ |
1706 | reg_spacing = (data[0x10] & 0xC0) >> 6; | 1667 | reg_spacing = (data[0x10] & 0xC0) >> 6; |
1707 | switch(reg_spacing){ | 1668 | switch(reg_spacing){ |
1708 | case 0x00: /* Byte boundaries */ | 1669 | case 0x00: /* Byte boundaries */ |
1709 | ipmi_data->offset = 1; | 1670 | dmi->offset = 1; |
1710 | break; | 1671 | break; |
1711 | case 0x01: /* 32-bit boundaries */ | 1672 | case 0x01: /* 32-bit boundaries */ |
1712 | ipmi_data->offset = 4; | 1673 | dmi->offset = 4; |
1713 | break; | 1674 | break; |
1714 | case 0x02: /* 16-byte boundaries */ | 1675 | case 0x02: /* 16-byte boundaries */ |
1715 | ipmi_data->offset = 16; | 1676 | dmi->offset = 16; |
1716 | break; | 1677 | break; |
1717 | default: | 1678 | default: |
1718 | /* Some other interface, just ignore it. */ | 1679 | /* Some other interface, just ignore it. */ |
@@ -1726,205 +1687,213 @@ static int __init decode_dmi(struct dmi_header *dm, int intf_num) | |||
1726 | * wrong (and all that I have seen are I/O) so we just | 1687 | * wrong (and all that I have seen are I/O) so we just |
1727 | * ignore that bit and assume I/O. Systems that use | 1688 | * ignore that bit and assume I/O. Systems that use |
1728 | * memory should use the newer spec, anyway. */ | 1689 | * memory should use the newer spec, anyway. */ |
1729 | ipmi_data->base_addr = base_addr & 0xfffe; | 1690 | dmi->base_addr = base_addr & 0xfffe; |
1730 | ipmi_data->addr_space = IPMI_IO_ADDR_SPACE; | 1691 | dmi->addr_space = IPMI_IO_ADDR_SPACE; |
1731 | ipmi_data->offset = 1; | 1692 | dmi->offset = 1; |
1732 | } | ||
1733 | |||
1734 | ipmi_data->slave_addr = data[6]; | ||
1735 | |||
1736 | if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { | ||
1737 | dmi_data_entries++; | ||
1738 | return 0; | ||
1739 | } | 1693 | } |
1740 | 1694 | ||
1741 | memset(ipmi_data, 0, sizeof(dmi_ipmi_data_t)); | 1695 | dmi->slave_addr = data[6]; |
1742 | 1696 | ||
1743 | return -1; | 1697 | return 0; |
1744 | } | 1698 | } |
1745 | 1699 | ||
1746 | static void __init dmi_find_bmc(void) | 1700 | static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) |
1747 | { | 1701 | { |
1748 | struct dmi_device *dev = NULL; | 1702 | struct smi_info *info; |
1749 | int intf_num = 0; | ||
1750 | |||
1751 | while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { | ||
1752 | if (intf_num >= SI_MAX_DRIVERS) | ||
1753 | break; | ||
1754 | 1703 | ||
1755 | decode_dmi((struct dmi_header *) dev->device_data, intf_num++); | 1704 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
1705 | if (!info) { | ||
1706 | printk(KERN_ERR | ||
1707 | "ipmi_si: Could not allocate SI data\n"); | ||
1708 | return; | ||
1756 | } | 1709 | } |
1757 | } | ||
1758 | |||
1759 | static int try_init_smbios(int intf_num, struct smi_info **new_info) | ||
1760 | { | ||
1761 | struct smi_info *info; | ||
1762 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; | ||
1763 | char *io_type; | ||
1764 | 1710 | ||
1765 | if (intf_num >= dmi_data_entries) | 1711 | info->addr_source = "SMBIOS"; |
1766 | return -ENODEV; | ||
1767 | 1712 | ||
1768 | switch (ipmi_data->type) { | 1713 | switch (ipmi_data->type) { |
1769 | case 0x01: /* KCS */ | 1714 | case 0x01: /* KCS */ |
1770 | si_type[intf_num] = "kcs"; | 1715 | info->si_type = SI_KCS; |
1771 | break; | 1716 | break; |
1772 | case 0x02: /* SMIC */ | 1717 | case 0x02: /* SMIC */ |
1773 | si_type[intf_num] = "smic"; | 1718 | info->si_type = SI_SMIC; |
1774 | break; | 1719 | break; |
1775 | case 0x03: /* BT */ | 1720 | case 0x03: /* BT */ |
1776 | si_type[intf_num] = "bt"; | 1721 | info->si_type = SI_BT; |
1777 | break; | 1722 | break; |
1778 | default: | 1723 | default: |
1779 | return -EIO; | 1724 | return; |
1780 | } | ||
1781 | |||
1782 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
1783 | if (! info) { | ||
1784 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); | ||
1785 | return -ENOMEM; | ||
1786 | } | 1725 | } |
1787 | memset(info, 0, sizeof(*info)); | ||
1788 | 1726 | ||
1789 | if (ipmi_data->addr_space == 1) { | 1727 | switch (ipmi_data->addr_space) { |
1790 | io_type = "memory"; | 1728 | case IPMI_MEM_ADDR_SPACE: |
1791 | info->io_setup = mem_setup; | 1729 | info->io_setup = mem_setup; |
1792 | addrs[intf_num] = ipmi_data->base_addr; | 1730 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; |
1793 | info->io.info = &(addrs[intf_num]); | 1731 | break; |
1794 | } else if (ipmi_data->addr_space == 2) { | 1732 | |
1795 | io_type = "I/O"; | 1733 | case IPMI_IO_ADDR_SPACE: |
1796 | info->io_setup = port_setup; | 1734 | info->io_setup = port_setup; |
1797 | ports[intf_num] = ipmi_data->base_addr; | 1735 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
1798 | info->io.info = &(ports[intf_num]); | 1736 | break; |
1799 | } else { | 1737 | |
1738 | default: | ||
1800 | kfree(info); | 1739 | kfree(info); |
1801 | printk("ipmi_si: Unknown SMBIOS I/O Address type.\n"); | 1740 | printk(KERN_WARNING |
1802 | return -EIO; | 1741 | "ipmi_si: Unknown SMBIOS I/O Address type: %d.\n", |
1742 | ipmi_data->addr_space); | ||
1743 | return; | ||
1803 | } | 1744 | } |
1745 | info->io.addr_data = ipmi_data->base_addr; | ||
1804 | 1746 | ||
1805 | regspacings[intf_num] = ipmi_data->offset; | 1747 | info->io.regspacing = ipmi_data->offset; |
1806 | info->io.regspacing = regspacings[intf_num]; | 1748 | if (!info->io.regspacing) |
1807 | if (! info->io.regspacing) | ||
1808 | info->io.regspacing = DEFAULT_REGSPACING; | 1749 | info->io.regspacing = DEFAULT_REGSPACING; |
1809 | info->io.regsize = DEFAULT_REGSPACING; | 1750 | info->io.regsize = DEFAULT_REGSPACING; |
1810 | info->io.regshift = regshifts[intf_num]; | 1751 | info->io.regshift = 0; |
1811 | 1752 | ||
1812 | info->slave_addr = ipmi_data->slave_addr; | 1753 | info->slave_addr = ipmi_data->slave_addr; |
1813 | 1754 | ||
1814 | irqs[intf_num] = ipmi_data->irq; | 1755 | info->irq = ipmi_data->irq; |
1756 | if (info->irq) | ||
1757 | info->irq_setup = std_irq_setup; | ||
1815 | 1758 | ||
1816 | *new_info = info; | 1759 | try_smi_init(info); |
1760 | } | ||
1817 | 1761 | ||
1818 | printk("ipmi_si: Found SMBIOS-specified state machine at %s" | 1762 | static void __devinit dmi_find_bmc(void) |
1819 | " address 0x%lx, slave address 0x%x\n", | 1763 | { |
1820 | io_type, (unsigned long)ipmi_data->base_addr, | 1764 | struct dmi_device *dev = NULL; |
1821 | ipmi_data->slave_addr); | 1765 | struct dmi_ipmi_data data; |
1822 | return 0; | 1766 | int rv; |
1767 | |||
1768 | while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { | ||
1769 | rv = decode_dmi((struct dmi_header *) dev->device_data, &data); | ||
1770 | if (!rv) | ||
1771 | try_init_dmi(&data); | ||
1772 | } | ||
1823 | } | 1773 | } |
1824 | #endif /* CONFIG_DMI */ | 1774 | #endif /* CONFIG_DMI */ |
1825 | 1775 | ||
1826 | #ifdef CONFIG_PCI | 1776 | #ifdef CONFIG_PCI |
1827 | 1777 | ||
1828 | #define PCI_ERMC_CLASSCODE 0x0C0700 | 1778 | #define PCI_ERMC_CLASSCODE 0x0C0700 |
1779 | #define PCI_ERMC_CLASSCODE_MASK 0xffffff00 | ||
1780 | #define PCI_ERMC_CLASSCODE_TYPE_MASK 0xff | ||
1781 | #define PCI_ERMC_CLASSCODE_TYPE_SMIC 0x00 | ||
1782 | #define PCI_ERMC_CLASSCODE_TYPE_KCS 0x01 | ||
1783 | #define PCI_ERMC_CLASSCODE_TYPE_BT 0x02 | ||
1784 | |||
1829 | #define PCI_HP_VENDOR_ID 0x103C | 1785 | #define PCI_HP_VENDOR_ID 0x103C |
1830 | #define PCI_MMC_DEVICE_ID 0x121A | 1786 | #define PCI_MMC_DEVICE_ID 0x121A |
1831 | #define PCI_MMC_ADDR_CW 0x10 | 1787 | #define PCI_MMC_ADDR_CW 0x10 |
1832 | 1788 | ||
1833 | /* Avoid more than one attempt to probe pci smic. */ | 1789 | static void ipmi_pci_cleanup(struct smi_info *info) |
1834 | static int pci_smic_checked = 0; | 1790 | { |
1791 | struct pci_dev *pdev = info->addr_source_data; | ||
1792 | |||
1793 | pci_disable_device(pdev); | ||
1794 | } | ||
1835 | 1795 | ||
1836 | static int find_pci_smic(int intf_num, struct smi_info **new_info) | 1796 | static int __devinit ipmi_pci_probe(struct pci_dev *pdev, |
1797 | const struct pci_device_id *ent) | ||
1837 | { | 1798 | { |
1838 | struct smi_info *info; | 1799 | int rv; |
1839 | int error; | 1800 | int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; |
1840 | struct pci_dev *pci_dev = NULL; | 1801 | struct smi_info *info; |
1841 | u16 base_addr; | 1802 | int first_reg_offset = 0; |
1842 | int fe_rmc = 0; | ||
1843 | 1803 | ||
1844 | if (pci_smic_checked) | 1804 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
1845 | return -ENODEV; | 1805 | if (!info) |
1806 | return ENOMEM; | ||
1846 | 1807 | ||
1847 | pci_smic_checked = 1; | 1808 | info->addr_source = "PCI"; |
1848 | 1809 | ||
1849 | pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL); | 1810 | switch (class_type) { |
1850 | if (! pci_dev) { | 1811 | case PCI_ERMC_CLASSCODE_TYPE_SMIC: |
1851 | pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL); | 1812 | info->si_type = SI_SMIC; |
1852 | if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)) | 1813 | break; |
1853 | fe_rmc = 1; | ||
1854 | else | ||
1855 | return -ENODEV; | ||
1856 | } | ||
1857 | 1814 | ||
1858 | error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); | 1815 | case PCI_ERMC_CLASSCODE_TYPE_KCS: |
1859 | if (error) | 1816 | info->si_type = SI_KCS; |
1860 | { | 1817 | break; |
1861 | pci_dev_put(pci_dev); | 1818 | |
1862 | printk(KERN_ERR | 1819 | case PCI_ERMC_CLASSCODE_TYPE_BT: |
1863 | "ipmi_si: pci_read_config_word() failed (%d).\n", | 1820 | info->si_type = SI_BT; |
1864 | error); | 1821 | break; |
1865 | return -ENODEV; | 1822 | |
1823 | default: | ||
1824 | kfree(info); | ||
1825 | printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n", | ||
1826 | pci_name(pdev), class_type); | ||
1827 | return ENOMEM; | ||
1866 | } | 1828 | } |
1867 | 1829 | ||
1868 | /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ | 1830 | rv = pci_enable_device(pdev); |
1869 | if (! (base_addr & 0x0001)) | 1831 | if (rv) { |
1870 | { | 1832 | printk(KERN_ERR "ipmi_si: %s: couldn't enable PCI device\n", |
1871 | pci_dev_put(pci_dev); | 1833 | pci_name(pdev)); |
1872 | printk(KERN_ERR | 1834 | kfree(info); |
1873 | "ipmi_si: memory mapped I/O not supported for PCI" | 1835 | return rv; |
1874 | " smic.\n"); | ||
1875 | return -ENODEV; | ||
1876 | } | 1836 | } |
1877 | 1837 | ||
1878 | base_addr &= 0xFFFE; | 1838 | info->addr_source_cleanup = ipmi_pci_cleanup; |
1879 | if (! fe_rmc) | 1839 | info->addr_source_data = pdev; |
1880 | /* Data register starts at base address + 1 in eRMC */ | ||
1881 | ++base_addr; | ||
1882 | 1840 | ||
1883 | if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { | 1841 | if (pdev->subsystem_vendor == PCI_HP_VENDOR_ID) |
1884 | pci_dev_put(pci_dev); | 1842 | first_reg_offset = 1; |
1885 | return -ENODEV; | ||
1886 | } | ||
1887 | 1843 | ||
1888 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1844 | if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { |
1889 | if (! info) { | 1845 | info->io_setup = port_setup; |
1890 | pci_dev_put(pci_dev); | 1846 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
1891 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); | 1847 | } else { |
1892 | return -ENOMEM; | 1848 | info->io_setup = mem_setup; |
1849 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | ||
1893 | } | 1850 | } |
1894 | memset(info, 0, sizeof(*info)); | 1851 | info->io.addr_data = pci_resource_start(pdev, 0); |
1895 | 1852 | ||
1896 | info->io_setup = port_setup; | 1853 | info->io.regspacing = DEFAULT_REGSPACING; |
1897 | ports[intf_num] = base_addr; | ||
1898 | info->io.info = &(ports[intf_num]); | ||
1899 | info->io.regspacing = regspacings[intf_num]; | ||
1900 | if (! info->io.regspacing) | ||
1901 | info->io.regspacing = DEFAULT_REGSPACING; | ||
1902 | info->io.regsize = DEFAULT_REGSPACING; | 1854 | info->io.regsize = DEFAULT_REGSPACING; |
1903 | info->io.regshift = regshifts[intf_num]; | 1855 | info->io.regshift = 0; |
1904 | 1856 | ||
1905 | *new_info = info; | 1857 | info->irq = pdev->irq; |
1858 | if (info->irq) | ||
1859 | info->irq_setup = std_irq_setup; | ||
1906 | 1860 | ||
1907 | irqs[intf_num] = pci_dev->irq; | 1861 | return try_smi_init(info); |
1908 | si_type[intf_num] = "smic"; | 1862 | } |
1909 | 1863 | ||
1910 | printk("ipmi_si: Found PCI SMIC at I/O address 0x%lx\n", | 1864 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) |
1911 | (long unsigned int) base_addr); | 1865 | { |
1866 | } | ||
1912 | 1867 | ||
1913 | pci_dev_put(pci_dev); | 1868 | #ifdef CONFIG_PM |
1869 | static int ipmi_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1870 | { | ||
1914 | return 0; | 1871 | return 0; |
1915 | } | 1872 | } |
1916 | #endif /* CONFIG_PCI */ | ||
1917 | 1873 | ||
1918 | static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) | 1874 | static int ipmi_pci_resume(struct pci_dev *pdev) |
1919 | { | 1875 | { |
1920 | #ifdef CONFIG_PCI | 1876 | return 0; |
1921 | if (find_pci_smic(intf_num, new_info) == 0) | 1877 | } |
1922 | return 0; | ||
1923 | #endif | 1878 | #endif |
1924 | /* Include other methods here. */ | ||
1925 | 1879 | ||
1926 | return -ENODEV; | 1880 | static struct pci_device_id ipmi_pci_devices[] = { |
1927 | } | 1881 | { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, |
1882 | { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE) } | ||
1883 | }; | ||
1884 | MODULE_DEVICE_TABLE(pci, ipmi_pci_devices); | ||
1885 | |||
1886 | static struct pci_driver ipmi_pci_driver = { | ||
1887 | .name = DEVICE_NAME, | ||
1888 | .id_table = ipmi_pci_devices, | ||
1889 | .probe = ipmi_pci_probe, | ||
1890 | .remove = __devexit_p(ipmi_pci_remove), | ||
1891 | #ifdef CONFIG_PM | ||
1892 | .suspend = ipmi_pci_suspend, | ||
1893 | .resume = ipmi_pci_resume, | ||
1894 | #endif | ||
1895 | }; | ||
1896 | #endif /* CONFIG_PCI */ | ||
1928 | 1897 | ||
1929 | 1898 | ||
1930 | static int try_get_dev_id(struct smi_info *smi_info) | 1899 | static int try_get_dev_id(struct smi_info *smi_info) |
@@ -1936,7 +1905,7 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
1936 | int rv = 0; | 1905 | int rv = 0; |
1937 | 1906 | ||
1938 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); | 1907 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); |
1939 | if (! resp) | 1908 | if (!resp) |
1940 | return -ENOMEM; | 1909 | return -ENOMEM; |
1941 | 1910 | ||
1942 | /* Do a Get Device ID command, since it comes back with some | 1911 | /* Do a Get Device ID command, since it comes back with some |
@@ -2018,7 +1987,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
2018 | struct smi_info *smi = data; | 1987 | struct smi_info *smi = data; |
2019 | 1988 | ||
2020 | out += sprintf(out, "interrupts_enabled: %d\n", | 1989 | out += sprintf(out, "interrupts_enabled: %d\n", |
2021 | smi->irq && ! smi->interrupt_disabled); | 1990 | smi->irq && !smi->interrupt_disabled); |
2022 | out += sprintf(out, "short_timeouts: %ld\n", | 1991 | out += sprintf(out, "short_timeouts: %ld\n", |
2023 | smi->short_timeouts); | 1992 | smi->short_timeouts); |
2024 | out += sprintf(out, "long_timeouts: %ld\n", | 1993 | out += sprintf(out, "long_timeouts: %ld\n", |
@@ -2094,7 +2063,7 @@ static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) | |||
2094 | { | 2063 | { |
2095 | struct ipmi_device_id *id = &smi_info->device_id; | 2064 | struct ipmi_device_id *id = &smi_info->device_id; |
2096 | const char mfr[3]=DELL_IANA_MFR_ID; | 2065 | const char mfr[3]=DELL_IANA_MFR_ID; |
2097 | if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr))) { | 2066 | if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr))) { |
2098 | if (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID && | 2067 | if (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID && |
2099 | id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV && | 2068 | id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV && |
2100 | id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) { | 2069 | id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) { |
@@ -2170,7 +2139,7 @@ setup_dell_poweredge_bt_xaction_handler(struct smi_info *smi_info) | |||
2170 | { | 2139 | { |
2171 | struct ipmi_device_id *id = &smi_info->device_id; | 2140 | struct ipmi_device_id *id = &smi_info->device_id; |
2172 | const char mfr[3]=DELL_IANA_MFR_ID; | 2141 | const char mfr[3]=DELL_IANA_MFR_ID; |
2173 | if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) && | 2142 | if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr)) && |
2174 | smi_info->si_type == SI_BT) | 2143 | smi_info->si_type == SI_BT) |
2175 | register_xaction_notifier(&dell_poweredge_bt_xaction_notifier); | 2144 | register_xaction_notifier(&dell_poweredge_bt_xaction_notifier); |
2176 | } | 2145 | } |
@@ -2200,62 +2169,110 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info) | |||
2200 | del_timer_sync(&smi_info->si_timer); | 2169 | del_timer_sync(&smi_info->si_timer); |
2201 | } | 2170 | } |
2202 | 2171 | ||
2203 | /* Returns 0 if initialized, or negative on an error. */ | 2172 | static struct ipmi_default_vals |
2204 | static int init_one_smi(int intf_num, struct smi_info **smi) | 2173 | { |
2174 | int type; | ||
2175 | int port; | ||
2176 | } __devinit ipmi_defaults[] = | ||
2177 | { | ||
2178 | { .type = SI_KCS, .port = 0xca2 }, | ||
2179 | { .type = SI_SMIC, .port = 0xca9 }, | ||
2180 | { .type = SI_BT, .port = 0xe4 }, | ||
2181 | { .port = 0 } | ||
2182 | }; | ||
2183 | |||
2184 | static __devinit void default_find_bmc(void) | ||
2185 | { | ||
2186 | struct smi_info *info; | ||
2187 | int i; | ||
2188 | |||
2189 | for (i = 0; ; i++) { | ||
2190 | if (!ipmi_defaults[i].port) | ||
2191 | break; | ||
2192 | |||
2193 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
2194 | if (!info) | ||
2195 | return; | ||
2196 | |||
2197 | info->addr_source = NULL; | ||
2198 | |||
2199 | info->si_type = ipmi_defaults[i].type; | ||
2200 | info->io_setup = port_setup; | ||
2201 | info->io.addr_data = ipmi_defaults[i].port; | ||
2202 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | ||
2203 | |||
2204 | info->io.addr = NULL; | ||
2205 | info->io.regspacing = DEFAULT_REGSPACING; | ||
2206 | info->io.regsize = DEFAULT_REGSPACING; | ||
2207 | info->io.regshift = 0; | ||
2208 | |||
2209 | if (try_smi_init(info) == 0) { | ||
2210 | /* Found one... */ | ||
2211 | printk(KERN_INFO "ipmi_si: Found default %s state" | ||
2212 | " machine at %s address 0x%lx\n", | ||
2213 | si_to_str[info->si_type], | ||
2214 | addr_space_to_str[info->io.addr_type], | ||
2215 | info->io.addr_data); | ||
2216 | return; | ||
2217 | } | ||
2218 | } | ||
2219 | } | ||
2220 | |||
2221 | static int is_new_interface(struct smi_info *info) | ||
2205 | { | 2222 | { |
2206 | int rv; | 2223 | struct smi_info *e; |
2207 | struct smi_info *new_smi; | ||
2208 | 2224 | ||
2225 | list_for_each_entry(e, &smi_infos, link) { | ||
2226 | if (e->io.addr_type != info->io.addr_type) | ||
2227 | continue; | ||
2228 | if (e->io.addr_data == info->io.addr_data) | ||
2229 | return 0; | ||
2230 | } | ||
2209 | 2231 | ||
2210 | rv = try_init_mem(intf_num, &new_smi); | 2232 | return 1; |
2211 | if (rv) | 2233 | } |
2212 | rv = try_init_port(intf_num, &new_smi); | ||
2213 | #ifdef CONFIG_ACPI | ||
2214 | if (rv && si_trydefaults) | ||
2215 | rv = try_init_acpi(intf_num, &new_smi); | ||
2216 | #endif | ||
2217 | #ifdef CONFIG_DMI | ||
2218 | if (rv && si_trydefaults) | ||
2219 | rv = try_init_smbios(intf_num, &new_smi); | ||
2220 | #endif | ||
2221 | if (rv && si_trydefaults) | ||
2222 | rv = try_init_plug_and_play(intf_num, &new_smi); | ||
2223 | 2234 | ||
2224 | if (rv) | 2235 | static int try_smi_init(struct smi_info *new_smi) |
2225 | return rv; | 2236 | { |
2237 | int rv; | ||
2238 | |||
2239 | if (new_smi->addr_source) { | ||
2240 | printk(KERN_INFO "ipmi_si: Trying %s-specified %s state" | ||
2241 | " machine at %s address 0x%lx, slave address 0x%x," | ||
2242 | " irq %d\n", | ||
2243 | new_smi->addr_source, | ||
2244 | si_to_str[new_smi->si_type], | ||
2245 | addr_space_to_str[new_smi->io.addr_type], | ||
2246 | new_smi->io.addr_data, | ||
2247 | new_smi->slave_addr, new_smi->irq); | ||
2248 | } | ||
2249 | |||
2250 | down(&smi_infos_lock); | ||
2251 | if (!is_new_interface(new_smi)) { | ||
2252 | printk(KERN_WARNING "ipmi_si: duplicate interface\n"); | ||
2253 | rv = -EBUSY; | ||
2254 | goto out_err; | ||
2255 | } | ||
2226 | 2256 | ||
2227 | /* So we know not to free it unless we have allocated one. */ | 2257 | /* So we know not to free it unless we have allocated one. */ |
2228 | new_smi->intf = NULL; | 2258 | new_smi->intf = NULL; |
2229 | new_smi->si_sm = NULL; | 2259 | new_smi->si_sm = NULL; |
2230 | new_smi->handlers = NULL; | 2260 | new_smi->handlers = NULL; |
2231 | 2261 | ||
2232 | if (! new_smi->irq_setup) { | 2262 | switch (new_smi->si_type) { |
2233 | new_smi->irq = irqs[intf_num]; | 2263 | case SI_KCS: |
2234 | new_smi->irq_setup = std_irq_setup; | ||
2235 | new_smi->irq_cleanup = std_irq_cleanup; | ||
2236 | } | ||
2237 | |||
2238 | /* Default to KCS if no type is specified. */ | ||
2239 | if (si_type[intf_num] == NULL) { | ||
2240 | if (si_trydefaults) | ||
2241 | si_type[intf_num] = "kcs"; | ||
2242 | else { | ||
2243 | rv = -EINVAL; | ||
2244 | goto out_err; | ||
2245 | } | ||
2246 | } | ||
2247 | |||
2248 | /* Set up the state machine to use. */ | ||
2249 | if (strcmp(si_type[intf_num], "kcs") == 0) { | ||
2250 | new_smi->handlers = &kcs_smi_handlers; | 2264 | new_smi->handlers = &kcs_smi_handlers; |
2251 | new_smi->si_type = SI_KCS; | 2265 | break; |
2252 | } else if (strcmp(si_type[intf_num], "smic") == 0) { | 2266 | |
2267 | case SI_SMIC: | ||
2253 | new_smi->handlers = &smic_smi_handlers; | 2268 | new_smi->handlers = &smic_smi_handlers; |
2254 | new_smi->si_type = SI_SMIC; | 2269 | break; |
2255 | } else if (strcmp(si_type[intf_num], "bt") == 0) { | 2270 | |
2271 | case SI_BT: | ||
2256 | new_smi->handlers = &bt_smi_handlers; | 2272 | new_smi->handlers = &bt_smi_handlers; |
2257 | new_smi->si_type = SI_BT; | 2273 | break; |
2258 | } else { | 2274 | |
2275 | default: | ||
2259 | /* No support for anything else yet. */ | 2276 | /* No support for anything else yet. */ |
2260 | rv = -EIO; | 2277 | rv = -EIO; |
2261 | goto out_err; | 2278 | goto out_err; |
@@ -2263,7 +2280,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2263 | 2280 | ||
2264 | /* Allocate the state machine's data and initialize it. */ | 2281 | /* Allocate the state machine's data and initialize it. */ |
2265 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); | 2282 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); |
2266 | if (! new_smi->si_sm) { | 2283 | if (!new_smi->si_sm) { |
2267 | printk(" Could not allocate state machine memory\n"); | 2284 | printk(" Could not allocate state machine memory\n"); |
2268 | rv = -ENOMEM; | 2285 | rv = -ENOMEM; |
2269 | goto out_err; | 2286 | goto out_err; |
@@ -2284,21 +2301,29 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2284 | 2301 | ||
2285 | /* Do low-level detection first. */ | 2302 | /* Do low-level detection first. */ |
2286 | if (new_smi->handlers->detect(new_smi->si_sm)) { | 2303 | if (new_smi->handlers->detect(new_smi->si_sm)) { |
2304 | if (new_smi->addr_source) | ||
2305 | printk(KERN_INFO "ipmi_si: Interface detection" | ||
2306 | " failed\n"); | ||
2287 | rv = -ENODEV; | 2307 | rv = -ENODEV; |
2288 | goto out_err; | 2308 | goto out_err; |
2289 | } | 2309 | } |
2290 | 2310 | ||
2291 | /* Attempt a get device id command. If it fails, we probably | 2311 | /* Attempt a get device id command. If it fails, we probably |
2292 | don't have a SMI here. */ | 2312 | don't have a BMC here. */ |
2293 | rv = try_get_dev_id(new_smi); | 2313 | rv = try_get_dev_id(new_smi); |
2294 | if (rv) | 2314 | if (rv) { |
2315 | if (new_smi->addr_source) | ||
2316 | printk(KERN_INFO "ipmi_si: There appears to be no BMC" | ||
2317 | " at this location\n"); | ||
2295 | goto out_err; | 2318 | goto out_err; |
2319 | } | ||
2296 | 2320 | ||
2297 | setup_oem_data_handler(new_smi); | 2321 | setup_oem_data_handler(new_smi); |
2298 | setup_xaction_handlers(new_smi); | 2322 | setup_xaction_handlers(new_smi); |
2299 | 2323 | ||
2300 | /* Try to claim any interrupts. */ | 2324 | /* Try to claim any interrupts. */ |
2301 | new_smi->irq_setup(new_smi); | 2325 | if (new_smi->irq_setup) |
2326 | new_smi->irq_setup(new_smi); | ||
2302 | 2327 | ||
2303 | INIT_LIST_HEAD(&(new_smi->xmit_msgs)); | 2328 | INIT_LIST_HEAD(&(new_smi->xmit_msgs)); |
2304 | INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs)); | 2329 | INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs)); |
@@ -2308,7 +2333,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2308 | 2333 | ||
2309 | new_smi->interrupt_disabled = 0; | 2334 | new_smi->interrupt_disabled = 0; |
2310 | atomic_set(&new_smi->stop_operation, 0); | 2335 | atomic_set(&new_smi->stop_operation, 0); |
2311 | new_smi->intf_num = intf_num; | 2336 | new_smi->intf_num = smi_num; |
2337 | smi_num++; | ||
2312 | 2338 | ||
2313 | /* Start clearing the flags before we enable interrupts or the | 2339 | /* Start clearing the flags before we enable interrupts or the |
2314 | timer to avoid racing with the timer. */ | 2340 | timer to avoid racing with the timer. */ |
@@ -2365,9 +2391,11 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2365 | goto out_err_stop_timer; | 2391 | goto out_err_stop_timer; |
2366 | } | 2392 | } |
2367 | 2393 | ||
2368 | *smi = new_smi; | 2394 | list_add_tail(&new_smi->link, &smi_infos); |
2395 | |||
2396 | up(&smi_infos_lock); | ||
2369 | 2397 | ||
2370 | printk(" IPMI %s interface initialized\n", si_type[intf_num]); | 2398 | printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); |
2371 | 2399 | ||
2372 | return 0; | 2400 | return 0; |
2373 | 2401 | ||
@@ -2379,7 +2407,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2379 | if (new_smi->intf) | 2407 | if (new_smi->intf) |
2380 | ipmi_unregister_smi(new_smi->intf); | 2408 | ipmi_unregister_smi(new_smi->intf); |
2381 | 2409 | ||
2382 | new_smi->irq_cleanup(new_smi); | 2410 | if (new_smi->irq_cleanup) |
2411 | new_smi->irq_cleanup(new_smi); | ||
2383 | 2412 | ||
2384 | /* Wait until we know that we are out of any interrupt | 2413 | /* Wait until we know that we are out of any interrupt |
2385 | handlers might have been running before we freed the | 2414 | handlers might have been running before we freed the |
@@ -2391,16 +2420,18 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2391 | new_smi->handlers->cleanup(new_smi->si_sm); | 2420 | new_smi->handlers->cleanup(new_smi->si_sm); |
2392 | kfree(new_smi->si_sm); | 2421 | kfree(new_smi->si_sm); |
2393 | } | 2422 | } |
2423 | if (new_smi->addr_source_cleanup) | ||
2424 | new_smi->addr_source_cleanup(new_smi); | ||
2394 | if (new_smi->io_cleanup) | 2425 | if (new_smi->io_cleanup) |
2395 | new_smi->io_cleanup(new_smi); | 2426 | new_smi->io_cleanup(new_smi); |
2396 | 2427 | ||
2428 | up(&smi_infos_lock); | ||
2429 | |||
2397 | return rv; | 2430 | return rv; |
2398 | } | 2431 | } |
2399 | 2432 | ||
2400 | static __init int init_ipmi_si(void) | 2433 | static __devinit int init_ipmi_si(void) |
2401 | { | 2434 | { |
2402 | int rv = 0; | ||
2403 | int pos = 0; | ||
2404 | int i; | 2435 | int i; |
2405 | char *str; | 2436 | char *str; |
2406 | 2437 | ||
@@ -2425,63 +2456,66 @@ static __init int init_ipmi_si(void) | |||
2425 | 2456 | ||
2426 | printk(KERN_INFO "IPMI System Interface driver.\n"); | 2457 | printk(KERN_INFO "IPMI System Interface driver.\n"); |
2427 | 2458 | ||
2459 | hardcode_find_bmc(); | ||
2460 | |||
2428 | #ifdef CONFIG_DMI | 2461 | #ifdef CONFIG_DMI |
2429 | dmi_find_bmc(); | 2462 | dmi_find_bmc(); |
2430 | #endif | 2463 | #endif |
2431 | 2464 | ||
2432 | rv = init_one_smi(0, &(smi_infos[pos])); | 2465 | #ifdef CONFIG_ACPI |
2433 | if (rv && ! ports[0] && si_trydefaults) { | 2466 | if (si_trydefaults) |
2434 | /* If we are trying defaults and the initial port is | 2467 | acpi_find_bmc(); |
2435 | not set, then set it. */ | 2468 | #endif |
2436 | si_type[0] = "kcs"; | ||
2437 | ports[0] = DEFAULT_KCS_IO_PORT; | ||
2438 | rv = init_one_smi(0, &(smi_infos[pos])); | ||
2439 | if (rv) { | ||
2440 | /* No KCS - try SMIC */ | ||
2441 | si_type[0] = "smic"; | ||
2442 | ports[0] = DEFAULT_SMIC_IO_PORT; | ||
2443 | rv = init_one_smi(0, &(smi_infos[pos])); | ||
2444 | } | ||
2445 | if (rv) { | ||
2446 | /* No SMIC - try BT */ | ||
2447 | si_type[0] = "bt"; | ||
2448 | ports[0] = DEFAULT_BT_IO_PORT; | ||
2449 | rv = init_one_smi(0, &(smi_infos[pos])); | ||
2450 | } | ||
2451 | } | ||
2452 | if (rv == 0) | ||
2453 | pos++; | ||
2454 | 2469 | ||
2455 | for (i = 1; i < SI_MAX_PARMS; i++) { | 2470 | #ifdef CONFIG_PCI |
2456 | rv = init_one_smi(i, &(smi_infos[pos])); | 2471 | pci_module_init(&ipmi_pci_driver); |
2457 | if (rv == 0) | 2472 | #endif |
2458 | pos++; | 2473 | |
2474 | if (si_trydefaults) { | ||
2475 | down(&smi_infos_lock); | ||
2476 | if (list_empty(&smi_infos)) { | ||
2477 | /* No BMC was found, try defaults. */ | ||
2478 | up(&smi_infos_lock); | ||
2479 | default_find_bmc(); | ||
2480 | } else { | ||
2481 | up(&smi_infos_lock); | ||
2482 | } | ||
2459 | } | 2483 | } |
2460 | 2484 | ||
2461 | if (smi_infos[0] == NULL) { | 2485 | down(&smi_infos_lock); |
2486 | if (list_empty(&smi_infos)) { | ||
2487 | up(&smi_infos_lock); | ||
2488 | #ifdef CONFIG_PCI | ||
2489 | pci_unregister_driver(&ipmi_pci_driver); | ||
2490 | #endif | ||
2462 | printk("ipmi_si: Unable to find any System Interface(s)\n"); | 2491 | printk("ipmi_si: Unable to find any System Interface(s)\n"); |
2463 | return -ENODEV; | 2492 | return -ENODEV; |
2493 | } else { | ||
2494 | up(&smi_infos_lock); | ||
2495 | return 0; | ||
2464 | } | 2496 | } |
2465 | |||
2466 | return 0; | ||
2467 | } | 2497 | } |
2468 | module_init(init_ipmi_si); | 2498 | module_init(init_ipmi_si); |
2469 | 2499 | ||
2470 | static void __exit cleanup_one_si(struct smi_info *to_clean) | 2500 | static void __devexit cleanup_one_si(struct smi_info *to_clean) |
2471 | { | 2501 | { |
2472 | int rv; | 2502 | int rv; |
2473 | unsigned long flags; | 2503 | unsigned long flags; |
2474 | 2504 | ||
2475 | if (! to_clean) | 2505 | if (!to_clean) |
2476 | return; | 2506 | return; |
2477 | 2507 | ||
2508 | list_del(&to_clean->link); | ||
2509 | |||
2478 | /* Tell the timer and interrupt handlers that we are shutting | 2510 | /* Tell the timer and interrupt handlers that we are shutting |
2479 | down. */ | 2511 | down. */ |
2480 | spin_lock_irqsave(&(to_clean->si_lock), flags); | 2512 | spin_lock_irqsave(&(to_clean->si_lock), flags); |
2481 | spin_lock(&(to_clean->msg_lock)); | 2513 | spin_lock(&(to_clean->msg_lock)); |
2482 | 2514 | ||
2483 | atomic_inc(&to_clean->stop_operation); | 2515 | atomic_inc(&to_clean->stop_operation); |
2484 | to_clean->irq_cleanup(to_clean); | 2516 | |
2517 | if (to_clean->irq_cleanup) | ||
2518 | to_clean->irq_cleanup(to_clean); | ||
2485 | 2519 | ||
2486 | spin_unlock(&(to_clean->msg_lock)); | 2520 | spin_unlock(&(to_clean->msg_lock)); |
2487 | spin_unlock_irqrestore(&(to_clean->si_lock), flags); | 2521 | spin_unlock_irqrestore(&(to_clean->si_lock), flags); |
@@ -2511,20 +2545,27 @@ static void __exit cleanup_one_si(struct smi_info *to_clean) | |||
2511 | 2545 | ||
2512 | kfree(to_clean->si_sm); | 2546 | kfree(to_clean->si_sm); |
2513 | 2547 | ||
2548 | if (to_clean->addr_source_cleanup) | ||
2549 | to_clean->addr_source_cleanup(to_clean); | ||
2514 | if (to_clean->io_cleanup) | 2550 | if (to_clean->io_cleanup) |
2515 | to_clean->io_cleanup(to_clean); | 2551 | to_clean->io_cleanup(to_clean); |
2516 | } | 2552 | } |
2517 | 2553 | ||
2518 | static __exit void cleanup_ipmi_si(void) | 2554 | static __exit void cleanup_ipmi_si(void) |
2519 | { | 2555 | { |
2520 | int i; | 2556 | struct smi_info *e, *tmp_e; |
2521 | 2557 | ||
2522 | if (! initialized) | 2558 | if (!initialized) |
2523 | return; | 2559 | return; |
2524 | 2560 | ||
2525 | for (i = 0; i < SI_MAX_DRIVERS; i++) { | 2561 | #ifdef CONFIG_PCI |
2526 | cleanup_one_si(smi_infos[i]); | 2562 | pci_unregister_driver(&ipmi_pci_driver); |
2527 | } | 2563 | #endif |
2564 | |||
2565 | down(&smi_infos_lock); | ||
2566 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) | ||
2567 | cleanup_one_si(e); | ||
2568 | up(&smi_infos_lock); | ||
2528 | } | 2569 | } |
2529 | module_exit(cleanup_ipmi_si); | 2570 | module_exit(cleanup_ipmi_si); |
2530 | 2571 | ||
diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h index bf3d4962d6a5..4b731b24dc16 100644 --- a/drivers/char/ipmi/ipmi_si_sm.h +++ b/drivers/char/ipmi/ipmi_si_sm.h | |||
@@ -50,11 +50,12 @@ struct si_sm_io | |||
50 | 50 | ||
51 | /* Generic info used by the actual handling routines, the | 51 | /* Generic info used by the actual handling routines, the |
52 | state machine shouldn't touch these. */ | 52 | state machine shouldn't touch these. */ |
53 | void *info; | ||
54 | void __iomem *addr; | 53 | void __iomem *addr; |
55 | int regspacing; | 54 | int regspacing; |
56 | int regsize; | 55 | int regsize; |
57 | int regshift; | 56 | int regshift; |
57 | int addr_type; | ||
58 | long addr_data; | ||
58 | }; | 59 | }; |
59 | 60 | ||
60 | /* Results of SMI events. */ | 61 | /* Results of SMI events. */ |