|
29 | 29 | #include <linux/sysfs.h> |
30 | 30 | #include <linux/hwmon.h> |
31 | 31 | #include <linux/hwmon-sysfs.h> |
32 | | -#include <linux/ipmi.h> |
33 | | -#include <linux/ipmi_smi.h> |
34 | 32 | #include <linux/platform_device.h> |
35 | 33 | #include <linux/string_helpers.h> |
| 34 | +#include "accton_ipmi_intf.h" |
36 | 35 |
|
37 | 36 | #define DRVNAME "as9947_72xkb_fan" |
38 | | -#define ACCTON_IPMI_NETFN 0x34 |
39 | 37 | #define IPMI_FAN_READ_CMD 0x14 |
40 | 38 | #define IPMI_FAN_WRITE_CMD 0x15 |
41 | 39 | #define IPMI_FAN_READ_MODEL_CMD 0x10 |
42 | 40 | #define IPMI_FAN_READ_SERIAL_CMD 0x11 |
43 | | -#define IPMI_TIMEOUT (5 * HZ) |
44 | | -#define IPMI_ERR_RETRY_TIMES 1 |
45 | 41 | #define IPMI_FAN_REG_READ_CMD 0x20 |
46 | 42 | #define MAX_FAN_SPEED_RPM 33000 |
47 | 43 | #define IPMI_FAN_MODEL_SIZE 15 |
48 | 44 | #define IPMI_FAN_SERIAL_SIZE 13 |
49 | 45 |
|
50 | | -static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); |
51 | 46 | static ssize_t set_fan(struct device *dev, struct device_attribute *da, |
52 | 47 | const char *buf, size_t count); |
53 | 48 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, |
@@ -90,24 +85,6 @@ enum fan_data_index { |
90 | 85 | FAN_DATA_COUNT |
91 | 86 | }; |
92 | 87 |
|
93 | | - |
94 | | -struct ipmi_data { |
95 | | - struct completion read_complete; |
96 | | - struct ipmi_addr address; |
97 | | - struct ipmi_user *user; |
98 | | - int interface; |
99 | | - |
100 | | - struct kernel_ipmi_msg tx_message; |
101 | | - long tx_msgid; |
102 | | - |
103 | | - void *rx_msg_data; |
104 | | - unsigned short rx_msg_len; |
105 | | - unsigned char rx_result; |
106 | | - int rx_recv_type; |
107 | | - |
108 | | - struct ipmi_user_hndl ipmi_hndlrs; |
109 | | -}; |
110 | | - |
111 | 88 | struct as9947_72xkb_fan_data { |
112 | 89 | struct platform_device *pdev; |
113 | 90 | struct device *hwmon_dev; |
@@ -246,156 +223,6 @@ static struct attribute *as9947_72xkb_fan_attrs[] = { |
246 | 223 | }; |
247 | 224 | ATTRIBUTE_GROUPS(as9947_72xkb_fan); |
248 | 225 |
|
249 | | -/* Functions to talk to the IPMI layer */ |
250 | | - |
251 | | -/* Initialize IPMI address, message buffers and user data */ |
252 | | -static int init_ipmi_data(struct ipmi_data *ipmi, int iface, |
253 | | - struct device *dev) |
254 | | -{ |
255 | | - int err; |
256 | | - |
257 | | - init_completion(&ipmi->read_complete); |
258 | | - |
259 | | - /* Initialize IPMI address */ |
260 | | - ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; |
261 | | - ipmi->address.channel = IPMI_BMC_CHANNEL; |
262 | | - ipmi->address.data[0] = 0; |
263 | | - ipmi->interface = iface; |
264 | | - |
265 | | - /* Initialize message buffers */ |
266 | | - ipmi->tx_msgid = 0; |
267 | | - ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; |
268 | | - |
269 | | - ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; |
270 | | - |
271 | | - /* Create IPMI messaging interface user */ |
272 | | - err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, |
273 | | - ipmi, &ipmi->user); |
274 | | - if (err < 0) { |
275 | | - dev_err(dev, "Unable to register user with IPMI " |
276 | | - "interface %d\n", ipmi->interface); |
277 | | - return -EACCES; |
278 | | - } |
279 | | - |
280 | | - return 0; |
281 | | -} |
282 | | - |
283 | | -/* Send an IPMI command */ |
284 | | -static int _ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, |
285 | | - unsigned char *tx_data, unsigned short tx_len, |
286 | | - unsigned char *rx_data, unsigned short rx_len) |
287 | | -{ |
288 | | - int err; |
289 | | - |
290 | | - ipmi->tx_message.cmd = cmd; |
291 | | - ipmi->tx_message.data = tx_data; |
292 | | - ipmi->tx_message.data_len = tx_len; |
293 | | - ipmi->rx_msg_data = rx_data; |
294 | | - ipmi->rx_msg_len = rx_len; |
295 | | - |
296 | | - err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); |
297 | | - if (err) |
298 | | - goto addr_err; |
299 | | - |
300 | | - ipmi->tx_msgid++; |
301 | | - err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, |
302 | | - &ipmi->tx_message, ipmi, 0, 0, 0); |
303 | | - if (err) |
304 | | - goto ipmi_req_err; |
305 | | - |
306 | | - err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); |
307 | | - if (!err) |
308 | | - goto ipmi_timeout_err; |
309 | | - |
310 | | - return 0; |
311 | | - |
312 | | -ipmi_timeout_err: |
313 | | - err = -ETIMEDOUT; |
314 | | - dev_err(&data->pdev->dev, "request_timeout=%x\n", err); |
315 | | - return err; |
316 | | -ipmi_req_err: |
317 | | - dev_err(&data->pdev->dev, "request_settime=%x\n", err); |
318 | | - return err; |
319 | | -addr_err: |
320 | | - dev_err(&data->pdev->dev, "validate_addr=%x\n", err); |
321 | | - return err; |
322 | | -} |
323 | | - |
324 | | -/* Send an IPMI command with retry */ |
325 | | -static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, |
326 | | - unsigned char *tx_data, unsigned short tx_len, |
327 | | - unsigned char *rx_data, unsigned short rx_len) |
328 | | -{ |
329 | | - int status = 0, retry = 0; |
330 | | - char *cmdline = kstrdup_quotable_cmdline(current, GFP_KERNEL); |
331 | | - int i = 0; |
332 | | - char raw_cmd[20] = ""; |
333 | | - |
334 | | - sprintf(raw_cmd, "0x%02x", cmd); |
335 | | - |
336 | | - if(tx_len) { |
337 | | - for(i = 0; i < tx_len; i++) |
338 | | - sprintf(raw_cmd + strlen(raw_cmd), " 0x%02x", tx_data[i]); |
339 | | - } |
340 | | - |
341 | | - for (retry = 0; retry <= IPMI_ERR_RETRY_TIMES; retry++) { |
342 | | - status = _ipmi_send_message(ipmi,cmd, tx_data, tx_len, rx_data, rx_len); |
343 | | - if (unlikely(status != 0)) { |
344 | | - dev_err(&data->pdev->dev, |
345 | | - "ipmi_send_message_%d err status(%d)[%s] raw_cmd=[%s] tx_msgid=(%02x)\r\n", |
346 | | - retry, status, cmdline ? cmdline : "", raw_cmd, |
347 | | - (int)ipmi->tx_msgid); |
348 | | - continue; |
349 | | - } |
350 | | - |
351 | | - if (unlikely(ipmi->rx_result != 0)) { |
352 | | - dev_err(&data->pdev->dev, |
353 | | - "ipmi_send_message_%d err result(%d)[%s] raw_cmd=[%s] tx_msgid=(%02x)\r\n", |
354 | | - retry, ipmi->rx_result, cmdline ? cmdline : "", raw_cmd, |
355 | | - (int)ipmi->tx_msgid); |
356 | | - continue; |
357 | | - } |
358 | | - |
359 | | - break; |
360 | | - } |
361 | | - |
362 | | - return status; |
363 | | -} |
364 | | - |
365 | | -/* Dispatch IPMI messages to callers */ |
366 | | -static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) |
367 | | -{ |
368 | | - unsigned short rx_len; |
369 | | - struct ipmi_data *ipmi = user_msg_data; |
370 | | - |
371 | | - if (msg->msgid != ipmi->tx_msgid) { |
372 | | - dev_err(&data->pdev->dev, "Mismatch between received msgid " |
373 | | - "(%02x) and transmitted msgid (%02x)!\n", |
374 | | - (int)msg->msgid, |
375 | | - (int)ipmi->tx_msgid); |
376 | | - ipmi_free_recv_msg(msg); |
377 | | - return; |
378 | | - } |
379 | | - |
380 | | - ipmi->rx_recv_type = msg->recv_type; |
381 | | - if (msg->msg.data_len > 0) |
382 | | - ipmi->rx_result = msg->msg.data[0]; |
383 | | - else |
384 | | - ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; |
385 | | - |
386 | | - if (msg->msg.data_len > 1) { |
387 | | - rx_len = msg->msg.data_len - 1; |
388 | | - if (ipmi->rx_msg_len < rx_len) |
389 | | - rx_len = ipmi->rx_msg_len; |
390 | | - ipmi->rx_msg_len = rx_len; |
391 | | - memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); |
392 | | - } else |
393 | | - ipmi->rx_msg_len = 0; |
394 | | - |
395 | | - ipmi_free_recv_msg(msg); |
396 | | - complete(&ipmi->read_complete); |
397 | | -} |
398 | | - |
399 | 226 | static struct as9947_72xkb_fan_data *as9947_72xkb_fan_update_device(void) |
400 | 227 | { |
401 | 228 | int status = 0; |
|
0 commit comments