diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_msghandler.c')
| -rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 155 |
1 files changed, 119 insertions, 36 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. |
