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

Commit e61444d9 authored by David S. Miller's avatar David S. Miller
Browse files
parents a252e749 6a213afd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@ static const struct pci_device_id ath5k_led_devices[] = {
	{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) },
	/* IBM-specific AR5212 (all others) */
	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
	/* Dell Vostro A860 (shahar@shahar-or.co.il) */
	{ ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0112), ATH_LED(3, 0) },
	{ }
};

+1 −1
Original line number Diff line number Diff line
@@ -2078,7 +2078,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
				&txq->axq_q, lastbf->list.prev);

		txq->axq_depth--;
		txok = (ds->ds_txstat.ts_status == 0);
		txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT);
		txq->axq_tx_inprogress = false;
		spin_unlock_bh(&txq->axq_lock);

+1 −1
Original line number Diff line number Diff line
@@ -1353,7 +1353,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
	if (priv->stations[sta_id].tid[tid].agg.state ==
				IWL_EMPTYING_HW_QUEUE_ADDBA) {
		IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
		ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid);
		ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
		priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
		return 0;
	}
+163 −164
Original line number Diff line number Diff line
@@ -84,7 +84,8 @@ struct rxd_ops {
	int rxd_size;
	void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr);
	void (*rxd_refill)(void *rxd, dma_addr_t addr, int len);
	int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status);
	int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status,
			   __le16 *qos);
};

struct mwl8k_device_info {
@@ -184,7 +185,7 @@ struct mwl8k_priv {
	/* PHY parameters */
	struct ieee80211_supported_band band;
	struct ieee80211_channel channels[14];
	struct ieee80211_rate rates[13];
	struct ieee80211_rate rates[14];

	bool radio_on;
	bool radio_short_preamble;
@@ -220,15 +221,6 @@ struct mwl8k_vif {
	u8	bssid[ETH_ALEN];
	u8	mac_addr[ETH_ALEN];

	/*
	 * Subset of supported legacy rates.
	 * Intersection of AP and STA supported rates.
	 */
	struct ieee80211_rate legacy_rates[13];

	/* number of supported legacy rates */
	u8	legacy_nrates;

	 /* Index into station database.Returned by update_sta_db call */
	u8	peer_id;

@@ -266,6 +258,11 @@ static const struct ieee80211_rate mwl8k_rates[] = {
	{ .bitrate = 360, .hw_value = 72, },
	{ .bitrate = 480, .hw_value = 96, },
	{ .bitrate = 540, .hw_value = 108, },
	{ .bitrate = 720, .hw_value = 144, },
};

static const u8 mwl8k_rateids[12] = {
	2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108,
};

/* Set or get info from Firmware */
@@ -574,7 +571,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
			       "helper image\n", pci_name(priv->pdev));
			return rc;
		}
		msleep(1);
		msleep(5);

		rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
	} else {
@@ -591,9 +588,8 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
		iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR);
	else
		iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
	msleep(1);

	loops = 200000;
	loops = 500000;
	do {
		u32 ready_code;

@@ -633,9 +629,6 @@ struct ewc_ht_info {
/* Peer Entry flags - used to define the type of the peer node */
#define MWL8K_PEER_TYPE_ACCESSPOINT	2

#define MWL8K_IEEE_LEGACY_DATA_RATES	13
#define MWL8K_MCS_BITMAP_SIZE		16

struct peer_capability_info {
	/* Peer type - AP vs. STA.  */
	__u8	peer_type;
@@ -652,10 +645,10 @@ struct peer_capability_info {
	struct ewc_ht_info	ewc_info;

	/* Legacy rate table. Intersection of our rates and peer rates.  */
	__u8	legacy_rates[MWL8K_IEEE_LEGACY_DATA_RATES];
	__u8	legacy_rates[12];

	/* HT rate table. Intersection of our rates and peer rates.  */
	__u8	ht_rates[MWL8K_MCS_BITMAP_SIZE];
	__u8	ht_rates[16];
	__u8	pad[16];

	/* If set, interoperability mode, no proprietary extensions.  */
@@ -706,55 +699,64 @@ static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len)
struct mwl8k_dma_data {
	__le16 fwlen;
	struct ieee80211_hdr wh;
	char data[0];
} __attribute__((packed));

/* Routines to add/remove DMA header from skb.  */
static inline void mwl8k_remove_dma_header(struct sk_buff *skb)
static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos)
{
	struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data;
	void *dst, *src = &tr->wh;
	int hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
	u16 space = sizeof(struct mwl8k_dma_data) - hdrlen;
	struct mwl8k_dma_data *tr;
	int hdrlen;

	tr = (struct mwl8k_dma_data *)skb->data;
	hdrlen = ieee80211_hdrlen(tr->wh.frame_control);

	dst = (void *)tr + space;
	if (dst != src) {
		memmove(dst, src, hdrlen);
		skb_pull(skb, space);
	if (hdrlen != sizeof(tr->wh)) {
		if (ieee80211_is_data_qos(tr->wh.frame_control)) {
			memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2);
			*((__le16 *)(tr->data - 2)) = qos;
		} else {
			memmove(tr->data - hdrlen, &tr->wh, hdrlen);
		}
	}

	if (hdrlen != sizeof(*tr))
		skb_pull(skb, sizeof(*tr) - hdrlen);
}

static inline void mwl8k_add_dma_header(struct sk_buff *skb)
{
	struct ieee80211_hdr *wh;
	u32 hdrlen, pktlen;
	int hdrlen;
	struct mwl8k_dma_data *tr;

	/*
	 * Add a firmware DMA header; the firmware requires that we
	 * present a 2-byte payload length followed by a 4-address
	 * header (without QoS field), followed (optionally) by any
	 * WEP/ExtIV header (but only filled in for CCMP).
	 */
	wh = (struct ieee80211_hdr *)skb->data;

	hdrlen = ieee80211_hdrlen(wh->frame_control);
	pktlen = skb->len;
	if (hdrlen != sizeof(*tr))
		skb_push(skb, sizeof(*tr) - hdrlen);

	/*
	 * Copy up/down the 802.11 header; the firmware requires
	 * we present a 2-byte payload length followed by a
	 * 4-address header (w/o QoS), followed (optionally) by
	 * any WEP/ExtIV header (but only filled in for CCMP).
	 */
	if (hdrlen != sizeof(struct mwl8k_dma_data))
		skb_push(skb, sizeof(struct mwl8k_dma_data) - hdrlen);
	if (ieee80211_is_data_qos(wh->frame_control))
		hdrlen -= 2;

	tr = (struct mwl8k_dma_data *)skb->data;
	if (wh != &tr->wh)
		memmove(&tr->wh, wh, hdrlen);

	/* Clear addr4 */
	memset(tr->wh.addr4, 0, ETH_ALEN);
	if (hdrlen != sizeof(tr->wh))
		memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen);

	/*
	 * Firmware length is the length of the fully formed "802.11
	 * payload".  That is, everything except for the 802.11 header.
	 * This includes all crypto material including the MIC.
	 */
	tr->fwlen = cpu_to_le16(pktlen - hdrlen);
	tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr));
}


@@ -779,6 +781,10 @@ struct mwl8k_rxd_8366 {
	__u8 rx_ctrl;
} __attribute__((packed));

#define MWL8K_8366_RATE_INFO_MCS_FORMAT		0x80
#define MWL8K_8366_RATE_INFO_40MHZ		0x40
#define MWL8K_8366_RATE_INFO_RATEID(x)		((x) & 0x3f)

#define MWL8K_8366_RX_CTRL_OWNED_BY_HOST	0x80

static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr)
@@ -800,7 +806,8 @@ static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len)
}

