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 }

今天刚好加了一个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) |
+-----+------------------+------------------+------------------+------------------+
时间: 2024-10-11 05:22:15

linux内核debug的一种方式:procfs的相关文章

Linux 远程桌面的两种方式

在绝多数情况下,Linux 不需要使用到GUI的桌面环境,但是有时在一些特殊的场景如安装Oracle的时候,需要有图形界面进行辅助才可以安装. 如果要使用Linux的图形界面,一般有两种方式: 1.Linux系统安装X Windows图形界面,使用vnc远程. 2.Linux系统启用X协议,配置X Clent,本地有桌面环境的机器(如Windows)配置X Server,获取远程的信息,在本地X server上显示图形界面. 方法一: 本机安装图形界面 这里以CentOS6.5的机器为例,安装图

Linux下定时执行任务的几种方式

如果说我说如果,你的某一个目录下会经常的生成一些垃圾文件,比如访问日志.错误日志.core文件,而你又不想过几分钟就去手动检查一下,那么可以使用定时执行任务的方式来解决.目前我所知道的可以执行定时任务的方式有这么几种:crontab.后台脚本定时检查. 下面对这几种方式进行一下讲解: 1.使用脚本 这个方式比较简单,就是写个脚本,每次开机的时候自动让它启动,然后放在后台去执行就可以了.脚本代码如下: $ cat cleanwitch.sh 1 #!/bin/bash 2 3 # which di

linux下进程间通信IPC几种方式性能比较

在项目中,经常会遇到单机上进程间的通信,常用的进程间通信方式一般有以下几种 1 socket 2 unixsocket 3 共享内存(share-memory) 4 管道(pipe) 5 消息队列(message-queue) 6 文件(file) 7 消息总线(比如zeromq) 8 其他中间件(比如redis, memchache, 数据库等) 如果项目仅仅是消息的传递,对性能要求不高,则以上每种方式都可以实现进程间通信,我们可以选择较容易实现的方式来运用. 如果项目对消息传递性能要求很高,

虚拟机 linux 网络连接的三种方式

在VMare虚拟机中,网络连接有三种方式 1.桥接模式   2.only host模式     3.NAT模式   当然还可以自定义,但是虚拟机提供的只有三种方式. 在装完虚拟机之后,网络适配器中就会多出来两个虚拟网卡,VMent1 和Vment8.在使用桥接模式的时候是不需要使用虚拟网卡的,因为它使用的是 你的真实网卡,也就是有线网卡,所以有时候使用桥接模式链接的时候会发现自己没有连通,原因可能是使用了无线网卡,在虚拟机桥接模式中将自动链接 改成自己的有线网卡就可以了. 使用桥接模式因为使用的

「linux学习」之两种方式yum搭建

方式一本地yum源配置: mkdir /mnt/cdrom/ 将/mnt/cdrom/目录称为 /dev/cdrom 的挂载入口 执行挂载命令 mount /dev/cdrom  /cdrom/mnt/ # mount: /dev/sr0 写保护,将以只读方式挂载 挂载后查看目录文件: ls /mnt/cdrom 挂载成功后使用 rpm -qa | grep rpm 查看所有rpm的包,选取需要的安装 rpm -ivh /mnt/cdrom/Packages/rpm+tab键自动补齐,这里需要注

Linux进程通信的几种方式总结

进程通信的目的 数据传输 一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间 共享数据 多个进程想要操作共享数据,一个进程对共享数据 通知事 一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程). 资源共享 多个进程之间共享同样的资源.为了作到这一点,需要内核提供锁和同步机制. 进程控制 有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变.

Linux系统软件安装的几种方式

Linux系统,一个文件能不能执行看的是有没有可执行权限x,不过真正的可执行文件是二进制文件(binary file),举例来说Linux上的c语言源码编写完后,通过gcc程序编译后就可以创建一个可执行的二进制文件. 1.什么是make 与configure make是一个程序,会去找makefile(记录了源码如何编译的详细信息),通常这个检测程序文件名为configure或config:基本的makefile规则是: 目标:目标文件1 目标文件2 <tab> gcc -o 欲建立的执行文件

linux开机启动的三种方式

参考:www.cnblogs.com/gzggyy/archive/2012/08/07/2626574.html 一./etc/rc.local这是一个最简单的方法,编辑"/etc/rc.local",把启动程序的shell命令输入进去即可(要输入命令的全路径),类似于windows系统"开始"-->"所有程序"-->"启动"方式 二.crontab(类似于windows的任务计划服务)通过crontab可以设定

Linux安装软件的3种方式

1.源代码编译安装 2.yum方式,自动搜索依赖关系,自动下载解决依赖关系 446 pip3 list 447 pip3 install -i https://pypi.douban.com/simple flask 448 flask 449 pip3 list 450 clear 451 cd /etc/yum.repos.d/ 452 ls 453 mkdir allrepo 454 mv ./* allrepo 455 ls 456 cd allrepo 457 ls 458 cd ..