struct ieee80211_rx_status rx_status = {0};
 
                        if (priv->pdev->revision < ADM8211_REV_CA)
-                               rx_status.ssi = rssi;
+                               rx_status.signal = rssi;
                        else
-                               rx_status.ssi = 100 - rssi;
+                               rx_status.signal = 100 - rssi;
 
                        rx_status.rate_idx = rate;
 
 
        dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
        /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
+       dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
 
        dev->channel_change_time = 1000;
-       dev->max_rssi = 100;    /* FIXME: find better value */
+       dev->max_signal = 100;    /* FIXME: find better value */
 
        dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */
 
 
 
        /* Initialize driver private data */
        SET_IEEE80211_DEV(hw, &pdev->dev);
-       hw->flags = IEEE80211_HW_RX_INCLUDES_FCS;
+       hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+                   IEEE80211_HW_SIGNAL_DBM |
+                   IEEE80211_HW_NOISE_DBM;
        hw->extra_tx_headroom = 2;
        hw->channel_change_time = 5000;
-       /* these names are misleading */
-       hw->max_rssi = -110; /* signal in dBm */
-       hw->max_noise = -110; /* noise in dBm */
-       hw->max_signal = 100; /* we will provide a percentage based on rssi */
        sc = hw->priv;
        sc->hw = hw;
        sc->pdev = pdev;
                rxs.freq = sc->curchan->center_freq;
                rxs.band = sc->curband->band;
 
-               /*
-                * signal quality:
-                * the names here are misleading and the usage of these
-                * values by iwconfig makes it even worse
-                */
-               /* noise floor in dBm, from the last noise calibration */
                rxs.noise = sc->ah->ah_noise_floor;
-               /* signal level in dBm */
-               rxs.ssi = rxs.noise + rs.rs_rssi;
-               /*
-                * "signal" is actually displayed as Link Quality by iwconfig
-                * we provide a percentage based on rssi (assuming max rssi 64)
-                */
-               rxs.signal = rs.rs_rssi * 100 / 64;
+               rxs.signal = rxs.noise + rs.rs_rssi;
+               rxs.qual = rs.rs_rssi * 100 / 64;
 
                rxs.antenna = rs.rs_antenna;
                rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
 
 
        /* fill hw info */
        hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
-                   IEEE80211_HW_RX_INCLUDES_FCS;
-       hw->max_signal = 100;
-       hw->max_rssi = -110;
-       hw->max_noise = -110;
+                   IEEE80211_HW_RX_INCLUDES_FCS |
+                   IEEE80211_HW_SIGNAL_DBM |
+                   IEEE80211_HW_NOISE_DBM;
+
        hw->queues = b43_modparam_qos ? 4 : 1;
        SET_IEEE80211_DEV(hw, dev->dev);
        if (is_valid_ether_addr(sprom->et1mac))
 
                //      and also find out what the maximum possible value is.
                //      Fill status.ssi and status.signal fields.
        } else {
-               status.ssi = b43_rssi_postprocess(dev, rxhdr->jssi,
+               status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
                                                  (phystat0 & B43_RX_PHYST0_OFDM),
                                                  (phystat0 & B43_RX_PHYST0_GAINCTL),
                                                  (phystat3 & B43_RX_PHYST3_TRSTATE));
-               /* the next line looks wrong, but is what mac80211 wants */
-               status.signal = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
+               status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
        }
 
        if (phystat0 & B43_RX_PHYST0_OFDM)
 
 
        /* fill hw info */
        hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
-                   IEEE80211_HW_RX_INCLUDES_FCS;
-       hw->max_signal = 100;
-       hw->max_rssi = -110;
-       hw->max_noise = -110;
+                   IEEE80211_HW_RX_INCLUDES_FCS |
+                   IEEE80211_HW_SIGNAL_DBM |
+                   IEEE80211_HW_NOISE_DBM;
        hw->queues = 1; /* FIXME: hardware has more queues */
        SET_IEEE80211_DEV(hw, dev->dev);
        if (is_valid_ether_addr(sprom->et1mac))
 
                }
        }
 
