Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c34a5d8 authored by Dan Williams's avatar Dan Williams Committed by John W. Linville
Browse files

atmel: return ENOENT on request_firmware failure



Return errors from request_firmware() (like other drivers that do
firmware load on device open) and make up plausible codes for other
error conditions. Gives userspace tools like NetworkManager a clue that
firmware may be missing when the result of setting IFF_UP is ENOENT.

Signed-off-by: default avatarDan Williams <dcbw@redhat.com>

v2: fix reversed check of atmel_wakeup_firmware() in probe_atmel_card()
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c2d42545
Loading
Loading
Loading
Loading
+22 −19
Original line number Original line Diff line number Diff line
@@ -1304,7 +1304,7 @@ EXPORT_SYMBOL(atmel_open);
int atmel_open(struct net_device *dev)
int atmel_open(struct net_device *dev)
{
{
	struct atmel_private *priv = netdev_priv(dev);
	struct atmel_private *priv = netdev_priv(dev);
	int i, channel;
	int i, channel, err;


	/* any scheduled timer is no longer needed and might screw things up.. */
	/* any scheduled timer is no longer needed and might screw things up.. */
	del_timer_sync(&priv->management_timer);
	del_timer_sync(&priv->management_timer);
@@ -1328,8 +1328,9 @@ int atmel_open(struct net_device *dev)
	priv->site_survey_state = SITE_SURVEY_IDLE;
	priv->site_survey_state = SITE_SURVEY_IDLE;
	priv->station_is_associated = 0;
	priv->station_is_associated = 0;


	if (!reset_atmel_card(dev))
	err = reset_atmel_card(dev);
		return -EAGAIN;
	if (err)
		return err;


	if (priv->config_reg_domain) {
	if (priv->config_reg_domain) {
		priv->reg_domain = priv->config_reg_domain;
		priv->reg_domain = priv->config_reg_domain;
@@ -3580,12 +3581,12 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)


	if (i == 0) {
	if (i == 0) {
		printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name);
		printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name);
		return 0;
		return -EIO;
	}
	}


	if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
	if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
		printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
		printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
		return 0;
		return -ENODEV;
	}
	}


	/* now check for completion of MAC initialization through
	/* now check for completion of MAC initialization through
@@ -3609,19 +3610,19 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
	if (i == 0) {
	if (i == 0) {
		printk(KERN_ALERT "%s: MAC failed to initialise.\n",
		printk(KERN_ALERT "%s: MAC failed to initialise.\n",
				priv->dev->name);
				priv->dev->name);
		return 0;
		return -EIO;
	}
	}


	/* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */
	/* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */
	if ((mr3 & MAC_INIT_COMPLETE) &&
	if ((mr3 & MAC_INIT_COMPLETE) &&
	    !(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) {
	    !(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) {
		printk(KERN_ALERT "%s: MAC failed MR3 self-test.\n", priv->dev->name);
		printk(KERN_ALERT "%s: MAC failed MR3 self-test.\n", priv->dev->name);
		return 0;
		return -EIO;
	}
	}
	if ((mr1 & MAC_INIT_COMPLETE) &&
	if ((mr1 & MAC_INIT_COMPLETE) &&
	    !(atmel_read16(priv->dev, MR1) & MAC_INIT_OK)) {
	    !(atmel_read16(priv->dev, MR1) & MAC_INIT_OK)) {
		printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name);
		printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name);
		return 0;
		return -EIO;
	}
	}


	atmel_copy_to_host(priv->dev, (unsigned char *)iface,
	atmel_copy_to_host(priv->dev, (unsigned char *)iface,
@@ -3642,7 +3643,7 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
	iface->func_ctrl = le16_to_cpu(iface->func_ctrl);
	iface->func_ctrl = le16_to_cpu(iface->func_ctrl);
	iface->mac_status = le16_to_cpu(iface->mac_status);
	iface->mac_status = le16_to_cpu(iface->mac_status);


	return 1;
	return 0;
}
}


/* determine type of memory and MAC address */
/* determine type of memory and MAC address */
@@ -3693,7 +3694,7 @@ static int probe_atmel_card(struct net_device *dev)
		/* Standard firmware in flash, boot it up and ask
		/* Standard firmware in flash, boot it up and ask
		   for the Mac Address */
		   for the Mac Address */
		priv->card_type = CARD_TYPE_SPI_FLASH;
		priv->card_type = CARD_TYPE_SPI_FLASH;
		if (atmel_wakeup_firmware(priv)) {
		if (atmel_wakeup_firmware(priv) == 0) {
			atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);
			atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);


			/* got address, now squash it again until the network
			/* got address, now squash it again until the network
@@ -3835,6 +3836,7 @@ static int reset_atmel_card(struct net_device *dev)
	struct atmel_private *priv = netdev_priv(dev);
	struct atmel_private *priv = netdev_priv(dev);
	u8 configuration;
	u8 configuration;
	int old_state = priv->station_state;
	int old_state = priv->station_state;
	int err = 0;


	/* data to add to the firmware names, in priority order
	/* data to add to the firmware names, in priority order
	   this implemenents firmware versioning */
	   this implemenents firmware versioning */
@@ -3868,11 +3870,12 @@ static int reset_atmel_card(struct net_device *dev)
					       dev->name);
					       dev->name);
					strcpy(priv->firmware_id, "atmel_at76c502.bin");
					strcpy(priv->firmware_id, "atmel_at76c502.bin");
				}
				}
				if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) != 0) {
				err = request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev);
				if (err != 0) {
					printk(KERN_ALERT
					printk(KERN_ALERT
					       "%s: firmware %s is missing, cannot continue.\n",
					       "%s: firmware %s is missing, cannot continue.\n",
					       dev->name, priv->firmware_id);
					       dev->name, priv->firmware_id);
					return 0;
					return err;
				}
				}
			} else {
			} else {
				int fw_index = 0;
				int fw_index = 0;
@@ -3901,7 +3904,7 @@ static int reset_atmel_card(struct net_device *dev)
					       "%s: firmware %s is missing, cannot start.\n",
					       "%s: firmware %s is missing, cannot start.\n",
					       dev->name, priv->firmware_id);
					       dev->name, priv->firmware_id);
					priv->firmware_id[0] = '\0';
					priv->firmware_id[0] = '\0';
					return 0;
					return -ENOENT;
				}
				}
			}
			}


@@ -3926,8 +3929,9 @@ static int reset_atmel_card(struct net_device *dev)
			release_firmware(fw_entry);
			release_firmware(fw_entry);
	}
	}


	if (!atmel_wakeup_firmware(priv))
	err = atmel_wakeup_firmware(priv);
		return 0;
	if (err != 0)
		return err;


	/* Check the version and set the correct flag for wpa stuff,
	/* Check the version and set the correct flag for wpa stuff,
	   old and new firmware is incompatible.
	   old and new firmware is incompatible.
@@ -3968,10 +3972,9 @@ static int reset_atmel_card(struct net_device *dev)
	if (!priv->radio_on_broken) {
	if (!priv->radio_on_broken) {
		if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
		if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
		    CMD_STATUS_REJECTED_RADIO_OFF) {
		    CMD_STATUS_REJECTED_RADIO_OFF) {
			printk(KERN_INFO
			printk(KERN_INFO "%s: cannot turn the radio on.\n",
			       "%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n",
			       dev->name);
			       dev->name);
                        return 0;
                        return -EIO;
		}
		}
	}
	}


@@ -4006,7 +4009,7 @@ static int reset_atmel_card(struct net_device *dev)
		wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
		wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
	}
	}


	return 1;
	return 0;
}
}


static void atmel_send_command(struct atmel_private *priv, int command,
static void atmel_send_command(struct atmel_private *priv, int command,