linux/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2016 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#include "mt76x2.h"
  18
  19#define RADAR_SPEC(m, len, el, eh, wl, wh,              \
  20                   w_tolerance, tl, th, t_tolerance,    \
  21                   bl, bh, event_exp, power_jmp)        \
  22{                                                       \
  23        .mode = m,                                      \
  24        .avg_len = len,                                 \
  25        .e_low = el,                                    \
  26        .e_high = eh,                                   \
  27        .w_low = wl,                                    \
  28        .w_high = wh,                                   \
  29        .w_margin = w_tolerance,                        \
  30        .t_low = tl,                                    \
  31        .t_high = th,                                   \
  32        .t_margin = t_tolerance,                        \
  33        .b_low = bl,                                    \
  34        .b_high = bh,                                   \
  35        .event_expiration = event_exp,                  \
  36        .pwr_jmp = power_jmp                            \
  37}
  38
  39static const struct mt76x2_radar_specs etsi_radar_specs[] = {
  40        /* 20MHz */
  41        RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0,
  42                   0x7fffffff, 0x155cc0, 0x19cc),
  43        RADAR_SPEC(0, 40, 4, 59, 96, 380, 150, 4900, 100096, 40, 0,
  44                   0x7fffffff, 0x155cc0, 0x19cc),
  45        RADAR_SPEC(3, 60, 20, 46, 300, 640, 80, 4900, 10100, 80, 0,
  46                   0x7fffffff, 0x155cc0, 0x19dd),
  47        RADAR_SPEC(8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0,
  48                   0x7fffffff, 0x2191c0, 0x15cc),
  49        /* 40MHz */
  50        RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0,
  51                   0x7fffffff, 0x155cc0, 0x19cc),
  52        RADAR_SPEC(0, 40, 4, 59, 96, 380, 150, 4900, 100096, 40, 0,
  53                   0x7fffffff, 0x155cc0, 0x19cc),
  54        RADAR_SPEC(3, 60, 20, 46, 300, 640, 80, 4900, 10100, 80, 0,
  55                   0x7fffffff, 0x155cc0, 0x19dd),
  56        RADAR_SPEC(8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0,
  57                   0x7fffffff, 0x2191c0, 0x15cc),
  58        /* 80MHz */
  59        RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0,
  60                   0x7fffffff, 0x155cc0, 0x19cc),
  61        RADAR_SPEC(0, 40, 4, 59, 96, 380, 150, 4900, 100096, 40, 0,
  62                   0x7fffffff, 0x155cc0, 0x19cc),
  63        RADAR_SPEC(3, 60, 20, 46, 300, 640, 80, 4900, 10100, 80, 0,
  64                   0x7fffffff, 0x155cc0, 0x19dd),
  65        RADAR_SPEC(8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0,
  66                   0x7fffffff, 0x2191c0, 0x15cc)
  67};
  68
  69static const struct mt76x2_radar_specs fcc_radar_specs[] = {
  70        /* 20MHz */
  71        RADAR_SPEC(0, 8, 2, 12, 106, 150, 5, 2900, 80100, 5, 0,
  72                   0x7fffffff, 0xfe808, 0x13dc),
  73        RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
  74                   0x7fffffff, 0xfe808, 0x19dd),
  75        RADAR_SPEC(0, 40, 4, 54, 96, 480, 150, 2900, 80100, 40, 0,
  76                   0x7fffffff, 0xfe808, 0x12cc),
  77        RADAR_SPEC(2, 60, 15, 63, 640, 2080, 32, 19600, 40200, 32, 0,
  78                   0x3938700, 0x57bcf00, 0x1289),
  79        /* 40MHz */
  80        RADAR_SPEC(0, 8, 2, 12, 106, 150, 5, 2900, 80100, 5, 0,
  81                   0x7fffffff, 0xfe808, 0x13dc),
  82        RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
  83                   0x7fffffff, 0xfe808, 0x19dd),
  84        RADAR_SPEC(0, 40, 4, 54, 96, 480, 150, 2900, 80100, 40, 0,
  85                   0x7fffffff, 0xfe808, 0x12cc),
  86        RADAR_SPEC(2, 60, 15, 63, 640, 2080, 32, 19600, 40200, 32, 0,
  87                   0x3938700, 0x57bcf00, 0x1289),
  88        /* 80MHz */
  89        RADAR_SPEC(0, 8, 2, 14, 106, 150, 15, 2900, 80100, 15, 0,
  90                   0x7fffffff, 0xfe808, 0x16cc),
  91        RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
  92                   0x7fffffff, 0xfe808, 0x19dd),
  93        RADAR_SPEC(0, 40, 4, 54, 96, 480, 150, 2900, 80100, 40, 0,
  94                   0x7fffffff, 0xfe808, 0x12cc),
  95        RADAR_SPEC(2, 60, 15, 63, 640, 2080, 32, 19600, 40200, 32, 0,
  96                   0x3938700, 0x57bcf00, 0x1289)
  97};
  98
  99static const struct mt76x2_radar_specs jp_w56_radar_specs[] = {
 100        /* 20MHz */
 101        RADAR_SPEC(0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0,
 102                   0x7fffffff, 0x14c080, 0x13dc),
 103        RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
 104                   0x7fffffff, 0x14c080, 0x19dd),
 105        RADAR_SPEC(0, 40, 4, 44, 96, 480, 150, 2900, 80100, 40, 0,
 106                   0x7fffffff, 0x14c080, 0x12cc),
 107        RADAR_SPEC(2, 60, 15, 48, 940, 2080, 32, 19600, 40200, 32, 0,
 108                   0x3938700, 0X57bcf00, 0x1289),
 109        /* 40MHz */
 110        RADAR_SPEC(0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0,
 111                   0x7fffffff, 0x14c080, 0x13dc),
 112        RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
 113                   0x7fffffff, 0x14c080, 0x19dd),
 114        RADAR_SPEC(0, 40, 4, 44, 96, 480, 150, 2900, 80100, 40, 0,
 115                   0x7fffffff, 0x14c080, 0x12cc),
 116        RADAR_SPEC(2, 60, 15, 48, 940, 2080, 32, 19600, 40200, 32, 0,
 117                   0x3938700, 0X57bcf00, 0x1289),
 118        /* 80MHz */
 119        RADAR_SPEC(0, 8, 2, 9, 106, 150, 15, 2900, 80100, 15, 0,
 120                   0x7fffffff, 0x14c080, 0x16cc),
 121        RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0,
 122                   0x7fffffff, 0x14c080, 0x19dd),
 123        RADAR_SPEC(0, 40, 4, 44, 96, 480, 150, 2900, 80100, 40, 0,
 124                   0x7fffffff, 0x14c080, 0x12cc),
 125        RADAR_SPEC(2, 60, 15, 48, 940, 2080, 32, 19600, 40200, 32, 0,
 126                   0x3938700, 0X57bcf00, 0x1289)
 127};
 128
 129static const struct mt76x2_radar_specs jp_w53_radar_specs[] = {
 130        /* 20MHz */
 131        RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0,
 132                   0x7fffffff, 0x14c080, 0x16cc),
 133        { 0 },
 134        RADAR_SPEC(0, 40, 4, 44, 96, 200, 150, 28400, 77000, 60, 0,
 135                   0x7fffffff, 0x14c080, 0x16cc),
 136        { 0 },
 137        /* 40MHz */
 138        RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0,
 139                   0x7fffffff, 0x14c080, 0x16cc),
 140        { 0 },
 141        RADAR_SPEC(0, 40, 4, 44, 96, 200, 150, 28400, 77000, 60, 0,
 142                   0x7fffffff, 0x14c080, 0x16cc),
 143        { 0 },
 144        /* 80MHz */
 145        RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0,
 146                   0x7fffffff, 0x14c080, 0x16cc),
 147        { 0 },
 148        RADAR_SPEC(0, 40, 4, 44, 96, 200, 150, 28400, 77000, 60, 0,
 149                   0x7fffffff, 0x14c080, 0x16cc),
 150        { 0 }
 151};
 152
 153static void mt76x2_dfs_set_capture_mode_ctrl(struct mt76x2_dev *dev,
 154                                             u8 enable)
 155{
 156        u32 data;
 157
 158        data = (1 << 1) | enable;
 159        mt76_wr(dev, MT_BBP(DFS, 36), data);
 160}
 161
 162static bool mt76x2_dfs_check_chirp(struct mt76x2_dev *dev)
 163{
 164        bool ret = false;
 165        u32 current_ts, delta_ts;
 166        struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
 167
 168        current_ts = mt76_rr(dev, MT_PBF_LIFE_TIMER);
 169        delta_ts = current_ts - dfs_pd->chirp_pulse_ts;
 170        dfs_pd->chirp_pulse_ts = current_ts;
 171
 172        /* 12 sec */
 173        if (delta_ts <= (12 * (1 << 20))) {
 174                if (++dfs_pd->chirp_pulse_cnt > 8)
 175                        ret = true;
 176        } else {
 177                dfs_pd->chirp_pulse_cnt = 1;
 178        }
 179
 180        return ret;
 181}
 182
 183static void mt76x2_dfs_get_hw_pulse(struct mt76x2_dev *dev,
 184                                    struct mt76x2_dfs_hw_pulse *pulse)
 185{
 186        u32 data;
 187
 188        /* select channel */
 189        data = (MT_DFS_CH_EN << 16) | pulse->engine;
 190        mt76_wr(dev, MT_BBP(DFS, 0), data);
 191
 192        /* reported period */
 193        pulse->period = mt76_rr(dev, MT_BBP(DFS, 19));
 194
 195        /* reported width */
 196        pulse->w1 = mt76_rr(dev, MT_BBP(DFS, 20));
 197        pulse->w2 = mt76_rr(dev, MT_BBP(DFS, 23));
 198
 199        /* reported burst number */
 200        pulse->burst = mt76_rr(dev, MT_BBP(DFS, 22));
 201}
 202
 203static bool mt76x2_dfs_check_hw_pulse(struct mt76x2_dev *dev,
 204                                      struct mt76x2_dfs_hw_pulse *pulse)
 205{
 206        bool ret = false;
 207
 208        if (!pulse->period || !pulse->w1)
 209                return false;
 210
 211        switch (dev->dfs_pd.region) {
 212        case NL80211_DFS_FCC:
 213                if (pulse->engine > 3)
 214                        break;
 215
 216                if (pulse->engine == 3) {
 217                        ret = mt76x2_dfs_check_chirp(dev);
 218                        break;
 219                }
 220
 221                /* check short pulse*/
 222                if (pulse->w1 < 120)
 223                        ret = (pulse->period >= 2900 &&
 224                               (pulse->period <= 4700 ||
 225                                pulse->period >= 6400) &&
 226                               (pulse->period <= 6800 ||
 227                                pulse->period >= 10200) &&
 228                               pulse->period <= 61600);
 229                else if (pulse->w1 < 130) /* 120 - 130 */
 230                        ret = (pulse->period >= 2900 &&
 231                               pulse->period <= 61600);
 232                else
 233                        ret = (pulse->period >= 3500 &&
 234                               pulse->period <= 10100);
 235                break;
 236        case NL80211_DFS_ETSI:
 237                if (pulse->engine >= 3)
 238                        break;
 239
 240                ret = (pulse->period >= 4900 &&
 241                       (pulse->period <= 10200 ||
 242                        pulse->period >= 12400) &&
 243                       pulse->period <= 100100);
 244                break;
 245        case NL80211_DFS_JP:
 246                if (dev->mt76.chandef.chan->center_freq >= 5250 &&
 247                    dev->mt76.chandef.chan->center_freq <= 5350) {
 248                        /* JPW53 */
 249                        if (pulse->w1 <= 130)
 250                                ret = (pulse->period >= 28360 &&
 251                                       (pulse->period <= 28700 ||
 252                                        pulse->period >= 76900) &&
 253                                       pulse->period <= 76940);
 254                        break;
 255                }
 256
 257                if (pulse->engine > 3)
 258                        break;
 259
 260                if (pulse->engine == 3) {
 261                        ret = mt76x2_dfs_check_chirp(dev);
 262                        break;
 263                }
 264
 265                /* check short pulse*/
 266                if (pulse->w1 < 120)
 267                        ret = (pulse->period >= 2900 &&
 268                               (pulse->period <= 4700 ||
 269                                pulse->period >= 6400) &&
 270                               (pulse->period <= 6800 ||
 271                                pulse->period >= 27560) &&
 272                               (pulse->period <= 27960 ||
 273                                pulse->period >= 28360) &&
 274                               (pulse->period <= 28700 ||
 275                                pulse->period >= 79900) &&
 276                               pulse->period <= 80100);
 277                else if (pulse->w1 < 130) /* 120 - 130 */
 278                        ret = (pulse->period >= 2900 &&
 279                               (pulse->period <= 10100 ||
 280                                pulse->period >= 27560) &&
 281                               (pulse->period <= 27960 ||
 282                                pulse->period >= 28360) &&
 283                               (pulse->period <= 28700 ||
 284                                pulse->period >= 79900) &&
 285                               pulse->period <= 80100);
 286                else
 287                        ret = (pulse->period >= 3900 &&
 288                               pulse->period <= 10100);
 289                break;
 290        case NL80211_DFS_UNSET:
 291        default:
 292                return false;
 293        }
 294
 295        return ret;
 296}
 297
 298static void mt76x2_dfs_tasklet(unsigned long arg)
 299{
 300        struct mt76x2_dev *dev = (struct mt76x2_dev *)arg;
 301        struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
 302        u32 engine_mask;
 303        int i;
 304
 305        if (test_bit(MT76_SCANNING, &dev->mt76.state))
 306                goto out;
 307
 308        engine_mask = mt76_rr(dev, MT_BBP(DFS, 1));
 309        if (!(engine_mask & 0xf))
 310                goto out;
 311
 312        for (i = 0; i < MT_DFS_NUM_ENGINES; i++) {
 313                struct mt76x2_dfs_hw_pulse pulse;
 314
 315                if (!(engine_mask & (1 << i)))
 316                        continue;
 317
 318                pulse.engine = i;
 319                mt76x2_dfs_get_hw_pulse(dev, &pulse);
 320
 321                if (!mt76x2_dfs_check_hw_pulse(dev, &pulse)) {
 322                        dfs_pd->stats[i].hw_pulse_discarded++;
 323                        continue;
 324                }
 325
 326                /* hw detector rx radar pattern */
 327                dfs_pd->stats[i].hw_pattern++;
 328                ieee80211_radar_detected(dev->mt76.hw);
 329
 330                /* reset hw detector */
 331                mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
 332
 333                return;
 334        }
 335
 336        /* reset hw detector */
 337        mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
 338
 339out:
 340        mt76x2_irq_enable(dev, MT_INT_GPTIMER);
 341}
 342
 343static void mt76x2_dfs_set_bbp_params(struct mt76x2_dev *dev)
 344{
 345        u32 data;
 346        u8 i, shift;
 347        const struct mt76x2_radar_specs *radar_specs;
 348
 349        switch (dev->mt76.chandef.width) {
 350        case NL80211_CHAN_WIDTH_40:
 351                shift = MT_DFS_NUM_ENGINES;
 352                break;
 353        case NL80211_CHAN_WIDTH_80:
 354                shift = 2 * MT_DFS_NUM_ENGINES;
 355                break;
 356        default:
 357                shift = 0;
 358                break;
 359        }
 360
 361        switch (dev->dfs_pd.region) {
 362        case NL80211_DFS_FCC:
 363                radar_specs = &fcc_radar_specs[shift];
 364                break;
 365        case NL80211_DFS_ETSI:
 366                radar_specs = &etsi_radar_specs[shift];
 367                break;
 368        case NL80211_DFS_JP:
 369                if (dev->mt76.chandef.chan->center_freq >= 5250 &&
 370                    dev->mt76.chandef.chan->center_freq <= 5350)
 371                        radar_specs = &jp_w53_radar_specs[shift];
 372                else
 373                        radar_specs = &jp_w56_radar_specs[shift];
 374                break;
 375        case NL80211_DFS_UNSET:
 376        default:
 377                return;
 378        }
 379
 380        data = (MT_DFS_VGA_MASK << 16) |
 381               (MT_DFS_PWR_GAIN_OFFSET << 12) |
 382               (MT_DFS_PWR_DOWN_TIME << 8) |
 383               (MT_DFS_SYM_ROUND << 4) |
 384               (MT_DFS_DELTA_DELAY & 0xf);
 385        mt76_wr(dev, MT_BBP(DFS, 2), data);
 386
 387        data = (MT_DFS_RX_PE_MASK << 16) | MT_DFS_PKT_END_MASK;
 388        mt76_wr(dev, MT_BBP(DFS, 3), data);
 389
 390        for (i = 0; i < MT_DFS_NUM_ENGINES; i++) {
 391                /* configure engine */
 392                mt76_wr(dev, MT_BBP(DFS, 0), i);
 393
 394                /* detection mode + avg_len */
 395                data = ((radar_specs[i].avg_len & 0x1ff) << 16) |
 396                       (radar_specs[i].mode & 0xf);
 397                mt76_wr(dev, MT_BBP(DFS, 4), data);
 398
 399                /* dfs energy */
 400                data = ((radar_specs[i].e_high & 0x0fff) << 16) |
 401                       (radar_specs[i].e_low & 0x0fff);
 402                mt76_wr(dev, MT_BBP(DFS, 5), data);
 403
 404                /* dfs period */
 405                mt76_wr(dev, MT_BBP(DFS, 7), radar_specs[i].t_low);
 406                mt76_wr(dev, MT_BBP(DFS, 9), radar_specs[i].t_high);
 407
 408                /* dfs burst */
 409                mt76_wr(dev, MT_BBP(DFS, 11), radar_specs[i].b_low);
 410                mt76_wr(dev, MT_BBP(DFS, 13), radar_specs[i].b_high);
 411
 412                /* dfs width */
 413                data = ((radar_specs[i].w_high & 0x0fff) << 16) |
 414                       (radar_specs[i].w_low & 0x0fff);
 415                mt76_wr(dev, MT_BBP(DFS, 14), data);
 416
 417                /* dfs margins */
 418                data = (radar_specs[i].w_margin << 16) |
 419                       radar_specs[i].t_margin;
 420                mt76_wr(dev, MT_BBP(DFS, 15), data);
 421
 422                /* dfs event expiration */
 423                mt76_wr(dev, MT_BBP(DFS, 17), radar_specs[i].event_expiration);
 424
 425                /* dfs pwr adj */
 426                mt76_wr(dev, MT_BBP(DFS, 30), radar_specs[i].pwr_jmp);
 427        }
 428
 429        /* reset status */
 430        mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
 431        mt76_wr(dev, MT_BBP(DFS, 36), 0x3);
 432
 433        /* enable detection*/
 434        mt76_wr(dev, MT_BBP(DFS, 0), MT_DFS_CH_EN << 16);
 435        mt76_wr(dev, 0x212c, 0x0c350001);
 436}
 437
 438void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev)
 439{
 440        u32 agc_r8, agc_r4, val_r8, val_r4, dfs_r31;
 441
 442        agc_r8 = mt76_rr(dev, MT_BBP(AGC, 8));
 443        agc_r4 = mt76_rr(dev, MT_BBP(AGC, 4));
 444
 445        val_r8 = (agc_r8 & 0x00007e00) >> 9;
 446        val_r4 = agc_r4 & ~0x1f000000;
 447        val_r4 += (((val_r8 + 1) >> 1) << 24);
 448        mt76_wr(dev, MT_BBP(AGC, 4), val_r4);
 449
 450        dfs_r31 = FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN, val_r4);
 451        dfs_r31 += val_r8;
 452        dfs_r31 -= (agc_r8 & 0x00000038) >> 3;
 453        dfs_r31 = (dfs_r31 << 16) | 0x00000307;
 454        mt76_wr(dev, MT_BBP(DFS, 31), dfs_r31);
 455
 456        mt76_wr(dev, MT_BBP(DFS, 32), 0x00040071);
 457}
 458
 459void mt76x2_dfs_init_params(struct mt76x2_dev *dev)
 460{
 461        struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
 462
 463        if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
 464            dev->dfs_pd.region != NL80211_DFS_UNSET) {
 465                mt76x2_dfs_set_bbp_params(dev);
 466                /* enable debug mode */
 467                mt76x2_dfs_set_capture_mode_ctrl(dev, true);
 468
 469                mt76x2_irq_enable(dev, MT_INT_GPTIMER);
 470                mt76_rmw_field(dev, MT_INT_TIMER_EN,
 471                               MT_INT_TIMER_EN_GP_TIMER_EN, 1);
 472        } else {
 473                /* disable hw detector */
 474                mt76_wr(dev, MT_BBP(DFS, 0), 0);
 475                /* clear detector status */
 476                mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
 477                mt76_wr(dev, 0x212c, 0);
 478
 479                mt76x2_irq_disable(dev, MT_INT_GPTIMER);
 480                mt76_rmw_field(dev, MT_INT_TIMER_EN,
 481                               MT_INT_TIMER_EN_GP_TIMER_EN, 0);
 482        }
 483}
 484
 485void mt76x2_dfs_init_detector(struct mt76x2_dev *dev)
 486{
 487        struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
 488
 489        dfs_pd->region = NL80211_DFS_UNSET;
 490        tasklet_init(&dfs_pd->dfs_tasklet, mt76x2_dfs_tasklet,
 491                     (unsigned long)dev);
 492}
 493
 494void mt76x2_dfs_set_domain(struct mt76x2_dev *dev,
 495                           enum nl80211_dfs_regions region)
 496{
 497        struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
 498
 499        if (dfs_pd->region != region) {
 500                tasklet_disable(&dfs_pd->dfs_tasklet);
 501                dfs_pd->region = region;
 502                mt76x2_dfs_init_params(dev);
 503                tasklet_enable(&dfs_pd->dfs_tasklet);
 504        }
 505}
 506
 507