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

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

zd1211rw: beacon config error checking



Add some error checking to the new beacon configuration code.

Signed-off-by: default avatarDaniel Drake <dsd@gentoo.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6ef307bc
Loading
Loading
Loading
Loading
+45 −17
Original line number Diff line number Diff line
@@ -405,43 +405,66 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
	/* FIXME: Management frame? */
}

void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
{
	struct zd_mac *mac = zd_hw_mac(hw);
	int r;
	u32 tmp, j = 0;
	/* 4 more bytes for tail CRC */
	u32 full_len = beacon->len + 4;
	zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
	zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);

	r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
	if (r < 0)
		return r;
	r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
	if (r < 0)
		return r;

	while (tmp & 0x2) {
		zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
		r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
		if (r < 0)
			return r;
		if ((++j % 100) == 0) {
			printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
			if (j >= 500)  {
				printk(KERN_ERR "Giving up beacon config.\n");
				return;
				return -ETIMEDOUT;
			}
		}
		msleep(1);
	}

	zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
	if (zd_chip_is_zd1211b(&mac->chip))
		zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
	r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
	if (r < 0)
		return r;
	if (zd_chip_is_zd1211b(&mac->chip)) {
		r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
		if (r < 0)
			return r;
	}

	for (j = 0 ; j < beacon->len; j++)
		zd_iowrite32(&mac->chip, CR_BCN_FIFO,
	for (j = 0 ; j < beacon->len; j++) {
		r = zd_iowrite32(&mac->chip, CR_BCN_FIFO,
				*((u8 *)(beacon->data + j)));
		if (r < 0)
			return r;
	}

	for (j = 0; j < 4; j++) {
		r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
		if (r < 0)
			return r;
	}

	for (j = 0; j < 4; j++)
		zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
	r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
	if (r < 0)
		return r;

	zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
	/* 802.11b/g 2.4G CCK 1Mb
	 * 802.11a, not yet implemented, uses different values (see GPL vendor
	 * driver)
	 */
	zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
	return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
			(full_len << 19));
}

@@ -699,15 +722,20 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
{
	struct zd_mac *mac = zd_hw_mac(hw);
	int associated;
	int r;

	if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
	    mac->type == IEEE80211_IF_TYPE_IBSS) {
		associated = true;
		if (conf->beacon) {
			zd_mac_config_beacon(hw, conf->beacon);
			kfree_skb(conf->beacon);
			zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
			r = zd_mac_config_beacon(hw, conf->beacon);
			if (r < 0)
				return r;
			r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
					hw->conf.beacon_int);
			if (r < 0)
				return r;
			kfree_skb(conf->beacon);
		}
	} else
		associated = is_valid_ether_addr(conf->bssid);