88#include <linux/kfifo.h>
99#include <linux/module.h>
1010#include <linux/slab.h>
11+ #include <linux/sysfs.h>
1112#include <linux/version.h>
1213#include <linux/workqueue.h>
1314
@@ -32,6 +33,42 @@ MODULE_DESCRIPTION("A device that simulates interrupts");
3233
3334static int delay = 100 ; /* time (in ms) to generate an event */
3435
36+ /* Declare kernel module attribute for sysfs */
37+
38+ struct kmldrv_attr {
39+ char display ;
40+ char restart ;
41+ char end ;
42+ rwlock_t lock ;
43+ };
44+
45+ static struct kmldrv_attr attr_obj ;
46+
47+ static ssize_t kmldrv_state_show (struct device * dev ,
48+ struct device_attribute * attr ,
49+ char * buf )
50+ {
51+ read_lock (& attr_obj .lock );
52+ int ret = snprintf (buf , 6 , "%c %c %c\n" , attr_obj .display , attr_obj .restart ,
53+ attr_obj .end );
54+ read_unlock (& attr_obj .lock );
55+ return ret ;
56+ }
57+
58+ static ssize_t kmldrv_state_store (struct device * dev ,
59+ struct device_attribute * attr ,
60+ const char * buf ,
61+ size_t count )
62+ {
63+ write_lock (& attr_obj .lock );
64+ sscanf (buf , "%c %c %c" , & (attr_obj .display ), & (attr_obj .restart ),
65+ & (attr_obj .end ));
66+ write_unlock (& attr_obj .lock );
67+ return count ;
68+ }
69+
70+ static DEVICE_ATTR_RW (kmldrv_state );
71+
3572/* Data produced by the simulated device */
3673
3774/* Timer to simulate a periodic IRQ */
@@ -135,16 +172,21 @@ static void drawboard_work_func(struct work_struct *w)
135172 pr_info ("kmldrv: [CPU#%d] %s\n" , cpu , __func__ );
136173 put_cpu ();
137174
175+ read_lock (& attr_obj .lock );
176+ if (attr_obj .display == '0' ) {
177+ read_unlock (& attr_obj .lock );
178+ return ;
179+ }
180+ read_unlock (& attr_obj .lock );
181+
138182 mutex_lock (& producer_lock );
139183 draw_board (table );
140184 mutex_unlock (& producer_lock );
141185
142186 /* Store data to the kfifo buffer */
143- // mutex_lock(&producer_lock);
144187 mutex_lock (& consumer_lock );
145188 produce_board ();
146189 mutex_unlock (& consumer_lock );
147- // mutex_unlock(&producer_lock);
148190
149191 wake_up_interruptible (& rx_wait );
150192}
@@ -300,24 +342,28 @@ static void timer_handler(struct timer_list *__timer)
300342
301343 if (win == ' ' ) {
302344 ai_game ();
303- mod_timer (& timer , jiffies + msecs_to_jiffies (delay ));
304345 } else {
305- int cpu = get_cpu ();
306- pr_info ("kmldrv: [CPU#%d] Drawing final board\n" , cpu );
307- put_cpu ();
308-
309- mutex_lock (& producer_lock );
310- draw_board (table );
311- mutex_unlock (& producer_lock );
312-
313- /* Store data to the kfifo buffer */
314- mutex_lock (& consumer_lock );
315- produce_board ();
316- mutex_unlock (& consumer_lock );
317-
318- wake_up_interruptible (& rx_wait );
346+ read_lock (& attr_obj .lock );
347+ if (attr_obj .display == '1' ) {
348+ int cpu = get_cpu ();
349+ pr_info ("kmldrv: [CPU#%d] Drawing final board\n" , cpu );
350+ put_cpu ();
351+
352+ mutex_lock (& producer_lock );
353+ draw_board (table );
354+ mutex_unlock (& producer_lock );
355+
356+ /* Store data to the kfifo buffer */
357+ mutex_lock (& consumer_lock );
358+ produce_board ();
359+ mutex_unlock (& consumer_lock );
360+
361+ wake_up_interruptible (& rx_wait );
362+ }
363+ read_unlock (& attr_obj .lock );
319364
320365 pr_info ("kmldrv: %c win!!!\n" , win );
366+ memset (table , ' ' , N_GRIDS ); /* Reset the table so the game restart */
321367 }
322368 tv_end = ktime_get ();
323369
@@ -326,6 +372,8 @@ static void timer_handler(struct timer_list *__timer)
326372 pr_info ("kmldrv: [CPU#%d] %s in_irq: %llu usec\n" , smp_processor_id (),
327373 __func__ , (unsigned long long ) nsecs >> 10 );
328374
375+ mod_timer (& timer , jiffies + msecs_to_jiffies (delay ));
376+
329377 local_irq_enable ();
330378}
331379
@@ -433,7 +481,14 @@ static int __init kmldrv_init(void)
433481 }
434482
435483 /* Register the device with sysfs */
436- device_create (kmldrv_class , NULL , MKDEV (major , 0 ), NULL , DEV_NAME );
484+ struct device * kmldrv_dev =
485+ device_create (kmldrv_class , NULL , MKDEV (major , 0 ), NULL , DEV_NAME );
486+
487+ ret = device_create_file (kmldrv_dev , & dev_attr_kmldrv_state );
488+ if (ret < 0 ) {
489+ printk (KERN_ERR "failed to create sysfs file kmldrv_state\n" );
490+ goto error_cdev ;
491+ }
437492
438493 /* Allocate fast circular buffer */
439494 fast_buf .buf = vmalloc (PAGE_SIZE );
@@ -458,6 +513,11 @@ static int __init kmldrv_init(void)
458513 memset (table , ' ' , N_GRIDS );
459514 turn = 'O' ;
460515 finish = 1 ;
516+
517+ attr_obj .display = '1' ;
518+ attr_obj .restart = '0' ;
519+ attr_obj .end = '0' ;
520+ rwlock_init (& attr_obj .lock );
461521 /* Setup the timer */
462522 timer_setup (& timer , timer_handler , 0 );
463523 atomic_set (& open_cnt , 0 );
0 commit comments