1010#define PROC_FILENAME_MAXLENGTH 20
1111
1212static ack_proc_file * ack_proc_file_list = NULL ;
13- /* Queue of processes who want data */
14- DECLARE_WAIT_QUEUE_HEAD (wait_iop_q );
1513/* Queue of processes who want our file */
1614static DECLARE_WAIT_QUEUE_HEAD (waitq );
1715
@@ -154,9 +152,40 @@ static int ami_close(struct inode *inode, struct file *file)
154152 return 0 ; /* success */
155153}
156154
155+ static int ami_mmap (struct file * file , struct vm_area_struct * vma ) {
156+ unsigned long pfn ;
157+ ack_proc_file * read_apf = NULL ;
158+
159+ if (file == NULL ) {
160+ PR_ERR ("ami_mmap: file* %p is NULL" , file );
161+ return - ENODEV ;
162+ }
163+
164+ read_apf = find_ack_proc_file_by_file (file );
165+ if (read_apf == NULL ) {
166+ PR_ERR ("ami_mmap: Ack file corresponding to file* %p not found" , file );
167+ return - EINVAL ;
168+ }
169+ // Get Physical Frame Number (PFN) of our allocated page
170+ pfn = virt_to_phys (read_apf ) >> PAGE_SHIFT ;
171+
172+ if ((vma -> vm_end - vma -> vm_start ) > PAGE_SIZE ) {
173+ PR_ERR ("ami_mmap: mmap request bigger than a page rejected" );
174+ return - EINVAL ;
175+ }
176+ // Map it to user space
177+ if (remap_pfn_range (vma , vma -> vm_start , pfn ,
178+ PAGE_SIZE , vma -> vm_page_prot )) {
179+ return - EAGAIN ;
180+ }
181+
182+ return 0 ;
183+ }
184+
157185static const struct proc_ops file_ops_4_ami_proc_file = {
158186 .proc_read = ami_output , /* "read" from the file */
159187 .proc_write = NULL , /* "write" to the file */
188+ .proc_mmap = ami_mmap ,
160189 .proc_open = ami_open , /* called when the /proc file is opened */
161190 .proc_release = ami_close , /* called when it's closed */
162191 .proc_lseek = noop_llseek , /* return file->f_pos */
@@ -178,7 +207,8 @@ int create_proc_file(unsigned dev_index)
178207 proc_set_size (ami_proc_file , 80 );
179208 proc_set_user (ami_proc_file , GLOBAL_ROOT_UID , GLOBAL_ROOT_GID );
180209
181- new_ack_proc_file = kzalloc (sizeof (struct ack_proc_file ), GFP_KERNEL );
210+ unsigned long page_addr = get_zeroed_page (GFP_KERNEL );
211+ new_ack_proc_file = (ack_proc_file * ) page_addr ;
182212 new_ack_proc_file -> minor_cdev_number = dev_index ;
183213 new_ack_proc_file -> ami_proc_file = ami_proc_file ;
184214 atomic_set (& new_ack_proc_file -> iop_ack_cnt_atomic , 0 );
@@ -216,8 +246,12 @@ unsigned remove_ack_proc_file_by_cdevn(unsigned target_minor_cdev_number) {
216246 prev_apf -> next = current_apf -> next ;
217247 }
218248
249+ if (current_apf -> ami_proc_file ) {
250+ proc_remove (current_apf -> ami_proc_file );
251+ current_apf -> ami_proc_file = NULL ;
252+ }
219253 PR_INFO ("Removed /proc node with minor_cdev_number: %u" , current_apf -> minor_cdev_number );
220- kfree ( current_apf );
254+ free_page (( unsigned long ) current_apf );
221255 return 0 ;
222256 }
223257
@@ -279,17 +313,10 @@ ack_proc_file* find_ack_proc_file_by_file(struct file *file) {
279313
280314int delete_proc_file (unsigned dev_index )
281315{
282- char proc_filename [PROC_FILENAME_MAXLENGTH ];
283-
284316 if (remove_ack_proc_file_by_cdevn (dev_index )) {
285317 // the proc file to delete has not been found
286318 return 1 ;
287319 }
288320
289- snprintf (proc_filename ,PROC_FILENAME_MAXLENGTH ,"%s_%d" ,PROC_ENTRY_FILENAME , dev_index );
290-
291- remove_proc_entry (proc_filename , NULL );
292- PR_INFO ("/proc/%s removed\n" , proc_filename );
293-
294321 return 0 ;
295322}
0 commit comments