[PATCH 19/19] Add in-kernel firmware loading support

Mark Hounschell markh at compro.net
Wed Feb 19 21:01:59 UTC 2014


On 02/19/2014 03:17 PM, Dan Carpenter wrote:
> This one has white space problems.  Run scripts/checkpatch.pl on your
> patches before sending.  Comments below.
> 
> On Wed, Feb 19, 2014 at 01:12:15PM -0500, Mark Hounschell wrote:
>> +static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
>> +{
>> +	struct board_t *brd = dgap_Board[dgap_NumBoards - 1];
>> +	const struct firmware *fw;
>> +	char *uaddr;
>> +	int ret;
>> +	
>> +	dgap_get_vpd(brd);
>> +	dgap_do_reset_board(brd);
>> +
>> +	if ((fw_info[card_type].conf_name) && 
>> +	    (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD)) {
>> +		ret = request_firmware(&fw, fw_info[card_type].conf_name, &pdev->dev);
>> +		if (ret) {
>> +			printk(KERN_ERR "DGAP: request_firmware failed. Make sure "
>> +					"you've placed '%s' file into your firmware "
>> +					"loader directory (e.g. /lib/firmware)\n",
>> +					fw_info[card_type].conf_name);
>> +			return ret; 
>> +		} else {
>> +			if (!dgap_config_buf) {
>> +				uaddr = dgap_config_buf = kmalloc(fw->size + 1, GFP_ATOMIC);
>> +				if (!dgap_config_buf) {
>> +					DPR_INIT(("DGAP: dgap_firmware_load - unable to allocate memory for config file\n"));
> 
> Don't print an error if kmalloc() fails.  kmalloc() prints a far more
> useful error message already before returning NULL.
> 
>> +					release_firmware(fw);
>> +					return -ENOMEM;
>> +				}
>> +			}
>> +
>> +			memcpy(uaddr, fw->data, fw->size);
>> +			release_firmware(fw);
>> +			uaddr[fw->size + 1] = '\0'; 	// The config file is treated as a string
>> +
>> +			if (dgap_parsefile(&uaddr, TRUE) != 0) 
>> +				return -EINVAL;
>> +
>> +			dgap_driver_state = -1;
>> +		}
> 
> You are going over the 80 character limit unnecessarily.  Change the
> "} else {" to "}" and pull everything in one indent level.
> 
> Get rid of the uaddr temporary variable.  It is not needed.  Actually
> there is a bug where it is used uninitialized.  I haven't tried to
> compile this, doesn't GCC complain?
> 
> 
>> +	}
>> +
>> +	ret = dgap_after_config_loaded(brd->boardnum);
>> +	if (ret != 0)
> 
> 	if (ret)
> 		return ret;
> 
> The "!= 0" double negative doesn't add anything.
> 
>> +		return ret;
>> +	/*
>> +	 * Match this board to a config the user created for us.
>> +	 */
>> +	brd->bd_config = dgap_find_config(brd->type, brd->pci_bus, brd->pci_slot);
>> +
>> +	/*
>> +	 * Because the 4 port Xr products share the same PCI ID
>> +	 * as the 8 port Xr products, if we receive a NULL config
>> +	 * back, and this is a PAPORT8 board, retry with a
>> +	 * PAPORT4 attempt as well.
>> +	 */
>> +	if (brd->type == PAPORT8 && !brd->bd_config)
>> +		brd->bd_config = dgap_find_config(PAPORT4, brd->pci_bus, brd->pci_slot);
>> +
>> +	if (!brd->bd_config) {
>> +		printk(KERN_ERR "DGAP: dgap_firmware_load: No valid configuration found\n");
>> +		return -EINVAL;
>> +	}
>> +	
>> +	dgap_tty_register(brd);
>> +	dgap_finalize_board_init(brd);
>> +
>> +	if (fw_info[card_type].bios_name) {
>> +		ret = request_firmware(&fw, fw_info[card_type].bios_name, &pdev->dev);
>> +		if (ret) {
>> +			printk(KERN_ERR "DGAP: request_firmware failed. Make sure "
>> +					"you've placed '%s' file into your firmware "
>> +					"loader directory (e.g. /lib/firmware)\n",
>> +					fw_info[card_type].bios_name);
>> +			return ret;
>> +		} else {
>> +			uaddr = (char *)fw->data;
>> +			dgap_do_bios_load(brd, uaddr, fw->size);
>> +			release_firmware(fw);
>> +
>> +			/* Wait for BIOS to test board... */
>> +			dgap_do_wait_for_bios(brd);
>> +
>> +			if (brd->state != FINISHED_BIOS_LOAD)
>> +				return -ENXIO;
>> +		}
> 
> 
> Same thing.  Change "} else {" to "}".  In the kernel we do "error
> handling", this is "error handling followed by success handling."  We
> don't want special success handling.  Success is the default state.
> 
> No need for the uaddr variable.
> 
>> +	}
>> +
>> +        if (fw_info[card_type].fep_name) {
>> +                ret = request_firmware(&fw, fw_info[card_type].fep_name, &pdev->dev);
>> +                if (ret) {
>> +                        printk(KERN_ERR "DGAP: request_firmware failed. Make sure "
>> +                                        "you've placed '%s' file into your firmware "
>> +                                        "loader directory (e.g. /lib/firmware)\n",
>> +                                        fw_info[card_type].fep_name);
>> +                        return ret;
>> +                } else {
>> +                        uaddr = (char *)fw->data;
>> +                        dgap_do_fep_load(brd, uaddr, fw->size);
>> +			release_firmware(fw);
>> +
>> +                        /* Wait for FEP to load on board... */
>> +                        dgap_do_wait_for_fep(brd);
>> +
>> +                        if (brd->state != FINISHED_FEP_LOAD)
>> +                                return -ENXIO;
>> +                }
>> +        }
>> +        
>> +#ifdef DIGI_CONCENTRATORS_SUPPORTED
>> +	/*
>> +	 * If this is a CX or EPCX, we need to see if the firmware
>> +	 * is requesting a concentrator image from us.
>> +	 */
>> +	if ((bd->type == PCX) || (bd->type == PEPC)) {
>> +		chk_addr = (u16 *) (vaddr + DOWNREQ);
>> +		/* Nonzero if FEP is requesting concentrator image. */
>> +		check = readw(chk_addr);
>> +		vaddr = brd->re_map_membase;
>> +	}
>> +
>> +	if (fw_info[card_type].con_name && check && vaddr) {
>> +		ret = request_firmware(&fw, fw_info[card_type].con_name, &pdev->dev);
>> +		if (ret) {
>> +			printk(KERN_ERR "DGAP: request_firmware failed. Make sure "
>> +					"you've placed '%s' file into your firmware "
>> +					"loader directory (e.g. /lib/firmware)\n",
>> +					fw_info[card_type].con_name);
>> +			return ret;
>> +		} else {
>> +			/* Put concentrator firmware loading code here */
>> +			offset = readw((u16 *) (vaddr + DOWNREQ)); 
>> +        		memcpy_toio(offset, fw->data, fw->size);
>> +
>> +                        uaddr = (char *)fw->data;
>> +			dgap_do_conc_load(brd, uaddr, fw->size)
>> +			release_firmware(fw);
>> +		}
>> +	}
>> +#endif
>> +	/*
>> +	 * Do tty device initialization.
>> +	 */
>> +	ret = dgap_tty_init(brd); 
>> +	if (ret < 0) {
>> +		dgap_tty_uninit(brd);
>> +        	printk("DGAP: dgap_firmware_load: Can't init tty devices (%d)\n", ret);
>> +		return -EIO;
> 
> return ret, don't hard code EIO here.
> 
>> +	}
>> +
>> +	dgap_sysfs_create(brd);
>> +
>> +	brd->state = BOARD_READY;
>> +	brd->dpastatus = BD_RUNNING;
>> +
>> +	return 0;
>> +}
>>  
>>  /*
>>   * Remap PCI memory.
>> @@ -983,37 +1221,18 @@ static void dgap_poll_handler(ulong dummy)
>>  	int i;
>>          struct board_t *brd;
>>          unsigned long lock_flags;
>> -        unsigned long lock_flags2;
>>  	ulong new_time;
>>  
>>  	dgap_poll_counter++;
>>  
>>  
>>  	/*
>> -	 * If driver needs the config file still,
>> -	 * keep trying to wake up the downloader to
>> -	 * send us the file.
>> -	 */
>> -        if (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD) {
>> -		/*
>> -		 * Signal downloader, its got some work to do.
>> -		 */
>> -		DGAP_LOCK(dgap_dl_lock, lock_flags2);
>> -		if (dgap_dl_action != 1) {
>> -			dgap_dl_action = 1;
>> -			wake_up_interruptible(&dgap_dl_wait);
>> -		}
>> -		DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
>> -		goto schedule_poller;
>> -        }
>> -	/*
>>  	 * Do not start the board state machine until
>>  	 * driver tells us its up and running, and has
>>  	 * everything it needs.
>>  	 */
>> -	else if (dgap_driver_state != DRIVER_READY) {
>> +	if (dgap_driver_state != DRIVER_READY)
>>  		goto schedule_poller;
>> -	}
>>  
>>  	/*
>>  	 * If we have just 1 board, or the system is not SMP,
>> @@ -4656,112 +4875,54 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
>>  		return(-ENOIOCTLCMD);
>>  	}
>>  }
>> -/*
>> - * Loads the dgap.conf config file from the user.
>> - */
>> -static void dgap_do_config_load(uchar __user *uaddr, int len)
>> -{
>> -	int orig_len = len;
>> -	char *to_addr;
>> -	uchar __user *from_addr = uaddr;
>> -	char buf[U2BSIZE];
>> -	int n;
>> -
>> -	to_addr = dgap_config_buf = kzalloc(len + 1, GFP_ATOMIC);
>> -	if (!dgap_config_buf) {
>> -		DPR_INIT(("dgap_do_config_load - unable to allocate memory for file\n"));
>> -		dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
>> -		return;
>> -	}
>>  
>> -	n = U2BSIZE;
>> -	while (len) {
>> -
>> -		if (n > len)
>> -			n = len;
>> -
>> -		if (copy_from_user((char *) &buf, from_addr, n) == -1 )
>> -			return;
>> -
>> -		/* Copy data from buffer to kernel memory */
>> -		memcpy(to_addr, buf, n);
>> -
>> -		/* increment counts */
>> -		len -= n;
>> -		to_addr += n;
>> -		from_addr += n;
>> -		n = U2BSIZE;
>> -	}
>> -
>> -	dgap_config_buf[orig_len] = '\0';
>> -
>> -	to_addr = dgap_config_buf;
>> -	dgap_parsefile(&to_addr, TRUE);
>> -
>> -	DPR_INIT(("dgap_config_load() finish\n"));
>> -
>> -	return;
>> -}
>> -
>> -
>> -static int dgap_after_config_loaded(void)
>> +static int dgap_after_config_loaded(int board)
>>  {
>> -	int i = 0;
>> -	int rc = 0;
>> +        int ret = 0;
>>  
>>  	/*
>> -	 * Register our ttys, now that we have the config loaded.
>> +	 * Initialize KME waitqueues...
>>  	 */
>> -	for (i = 0; i < dgap_NumBoards; ++i) {
>> +	init_waitqueue_head(&(dgap_Board[board]->kme_wait));
>>  
>> -		/*
>> -		 * Initialize KME waitqueues...
>> -		 */
>> -		init_waitqueue_head(&(dgap_Board[i]->kme_wait));
>> -
>> -		/*
>> -		 * allocate flip buffer for board.
>> -		 */
>> -		dgap_Board[i]->flipbuf = kzalloc(MYFLIPLEN, GFP_ATOMIC);
>> -		dgap_Board[i]->flipflagbuf = kzalloc(MYFLIPLEN, GFP_ATOMIC);
>> +	/*
>> +	 * allocate flip buffer for board.
>> +	 */
>> +	dgap_Board[board]->flipbuf = kmalloc(MYFLIPLEN, GFP_ATOMIC);
>> +	if (!dgap_Board[board]->flipbuf) {
>> +		ret = -ENOMEM;
>> +		goto out;
> 
> Just return -ENOMEM directly.
> 
> 
>>  	}
>> +	dgap_Board[board]->flipflagbuf = kmalloc(MYFLIPLEN, GFP_ATOMIC);
>> +	if (!dgap_Board[board]->flipflagbuf) 
>> +		ret = -ENOMEM;
> 
> Free the other allocation and return -ENOMEM.  Don't use a goto since
> there is only one kfree() in the function.
> 
> 
>>  
>> -	return rc;
>> +    out:
>> +        return ret;
> 
> This should be the success path now.  "return 0;"
> 

OK, thanks Dan. I'll followup with a new 19/19 patch. It did compile and
work with no complaints about the above though. I should have checked
that last one better as it is
new code added.

Thanks
Mark



More information about the devel mailing list