aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/adm8211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/adm8211.c')
-rw-r--r--drivers/net/wireless/adm8211.c144
1 files changed, 78 insertions, 66 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index ac2ea237019d..49a6b9eda4ea 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -281,49 +281,6 @@ static int adm8211_get_stats(struct ieee80211_hw *dev,
281 return 0; 281 return 0;
282} 282}
283 283
284static void adm8211_set_rx_mode(struct ieee80211_hw *dev,
285 unsigned short flags, int mc_count)
286{
287 struct adm8211_priv *priv = dev->priv;
288 unsigned int bit_nr;
289 u32 mc_filter[2];
290 struct dev_mc_list *mclist;
291 void *tmp;
292
293 if (flags & IFF_PROMISC) {
294 priv->nar |= ADM8211_NAR_PR;
295 priv->nar &= ~ADM8211_NAR_MM;
296 mc_filter[1] = mc_filter[0] = ~0;
297 } else if ((flags & IFF_ALLMULTI) || (mc_count > -1)) {
298 priv->nar &= ~ADM8211_NAR_PR;
299 priv->nar |= ADM8211_NAR_MM;
300 mc_filter[1] = mc_filter[0] = ~0;
301 } else {
302 priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR);
303 mc_filter[1] = mc_filter[0] = 0;
304 mclist = NULL;
305 while ((mclist = ieee80211_get_mc_list_item(dev, mclist, &tmp))) {
306 bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
307
308 bit_nr &= 0x3F;
309 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
310 }
311 }
312
313 ADM8211_IDLE_RX();
314
315 ADM8211_CSR_WRITE(MAR0, mc_filter[0]);
316 ADM8211_CSR_WRITE(MAR1, mc_filter[1]);
317 ADM8211_CSR_READ(NAR);
318
319 if (flags & IFF_PROMISC)
320 dev->flags |= IEEE80211_HW_RX_INCLUDES_FCS;
321 else
322 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
323
324 ADM8211_RESTORE();
325}
326
327static int adm8211_get_tx_stats(struct ieee80211_hw *dev, 284static int adm8211_get_tx_stats(struct ieee80211_hw *dev,
328 struct ieee80211_tx_queue_stats *stats) 285 struct ieee80211_tx_queue_stats *stats)
329{ 286{
@@ -1254,13 +1211,6 @@ static void adm8211_hw_init(struct ieee80211_hw *dev)
1254 1211
1255 /* Clear the missed-packet counter. */ 1212 /* Clear the missed-packet counter. */
1256 ADM8211_CSR_READ(LPC); 1213 ADM8211_CSR_READ(LPC);
1257
1258 if (!priv->mac_addr)
1259 return;
1260
1261 /* set mac address */
1262 ADM8211_CSR_WRITE(PAR0, *(u32 *)priv->mac_addr);
1263 ADM8211_CSR_WRITE(PAR1, *(u16 *)&priv->mac_addr[4]);
1264} 1214}
1265 1215
1266static int adm8211_hw_reset(struct ieee80211_hw *dev) 1216static int adm8211_hw_reset(struct ieee80211_hw *dev)
@@ -1334,7 +1284,7 @@ static void adm8211_set_interval(struct ieee80211_hw *dev,
1334 ADM8211_CSR_WRITE(BPLI, reg); 1284 ADM8211_CSR_WRITE(BPLI, reg);
1335} 1285}
1336 1286
1337static void adm8211_set_bssid(struct ieee80211_hw *dev, u8 *bssid) 1287static void adm8211_set_bssid(struct ieee80211_hw *dev, const u8 *bssid)
1338{ 1288{
1339 struct adm8211_priv *priv = dev->priv; 1289 struct adm8211_priv *priv = dev->priv;
1340 u32 reg; 1290 u32 reg;
@@ -1395,24 +1345,87 @@ static int adm8211_config_interface(struct ieee80211_hw *dev, int if_id,
1395 return 0; 1345 return 0;
1396} 1346}
1397 1347
1348static void adm8211_configure_filter(struct ieee80211_hw *dev,
1349 unsigned int changed_flags,
1350 unsigned int *total_flags,
1351 int mc_count, struct dev_mc_list *mclist)
1352{
1353 static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
1354 struct adm8211_priv *priv = dev->priv;
1355 unsigned int bit_nr, new_flags;
1356 u32 mc_filter[2];
1357 int i;
1358
1359 new_flags = 0;
1360
1361 if (*total_flags & FIF_PROMISC_IN_BSS) {
1362 new_flags |= FIF_PROMISC_IN_BSS;
1363 priv->nar |= ADM8211_NAR_PR;
1364 priv->nar &= ~ADM8211_NAR_MM;
1365 mc_filter[1] = mc_filter[0] = ~0;
1366 } else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) {
1367 new_flags |= FIF_ALLMULTI;
1368 priv->nar &= ~ADM8211_NAR_PR;
1369 priv->nar |= ADM8211_NAR_MM;
1370 mc_filter[1] = mc_filter[0] = ~0;
1371 } else {
1372 priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR);
1373 mc_filter[1] = mc_filter[0] = 0;
1374 for (i = 0; i < mc_count; i++) {
1375 if (!mclist)
1376 break;
1377 bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
1378
1379 bit_nr &= 0x3F;
1380 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
1381 mclist = mclist->next;
1382 }
1383 }
1384
1385 ADM8211_IDLE_RX();
1386
1387 ADM8211_CSR_WRITE(MAR0, mc_filter[0]);
1388 ADM8211_CSR_WRITE(MAR1, mc_filter[1]);
1389 ADM8211_CSR_READ(NAR);
1390
1391 if (priv->nar & ADM8211_NAR_PR)
1392 dev->flags |= IEEE80211_HW_RX_INCLUDES_FCS;
1393 else
1394 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
1395
1396 if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
1397 adm8211_set_bssid(dev, bcast);
1398 else
1399 adm8211_set_bssid(dev, priv->bssid);
1400
1401 ADM8211_RESTORE();
1402
1403 *total_flags = new_flags;
1404}
1405
1398static int adm8211_add_interface(struct ieee80211_hw *dev, 1406static int adm8211_add_interface(struct ieee80211_hw *dev,
1399 struct ieee80211_if_init_conf *conf) 1407 struct ieee80211_if_init_conf *conf)
1400{ 1408{
1401 struct adm8211_priv *priv = dev->priv; 1409 struct adm8211_priv *priv = dev->priv;
1402 /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */ 1410 if (priv->mode != IEEE80211_IF_TYPE_MNTR)
1403 if (priv->mode != IEEE80211_IF_TYPE_MGMT) 1411 return -EOPNOTSUPP;
1404 return -1;
1405 1412
1406 switch (conf->type) { 1413 switch (conf->type) {
1407 case IEEE80211_IF_TYPE_STA: 1414 case IEEE80211_IF_TYPE_STA:
1408 case IEEE80211_IF_TYPE_MNTR:
1409 priv->mode = conf->type; 1415 priv->mode = conf->type;
1410 break; 1416 break;
1411 default: 1417 default:
1412 return -EOPNOTSUPP; 1418 return -EOPNOTSUPP;
1413 } 1419 }
1414 1420
1415 priv->mac_addr = conf->mac_addr; 1421 ADM8211_IDLE();
1422
1423 ADM8211_CSR_WRITE(PAR0, *(u32 *)conf->mac_addr);
1424 ADM8211_CSR_WRITE(PAR1, *(u16 *)(conf->mac_addr + 4));
1425
1426 adm8211_update_mode(dev);
1427
1428 ADM8211_RESTORE();
1416 1429
1417 return 0; 1430 return 0;
1418} 1431}
@@ -1421,7 +1434,7 @@ static void adm8211_remove_interface(struct ieee80211_hw *dev,
1421 struct ieee80211_if_init_conf *conf) 1434 struct ieee80211_if_init_conf *conf)
1422{ 1435{
1423 struct adm8211_priv *priv = dev->priv; 1436 struct adm8211_priv *priv = dev->priv;
1424 priv->mode = IEEE80211_IF_TYPE_MGMT; 1437 priv->mode = IEEE80211_IF_TYPE_MNTR;
1425} 1438}
1426 1439
1427static int adm8211_init_rings(struct ieee80211_hw *dev) 1440static int adm8211_init_rings(struct ieee80211_hw *dev)
@@ -1505,7 +1518,7 @@ static void adm8211_free_rings(struct ieee80211_hw *dev)
1505 } 1518 }
1506} 1519}
1507 1520
1508static int adm8211_open(struct ieee80211_hw *dev) 1521static int adm8211_start(struct ieee80211_hw *dev)
1509{ 1522{
1510 struct adm8211_priv *priv = dev->priv; 1523 struct adm8211_priv *priv = dev->priv;
1511 int retval; 1524 int retval;
@@ -1550,7 +1563,7 @@ fail:
1550 return retval; 1563 return retval;
1551} 1564}
1552 1565
1553static int adm8211_stop(struct ieee80211_hw *dev) 1566static void adm8211_stop(struct ieee80211_hw *dev)
1554{ 1567{
1555 struct adm8211_priv *priv = dev->priv; 1568 struct adm8211_priv *priv = dev->priv;
1556 1569
@@ -1562,7 +1575,6 @@ static int adm8211_stop(struct ieee80211_hw *dev)
1562 free_irq(priv->pdev->irq, dev); 1575 free_irq(priv->pdev->irq, dev);
1563 1576
1564 adm8211_free_rings(dev); 1577 adm8211_free_rings(dev);
1565 return 0;
1566} 1578}
1567 1579
1568static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int len, 1580static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int len,
@@ -1765,13 +1777,13 @@ static int adm8211_alloc_rings(struct ieee80211_hw *dev)
1765 1777
1766static const struct ieee80211_ops adm8211_ops = { 1778static const struct ieee80211_ops adm8211_ops = {
1767 .tx = adm8211_tx, 1779 .tx = adm8211_tx,
1768 .open = adm8211_open, 1780 .start = adm8211_start,
1769 .stop = adm8211_stop, 1781 .stop = adm8211_stop,
1770 .add_interface = adm8211_add_interface, 1782 .add_interface = adm8211_add_interface,
1771 .remove_interface = adm8211_remove_interface, 1783 .remove_interface = adm8211_remove_interface,
1772 .config = adm8211_config, 1784 .config = adm8211_config,
1773 .config_interface = adm8211_config_interface, 1785 .config_interface = adm8211_config_interface,
1774 .set_multicast_list = adm8211_set_rx_mode, 1786 .configure_filter = adm8211_configure_filter,
1775 .get_stats = adm8211_get_stats, 1787 .get_stats = adm8211_get_stats,
1776 .get_tx_stats = adm8211_get_tx_stats, 1788 .get_tx_stats = adm8211_get_tx_stats,
1777 .get_tsf = adm8211_get_tsft 1789 .get_tsf = adm8211_get_tsft
@@ -1905,7 +1917,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
1905 priv->tx_power = 0x40; 1917 priv->tx_power = 0x40;
1906 priv->lpf_cutoff = 0xFF; 1918 priv->lpf_cutoff = 0xFF;
1907 priv->lnags_threshold = 0xFF; 1919 priv->lnags_threshold = 0xFF;
1908 priv->mode = IEEE80211_IF_TYPE_MGMT; 1920 priv->mode = IEEE80211_IF_TYPE_MNTR;
1909 1921
1910 /* Power-on issue. EEPROM won't read correctly without */ 1922 /* Power-on issue. EEPROM won't read correctly without */
1911 if (priv->revid >= ADM8211_REV_BA) { 1923 if (priv->revid >= ADM8211_REV_BA) {
@@ -2000,7 +2012,7 @@ static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state)
2000 struct ieee80211_hw *dev = pci_get_drvdata(pdev); 2012 struct ieee80211_hw *dev = pci_get_drvdata(pdev);
2001 struct adm8211_priv *priv = dev->priv; 2013 struct adm8211_priv *priv = dev->priv;
2002 2014
2003 if (priv->mode != IEEE80211_IF_TYPE_MGMT) { 2015 if (priv->mode != IEEE80211_IF_TYPE_MNTR) {
2004 ieee80211_stop_queues(dev); 2016 ieee80211_stop_queues(dev);
2005 adm8211_stop(dev); 2017 adm8211_stop(dev);
2006 } 2018 }
@@ -2018,8 +2030,8 @@ static int adm8211_resume(struct pci_dev *pdev)
2018 pci_set_power_state(pdev, PCI_D0); 2030 pci_set_power_state(pdev, PCI_D0);
2019 pci_restore_state(pdev); 2031 pci_restore_state(pdev);
2020 2032
2021 if (priv->mode != IEEE80211_IF_TYPE_MGMT) { 2033 if (priv->mode != IEEE80211_IF_TYPE_MNTR) {
2022 adm8211_open(dev); 2034 adm8211_start(dev);
2023 ieee80211_start_queues(dev); 2035 ieee80211_start_queues(dev);
2024 } 2036 }
2025 2037