static int
mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status)
mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status,
		       __le16 *qos)
{
	struct mwl8k_rxd_8366 *rxd = _rxd;

@@ -813,9 +820,11 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status)
	status->signal = -rxd->rssi;
	status->noise = -rxd->noise_floor;

	if (rxd->rate & 0x80) {
	if (rxd->rate & MWL8K_8366_RATE_INFO_MCS_FORMAT) {
		status->flag |= RX_FLAG_HT;
		status->rate_idx = rxd->rate & 0x7f;
		if (rxd->rate & MWL8K_8366_RATE_INFO_40MHZ)
			status->flag |= RX_FLAG_40MHZ;
		status->rate_idx = MWL8K_8366_RATE_INFO_RATEID(rxd->rate);
	} else {
		int i;

@@ -830,6 +839,8 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status)
	status->band = IEEE80211_BAND_2GHZ;
	status->freq = ieee80211_channel_to_frequency(rxd->channel);

	*qos = rxd->qos_control;

	return le16_to_cpu(rxd->pkt_len);
}

@@ -888,7 +899,8 @@ static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len)
}

static int
mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status,
		       __le16 *qos)
{
	struct mwl8k_rxd_8687 *rxd = _rxd;
	u16 rate_info;
@@ -903,7 +915,6 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)

	status->signal = -rxd->rssi;
	status->noise = -rxd->noise_level;
	status->qual = rxd->link_quality;
	status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info);
	status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info);

@@ -919,6 +930,8 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
	status->band = IEEE80211_BAND_2GHZ;
	status->freq = ieee80211_channel_to_frequency(rxd->channel);

	*qos = rxd->qos_control;

	return le16_to_cpu(rxd->pkt_len);
}

@@ -1090,6 +1103,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
		void *rxd;
		int pkt_len;
		struct ieee80211_rx_status status;
		__le16 qos;

		skb = rxq->buf[rxq->head].skb;
		if (skb == NULL)
@@ -1097,7 +1111,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)

		rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size);

		pkt_len = priv->rxd_ops->rxd_process(rxd, &status);
		pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos);
		if (pkt_len < 0)
			break;

@@ -1115,7 +1129,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
		rxq->rxd_count--;

		skb_put(skb, pkt_len);
		mwl8k_remove_dma_header(skb);
		mwl8k_remove_dma_header(skb, qos);

		/*
		 * Check for a pending join operation.  Save a
@@ -1221,99 +1235,106 @@ static inline void mwl8k_tx_start(struct mwl8k_priv *priv)
	ioread32(priv->regs + MWL8K_HIU_INT_CODE);
}

struct mwl8k_txq_info {
	u32 fw_owned;
	u32 drv_owned;
	u32 unused;
	u32 len;
	u32 head;
	u32 tail;
};

static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
				struct mwl8k_txq_info *txinfo)
static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw)
{
	int count, desc, status;
	struct mwl8k_tx_queue *txq;
	struct mwl8k_tx_desc *tx_desc;
	int ndescs = 0;
	struct mwl8k_priv *priv = hw->priv;
	int i;

	memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info));
	for (i = 0; i < MWL8K_TX_QUEUES; i++) {
		struct mwl8k_tx_queue *txq = priv->txq + i;
		int fw_owned = 0;
		int drv_owned = 0;
		int unused = 0;
		int desc;

	for (count = 0; count < MWL8K_TX_QUEUES; count++) {
		txq = priv->txq + count;
		txinfo[count].len = txq->stats.len;
		txinfo[count].head = txq->head;
		txinfo[count].tail = txq->tail;
		for (desc = 0; desc < MWL8K_TX_DESCS; desc++) {
			tx_desc = txq->txd + desc;
			status = le32_to_cpu(tx_desc->status);
			struct mwl8k_tx_desc *tx_desc = txq->txd + desc;
			u32 status;

			status = le32_to_cpu(tx_desc->status);
			if (status & MWL8K_TXD_STATUS_FW_OWNED)
				txinfo[count].fw_owned++;
				fw_owned++;
			else
				txinfo[count].drv_owned++;
				drv_owned++;

			if (tx_desc->pkt_len == 0)
				txinfo[count].unused++;
		}
				unused++;
		}

	return ndescs;
		printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d "
		       "fw_owned=%d drv_owned=%d unused=%d\n",
		       wiphy_name(hw->wiphy), i,
		       txq->stats.len, txq->head, txq->tail,
		       fw_owned, drv_owned, unused);
	}
}

/*
 * Must be called with priv->fw_mutex held and tx queues stopped.
 */
