From eb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 3 Jan 1999 17:49:53 +0000 Subject: Merge with Linux 2.1.131 plus some more MIPS goodies. --- arch/m68k/atari/ataints.c | 10 +- arch/m68k/atari/stram.c | 259 +++++++++++++++++++++------------------------- arch/m68k/atari/time.c | 3 +- 3 files changed, 125 insertions(+), 147 deletions(-) (limited to 'arch/m68k/atari') diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 15e4c2d09..0f6ddf111 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -419,6 +419,7 @@ int atari_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r unsigned long flags, const char *devname, void *dev_id) { int vector; + unsigned long oflags = flags; /* * The following is a hack to make some PCI card drivers work, @@ -427,9 +428,14 @@ int atari_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r flags &= ~SA_SHIRQ; + if (flags == SA_INTERRUPT) { + printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n", + __FUNCTION__, devname); + flags = IRQ_TYPE_SLOW; + } if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) { - printk ("%s: Bad irq type %ld requested from %s\n", - __FUNCTION__, flags, devname); + printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n", + __FUNCTION__, flags, oflags, devname); return -EINVAL; } if (!IS_VALID_INTNO(irq)) { diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index b3741ed96..cade2173a 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -19,6 +19,8 @@ #include #include #include +#include + #include #include #include @@ -26,6 +28,7 @@ #include #include #include +#include #ifdef CONFIG_STRAM_SWAP @@ -116,6 +119,10 @@ * since the freeing algorithms are also blind to DMA capability of pages. */ +/* 1998-10-20: ++andreas + unswap_by_move disabled because it does not handle swapped shm pages. +*/ + #ifdef CONFIG_STRAM_SWAP #define ALIGN_IF_SWAP(x) PAGE_ALIGN(x) #else @@ -192,6 +199,9 @@ static struct swap_info_struct *stram_swap_info; /* The ST-RAM's swap type */ static int stram_swap_type; +/* Semaphore for get_stram_region. */ +static struct semaphore stram_swap_sem = MUTEX; + /* major and minor device number of the ST-RAM device; for the major, we use * the same as Amiga z2ram, which is really similar and impossible on Atari, * and for the minor a relatively odd number to avoid the user creating and @@ -215,25 +225,6 @@ static unsigned stat_swap_force = 0; #ifdef CONFIG_STRAM_SWAP static int swap_init( unsigned long start_mem, unsigned long swap_data ); -static inline int unswap_pte( struct vm_area_struct * vma, unsigned long - address, pte_t *dir, unsigned long entry, - unsigned long page, int isswap ); -static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir, - unsigned long address, unsigned long size, - unsigned long offset, unsigned long entry, - unsigned long page, int isswap ); -static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir, - unsigned long address, unsigned long size, - unsigned long entry, unsigned long page, int - isswap ); -static int unswap_vma( struct vm_area_struct * vma, pgd_t *pgdir, unsigned - long entry, unsigned long page, int isswap ); -static int unswap_process( struct mm_struct * mm, unsigned long entry, - unsigned long page, int isswap ); -static int unswap_by_move(unsigned short *, unsigned long, unsigned long, - unsigned long); -static int unswap_by_read(unsigned short *, unsigned long, unsigned long, - unsigned long); static void *get_stram_region( unsigned long n_pages ); static void free_stram_region( unsigned long offset, unsigned long n_pages ); @@ -263,7 +254,7 @@ static int remove_region( BLOCK *block ); * This init function is called very early by atari/config.c * It initializes some internal variables needed for stram_alloc() */ -__initfunc(void atari_stram_init( void )) +void __init atari_stram_init(void) { int i; @@ -273,7 +264,7 @@ __initfunc(void atari_stram_init( void )) /* determine whether kernel code resides in ST-RAM (then ST-RAM is the * first memory block at virtual 0x0) */ - stram_start = phys_to_virt( 0 ); + stram_start = (unsigned long)phys_to_virt(0); kernel_in_stram = (stram_start == 0); for( i = 0; i < m68k_num_memory; ++i ) { @@ -294,7 +285,7 @@ __initfunc(void atari_stram_init( void )) * This function is called from mem_init() to reserve the pages needed for * ST-RAM management. */ -__initfunc(void atari_stram_reserve_pages( unsigned long start_mem )) +void __init atari_stram_reserve_pages(unsigned long start_mem) { #ifdef CONFIG_STRAM_SWAP /* if max_swap_size is negative (i.e. no stram_swap= option given), @@ -573,8 +564,7 @@ void atari_stram_free( void *addr ) * Initialize ST-RAM swap device * (lots copied and modified from sys_swapon() in mm/swapfile.c) */ -__initfunc(static int swap_init( unsigned long start_mem, - unsigned long swap_data )) +static int __init swap_init(unsigned long start_mem, unsigned long swap_data) { static struct dentry fake_dentry[3]; struct swap_info_struct *p; @@ -691,75 +681,64 @@ __initfunc(static int swap_init( unsigned long start_mem, /* * The swap entry has been read in advance, and we return 1 to indicate * that the page has been used or is no longer needed. + * + * Always set the resulting pte to be nowrite (the same as COW pages + * after one process has exited). We don't know just how many PTEs will + * share this swap entry, so be cautious and let do_wp_page work out + * what to do if a write is requested later. */ -static inline int unswap_pte( struct vm_area_struct * vma, unsigned long - address, pte_t *dir, unsigned long entry, - unsigned long page, int isswap ) +static inline void unswap_pte(struct vm_area_struct * vma, unsigned long + address, pte_t *dir, unsigned long entry, + unsigned long page /*, int isswap */) { pte_t pte = *dir; if (pte_none(pte)) - return 0; + return; if (pte_present(pte)) { - struct page *pg; - unsigned long page_nr = MAP_NR(pte_page(pte)); - unsigned long pg_swap_entry; - - if (page_nr >= max_mapnr) - return 0; - pg = mem_map + page_nr; - if (!(pg_swap_entry = in_swap_cache(pg))) - return 0; - if (pg_swap_entry != entry) - return 0; - if (isswap) { - DPRINTK( "unswap_pte: page %08lx = entry %08lx was in swap cache; " - "exchanging to %08lx\n", - page_address(pg), entry, page ); - pg->offset = page; - swap_free(entry); - return 1; - } - else { - DPRINTK( "unswap_pte: page %08lx = entry %08lx was in swap cache; " - "deleted there\n", page_address(pg), entry ); - delete_from_swap_cache(pg); + /* If this entry is swap-cached, then page must already + hold the right address for any copies in physical + memory */ + if (pte_page(pte) != page) + return; + if (0 /* isswap */) + mem_map[MAP_NR(pte_page(pte))].offset = page; + else + /* We will be removing the swap cache in a moment, so... */ set_pte(dir, pte_mkdirty(pte)); - free_page(page); - return 1; - } + return; } if (pte_val(pte) != entry) - return 0; + return; - if (isswap) { + if (0 /* isswap */) { DPRINTK( "unswap_pte: replacing entry %08lx by %08lx", entry, page ); set_pte(dir, __pte(page)); } else { DPRINTK( "unswap_pte: replacing entry %08lx by new page %08lx", entry, page ); - set_pte(dir, pte_mkwrite(pte_mkdirty(mk_pte(page,vma->vm_page_prot)))); + set_pte(dir, pte_mkdirty(mk_pte(page,vma->vm_page_prot))); + atomic_inc(&mem_map[MAP_NR(page)].count); ++vma->vm_mm->rss; } swap_free(entry); - return 1; } -static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir, - unsigned long address, unsigned long size, - unsigned long offset, unsigned long entry, - unsigned long page, int isswap ) +static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir, + unsigned long address, unsigned long size, + unsigned long offset, unsigned long entry, + unsigned long page /* , int isswap */) { pte_t * pte; unsigned long end; if (pmd_none(*dir)) - return 0; + return; if (pmd_bad(*dir)) { printk("unswap_pmd: bad pmd (%08lx)\n", pmd_val(*dir)); pmd_clear(dir); - return 0; + return; } pte = pte_offset(dir, address); offset += address & PMD_MASK; @@ -768,29 +747,27 @@ static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir, if (end > PMD_SIZE) end = PMD_SIZE; do { - if (unswap_pte( vma, offset+address-vma->vm_start, pte, entry, - page, isswap )) - return 1; + unswap_pte(vma, offset+address-vma->vm_start, pte, entry, + page /* , isswap */); address += PAGE_SIZE; pte++; } while (address < end); - return 0; } -static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir, - unsigned long address, unsigned long size, - unsigned long entry, unsigned long page, - int isswap ) +static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir, + unsigned long address, unsigned long size, + unsigned long entry, unsigned long page + /* , int isswap */) { pmd_t * pmd; unsigned long offset, end; if (pgd_none(*dir)) - return 0; + return; if (pgd_bad(*dir)) { printk("unswap_pgd: bad pgd (%08lx)\n", pgd_val(*dir)); pgd_clear(dir); - return 0; + return; } pmd = pmd_offset(dir, address); offset = address & PGDIR_MASK; @@ -799,53 +776,45 @@ static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir, if (end > PGDIR_SIZE) end = PGDIR_SIZE; do { - if (unswap_pmd( vma, pmd, address, end - address, offset, entry, - page, isswap )) - return 1; + unswap_pmd(vma, pmd, address, end - address, offset, entry, + page /* , isswap */); address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address < end); - return 0; } -static int unswap_vma( struct vm_area_struct * vma, pgd_t *pgdir, - unsigned long entry, unsigned long page, int isswap ) +static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir, + unsigned long entry, unsigned long page + /* , int isswap */) { unsigned long start = vma->vm_start, end = vma->vm_end; - while( start < end ) { - if (unswap_pgd( vma, pgdir, start, end - start, entry, page, isswap )) - return 1; + while (start < end) { + unswap_pgd(vma, pgdir, start, end - start, entry, page + /* , isswap */); start = (start + PGDIR_SIZE) & PGDIR_MASK; pgdir++; } - return 0; } -static int unswap_process( struct mm_struct * mm, unsigned long entry, - unsigned long page, int isswap ) +static void unswap_process(struct mm_struct * mm, unsigned long entry, + unsigned long page /* , int isswap */) { struct vm_area_struct* vma; - int retval = 0; /* * Go through process' page directory. */ if (!mm || mm == &init_mm) - return 0; - down(&mm->mmap_sem); - for( vma = mm->mmap; vma; vma = vma->vm_next ) { + return; + for (vma = mm->mmap; vma; vma = vma->vm_next) { pgd_t * pgd = pgd_offset(mm, vma->vm_start); - if (unswap_vma( vma, pgd, entry, page, isswap )) { - retval = 1; - break; - } + unswap_vma(vma, pgd, entry, page /* , isswap */); } - up(&mm->mmap_sem); - return retval; } +#if 0 static int unswap_by_move(unsigned short *map, unsigned long max, unsigned long start, unsigned long n_pages) { @@ -899,14 +868,17 @@ static int unswap_by_move(unsigned short *map, unsigned long max, #endif while( map[i] ) { + read_lock(&tasklist_lock); for_each_task(p) { if (unswap_process( p->mm, SWP_ENTRY( stram_swap_type, i ), entry, 1 )) { + read_unlock(&tasklist_lock); map[j]++; goto repeat; } } - if (map[i] && map[i] != 127) { + read_unlock(&tasklist_lock); + if (map[i] && map[i] != SWAP_MAP_MAX) { printk( KERN_ERR "get_stram_region: ST-RAM swap page %lu " "not used by any process\n", i ); /* quit while loop and overwrite bad map entry */ @@ -932,13 +904,15 @@ static int unswap_by_move(unsigned short *map, unsigned long max, } return( 0 ); } +#endif static int unswap_by_read(unsigned short *map, unsigned long max, unsigned long start, unsigned long n_pages) { struct task_struct *p; - unsigned long entry, page = 0; + unsigned long entry, page; unsigned long i; + struct page *page_map; DPRINTK( "unswapping %lu..%lu by reading in\n", start, start+n_pages-1 ); @@ -949,43 +923,35 @@ static int unswap_by_read(unsigned short *map, unsigned long max, "reserved??\n", i ); continue; } - entry = SWP_ENTRY( stram_swap_type, i ); - DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n", - i, map[i], nr_swap_pages ); - while( map[i] ) { - if (!page && !(page = __get_free_page(GFP_KERNEL))) { - printk( KERN_NOTICE "get_stram_region: out of memory\n" ); - return( -ENOMEM ); - } - DPRINTK( "unswap: reading swap page %lu to %08lx\n", i, page ); - rw_swap_page( READ, entry, (char *)page, 1 ); - - for_each_task(p) { - if (unswap_process( p->mm, entry, page, 0 )) { - page = 0; -#ifdef DO_PROC - stat_swap_force++; -#endif - break; - } - } - if (page) { - /* - * If we couldn't find an entry, there are several - * possible reasons: someone else freed it first, - * we freed the last reference to an overflowed entry, - * or the system has lost track of the use counts. - */ - if (map[i] && map[i] != SWAP_MAP_MAX) - printk( KERN_ERR "get_stram_region: swap entry %08lx " - "not used by any process\n", entry ); - /* quit while loop and overwrite bad map entry */ - if (!map[i]) { - DPRINTK( "unswap: map[i] became 0\n" ); - } - break; + if (map[i]) { + entry = SWP_ENTRY(stram_swap_type, i); + DPRINTK("unswap: map[i=%lu]=%u nr_swap=%u\n", + i, map[i], nr_swap_pages); + + /* Get a page for the entry, using the existing + swap cache page if there is one. Otherwise, + get a clean page and read the swap into it. */ + page_map = read_swap_cache(entry); + if (page_map) { + page = page_address(page_map); + read_lock(&tasklist_lock); + for_each_task(p) + unswap_process(p->mm, entry, page + /* , 0 */); + read_unlock(&tasklist_lock); + shm_unuse(entry, page); + /* Now get rid of the extra reference to + the temporary page we've been using. */ + if (PageSwapCache(page_map)) + delete_from_swap_cache(page_map); + __free_page(page_map); + #ifdef DO_PROC + stat_swap_force++; + #endif } + else if (map[i]) + return -ENOMEM; } DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n", @@ -998,9 +964,7 @@ static int unswap_by_read(unsigned short *map, unsigned long max, --nr_swap_pages; } - if (page) - free_page(page); - return( 0 ); + return 0; } /* @@ -1015,7 +979,9 @@ static void *get_stram_region( unsigned long n_pages ) void *ret = NULL; DPRINTK( "get_stram_region(n_pages=%lu)\n", n_pages ); - + + down(&stram_swap_sem); + /* disallow writing to the swap device now */ stram_swap_info->flags = SWP_USED; @@ -1026,9 +992,14 @@ static void *get_stram_region( unsigned long n_pages ) DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n", start, region_free ); +#if 0 err = ((total_free-region_free >= n_pages-region_free) ? unswap_by_move( map, max, start, n_pages ) : unswap_by_read( map, max, start, n_pages )); +#else + err = unswap_by_read(map, max, start, n_pages); +#endif + if (err) goto end; @@ -1036,6 +1007,7 @@ static void *get_stram_region( unsigned long n_pages ) end: /* allow using swap device again */ stram_swap_info->flags = SWP_WRITEOK; + up(&stram_swap_sem); DPRINTK( "get_stram_region: returning %p\n", ret ); return( ret ); } @@ -1110,7 +1082,7 @@ static unsigned long find_free_region(unsigned long n_pages, start_over: /* increment tail until final window size reached, and count free pages */ nfree = 0; - for( tail = head; tail-head < n_pages && tail < max-n_pages; ++tail ) { + for( tail = head; tail-head < n_pages && tail < max; ++tail ) { if (map[tail] == SWAP_MAP_BAD) { head = tail+1; goto start_over; @@ -1165,7 +1137,7 @@ static unsigned long find_free_region(unsigned long n_pages, /* setup parameters from command line */ -__initfunc(void stram_swap_setup(char *str, int *ints)) +void __init stram_swap_setup(char *str, int *ints) { if (ints[0] >= 1) max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK; @@ -1262,7 +1234,7 @@ static struct file_operations stram_fops = { block_fsync /* fsync */ }; -__initfunc(int stram_device_init(void)) +int __init stram_device_init(void) { if (!MACH_IS_ATARI) @@ -1465,9 +1437,10 @@ int get_stram_list( char *buf ) for( p = alloc_list; p; p = p->next ) { if (len + 50 >= PAGE_SIZE) break; - PRINT_PROC( "0x%08lx-0x%08lx: %s (", - virt_to_phys(p->start), - virt_to_phys(p->start+p->size-1), p->owner ); + PRINT_PROC("0x%08lx-0x%08lx: %s (", + virt_to_phys((void *)p->start), + virt_to_phys((void *)p->start+p->size-1), + p->owner); if (p->flags & BLOCK_STATIC) PRINT_PROC( "static)\n" ); else if (p->flags & BLOCK_GFP) diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c index 79c4f48f2..0fd3795a5 100644 --- a/arch/m68k/atari/time.c +++ b/arch/m68k/atari/time.c @@ -279,8 +279,7 @@ int atari_tt_hwclk( int op, struct hwclk_time *t ) while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + HWCLK_POLL_INTERVAL; - schedule(); + schedule_timeout(HWCLK_POLL_INTERVAL); } save_flags(flags); -- cgit v1.2.3