313 lines · 8.1 KB · C
RawDownload
/* *	Functions to handle I2O memory * *	Pulled from the inlines in i2o headers and uninlined * * *	This program is free software; you can redistribute it and/or modify it *	under the terms of the GNU General Public License as published by the *	Free Software Foundation; either version 2 of the License, or (at your *	option) any later version. */ #include <linux/module.h>#include <linux/i2o.h>#include <linux/delay.h>#include <linux/string.h>#include <linux/slab.h>#include "core.h" /* Protects our 32/64bit mask switching */static DEFINE_MUTEX(mem_lock); /** *	i2o_sg_tablesize - Calculate the maximum number of elements in a SGL *	@c: I2O controller for which the calculation should be done *	@body_size: maximum body size used for message in 32-bit words. * *	Return the maximum number of SG elements in a SG list. */u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size){	i2o_status_block *sb = c->status_block.virt;	u16 sg_count =	    (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) -	    body_size; 	if (c->pae_support) {		/*		 * for 64-bit a SG attribute element must be added and each		 * SG element needs 12 bytes instead of 8.		 */		sg_count -= 2;		sg_count /= 3;	} else		sg_count /= 2; 	if (c->short_req && (sg_count > 8))		sg_count = 8; 	return sg_count;}EXPORT_SYMBOL_GPL(i2o_sg_tablesize);  /** *	i2o_dma_map_single - Map pointer to controller and fill in I2O message. *	@c: I2O controller *	@ptr: pointer to the data which should be mapped *	@size: size of data in bytes *	@direction: DMA_TO_DEVICE / DMA_FROM_DEVICE *	@sg_ptr: pointer to the SG list inside the I2O message * *	This function does all necessary DMA handling and also writes the I2O *	SGL elements into the I2O message. For details on DMA handling see also *	dma_map_single(). The pointer sg_ptr will only be set to the end of the *	SG list if the allocation was successful. * *	Returns DMA address which must be checked for failures using *	dma_mapping_error(). */dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,					    size_t size,					    enum dma_data_direction direction,					    u32 ** sg_ptr){	u32 sg_flags;	u32 *mptr = *sg_ptr;	dma_addr_t dma_addr; 	switch (direction) {	case DMA_TO_DEVICE:		sg_flags = 0xd4000000;		break;	case DMA_FROM_DEVICE:		sg_flags = 0xd0000000;		break;	default:		return 0;	} 	dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);	if (!dma_mapping_error(&c->pdev->dev, dma_addr)) {#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64		if ((sizeof(dma_addr_t) > 4) && c->pae_support) {			*mptr++ = cpu_to_le32(0x7C020002);			*mptr++ = cpu_to_le32(PAGE_SIZE);		}#endif 		*mptr++ = cpu_to_le32(sg_flags | size);		*mptr++ = cpu_to_le32(i2o_dma_low(dma_addr));#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64		if ((sizeof(dma_addr_t) > 4) && c->pae_support)			*mptr++ = cpu_to_le32(i2o_dma_high(dma_addr));#endif		*sg_ptr = mptr;	}	return dma_addr;}EXPORT_SYMBOL_GPL(i2o_dma_map_single); /** *	i2o_dma_map_sg - Map a SG List to controller and fill in I2O message. *	@c: I2O controller *	@sg: SG list to be mapped *	@sg_count: number of elements in the SG list *	@direction: DMA_TO_DEVICE / DMA_FROM_DEVICE *	@sg_ptr: pointer to the SG list inside the I2O message * *	This function does all necessary DMA handling and also writes the I2O *	SGL elements into the I2O message. For details on DMA handling see also *	dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG *	list if the allocation was successful. * *	Returns 0 on failure or 1 on success. */int i2o_dma_map_sg(struct i2o_controller *c, struct scatterlist *sg,	    int sg_count, enum dma_data_direction direction, u32 ** sg_ptr){	u32 sg_flags;	u32 *mptr = *sg_ptr; 	switch (direction) {	case DMA_TO_DEVICE:		sg_flags = 0x14000000;		break;	case DMA_FROM_DEVICE:		sg_flags = 0x10000000;		break;	default:		return 0;	} 	sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction);	if (!sg_count)		return 0; #ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64	if ((sizeof(dma_addr_t) > 4) && c->pae_support) {		*mptr++ = cpu_to_le32(0x7C020002);		*mptr++ = cpu_to_le32(PAGE_SIZE);	}#endif 	while (sg_count-- > 0) {		if (!sg_count)			sg_flags |= 0xC0000000;		*mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg));		*mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg)));#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64		if ((sizeof(dma_addr_t) > 4) && c->pae_support)			*mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg)));#endif		sg = sg_next(sg);	}	*sg_ptr = mptr; 	return 1;}EXPORT_SYMBOL_GPL(i2o_dma_map_sg); /** *	i2o_dma_alloc - Allocate DMA memory *	@dev: struct device pointer to the PCI device of the I2O controller *	@addr: i2o_dma struct which should get the DMA buffer *	@len: length of the new DMA memory * *	Allocate a coherent DMA memory and write the pointers into addr. * *	Returns 0 on success or -ENOMEM on failure. */int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len){	struct pci_dev *pdev = to_pci_dev(dev);	int dma_64 = 0; 	mutex_lock(&mem_lock);	if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_BIT_MASK(64))) {		dma_64 = 1;		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {			mutex_unlock(&mem_lock);			return -ENOMEM;		}	} 	addr->virt = dma_alloc_coherent(dev, len, &addr->phys, GFP_KERNEL); 	if ((sizeof(dma_addr_t) > 4) && dma_64)		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))			printk(KERN_WARNING "i2o: unable to set 64-bit DMA");	mutex_unlock(&mem_lock); 	if (!addr->virt)		return -ENOMEM; 	memset(addr->virt, 0, len);	addr->len = len; 	return 0;}EXPORT_SYMBOL_GPL(i2o_dma_alloc);  /** *	i2o_dma_free - Free DMA memory *	@dev: struct device pointer to the PCI device of the I2O controller *	@addr: i2o_dma struct which contains the DMA buffer * *	Free a coherent DMA memory and set virtual address of addr to NULL. */void i2o_dma_free(struct device *dev, struct i2o_dma *addr){	if (addr->virt) {		if (addr->phys)			dma_free_coherent(dev, addr->len, addr->virt,					  addr->phys);		else			kfree(addr->virt);		addr->virt = NULL;	}}EXPORT_SYMBOL_GPL(i2o_dma_free);  /** *	i2o_dma_realloc - Realloc DMA memory *	@dev: struct device pointer to the PCI device of the I2O controller *	@addr: pointer to a i2o_dma struct DMA buffer *	@len: new length of memory * *	If there was something allocated in the addr, free it first. If len > 0 *	than try to allocate it and write the addresses back to the addr *	structure. If len == 0 set the virtual address to NULL. * *	Returns the 0 on success or negative error code on failure. */int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len){	i2o_dma_free(dev, addr); 	if (len)		return i2o_dma_alloc(dev, addr, len); 	return 0;}EXPORT_SYMBOL_GPL(i2o_dma_realloc); /* *	i2o_pool_alloc - Allocate an slab cache and mempool *	@mempool: pointer to struct i2o_pool to write data into. *	@name: name which is used to identify cache *	@size: size of each object *	@min_nr: minimum number of objects * *	First allocates a slab cache with name and size. Then allocates a *	mempool which uses the slab cache for allocation and freeing. * *	Returns 0 on success or negative error code on failure. */int i2o_pool_alloc(struct i2o_pool *pool, const char *name,				 size_t size, int min_nr){	pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL);	if (!pool->name)		goto exit;	strcpy(pool->name, name); 	pool->slab =	    kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL);	if (!pool->slab)		goto free_name; 	pool->mempool = mempool_create_slab_pool(min_nr, pool->slab);	if (!pool->mempool)		goto free_slab; 	return 0; free_slab:	kmem_cache_destroy(pool->slab); free_name:	kfree(pool->name); exit:	return -ENOMEM;}EXPORT_SYMBOL_GPL(i2o_pool_alloc); /* *	i2o_pool_free - Free slab cache and mempool again *	@mempool: pointer to struct i2o_pool which should be freed * *	Note that you have to return all objects to the mempool again before *	calling i2o_pool_free(). */void i2o_pool_free(struct i2o_pool *pool){	mempool_destroy(pool->mempool);	kmem_cache_destroy(pool->slab);	kfree(pool->name);};EXPORT_SYMBOL_GPL(i2o_pool_free);