p54: various updates
cover p54: various updates
Hi,
this is the next RFC round...
1) rename all prism54* to p54* (to match the filenames)
2) rx_tasklet for p54pci
3) link statistics
4) AP-Patch
---
diffstat:
p54.h | 40 ++++ p54common.c | 487 ++++++++++++++++++++++++++++++++++++++++++++++++------------ p54common.h | 111 ++++++++++--- p54pci.c | 283 ++++++++++++++++++++++------------ p54pci.h | 20 +- p54usb.c | 34 ++-- p54usb.h | 6 7 files changed, 726 insertions(+), 255 deletions(-)
Quoted 10 lines · Chr
Hi,
this is the next RFC round...
1) rename all prism54* to p54* (to match the filenames)
2)rx_taskletfor p54pci
3) link statistics
4) AP-PatchSigned-off-by Christian Lamparter <[email protected]>
Thanks, can you resend as inline patches so it can help get better review. Also while you're at it can you stuff all p54 files into its own folder?
Luis
Quoted 4 lines · On Thursday 03 April 2008 01:42:59 Luis R. Rodriguez wrote:
Thanks, can you resend as inline patches so it can help get better review. Also while you're at it can you stuff all p54 files into its own folder?
hmm, I can.... but:
- in which folder? for now.. I put everything into a new one folder named p54, but as you know the fullmac driver has already the prism54 subdirectory... should I put it there? or is this confusing?
- the resulting patch is too big to post it here, ~ 271kb as plaintext... is a bz2 (32kb) attachment ok too?
diffstat:
b/drivers/net/wireless/Kconfig | 65 -- b/drivers/net/wireless/Makefile | 4 b/drivers/net/wireless/p54/Kconfig | 63 + b/drivers/net/wireless/p54/Makefile | 3 b/drivers/net/wireless/p54/net2280.h | 452 ++++++++++++++ b/drivers/net/wireless/p54/p54.h | 77 ++ b/drivers/net/wireless/p54/p54common.c | 1051 +++++++++++++++++++++++++++++++++ b/drivers/net/wireless/p54/p54common.h | 254 +++++++ b/drivers/net/wireless/p54/p54pci.c | 697 +++++++++++++++++++++ b/drivers/net/wireless/p54/p54pci.h | 106 +++ b/drivers/net/wireless/p54/p54usb.c | 910 ++++++++++++++++++++++++++++ b/drivers/net/wireless/p54/p54usb.h | 133 ++++ drivers/net/wireless/net2280.h | 452 -------------- drivers/net/wireless/p54.h | 77 -- drivers/net/wireless/p54common.c | 1051 --------------------------------- drivers/net/wireless/p54common.h | 254 ------- drivers/net/wireless/p54pci.c | 697 --------------------- drivers/net/wireless/p54pci.h | 106 --- drivers/net/wireless/p54usb.c | 910 ---------------------------- drivers/net/wireless/p54usb.h | 133 ---- 20 files changed, 3748 insertions(+), 3747 deletions(-)
Regards,
Chr
Quoted 9 lines · Chr
Quoted 4 lines · On Thursday 03 April 2008 01:42:59 Luis R. Rodriguez wrote:
Thanks, can you resend as inline patches so it can help get better review. Also while you're at it can you stuff all p54 files into its own folder?
hmm, I can.... but:
- in which folder? for now.. I put everything into a new one folder named p54, but as you know the fullmac driver has already the prism54 subdirectory... should I put it there? or is this confusing?
p54 directory works nice. Now that you are introducing master mode the only thing left I think is IBSS compared to prism54, and if that is done I think we should *consider* removing prism54 driver after one release cycle of the kernel. I once was told that for some cards the softmac driver wouldn't work on some fullmac chipsets. I have yet to hear of someone who found these type of cards though. I know we also had some WDS code for prism54 lying around, it just never got merged in because Jeff didn't find it widely used and IIRC it needed a little more cleanup.
Think you can get IBSS and maybe WDS to work too?
Quoted 2 lines
- the resulting patch is too big to post it here, ~ 271kb as plaintext... is a bz2 (32kb) attachment ok too?
Oh OK, I see. Can you perhaps split the big patch up into a few series?
Luis
Quoted 21 lines · On Friday 04 April 2008 00:34:35 Luis R. Rodriguez wrote:
Quoted 9 lines · Chr
Quoted 3 lines · On Thursday 03 April 2008 01:42:59 Luis R. Rodriguez wrote:
Thanks, can you resend as inline patches so it can help get better review. Also while you're at it can you stuff all p54 files into its own folder?
hmm, I can.... but:
- in which folder? for now.. I put everything into a new one folder
named p54, but as you know the fullmac driver has already the prism54 subdirectory... should I put it there? or is this confusing?p54 directory works nice. Now that you are introducing master mode the only thing left I think is IBSS compared to prism54, and if that is done I think we should *consider* removing prism54 driver after one release cycle of the kernel. I once was told that for some cards the softmac driver wouldn't work on some fullmac chipsets. I have yet to hear of someone who found these type of cards though. I know we also had some WDS code for prism54 lying around, it just never got merged in because Jeff didn't find it widely used and IIRC it needed a little more cleanup.
Quoted 2 lines
Think you can get IBSS and maybe WDS to work too?
Hmm, AFAIK they were thinking of the 3877 (802.11a only)... I guess this one won't work with p54. But have you ever see anyone (except the Intersil/Conexant people) with a 5Ghz prism card at all? It'll be interesting to get a eeprom dump from them...
About WDS: is there anything special about WDS, that I should know? Since, I thought it's entirely done by mac80211 by now?
About IBSS: yes, it is kind of working... I'll put some code for this in the next round.
Quoted 4 lines
Quoted 2 lines
- the resulting patch is too big to post it here, ~ 271kb as
plaintext... is a bz2 (32kb) attachment ok too?Oh OK, I see. Can you perhaps split the big patch up into a few series?
that'll be about 3 or 4 parts... tomorrow! I have to figure out how I can split up the _big_ one.
Regards,
Chr
cover p54: various updates (all in one)
Give it a good testing!
Notes:
- IBSS mode is maybe a buggy, but it'll take another semester break to figure out whats wrong with the TSF timer.
- Powersaving package queueing is disabled in AP-Mode. As my Intel 4965N won't reconnect with it. (but the atheros card does?!)
BTW:
since no one has the codebase to p54/, or made any other changes I made the (all-in-on) diff against the (old) kernel-code... but with the _new_ path!
if you want to test it, don't forget the mac80211 patch!
http://article.gmane.org/gmane.linux.kernel.wireless.general/13115
Regards,
Chr.
drivers/net/wireless/p54/p54common.c +444 -91
@@ -3,7 +3,7 @@* Common code for mac80211 Prism54 drivers * * Copyright (c) 2006, Michael Wu <[email protected]> -* Copyright (c) 2007, Christian Lamparter <[email protected]> +* Copyright (c) 2007, 2008, Christian Lamparter <[email protected]> * * Based on the islsm (softmac prism54) driver, which is: * Copyright 2004-2006 Jean-Baptiste Note <[email protected]>, et al.
@@ -25,7 +25,7 @@MODULE_AUTHOR ("Michael Wu <[email protected]>" );MODULE_DESCRIPTION ("Softmac Prism54 common code" );MODULE_LICENSE ("GPL" ); -MODULE_ALIAS ("prism54common" ); +MODULE_ALIAS ("p54common" );static struct ieee80211_rate p54_rates[] = { { .bitrate =10 , .hw_value =0 , .flags =IEEE80211_RATE_SHORT_PREAMBLE },
@@ -66,7 +66,6 @@ static struct ieee80211_supported_band b .n_bitrates = ARRAY_SIZE(p54_rates), }; -void p54_parse_firmware (struct ieee80211_hw *dev,const struct firmware *fw) {struct p54_common *priv = dev->priv;
@@ -146,10 +145,10 @@ void p54_parse_firmware(struct ieee80211if (priv->fw_var >=0x300 ) {/* Firmware supports QoS, use it! */ - priv->tx_stats.data[0 ].limit =3 ; - priv->tx_stats.data[1 ].limit =4 ; - priv->tx_stats.data[2 ].limit =3 ; - priv->tx_stats.data[3 ].limit =1 ; + priv->tx_stats[4 ].limit =3 ; + priv->tx_stats[5 ].limit =4 ; + priv->tx_stats[6 ].limit =3 ; + priv->tx_stats[7 ].limit =1 ; dev->queues =4 ; } }
@@ -297,10 +296,6 @@ int p54_parse_eeprom(struct ieee80211_hw/* make it overrun */ entry_len = len;break ; -default : -printk (KERN_INFO "p54: unknown eeprom code : 0x%x\n" , -le16_to_cpu (entry->code)); -break ; } entry = (void *)entry + (entry_len +1 )*2 ;
@@ -335,6 +330,11 @@ int p54_parse_eeprom(struct ieee80211_hw }EXPORT_SYMBOL_GPL (p54_parse_eeprom); +static inline int p54_rssi_to_dbm (u8 rssi) +{ +return rssi /2 -100 ; +} +void p54_fill_eeprom_readback (struct p54_control_hdr *hdr) {struct p54_eeprom_lm86 *eeprom_hdr;
@@ -349,16 +349,28 @@ void p54_fill_eeprom_readback(struct p54 }EXPORT_SYMBOL_GPL (p54_fill_eeprom_readback); -static void p54_rx_data (struct ieee80211_hw *dev,struct sk_buff *skb) +static int p54_rx_data (struct ieee80211_hw *dev,struct sk_buff *skb) { +struct p54_common *priv = dev->priv;struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;struct ieee80211_rx_status rx_status = {0 }; -u16 freq =le16_to_cpu (hdr->freq); - rx_status.ssi = hdr->rssi; -/* XX correct? */ +if (!(hdr->magic &cpu_to_le16 (0x01 ))) { +if (priv->rx_filter ==P54_RX_FILTER_FCSFAIL ) + rx_status.flag |=RX_FLAG_FAILED_FCS_CRC ; +else +/* reuse skb */ +return 0 ; + } + rx_status.ssi =p54_rssi_to_dbm (hdr->rssi); + rx_status.noise = priv->stats.noise_floor; +if (rx_status.ssi > rx_status.noise) + rx_status.signal = rx_status.ssi - rx_status.noise; + +/* FIX MAC80211: for now we remove the short preamble flag */ rx_status.rate_idx = hdr->rate &0xf ; - rx_status.freq = freq; + + rx_status.freq =le16_to_cpu (hdr->freq); rx_status.band =IEEE80211_BAND_2GHZ ; rx_status.antenna = hdr->antenna; rx_status.mactime =le64_to_cpu (hdr->timestamp);
@@ -368,6 +380,8 @@ static void p54_rx_data(struct ieee80211skb_trim (skb,le16_to_cpu (hdr->len));ieee80211_rx_irqsafe (dev, skb, &rx_status); + +return -1 ; }static void inline p54_wake_free_queues (struct ieee80211_hw *dev)
@@ -379,7 +393,7 @@ static void inline p54_wake_free_queues(* But, what if some are full? */ for (i =0 ; i < dev->queues; i++) -if (priv->tx_stats.data[i].len < priv->tx_stats.data[i].limit) +if (priv->tx_stats[i +4 ].len < priv->tx_stats[i +4 ].limit)ieee80211_wake_queue (dev, i); }
@@ -388,12 +402,15 @@ static void p54_rx_frame_sent(struct ieestruct p54_common *priv = dev->priv;struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data; -struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next; +struct sk_buff *entry; +unsigned long flags;u32 addr =le32_to_cpu (hdr->req_id) -0x70 ;struct memrecord *range =NULL ;u32 freed =0 ;u32 last_addr = priv->rx_start; +spin_lock_irqsave (&priv->tx_queue.lock, flags); + entry = (struct sk_buff *) priv->tx_queue.next;while (entry != (struct sk_buff *)&priv->tx_queue) { range = (struct memrecord *)&entry->cb;if (range->start_addr == addr) {
@@ -409,42 +426,68 @@ static void p54_rx_frame_sent(struct iee last_addr = range->end_addr;__skb_unlink (entry, &priv->tx_queue); +spin_unlock_irqrestore (&priv->tx_queue.lock, flags); +if (!range->control) {kfree_skb (entry); -break ; + goto out; }memset (&status,0 ,sizeof (status));memcpy (&status.control, range->control,sizeof (status.control));kfree (range->control); - priv->tx_stats.data[status.control.queue].len--; entry_hdr = (struct p54_control_hdr *) entry->data; entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; + priv->tx_stats[entry_data->frame_type].len--; +if ((entry_hdr->magic1 &cpu_to_le16 (0x4000 )) !=0 ) pad = entry_data->align[0 ];if (!(status.control.flags &IEEE80211_TXCTL_NO_ACK )) {if (!(payload->status &0x01 )) status.flags |=IEEE80211_TX_STATUS_ACK ; -else - status.excessive_retries =1 ; +else { +if ((payload->status &0x04 ) && + (priv->mode ==IEEE80211_IF_TYPE_AP )) + status.flags |=IEEE80211_TX_STATUS_TX_FILTERED ; +else + status.excessive_retries =1 ; + } } status.retry_count = payload->retries -1 ; status.ack_signal =le16_to_cpu (payload->ack_rssi);skb_pull (entry,sizeof (*hdr) + pad +sizeof (*entry_data));ieee80211_tx_status_irqsafe (dev, entry, &status); -break ; + goto out; }else last_addr = range->end_addr; entry = entry->next; } +spin_unlock_irqrestore (&priv->tx_queue.lock, flags); +out:if (freed >=IEEE80211_MAX_RTS_THRESHOLD +0x170 +sizeof (struct p54_control_hdr ))p54_wake_free_queues (dev); } +static void p54_rx_stats (struct ieee80211_hw *dev,struct sk_buff *skb) +{ +struct p54_common *priv = dev->priv; +struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data; +struct p54_statistics *hw_stats = (struct p54_statistics *)hdr->data; + + priv->stats.rx_success =le32_to_cpu (hw_stats->rx_success); + priv->stats.rx_errors =le32_to_cpu (hw_stats->rx_errors); + priv->stats.rx_aborts =le32_to_cpu (hw_stats->rx_aborts); + priv->stats.rx_aborts_phy =le32_to_cpu (hw_stats->rx_aborts_phy); + priv->stats.rx_rts_success =le32_to_cpu (hw_stats->rx_rts_success); + priv->stats.rx_rts_failed =le32_to_cpu (hw_stats->rx_rts_failed); + priv->stats.noise_floor =p54_rssi_to_dbm (hw_stats->noise_floor); + priv->stats.tsf =le32_to_cpu (hw_stats->tsf); +} +static void p54_rx_control (struct ieee80211_hw *dev,struct sk_buff *skb) {struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
@@ -453,6 +496,9 @@ static void p54_rx_control(struct ieee80case P54_CONTROL_TYPE_TXDONE :p54_rx_frame_sent (dev, skb);break ; +case P54_CONTROL_TYPE_STAT_READBACK : +p54_rx_stats (dev, skb); +break ;case P54_CONTROL_TYPE_BBP :break ;default :
@@ -469,8 +515,7 @@ int p54_rx(struct ieee80211_hw *dev, strswitch (type) {case 0x00 :case 0x01 : -p54_rx_data (dev, skb); -return -1 ; +return p54_rx_data (dev, skb);case 0x4d :/* TODO: do something better... but then again, I've never seen this happen */ printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n",
@@ -552,6 +597,67 @@ static void p54_assign_address(struct ie data->req_id =cpu_to_le32 (target_addr +0x70 ); } +#ifndef WLAN_FC_GET_TYPE +#define WLAN_FC_GET_TYPE (fc) (fc & IEEE80211_FCTL_FTYPE) +#define WLAN_FC_GET_STYPE (fc) (fc & IEEE80211_FCTL_STYPE) +#endif + +static int p54_tx_fill_header (struct ieee80211_hw *dev,struct ieee80211_hdr *hdr, +struct ieee80211_tx_control *control,u8 *retry1,u8 *retry2, +u8 *frame_type,u16 *magic,u16 *aid) +{ +struct p54_common *priv = dev->priv; +u16 fc =le16_to_cpu (hdr->frame_control); + +if (!(control->flags & (IEEE80211_TXCTL_USE_RTS_CTS | +IEEE80211_TXCTL_USE_CTS_PROTECT ))) + *magic =0x10 ; +else + *magic =0 ; + + *retry1 = *retry2 = control->retry_limit; + +if ((control->flags &IEEE80211_TXCTL_NO_ACK )) + *aid =0 ; +else { +if (control->aid) + *aid = control->aid +1 ; +else + *aid =1 ; + } + +/* TODO: enable powersaving package queueing in AP-Mode */ +if (priv->mode ==IEEE80211_IF_TYPE_AP ) + *magic |=0x20 ; + +if (unlikely (WLAN_FC_GET_TYPE (fc) ==IEEE80211_FTYPE_MGMT )) +switch (WLAN_FC_GET_STYPE (fc)) { +case IEEE80211_STYPE_PROBE_REQ : + *aid =0 ; + *magic |=0x20 ; + *frame_type =1 ; +return 0 ; +case IEEE80211_STYPE_BEACON : + *aid =0 ; + *retry2 = *retry1 =1 ; + *frame_type =0 ; + *magic =0x02 ;/* tell the FW to fill in the TSF */ +return 0 ; +case IEEE80211_STYPE_PROBE_RESP : + *magic |=0x02 ; + *aid =0 ; + *frame_type =2 ; +return 0 ; +default : + *frame_type =2 ; +return 0 ; + } +else + *frame_type = control->queue +4 ; + +return 1 ; +} +static int p54_tx (struct ieee80211_hw *dev,struct sk_buff *skb,struct ieee80211_tx_control *control) {
@@ -560,16 +666,26 @@ static int p54_tx(struct ieee80211_hw *dstruct p54_control_hdr *hdr;struct p54_tx_control_allocdata *txhdr;struct ieee80211_tx_control *control_copy; +struct ieee80211_hdr *ieeehdr = (struct ieee80211_hdr *)skb->data;size_t padding, len; -u8 rate; +u16 aid, magic; +u8 rate, retry1, retry2, frame_type; - current_queue = &priv->tx_stats.data[control->queue]; -if (unlikely (current_queue->len > current_queue->limit)) -return NETDEV_TX_BUSY ; - current_queue->len++; - current_queue->count++; -if (current_queue->len == current_queue->limit) -ieee80211_stop_queue (dev, control->queue); +if (p54_tx_fill_header (dev, ieeehdr, control, &retry1, &retry2, + &frame_type, &magic, &aid)) { + + current_queue = &priv->tx_stats[frame_type]; +if (unlikely (current_queue->len > current_queue->limit)) +return NETDEV_TX_BUSY ; + current_queue->len++; + current_queue->count++; +if (current_queue->len == current_queue->limit) +ieee80211_stop_queue (dev, control->queue); + }else { + current_queue = &priv->tx_stats[frame_type]; + current_queue->len++; + current_queue->count++; + } padding = (unsigned long )(skb->data - (sizeof (*hdr) +sizeof (*txhdr))) &3 ; len = skb->len;
@@ -583,36 +699,38 @@ static int p54_tx(struct ieee80211_hw *d hdr = (struct p54_control_hdr *)skb_push (skb,sizeof (*hdr));if (padding) - hdr->magic1 =cpu_to_le16 (0x4010 ); -else - hdr->magic1 =cpu_to_le16 (0x0010 ); + magic |=0x4000 ; + + hdr->magic1 =cpu_to_le16 (magic); hdr->len =cpu_to_le16 (len); - hdr->type = (control->flags &IEEE80211_TXCTL_NO_ACK ) ?0 :cpu_to_le16 (1 ); - hdr->retry1 = hdr->retry2 = control->retry_limit; + hdr->type =cpu_to_le16 (aid); + hdr->retry1 = retry1; + hdr->retry2 = retry2;p54_assign_address (dev, skb, hdr, skb->len, control_copy); -memset (txhdr->wep_key,0x0 ,16 ); - txhdr->padding =0 ; - txhdr->padding2 =0 ; -/* TODO: add support for alternate retry TX rates */ rate = control->tx_rate->hw_value;if (control->flags &IEEE80211_TXCTL_SHORT_PREAMBLE ) rate |=0x10 ; -if (control->flags &IEEE80211_TXCTL_USE_RTS_CTS ) +else if (control->flags &IEEE80211_TXCTL_USE_RTS_CTS ) rate |=0x40 ;else if (control->flags &IEEE80211_TXCTL_USE_CTS_PROTECT ) rate |=0x20 ;memset (txhdr->rateset, rate,8 ); - txhdr->wep_key_present =0 ; - txhdr->wep_key_len =0 ; - txhdr->frame_type =cpu_to_le32 (control->queue +4 ); - txhdr->magic4 =0 ; + txhdr->key_type =0 ; + txhdr->key_len =0 ; + txhdr->frame_type = frame_type; txhdr->antenna = (control->antenna_sel_tx ==0 ) ?2 : control->antenna_sel_tx -1 ; - txhdr->output_power =0x7f ;// HW Maximum - txhdr->magic5 = (control->flags &IEEE80211_TXCTL_NO_ACK ) ? -0 : ((rate >0x3 ) ?cpu_to_le32 (0x33 ) :cpu_to_le32 (0x23 )); + txhdr->output_power =0x7f ;/* 0.25 dbm / unit */ +if (control->rts_cts_rate) + txhdr->cts_rate = (control->flags &IEEE80211_TXCTL_NO_ACK ) ? +0 : (control->rts_cts_rate->hw_value |0x20 | + (rate &0x10 )); +else + txhdr->cts_rate = (control->flags &IEEE80211_TXCTL_NO_ACK ) ? +0 : (0x23 | (rate &0x10 )); +if (padding) txhdr->align[0 ] = padding;
@@ -620,9 +738,36 @@ static int p54_tx(struct ieee80211_hw *dreturn 0 ; } -static int p54_set_filter (struct ieee80211_hw *dev,u16 filter_type, -const u8 *dst,const u8 *src,u8 antenna, -u32 magic3,u32 magic8,u32 magic9) +int __p54_set_tim (struct ieee80211_hw *dev,u16 aid,int set) +{ +struct p54_common *priv = dev->priv; +struct p54_control_hdr *hdr; +struct p54_tx_control_tim *tim; + + hdr =kzalloc (sizeof (*hdr) +sizeof (*tim) + + priv->tx_hdr_len,GFP_ATOMIC ); +if (!hdr) +return -ENOMEM ; + + hdr = (void *)hdr + priv->tx_hdr_len; + hdr->magic1 =cpu_to_le16 (0x8001 ); + hdr->len =cpu_to_le16 (sizeof (*tim)); + hdr->type =cpu_to_le16 (P54_CONTROL_TYPE_TIM ); +p54_assign_address (dev,NULL , hdr,sizeof (*hdr) +sizeof (*tim),NULL ); + + tim = (struct p54_tx_control_tim *) hdr->data; + tim->count =1 ;/* just one entry */ + tim->entry[0 ] = set ?cpu_to_le16 (aid |0x8000 ) :cpu_to_le16 (aid); + + priv->tx (dev, hdr,sizeof (*hdr) +sizeof (*tim),1 ); + +return 0 ; +} + +const static unsigned char p54_client_rts_rates[8 ] = {8 ,6 ,4 ,1 ,0 ,0 ,0 ,0 }; +const static unsigned char p54_ap_rts_rates[8 ] = {3 ,3 ,1 ,0 ,0 ,0 ,0 ,0 }; + +static int p54_set_filter (struct ieee80211_hw *dev,u8 filter_type) {struct p54_common *priv = dev->priv;struct p54_control_hdr *hdr;
@@ -641,24 +786,68 @@ static int p54_set_filter(struct ieee802p54_assign_address (dev,NULL , hdr,sizeof (*hdr) +sizeof (*filter),NULL ); hdr->type =cpu_to_le16 (P54_CONTROL_TYPE_FILTER_SET ); - filter->filter_type =cpu_to_le16 (filter_type); -memcpy (filter->dst, dst,ETH_ALEN ); -if (!src) -memset (filter->src, ~0 ,ETH_ALEN ); + filter->filter_type = filter_type; +memcpy (filter->our_mac, priv->mac_addr,ETH_ALEN ); + +/* 0x15F is a bitrate mask +* = 0000000101011111b +* = 24MBits 12MBits 6MBit 11MBit 5.5MBits 2MBits 1Mbit */ + filter->bss_basic_rates =cpu_to_le32 (0x15F ); +memset (filter->bss_filter_mac, ~0 ,ETH_ALEN ); + +if (filter_type ==P54_FILTER_TYPE_AP ) +memcpy (filter->rts_rates, p54_ap_rts_rates,8 );else -memcpy (filter->src, src,ETH_ALEN ); - filter->antenna = antenna; - filter->magic3 =cpu_to_le32 (magic3); +memcpy (filter->rts_rates, p54_client_rts_rates,8 ); + + filter->rx_antenna = (dev->conf.antenna_sel_rx ==0 ) ?2 : + dev->conf.antenna_sel_rx -1 ; filter->rx_addr =cpu_to_le32 (priv->rx_end); filter->max_rx =cpu_to_le16 (0x0620 );/* FIXME: for usb ver 1.. maybe */ filter->rxhw = priv->rxhw; - filter->magic8 =cpu_to_le16 (magic8); - filter->magic9 =cpu_to_le16 (magic9); + +/* that's beacon_int * dtim_period * 5, unless +* there's a way to get these values here, let's +* use the standard ones */ + filter->dtim_timer =cpu_to_le16 (dev->conf.beacon_int *1 *5 ); priv->tx (dev, hdr,sizeof (*hdr) +sizeof (*filter),1 );return 0 ; } +static int p54_init_misc (struct ieee80211_hw *dev) +{ +struct p54_common *priv = dev->priv; +struct p54_control_hdr *hdr; +struct p54_tx_control_misc *misc; + + hdr =kzalloc (sizeof (*hdr) +sizeof (*misc) + + priv->tx_hdr_len,GFP_KERNEL ); +if (!hdr) +return -ENOMEM ; + + hdr = (void *)hdr + priv->tx_hdr_len; + hdr->magic1 =cpu_to_le16 (0x8001 ); + hdr->len =cpu_to_le16 (sizeof (*misc)); + hdr->type =cpu_to_le16 (P54_CONTROL_TYPE_MISCINIT ); +p54_assign_address (dev,NULL , hdr,sizeof (*hdr) +sizeof (*misc),NULL ); + + misc = (struct p54_tx_control_misc *) hdr->data; + + misc->flags =cpu_to_le16 (0 ); + misc->entry[1 ] =cpu_to_le16 (1000 ); + misc->entry[3 ] =cpu_to_le16 (1000 ); + misc->entry[5 ] =cpu_to_le16 (1000 ); + misc->entry[7 ] =cpu_to_le16 (1000 ); + + misc->flag2 =cpu_to_le16 (1 ); + misc->flag3 = misc->data =0 ; + + priv->tx (dev, hdr,sizeof (*hdr) +sizeof (*misc),1 ); + +return 0 ; +} +static int p54_set_freq (struct ieee80211_hw *dev,__le16 freq) {struct p54_common *priv = dev->priv;
@@ -811,8 +1000,8 @@ static void p54_set_vdcf(struct ieee8021if (dev->conf.flags &IEEE80211_CONF_SHORT_SLOT_TIME ) { vdcf->slottime =9 ; - vdcf->magic1 =0x00 ; - vdcf->magic2 =0x10 ; + vdcf->magic1 =0x10 ; + vdcf->magic2 =0x00 ; }else { vdcf->slottime =20 ; vdcf->magic1 =0x0a ;
@@ -861,6 +1050,8 @@ static int p54_add_interface(struct ieeeswitch (conf->type) {case IEEE80211_IF_TYPE_STA : +case IEEE80211_IF_TYPE_AP : +case IEEE80211_IF_TYPE_IBSS : priv->mode = conf->type;break ;default :
@@ -869,20 +1060,29 @@ static int p54_add_interface(struct ieeememcpy (priv->mac_addr, conf->mac_addr,ETH_ALEN ); -p54_set_filter (dev,0 , priv->mac_addr,NULL ,0 ,1 ,0 ,0xF642 ); -p54_set_filter (dev,0 , priv->mac_addr,NULL ,1 ,0 ,0 ,0xF642 ); +p54_set_filter (dev,P54_FILTER_TYPE_NONE );switch (conf->type) {case IEEE80211_IF_TYPE_STA : -p54_set_filter (dev,1 , priv->mac_addr,NULL ,0 ,0x15F ,0x1F4 ,0 ); + priv->filter_type =P54_FILTER_TYPE_STA ; +break ; +case IEEE80211_IF_TYPE_AP : + priv->filter_type =P54_FILTER_TYPE_AP ; +break ; +case IEEE80211_IF_TYPE_IBSS : + priv->filter_type =P54_FILTER_TYPE_ADHOC ;break ;default :BUG ();/* impossible */ break ; } +p54_init_misc (dev);p54_set_leds (dev,1 ,0 ,0 ); +/* start statistics readback timer */ +mod_timer (&priv->stats.timer, jiffies +HZ ); +return 0 ; }
@@ -890,9 +1090,15 @@ static void p54_remove_interface(struct struct ieee80211_if_init_conf *conf) {struct p54_common *priv = dev->priv; + +del_timer (&priv->stats.timer); +if (priv->mode ==P54_FILTER_TYPE_AP ) +__p54_set_tim (dev,0 ,0 ); + priv->mode =IEEE80211_IF_TYPE_MNTR ; + priv->filter_type =P54_FILTER_TYPE_NONE ;memset (priv->mac_addr,0 ,ETH_ALEN ); -p54_set_filter (dev,0 , priv->mac_addr,NULL ,2 ,0 ,0 ,0 ); +p54_set_filter (dev,P54_FILTER_TYPE_NONE ); }static int p54_config (struct ieee80211_hw *dev,struct ieee80211_conf *conf)
@@ -904,16 +1110,90 @@ static int p54_config(struct ieee80211_hreturn ret; } +static void p54_beacon_tim (struct sk_buff *skb) +{ +/* +* the TIM MUST be at the end of the beacon frame, +* because it'll be overwritten! +*/ + +struct ieee80211_mgmt *mgmt = (void *)skb->data; +u8 *pos, *end; + +if (skb->len <=sizeof (mgmt)) +return ; + + pos = (u8 *)mgmt->u.beacon.variable; + end = skb->data + skb->len; +while (pos < end) { +if (pos +2 + pos[1 ] > end) { +printk (KERN_ERR "p54: parsing beacon failed\n" ); +return ; + } + +if (pos[0 ] ==WLAN_EID_TIM ) { +u8 dtim_len = pos[1 ]; +u8 dtim_period; +u8 *next = pos +2 + dtim_len; + +/* mac80211 sets it atleast to 4... */ +if (dtim_len <3 ) +return ; + + dtim_period = pos[3 ]; +memmove (pos, next, end - next); +skb_trim (skb, skb->len - (dtim_len -3 )); + pos = end - (dtim_len +2 ); + +/* add a dummy at the end */ + pos[0 ] =WLAN_EID_TIM ; + pos[1 ] =3 ; + pos[2 ] =0 ; + pos[3 ] = dtim_period; + pos[4 ] =0 ; +return ; + } + pos +=2 + pos[1 ]; + } +} + +static int p54_beacon_update (struct ieee80211_hw *dev, +struct sk_buff *skb, +struct ieee80211_tx_control *control) +{ +struct p54_common *priv = dev->priv; + +p54_set_freq (dev, dev->conf.channel->center_freq); +p54_set_filter (dev, priv->filter_type); +p54_beacon_tim (skb); +p54_tx (dev, skb, control); +p54_set_vdcf (dev); +p54_set_leds (dev,1 ,1 ,0 ); + +return 0 ; +} +static int p54_config_interface (struct ieee80211_hw *dev,struct ieee80211_vif *vif,struct ieee80211_if_conf *conf) {struct p54_common *priv = dev->priv; -p54_set_filter (dev,0 , priv->mac_addr, conf->bssid,0 ,1 ,0 ,0xF642 ); -p54_set_filter (dev,0 , priv->mac_addr, conf->bssid,2 ,0 ,0 ,0 ); -p54_set_leds (dev,1 , !is_multicast_ether_addr (conf->bssid),0 ); -memcpy (priv->bssid, conf->bssid,ETH_ALEN ); +switch (conf->type) { +case IEEE80211_IF_TYPE_STA : +memcpy (priv->bssid, conf->bssid,ETH_ALEN ); +p54_set_leds (dev,1 , !is_multicast_ether_addr (conf->bssid),0 ); +break ; +case IEEE80211_IF_TYPE_AP : +if (conf->beacon && conf->beacon_control) +return p54_beacon_update (dev, conf->beacon, + conf->beacon_control); +__p54_set_tim (dev,0 ,0 ); +break ; + } + +p54_set_filter (dev, priv->filter_type); +return 0 ; }
@@ -923,16 +1203,34 @@ static void p54_configure_filter(struct int mc_count, struct dev_mc_list *mclist) { struct p54_common *priv = dev->priv; +unsigned flags =FIF_BCN_PRBRESP_PROMISC |FIF_PROMISC_IN_BSS ; + +if (priv->filter_type &P54_FILTER_TYPE_PROMISC ) + flags |=FIF_FCSFAIL ; - *total_flags &=FIF_BCN_PRBRESP_PROMISC ; + *total_flags &= flags;if (changed_flags &FIF_BCN_PRBRESP_PROMISC ) {if (*total_flags &FIF_BCN_PRBRESP_PROMISC ) -p54_set_filter (dev,0 , priv->mac_addr, -NULL ,2 ,0 ,0 ,0 ); +p54_set_filter (dev,P54_FILTER_TYPE_NONE ); +else +p54_set_filter (dev, priv->filter_type); + } + +if (changed_flags &FIF_PROMISC_IN_BSS ) { +if (*total_flags &FIF_PROMISC_IN_BSS ) + priv->filter_type |=P54_FILTER_TYPE_PROMISC ; +else + priv->filter_type &= ~P54_FILTER_TYPE_PROMISC ; + +p54_set_filter (dev, priv->filter_type); + } + +if (changed_flags &FIF_FCSFAIL ) { +if (*total_flags &FIF_FCSFAIL ) + priv->rx_filter |=P54_RX_FILTER_FCSFAIL ;else -p54_set_filter (dev,0 , priv->mac_addr, - priv->bssid,2 ,0 ,0 ,0 ); + priv->rx_filter &= ~P54_RX_FILTER_FCSFAIL ; } }
@@ -956,10 +1254,38 @@ static int p54_conf_tx(struct ieee80211_return 0 ; } +static void p54_stats_timer (unsigned long data) +{ +struct ieee80211_hw *dev = (struct ieee80211_hw *)data; +struct p54_common *priv = dev->priv; +struct p54_control_hdr *hdr; +struct p54_statistics *stat; + + hdr = (void *)priv->stats.cached_stats + priv->tx_hdr_len; + hdr->magic1 =cpu_to_le16 (0x8000 ); + hdr->len =cpu_to_le16 (sizeof (*stat)); + hdr->type =cpu_to_le16 (P54_CONTROL_TYPE_STAT_READBACK ); + hdr->retry1 = hdr->retry2 =0 ; +p54_assign_address (dev,NULL , hdr,sizeof (*hdr) +sizeof (*stat),NULL ); + + stat = (struct p54_statistics *)hdr->data; +memset (stat,0x0 ,sizeof (*stat)); + + priv->tx (dev, hdr,sizeof (*hdr) +sizeof (*stat),0 ); + +/* get stats every 5 seconds */ +mod_timer (&priv->stats.timer, jiffies +5 *HZ ); +} +static int p54_get_stats (struct ieee80211_hw *dev,struct ieee80211_low_level_stats *stats) { -/* TODO */ +struct p54_common *priv = dev->priv; + + stats->dot11RTSFailureCount = priv->stats.rx_rts_failed; + stats->dot11RTSSuccessCount = priv->stats.rx_rts_success; + stats->dot11FCSErrorCount = priv->stats.rx_errors; +return 0 ; }
@@ -967,11 +1293,19 @@ static int p54_get_tx_stats(struct ieee8 struct ieee80211_tx_queue_stats *stats) {struct p54_common *priv = dev->priv; -unsigned int i; -for (i =0 ; i < dev->queues; i++) -memcpy (&stats->data[i], &priv->tx_stats.data[i], -sizeof (stats->data[i])); +memcpy (&stats->data, &priv->tx_stats[4 ], +sizeof (stats->data[0 ]) * dev->queues); + +return 0 ; +} + + +int p54_set_tim (struct ieee80211_hw *dev,int aid,int set) +{ +/* AID 1 is reserved */ + +__p54_set_tim (dev, (u16 )aid +1 , set);return 0 ; }
@@ -986,6 +1320,8 @@ static const struct ieee80211_ops p54_op .config_interface = p54_config_interface, .configure_filter = p54_configure_filter, .conf_tx = p54_conf_tx, + .set_tim = p54_set_tim, + .beacon_update = p54_beacon_update, .get_stats = p54_get_stats, .get_tx_stats = p54_get_tx_stats };
@@ -1003,25 +1339,41 @@ struct ieee80211_hw *p54_init_common(siz priv->mode =IEEE80211_IF_TYPE_INVALID ;skb_queue_head_init (&priv->tx_queue); dev->wiphy->bands[IEEE80211_BAND_2GHZ ] = &band_2GHz; - dev->flags =IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |/* not sure */ -IEEE80211_HW_RX_INCLUDES_FCS ; - dev->channel_change_time =1000 ;/* TODO: find actual value */ - dev->max_rssi =127 ; - - priv->tx_stats.data[0 ].limit =5 ; + dev->flags =IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | +IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | +IEEE80211_HW_RX_INCLUDES_FCS ; + + dev->channel_change_time =5000 ; + priv->stats.noise_floor =-93 ; + dev->max_signal =64 ; + dev->max_rssi =-36 ; + dev->max_noise =-36 ; + + priv->tx_stats[0 ].limit =1 ;/* beacon queue */ + priv->tx_stats[1 ].limit =1 ;/* broadcasts / probes (passive scan)*/ + priv->tx_stats[2 ].limit =1 ;/* management frame queue */ + priv->tx_stats[3 ].limit =1 ;/* used to be the data queue */ + priv->tx_stats[4 ].limit =5 ;/* data queue */ + priv->filter_type =P54_FILTER_TYPE_NONE ; + priv->rx_filter =P54_RX_FILTER_NOTHING ; dev->queues =1 ; dev->extra_tx_headroom =sizeof (struct p54_control_hdr ) +4 +sizeof (struct p54_tx_control_allocdata ); priv->cached_vdcf =kzalloc (sizeof (struct p54_tx_control_vdcf ) + - priv->tx_hdr_len +sizeof (struct p54_control_hdr ),GFP_KERNEL ); - -if (!priv->cached_vdcf) { + priv->tx_hdr_len +sizeof (struct p54_control_hdr ),GFP_KERNEL ); + priv->stats.cached_stats =kzalloc (sizeof (struct p54_statistics ) + + priv->tx_hdr_len +sizeof (struct p54_control_hdr ),GFP_KERNEL ); + +if (!priv->cached_vdcf || !priv->stats.cached_stats) { +kfree (priv->cached_vdcf); +kfree (priv->stats.cached_stats);ieee80211_free_hw (dev);return NULL ; } +setup_timer (&priv->stats.timer, p54_stats_timer, (unsigned long )dev);p54_init_vdcf (dev);return dev;
@@ -1035,6 +1387,7 @@ void p54_free_common(struct ieee80211_hwkfree (priv->output_limit);kfree (priv->curve_data);kfree (priv->cached_vdcf); +kfree (priv->stats.cached_stats); }EXPORT_SYMBOL_GPL (p54_free_common);
drivers/net/wireless/p54/p54common.h +81 -26
166 lines not on this page · raw message
drivers/net/wireless/p54/p54.h +37 -6
86 lines not on this page · raw message
drivers/net/wireless/p54/p54pci.c +193 -107
491 lines not on this page · raw message
drivers/net/wireless/p54/p54pci.h +14 -9
@@ -1,5 +1,5 @@ -#ifndef PRISM54PCI_H -#define PRISM54PCI_H +#ifndef P54PCI_H +#define P54PCI_H /* * Defines for PCI based mac80211 Prism54 driver
@@ -68,7 +68,7 @@ struct p54p_csr { } __attribute__ ((packed));/* usb backend only needs the register defines above */ -#ifndef PRISM54USB_H +#ifndef P54USB_H struct p54p_desc { __le32 host_addr; __le32 device_addr;
@@ -92,15 +92,20 @@ struct p54p_priv {struct p54_common common;struct pci_dev *pdev;struct p54p_csr __iomem *map; +struct tasklet_struct rx_tasklet; -spinlock_t lock; +spinlock_t tx_lock; +spinlock_t rx_lock;struct p54p_ring_control *ring_control;dma_addr_t ring_control_dma; -u32 rx_idx, tx_idx; -struct sk_buff *rx_buf[8 ]; -void *tx_buf[32 ]; +u32 rx_idx_data, tx_idx_data; +u32 rx_idx_mgmt, tx_idx_mgmt; +struct sk_buff *rx_buf_data[8 ]; +struct sk_buff *rx_buf_mgmt[4 ]; +void *tx_buf_data[32 ]; +void *tx_buf_mgmt[4 ];struct completion boot_comp; }; -#endif /* PRISM54USB_H */ -#endif /* PRISM54PCI_H */ +#endif /* P54USB_H */ +#endif /* P54PCI_H */
drivers/net/wireless/p54/p54usb.c +17 -17
@@ -27,7 +27,7 @@MODULE_AUTHOR ("Michael Wu <[email protected]>" );MODULE_DESCRIPTION ("Prism54 USB wireless driver" );MODULE_LICENSE ("GPL" ); -MODULE_ALIAS ("prism54usb" ); +MODULE_ALIAS ("p54usb" );static struct usb_device_id p54u_table[]__devinitdata = {/* Version 1 devices (pci chip + net2280) */
@@ -311,7 +311,7 @@ static int p54u_read_eeprom(struct ieee8 buf =kmalloc (0x2020 ,GFP_KERNEL );if (!buf) { -printk (KERN_ERR "prism54usb: cannot allocate memory for " +printk (KERN_ERR "p54usb: cannot allocate memory for " "eeprom readback!\n" );return -ENOMEM ; }
@@ -320,7 +320,7 @@ static int p54u_read_eeprom(struct ieee8 *((u32 *) buf) = priv->common.rx_start; err =p54u_bulk_msg (priv,P54U_PIPE_DATA , buf,sizeof (u32));if (err) { -printk (KERN_ERR "prism54usb: addr send failed\n" ); +printk (KERN_ERR "p54usb: addr send failed\n" ); goto fail; } }else {
@@ -330,7 +330,7 @@ static int p54u_read_eeprom(struct ieee8 reg->val =cpu_to_le32 (ISL38XX_DEV_INT_DATA ); err =p54u_bulk_msg (priv,P54U_PIPE_DEV , buf,sizeof (*reg));if (err) { -printk (KERN_ERR "prism54usb: dev_int send failed\n" ); +printk (KERN_ERR "p54usb: dev_int send failed\n" ); goto fail; } }
@@ -348,7 +348,7 @@ static int p54u_read_eeprom(struct ieee8 err =p54u_bulk_msg (priv,P54U_PIPE_DATA , buf,EEPROM_READBACK_LEN + priv->common.tx_hdr_len);if (err) { -printk (KERN_ERR "prism54usb: eeprom req send failed\n" ); +printk (KERN_ERR "p54usb: eeprom req send failed\n" ); goto fail; }
@@ -358,7 +358,7 @@ static int p54u_read_eeprom(struct ieee8if (!err && alen > offset) {p54_parse_eeprom (dev, (u8 *)buf + offset, alen - offset); }else { -printk (KERN_ERR "prism54usb: eeprom read failed!\n" ); +printk (KERN_ERR "p54usb: eeprom read failed!\n" ); err = -EINVAL ; goto fail; }
@@ -446,7 +446,7 @@ static int p54u_upload_firmware_3887(str err =p54u_bulk_msg (priv,P54U_PIPE_DATA , buf, block_size);if (err) { -printk (KERN_ERR "prism54usb: firmware upload failed!\n" ); +printk (KERN_ERR "p54usb: firmware upload failed!\n" ); goto err_upload_failed; }
@@ -457,7 +457,7 @@ static int p54u_upload_firmware_3887(str *((__le32 *)buf) =cpu_to_le32 (~crc32_le (~0 , fw_entry->data, fw_entry->size)); err =p54u_bulk_msg (priv,P54U_PIPE_DATA , buf,sizeof (u32));if (err) { -printk (KERN_ERR "prism54usb: firmware upload failed!\n" ); +printk (KERN_ERR "p54usb: firmware upload failed!\n" ); goto err_upload_failed; }
@@ -468,13 +468,13 @@ static int p54u_upload_firmware_3887(strbreak ;if (alen >5 && !memcmp (buf,"ERROR" ,5 )) { -printk (KERN_INFO "prism54usb: firmware upload failed!\n" ); +printk (KERN_INFO "p54usb: firmware upload failed!\n" ); err = -EINVAL ;break ; }if (time_after (jiffies, timeout)) { -printk (KERN_ERR "prism54usb: firmware boot timed out!\n" ); +printk (KERN_ERR "p54usb: firmware boot timed out!\n" ); err = -ETIMEDOUT ;break ; }
@@ -486,7 +486,7 @@ static int p54u_upload_firmware_3887(str buf[1 ] ='\r' ; err =p54u_bulk_msg (priv,P54U_PIPE_DATA , buf,2 );if (err) { -printk (KERN_ERR "prism54usb: firmware boot failed!\n" ); +printk (KERN_ERR "p54usb: firmware boot failed!\n" ); goto err_upload_failed; }
@@ -648,7 +648,7 @@ static int p54u_upload_firmware_net2280( err =p54u_bulk_msg (priv,P54U_PIPE_DATA , buf, block_len);if (err) { -printk (KERN_ERR "prism54usb: firmware block upload " +printk (KERN_ERR "p54usb: firmware block upload " "failed\n" ); goto fail; }
@@ -682,7 +682,7 @@ static int p54u_upload_firmware_net2280( 0x002C | (unsigned long)&devreg->direct_mem_win);if (!(reg &cpu_to_le32 (ISL38XX_DMA_STATUS_DONE )) || !(reg &cpu_to_le32 (ISL38XX_DMA_STATUS_READY ))) { -printk (KERN_ERR "prism54usb: firmware DMA transfer " +printk (KERN_ERR "p54usb: firmware DMA transfer " "failed\n" ); goto fail; }
@@ -790,7 +790,7 @@ static int __devinit p54u_probe(struct u dev =p54_init_common (sizeof (*priv));if (!dev) { -printk (KERN_ERR "prism54usb: ieee80211 alloc failed\n" ); +printk (KERN_ERR "p54usb: ieee80211 alloc failed\n" );return -ENOMEM ; }
@@ -846,7 +846,7 @@ static int __devinit p54u_probe(struct uif (!is_valid_ether_addr (dev->wiphy->perm_addr)) {u8 perm_addr[ETH_ALEN ]; -printk (KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n" ); +printk (KERN_WARNING "p54usb: Invalid hwaddr! Using randomly generated MAC addr\n" );random_ether_addr (perm_addr);SET_IEEE80211_PERM_ADDR (dev, perm_addr); }
@@ -855,7 +855,7 @@ static int __devinit p54u_probe(struct u err =ieee80211_register_hw (dev);if (err) { -printk (KERN_ERR "prism54usb: Cannot register netdevice\n" ); +printk (KERN_ERR "p54usb: Cannot register netdevice\n" ); goto err_free_dev; }
@@ -890,7 +890,7 @@ static void __devexit p54u_disconnect(st }static struct usb_driver p54u_driver = { - .name ="prism54usb" , + .name ="p54usb" , .id_table = p54u_table, .probe = p54u_probe, .disconnect = p54u_disconnect,
drivers/net/wireless/p54/p54usb.h +3 -3
@@ -1,5 +1,5 @@ -#ifndef PRISM54USB_H -#define PRISM54USB_H +#ifndef P54USB_H +#define P54USB_H /* * Defines for USB based mac80211 Prism54 driver
@@ -130,4 +130,4 @@ struct p54u_priv { struct sk_buff_head rx_queue; }; -#endif /* PRISM54USB_H */ +#endif /* P54USB_H */