-       status.ssi = b43legacy_rssi_postprocess(dev, jssi,
+       status.signal = b43legacy_rssi_postprocess(dev, jssi,
                                      (phystat0 & B43legacy_RX_PHYST0_OFDM),
                                      (phystat0 & B43legacy_RX_PHYST0_GAINCTL),
                                      (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
        status.noise = dev->stats.link_noise;
-       status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI;
+       status.qual = (jssi * 100) / B43legacy_RX_MAX_SSI;
        /* change to support A PHY */
        if (phystat0 & B43legacy_RX_PHYST0_OFDM)
                status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
 
 {
        /* First cache any information we need before we overwrite
         * the information provided in the skb from the hardware */
-       s8 signal = stats->ssi;
+       s8 signal = stats->signal;
        s8 noise = 0;
        int rate = stats->rate_idx;
        u64 tsf = stats->mactime;
        }
 
        /* Convert 3945's rssi indicator to dBm */
-       rx_status.ssi = rx_stats->rssi - IWL_RSSI_OFFSET;
+       rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET;
 
        /* Set default noise value to -127 */
        if (priv->last_rx_noise == 0)
         * Calculate rx_status.signal (quality indicator in %) based on SNR. */
        if (rx_stats_noise_diff) {
                snr = rx_stats_sig_avg / rx_stats_noise_diff;
-               rx_status.noise = rx_status.ssi -
+               rx_status.noise = rx_status.signal -
                                        iwl3945_calc_db_from_ratio(snr);
-               rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi,
+               rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal,
                                                         rx_status.noise);
 
        /* If noise info not available, calculate signal quality indicator (%)
         *   using just the dBm signal level. */
        } else {
                rx_status.noise = priv->last_rx_noise;
-               rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, 0);
+               rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0);
        }
 
 
        IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n",
-                       rx_status.ssi, rx_status.noise, rx_status.signal,
+                       rx_status.signal, rx_status.noise, rx_status.qual,
                        rx_stats_sig_avg, rx_stats_noise_diff);
 
        header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
        IWL_DEBUG_STATS_LIMIT("[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n",
                              network_packet ? '*' : ' ',
                              le16_to_cpu(rx_hdr->channel),
-                             rx_status.ssi, rx_status.ssi,
-                             rx_status.ssi, rx_status.rate_idx);
+                             rx_status.signal, rx_status.signal,
+                             rx_status.noise, rx_status.rate_idx);
 
 #ifdef CONFIG_IWL3945_DEBUG
        if (iwl3945_debug_level & (IWL_DL_RX))
        if (network_packet) {
                priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
                priv->last_tsf = le64_to_cpu(rx_end->timestamp);
-               priv->last_rx_rssi = rx_status.ssi;
+               priv->last_rx_rssi = rx_status.signal;
                priv->last_rx_noise = rx_status.noise;
        }
 
 
                                 struct ieee80211_rx_status *stats,
                                 u32 ampdu_status)
 {
-       s8 signal = stats->ssi;
+       s8 signal = stats->signal;
        s8 noise = 0;
        int rate = stats->rate_idx;
        u64 tsf = stats->mactime;
        priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
 
        /* Find max signal strength (dBm) among 3 antenna/receiver chains */
-       rx_status.ssi = iwl4965_calc_rssi(priv, rx_start);
+       rx_status.signal = iwl4965_calc_rssi(priv, rx_start);
 
        /* Meaningful noise values are available only from beacon statistics,
         *   which are gathered only when associated, and indicate noise
        if (iwl_is_associated(priv) &&
            !test_bit(STATUS_SCANNING, &priv->status)) {
                rx_status.noise = priv->last_rx_noise;
-               rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi,
+               rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal,
                                                         rx_status.noise);
        } else {
                rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-               rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, 0);
+               rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal, 0);
        }
 
        /* Reset beacon noise level if not associated. */
        iwl4965_dbg_report_frame(priv, pkt, header, 1);
 
        IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
-                             rx_status.ssi, rx_status.noise, rx_status.signal,
+                             rx_status.signal, rx_status.noise, rx_status.signal,
                              (unsigned long long)rx_status.mactime);
 
 
 
        network_packet = iwl4965_is_network_packet(priv, header);
        if (network_packet) {
-               priv->last_rx_rssi = rx_status.ssi;
+               priv->last_rx_rssi = rx_status.signal;
                priv->last_beacon_time =  priv->ucode_beacon_time;
                priv->last_tsf = le64_to_cpu(rx_start->timestamp);
        }
 
        struct ieee80211_hw *hw = priv->hw;
        hw->rate_control_algorithm = "iwl-4965-rs";
 
