return -EINVAL;
        if (!tb[NL80211_ATTR_FREQ_RANGE_END])
                return -EINVAL;
-       if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
-               return -EINVAL;
        if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
                return -EINVAL;
 
                nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
        freq_range->end_freq_khz =
                nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
-       freq_range->max_bandwidth_khz =
-               nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
+       if (tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
+               freq_range->max_bandwidth_khz =
+                       nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
 
        power_rule->max_eirp =
                nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
                const struct ieee80211_reg_rule *reg_rule;
                const struct ieee80211_freq_range *freq_range;
                const struct ieee80211_power_rule *power_rule;
+               unsigned int max_bandwidth_khz;
 
                reg_rule = ®dom->reg_rules[i];
                freq_range = ®_rule->freq_range;
                if (!nl_reg_rule)
                        goto nla_put_failure_rcu;
 
+               max_bandwidth_khz = freq_range->max_bandwidth_khz;
+               if (!max_bandwidth_khz)
+                       max_bandwidth_khz = reg_get_max_bandwidth(regdom,
+                                                                 reg_rule);
+
                if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
                                reg_rule->flags) ||
                    nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
                    nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
                                freq_range->end_freq_khz) ||
                    nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
-                               freq_range->max_bandwidth_khz) ||
+                               max_bandwidth_khz) ||
                    nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
                                power_rule->max_antenna_gain) ||
                    nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
 
        return get_cfg80211_regdom();
 }
 
+unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
+                                  const struct ieee80211_reg_rule *rule)
+{
+       const struct ieee80211_freq_range *freq_range = &rule->freq_range;
+       const struct ieee80211_freq_range *freq_range_tmp;
+       const struct ieee80211_reg_rule *tmp;
+       u32 start_freq, end_freq, idx, no;
+
+       for (idx = 0; idx < rd->n_reg_rules; idx++)
+               if (rule == &rd->reg_rules[idx])
+                       break;
+
+       if (idx == rd->n_reg_rules)
+               return 0;
+
+       /* get start_freq */
+       no = idx;
+
+       while (no) {
+               tmp = &rd->reg_rules[--no];
+               freq_range_tmp = &tmp->freq_range;
+
+               if (freq_range_tmp->end_freq_khz < freq_range->start_freq_khz)
+                       break;
+
+               if (freq_range_tmp->max_bandwidth_khz)
+                       break;
+
+               freq_range = freq_range_tmp;
+       }
+
+       start_freq = freq_range->start_freq_khz;
+
+       /* get end_freq */
+       freq_range = &rule->freq_range;
+       no = idx;
+
+       while (no < rd->n_reg_rules - 1) {
+               tmp = &rd->reg_rules[++no];
+               freq_range_tmp = &tmp->freq_range;
+
+               if (freq_range_tmp->start_freq_khz > freq_range->end_freq_khz)
+                       break;
+
+               if (freq_range_tmp->max_bandwidth_khz)
+                       break;
+
+               freq_range = freq_range_tmp;
+       }
+
+       end_freq = freq_range->end_freq_khz;
+
+       return end_freq - start_freq;
+}
+
 /* Sanity check on a regulatory rule */
 static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 {
  * Helper for regdom_intersect(), this does the real
  * mathematical intersection fun
  */
-static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
+static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
+                              const struct ieee80211_regdomain *rd2,
+                              const struct ieee80211_reg_rule *rule1,
                               const struct ieee80211_reg_rule *rule2,
                               struct ieee80211_reg_rule *intersected_rule)
 {
        struct ieee80211_freq_range *freq_range;
        const struct ieee80211_power_rule *power_rule1, *power_rule2;
        struct ieee80211_power_rule *power_rule;
-       u32 freq_diff;
+       u32 freq_diff, max_bandwidth1, max_bandwidth2;
 
        freq_range1 = &rule1->freq_range;
        freq_range2 = &rule2->freq_range;
                                         freq_range2->start_freq_khz);
        freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
                                       freq_range2->end_freq_khz);
