diff options
Diffstat (limited to 'drivers/net/wireless/adm8211.c')
-rw-r--r-- | drivers/net/wireless/adm8211.c | 144 |
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 | ||
284 | static 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 | |||
327 | static int adm8211_get_tx_stats(struct ieee80211_hw *dev, | 284 | static 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 | ||
1266 | static int adm8211_hw_reset(struct ieee80211_hw *dev) | 1216 | static 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 | ||
1337 | static void adm8211_set_bssid(struct ieee80211_hw *dev, u8 *bssid) | 1287 | static 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 | ||
1348 | static 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 | |||
1398 | static int adm8211_add_interface(struct ieee80211_hw *dev, | 1406 | static 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 | ||
1427 | static int adm8211_init_rings(struct ieee80211_hw *dev) | 1440 | static 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 | ||
1508 | static int adm8211_open(struct ieee80211_hw *dev) | 1521 | static 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 | ||
1553 | static int adm8211_stop(struct ieee80211_hw *dev) | 1566 | static 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 | ||
1568 | static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int len, | 1580 | static 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 | ||
1766 | static const struct ieee80211_ops adm8211_ops = { | 1778 | static 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 | ||