-       /* Tell mac80211 and its clients (e.g. Wireless Extensions)
-        *       the range of signal quality values that we'll provide.
-        * Negative values for level/noise indicate that we'll provide dBm.
-        * For WE, at least, non-0 values here *enable* display of values
-        *       in app (iwconfig). */
-       hw->max_rssi = -20; /* signal level, negative indicates dBm */
-       hw->max_noise = -20;    /* noise level, negative indicates dBm */
-       hw->max_signal = 100;   /* link quality indication (%) */
-
-       /* Tell mac80211 our Tx characteristics */
-       hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
-
+       /* Tell mac80211 our characteristics */
+       hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
+                   IEEE80211_HW_SIGNAL_DBM |
+                   IEEE80211_HW_NOISE_DBM;
        /* Default value; 4 EDCA QOS priorities */
        hw->queues = 4;
 #ifdef CONFIG_IWL4965_HT
 
 
        priv->ibss_beacon = NULL;
 
-       /* Tell mac80211 and its clients (e.g. Wireless Extensions)
-        *   the range of signal quality values that we'll provide.
-        * Negative values for level/noise indicate that we'll provide dBm.
-        * For WE, at least, non-0 values here *enable* display of values
-        *   in app (iwconfig). */
-       hw->max_rssi = -20;     /* signal level, negative indicates dBm */
-       hw->max_noise = -20;    /* noise level, negative indicates dBm */
-       hw->max_signal = 100;   /* link quality indication (%) */
-
-       /* Tell mac80211 our Tx characteristics */
-       hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+       /* Tell mac80211 our characteristics */
+       hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
+                   IEEE80211_HW_SIGNAL_DBM |
+                   IEEE80211_HW_NOISE_DBM;
 
        /* 4 EDCA QOS priorities */
        hw->queues = 4;
 
        struct ieee80211_rx_status rx_status = {0};
        u16 freq = le16_to_cpu(hdr->freq);
 
-       rx_status.ssi = hdr->rssi;
+       rx_status.signal = hdr->rssi;
        /* XX correct? */
        rx_status.rate_idx = hdr->rate & 0xf;
        rx_status.freq = freq;
        skb_queue_head_init(&priv->tx_queue);
        dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
        dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
-                   IEEE80211_HW_RX_INCLUDES_FCS;
+                    IEEE80211_HW_RX_INCLUDES_FCS |
+                    IEEE80211_HW_SIGNAL_UNSPEC;
        dev->channel_change_time = 1000;        /* TODO: find actual value */
-       dev->max_rssi = 127;
+       dev->max_signal = 127;
 
        priv->tx_stats[0].limit = 5;
        dev->queues = 1;
 
        /*
         * Initialize all hw fields.
         */
-       rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+       rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+                              IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = 0;
-       rt2x00dev->hw->max_signal = MAX_SIGNAL;
-       rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->queues = 2;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
 
        /*
         * Initialize all hw fields.
         */
-       rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+       rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+                              IEEE80211_HW_SIGNAL_DBM;
+
        rt2x00dev->hw->extra_tx_headroom = 0;
-       rt2x00dev->hw->max_signal = MAX_SIGNAL;
-       rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->queues = 2;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
 
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
            IEEE80211_HW_RX_INCLUDES_FCS |
-           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+           IEEE80211_HW_SIGNAL_DBM;
+
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
-       rt2x00dev->hw->max_signal = MAX_SIGNAL;
-       rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->queues = 2;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
 
        rt2x00dev->link.qual.rx_success++;
 
        rx_status->rate_idx = idx;
-       rx_status->signal =
+       rx_status->qual =
            rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi);
-       rx_status->ssi = rxdesc->rssi;
+       rx_status->signal = rxdesc->rssi;
        rx_status->flag = rxdesc->flags;
        rx_status->antenna = rt2x00dev->link.ant.active.rx;
 
 
         */
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
-           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+           IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = 0;
-       rt2x00dev->hw->max_signal = MAX_SIGNAL;
-       rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->queues = 4;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
 
         */
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
-           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+           IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
-       rt2x00dev->hw->max_signal = MAX_SIGNAL;
-       rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->queues = 4;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
 
 
                        rx_status.antenna = (flags2 >> 15) & 1;
                        /* TODO: improve signal/rssi reporting */
-                       rx_status.signal = flags2 & 0xFF;
-                       rx_status.ssi = (flags2 >> 8) & 0x7F;
+                       rx_status.qual = flags2 & 0xFF;
+                       rx_status.signal = (flags2 >> 8) & 0x7F;
                        /* XXX: is this correct? */
                        rx_status.rate_idx = (flags >> 20) & 0xF;
                        rx_status.freq = dev->conf.channel->center_freq;
        dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
 
        dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-                    IEEE80211_HW_RX_INCLUDES_FCS;
+                    IEEE80211_HW_RX_INCLUDES_FCS |
+                    IEEE80211_HW_SIGNAL_UNSPEC;
        dev->queues = 1;
-       dev->max_rssi = 65;
+       dev->max_signal = 65;
 
        reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
        reg &= RTL818X_TX_CONF_HWVER_MASK;
 
        }
 
        rx_status.antenna = (hdr->signal >> 7) & 1;
-       rx_status.signal = 64 - min(hdr->noise, (u8)64);
-       rx_status.ssi = signal;
+       rx_status.qual = 64 - min(hdr->noise, (u8)64);
+       rx_status.signal = signal;
        rx_status.rate_idx = rate;
        rx_status.freq = dev->conf.channel->center_freq;
        rx_status.band = dev->conf.channel->band;
 
        priv->mode = IEEE80211_IF_TYPE_MNTR;
        dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-                    IEEE80211_HW_RX_INCLUDES_FCS;
+                    IEEE80211_HW_RX_INCLUDES_FCS |
+                    IEEE80211_HW_SIGNAL_UNSPEC;
        dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
        dev->queues = 1;
-       dev->max_rssi = 65;
-       dev->max_signal = 64;
+       dev->max_signal = 65;
 
        eeprom.data = dev;
        eeprom.register_read = rtl8187_eeprom_register_read;
 
 
                        memset(&status, 0, sizeof(status));
                        status.flags = IEEE80211_TX_STATUS_ACK;
-                       status.ack_signal = stats->ssi;
+                       status.ack_signal = stats->signal;
                        __skb_unlink(skb, q);
                        tx_status(hw, skb, &status, 1);
                        goto out;
 
        stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
        stats.band = IEEE80211_BAND_2GHZ;
