summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2009-11-11 14:36:30 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-23 17:05:27 -0500
commitc26409a919e2a338f0cff6ea0e1a96e658a3bfaa (patch)
tree25a3759a1d65bc70b329fa44df4b76c74b942609
parenta3caa99e6c68f466c13cfea74097f6fb01b45e25 (diff)
ipw2100: Register the wiphy device
libipw unconditionally calls wiphy_unregister, but it's up to the driver to register it in the first place. ipw2100 fails to do so. Add the necessary glue code, and also ensure that rfkill statuses get set up appropriately. (Augmented for proper wiphy_unregister placement. -- JWL) Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c124
1 files changed, 95 insertions, 29 deletions
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index a9bc8a97c4e1..6c836c892e43 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -296,6 +296,33 @@ static const char *command_types[] = {
};
#endif
+#define WEXT_USECHANNELS 1
+
+static const long ipw2100_frequencies[] = {
+ 2412, 2417, 2422, 2427,
+ 2432, 2437, 2442, 2447,
+ 2452, 2457, 2462, 2467,
+ 2472, 2484
+};
+
+#define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies)
+
+static const long ipw2100_rates_11b[] = {
+ 1000000,
+ 2000000,
+ 5500000,
+ 11000000
+};
+
+static struct ieee80211_rate ipw2100_bg_rates[] = {
+ { .bitrate = 10 },
+ { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+};
+
+#define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b)
+
/* Pre-decl until we get the code solid and then we can clean it up */
static void ipw2100_tx_send_commands(struct ipw2100_priv *priv);
static void ipw2100_tx_send_data(struct ipw2100_priv *priv);
@@ -1141,6 +1168,7 @@ static int rf_kill_active(struct ipw2100_priv *priv)
int i;
if (!(priv->hw_features & HW_FEATURE_RFKILL)) {
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false);
priv->status &= ~STATUS_RF_KILL_HW;
return 0;
}
@@ -1151,10 +1179,13 @@ static int rf_kill_active(struct ipw2100_priv *priv)
value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1);
}
- if (value == 0)
+ if (value == 0) {
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
priv->status |= STATUS_RF_KILL_HW;
- else
+ } else {
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false);
priv->status &= ~STATUS_RF_KILL_HW;
+ }
return (value == 0);
}
@@ -1814,13 +1845,6 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
return rc;
}
-/* Called by register_netdev() */
-static int ipw2100_net_init(struct net_device *dev)
-{
- struct ipw2100_priv *priv = libipw_priv(dev);
- return ipw2100_up(priv, 1);
-}
-
static void ipw2100_down(struct ipw2100_priv *priv)
{
unsigned long flags;
@@ -1875,6 +1899,64 @@ static void ipw2100_down(struct ipw2100_priv *priv)
netif_stop_queue(priv->net_dev);
}
+/* Called by register_netdev() */
+static int ipw2100_net_init(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = libipw_priv(dev);
+ const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
+ struct wireless_dev *wdev = &priv->ieee->wdev;
+ int ret;
+ int i;
+
+ ret = ipw2100_up(priv, 1);
+ if (ret)
+ return ret;
+
+ memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
+
+ /* fill-out priv->ieee->bg_band */
+ if (geo->bg_channels) {
+ struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band;
+
+ bg_band->band = IEEE80211_BAND_2GHZ;
+ bg_band->n_channels = geo->bg_channels;
+ bg_band->channels =
+ kzalloc(geo->bg_channels *
+ sizeof(struct ieee80211_channel), GFP_KERNEL);
+ /* translate geo->bg to bg_band.channels */
+ for (i = 0; i < geo->bg_channels; i++) {
+ bg_band->channels[i].band = IEEE80211_BAND_2GHZ;
+ bg_band->channels[i].center_freq = geo->bg[i].freq;
+ bg_band->channels[i].hw_value = geo->bg[i].channel;
+ bg_band->channels[i].max_power = geo->bg[i].max_power;
+ if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
+ bg_band->channels[i].flags |=
+ IEEE80211_CHAN_PASSIVE_SCAN;
+ if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
+ bg_band->channels[i].flags |=
+ IEEE80211_CHAN_NO_IBSS;
+ if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
+ bg_band->channels[i].flags |=
+ IEEE80211_CHAN_RADAR;
+ /* No equivalent for LIBIPW_CH_80211H_RULES,
+ LIBIPW_CH_UNIFORM_SPREADING, or
+ LIBIPW_CH_B_ONLY... */
+ }
+ /* point at bitrate info */
+ bg_band->bitrates = ipw2100_bg_rates;
+ bg_band->n_bitrates = RATE_COUNT;
+
+ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band;
+ }
+
+ set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
+ if (wiphy_register(wdev->wiphy)) {
+ ipw2100_down(priv);
+ return -EIO;
+ }
+ return 0;
+}
+
static void ipw2100_reset_adapter(struct work_struct *work)
{
struct ipw2100_priv *priv =
@@ -2090,6 +2172,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
priv->net_dev->name);
/* RF_KILL is now enabled (else we wouldn't be here) */
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
priv->status |= STATUS_RF_KILL_HW;
/* Make sure the RF Kill check timer is running */
@@ -6400,6 +6483,9 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
if (dev->base_addr)
iounmap((void __iomem *)dev->base_addr);
+ /* wiphy_unregister needs to be here, before free_ieee80211 */
+ wiphy_unregister(priv->ieee->wdev.wiphy);
+ kfree(priv->ieee->bg_band.channels);
free_ieee80211(dev, 0);
}
@@ -6601,26 +6687,6 @@ static void __exit ipw2100_exit(void)
module_init(ipw2100_init);
module_exit(ipw2100_exit);
-#define WEXT_USECHANNELS 1
-
-static const long ipw2100_frequencies[] = {
- 2412, 2417, 2422, 2427,
- 2432, 2437, 2442, 2447,
- 2452, 2457, 2462, 2467,
- 2472, 2484
-};
-
-#define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies)
-
-static const long ipw2100_rates_11b[] = {
- 1000000,
- 2000000,
- 5500000,
- 11000000
-};
-
-#define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b)
-
static int ipw2100_wx_get_name(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)