#define MWL8K_TX_WAIT_TIMEOUT_MS	1000

static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
{
	struct mwl8k_priv *priv = hw->priv;
	DECLARE_COMPLETION_ONSTACK(tx_wait);
	u32 count;
	unsigned long timeout;
	int retry;
	int rc;

	might_sleep();

	/*
	 * The TX queues are stopped at this point, so this test
	 * doesn't need to take ->tx_lock.
	 */
	if (!priv->pending_tx_pkts)
		return 0;

	retry = 0;
	rc = 0;

	spin_lock_bh(&priv->tx_lock);
	count = priv->pending_tx_pkts;
	if (count)
	priv->tx_wait = &tx_wait;
	spin_unlock_bh(&priv->tx_lock);
	while (!rc) {
		int oldcount;
		unsigned long timeout;

	if (count) {
		struct mwl8k_txq_info txinfo[MWL8K_TX_QUEUES];
		int index;
		int newcount;
		oldcount = priv->pending_tx_pkts;

		spin_unlock_bh(&priv->tx_lock);
		timeout = wait_for_completion_timeout(&tx_wait,
					msecs_to_jiffies(5000));
		if (timeout)
			return 0;

			    msecs_to_jiffies(MWL8K_TX_WAIT_TIMEOUT_MS));
		spin_lock_bh(&priv->tx_lock);
		priv->tx_wait = NULL;
		newcount = priv->pending_tx_pkts;
		mwl8k_scan_tx_ring(priv, txinfo);
		spin_unlock_bh(&priv->tx_lock);

		printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n",
		       __func__, __LINE__, count, newcount);
		if (timeout) {
			WARN_ON(priv->pending_tx_pkts);
			if (retry) {
				printk(KERN_NOTICE "%s: tx rings drained\n",
				       wiphy_name(hw->wiphy));
			}
			break;
		}

		for (index = 0; index < MWL8K_TX_QUEUES; index++)
			printk(KERN_ERR "TXQ:%u L:%u H:%u T:%u FW:%u "
			       "DRV:%u U:%u\n",
					index,
					txinfo[index].len,
					txinfo[index].head,
					txinfo[index].tail,
					txinfo[index].fw_owned,
					txinfo[index].drv_owned,
					txinfo[index].unused);
		if (priv->pending_tx_pkts < oldcount) {
			printk(KERN_NOTICE "%s: timeout waiting for tx "
			       "rings to drain (%d -> %d pkts), retrying\n",
			       wiphy_name(hw->wiphy), oldcount,
			       priv->pending_tx_pkts);
			retry = 1;
			continue;
		}

		priv->tx_wait = NULL;

		printk(KERN_ERR "%s: tx rings stuck for %d ms\n",
		       wiphy_name(hw->wiphy), MWL8K_TX_WAIT_TIMEOUT_MS);
		mwl8k_dump_tx_rings(hw);

		return -ETIMEDOUT;
		rc = -ETIMEDOUT;
	}
	spin_unlock_bh(&priv->tx_lock);

	return 0;
	return rc;
}

#define MWL8K_TXD_SUCCESS(status)				\
@@ -1361,7 +1382,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
		BUG_ON(skb == NULL);
		pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);

		mwl8k_remove_dma_header(skb);
		mwl8k_remove_dma_header(skb, tx_desc->qos_control);

		/* Mark descriptor as unused */
		tx_desc->pkt_phys_addr = 0;
@@ -1563,8 +1584,8 @@ static void mwl8k_fw_unlock(struct ieee80211_hw *hw)
 * Command processing.
 */