-       freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz,
-                                           freq_range2->max_bandwidth_khz);
+
+       max_bandwidth1 = freq_range1->max_bandwidth_khz;
+       max_bandwidth2 = freq_range2->max_bandwidth_khz;
+
+       /*
+        * In case max_bandwidth1 == 0 and max_bandwith2 == 0 set
+        * output bandwidth as 0 (auto calculation). Next we will
+        * calculate this correctly in handle_channel function.
+        * In other case calculate output bandwidth here.
+        */
+       if (max_bandwidth1 || max_bandwidth2) {
+               if (!max_bandwidth1)
+                       max_bandwidth1 = reg_get_max_bandwidth(rd1, rule1);
+               if (!max_bandwidth2)
+                       max_bandwidth2 = reg_get_max_bandwidth(rd2, rule2);
+       }
+
+       freq_range->max_bandwidth_khz = min(max_bandwidth1, max_bandwidth2);
 
        freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
        if (freq_range->max_bandwidth_khz > freq_diff)
                rule1 = &rd1->reg_rules[x];
                for (y = 0; y < rd2->n_reg_rules; y++) {
                        rule2 = &rd2->reg_rules[y];
-                       if (!reg_rules_intersect(rule1, rule2, &dummy_rule))
+                       if (!reg_rules_intersect(rd1, rd2, rule1, rule2,
+                                                &dummy_rule))
                                num_rules++;
                }
        }
                         * a memcpy()
                         */
                        intersected_rule = &rd->reg_rules[rule_idx];
-                       r = reg_rules_intersect(rule1, rule2, intersected_rule);
+                       r = reg_rules_intersect(rd1, rd2, rule1, rule2,
+                                               intersected_rule);
                        /*
                         * No need to memset here the intersected rule here as
                         * we're not using the stack anymore
        const struct ieee80211_freq_range *freq_range = NULL;
        struct wiphy *request_wiphy = NULL;
        struct regulatory_request *lr = get_last_request();
+       const struct ieee80211_regdomain *regd;
+       u32 max_bandwidth_khz;
 
        request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
 
        power_rule = ®_rule->power_rule;
        freq_range = ®_rule->freq_range;
 
-       if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
+       max_bandwidth_khz = freq_range->max_bandwidth_khz;
+       /* Check if auto calculation requested */
+       if (!max_bandwidth_khz) {
+               regd = reg_get_regdomain(wiphy);
+               max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
+       }
+
+       if (max_bandwidth_khz < MHZ_TO_KHZ(40))
                bw_flags = IEEE80211_CHAN_NO_HT40;
-       if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
+       if (max_bandwidth_khz < MHZ_TO_KHZ(80))
                bw_flags |= IEEE80211_CHAN_NO_80MHZ;
-       if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
+       if (max_bandwidth_khz < MHZ_TO_KHZ(160))
                bw_flags |= IEEE80211_CHAN_NO_160MHZ;
 
        if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
        const struct ieee80211_reg_rule *reg_rule = NULL;
        const struct ieee80211_power_rule *power_rule = NULL;
        const struct ieee80211_freq_range *freq_range = NULL;
+       u32 max_bandwidth_khz;
 
        reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq),
                                      regd);
        power_rule = ®_rule->power_rule;
        freq_range = ®_rule->freq_range;
 
-       if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
+       max_bandwidth_khz = freq_range->max_bandwidth_khz;
+       /* Check if auto calculation requested */
+       if (!max_bandwidth_khz)
+               max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
+
+       if (max_bandwidth_khz < MHZ_TO_KHZ(40))
                bw_flags = IEEE80211_CHAN_NO_HT40;
-       if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
+       if (max_bandwidth_khz < MHZ_TO_KHZ(80))
                bw_flags |= IEEE80211_CHAN_NO_80MHZ;
-       if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
+       if (max_bandwidth_khz < MHZ_TO_KHZ(160))
                bw_flags |= IEEE80211_CHAN_NO_160MHZ;
 
        chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
        const struct ieee80211_reg_rule *reg_rule = NULL;
        const struct ieee80211_freq_range *freq_range = NULL;
        const struct ieee80211_power_rule *power_rule = NULL;
+       char bw[32];
 
        pr_info("  (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n");
 
                freq_range = ®_rule->freq_range;
                power_rule = ®_rule->power_rule;
 
+               if (!freq_range->max_bandwidth_khz)
+                       snprintf(bw, 32, "%d KHz, AUTO",
+                                reg_get_max_bandwidth(rd, reg_rule));
+               else
+                       snprintf(bw, 32, "%d KHz",
+                                freq_range->max_bandwidth_khz);
+
                /*
                 * There may not be documentation for max antenna gain
                 * in certain regions
                 */
                if (power_rule->max_antenna_gain)
-                       pr_info("  (%d KHz - %d KHz @ %d KHz), (%d mBi, %d mBm)\n",
+                       pr_info("  (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n",
                                freq_range->start_freq_khz,
                                freq_range->end_freq_khz,
-                               freq_range->max_bandwidth_khz,
+                               bw,
                                power_rule->max_antenna_gain,
                                power_rule->max_eirp);
                else
-                       pr_info("  (%d KHz - %d KHz @ %d KHz), (N/A, %d mBm)\n",
+                       pr_info("  (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n",
                                freq_range->start_freq_khz,
                                freq_range->end_freq_khz,
-                               freq_range->max_bandwidth_khz,
+                               bw,
                                power_rule->max_eirp);
        }
 }