diff options
Diffstat (limited to 'drivers/net/wireless/p54/fwio.c')
| -rw-r--r-- | drivers/net/wireless/p54/fwio.c | 62 | 
1 files changed, 52 insertions, 10 deletions
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 92b9b1f05fd..bc065e8e348 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -16,10 +16,10 @@   * published by the Free Software Foundation.   */ -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/firmware.h>  #include <linux/etherdevice.h> +#include <linux/export.h>  #include <net/mac80211.h> @@ -385,6 +385,7 @@ int p54_setup_mac(struct p54_common *priv)  		setup->v2.osc_start_delay = cpu_to_le16(65535);  	}  	p54_tx(priv, skb); +	priv->phy_idle = mode == P54_FILTER_TYPE_HIBERNATE;  	return 0;  } @@ -397,10 +398,10 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)  	union p54_scan_body_union *body;  	struct p54_scan_tail_rate *rate;  	struct pda_rssi_cal_entry *rssi; +	struct p54_rssi_db_entry *rssi_data;  	unsigned int i;  	void *entry; -	int band = priv->hw->conf.channel->band; -	__le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq); +	__le16 freq = cpu_to_le16(priv->hw->conf.chandef.chan->center_freq);  	skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +  			    2 + sizeof(*iq_autocal) + sizeof(*body) + @@ -476,7 +477,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)  		if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {  			memcpy(&body->longbow.curve_data, -				(void *) entry + sizeof(__le16), +				entry + sizeof(__le16),  				priv->curve_data->entry_size);  		} else {  			struct p54_scan_body *chan = &body->normal; @@ -503,13 +504,14 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)  	}  	rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi)); -	rssi->mul = cpu_to_le16(priv->rssical_db[band].mul); -	rssi->add = cpu_to_le16(priv->rssical_db[band].add); +	rssi_data = p54_rssi_find(priv, le16_to_cpu(freq)); +	rssi->mul = cpu_to_le16(rssi_data->mul); +	rssi->add = cpu_to_le16(rssi_data->add);  	if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {  		/* Longbow frontend needs ever more */  		rssi = (void *) skb_put(skb, sizeof(*rssi)); -		rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn); -		rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2); +		rssi->mul = cpu_to_le16(rssi_data->longbow_unkn); +		rssi->add = cpu_to_le16(rssi_data->longbow_unk2);  	}  	if (priv->fw_var >= 0x509) { @@ -523,12 +525,13 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)  	hdr->len = cpu_to_le16(skb->len - sizeof(*hdr));  	p54_tx(priv, skb); +	priv->cur_rssi = rssi_data;  	return 0;  err:  	wiphy_err(priv->hw->wiphy, "frequency change to channel %d failed.\n",  		  ieee80211_frequency_to_channel( -			  priv->hw->conf.channel->center_freq)); +			  priv->hw->conf.chandef.chan->center_freq));  	dev_kfree_skb_any(skb);  	return -EINVAL; @@ -557,6 +560,7 @@ int p54_set_edcf(struct p54_common *priv)  {  	struct sk_buff *skb;  	struct p54_edcf *edcf; +	u8 rtd;  	skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf),  			    P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC); @@ -573,9 +577,15 @@ int p54_set_edcf(struct p54_common *priv)  		edcf->sifs = 0x0a;  		edcf->eofpad = 0x06;  	} +	/* +	 * calculate the extra round trip delay according to the +	 * formula from 802.11-2007 17.3.8.6. +	 */ +	rtd = 3 * priv->coverage_class; +	edcf->slottime += rtd; +	edcf->round_trip_delay = cpu_to_le16(rtd);  	/* (see prism54/isl_oid.h for further details) */  	edcf->frameburst = cpu_to_le16(0); -	edcf->round_trip_delay = cpu_to_le16(0);  	edcf->flags = 0;  	memset(edcf->mapping, 0, sizeof(edcf->mapping));  	memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue)); @@ -617,6 +627,7 @@ int p54_set_ps(struct p54_common *priv)  	psm->exclude[0] = WLAN_EID_TIM;  	p54_tx(priv, skb); +	priv->phy_ps = mode != P54_PSM_CAM;  	return 0;  } @@ -718,3 +729,34 @@ int p54_fetch_statistics(struct p54_common *priv)  	p54_tx(priv, skb);  	return 0;  } + +int p54_set_groupfilter(struct p54_common *priv) +{ +	struct p54_group_address_table *grp; +	struct sk_buff *skb; +	bool on = false; + +	skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*grp), +			    P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE, GFP_KERNEL); +	if (!skb) +		return -ENOMEM; + +	grp = (struct p54_group_address_table *)skb_put(skb, sizeof(*grp)); + +	on = !(priv->filter_flags & FIF_ALLMULTI) && +	     (priv->mc_maclist_num > 0 && +	      priv->mc_maclist_num <= MC_FILTER_ADDRESS_NUM); + +	if (on) { +		grp->filter_enable = cpu_to_le16(1); +		grp->num_address = cpu_to_le16(priv->mc_maclist_num); +		memcpy(grp->mac_list, priv->mc_maclist, sizeof(grp->mac_list)); +	} else { +		grp->filter_enable = cpu_to_le16(0); +		grp->num_address = cpu_to_le16(0); +		memset(grp->mac_list, 0, sizeof(grp->mac_list)); +	} + +	p54_tx(priv, skb); +	return 0; +}  | 