-       stats.ssi = status->signal_strength;
-       stats.signal = zd_rx_qual_percent(buffer,
+       stats.signal = status->signal_strength;
+       stats.qual = zd_rx_qual_percent(buffer,
                                          length - sizeof(struct rx_status),
                                          status);
 
        hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
 
        hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-                   IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
-       hw->max_rssi = 100;
-       hw->max_signal = 100;
+                   IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
+                   IEEE80211_HW_SIGNAL_DB;
 
+       hw->max_signal = 100;
        hw->queues = 1;
        hw->extra_tx_headroom = sizeof(struct zd_ctrlset);
 
 
  * The low-level driver should provide this information (the subset
  * supported by hardware) to the 802.11 code with each received
  * frame.
+ *
  * @mactime: value in microseconds of the 64-bit Time Synchronization Function
  *     (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
  * @band: the active band when this frame was received
  * @freq: frequency the radio was tuned to when receiving this frame, in MHz
- * @ssi: signal strength when receiving this frame
- * @signal: used as 'qual' in statistics reporting
- * @noise: PHY noise when receiving this frame
+ * @signal: signal strength when receiving this frame, either in dBm, in dB or
+ *     unspecified depending on the hardware capabilities flags
+ *     @IEEE80211_HW_SIGNAL_*
+ * @noise: noise when receiving this frame, in dBm.
+ * @qual: overall signal quality indication, in percent (0-100).
  * @antenna: antenna used
  * @rate_idx: index of data rate into band's supported rates
  * @flag: %RX_FLAG_*
        u64 mactime;
        enum ieee80211_band band;
        int freq;
-       int ssi;
        int signal;
        int noise;
+       int qual;
        int antenna;
        int rate_idx;
        int flag;
  *     relevant only if IEEE80211_TX_STATUS_AMPDU was set.
  * @ampdu_ack_map: block ack bit map for the aggregation.
  *     relevant only if IEEE80211_TX_STATUS_AMPDU was set.
- * @ack_signal: signal strength of the ACK frame
+ * @ack_signal: signal strength of the ACK frame either in dBm, dB or unspec
+ *     depending on hardware capabilites flags @IEEE80211_HW_SIGNAL_*
  */
 struct ieee80211_tx_status {
        struct ieee80211_tx_control control;
  * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE:
  *     Hardware is not capable of receiving frames with short preamble on
  *     the 2.4 GHz band.
+ *
+ * @IEEE80211_HW_SIGNAL_UNSPEC:
+ *     Hardware can provide signal values but we don't know its units. We
+ *     expect values between 0 and @max_signal.
+ *     If possible please provide dB or dBm instead.
+ *
+ * @IEEE80211_HW_SIGNAL_DB:
+ *     Hardware gives signal values in dB, decibel difference from an
+ *     arbitrary, fixed reference. We expect values between 0 and @max_signal.
+ *     If possible please provide dBm instead.
+ *
+ * @IEEE80211_HW_SIGNAL_DBM:
+ *     Hardware gives signal values in dBm, decibel difference from
+ *     one milliwatt. This is the preferred method since it is standardized
+ *     between different devices. @max_signal does not need to be set.
+ *
+ * @IEEE80211_HW_NOISE_DBM:
+ *     Hardware can provide noise (radio interference) values in units dBm,
+ *      decibel difference from one milliwatt.
  */
 enum ieee80211_hw_flags {
        IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE           = 1<<0,
        IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING        = 1<<2,
        IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE          = 1<<3,
        IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE      = 1<<4,
+       IEEE80211_HW_SIGNAL_UNSPEC                      = 1<<5,
+       IEEE80211_HW_SIGNAL_DB                          = 1<<6,
+       IEEE80211_HW_SIGNAL_DBM                         = 1<<7,
+       IEEE80211_HW_NOISE_DBM                          = 1<<8,
 };
 
 /**
  *
  * @channel_change_time: time (in microseconds) it takes to change channels.
  *
- * @max_rssi: Maximum value for ssi in RX information, use
- *     negative numbers for dBm and 0 to indicate no support.
- *
- * @max_signal: like @max_rssi, but for the signal value.
- *
- * @max_noise: like @max_rssi, but for the noise value.
+ * @max_signal: Maximum value for signal (rssi) in RX information, used
+ *     only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
  *
  * @queues: number of available hardware transmit queues for
  *     data packets. WMM/QoS requires at least four, these
        int channel_change_time;
        int vif_data_size;
        u16 queues, ampdu_queues;
-       s8 max_rssi;
        s8 max_signal;
-       s8 max_noise;
 };
 
 /**
 
 
                wstats.updated = 0;
                if (rx_stats->mask & IEEE80211_STATMASK_RSSI) {
-                       wstats.level = rx_stats->rssi;
+                       wstats.level = rx_stats->signal;
                        wstats.updated |= IW_QUAL_LEVEL_UPDATED;
                } else
                        wstats.updated |= IW_QUAL_LEVEL_INVALID;
 
 STA_FILE(tx_filtered, tx_filtered_count, LU);
 STA_FILE(tx_retry_failed, tx_retry_failed, LU);
 STA_FILE(tx_retry_count, tx_retry_count, LU);
-STA_FILE(last_rssi, last_rssi, D);
 STA_FILE(last_signal, last_signal, D);
+STA_FILE(last_qual, last_qual, D);
 STA_FILE(last_noise, last_noise, D);
 STA_FILE(channel_use, channel_use, D);
 STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
 
        u16 capability; /* host byte order */
        enum ieee80211_band band;
        int freq;
-       int rssi, signal, noise;
+       int signal, noise, qual;
        u8 *wpa_ie;
        size_t wpa_ie_len;
        u8 *rsn_ie;
 
 
        local->hw.conf.beacon_int = 1000;
 
-       local->wstats_flags |= local->hw.max_rssi ?
-                              IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
-       local->wstats_flags |= local->hw.max_signal ?
+       local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
+                                                 IEEE80211_HW_SIGNAL_DB |
+                                                 IEEE80211_HW_SIGNAL_DBM) ?
                               IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
-       local->wstats_flags |= local->hw.max_noise ?
+       local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ?
                               IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
-       if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
+       if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
                local->wstats_flags |= IW_QUAL_DBM;
 
        result = sta_info_start(local);
 
                                           local->hw.conf.channel->center_freq,
                                           ifsta->ssid, ifsta->ssid_len);
                if (bss) {
-                       sta->last_rssi = bss->rssi;
                        sta->last_signal = bss->signal;
+                       sta->last_qual = bss->qual;
                        sta->last_noise = bss->noise;
                        ieee80211_rx_bss_put(dev, bss);
                }
 
        bss->timestamp = beacon_timestamp;
        bss->last_update = jiffies;
-       bss->rssi = rx_status->ssi;
        bss->signal = rx_status->signal;
        bss->noise = rx_status->noise;
+       bss->qual = rx_status->qual;
        if (!beacon && !bss->probe_resp)
                bss->probe_resp = true;
 
                    !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
                        continue;
 
-               if (!selected || top_rssi < bss->rssi) {
+               if (!selected || top_rssi < bss->signal) {
                        selected = bss;
-                       top_rssi = bss->rssi;
+                       top_rssi = bss->signal;
                }
        }
        if (selected)
 
        memset(&iwe, 0, sizeof(iwe));
        iwe.cmd = IWEVQUAL;
-       iwe.u.qual.qual = bss->signal;
-       iwe.u.qual.level = bss->rssi;
+       iwe.u.qual.qual = bss->qual;
+       iwe.u.qual.level = bss->signal;
        iwe.u.qual.noise = bss->noise;
        iwe.u.qual.updated = local->wstats_flags;
        current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
 
                                cpu_to_le16(IEEE80211_CHAN_DYN |
                                            IEEE80211_CHAN_2GHZ);
 
-               rtfixed->antsignal = status->ssi;
+               rtfixed->antsignal = status->signal;
                rthdr->it_len = cpu_to_le16(rtap_len);
        }
 
 
        sta->rx_fragments++;
        sta->rx_bytes += rx->skb->len;
