diff options
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 155 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_watchdog.c | 11 | ||||
-rw-r--r-- | include/linux/ipmi.h | 6 |
3 files changed, 130 insertions, 42 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index d92767225b15..89b72425f9ce 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -272,6 +272,9 @@ struct bmc_device { | |||
272 | }; | 272 | }; |
273 | #define to_bmc_device(x) container_of((x), struct bmc_device, pdev.dev) | 273 | #define to_bmc_device(x) container_of((x), struct bmc_device, pdev.dev) |
274 | 274 | ||
275 | static int bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc, | ||
276 | struct ipmi_device_id *id); | ||
277 | |||
275 | /* | 278 | /* |
276 | * Various statistics for IPMI, these index stats[] in the ipmi_smi | 279 | * Various statistics for IPMI, these index stats[] in the ipmi_smi |
277 | * structure. | 280 | * structure. |
@@ -396,10 +399,6 @@ struct ipmi_smi { | |||
396 | */ | 399 | */ |
397 | struct list_head users; | 400 | struct list_head users; |
398 | 401 | ||
399 | /* Information to supply to users. */ | ||
400 | unsigned char ipmi_version_major; | ||
401 | unsigned char ipmi_version_minor; | ||
402 | |||
403 | /* Used for wake ups at startup. */ | 402 | /* Used for wake ups at startup. */ |
404 | wait_queue_head_t waitq; | 403 | wait_queue_head_t waitq; |
405 | 404 | ||
@@ -1194,12 +1193,21 @@ int ipmi_destroy_user(ipmi_user_t user) | |||
1194 | } | 1193 | } |
1195 | EXPORT_SYMBOL(ipmi_destroy_user); | 1194 | EXPORT_SYMBOL(ipmi_destroy_user); |
1196 | 1195 | ||
1197 | void ipmi_get_version(ipmi_user_t user, | 1196 | int ipmi_get_version(ipmi_user_t user, |
1198 | unsigned char *major, | 1197 | unsigned char *major, |
1199 | unsigned char *minor) | 1198 | unsigned char *minor) |
1200 | { | 1199 | { |
1201 | *major = user->intf->ipmi_version_major; | 1200 | struct ipmi_device_id id; |
1202 | *minor = user->intf->ipmi_version_minor; | 1201 | int rv; |
1202 | |||
1203 | rv = bmc_get_device_id(user->intf, NULL, &id); | ||
1204 | if (rv) | ||
1205 | return rv; | ||
1206 | |||
1207 | *major = ipmi_version_major(&id); | ||
1208 | *minor = ipmi_version_minor(&id); | ||
1209 | |||
1210 | return 0; | ||
1203 | } | 1211 | } |
1204 | EXPORT_SYMBOL(ipmi_get_version); | 1212 | EXPORT_SYMBOL(ipmi_get_version); |
1205 | 1213 | ||
@@ -2072,6 +2080,16 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
2072 | } | 2080 | } |
2073 | EXPORT_SYMBOL(ipmi_request_supply_msgs); | 2081 | EXPORT_SYMBOL(ipmi_request_supply_msgs); |
2074 | 2082 | ||
2083 | static int bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc, | ||
2084 | struct ipmi_device_id *id) | ||
2085 | { | ||
2086 | if (!bmc) | ||
2087 | bmc = intf->bmc; | ||
2088 | |||
2089 | *id = bmc->id; | ||
2090 | return 0; | ||
2091 | } | ||
2092 | |||
2075 | #ifdef CONFIG_PROC_FS | 2093 | #ifdef CONFIG_PROC_FS |
2076 | static int smi_ipmb_proc_show(struct seq_file *m, void *v) | 2094 | static int smi_ipmb_proc_show(struct seq_file *m, void *v) |
2077 | { | 2095 | { |
@@ -2101,10 +2119,16 @@ static const struct file_operations smi_ipmb_proc_ops = { | |||
2101 | static int smi_version_proc_show(struct seq_file *m, void *v) | 2119 | static int smi_version_proc_show(struct seq_file *m, void *v) |
2102 | { | 2120 | { |
2103 | ipmi_smi_t intf = m->private; | 2121 | ipmi_smi_t intf = m->private; |
2122 | struct ipmi_device_id id; | ||
2123 | int rv; | ||
2124 | |||
2125 | rv = bmc_get_device_id(intf, NULL, &id); | ||
2126 | if (rv) | ||
2127 | return rv; | ||
2104 | 2128 | ||
2105 | seq_printf(m, "%u.%u\n", | 2129 | seq_printf(m, "%u.%u\n", |
2106 | ipmi_version_major(&intf->bmc->id), | 2130 | ipmi_version_major(&id), |
2107 | ipmi_version_minor(&intf->bmc->id)); | 2131 | ipmi_version_minor(&id)); |
2108 | 2132 | ||
2109 | return 0; | 2133 | return 0; |
2110 | } | 2134 | } |
@@ -2287,8 +2311,14 @@ static ssize_t device_id_show(struct device *dev, | |||
2287 | char *buf) | 2311 | char *buf) |
2288 | { | 2312 | { |
2289 | struct bmc_device *bmc = to_bmc_device(dev); | 2313 | struct bmc_device *bmc = to_bmc_device(dev); |
2314 | struct ipmi_device_id id; | ||
2315 | int rv; | ||
2316 | |||
2317 | rv = bmc_get_device_id(NULL, bmc, &id); | ||
2318 | if (rv) | ||
2319 | return rv; | ||
2290 | 2320 | ||
2291 | return snprintf(buf, 10, "%u\n", bmc->id.device_id); | 2321 | return snprintf(buf, 10, "%u\n", id.device_id); |
2292 | } | 2322 | } |
2293 | static DEVICE_ATTR(device_id, S_IRUGO, device_id_show, NULL); | 2323 | static DEVICE_ATTR(device_id, S_IRUGO, device_id_show, NULL); |
2294 | 2324 | ||
@@ -2297,9 +2327,14 @@ static ssize_t provides_device_sdrs_show(struct device *dev, | |||
2297 | char *buf) | 2327 | char *buf) |
2298 | { | 2328 | { |
2299 | struct bmc_device *bmc = to_bmc_device(dev); | 2329 | struct bmc_device *bmc = to_bmc_device(dev); |
2330 | struct ipmi_device_id id; | ||
2331 | int rv; | ||
2300 | 2332 | ||
2301 | return snprintf(buf, 10, "%u\n", | 2333 | rv = bmc_get_device_id(NULL, bmc, &id); |
2302 | (bmc->id.device_revision & 0x80) >> 7); | 2334 | if (rv) |
2335 | return rv; | ||
2336 | |||
2337 | return snprintf(buf, 10, "%u\n", (id.device_revision & 0x80) >> 7); | ||
2303 | } | 2338 | } |
2304 | static DEVICE_ATTR(provides_device_sdrs, S_IRUGO, provides_device_sdrs_show, | 2339 | static DEVICE_ATTR(provides_device_sdrs, S_IRUGO, provides_device_sdrs_show, |
2305 | NULL); | 2340 | NULL); |
@@ -2308,9 +2343,14 @@ static ssize_t revision_show(struct device *dev, struct device_attribute *attr, | |||
2308 | char *buf) | 2343 | char *buf) |
2309 | { | 2344 | { |
2310 | struct bmc_device *bmc = to_bmc_device(dev); | 2345 | struct bmc_device *bmc = to_bmc_device(dev); |
2346 | struct ipmi_device_id id; | ||
2347 | int rv; | ||
2311 | 2348 | ||
2312 | return snprintf(buf, 20, "%u\n", | 2349 | rv = bmc_get_device_id(NULL, bmc, &id); |
2313 | bmc->id.device_revision & 0x0F); | 2350 | if (rv) |
2351 | return rv; | ||
2352 | |||
2353 | return snprintf(buf, 20, "%u\n", id.device_revision & 0x0F); | ||
2314 | } | 2354 | } |
2315 | static DEVICE_ATTR(revision, S_IRUGO, revision_show, NULL); | 2355 | static DEVICE_ATTR(revision, S_IRUGO, revision_show, NULL); |
2316 | 2356 | ||
@@ -2319,9 +2359,15 @@ static ssize_t firmware_revision_show(struct device *dev, | |||
2319 | char *buf) | 2359 | char *buf) |
2320 | { | 2360 | { |
2321 | struct bmc_device *bmc = to_bmc_device(dev); | 2361 | struct bmc_device *bmc = to_bmc_device(dev); |
2362 | struct ipmi_device_id id; | ||
2363 | int rv; | ||
2322 | 2364 | ||
2323 | return snprintf(buf, 20, "%u.%x\n", bmc->id.firmware_revision_1, | 2365 | rv = bmc_get_device_id(NULL, bmc, &id); |
2324 | bmc->id.firmware_revision_2); | 2366 | if (rv) |
2367 | return rv; | ||
2368 | |||
2369 | return snprintf(buf, 20, "%u.%x\n", id.firmware_revision_1, | ||
2370 | id.firmware_revision_2); | ||
2325 | } | 2371 | } |
2326 | static DEVICE_ATTR(firmware_revision, S_IRUGO, firmware_revision_show, NULL); | 2372 | static DEVICE_ATTR(firmware_revision, S_IRUGO, firmware_revision_show, NULL); |
2327 | 2373 | ||
@@ -2330,10 +2376,16 @@ static ssize_t ipmi_version_show(struct device *dev, | |||
2330 | char *buf) | 2376 | char *buf) |
2331 | { | 2377 | { |
2332 | struct bmc_device *bmc = to_bmc_device(dev); | 2378 | struct bmc_device *bmc = to_bmc_device(dev); |
2379 | struct ipmi_device_id id; | ||
2380 | int rv; | ||
2381 | |||
2382 | rv = bmc_get_device_id(NULL, bmc, &id); | ||
2383 | if (rv) | ||
2384 | return rv; | ||
2333 | 2385 | ||
2334 | return snprintf(buf, 20, "%u.%u\n", | 2386 | return snprintf(buf, 20, "%u.%u\n", |
2335 | ipmi_version_major(&bmc->id), | 2387 | ipmi_version_major(&id), |
2336 | ipmi_version_minor(&bmc->id)); | 2388 | ipmi_version_minor(&id)); |
2337 | } | 2389 | } |
2338 | static DEVICE_ATTR(ipmi_version, S_IRUGO, ipmi_version_show, NULL); | 2390 | static DEVICE_ATTR(ipmi_version, S_IRUGO, ipmi_version_show, NULL); |
2339 | 2391 | ||
@@ -2342,9 +2394,14 @@ static ssize_t add_dev_support_show(struct device *dev, | |||
2342 | char *buf) | 2394 | char *buf) |
2343 | { | 2395 | { |
2344 | struct bmc_device *bmc = to_bmc_device(dev); | 2396 | struct bmc_device *bmc = to_bmc_device(dev); |
2397 | struct ipmi_device_id id; | ||
2398 | int rv; | ||
2345 | 2399 | ||
2346 | return snprintf(buf, 10, "0x%02x\n", | 2400 | rv = bmc_get_device_id(NULL, bmc, &id); |
2347 | bmc->id.additional_device_support); | 2401 | if (rv) |
2402 | return rv; | ||
2403 | |||
2404 | return snprintf(buf, 10, "0x%02x\n", id.additional_device_support); | ||
2348 | } | 2405 | } |
2349 | static DEVICE_ATTR(additional_device_support, S_IRUGO, add_dev_support_show, | 2406 | static DEVICE_ATTR(additional_device_support, S_IRUGO, add_dev_support_show, |
2350 | NULL); | 2407 | NULL); |
@@ -2354,8 +2411,14 @@ static ssize_t manufacturer_id_show(struct device *dev, | |||
2354 | char *buf) | 2411 | char *buf) |
2355 | { | 2412 | { |
2356 | struct bmc_device *bmc = to_bmc_device(dev); | 2413 | struct bmc_device *bmc = to_bmc_device(dev); |
2414 | struct ipmi_device_id id; | ||
2415 | int rv; | ||
2416 | |||
2417 | rv = bmc_get_device_id(NULL, bmc, &id); | ||
2418 | if (rv) | ||
2419 | return rv; | ||
2357 | 2420 | ||
2358 | return snprintf(buf, 20, "0x%6.6x\n", bmc->id.manufacturer_id); | 2421 | return snprintf(buf, 20, "0x%6.6x\n", id.manufacturer_id); |
2359 | } | 2422 | } |
2360 | static DEVICE_ATTR(manufacturer_id, S_IRUGO, manufacturer_id_show, NULL); | 2423 | static DEVICE_ATTR(manufacturer_id, S_IRUGO, manufacturer_id_show, NULL); |
2361 | 2424 | ||
@@ -2364,8 +2427,14 @@ static ssize_t product_id_show(struct device *dev, | |||
2364 | char *buf) | 2427 | char *buf) |
2365 | { | 2428 | { |
2366 | struct bmc_device *bmc = to_bmc_device(dev); | 2429 | struct bmc_device *bmc = to_bmc_device(dev); |
2430 | struct ipmi_device_id id; | ||
2431 | int rv; | ||
2432 | |||
2433 | rv = bmc_get_device_id(NULL, bmc, &id); | ||
2434 | if (rv) | ||
2435 | return rv; | ||
2367 | 2436 | ||
2368 | return snprintf(buf, 10, "0x%4.4x\n", bmc->id.product_id); | 2437 | return snprintf(buf, 10, "0x%4.4x\n", id.product_id); |
2369 | } | 2438 | } |
2370 | static DEVICE_ATTR(product_id, S_IRUGO, product_id_show, NULL); | 2439 | static DEVICE_ATTR(product_id, S_IRUGO, product_id_show, NULL); |
2371 | 2440 | ||
@@ -2374,12 +2443,18 @@ static ssize_t aux_firmware_rev_show(struct device *dev, | |||
2374 | char *buf) | 2443 | char *buf) |
2375 | { | 2444 | { |
2376 | struct bmc_device *bmc = to_bmc_device(dev); | 2445 | struct bmc_device *bmc = to_bmc_device(dev); |
2446 | struct ipmi_device_id id; | ||
2447 | int rv; | ||
2448 | |||
2449 | rv = bmc_get_device_id(NULL, bmc, &id); | ||
2450 | if (rv) | ||
2451 | return rv; | ||
2377 | 2452 | ||
2378 | return snprintf(buf, 21, "0x%02x 0x%02x 0x%02x 0x%02x\n", | 2453 | return snprintf(buf, 21, "0x%02x 0x%02x 0x%02x 0x%02x\n", |
2379 | bmc->id.aux_firmware_revision[3], | 2454 | id.aux_firmware_revision[3], |
2380 | bmc->id.aux_firmware_revision[2], | 2455 | id.aux_firmware_revision[2], |
2381 | bmc->id.aux_firmware_revision[1], | 2456 | id.aux_firmware_revision[1], |
2382 | bmc->id.aux_firmware_revision[0]); | 2457 | id.aux_firmware_revision[0]); |
2383 | } | 2458 | } |
2384 | static DEVICE_ATTR(aux_firmware_revision, S_IRUGO, aux_firmware_rev_show, NULL); | 2459 | static DEVICE_ATTR(aux_firmware_revision, S_IRUGO, aux_firmware_rev_show, NULL); |
2385 | 2460 | ||
@@ -2417,9 +2492,13 @@ static umode_t bmc_dev_attr_is_visible(struct kobject *kobj, | |||
2417 | struct device *dev = kobj_to_dev(kobj); | 2492 | struct device *dev = kobj_to_dev(kobj); |
2418 | struct bmc_device *bmc = to_bmc_device(dev); | 2493 | struct bmc_device *bmc = to_bmc_device(dev); |
2419 | umode_t mode = attr->mode; | 2494 | umode_t mode = attr->mode; |
2495 | struct ipmi_device_id id; | ||
2496 | int rv; | ||
2420 | 2497 | ||
2421 | if (attr == &dev_attr_aux_firmware_revision.attr) | 2498 | if (attr == &dev_attr_aux_firmware_revision.attr) { |
2422 | return bmc->id.aux_firmware_revision_set ? mode : 0; | 2499 | rv = bmc_get_device_id(NULL, bmc, &id); |
2500 | return (!rv && id.aux_firmware_revision_set) ? mode : 0; | ||
2501 | } | ||
2423 | if (attr == &dev_attr_guid.attr) | 2502 | if (attr == &dev_attr_guid.attr) |
2424 | return bmc->guid_set ? mode : 0; | 2503 | return bmc->guid_set ? mode : 0; |
2425 | return mode; | 2504 | return mode; |
@@ -2884,6 +2963,7 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers, | |||
2884 | ipmi_smi_t intf; | 2963 | ipmi_smi_t intf; |
2885 | ipmi_smi_t tintf; | 2964 | ipmi_smi_t tintf; |
2886 | struct list_head *link; | 2965 | struct list_head *link; |
2966 | struct ipmi_device_id id; | ||
2887 | 2967 | ||
2888 | /* | 2968 | /* |
2889 | * Make sure the driver is actually initialized, this handles | 2969 | * Make sure the driver is actually initialized, this handles |
@@ -2905,9 +2985,6 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers, | |||
2905 | if (!intf) | 2985 | if (!intf) |
2906 | return -ENOMEM; | 2986 | return -ENOMEM; |
2907 | 2987 | ||
2908 | intf->ipmi_version_major = ipmi_version_major(device_id); | ||
2909 | intf->ipmi_version_minor = ipmi_version_minor(device_id); | ||
2910 | |||
2911 | intf->bmc = kzalloc(sizeof(*intf->bmc), GFP_KERNEL); | 2988 | intf->bmc = kzalloc(sizeof(*intf->bmc), GFP_KERNEL); |
2912 | if (!intf->bmc) { | 2989 | if (!intf->bmc) { |
2913 | kfree(intf); | 2990 | kfree(intf); |
@@ -2982,13 +3059,19 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers, | |||
2982 | 3059 | ||
2983 | get_guid(intf); | 3060 | get_guid(intf); |
2984 | 3061 | ||
3062 | rv = bmc_get_device_id(intf, NULL, &id); | ||
3063 | if (rv) { | ||
3064 | dev_err(si_dev, "Unable to get the device id: %d\n", rv); | ||
3065 | goto out; | ||
3066 | } | ||
3067 | |||
2985 | rv = ipmi_bmc_register(intf, i); | 3068 | rv = ipmi_bmc_register(intf, i); |
2986 | if (rv) | 3069 | if (rv) |
2987 | goto out; | 3070 | goto out; |
2988 | 3071 | ||
2989 | if ((intf->ipmi_version_major > 1) | 3072 | if (ipmi_version_major(&id) > 1 |
2990 | || ((intf->ipmi_version_major == 1) | 3073 | || (ipmi_version_major(&id) == 1 |
2991 | && (intf->ipmi_version_minor >= 5))) { | 3074 | && ipmi_version_minor(&id) >= 5)) { |
2992 | /* | 3075 | /* |
2993 | * Start scanning the channels to see what is | 3076 | * Start scanning the channels to see what is |
2994 | * available. | 3077 | * available. |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 3d832d0362a4..76b270678b50 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -1009,9 +1009,14 @@ static void ipmi_register_watchdog(int ipmi_intf) | |||
1009 | goto out; | 1009 | goto out; |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | ipmi_get_version(watchdog_user, | 1012 | rv = ipmi_get_version(watchdog_user, |
1013 | &ipmi_version_major, | 1013 | &ipmi_version_major, |
1014 | &ipmi_version_minor); | 1014 | &ipmi_version_minor); |
1015 | if (rv) { | ||
1016 | pr_warn(PFX "Unable to get IPMI version, assuming 1.0\n"); | ||
1017 | ipmi_version_major = 1; | ||
1018 | ipmi_version_minor = 0; | ||
1019 | } | ||
1015 | 1020 | ||
1016 | rv = misc_register(&ipmi_wdog_miscdev); | 1021 | rv = misc_register(&ipmi_wdog_miscdev); |
1017 | if (rv < 0) { | 1022 | if (rv < 0) { |
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index f1045b2c6a00..80fc3f798984 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h | |||
@@ -113,9 +113,9 @@ int ipmi_create_user(unsigned int if_num, | |||
113 | int ipmi_destroy_user(ipmi_user_t user); | 113 | int ipmi_destroy_user(ipmi_user_t user); |
114 | 114 | ||
115 | /* Get the IPMI version of the BMC we are talking to. */ | 115 | /* Get the IPMI version of the BMC we are talking to. */ |
116 | void ipmi_get_version(ipmi_user_t user, | 116 | int ipmi_get_version(ipmi_user_t user, |
117 | unsigned char *major, | 117 | unsigned char *major, |
118 | unsigned char *minor); | 118 | unsigned char *minor); |
119 | 119 | ||
120 | /* Set and get the slave address and LUN that we will use for our | 120 | /* Set and get the slave address and LUN that we will use for our |
121 | source messages. Note that this affects the interface, not just | 121 | source messages. Note that this affects the interface, not just |