⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccwcache.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
字号:
/*  * File...........: linux/drivers/s390/ccwcache.c * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> *                  Martin Schiwdefsky <schwidefsky@de.ibm.com> * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000a  * History of changes * 11/14/00 redesign by Martin Schwidefsky */#include <linux/module.h>#include <linux/slab.h>#include <linux/version.h>#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))#include <linux/spinlock.h>#else#include <asm/spinlock.h>#endif#include <asm/debug.h>#include <asm/ccwcache.h>#include <asm/ebcdic.h>#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))#define CCW_CACHE_SLAB_TYPE (SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA)#define CCW_CACHE_TYPE (GFP_ATOMIC | GFP_DMA)#else#define CCW_CACHE_SLAB_TYPE (SLAB_HWCACHE_ALIGN)#define CCW_CACHE_TYPE (GFP_ATOMIC)#define kmem_cache_destroy(x) do {} while(0)#endif#undef PRINTK_HEADER#define PRINTK_HEADER "ccwcache"/* pointer to list of allocated requests */static ccw_req_t *ccwreq_actual = NULL;static spinlock_t ccwchain_lock;/* pointer to debug area */static debug_info_t *debug_area = NULL;/* SECTION: Handling of the dynamically allocated kmem slabs *//* a name template for the cache-names */static char ccw_name_template[] = "ccwcache-\0\0\0\0"; /* fill name with zeroes! *//* the cache's names */static char ccw_cache_name[CCW_NUMBER_CACHES][sizeof(ccw_name_template)+1]; /* the caches itself*/static kmem_cache_t *ccw_cache[CCW_NUMBER_CACHES]; /* SECTION: (de)allocation of ccw_req_t *//*  * void enchain ( ccw_req_t *request ) * enchains the request to the ringbuffer */static inline void enchain ( ccw_req_t *request ){	unsigned long flags;	/* Sanity checks */	if ( request == NULL )		BUG();	spin_lock_irqsave(&ccwchain_lock,flags);	if ( ccwreq_actual == NULL ) { /* queue empty */		ccwreq_actual = request;		request->int_prev = ccwreq_actual;		request->int_next = ccwreq_actual;	} else {		request->int_next = ccwreq_actual;		request->int_prev = ccwreq_actual->int_prev;		request->int_prev->int_next = request;		request->int_next->int_prev = request;	}	spin_unlock_irqrestore(&ccwchain_lock,flags);}/*  * void dechain ( ccw_req_t *request ) * dechains the request from the ringbuffer */static inline void dechain ( ccw_req_t *request ){	unsigned long flags;	/* Sanity checks */	if ( request == NULL || 	     request->int_next == NULL ||	     request->int_prev == NULL)		BUG();	/* first deallocate request from list of allocates requests */	spin_lock_irqsave(&ccwchain_lock,flags);	if ( request -> int_next == request -> int_prev ) {		ccwreq_actual = NULL;	} else {		if ( ccwreq_actual == request ) {			ccwreq_actual = request->int_next;		}		request->int_prev->int_next = request->int_next;		request->int_next->int_prev = request->int_prev;	}	spin_unlock_irqrestore(&ccwchain_lock,flags);}/*  * ccw_req_t *ccw_alloc_request ( int cplength, int datasize ) * allocates a ccw_req_t, that  * - can hold a CP of cplength CCWS * - can hold additional data up to datasize  */ccw_req_t *ccw_alloc_request ( char *magic, int cplength, int datasize ){	ccw_req_t * request = NULL;        int size_needed;	int data_offset, ccw_offset;	int cachind;	/* Sanity checks */	if ( magic == NULL || datasize > PAGE_SIZE ||	     cplength == 0 || (cplength*sizeof(ccw1_t)) > PAGE_SIZE)		BUG();	debug_text_event ( debug_area, 1, "ALLC");	debug_text_event ( debug_area, 1, magic);	debug_int_event ( debug_area, 1, cplength);	debug_int_event ( debug_area, 1, datasize);	/* We try to keep things together in memory */	size_needed = (sizeof (ccw_req_t) + 7) & -8;	data_offset = ccw_offset = 0;	if (size_needed + datasize <= PAGE_SIZE) {		/* Keep data with the request */		data_offset = size_needed;		size_needed += (datasize + 7) & -8;	}	if (size_needed + cplength*sizeof(ccw1_t) <= PAGE_SIZE) {		/* Keep CCWs with request */		ccw_offset = size_needed;		size_needed += cplength*sizeof(ccw1_t);	}	/* determine cache index for the requested size */	for (cachind = 0; cachind < CCW_NUMBER_CACHES; cachind ++ )	   if ( size_needed < (SMALLEST_SLAB << cachind) ) 			break;	/* Try to fulfill the request from a cache */	if ( ccw_cache[cachind] == NULL )		BUG();	request = kmem_cache_alloc ( ccw_cache[cachind], CCW_CACHE_TYPE );	if (request == NULL)		return NULL;	memset ( request, 0, (SMALLEST_SLAB << cachind));	request->cache = ccw_cache[cachind];	/* Allocate memory for the extra data */	if (data_offset == 0) {		/* Allocated memory for extra data with kmalloc */	    request->data = (void *) kmalloc(datasize, CCW_CACHE_TYPE );		if (request->data == NULL) {			printk(KERN_WARNING PRINTK_HEADER 			       "Couldn't allocate data area\n");			kmem_cache_free(request->cache, request);			return NULL;		}	} else		/* Extra data already allocated with the request */		request->data = (void *) ((addr_t) request + data_offset);	/* Allocate memory for the channel program */	if (ccw_offset == 0) {		/* Allocated memory for the channel program with kmalloc */		request->cpaddr = (ccw1_t *) kmalloc(cplength*sizeof(ccw1_t),						     CCW_CACHE_TYPE);		if (request->cpaddr == NULL) {			printk (KERN_DEBUG PRINTK_HEADER				"Couldn't allocate ccw area\n");			if (data_offset == 0)				kfree(request->data);			kmem_cache_free(request->cache, request);			return NULL;		}	} else		/* Channel program already allocated with the request */		request->cpaddr = (ccw1_t *) ((addr_t) request + ccw_offset);	memset ( request->data, 0, datasize );	memset ( request->cpaddr, 0, cplength*sizeof(ccw1_t) );	strncpy ( (char *)(&request->magic), magic, 4);	ASCEBC((char *)(&request->magic),4);	request -> cplength = cplength;	request -> datasize = datasize;	/* enqueue request to list of allocated requests */	enchain(request);	debug_int_event ( debug_area, 1, (long)request);	return request;}/*  * void ccw_free_request ( ccw_req_t * ) * deallocates the ccw_req_t, given as argument */voidccw_free_request ( ccw_req_t * request ){        int size_needed;	debug_text_event ( debug_area, 1, "FREE");	debug_int_event ( debug_area, 1, (long)request);	/* Sanity checks */	if ( request == NULL || request->cache == NULL)                BUG();        dechain ( request);	/* Free memory allocated with kmalloc         * make the same decisions as in ccw_alloc_requets */	size_needed = (sizeof (ccw_req_t) + 7) & -8;	if (size_needed + request->datasize <= PAGE_SIZE)		/* We kept the data with the request */		size_needed += (request->datasize + 7) & -8;	else		kfree(request->data);	if (size_needed + request->cplength*sizeof(ccw1_t) > PAGE_SIZE)		/* We kept the CCWs with request */                kfree(request->cpaddr);        kmem_cache_free(request -> cache, request);}/* SECTION: initialization and cleanup functions *//*  * ccwcache_init * called as an initializer function for the ccw memory management */intccwcache_init (void){	int rc = 0;	int cachind;        /* initialize variables */	spin_lock_init(&ccwchain_lock);	/* allocate a debug area */	debug_area = debug_register( "ccwcache", 2, 4,sizeof(void*));	if ( debug_area == NULL )                BUG();        debug_register_view(debug_area,&debug_hex_ascii_view);        debug_register_view(debug_area,&debug_raw_view);	debug_text_event ( debug_area, 0, "INIT");	/* First allocate the kmem caches */	for ( cachind = 0; cachind < CCW_NUMBER_CACHES; cachind ++ ) {		int slabsize = SMALLEST_SLAB << cachind;		debug_text_event ( debug_area, 1, "allc");		debug_int_event ( debug_area, 1, slabsize);		sprintf ( ccw_cache_name[cachind], 			  "%s%d%c", ccw_name_template, slabsize, 0);		ccw_cache[cachind] = 			kmem_cache_create( ccw_cache_name[cachind], 					   slabsize, 0,					   CCW_CACHE_SLAB_TYPE,					   NULL, NULL );		debug_int_event ( debug_area, 1, (long)ccw_cache[cachind]);		if (ccw_cache[cachind] == NULL)			panic ("Allocation of CCW cache failed\n");	}	return rc;}/*  * ccwcache_cleanup * called as a cleanup function for the ccw memory management */voidccwcache_cleanup (void){	int cachind;	/* Shrink the caches, if available */	for ( cachind = 0; cachind < CCW_NUMBER_CACHES; cachind ++ ) {		if ( ccw_cache[cachind] ) {			if ( kmem_cache_shrink(ccw_cache[cachind]) == 0 ) {				ccw_cache[cachind] = NULL;			}			kmem_cache_destroy(ccw_cache[cachind]);		}	}	debug_unregister( debug_area );}EXPORT_SYMBOL(ccw_alloc_request);EXPORT_SYMBOL(ccw_free_request);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -