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

Commit d2e7b342 authored by Daniel Drake's avatar Daniel Drake Committed by John W. Linville
Browse files

libertas: disable functionality when interface is down



Modify the driver so that it does not function when the interface is
down, in preparation for runtime power management.

No commands can be run while the interface is down, so the ndo_dev_stop
routine now directly does all necessary work (including asking the device
to disconnect from the network and disabling multicast functionality)
directly.

power_save and power_restore hooks are added meaning that card drivers
can take steps to turn the device off when the interface is down.

The MAC address can now only be changed when all interfaces are down;
the new address will be programmed when an interface gets brought up.
This matches mac80211 behaviour.

Also, some small cleanups/simplifications were made in the surrounding
device handling logic.

Signed-off-by: default avatarDaniel Drake <dsd@laptop.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6de062ce
Loading
Loading
Loading
Loading
+23 −16
Original line number Original line Diff line number Diff line
@@ -712,7 +712,7 @@ static void lbs_scan_worker(struct work_struct *work)


	if (priv->scan_channel < priv->scan_req->n_channels) {
	if (priv->scan_channel < priv->scan_req->n_channels) {
		cancel_delayed_work(&priv->scan_work);
		cancel_delayed_work(&priv->scan_work);
		if (!priv->stopping)
		if (netif_running(priv->dev))
			queue_delayed_work(priv->work_thread, &priv->scan_work,
			queue_delayed_work(priv->work_thread, &priv->scan_work,
				msecs_to_jiffies(300));
				msecs_to_jiffies(300));
	}
	}
@@ -1409,31 +1409,23 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
	return ret;
	return ret;
}
}


static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
int lbs_disconnect(struct lbs_private *priv, u16 reason)
	u16 reason_code)
{
{
	struct lbs_private *priv = wiphy_priv(wiphy);
	struct cmd_ds_802_11_deauthenticate cmd;
	struct cmd_ds_802_11_deauthenticate cmd;

	int ret;
	if (dev == priv->mesh_dev)
		return -EOPNOTSUPP;

	lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);

	/* store for lbs_cfg_ret_disconnect() */
	priv->disassoc_reason = reason_code;


	memset(&cmd, 0, sizeof(cmd));
	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	/* Mildly ugly to use a locally store my own BSSID ... */
	/* Mildly ugly to use a locally store my own BSSID ... */
	memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN);
	memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN);
	cmd.reasoncode = cpu_to_le16(reason_code);
	cmd.reasoncode = cpu_to_le16(reason);


	if (lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd))
	ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
		return -EFAULT;
	if (ret)
		return ret;


	cfg80211_disconnected(priv->dev,
	cfg80211_disconnected(priv->dev,
			priv->disassoc_reason,
			reason,
			NULL, 0,
			NULL, 0,
			GFP_KERNEL);
			GFP_KERNEL);
	priv->connect_status = LBS_DISCONNECTED;
	priv->connect_status = LBS_DISCONNECTED;
@@ -1441,6 +1433,21 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
	return 0;
	return 0;
}
}


static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
	u16 reason_code)
{
	struct lbs_private *priv = wiphy_priv(wiphy);

	if (dev == priv->mesh_dev)
		return -EOPNOTSUPP;

	lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);

	/* store for lbs_cfg_ret_disconnect() */
	priv->disassoc_reason = reason_code;

	return lbs_disconnect(priv, reason_code);
}


static int lbs_cfg_set_default_key(struct wiphy *wiphy,
static int lbs_cfg_set_default_key(struct wiphy *wiphy,
				   struct net_device *netdev,
				   struct net_device *netdev,
+1 −0
Original line number Original line Diff line number Diff line
@@ -17,5 +17,6 @@ void lbs_send_disconnect_notification(struct lbs_private *priv);
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);


void lbs_scan_deinit(struct lbs_private *priv);
void lbs_scan_deinit(struct lbs_private *priv);
int lbs_disconnect(struct lbs_private *priv, u16 reason);


#endif
#endif
+3 −3
Original line number Original line Diff line number Diff line
@@ -1088,7 +1088,7 @@ void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
	if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
	if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
		__lbs_cleanup_and_insert_cmd(priv, cmd);
		__lbs_cleanup_and_insert_cmd(priv, cmd);
	priv->cur_cmd = NULL;
	priv->cur_cmd = NULL;
	wake_up_interruptible(&priv->waitq);
	wake_up(&priv->waitq);
}
}


void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
@@ -1627,7 +1627,7 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
		lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
		lbs_deb_host("PREP_CMD: cmdnode is NULL\n");


		/* Wake up main thread to execute next command */
		/* Wake up main thread to execute next command */
		wake_up_interruptible(&priv->waitq);
		wake_up(&priv->waitq);
		cmdnode = ERR_PTR(-ENOBUFS);
		cmdnode = ERR_PTR(-ENOBUFS);
		goto done;
		goto done;
	}
	}
@@ -1647,7 +1647,7 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,


	cmdnode->cmdwaitqwoken = 0;
	cmdnode->cmdwaitqwoken = 0;
	lbs_queue_cmd(priv, cmdnode);
	lbs_queue_cmd(priv, cmdnode);
	wake_up_interruptible(&priv->waitq);
	wake_up(&priv->waitq);


 done:
 done:
	lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
	lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
+4 −0
Original line number Original line Diff line number Diff line
@@ -43,10 +43,14 @@ int lbs_start_card(struct lbs_private *priv);
void lbs_stop_card(struct lbs_private *priv);
void lbs_stop_card(struct lbs_private *priv);
void lbs_host_to_card_done(struct lbs_private *priv);
void lbs_host_to_card_done(struct lbs_private *priv);


int lbs_start_iface(struct lbs_private *priv);
int lbs_stop_iface(struct lbs_private *priv);

int lbs_rtap_supported(struct lbs_private *priv);
int lbs_rtap_supported(struct lbs_private *priv);


int lbs_set_mac_address(struct net_device *dev, void *addr);
int lbs_set_mac_address(struct net_device *dev, void *addr);
void lbs_set_multicast_list(struct net_device *dev);
void lbs_set_multicast_list(struct net_device *dev);
void lbs_update_mcast(struct lbs_private *priv);


int lbs_suspend(struct lbs_private *priv);
int lbs_suspend(struct lbs_private *priv);
int lbs_resume(struct lbs_private *priv);
int lbs_resume(struct lbs_private *priv);
+15 −1
Original line number Original line Diff line number Diff line
@@ -46,7 +46,6 @@ struct lbs_private {
	/* CFG80211 */
	/* CFG80211 */
	struct wireless_dev *wdev;
	struct wireless_dev *wdev;
	bool wiphy_registered;
	bool wiphy_registered;
	bool stopping;
	struct cfg80211_scan_request *scan_req;
	struct cfg80211_scan_request *scan_req;
	u8 assoc_bss[ETH_ALEN];
	u8 assoc_bss[ETH_ALEN];
	u8 disassoc_reason;
	u8 disassoc_reason;
@@ -96,11 +95,14 @@ struct lbs_private {


	/* Hardware access */
	/* Hardware access */
	void *card;
	void *card;
	bool iface_running;
	u8 fw_ready;
	u8 fw_ready;
	u8 surpriseremoved;
	u8 surpriseremoved;
	u8 setup_fw_on_resume;
	u8 setup_fw_on_resume;
	int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
	int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
	void (*reset_card) (struct lbs_private *priv);
	void (*reset_card) (struct lbs_private *priv);
	int (*power_save) (struct lbs_private *priv);
	int (*power_restore) (struct lbs_private *priv);
	int (*enter_deep_sleep) (struct lbs_private *priv);
	int (*enter_deep_sleep) (struct lbs_private *priv);
	int (*exit_deep_sleep) (struct lbs_private *priv);
	int (*exit_deep_sleep) (struct lbs_private *priv);
	int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
	int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
@@ -182,4 +184,16 @@ struct lbs_private {


extern struct cmd_confirm_sleep confirm_sleep;
extern struct cmd_confirm_sleep confirm_sleep;


/* Check if there is an interface active. */
static inline int lbs_iface_active(struct lbs_private *priv)
{
	int r;

	r = netif_running(priv->dev);
	if (priv->mesh_dev);
		r |= netif_running(priv->dev);

	return r;
}

#endif
#endif
Loading