2 * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
3 * drivers/misc/iwmc3200top/log.c
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
27 #include <linux/kernel.h>
28 #include <linux/mmc/sdio_func.h>
29 #include <linux/ctype.h>
31 #include "iwmc3200top.h"
34 /* Maximal hexadecimal string size of the FW memdump message */
35 #define LOG_MSG_SIZE_MAX 12400
37 /* iwmct_logdefs is a global used by log macros */
38 u8 iwmct_logdefs
[LOG_SRC_MAX
];
39 static u8 iwmct_fw_logdefs
[FW_LOG_SRC_MAX
];
42 static int _log_set_log_filter(u8
*logdefs
, int size
, u8 src
, u8 logmask
)
47 logdefs
[src
] = logmask
;
48 else if (src
== LOG_SRC_ALL
)
49 for (i
= 0; i
< size
; i
++)
58 int iwmct_log_set_filter(u8 src
, u8 logmask
)
60 return _log_set_log_filter(iwmct_logdefs
, LOG_SRC_MAX
, src
, logmask
);
64 int iwmct_log_set_fw_filter(u8 src
, u8 logmask
)
66 return _log_set_log_filter(iwmct_fw_logdefs
,
67 FW_LOG_SRC_MAX
, src
, logmask
);
71 static int log_msg_format_hex(char *str
, int slen
, u8
*ibuf
,
78 for (pos
= 0, i
= 0; pos
< slen
- 2 && pref
[i
] != '\0'; i
++, pos
++)
81 for (i
= 0; pos
< slen
- 2 && i
< ilen
; pos
+= len
, i
++)
82 len
= snprintf(&str
[pos
], slen
- pos
- 1, " %2.2X", ibuf
[i
]);
90 /* NOTE: This function is not thread safe.
91 Currently it's called only from sdio rx worker - no race there
93 void iwmct_log_top_message(struct iwmct_priv
*priv
, u8
*buf
, int len
)
96 static char logbuf
[LOG_MSG_SIZE_MAX
];
98 msg
= (struct top_msg
*)buf
;
100 if (len
< sizeof(msg
->hdr
) + sizeof(msg
->u
.log
.log_hdr
)) {
101 LOG_ERROR(priv
, FW_MSG
, "Log message from TOP "
102 "is too short %d (expected %zd)\n",
103 len
, sizeof(msg
->hdr
) + sizeof(msg
->u
.log
.log_hdr
));
107 if (!(iwmct_fw_logdefs
[msg
->u
.log
.log_hdr
.logsource
] &
108 BIT(msg
->u
.log
.log_hdr
.severity
)) ||
109 !(iwmct_logdefs
[LOG_SRC_FW_MSG
] & BIT(msg
->u
.log
.log_hdr
.severity
)))
112 switch (msg
->hdr
.category
) {
113 case COMM_CATEGORY_TESTABILITY
:
114 if (!(iwmct_logdefs
[LOG_SRC_TST
] &
115 BIT(msg
->u
.log
.log_hdr
.severity
)))
117 if (log_msg_format_hex(logbuf
, LOG_MSG_SIZE_MAX
, buf
,
118 le16_to_cpu(msg
->hdr
.length
) +
119 sizeof(msg
->hdr
), "<TST>"))
120 LOG_WARNING(priv
, TST
,
121 "TOP TST message is too long, truncating...");
122 LOG_WARNING(priv
, TST
, "%s\n", logbuf
);
124 case COMM_CATEGORY_DEBUG
:
125 if (msg
->hdr
.opcode
== OP_DBG_ZSTR_MSG
)
126 LOG_INFO(priv
, FW_MSG
, "%s %s", "<DBG>",
127 ((u8
*)msg
) + sizeof(msg
->hdr
)
128 + sizeof(msg
->u
.log
.log_hdr
));
130 if (log_msg_format_hex(logbuf
, LOG_MSG_SIZE_MAX
, buf
,
131 le16_to_cpu(msg
->hdr
.length
)
134 LOG_WARNING(priv
, FW_MSG
,
135 "TOP DBG message is too long,"
137 LOG_WARNING(priv
, FW_MSG
, "%s\n", logbuf
);
145 static int _log_get_filter_str(u8
*logdefs
, int logdefsz
, char *buf
, int size
)
148 for (i
= 0, pos
= 0; (pos
< size
-1) && (i
< logdefsz
); i
++) {
149 len
= snprintf(&buf
[pos
], size
- pos
- 1, "0x%02X%02X,",
161 int log_get_filter_str(char *buf
, int size
)
163 return _log_get_filter_str(iwmct_logdefs
, LOG_SRC_MAX
, buf
, size
);
166 int log_get_fw_filter_str(char *buf
, int size
)
168 return _log_get_filter_str(iwmct_fw_logdefs
, FW_LOG_SRC_MAX
, buf
, size
);
171 #define HEXADECIMAL_RADIX 16
172 #define LOG_SRC_FORMAT 7 /* log level is in format of "0xXXXX," */
174 ssize_t
show_iwmct_log_level(struct device
*d
,
175 struct device_attribute
*attr
, char *buf
)
177 struct iwmct_priv
*priv
= dev_get_drvdata(d
);
182 buf_size
= (LOG_SRC_FORMAT
* LOG_SRC_MAX
) + 1;
183 str_buf
= kzalloc(buf_size
, GFP_KERNEL
);
185 LOG_ERROR(priv
, DEBUGFS
,
186 "failed to allocate %d bytes\n", buf_size
);
191 if (log_get_filter_str(str_buf
, buf_size
) < 0) {
196 ret
= sprintf(buf
, "%s", str_buf
);
203 ssize_t
store_iwmct_log_level(struct device
*d
,
204 struct device_attribute
*attr
,
205 const char *buf
, size_t count
)
207 struct iwmct_priv
*priv
= dev_get_drvdata(d
);
208 char *token
, *str_buf
= NULL
;
216 str_buf
= kzalloc(count
, GFP_KERNEL
);
218 LOG_ERROR(priv
, DEBUGFS
,
219 "failed to allocate %zd bytes\n", count
);
224 memcpy(str_buf
, buf
, count
);
226 while ((token
= strsep(&str_buf
, ",")) != NULL
) {
227 while (isspace(*token
))
229 if (strict_strtol(token
, HEXADECIMAL_RADIX
, &val
)) {
230 LOG_ERROR(priv
, DEBUGFS
,
231 "failed to convert string to long %s\n",
238 src
= (val
& 0XFF00) >> 8;
239 iwmct_log_set_filter(src
, mask
);
247 ssize_t
show_iwmct_log_level_fw(struct device
*d
,
248 struct device_attribute
*attr
, char *buf
)
250 struct iwmct_priv
*priv
= dev_get_drvdata(d
);
255 buf_size
= (LOG_SRC_FORMAT
* FW_LOG_SRC_MAX
) + 2;
257 str_buf
= kzalloc(buf_size
, GFP_KERNEL
);
259 LOG_ERROR(priv
, DEBUGFS
,
260 "failed to allocate %d bytes\n", buf_size
);
265 if (log_get_fw_filter_str(str_buf
, buf_size
) < 0) {
270 ret
= sprintf(buf
, "%s", str_buf
);
277 ssize_t
store_iwmct_log_level_fw(struct device
*d
,
278 struct device_attribute
*attr
,
279 const char *buf
, size_t count
)
281 struct iwmct_priv
*priv
= dev_get_drvdata(d
);
283 char *token
, *str_buf
= NULL
;
293 str_buf
= kzalloc(count
, GFP_KERNEL
);
295 LOG_ERROR(priv
, DEBUGFS
,
296 "failed to allocate %zd bytes\n", count
);
301 memcpy(str_buf
, buf
, count
);
303 cmd
.hdr
.type
= COMM_TYPE_H2D
;
304 cmd
.hdr
.category
= COMM_CATEGORY_DEBUG
;
305 cmd
.hdr
.opcode
= CMD_DBG_LOG_LEVEL
;
307 for (i
= 0; ((token
= strsep(&str_buf
, ",")) != NULL
) &&
308 (i
< FW_LOG_SRC_MAX
); i
++) {
310 while (isspace(*token
))
313 if (strict_strtol(token
, HEXADECIMAL_RADIX
, &val
)) {
314 LOG_ERROR(priv
, DEBUGFS
,
315 "failed to convert string to long %s\n",
321 mask
= val
& 0xFF; /* LSB */
322 src
= (val
& 0XFF00) >> 8; /* 2nd least significant byte. */
323 iwmct_log_set_fw_filter(src
, mask
);
325 cmd
.u
.logdefs
[i
].logsource
= src
;
326 cmd
.u
.logdefs
[i
].sevmask
= mask
;
329 cmd
.hdr
.length
= cpu_to_le16(i
* sizeof(cmd
.u
.logdefs
[0]));
330 cmdlen
= (i
* sizeof(cmd
.u
.logdefs
[0]) + sizeof(cmd
.hdr
));
332 ret
= iwmct_send_hcmd(priv
, (u8
*)&cmd
, cmdlen
);
334 LOG_ERROR(priv
, DEBUGFS
,
335 "Failed to send %d bytes of fwcmd, ret=%zd\n",
339 LOG_INFO(priv
, DEBUGFS
, "fwcmd sent (%d bytes)\n", cmdlen
);