/* Timeout firmware commands after 2000ms */
#define MWL8K_CMD_TIMEOUT_MS	2000
/* Timeout firmware commands after 10s */
#define MWL8K_CMD_TIMEOUT_MS	10000

static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
{
@@ -1615,12 +1636,21 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
		       MWL8K_CMD_TIMEOUT_MS);
		rc = -ETIMEDOUT;
	} else {
		int ms;

		ms = MWL8K_CMD_TIMEOUT_MS - jiffies_to_msecs(timeout);

		rc = cmd->result ? -EINVAL : 0;
		if (rc)
			printk(KERN_ERR "%s: Command %s error 0x%x\n",
			       wiphy_name(hw->wiphy),
			       mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
			       le16_to_cpu(cmd->result));
		else if (ms > 2000)
			printk(KERN_NOTICE "%s: Command %s took %d ms\n",
			       wiphy_name(hw->wiphy),
			       mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
			       ms);
	}

	return rc;
@@ -2439,8 +2469,6 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
/*
 * CMD_FINALIZE_JOIN.
 */

/* FJ beacon buffer size is compiled into the firmware.  */
#define MWL8K_FJ_BEACON_MAXLEN	128

struct mwl8k_cmd_finalize_join {
@@ -2450,17 +2478,13 @@ struct mwl8k_cmd_finalize_join {
} __attribute__((packed));

static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
				__u16 framelen, __u16 dtim)
			       int framelen, int dtim)
{
	struct mwl8k_cmd_finalize_join *cmd;
	struct ieee80211_mgmt *payload = frame;
	u16 hdrlen;
	u32 payload_len;
	int payload_len;
	int rc;

	if (frame == NULL)
		return -EINVAL;

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
	if (cmd == NULL)
		return -ENOMEM;
@@ -2469,24 +2493,17 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
	cmd->header.length = cpu_to_le16(sizeof(*cmd));
	cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1);

	hdrlen = ieee80211_hdrlen(payload->frame_control);

	payload_len = framelen > hdrlen ? framelen - hdrlen : 0;

	/* XXX TBD Might just have to abort and return an error */
	if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
		printk(KERN_ERR "%s(): WARNING: Incomplete beacon "
		       "sent to firmware. Sz=%u MAX=%u\n", __func__,
		       payload_len, MWL8K_FJ_BEACON_MAXLEN);

	if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
	payload_len = framelen - ieee80211_hdrlen(payload->frame_control);
	if (payload_len < 0)
		payload_len = 0;
	else if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
		payload_len = MWL8K_FJ_BEACON_MAXLEN;

	if (payload && payload_len)
	memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);

	rc = mwl8k_post_cmd(hw, &cmd->header);
	kfree(cmd);

	return rc;
}

@@ -2515,9 +2532,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
	struct ieee80211_bss_conf *info = &mv_vif->bss_info;
	struct mwl8k_cmd_update_sta_db *cmd;
	struct peer_capability_info *peer_info;
	struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
	int rc;
	__u8 count, *rates;

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
	if (cmd == NULL)
@@ -2536,13 +2551,11 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
		/* Build peer_info block */
		peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
		peer_info->basic_caps = cpu_to_le16(info->assoc_capability);
		memcpy(peer_info->legacy_rates, mwl8k_rateids,
		       sizeof(mwl8k_rateids));
		peer_info->interop = 1;
		peer_info->amsdu_enabled = 0;

		rates = peer_info->legacy_rates;
		for (count = 0; count < mv_vif->legacy_nrates; count++)
			rates[count] = bitrates[count].hw_value;

		rc = mwl8k_post_cmd(hw, &cmd->header);
		if (rc == 0)
			mv_vif->peer_id = peer_info->station_id;
@@ -2565,8 +2578,6 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
/*
 * CMD_SET_AID.
 */
#define MWL8K_RATE_INDEX_MAX_ARRAY			14

