linux内核debug的一种方式:procfs

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux内核debug的一种方式:procfs相关的知识,希望对你有一定的参考价值。

技术分享
  1 #include <linux/module.h>
  2 
  3 #include <linux/compat.h>
  4 #include <linux/types.h>
  5 #include <linux/errno.h>
  6 #include <linux/kernel.h>
  7 #include <linux/major.h>
  8 #include <linux/slab.h>
  9 #include <linux/mm.h>
 10 #include <linux/mman.h>
 11 #include <linux/vt.h>
 12 #include <linux/init.h>
 13 #include <linux/linux_logo.h>
 14 #include <linux/proc_fs.h>
 15 #include <linux/seq_file.h>
 16 #include <linux/console.h>
 17 #include <linux/kmod.h>
 18 #include <linux/err.h>
 19 #include <linux/device.h>
 20 #include <linux/efi.h>
 21 #include <linux/fb.h>
 22 #include <linux/delay.h>
 23 #include <linux/version.h>
 24 #include <linux/kthread.h>
 25 #include <linux/poll.h>
 26 
 27 /*Proc based contron intertace*/
 28 #define AUDIO_DEBUG_PROC_DIR "audio"
 29 #define AUDIO_DEBUG_PROC_INFO "debuginfo"
 30 #define MAX_BUF_WT_LEN 200 //do not bigger than one page size 1024 bytes
 31 #define MAX_BUF_RD_LEN 2048
 32 
 33 static struct proc_dir_entry *audio_proc_dir = NULL;
 34 static struct proc_dir_entry *audio_proc_dbginfo_file = NULL;
 35 
 36 static struct deca_device *audio_deca_dev=NULL;
 37 static struct snd_device *audio_snd_dev=NULL;
 38 
 39 static char *audio_info_buffer = NULL;
 40 static __u32 g_dbg_show_en = 0;
 41 static __u32 g_dbg_show_interval = 1;
 42 static     struct mutex audio_dbg_mutex;
 43 wait_queue_head_t audio_dbg_wq;
 44 static     struct task_struct *audio_dbg_show_thread_ptr;
 45 
 46 static char *audio_state(unsigned long state)
 47 {
 48     char *ret = NULL;
 49     switch(state)
 50     {
 51         case 0:
 52             ret="DETACH";
 53             break;
 54         case 1:
 55             ret="ATTACH";
 56             break;
 57         case 2:
 58             ret="IDLE";
 59             break;
 60         case 4:
 61             ret="PLAY";
 62             break;
 63         case 8:
 64             ret="PAUSE";
 65             break;
 66         default:
 67             ret="UNKNOWN";
 68             break;
 69     }
 70     return ret;
 71 }
 72 static char *audio_sub_state(unsigned long state)
 73 {
 74     char *ret = NULL;
 75     switch(state)
 76     {
 77         case 0:
 78             ret="IDLE";
 79             break;
 80         case 1:
 81             ret="NORMAL";
 82             break;
 83         case 2:
 84             ret="NO DATA";
 85             break;
 86         case 4:
 87             ret="NO BUFF";
 88             break;
 89         default:
 90             ret="UNKNOWN";
 91             break;
 92     }
 93     return ret;
 94 }
 95 static int audio_read_debug_info(char * buffer)
 96 {
 97     int len = 0;
 98     unsigned long len_max = MAX_BUF_RD_LEN - 100;
 99     struct audio_dbg_info dbg_info;
100 
101     if(!audio_deca_dev || !audio_snd_dev)
102     {
103         return -EUNATCH;
104     }
105 
106     if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info)))
107     {
108         len += sprintf(&buffer[len],"\ndesc enable    : %s\n", (1==dbg_info.snd.ad_en)?"yes":"no");
109         if (len_max <= len)
110             goto out;
111 
112         len += sprintf(&buffer[len],"deca state     : %s(%d)\n", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state);
113         if (len_max <= len)
114             goto out;
115 
116         len += sprintf(&buffer[len],"deca sub state : %s(%d)\n", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state);
117         if (len_max <= len)
118             goto out;
119 
120         len += sprintf(&buffer[len],"snd  state     : %s(%d)\n", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state);
121         if (len_max <= len)
122             goto out;
123 
124         len += sprintf(&buffer[len],"snd  sub state : %s(%d)\n", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state);
125         if (len_max <= len)
126             goto out;
127 
128         len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
129         if (len_max <= len)
130             goto out;
131         len += sprintf(&buffer[len],"|BUFF |PCM(HEX BYTE)     |DESC(HEX BYTE)    |DD(HEX BYTE)      |DDP(HEX BYTE)     |\n");
132         if (len_max <= len)
133             goto out;
134 
135         /* deca buff info */
136         len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
137         if (len_max <= len)
138             goto out;
139         len += sprintf(&buffer[len],"|BS   |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |                  |                  |\n",
140             (int)((dbg_info.deca.prog_bs_buff_rm*100)/(dbg_info.deca.prog_bs_buff_len)),
141             (unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len,
142             (int)((dbg_info.deca.desc_bs_buff_rm*100)/(dbg_info.deca.desc_bs_buff_len)),
143             (unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len);
144         if (len_max <= len)
145             goto out;
146         len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
147         if (len_max <= len)
148             goto out;
149         len += sprintf(&buffer[len],"|CB   |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |                  |                  |\n",
150             (int)((dbg_info.deca.prog_cb_buff_rm*100)/(dbg_info.deca.prog_cb_buff_len)),
151             (unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len,
152             (int)((dbg_info.deca.desc_cb_buff_rm*100)/(dbg_info.deca.desc_cb_buff_len)),
153             (unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len);
154         if (len_max <= len)
155             goto out;
156 
157         /* snd buff info */
158         len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
159         if (len_max <= len)
160             goto out;
161         len += sprintf(&buffer[len],"|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
162             (int)((dbg_info.snd.sync_buff_pcm_rm*100)/(dbg_info.snd.sync_buff_pcm_len)),
163             (unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len,
164             (int)((dbg_info.snd.sync_buff_desc_pcm_rm*100)/(dbg_info.snd.sync_buff_desc_pcm_len)),
165             (unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len,
166             (int)((dbg_info.snd.sync_buff_dd_rm*100)/(dbg_info.snd.sync_buff_dd_len)),
167             (unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len,
168             (int)((dbg_info.snd.sync_buff_ddp_rm*100)/(dbg_info.snd.sync_buff_ddp_len)),
169             (unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len        );
170         if (len_max <= len)
171             goto out;
172         len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
173         if (len_max <= len)
174             goto out;
175         len += sprintf(&buffer[len],"|DMA  |%03d%%(%05x/%05x) |                  |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
176             (int)((dbg_info.snd.dma_buff_pcm_rm*100)/(dbg_info.snd.dma_buff_pcm_len)),
177             (unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len,
178             (int)((dbg_info.snd.dma_buff_dd_rm*100)/(dbg_info.snd.dma_buff_dd_len)),
179             (unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len,
180             (int)((dbg_info.snd.dma_buff_ddp_rm*100)/(dbg_info.snd.dma_buff_ddp_len)),
181             (unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len        );
182         if (len_max <= len)
183             goto out;
184 
185         len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n\n");
186         if (len_max <= len)
187             goto out;
188     }
189 
190 out:
191     return len;
192 }
193 
194 static int audio_show_debug_info(void)
195 {
196     struct audio_dbg_info dbg_info;
197 
198     if(!audio_deca_dev || !audio_snd_dev)
199     {
200         return -EUNATCH;
201     }
202 
203     if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info)))
204     {
205         printk( "\ndesc enable    : %s\n", (1==dbg_info.snd.ad_en)?"yes":"no");
206         printk( "deca state     : %s(%d)\n", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state);
207         printk( "deca sub state : %s(%d)\n", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state);
208         printk( "snd  state     : %s(%d)\n", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state);
209         printk( "snd  sub state : %s(%d)\n", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state);
210 
211         printk( "+-----+------------------+------------------+------------------+------------------+\n");
212         printk( "|BUFF |PCM(HEX BYTE)     |DESC(HEX BYTE)    |DD(HEX BYTE)      |DDP(HEX BYTE)     |\n");
213 
214         /* deca buff info */
215         printk( "+-----+------------------+------------------+------------------+------------------+\n");
216         printk( "|BS   |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |                  |                  |\n",
217             (int)((dbg_info.deca.prog_bs_buff_rm*100)/(dbg_info.deca.prog_bs_buff_len)),
218             (unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len,
219             (int)((dbg_info.deca.desc_bs_buff_rm*100)/(dbg_info.deca.desc_bs_buff_len)),
220             (unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len);
221         printk( "+-----+------------------+------------------+------------------+------------------+\n");
222         printk( "|CB   |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |                  |                  |\n",
223             (int)((dbg_info.deca.prog_cb_buff_rm*100)/(dbg_info.deca.prog_cb_buff_len)),
224             (unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len,
225             (int)((dbg_info.deca.desc_cb_buff_rm*100)/(dbg_info.deca.desc_cb_buff_len)),
226             (unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len);
227 
228         /* snd buff info */
229         printk( "+-----+------------------+------------------+------------------+------------------+\n");
230         printk( "|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
231             (int)((dbg_info.snd.sync_buff_pcm_rm*100)/(dbg_info.snd.sync_buff_pcm_len)),
232             (unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len,
233             (int)((dbg_info.snd.sync_buff_desc_pcm_rm*100)/(dbg_info.snd.sync_buff_desc_pcm_len)),
234             (unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len,
235             (int)((dbg_info.snd.sync_buff_dd_rm*100)/(dbg_info.snd.sync_buff_dd_len)),
236             (unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len,
237             (int)((dbg_info.snd.sync_buff_ddp_rm*100)/(dbg_info.snd.sync_buff_ddp_len)),
238             (unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len        );
239         printk( "+-----+------------------+------------------+------------------+------------------+\n");
240         printk( "|DMA  |%03d%%(%05x/%05x) |                  |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
241             (int)((dbg_info.snd.dma_buff_pcm_rm*100)/(dbg_info.snd.dma_buff_pcm_len)),
242             (unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len,
243             (int)((dbg_info.snd.dma_buff_dd_rm*100)/(dbg_info.snd.dma_buff_dd_len)),
244             (unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len,
245             (int)((dbg_info.snd.dma_buff_ddp_rm*100)/(dbg_info.snd.dma_buff_ddp_len)),
246             (unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len        );
247 
248         printk( "+-----+------------------+------------------+------------------+------------------+\n\n");
249     }
250 
251     return 0;
252 }
253 
254 /*Process debug info*/
255 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
256 static ssize_t audio_dbginfo_procfile_read(struct file *file, char __user *ubuf, size_t size, loff_t *ppos)
257 {
258     int len = 0;
259     ssize_t ret_len = 0;
260 
261     if(audio_info_buffer)
262     {
263         memset(audio_info_buffer, 0, MAX_BUF_RD_LEN);
264         len = audio_read_debug_info(audio_info_buffer);
265         ret_len = simple_read_from_buffer(ubuf, size, ppos, audio_info_buffer, len);
266     }
267 
268     return ret_len;
269 }
270 
271 
272 static ssize_t audio_dbginfo_procfile_write(struct file *file, const char __user * buffer, size_t count, loff_t *ppos)
273 {
274     char            buf[MAX_BUF_WT_LEN] = {0};
275     char            *eq_ch = NULL;
276     char            *endp = NULL;
277     unsigned long   value = 0;
278 
279     if ((0>=count) || (MAX_BUF_WT_LEN<count))
280         return 0;
281 
282     if (copy_from_user(buf, buffer, count))
283         return -EFAULT;
284 
285     eq_ch = strstr(buf, "=");
286     if (NULL == eq_ch)
287     {
288         printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
289         return -EINVAL;
290     }
291 
292     value = simple_strtoul((char *)(eq_ch+1), &endp, 0);
293     if ((eq_ch+1) == endp || value >= INT_MAX)
294     {
295         printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+1));
296         return -EINVAL;
297     }
298 
299     switch(*buf)
300     {
301         case a:
302         {
303             if (strstr(buf, "ad_en"))
304             {
305                 if (0==value || 1==value)
306                 {
307                     if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))
308                     {
309                         printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);
310                         return -EFAULT;
311                     }
312                 }
313                 else
314                 {
315                     printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
316                     return -EINVAL;
317                 }
318             }
319             else
320             {
321                 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
322                 return -EINVAL;
323             }
324             break;
325         }
326         case m:
327         {
328             if (strstr(buf, "monitor"))
329             {
330                 if (0==value || 1==value)
331                 {
332                     g_dbg_show_en = value;
333                     if (g_dbg_show_en)
334                     {
335                         if (mutex_lock_interruptible(&audio_dbg_mutex))
336                         {
337                             return(-ERESTARTSYS);
338                         }
339                         wake_up_interruptible(&audio_dbg_wq);
340                         mutex_unlock(&audio_dbg_mutex);
341                     }
342                 }
343                 else
344                 {
345                     printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
346                     return -EINVAL;
347                 }
348             }
349             else
350             {
351                 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
352                 return -EINVAL;
353             }
354             break;
355         }
356         case i:
357         {
358             if (strstr(buf, "interval"))
359             {
360                 if (0<value && 100>value)
361                 {
362                     g_dbg_show_interval = value;
363                 }
364                 else
365                 {
366                     printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
367                     return -EINVAL;
368                 }
369             }
370             else
371             {
372                 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
373                 return -EINVAL;
374             }
375             break;
376         }
377         default:
378             printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
379             return -EINVAL;
380     }
381 
382 
383     #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */
384     if ((1 != sscanf(buf, "ad_en=%d", &ad_en)) && (0==ad_en || 1==ad_en))
385     {
386         return 0;
387     }
388     if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))
389     {
390         printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
391         return 0;
392     }
393     printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
394     #endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */
395 
396     return count;
397 }
398 #else
399 static int audio_dbginfo_procfile_read(char*buffer, char**buffer_localation, off_t offset,int buffer_length,int* eof, void *data )
400 {
401     int len = 0;
402     len =  audio_read_debug_info(buffer);
403     *eof = 1;
404     return len;
405 }
406 
407 static int audio_dbginfo_procfile_write(struct file *filp, const char *buffer,unsigned long count,void *data)
408 {
409     char            buf[MAX_BUF_WT_LEN] = {0};
410     char            *eq_ch = NULL;
411     char            *endp = NULL;
412     unsigned long   value = 0;
413 
414     if ((0>=count) || (MAX_BUF_WT_LEN<count))
415         return 0;
416 
417     if (copy_from_user(buf, buffer, count))
418         return -EFAULT;
419 
420     eq_ch = strstr(buf, "=");
421     if (NULL == eq_ch)
422     {
423         printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
424         return -EINVAL;
425     }
426 
427     value = simple_strtoul((char *)(eq_ch+1), &endp, 0);
428     if ((eq_ch+1) == endp || value >= INT_MAX)
429     {
430         printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+1));
431         return -EINVAL;
432     }
433 
434     switch(*buf)
435     {
436         case a:
437             if (strstr(buf, "ad_en"))
438             {
439                 if (0==value || 1==value)
440                 {
441                     if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))
442                     {
443                         printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);
444                         return -EFAULT;
445                     }
446                 }
447                 else
448                 {
449                     printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
450                     return -EINVAL;
451                 }
452             }
453             else
454             {
455                 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
456                 return -EINVAL;
457             }
458             break;
459         case m:
460             if (strstr(buf, "monitor"))
461             {
462                 if (0==value || 1==value)
463                 {
464                     g_dbg_show_en = value;
465                     if (g_dbg_show_en)
466                     {
467                         if (mutex_lock_interruptible(&audio_dbg_mutex))
468                         {
469                             return(-ERESTARTSYS);
470                         }
471                         wake_up_interruptible(&audio_dbg_wq);
472                         mutex_unlock(&audio_dbg_mutex);
473                     }
474                 }
475                 else
476                 {
477                     printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
478                     return -EINVAL;
479                 }
480             }
481             else
482             {
483                 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
484                 return -EINVAL;
485             }
486             break;
487         default:
488             printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
489             return -EINVAL;
490     }
491 
492 
493 #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */
494     if ((1 != sscanf(buf, "ad_en=%d", &ad_en)) && (0==ad_en || 1==ad_en))
495     {
496         return 0;
497     }
498     if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))
499     {
500         printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
501         return 0;
502     }
503     printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
504 #endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */
505 
506     return count;
507 }
508 
509 
510 #endif
511 
512 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
513 static const struct file_operations audio_debuginfo_fops = {
514     .read = audio_dbginfo_procfile_read,
515     .write = audio_dbginfo_procfile_write,
516     .llseek = default_llseek,
517 };
518 #endif
519 
520 static int audio_dbg_show_thread(void *param)
521 {
522     __s32 ret;
523 
524     for(;;)
525     {
526         if (mutex_lock_interruptible(&audio_dbg_mutex))
527         {
528             return(-ERESTARTSYS);
529         }
530 
531         /* Wait until we are allowed to show debug info.
532         */
533         while (g_dbg_show_en == 0)
534         {
535             mutex_unlock(&audio_dbg_mutex);
536             if (wait_event_interruptible(audio_dbg_wq, (1==g_dbg_show_en)))
537             {
538                 return(-ERESTARTSYS);
539             }
540             if (mutex_lock_interruptible(&audio_dbg_mutex))
541             {
542                 return(-ERESTARTSYS);
543             }
544         }
545 
546         ret = audio_show_debug_info();
547 
548         if (ret < 0)
549         {
550             g_dbg_show_en = 0;
551             printk("\033[40;31m%s->%s.%u, audio_show_debug_info failed!.\033[0m\n", __FILE__, __FUNCTION__, __LINE__);
552         }
553         mutex_unlock(&audio_dbg_mutex);
554 
555         msleep(g_dbg_show_interval*1000);
556     }
557 
558     return(0);
559 }
560 
561 int  audio_debug_procfs_init(void)
562 {
563     audio_info_buffer = kmalloc(MAX_BUF_RD_LEN, GFP_KERNEL);
564     if (NULL == audio_info_buffer)
565     {
566         printk("kmall audio_info_buffer %d failed!!\n", MAX_BUF_RD_LEN);
567         return -1;
568     }
569     mutex_init(&audio_dbg_mutex);
570     init_waitqueue_head(&audio_dbg_wq);
571 
572     audio_proc_dir = proc_mkdir(AUDIO_DEBUG_PROC_DIR, NULL);
573     if (audio_proc_dir == NULL) {
574         printk("audio_debug_procfs_init create dir audio failed!!\n");
575         kfree(audio_info_buffer);
576         return -1;
577     }
578 
579 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0))
580     /*For Debug info*/
581     audio_proc_dbginfo_file = proc_create(AUDIO_DEBUG_PROC_INFO,0644,audio_proc_dir, &audio_debuginfo_fops);
582 #else
583     /*For Debug info*/
584     audio_proc_dbginfo_file = create_proc_entry(AUDIO_DEBUG_PROC_INFO,0644,audio_proc_dir);
585 #endif
586     if(audio_proc_dbginfo_file == NULL)
587     {
588         remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
589         kfree(audio_info_buffer);
590         printk("Error:could not initialize /proc/%s/%s\n", AUDIO_DEBUG_PROC_DIR, AUDIO_DEBUG_PROC_INFO);
591         return -1;
592     }
593 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
594     audio_proc_dbginfo_file->read_proc = audio_dbginfo_procfile_read;
595     audio_proc_dbginfo_file->write_proc = audio_dbginfo_procfile_write;
596 #endif
597 
598     audio_deca_dev=(struct deca_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_DECA);
599     audio_snd_dev=(struct snd_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_SND);
600 
601     audio_dbg_show_thread_ptr = kthread_create(audio_dbg_show_thread, NULL, "audio_dbg");
602 
603     if (IS_ERR(audio_dbg_show_thread_ptr))
604     {
605         printk("%s,%d\n", __FUNCTION__, __LINE__);
606         remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);
607         remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
608         kfree(audio_info_buffer);
609         return(PTR_ERR(audio_dbg_show_thread_ptr));
610     }
611 
612     wake_up_process(audio_dbg_show_thread_ptr);
613 
614     return 0;
615 }
616 
617 
618 void  audio_debug_procfs_exit(void)
619 {
620     remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);
621     remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
622 
623     if (audio_info_buffer)
624         kfree(audio_info_buffer);
625 
626     return ;
627 }
View Code

 

