From alan@lxorguk.ukuu.org.uk Mon Aug 17 12:35:31 2009 From: Alan Cox Date: Fri, 14 Aug 2009 15:41:50 +0100 Subject: Staging: sep: tidy firmware load To: greg@kroah.com, mark.a.allyn@intel.com Message-ID: <20090814144121.6066.39068.stgit@localhost.localdomain> From: Alan Cox Start by removing unused fields and then work this back to eliminate unused chunks of the firmware loading ioctl (ie almost all of it) Also fix the wrong handling of shared allocations and allocate the rar region properly with dma_alloc_coherent not kmalloc, as it is device shared. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sep/sep_dev.h | 2 drivers/staging/sep/sep_driver.c | 130 +++++++++++------------------------ drivers/staging/sep/sep_driver_api.h | 26 +------ 3 files changed, 48 insertions(+), 110 deletions(-) --- a/drivers/staging/sep/sep_dev.h +++ b/drivers/staging/sep/sep_dev.h @@ -54,7 +54,7 @@ struct sep_device { unsigned long resident_size; void *resident_addr; - unsigned long rar_region_addr; + void *rar_region_addr; /* start address of the access to the SEP registers from driver */ void __iomem *reg_addr; --- a/drivers/staging/sep/sep_driver_api.h +++ b/drivers/staging/sep/sep_driver_api.h @@ -116,32 +116,14 @@ struct sep_driver_init_t { realloc cache resident command */ struct sep_driver_realloc_cache_resident_t { - /* base address */ - unsigned long base_addr; - - /* current cache address */ - unsigned long cache_addr; - - /* cache size in bytes */ - unsigned long cache_size_in_bytes; - - /* current resident address */ - unsigned long resident_addr; - - /* resident size in bytes */ - unsigned long resident_size_in_bytes; - /* new cache address */ - unsigned long new_cache_addr; - + u64 new_cache_addr; /* new resident address */ - unsigned long new_resident_addr; - + u64 new_resident_addr; /* new resident address */ - unsigned long new_shared_area_addr; - + u64 new_shared_area_addr; /* new base address */ - unsigned long new_base_addr; + u64 new_base_addr; }; struct sep_driver_alloc_t { --- a/drivers/staging/sep/sep_driver.c +++ b/drivers/staging/sep/sep_driver.c @@ -170,39 +170,25 @@ static DEFINE_MUTEX(sep_mutex); /* wait queue head (event) of the driver */ static DECLARE_WAIT_QUEUE_HEAD(sep_event); -/* - This functions copies the cache and resident from their source location into - destination memory, which is external to Linux VM and is given as - bus address -*/ -static int sep_copy_cache_resident_to_area(struct sep_device *sep, - unsigned long src_cache_addr, - unsigned long cache_size_in_bytes, - unsigned long src_resident_addr, - unsigned long resident_size_in_bytes, - unsigned long *dst_new_cache_addr_ptr, - unsigned long *dst_new_resident_addr_ptr) +/** + * sep_load_firmware - copy firmware cache/resident + * @sep: device we are loading + * + * This functions copies the cache and resident from their source + * location into destination shared memory. + */ + +static int sep_load_firmware(struct sep_device *sep) { - void *resident_addr; - void *cache_addr; const struct firmware *fw; - char *cache_name = "cache.image.bin"; char *res_name = "resident.image.bin"; - - /* error */ int error; - /*-------------------------------- - CODE - -------------------------------------*/ - error = 0; - edbg("SEP Driver:rar_virtual is %p\n", sep->rar_addr); edbg("SEP Driver:rar_bus is %08llx\n", (unsigned long long)sep->rar_bus); - sep->rar_region_addr = (unsigned long) sep->rar_addr; - + sep->rar_region_addr = sep->rar_addr; sep->cache_bus = sep->rar_bus; sep->cache_addr = sep->rar_addr; @@ -210,18 +196,12 @@ static int sep_copy_cache_resident_to_ar error = request_firmware(&fw, cache_name, &sep->pdev->dev); if (error) { edbg("SEP Driver:cant request cache fw\n"); - goto end_function; + return error; } - - edbg("SEP Driver:cache data loc is %p\n", (void *) fw->data); - edbg("SEP Driver:cache data size is %08Zx\n", fw->size); - - memcpy(sep->cache_addr, (void *) fw->data, fw->size); - + edbg("SEP Driver:cache %08Zx@%p\n", fw->size, (void *) fw->data); + + memcpy(sep->cache_addr, (void *)fw->data, fw->size); sep->cache_size = fw->size; - - cache_addr = sep->cache_addr; - release_firmware(fw); sep->resident_bus = sep->cache_bus + sep->cache_size; @@ -231,36 +211,18 @@ static int sep_copy_cache_resident_to_ar error = request_firmware(&fw, res_name, &sep->pdev->dev); if (error) { edbg("SEP Driver:cant request res fw\n"); - goto end_function; + return error; } + edbg("sep: res %08Zx@%p\n", fw->size, (void *)fw->data); - edbg("SEP Driver:res data loc is %p\n", (void *) fw->data); - edbg("SEP Driver:res data size is %08Zx\n", fw->size); - - memcpy((void *) sep->resident_addr, (void *) fw->data, fw->size); - + memcpy(sep->resident_addr, (void *) fw->data, fw->size); sep->resident_size = fw->size; - release_firmware(fw); - resident_addr = sep->resident_addr; - - edbg("SEP Driver:resident_addr (bus)is %08llx\n", (unsigned long long)sep->resident_bus); - edbg("SEP Driver:cache_addr (bus) is %08llx\n", (unsigned long long)sep->cache_bus); - - edbg("SEP Driver:resident_addr (virtual)is %p\n", resident_addr); - edbg("SEP Driver:cache_addr (virtual) is %08llx\n", (unsigned long long)cache_addr); - - edbg("SEP Driver:resident_size is %08lx\n", sep->resident_size); - edbg("SEP Driver:cache_size is %08llx\n", (unsigned long long)sep->cache_size); - - - - /* bus addresses */ - *dst_new_cache_addr_ptr = sep->cache_bus; - *dst_new_resident_addr_ptr = sep->resident_bus; -end_function: - return error; + edbg("sep: resident v %p b %08llx cache v %p b %08llx\n", + sep->resident_addr, (unsigned long long)sep->resident_bus, + sep->cache_addr, (unsigned long long)sep->cache_bus); + return 0; } /** @@ -2125,46 +2087,39 @@ end_function: static int sep_realloc_cache_resident_handler(struct sep_device *sep, unsigned long arg) { - int error; - unsigned long bus_cache_address; - unsigned long bus_resident_address; struct sep_driver_realloc_cache_resident_t command_args; - - /* copy the data */ - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_realloc_cache_resident_t)); - if (error) - goto end_function; + int error; /* copy cache and resident to the their intended locations */ - error = sep_copy_cache_resident_to_area(sep, command_args.cache_addr, command_args.cache_size_in_bytes, command_args.resident_addr, command_args.resident_size_in_bytes, &bus_cache_address, &bus_resident_address); + error = sep_load_firmware(sep); if (error) - goto end_function; + return error; command_args.new_base_addr = sep->shared_area_bus; /* find the new base address according to the lowest address between cache, resident and shared area */ - if (bus_resident_address < command_args.new_base_addr) - command_args.new_base_addr = bus_resident_address; - if (bus_cache_address < command_args.new_base_addr) - command_args.new_base_addr = bus_cache_address; + if (sep->resident_bus < command_args.new_base_addr) + command_args.new_base_addr = sep->resident_bus; + if (sep->cache_bus < command_args.new_base_addr) + command_args.new_base_addr = sep->cache_bus; /* set the return parameters */ - command_args.new_cache_addr = bus_cache_address; - command_args.new_resident_addr = bus_resident_address; + command_args.new_cache_addr = sep->cache_bus; + command_args.new_resident_addr = sep->resident_bus; /* set the new shared area */ command_args.new_shared_area_addr = sep->shared_area_bus; - edbg("SEP Driver:command_args.new_shared_area is %08lx\n", command_args.new_shared_area_addr); - edbg("SEP Driver:command_args.new_base_addr is %08lx\n", command_args.new_base_addr); - edbg("SEP Driver:command_args.new_resident_addr is %08lx\n", command_args.new_resident_addr); - edbg("SEP Driver:command_args.new_cache_addr is %08lx\n", command_args.new_cache_addr); + edbg("SEP Driver:command_args.new_shared_area is %08llx\n", command_args.new_shared_area_addr); + edbg("SEP Driver:command_args.new_base_addr is %08llx\n", command_args.new_base_addr); + edbg("SEP Driver:command_args.new_resident_addr is %08llx\n", command_args.new_resident_addr); + edbg("SEP Driver:command_args.new_cache_addr is %08llx\n", command_args.new_cache_addr); /* return to user */ - error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_realloc_cache_resident_t)); -end_function: - return error; + if (copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_realloc_cache_resident_t))) + return -EFAULT; + return 0; } /* @@ -2573,14 +2528,14 @@ static int __devinit sep_probe(struct pc /* set up system base address and shared memory location */ - sep->rar_addr = kmalloc(2 * SEP_RAR_IO_MEM_REGION_SIZE, GFP_KERNEL); + sep->rar_addr = dma_alloc_coherent(&sep->pdev->dev, + 2 * SEP_RAR_IO_MEM_REGION_SIZE, + &sep->rar_bus, GFP_KERNEL); if (!sep->rar_addr) { - edbg("SEP Driver:cant kmalloc rar\n"); + edbg("SEP Driver:can't allocate rar\n"); goto end_function_uniomap; } - /* FIXME */ - sep->rar_bus = __pa(sep->rar_addr); edbg("SEP Driver:rar_bus is %08llx\n", (unsigned long long)sep->rar_bus); edbg("SEP Driver:rar_virtual is %p\n", sep->rar_addr); @@ -2608,7 +2563,8 @@ static int __devinit sep_probe(struct pc sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); end_function_free_res: - kfree(sep->rar_addr); + dma_free_coherent(&sep->pdev->dev, 2 * SEP_RAR_IO_MEM_REGION_SIZE, + sep->rar_addr, sep->rar_bus); #endif /* SEP_DRIVER_POLLING_MODE */ end_function_uniomap: iounmap(sep->io_addr);