#define MWL8K_FRAME_PROT_DISABLED			0x00
#define MWL8K_FRAME_PROT_11G				0x07
#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY		0x02
@@ -2579,7 +2590,7 @@ struct mwl8k_cmd_update_set_aid {
	 /* AP's MAC address (BSSID) */
	__u8	bssid[ETH_ALEN];
	__le16	protection_mode;
	__u8	supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY];
	__u8	supp_rates[14];
} __attribute__((packed));

static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
@@ -2588,8 +2599,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
	struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
	struct ieee80211_bss_conf *info = &mv_vif->bss_info;
	struct mwl8k_cmd_update_set_aid *cmd;
	struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
	int count;
	u16 prot_mode;
	int rc;

@@ -2621,8 +2630,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
	}
	cmd->protection_mode = cpu_to_le16(prot_mode);

	for (count = 0; count < mv_vif->legacy_nrates; count++)
		cmd->supp_rates[count] = bitrates[count].hw_value;
	memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids));

	rc = mwl8k_post_cmd(hw, &cmd->header);
	kfree(cmd);
@@ -2635,20 +2643,17 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
 */
struct mwl8k_cmd_update_rateset {
	struct	mwl8k_cmd_pkt header;
	__u8	legacy_rates[MWL8K_RATE_INDEX_MAX_ARRAY];
	__u8	legacy_rates[14];

	/* Bitmap for supported MCS codes.  */
	__u8	mcs_set[MWL8K_IEEE_LEGACY_DATA_RATES];
	__u8	reserved[MWL8K_IEEE_LEGACY_DATA_RATES];
	__u8	mcs_set[16];
	__u8	reserved[16];
} __attribute__((packed));

static int mwl8k_update_rateset(struct ieee80211_hw *hw,
		struct ieee80211_vif *vif)
{
	struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
	struct mwl8k_cmd_update_rateset *cmd;
	struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
	int count;
	int rc;

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -2657,9 +2662,7 @@ static int mwl8k_update_rateset(struct ieee80211_hw *hw,

	cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
	cmd->header.length = cpu_to_le16(sizeof(*cmd));

	for (count = 0; count < mv_vif->legacy_nrates; count++)
		cmd->legacy_rates[count] = bitrates[count].hw_value;
	memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids));

	rc = mwl8k_post_cmd(hw, &cmd->header);
	kfree(cmd);
@@ -2932,11 +2935,6 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
	/* Back pointer to parent config block */
	mwl8k_vif->priv = priv;

	/* Setup initial PHY parameters */
	memcpy(mwl8k_vif->legacy_rates,
		priv->rates, sizeof(mwl8k_vif->legacy_rates));
	mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates);

	/* Set Initial sequence number to zero */
	mwl8k_vif->seqno = 0;

@@ -3014,9 +3012,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
	struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
	int rc;

	if (changed & BSS_CHANGED_BSSID)
		memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN);

	if ((changed & BSS_CHANGED_ASSOC) == 0)
		return;

@@ -3030,6 +3025,8 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
		memcpy(&mwl8k_vif->bss_info, info,
			sizeof(struct ieee80211_bss_conf));

		memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN);

		/* Install rates */
		rc = mwl8k_update_rateset(hw, vif);
		if (rc)
@@ -3366,7 +3363,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
	if (rc) {
		printk(KERN_ERR "%s: Cannot obtain PCI resources\n",
		       MWL8K_NAME);
		return rc;
		goto err_disable_device;
	}

	pci_set_master(pdev);
@@ -3597,6 +3594,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,

err_free_reg:
	pci_release_regions(pdev);

err_disable_device:
	pci_disable_device(pdev);

	return rc;
+1 −1
Original line number Diff line number Diff line
@@ -427,7 +427,7 @@ int hermesi_program_init(hermes_t *hw, u32 offset)
	if (err)
		return err;

	pr_debug(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset);
	pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset);
	err = hermes_doicmd_wait(hw,
				 HERMES_PROGRAM_ENABLE_VOLATILE,
				 offset & 0xFFFFu,
Loading