diff options
Diffstat (limited to 'drivers/net/wireless/ipw2x00/ipw2200.c')
| -rw-r--r-- | drivers/net/wireless/ipw2x00/ipw2200.c | 153 |
1 files changed, 123 insertions, 30 deletions
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 9fe0e8078a88..c28984ae46ff 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
| @@ -109,6 +109,25 @@ static int antenna = CFG_SYS_ANTENNA_BOTH; | |||
| 109 | static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ | 109 | static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ |
| 110 | #endif | 110 | #endif |
| 111 | 111 | ||
| 112 | static struct ieee80211_rate ipw2200_rates[] = { | ||
| 113 | { .bitrate = 10 }, | ||
| 114 | { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
| 115 | { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
| 116 | { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
| 117 | { .bitrate = 60 }, | ||
| 118 | { .bitrate = 90 }, | ||
| 119 | { .bitrate = 120 }, | ||
| 120 | { .bitrate = 180 }, | ||
| 121 | { .bitrate = 240 }, | ||
| 122 | { .bitrate = 360 }, | ||
| 123 | { .bitrate = 480 }, | ||
| 124 | { .bitrate = 540 } | ||
| 125 | }; | ||
| 126 | |||
| 127 | #define ipw2200_a_rates (ipw2200_rates + 4) | ||
| 128 | #define ipw2200_num_a_rates 8 | ||
| 129 | #define ipw2200_bg_rates (ipw2200_rates + 0) | ||
| 130 | #define ipw2200_num_bg_rates 12 | ||
| 112 | 131 | ||
| 113 | #ifdef CONFIG_IPW2200_QOS | 132 | #ifdef CONFIG_IPW2200_QOS |
| 114 | static int qos_enable = 0; | 133 | static int qos_enable = 0; |
| @@ -1739,10 +1758,13 @@ static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO, | |||
| 1739 | 1758 | ||
| 1740 | static int rf_kill_active(struct ipw_priv *priv) | 1759 | static int rf_kill_active(struct ipw_priv *priv) |
| 1741 | { | 1760 | { |
| 1742 | if (0 == (ipw_read32(priv, 0x30) & 0x10000)) | 1761 | if (0 == (ipw_read32(priv, 0x30) & 0x10000)) { |
| 1743 | priv->status |= STATUS_RF_KILL_HW; | 1762 | priv->status |= STATUS_RF_KILL_HW; |
| 1744 | else | 1763 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true); |
| 1764 | } else { | ||
| 1745 | priv->status &= ~STATUS_RF_KILL_HW; | 1765 | priv->status &= ~STATUS_RF_KILL_HW; |
| 1766 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false); | ||
| 1767 | } | ||
| 1746 | 1768 | ||
| 1747 | return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0; | 1769 | return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0; |
| 1748 | } | 1770 | } |
| @@ -2025,6 +2047,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
| 2025 | if (inta & IPW_INTA_BIT_RF_KILL_DONE) { | 2047 | if (inta & IPW_INTA_BIT_RF_KILL_DONE) { |
| 2026 | IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); | 2048 | IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); |
| 2027 | priv->status |= STATUS_RF_KILL_HW; | 2049 | priv->status |= STATUS_RF_KILL_HW; |
| 2050 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true); | ||
| 2028 | wake_up_interruptible(&priv->wait_command_queue); | 2051 | wake_up_interruptible(&priv->wait_command_queue); |
| 2029 | priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); | 2052 | priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); |
| 2030 | cancel_delayed_work(&priv->request_scan); | 2053 | cancel_delayed_work(&priv->request_scan); |
| @@ -8660,24 +8683,6 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) | |||
| 8660 | * | 8683 | * |
| 8661 | */ | 8684 | */ |
| 8662 | 8685 | ||
| 8663 | static int ipw_wx_get_name(struct net_device *dev, | ||
| 8664 | struct iw_request_info *info, | ||
| 8665 | union iwreq_data *wrqu, char *extra) | ||
| 8666 | { | ||
| 8667 | struct ipw_priv *priv = libipw_priv(dev); | ||
| 8668 | mutex_lock(&priv->mutex); | ||
| 8669 | if (priv->status & STATUS_RF_KILL_MASK) | ||
| 8670 | strcpy(wrqu->name, "radio off"); | ||
| 8671 | else if (!(priv->status & STATUS_ASSOCIATED)) | ||
| 8672 | strcpy(wrqu->name, "unassociated"); | ||
| 8673 | else | ||
| 8674 | snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c", | ||
| 8675 | ipw_modes[priv->assoc_request.ieee_mode]); | ||
| 8676 | IPW_DEBUG_WX("Name: %s\n", wrqu->name); | ||
| 8677 | mutex_unlock(&priv->mutex); | ||
| 8678 | return 0; | ||
| 8679 | } | ||
| 8680 | |||
| 8681 | static int ipw_set_channel(struct ipw_priv *priv, u8 channel) | 8686 | static int ipw_set_channel(struct ipw_priv *priv, u8 channel) |
| 8682 | { | 8687 | { |
| 8683 | if (channel == 0) { | 8688 | if (channel == 0) { |
| @@ -9977,7 +9982,7 @@ static int ipw_wx_sw_reset(struct net_device *dev, | |||
| 9977 | /* Rebase the WE IOCTLs to zero for the handler array */ | 9982 | /* Rebase the WE IOCTLs to zero for the handler array */ |
| 9978 | #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] | 9983 | #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] |
| 9979 | static iw_handler ipw_wx_handlers[] = { | 9984 | static iw_handler ipw_wx_handlers[] = { |
| 9980 | IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name, | 9985 | IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname, |
| 9981 | IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, | 9986 | IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, |
| 9982 | IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, | 9987 | IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, |
| 9983 | IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, | 9988 | IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, |
| @@ -11422,16 +11427,100 @@ static void ipw_bg_down(struct work_struct *work) | |||
| 11422 | /* Called by register_netdev() */ | 11427 | /* Called by register_netdev() */ |
| 11423 | static int ipw_net_init(struct net_device *dev) | 11428 | static int ipw_net_init(struct net_device *dev) |
| 11424 | { | 11429 | { |
| 11430 | int i, rc = 0; | ||
| 11425 | struct ipw_priv *priv = libipw_priv(dev); | 11431 | struct ipw_priv *priv = libipw_priv(dev); |
| 11432 | const struct libipw_geo *geo = libipw_get_geo(priv->ieee); | ||
| 11433 | struct wireless_dev *wdev = &priv->ieee->wdev; | ||
| 11426 | mutex_lock(&priv->mutex); | 11434 | mutex_lock(&priv->mutex); |
| 11427 | 11435 | ||
| 11428 | if (ipw_up(priv)) { | 11436 | if (ipw_up(priv)) { |
| 11429 | mutex_unlock(&priv->mutex); | 11437 | rc = -EIO; |
| 11430 | return -EIO; | 11438 | goto out; |
| 11439 | } | ||
| 11440 | |||
| 11441 | memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); | ||
| 11442 | |||
| 11443 | /* fill-out priv->ieee->bg_band */ | ||
| 11444 | if (geo->bg_channels) { | ||
| 11445 | struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band; | ||
| 11446 | |||
| 11447 | bg_band->band = IEEE80211_BAND_2GHZ; | ||
| 11448 | bg_band->n_channels = geo->bg_channels; | ||
| 11449 | bg_band->channels = | ||
| 11450 | kzalloc(geo->bg_channels * | ||
| 11451 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
| 11452 | /* translate geo->bg to bg_band.channels */ | ||
| 11453 | for (i = 0; i < geo->bg_channels; i++) { | ||
| 11454 | bg_band->channels[i].band = IEEE80211_BAND_2GHZ; | ||
| 11455 | bg_band->channels[i].center_freq = geo->bg[i].freq; | ||
| 11456 | bg_band->channels[i].hw_value = geo->bg[i].channel; | ||
| 11457 | bg_band->channels[i].max_power = geo->bg[i].max_power; | ||
| 11458 | if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) | ||
| 11459 | bg_band->channels[i].flags |= | ||
| 11460 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
| 11461 | if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) | ||
| 11462 | bg_band->channels[i].flags |= | ||
| 11463 | IEEE80211_CHAN_NO_IBSS; | ||
| 11464 | if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) | ||
| 11465 | bg_band->channels[i].flags |= | ||
| 11466 | IEEE80211_CHAN_RADAR; | ||
| 11467 | /* No equivalent for LIBIPW_CH_80211H_RULES, | ||
| 11468 | LIBIPW_CH_UNIFORM_SPREADING, or | ||
| 11469 | LIBIPW_CH_B_ONLY... */ | ||
| 11470 | } | ||
| 11471 | /* point at bitrate info */ | ||
| 11472 | bg_band->bitrates = ipw2200_bg_rates; | ||
| 11473 | bg_band->n_bitrates = ipw2200_num_bg_rates; | ||
| 11474 | |||
| 11475 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; | ||
| 11431 | } | 11476 | } |
| 11432 | 11477 | ||
| 11478 | /* fill-out priv->ieee->a_band */ | ||
| 11479 | if (geo->a_channels) { | ||
| 11480 | struct ieee80211_supported_band *a_band = &priv->ieee->a_band; | ||
| 11481 | |||
| 11482 | a_band->band = IEEE80211_BAND_5GHZ; | ||
| 11483 | a_band->n_channels = geo->a_channels; | ||
| 11484 | a_band->channels = | ||
| 11485 | kzalloc(geo->a_channels * | ||
| 11486 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
| 11487 | /* translate geo->bg to a_band.channels */ | ||
| 11488 | for (i = 0; i < geo->a_channels; i++) { | ||
| 11489 | a_band->channels[i].band = IEEE80211_BAND_2GHZ; | ||
| 11490 | a_band->channels[i].center_freq = geo->a[i].freq; | ||
| 11491 | a_band->channels[i].hw_value = geo->a[i].channel; | ||
| 11492 | a_band->channels[i].max_power = geo->a[i].max_power; | ||
| 11493 | if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY) | ||
| 11494 | a_band->channels[i].flags |= | ||
| 11495 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
| 11496 | if (geo->a[i].flags & LIBIPW_CH_NO_IBSS) | ||
| 11497 | a_band->channels[i].flags |= | ||
| 11498 | IEEE80211_CHAN_NO_IBSS; | ||
| 11499 | if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT) | ||
| 11500 | a_band->channels[i].flags |= | ||
| 11501 | IEEE80211_CHAN_RADAR; | ||
| 11502 | /* No equivalent for LIBIPW_CH_80211H_RULES, | ||
| 11503 | LIBIPW_CH_UNIFORM_SPREADING, or | ||
| 11504 | LIBIPW_CH_B_ONLY... */ | ||
| 11505 | } | ||
| 11506 | /* point at bitrate info */ | ||
| 11507 | a_band->bitrates = ipw2200_a_rates; | ||
| 11508 | a_band->n_bitrates = ipw2200_num_a_rates; | ||
| 11509 | |||
| 11510 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band; | ||
| 11511 | } | ||
| 11512 | |||
| 11513 | set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); | ||
| 11514 | |||
| 11515 | /* With that information in place, we can now register the wiphy... */ | ||
| 11516 | if (wiphy_register(wdev->wiphy)) { | ||
| 11517 | rc = -EIO; | ||
| 11518 | goto out; | ||
| 11519 | } | ||
| 11520 | |||
| 11521 | out: | ||
| 11433 | mutex_unlock(&priv->mutex); | 11522 | mutex_unlock(&priv->mutex); |
| 11434 | return 0; | 11523 | return rc; |
| 11435 | } | 11524 | } |
| 11436 | 11525 | ||
| 11437 | /* PCI driver stuff */ | 11526 | /* PCI driver stuff */ |
| @@ -11562,7 +11651,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) | |||
| 11562 | if (priv->prom_net_dev) | 11651 | if (priv->prom_net_dev) |
| 11563 | return -EPERM; | 11652 | return -EPERM; |
| 11564 | 11653 | ||
| 11565 | priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv)); | 11654 | priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv), 1); |
| 11566 | if (priv->prom_net_dev == NULL) | 11655 | if (priv->prom_net_dev == NULL) |
| 11567 | return -ENOMEM; | 11656 | return -ENOMEM; |
| 11568 | 11657 | ||
| @@ -11581,7 +11670,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) | |||
| 11581 | 11670 | ||
| 11582 | rc = register_netdev(priv->prom_net_dev); | 11671 | rc = register_netdev(priv->prom_net_dev); |
| 11583 | if (rc) { | 11672 | if (rc) { |
| 11584 | free_ieee80211(priv->prom_net_dev); | 11673 | free_ieee80211(priv->prom_net_dev, 1); |
| 11585 | priv->prom_net_dev = NULL; | 11674 | priv->prom_net_dev = NULL; |
| 11586 | return rc; | 11675 | return rc; |
| 11587 | } | 11676 | } |
| @@ -11595,7 +11684,7 @@ static void ipw_prom_free(struct ipw_priv *priv) | |||
| 11595 | return; | 11684 | return; |
| 11596 | 11685 | ||
| 11597 | unregister_netdev(priv->prom_net_dev); | 11686 | unregister_netdev(priv->prom_net_dev); |
| 11598 | free_ieee80211(priv->prom_net_dev); | 11687 | free_ieee80211(priv->prom_net_dev, 1); |
| 11599 | 11688 | ||
| 11600 | priv->prom_net_dev = NULL; | 11689 | priv->prom_net_dev = NULL; |
| 11601 | } | 11690 | } |
| @@ -11623,7 +11712,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, | |||
| 11623 | struct ipw_priv *priv; | 11712 | struct ipw_priv *priv; |
| 11624 | int i; | 11713 | int i; |
| 11625 | 11714 | ||
| 11626 | net_dev = alloc_ieee80211(sizeof(struct ipw_priv)); | 11715 | net_dev = alloc_ieee80211(sizeof(struct ipw_priv), 0); |
| 11627 | if (net_dev == NULL) { | 11716 | if (net_dev == NULL) { |
| 11628 | err = -ENOMEM; | 11717 | err = -ENOMEM; |
| 11629 | goto out; | 11718 | goto out; |
| @@ -11771,7 +11860,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, | |||
| 11771 | pci_disable_device(pdev); | 11860 | pci_disable_device(pdev); |
| 11772 | pci_set_drvdata(pdev, NULL); | 11861 | pci_set_drvdata(pdev, NULL); |
| 11773 | out_free_ieee80211: | 11862 | out_free_ieee80211: |
| 11774 | free_ieee80211(priv->net_dev); | 11863 | free_ieee80211(priv->net_dev, 0); |
| 11775 | out: | 11864 | out: |
| 11776 | return err; | 11865 | return err; |
| 11777 | } | 11866 | } |
| @@ -11838,7 +11927,11 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev) | |||
| 11838 | pci_release_regions(pdev); | 11927 | pci_release_regions(pdev); |
| 11839 | pci_disable_device(pdev); | 11928 | pci_disable_device(pdev); |
| 11840 | pci_set_drvdata(pdev, NULL); | 11929 | pci_set_drvdata(pdev, NULL); |
| 11841 | free_ieee80211(priv->net_dev); | 11930 | /* wiphy_unregister needs to be here, before free_ieee80211 */ |
| 11931 | wiphy_unregister(priv->ieee->wdev.wiphy); | ||
| 11932 | kfree(priv->ieee->a_band.channels); | ||
| 11933 | kfree(priv->ieee->bg_band.channels); | ||
| 11934 | free_ieee80211(priv->net_dev, 0); | ||
| 11842 | free_firmware(); | 11935 | free_firmware(); |
| 11843 | } | 11936 | } |
| 11844 | 11937 | ||