今天刚好加了一个procfs的目录,用于调试自己的驱动,使用方法如下:

目前支持如下几个命令:
cat /proc/audio/debuginfo --》查看audio信息
echo "ad_en=1" > /proc/audio/debuginfo --》动态打开/关闭audio desc,ad_en参数只能为0或1
echo "monitor=1" > /proc/audio/debuginfo --》wake up内核线程audio_dbg,默认每秒打印一次audio信息,monitor参数只能为0或1
echo "interval=5" > /proc/audio/debuginfo --》设置monitor打印的时间间隔(单位:秒),interval参数范围为[1,100]

audio打印信息如下:(其中表格记录的是audio各个buff的使用情况:剩余数据量百分比(剩余数据量/buff总大小),主要用于debug buff堵住的情况)

# cat /proc/audio/debuginfo

desc enable : no
deca state : IDLE(2)
deca sub state : IDLE(0)
snd state : IDLE(2)
snd sub state : IDLE(0)
+-----+------------------+------------------+------------------+------------------+
|BUFF |PCM(HEX BYTE)     |DESC(HEX BYTE)    |DD(HEX BYTE)      |DDP(HEX BYTE)     |
+-----+------------------+------------------+------------------+------------------+
|BS   |000%(00000/0c800) |000%(00000/0c800) |                  |                  |
+-----+------------------+------------------+------------------+------------------+
|CB   |000%(00000/000c8) |000%(00000/000c8) |                  |                  |
+-----+------------------+------------------+------------------+------------------+
|SYNC |000%(00000/60300) |000%(00000/60300) |000%(00000/60300) |000%(00000/60300) |
+-----+------------------+------------------+------------------+------------------+
|DMA  |000%(00000/20100) |                  |000%(00000/20100) |000%(00000/20100) |
+-----+------------------+------------------+------------------+------------------+

 

以上是关于linux内核debug的一种方式:procfs的主要内容,如果未能解决你的问题,请参考以下文章

Linux用户与内核空间交互—procfs

LiteOS-A内核中的procfs文件系统分析

Linux内核里的DebugFS

linux内核源码分析之proc文件系统

致驱动工程师的一封信 (转)

如何通过编译Linux内核打开IPVS(LVS)的debug模式