Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.16 130 lines 3.3 kB view raw
1/* 2 * Copyright (C) 1997 Claus-Justus Heine 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; see the file COPYING. If not, write to 16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 17 18 * 19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.c,v $ 20 * $Revision: 1.3 $ 21 * $Date: 1997/10/16 23:33:11 $ 22 * 23 * This file contains the allocator/dealloctor for ftape's dynamic dma 24 * buffer. 25 */ 26 27#include <linux/slab.h> 28#include <linux/mm.h> 29#include <linux/mman.h> 30#include <asm/dma.h> 31 32#include <linux/ftape.h> 33#include "../lowlevel/ftape-rw.h" 34#include "../lowlevel/ftape-read.h" 35#include "../lowlevel/ftape-tracing.h" 36#include "../lowlevel/ftape-buffer.h" 37 38/* DMA'able memory allocation stuff. 39 */ 40 41static inline void *dmaalloc(size_t size) 42{ 43 unsigned long addr; 44 45 if (size == 0) { 46 return NULL; 47 } 48 addr = __get_dma_pages(GFP_KERNEL, get_order(size)); 49 if (addr) { 50 struct page *page; 51 52 for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++) 53 SetPageReserved(page); 54 } 55 return (void *)addr; 56} 57 58static inline void dmafree(void *addr, size_t size) 59{ 60 if (size > 0) { 61 struct page *page; 62 63 for (page = virt_to_page((unsigned long)addr); 64 page < virt_to_page((unsigned long)addr+size); page++) 65 ClearPageReserved(page); 66 free_pages((unsigned long) addr, get_order(size)); 67 } 68} 69 70static int add_one_buffer(void) 71{ 72 TRACE_FUN(ft_t_flow); 73 74 if (ft_nr_buffers >= FT_MAX_NR_BUFFERS) { 75 TRACE_EXIT -ENOMEM; 76 } 77 ft_buffer[ft_nr_buffers] = kmalloc(sizeof(buffer_struct), GFP_KERNEL); 78 if (ft_buffer[ft_nr_buffers] == NULL) { 79 TRACE_EXIT -ENOMEM; 80 } 81 memset(ft_buffer[ft_nr_buffers], 0, sizeof(buffer_struct)); 82 ft_buffer[ft_nr_buffers]->address = dmaalloc(FT_BUFF_SIZE); 83 if (ft_buffer[ft_nr_buffers]->address == NULL) { 84 kfree(ft_buffer[ft_nr_buffers]); 85 ft_buffer[ft_nr_buffers] = NULL; 86 TRACE_EXIT -ENOMEM; 87 } 88 ft_nr_buffers ++; 89 TRACE(ft_t_info, "buffer nr #%d @ %p, dma area @ %p", 90 ft_nr_buffers, 91 ft_buffer[ft_nr_buffers-1], 92 ft_buffer[ft_nr_buffers-1]->address); 93 TRACE_EXIT 0; 94} 95 96static void del_one_buffer(void) 97{ 98 TRACE_FUN(ft_t_flow); 99 if (ft_nr_buffers > 0) { 100 TRACE(ft_t_info, "releasing buffer nr #%d @ %p, dma area @ %p", 101 ft_nr_buffers, 102 ft_buffer[ft_nr_buffers-1], 103 ft_buffer[ft_nr_buffers-1]->address); 104 ft_nr_buffers --; 105 dmafree(ft_buffer[ft_nr_buffers]->address, FT_BUFF_SIZE); 106 kfree(ft_buffer[ft_nr_buffers]); 107 ft_buffer[ft_nr_buffers] = NULL; 108 } 109 TRACE_EXIT; 110} 111 112int ftape_set_nr_buffers(int cnt) 113{ 114 int delta = cnt - ft_nr_buffers; 115 TRACE_FUN(ft_t_flow); 116 117 if (delta > 0) { 118 while (delta--) { 119 if (add_one_buffer() < 0) { 120 TRACE_EXIT -ENOMEM; 121 } 122 } 123 } else if (delta < 0) { 124 while (delta++) { 125 del_one_buffer(); 126 } 127 } 128 ftape_zap_read_buffers(); 129 TRACE_EXIT 0; 130}