Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IPMI: add 0.9 support

Add support for IPMI 0.9 systems to the IPMI driver. Just handle a shorter
get device ID command with less information.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
Cc: Stian Jordet <liste@jordet.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Corey Minyard and committed by
Linus Torvalds
d8c98618 ac019151

+30 -21
+2 -13
drivers/char/ipmi/ipmi_si_intf.c
··· 2380 2380 /* Otherwise, we got some data. */ 2381 2381 resp_len = smi_info->handlers->get_result(smi_info->si_sm, 2382 2382 resp, IPMI_MAX_MSG_LENGTH); 2383 - if (resp_len < 14) { 2384 - /* That's odd, it should be longer. */ 2385 - rv = -EINVAL; 2386 - goto out; 2387 - } 2388 2383 2389 - if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0)) { 2390 - /* That's odd, it shouldn't be able to fail. */ 2391 - rv = -EINVAL; 2392 - goto out; 2393 - } 2394 - 2395 - /* Record info from the get device id, in case we need it. */ 2396 - ipmi_demangle_device_id(resp+3, resp_len-3, &smi_info->device_id); 2384 + /* Check and record info from the get device id, in case we need it. */ 2385 + rv = ipmi_demangle_device_id(resp, resp_len, &smi_info->device_id); 2397 2386 2398 2387 out: 2399 2388 kfree(resp);
+28 -8
include/linux/ipmi_smi.h
··· 148 148 149 149 /* Take a pointer to a raw data buffer and a length and extract device 150 150 id information from it. The first byte of data must point to the 151 - byte from the get device id response after the completion code. 152 - The caller is responsible for making sure the length is at least 153 - 11 and the command completed without error. */ 154 - static inline void ipmi_demangle_device_id(unsigned char *data, 155 - unsigned int data_len, 156 - struct ipmi_device_id *id) 151 + netfn << 2, the data should be of the format: 152 + netfn << 2, cmd, completion code, data 153 + as normally comes from a device interface. */ 154 + static inline int ipmi_demangle_device_id(const unsigned char *data, 155 + unsigned int data_len, 156 + struct ipmi_device_id *id) 157 157 { 158 + if (data_len < 9) 159 + return -EINVAL; 160 + if (data[0] != IPMI_NETFN_APP_RESPONSE << 2 || 161 + data[1] != IPMI_GET_DEVICE_ID_CMD) 162 + /* Strange, didn't get the response we expected. */ 163 + return -EINVAL; 164 + if (data[2] != 0) 165 + /* That's odd, it shouldn't be able to fail. */ 166 + return -EINVAL; 167 + 168 + data += 3; 169 + data_len -= 3; 158 170 id->device_id = data[0]; 159 171 id->device_revision = data[1]; 160 172 id->firmware_revision_1 = data[2]; 161 173 id->firmware_revision_2 = data[3]; 162 174 id->ipmi_version = data[4]; 163 175 id->additional_device_support = data[5]; 164 - id->manufacturer_id = data[6] | (data[7] << 8) | (data[8] << 16); 165 - id->product_id = data[9] | (data[10] << 8); 176 + if (data_len >= 6) { 177 + id->manufacturer_id = (data[6] | (data[7] << 8) | 178 + (data[8] << 16)); 179 + id->product_id = data[9] | (data[10] << 8); 180 + } else { 181 + id->manufacturer_id = 0; 182 + id->product_id = 0; 183 + } 166 184 if (data_len >= 15) { 167 185 memcpy(id->aux_firmware_revision, data+11, 4); 168 186 id->aux_firmware_revision_set = 1; 169 187 } else 170 188 id->aux_firmware_revision_set = 0; 189 + 190 + return 0; 171 191 } 172 192 173 193 /* Add a low-level interface to the IPMI driver. Note that if the