aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtl8187_dev.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-09-17 01:29:23 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:52:57 -0400
commit4150c57212ad134765dd78c654a4b9906252b66d (patch)
treec37ab7a3f75532a623ed00339782d769514422d2 /drivers/net/wireless/rtl8187_dev.c
parent070ac3a2651e3c1c4d277c5f1981517427c386a7 (diff)
[PATCH] mac80211: revamp interface and filter configuration
Drivers are currently supposed to keep track of monitor interfaces if they allow so-called "hard" monitor, and they are also supposed to keep track of multicast etc. This patch changes that, replaces the set_multicast_list() callback with a new configure_filter() callback that takes filter flags (FIF_*) instead of interface flags (IFF_*). For a driver, this means it should open the filter as much as necessary to get all frames requested by the filter flags. Accordingly, the filter flags are named "positively", e.g. FIF_ALLMULTI. Multicast filtering is a bit special in that drivers that have no multicast address filters need to allow multicast frames through when either the FIF_ALLMULTI flag is set or when the mc_count value is positive. At the same time, drivers are no longer notified about monitor interfaces at all, this means they now need to implement the start() and stop() callbacks and the new change_filter_flags() callback. Also, the start()/stop() ordering changed, start() is now called *before* any add_interface() as it really should be, and stop() after any remove_interface(). The patch also changes the behaviour of setting the bssid to multicast for scanning when IEEE80211_HW_NO_PROBE_FILTERING is set; the IEEE80211_HW_NO_PROBE_FILTERING flag is removed and the filter flag FIF_BCN_PRBRESP_PROMISC introduced. This is a lot more efficient for hardware like b43 that supports it and other hardware can still set the BSSID to all-ones. Driver modifications by Johannes Berg (b43 & iwlwifi), Michael Wu (rtl8187, adm8211, and p54), Larry Finger (b43legacy), and Ivo van Doorn (rt2x00). Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtl8187_dev.c')
-rw-r--r--drivers/net/wireless/rtl8187_dev.c129
1 files changed, 110 insertions, 19 deletions
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index bf9f0cc5a64..b0a92f543da 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -41,6 +41,57 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
41 41
42MODULE_DEVICE_TABLE(usb, rtl8187_table); 42MODULE_DEVICE_TABLE(usb, rtl8187_table);
43 43
44static void rtl8187_iowrite_async_cb(struct urb *urb)
45{
46 kfree(urb->context);
47 usb_free_urb(urb);
48}
49
50static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
51 void *data, u16 len)
52{
53 struct usb_ctrlrequest *dr;
54 struct urb *urb;
55 struct rtl8187_async_write_data {
56 u8 data[4];
57 struct usb_ctrlrequest dr;
58 } *buf;
59
60 buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
61 if (!buf)
62 return;
63
64 urb = usb_alloc_urb(0, GFP_ATOMIC);
65 if (!urb) {
66 kfree(buf);
67 return;
68 }
69
70 dr = &buf->dr;
71
72 dr->bRequestType = RTL8187_REQT_WRITE;
73 dr->bRequest = RTL8187_REQ_SET_REG;
74 dr->wValue = addr;
75 dr->wIndex = 0;
76 dr->wLength = cpu_to_le16(len);
77
78 memcpy(buf, data, len);
79
80 usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0),
81 (unsigned char *)dr, buf, len,
82 rtl8187_iowrite_async_cb, buf);
83 usb_submit_urb(urb, GFP_ATOMIC);
84}
85
86static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv,
87 __le32 *addr, u32 val)
88{
89 __le32 buf = cpu_to_le32(val);
90
91 rtl8187_iowrite_async(priv, cpu_to_le16((unsigned long)addr),
92 &buf, sizeof(buf));
93}
94
44void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) 95void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
45{ 96{
46 struct rtl8187_priv *priv = dev->priv; 97 struct rtl8187_priv *priv = dev->priv;
@@ -125,6 +176,7 @@ static void rtl8187_rx_cb(struct urb *urb)
125 struct rtl8187_rx_hdr *hdr; 176 struct rtl8187_rx_hdr *hdr;
126 struct ieee80211_rx_status rx_status = { 0 }; 177 struct ieee80211_rx_status rx_status = { 0 };
127 int rate, signal; 178 int rate, signal;
179 u32 flags;
128 180
129 spin_lock(&priv->rx_queue.lock); 181 spin_lock(&priv->rx_queue.lock);
130 if (skb->next) 182 if (skb->next)
@@ -143,10 +195,11 @@ static void rtl8187_rx_cb(struct urb *urb)
143 195
144 skb_put(skb, urb->actual_length); 196 skb_put(skb, urb->actual_length);
145 hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr)); 197 hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
146 skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF); 198 flags = le32_to_cpu(hdr->flags);
199 skb_trim(skb, flags & 0x0FFF);
147 200
148 signal = hdr->agc >> 1; 201 signal = hdr->agc >> 1;
149 rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF; 202 rate = (flags >> 20) & 0xF;
150 if (rate > 3) { /* OFDM rate */ 203 if (rate > 3) { /* OFDM rate */
151 if (signal > 90) 204 if (signal > 90)
152 signal = 90; 205 signal = 90;
@@ -169,6 +222,8 @@ static void rtl8187_rx_cb(struct urb *urb)
169 rx_status.channel = dev->conf.channel; 222 rx_status.channel = dev->conf.channel;
170 rx_status.phymode = dev->conf.phymode; 223 rx_status.phymode = dev->conf.phymode;
171 rx_status.mactime = le64_to_cpu(hdr->mac_time); 224 rx_status.mactime = le64_to_cpu(hdr->mac_time);
225 if (flags & (1 << 13))
226 rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
172 ieee80211_rx_irqsafe(dev, skb, &rx_status); 227 ieee80211_rx_irqsafe(dev, skb, &rx_status);
173 228
174 skb = dev_alloc_skb(RTL8187_MAX_RX); 229 skb = dev_alloc_skb(RTL8187_MAX_RX);
@@ -293,8 +348,6 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
293 rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); 348 rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
294 349
295 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); 350 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
296 for (i = 0; i < ETH_ALEN; i++)
297 rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
298 351
299 rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF); 352 rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
300 reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); 353 reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
@@ -365,7 +418,7 @@ static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
365 rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); 418 rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
366} 419}
367 420
368static int rtl8187_open(struct ieee80211_hw *dev) 421static int rtl8187_start(struct ieee80211_hw *dev)
369{ 422{
370 struct rtl8187_priv *priv = dev->priv; 423 struct rtl8187_priv *priv = dev->priv;
371 u32 reg; 424 u32 reg;
@@ -383,16 +436,13 @@ static int rtl8187_open(struct ieee80211_hw *dev)
383 RTL818X_RX_CONF_RX_AUTORESETPHY | 436 RTL818X_RX_CONF_RX_AUTORESETPHY |
384 RTL818X_RX_CONF_BSSID | 437 RTL818X_RX_CONF_BSSID |
385 RTL818X_RX_CONF_MGMT | 438 RTL818X_RX_CONF_MGMT |
386 RTL818X_RX_CONF_CTRL |
387 RTL818X_RX_CONF_DATA | 439 RTL818X_RX_CONF_DATA |
388 (7 << 13 /* RX FIFO threshold NONE */) | 440 (7 << 13 /* RX FIFO threshold NONE */) |
389 (7 << 10 /* MAX RX DMA */) | 441 (7 << 10 /* MAX RX DMA */) |
390 RTL818X_RX_CONF_BROADCAST | 442 RTL818X_RX_CONF_BROADCAST |
391 RTL818X_RX_CONF_MULTICAST |
392 RTL818X_RX_CONF_NICMAC; 443 RTL818X_RX_CONF_NICMAC;
393 if (priv->mode == IEEE80211_IF_TYPE_MNTR)
394 reg |= RTL818X_RX_CONF_MONITOR;
395 444
445 priv->rx_conf = reg;
396 rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); 446 rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
397 447
398 reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); 448 reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
@@ -419,7 +469,7 @@ static int rtl8187_open(struct ieee80211_hw *dev)
419 return 0; 469 return 0;
420} 470}
421 471
422static int rtl8187_stop(struct ieee80211_hw *dev) 472static void rtl8187_stop(struct ieee80211_hw *dev)
423{ 473{
424 struct rtl8187_priv *priv = dev->priv; 474 struct rtl8187_priv *priv = dev->priv;
425 struct rtl8187_rx_info *info; 475 struct rtl8187_rx_info *info;
@@ -445,28 +495,31 @@ static int rtl8187_stop(struct ieee80211_hw *dev)
445 usb_kill_urb(info->urb); 495 usb_kill_urb(info->urb);
446 kfree_skb(skb); 496 kfree_skb(skb);
447 } 497 }
448 return 0; 498 return;
449} 499}
450 500
451static int rtl8187_add_interface(struct ieee80211_hw *dev, 501static int rtl8187_add_interface(struct ieee80211_hw *dev,
452 struct ieee80211_if_init_conf *conf) 502 struct ieee80211_if_init_conf *conf)
453{ 503{
454 struct rtl8187_priv *priv = dev->priv; 504 struct rtl8187_priv *priv = dev->priv;
505 int i;
455 506
456 /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */ 507 if (priv->mode != IEEE80211_IF_TYPE_MNTR)
457 if (priv->mode != IEEE80211_IF_TYPE_MGMT) 508 return -EOPNOTSUPP;
458 return -1;
459 509
460 switch (conf->type) { 510 switch (conf->type) {
461 case IEEE80211_IF_TYPE_STA: 511 case IEEE80211_IF_TYPE_STA:
462 case IEEE80211_IF_TYPE_MNTR:
463 priv->mode = conf->type; 512 priv->mode = conf->type;
464 break; 513 break;
465 default: 514 default:
466 return -EOPNOTSUPP; 515 return -EOPNOTSUPP;
467 } 516 }
468 517
469 priv->hwaddr = conf->mac_addr ? conf->mac_addr : dev->wiphy->perm_addr; 518 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
519 for (i = 0; i < ETH_ALEN; i++)
520 rtl818x_iowrite8(priv, &priv->map->MAC[i],
521 ((u8 *)conf->mac_addr)[i]);
522 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
470 523
471 return 0; 524 return 0;
472} 525}
@@ -475,7 +528,7 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
475 struct ieee80211_if_init_conf *conf) 528 struct ieee80211_if_init_conf *conf)
476{ 529{
477 struct rtl8187_priv *priv = dev->priv; 530 struct rtl8187_priv *priv = dev->priv;
478 priv->mode = IEEE80211_IF_TYPE_MGMT; 531 priv->mode = IEEE80211_IF_TYPE_MNTR;
479} 532}
480 533
481static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) 534static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
@@ -523,14 +576,52 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
523 return 0; 576 return 0;
524} 577}
525 578
579static void rtl8187_configure_filter(struct ieee80211_hw *dev,
580 unsigned int changed_flags,
581 unsigned int *total_flags,
582 int mc_count, struct dev_addr_list *mc_list)
583{
584 struct rtl8187_priv *priv = dev->priv;
585
586 *total_flags = 0;
587
588 if (changed_flags & FIF_PROMISC_IN_BSS)
589 priv->rx_conf ^= RTL818X_RX_CONF_NICMAC;
590 if (changed_flags & FIF_ALLMULTI)
591 priv->rx_conf ^= RTL818X_RX_CONF_MULTICAST;
592 if (changed_flags & FIF_FCSFAIL)
593 priv->rx_conf ^= RTL818X_RX_CONF_FCS;
594 if (changed_flags & FIF_CONTROL)
595 priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
596 if (changed_flags & FIF_OTHER_BSS)
597 priv->rx_conf ^= RTL818X_RX_CONF_MONITOR;
598
599 if (mc_count > 0)
600 priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
601
602 if (priv->rx_conf & RTL818X_RX_CONF_NICMAC)
603 *total_flags |= FIF_PROMISC_IN_BSS;
604 if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST)
605 *total_flags |= FIF_ALLMULTI;
606 if (priv->rx_conf & RTL818X_RX_CONF_FCS)
607 *total_flags |= FIF_FCSFAIL;
608 if (priv->rx_conf & RTL818X_RX_CONF_CTRL)
609 *total_flags |= FIF_CONTROL;
610 if (priv->rx_conf & RTL818X_RX_CONF_MONITOR)
611 *total_flags |= FIF_OTHER_BSS;
612
613 rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf);
614}
615
526static const struct ieee80211_ops rtl8187_ops = { 616static const struct ieee80211_ops rtl8187_ops = {
527 .tx = rtl8187_tx, 617 .tx = rtl8187_tx,
528 .open = rtl8187_open, 618 .start = rtl8187_start,
529 .stop = rtl8187_stop, 619 .stop = rtl8187_stop,
530 .add_interface = rtl8187_add_interface, 620 .add_interface = rtl8187_add_interface,
531 .remove_interface = rtl8187_remove_interface, 621 .remove_interface = rtl8187_remove_interface,
532 .config = rtl8187_config, 622 .config = rtl8187_config,
533 .config_interface = rtl8187_config_interface, 623 .config_interface = rtl8187_config_interface,
624 .configure_filter = rtl8187_configure_filter,
534}; 625};
535 626
536static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) 627static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
@@ -604,7 +695,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
604 priv->modes[1].rates = priv->rates; 695 priv->modes[1].rates = priv->rates;
605 priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels); 696 priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
606 priv->modes[1].channels = priv->channels; 697 priv->modes[1].channels = priv->channels;
607 priv->mode = IEEE80211_IF_TYPE_MGMT; 698 priv->mode = IEEE80211_IF_TYPE_MNTR;
608 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 699 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
609 IEEE80211_HW_RX_INCLUDES_FCS; 700 IEEE80211_HW_RX_INCLUDES_FCS;
610 dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr); 701 dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);