-       sta->last_rssi = rx->status->ssi;
        sta->last_signal = rx->status->signal;
+       sta->last_qual = rx->status->qual;
        sta->last_noise = rx->status->noise;
 
        if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
 
                                       * from this STA */
        unsigned long rx_fragments; /* number of received MPDUs */
        unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
-       int last_rssi; /* RSSI of last received frame from this STA */
        int last_signal; /* signal of last received frame from this STA */
+       int last_qual;  /* qual of last received frame from this STA */
        int last_noise; /* noise of last received frame from this STA */
        /* last received seq/frag number from this STA (per RX queue) */
        __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
 
        range->num_encoding_sizes = 2;
        range->max_encoding_tokens = NUM_DEFAULT_KEYS;
 
-       range->max_qual.qual = local->hw.max_signal;
-       range->max_qual.level = local->hw.max_rssi;
-       range->max_qual.noise = local->hw.max_noise;
+       if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC ||
+           local->hw.flags & IEEE80211_HW_SIGNAL_DB)
+               range->max_qual.level = local->hw.max_signal;
+       else if  (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+               range->max_qual.level = -110;
+       else
+               range->max_qual.level = 0;
+
+       if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
+               range->max_qual.noise = -110;
+       else
+               range->max_qual.noise = 0;
+
+       range->max_qual.qual = 100;
        range->max_qual.updated = local->wstats_flags;
 
-       range->avg_qual.qual = local->hw.max_signal/2;
-       range->avg_qual.level = 0;
-       range->avg_qual.noise = 0;
+       range->avg_qual.qual = 50;
+       /* not always true but better than nothing */
+       range->avg_qual.level = range->max_qual.level / 2;
+       range->avg_qual.noise = range->max_qual.noise / 2;
        range->avg_qual.updated = local->wstats_flags;
 
        range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
                wstats->qual.noise = 0;
                wstats->qual.updated = IW_QUAL_ALL_INVALID;
        } else {
-               wstats->qual.level = sta->last_rssi;
-               wstats->qual.qual = sta->last_signal;
+               wstats->qual.level = sta->last_signal;
+               wstats->qual.qual = sta->last_qual;
                wstats->qual.noise = sta->last_noise;
                wstats->qual.updated = local->wstats_flags;
        }