Message ID | d2a2e00a-6a71-49da-356d-53bcd7c0d7e1@gmail.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Kalle Valo |
Headers | show |
Series | [v2,1/5] wifi: rtl8xxxu: Deduplicate the efuse dumping code | expand |
Hi Bitterblue, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on wireless-next/main] [also build test WARNING on linus/master next-20221214] [cannot apply to wireless/main v6.1] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Bitterblue-Smith/wifi-rtl8xxxu-Deduplicate-the-efuse-dumping-code/20221214-013923 base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main patch link: https://lore.kernel.org/r/d2a2e00a-6a71-49da-356d-53bcd7c0d7e1%40gmail.com patch subject: [PATCH v2 5/5] wifi: rtl8xxxu: Add rate control code for RTL8188EU config: x86_64-allyesconfig compiler: gcc-11 (Debian 11.3.0-8) 11.3.0 reproduce (this is a W=1 build): # https://github.com/intel-lab-lkp/linux/commit/9ea9bb5b4820418238d20789475046de5b5e23f3 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Bitterblue-Smith/wifi-rtl8xxxu-Deduplicate-the-efuse-dumping-code/20221214-013923 git checkout 9ea9bb5b4820418238d20789475046de5b5e23f3 # save the config file mkdir build_dir && cp config build_dir/.config make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/net/wireless/realtek/rtl8xxxu/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c: In function 'rtl8188eu_config_channel': drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c:456:14: warning: variable 'ht' set but not used [-Wunused-but-set-variable] 456 | bool ht = true; | ^~ At top level: >> drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c:383:17: warning: 'trying_necessary' defined but not used [-Wunused-const-variable=] 383 | static const u8 trying_necessary[RATESIZE] = { | ^~~~~~~~~~~~~~~~ >> drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c:314:17: warning: 'retry_penalty_up' defined but not used [-Wunused-const-variable=] 314 | static const u8 retry_penalty_up[RETRYSIZE + 1] = {49, 44, 16, 16, 0, 48}; /* 12% for rate up */ | ^~~~~~~~~~~~~~~~ vim +/trying_necessary +383 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c 313 > 314 static const u8 retry_penalty_up[RETRYSIZE + 1] = {49, 44, 16, 16, 0, 48}; /* 12% for rate up */ 315 316 static const u8 pt_penalty[RETRYSIZE + 1] = {34, 31, 30, 24, 0, 32}; 317 318 static const u8 retry_penalty_idx_normal[2][RATESIZE] = { 319 { /* RSSI>TH */ 320 4, 4, 4, 5, 321 4, 4, 5, 7, 7, 7, 8, 0x0a, 322 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d, 323 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f 324 }, 325 { /* RSSI<TH */ 326 0x0a, 0x0a, 0x0b, 0x0c, 327 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13, 328 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x13, 0x13, 329 9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13 330 } 331 }; 332 333 static const u8 retry_penalty_idx_cut_i[2][RATESIZE] = { 334 { /* RSSI>TH */ 335 4, 4, 4, 5, 336 4, 4, 5, 7, 7, 7, 8, 0x0a, 337 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d, 338 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f 339 }, 340 { /* RSSI<TH */ 341 0x0a, 0x0a, 0x0b, 0x0c, 342 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13, 343 0x06, 0x07, 0x08, 0x0d, 0x0e, 0x11, 0x11, 0x11, 344 9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13 345 } 346 }; 347 348 static const u8 retry_penalty_up_idx_normal[RATESIZE] = { 349 0x0c, 0x0d, 0x0d, 0x0f, 350 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14, 351 0x0f, 0x10, 0x10, 0x12, 0x12, 0x13, 0x14, 0x15, 352 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15 353 }; 354 355 static const u8 retry_penalty_up_idx_cut_i[RATESIZE] = { 356 0x0c, 0x0d, 0x0d, 0x0f, 357 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14, 358 0x0b, 0x0b, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 359 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15 360 }; 361 362 static const u8 rssi_threshold[RATESIZE] = { 363 0, 0, 0, 0, 364 0, 0, 0, 0, 0, 0x24, 0x26, 0x2a, 365 0x18, 0x1a, 0x1d, 0x1f, 0x21, 0x27, 0x29, 0x2a, 366 0, 0, 0, 0x1f, 0x23, 0x28, 0x2a, 0x2c 367 }; 368 369 static const u16 n_threshold_high[RATESIZE] = { 370 4, 4, 8, 16, 371 24, 36, 48, 72, 96, 144, 192, 216, 372 60, 80, 100, 160, 240, 400, 600, 800, 373 300, 320, 480, 720, 1000, 1200, 1600, 2000 374 }; 375 376 static const u16 n_threshold_low[RATESIZE] = { 377 2, 2, 4, 8, 378 12, 18, 24, 36, 48, 72, 96, 108, 379 30, 40, 50, 80, 120, 200, 300, 400, 380 150, 160, 240, 360, 500, 600, 800, 1000 381 }; 382 > 383 static const u8 trying_necessary[RATESIZE] = { 384 2, 2, 2, 2, 385 2, 2, 3, 3, 4, 4, 5, 7, 386 4, 4, 7, 10, 10, 12, 12, 18, 387 5, 7, 7, 8, 11, 18, 36, 60 388 }; 389 390 static const u8 dropping_necessary[RATESIZE] = { 391 1, 1, 1, 1, 392 1, 2, 3, 4, 5, 6, 7, 8, 393 1, 2, 3, 4, 5, 6, 7, 8, 394 5, 6, 7, 8, 9, 10, 11, 12 395 }; 396 397 static const u8 pending_for_rate_up_fail[5] = {2, 10, 24, 40, 60}; 398 399 static const u16 dynamic_tx_rpt_timing[6] = { 400 0x186a, 0x30d4, 0x493e, 0x61a8, 0x7a12, 0x927c /* 200ms-1200ms */ 401 }; 402 403 enum rtl8188e_tx_rpt_timing { 404 DEFAULT_TIMING = 0, 405 INCREASE_TIMING, 406 DECREASE_TIMING 407 }; 408 409 static int rtl8188eu_identify_chip(struct rtl8xxxu_priv *priv) 410 { 411 struct device *dev = &priv->udev->dev; 412 u32 sys_cfg, vendor; 413 int ret = 0; 414 415 strscpy(priv->chip_name, "8188EU", sizeof(priv->chip_name)); 416 priv->rtl_chip = RTL8188E; 417 priv->rf_paths = 1; 418 priv->rx_paths = 1; 419 priv->tx_paths = 1; 420 priv->has_wifi = 1; 421 422 sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); 423 priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK); 424 if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { 425 dev_info(dev, "Unsupported test chip\n"); 426 ret = -EOPNOTSUPP; 427 goto out; 428 } 429 430 /* 431 * TODO: At a glance, I cut requires a different firmware, 432 * different initialisation tables, and no software rate 433 * control. The vendor driver is not configured to handle 434 * I cut chips by default. Are there any in the wild? 435 */ 436 if (priv->chip_cut == 8) { 437 dev_info(dev, "RTL8188EU cut I is not supported. Please complain about it at linux-wireless@vger.kernel.org.\n"); 438 ret = -EOPNOTSUPP; 439 goto out; 440 } 441 442 vendor = sys_cfg & SYS_CFG_VENDOR_ID; 443 rtl8xxxu_identify_vendor_1bit(priv, vendor); 444 445 ret = rtl8xxxu_config_endpoints_no_sie(priv); 446 447 out: 448 return ret; 449 } 450 451 static void rtl8188eu_config_channel(struct ieee80211_hw *hw) 452 { 453 struct rtl8xxxu_priv *priv = hw->priv; 454 u32 val32, rsr; 455 u8 opmode; > 456 bool ht = true; 457 int sec_ch_above, channel; 458 int i; 459 460 opmode = rtl8xxxu_read8(priv, REG_BW_OPMODE); 461 rsr = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); 462 channel = hw->conf.chandef.chan->hw_value; 463 464 switch (hw->conf.chandef.width) { 465 case NL80211_CHAN_WIDTH_20_NOHT: 466 ht = false; 467 fallthrough; 468 case NL80211_CHAN_WIDTH_20: 469 opmode |= BW_OPMODE_20MHZ; 470 rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); 471 472 val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); 473 val32 &= ~FPGA_RF_MODE; 474 rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); 475 476 val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); 477 val32 &= ~FPGA_RF_MODE; 478 rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32); 479 break; 480 case NL80211_CHAN_WIDTH_40: 481 if (hw->conf.chandef.center_freq1 > 482 hw->conf.chandef.chan->center_freq) { 483 sec_ch_above = 1; 484 channel += 2; 485 } else { 486 sec_ch_above = 0; 487 channel -= 2; 488 } 489 490 opmode &= ~BW_OPMODE_20MHZ; 491 rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); 492 rsr &= ~RSR_RSC_BANDWIDTH_40M; 493 if (sec_ch_above) 494 rsr |= RSR_RSC_LOWER_SUB_CHANNEL; 495 else 496 rsr |= RSR_RSC_UPPER_SUB_CHANNEL; 497 rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, rsr); 498 499 val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); 500 val32 |= FPGA_RF_MODE; 501 rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); 502 503 val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); 504 val32 |= FPGA_RF_MODE; 505 rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32); 506 507 /* 508 * Set Control channel to upper or lower. These settings 509 * are required only for 40MHz 510 */ 511 val32 = rtl8xxxu_read32(priv, REG_CCK0_SYSTEM); 512 val32 &= ~CCK0_SIDEBAND; 513 if (!sec_ch_above) 514 val32 |= CCK0_SIDEBAND; 515 rtl8xxxu_write32(priv, REG_CCK0_SYSTEM, val32); 516 517 val32 = rtl8xxxu_read32(priv, REG_OFDM1_LSTF); 518 val32 &= ~OFDM_LSTF_PRIME_CH_MASK; /* 0xc00 */ 519 if (sec_ch_above) 520 val32 |= OFDM_LSTF_PRIME_CH_LOW; 521 else 522 val32 |= OFDM_LSTF_PRIME_CH_HIGH; 523 rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val32); 524 525 val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); 526 val32 &= ~(FPGA0_PS_LOWER_CHANNEL | FPGA0_PS_UPPER_CHANNEL); 527 if (sec_ch_above) 528 val32 |= FPGA0_PS_UPPER_CHANNEL; 529 else 530 val32 |= FPGA0_PS_LOWER_CHANNEL; 531 rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val32); 532 break; 533 534 default: 535 break; 536 } 537 538 for (i = RF_A; i < priv->rf_paths; i++) { 539 val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG); 540 u32p_replace_bits(&val32, channel, MODE_AG_CHANNEL_MASK); 541 rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32); 542 } 543 544 for (i = RF_A; i < priv->rf_paths; i++) { 545 val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG); 546 val32 &= ~MODE_AG_BW_MASK; 547 if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40) 548 val32 |= MODE_AG_BW_40MHZ_8723B; 549 else 550 val32 |= MODE_AG_BW_20MHZ_8723B; 551 rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32); 552 } 553 } 554
On Tue, 2022-12-13 at 19:33 +0200, Bitterblue Smith wrote: > Copied from the newer vendor driver, v5.2.2.4. > > Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com> > --- > v2: > - Implement suggestions from Ping-Ke Shih: > - Add missing break in two switch statements. > - Remove unnecessary initialisation of idx in rtl8188e_set_tx_rpt_timing(). > --- > .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 39 ++ > .../realtek/rtl8xxxu/rtl8xxxu_8188e.c | 601 +++++++++++++++++- > .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 131 +++- > 3 files changed, 741 insertions(+), 30 deletions(-) > > diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h > b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h > index 29f5dbee16b0..be9479f969b7 100644 > --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h > +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h > [...] > + > +static void rtl8188e_power_training_try_state(struct rtl8xxxu_ra_info *ra) > +{ > + ra->pt_try_state = 0; > + switch (ra->pt_mode_ss) { > + case 3: > + if (ra->decision_rate >= DESC_RATE_MCS13) > + ra->pt_try_state = 1; > + break; > + case 2: > + if (ra->decision_rate >= DESC_RATE_MCS5) > + ra->pt_try_state = 1; > + break; > + case 1: > + if (ra->decision_rate >= DESC_RATE_48M) > + ra->pt_try_state = 1; > + break; > + case 0: > + if (ra->decision_rate >= DESC_RATE_11M) > + ra->pt_try_state = 1; > + break; > + default: > + ra->pt_try_state = 0; It seems to be 0 already because of first statement of this function. > + break; > + } > + > + if (ra->rssi_sta_ra < 48) { > + ra->pt_stage = 0; > + } else if (ra->pt_try_state == 1) { > + if ((ra->pt_stop_count >= 10) || > + (ra->pt_pre_rssi > ra->rssi_sta_ra + 5) || > + (ra->pt_pre_rssi < ra->rssi_sta_ra - 5) || > + (ra->decision_rate != ra->pt_pre_rate)) { > + if (ra->pt_stage == 0) > + ra->pt_stage = 1; > + else if (ra->pt_stage == 1) > + ra->pt_stage = 3; > + else > + ra->pt_stage = 5; > + > + ra->pt_pre_rssi = ra->rssi_sta_ra; > + ra->pt_stop_count = 0; > + } else { > + ra->ra_stage = 0; > + ra->pt_stop_count++; > + } > + } else { > + ra->pt_stage = 0; > + ra->ra_stage = 0; > + } > + > + ra->pt_pre_rate = ra->decision_rate; > + > + /* TODO: implement the "false alarm" statistics for this */ > + /* Disable power training when noisy environment */ > + /* if (p_dm_odm->is_disable_power_training) { */ > + if (1) { > + ra->pt_stage = 0; > + ra->ra_stage = 0; > + ra->pt_stop_count = 0; > + } > +} > + > +static void rtl8188e_power_training_decision(struct rtl8xxxu_ra_info *ra) > +{ > + u8 temp_stage; > + u32 numsc; > + u32 num_total; > + u8 stage_id; > + u8 j; > + > + numsc = 0; > + num_total = ra->total * pt_penalty[5]; > + for (j = 0; j <= 4; j++) { > + numsc += ra->retry[j] * pt_penalty[j]; > + > + if (numsc > num_total) > + break; > + } > + > + j = j >> 1; j >>= 1; > + temp_stage = (ra->pt_stage + 1) >> 1; > + if (temp_stage > j) > + stage_id = temp_stage - j; > + else > + stage_id = 0; > + > + ra->pt_smooth_factor = (ra->pt_smooth_factor >> 1) + > + (ra->pt_smooth_factor >> 2) + > + stage_id * 16 + 2; > + if (ra->pt_smooth_factor > 192) > + ra->pt_smooth_factor = 192; > + stage_id = ra->pt_smooth_factor >> 6; > + temp_stage = stage_id * 2; > + if (temp_stage != 0) > + temp_stage--; > + if (ra->drop > 3) > + temp_stage = 0; > + ra->pt_stage = temp_stage; > +} > + > +void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb) > +{ > + u32 *_rx_desc = (u32 *)(skb->data - sizeof(struct rtl8xxxu_rxdesc16)); > + struct rtl8xxxu_rxdesc16 *rx_desc = (struct rtl8xxxu_rxdesc16 *)_rx_desc; > + struct device *dev = &priv->udev->dev; > + struct rtl8xxxu_ra_info *ra = &priv->ra_info; > + no blank line in declaration part. > + u32 tx_rpt_len = rx_desc->pktlen & 0x3ff; > + u32 items = tx_rpt_len / TX_RPT2_ITEM_SIZE; > + u64 macid_valid = ((u64)_rx_desc[5] << 32) | _rx_desc[4]; > + u32 macid; > + u8 *rpt = skb->data; > + bool valid; > + u16 min_rpt_time = 0x927c; > + > + dev_dbg(dev, "%s: len: %d items: %d\n", __func__, tx_rpt_len, items); > + > + for (macid = 0; macid < items; macid++) { > + valid = false; > + > + if (macid < 64) > + valid = macid_valid & BIT(macid); > + > + if (valid) { > + ra->retry[0] = le16_to_cpu(*(__le16 *)rpt); > + ra->retry[1] = rpt[2]; > + ra->retry[2] = rpt[3]; > + ra->retry[3] = rpt[4]; > + ra->retry[4] = rpt[5]; > + ra->drop = rpt[6]; > + ra->total = ra->retry[0] + ra->retry[1] + ra->retry[2] + > + ra->retry[3] + ra->retry[4] + ra->drop; > + > + if (ra->total > 0) { > + if (ra->ra_stage < 5) > + rtl8188e_rate_decision(ra); > + else if (ra->ra_stage == 5) > + rtl8188e_power_training_try_state(ra); > + else /* ra->ra_stage == 6 */ > + rtl8188e_power_training_decision(ra); > + > + if (ra->ra_stage <= 5) > + ra->ra_stage++; > + else > + ra->ra_stage = 0; > + } > + } else if (macid == 0) { > + dev_warn(dev, "%s: TX report item 0 not valid\n", __func__); > + } > + > + dev_dbg(dev, "%s: valid: %d retry: %d %d %d %d %d drop: %d\n", > + __func__, valid, > + ra->retry[0], ra->retry[1], ra->retry[2], > + ra->retry[3], ra->retry[4], ra->drop); > + > + if (min_rpt_time > ra->rpt_time) > + min_rpt_time = ra->rpt_time; > + > + rpt += TX_RPT2_ITEM_SIZE; > + > + /* > + * We only use macid 0, so only the first item is relevant. > + * AP mode will use more of them if it's ever implemented. > + */ > + break; > + } > + > + if (min_rpt_time != ra->pre_min_rpt_time) { > + rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, min_rpt_time); > + ra->pre_min_rpt_time = min_rpt_time; > + } > +} > + [...] > + > int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) > { > struct ieee80211_hw *hw = priv->hw; > @@ -5823,38 +5884,46 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff > *skb) > > skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc16)); > > - phy_stats = (struct rtl8723au_phy_stats *)skb->data; > + if (rx_desc->rpt_sel) { > + skb_queue_tail(&priv->c2hcmd_queue, skb); > + schedule_work(&priv->c2hcmd_work); > + } else { > + phy_stats = (struct rtl8723au_phy_stats *)skb->data; > > - skb_pull(skb, drvinfo_sz + desc_shift); > + skb_pull(skb, drvinfo_sz + desc_shift); > > - skb_trim(skb, pkt_len); > + skb_trim(skb, pkt_len); > > - if (rx_desc->phy_stats) > - rtl8xxxu_rx_parse_phystats(priv, rx_status, phy_stats, > - rx_desc->rxmcs, (struct ieee80211_hdr *)skb- > >data, > - rx_desc->crc32 || rx_desc->icverr); > + if (rx_desc->phy_stats) > + rtl8xxxu_rx_parse_phystats( > + priv, rx_status, phy_stats, > + rx_desc->rxmcs, > + (struct ieee80211_hdr *)skb->data, > + rx_desc->crc32 || rx_desc->icverr > + ); squash this parenthesis to previous line. > > - rx_status->mactime = rx_desc->tsfl; > - rx_status->flag |= RX_FLAG_MACTIME_START; > + rx_status->mactime = rx_desc->tsfl; > + rx_status->flag |= RX_FLAG_MACTIME_START; > > - if (!rx_desc->swdec) > - rx_status->flag |= RX_FLAG_DECRYPTED; > - if (rx_desc->crc32) > - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; > - if (rx_desc->bw) > - rx_status->bw = RATE_INFO_BW_40; > + if (!rx_desc->swdec) > + rx_status->flag |= RX_FLAG_DECRYPTED; > + if (rx_desc->crc32) > + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; > + if (rx_desc->bw) > + rx_status->bw = RATE_INFO_BW_40; > > - if (rx_desc->rxht) { > - rx_status->encoding = RX_ENC_HT; > - rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; > - } else { > - rx_status->rate_idx = rx_desc->rxmcs; > - } > + if (rx_desc->rxht) { > + rx_status->encoding = RX_ENC_HT; > + rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; > + } else { > + rx_status->rate_idx = rx_desc->rxmcs; > + } > > - rx_status->freq = hw->conf.chandef.chan->center_freq; > - rx_status->band = hw->conf.chandef.chan->band; > + rx_status->freq = hw->conf.chandef.chan->center_freq; > + rx_status->band = hw->conf.chandef.chan->band; > > - ieee80211_rx_irqsafe(hw, skb); > + ieee80211_rx_irqsafe(hw, skb); > + } > > skb = next_skb; > if (skb) > [...] Only some minor comments. Thank you for the patches. -- Ping-Ke
On 15/12/2022 15:14, Ping-Ke Shih wrote: > On Tue, 2022-12-13 at 19:33 +0200, Bitterblue Smith wrote: >> Copied from the newer vendor driver, v5.2.2.4. >> >> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com> >> --- >> v2: >> - Implement suggestions from Ping-Ke Shih: >> - Add missing break in two switch statements. >> - Remove unnecessary initialisation of idx in rtl8188e_set_tx_rpt_timing(). >> --- >> .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 39 ++ >> .../realtek/rtl8xxxu/rtl8xxxu_8188e.c | 601 +++++++++++++++++- >> .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 131 +++- >> 3 files changed, 741 insertions(+), 30 deletions(-) >> >> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h >> b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h >> index 29f5dbee16b0..be9479f969b7 100644 >> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h >> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h >> > > [...] > >> + >> +static void rtl8188e_power_training_try_state(struct rtl8xxxu_ra_info *ra) >> +{ >> + ra->pt_try_state = 0; >> + switch (ra->pt_mode_ss) { >> + case 3: >> + if (ra->decision_rate >= DESC_RATE_MCS13) >> + ra->pt_try_state = 1; >> + break; >> + case 2: >> + if (ra->decision_rate >= DESC_RATE_MCS5) >> + ra->pt_try_state = 1; >> + break; >> + case 1: >> + if (ra->decision_rate >= DESC_RATE_48M) >> + ra->pt_try_state = 1; >> + break; >> + case 0: >> + if (ra->decision_rate >= DESC_RATE_11M) >> + ra->pt_try_state = 1; >> + break; >> + default: >> + ra->pt_try_state = 0; > > It seems to be 0 already because of first statement of this function. > >> + break; >> + } >> + >> + if (ra->rssi_sta_ra < 48) { >> + ra->pt_stage = 0; >> + } else if (ra->pt_try_state == 1) { >> + if ((ra->pt_stop_count >= 10) || >> + (ra->pt_pre_rssi > ra->rssi_sta_ra + 5) || >> + (ra->pt_pre_rssi < ra->rssi_sta_ra - 5) || >> + (ra->decision_rate != ra->pt_pre_rate)) { >> + if (ra->pt_stage == 0) >> + ra->pt_stage = 1; >> + else if (ra->pt_stage == 1) >> + ra->pt_stage = 3; >> + else >> + ra->pt_stage = 5; >> + >> + ra->pt_pre_rssi = ra->rssi_sta_ra; >> + ra->pt_stop_count = 0; >> + } else { >> + ra->ra_stage = 0; >> + ra->pt_stop_count++; >> + } >> + } else { >> + ra->pt_stage = 0; >> + ra->ra_stage = 0; >> + } >> + >> + ra->pt_pre_rate = ra->decision_rate; >> + >> + /* TODO: implement the "false alarm" statistics for this */ >> + /* Disable power training when noisy environment */ >> + /* if (p_dm_odm->is_disable_power_training) { */ >> + if (1) { >> + ra->pt_stage = 0; >> + ra->ra_stage = 0; >> + ra->pt_stop_count = 0; >> + } >> +} >> + >> +static void rtl8188e_power_training_decision(struct rtl8xxxu_ra_info *ra) >> +{ >> + u8 temp_stage; >> + u32 numsc; >> + u32 num_total; >> + u8 stage_id; >> + u8 j; >> + >> + numsc = 0; >> + num_total = ra->total * pt_penalty[5]; >> + for (j = 0; j <= 4; j++) { >> + numsc += ra->retry[j] * pt_penalty[j]; >> + >> + if (numsc > num_total) >> + break; >> + } >> + >> + j = j >> 1; > > j >>= 1; > >> + temp_stage = (ra->pt_stage + 1) >> 1; >> + if (temp_stage > j) >> + stage_id = temp_stage - j; >> + else >> + stage_id = 0; >> + >> + ra->pt_smooth_factor = (ra->pt_smooth_factor >> 1) + >> + (ra->pt_smooth_factor >> 2) + >> + stage_id * 16 + 2; >> + if (ra->pt_smooth_factor > 192) >> + ra->pt_smooth_factor = 192; >> + stage_id = ra->pt_smooth_factor >> 6; >> + temp_stage = stage_id * 2; >> + if (temp_stage != 0) >> + temp_stage--; >> + if (ra->drop > 3) >> + temp_stage = 0; >> + ra->pt_stage = temp_stage; >> +} >> + >> +void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb) >> +{ >> + u32 *_rx_desc = (u32 *)(skb->data - sizeof(struct rtl8xxxu_rxdesc16)); >> + struct rtl8xxxu_rxdesc16 *rx_desc = (struct rtl8xxxu_rxdesc16 *)_rx_desc; >> + struct device *dev = &priv->udev->dev; >> + struct rtl8xxxu_ra_info *ra = &priv->ra_info; >> + > > no blank line in declaration part. > >> + u32 tx_rpt_len = rx_desc->pktlen & 0x3ff; >> + u32 items = tx_rpt_len / TX_RPT2_ITEM_SIZE; >> + u64 macid_valid = ((u64)_rx_desc[5] << 32) | _rx_desc[4]; >> + u32 macid; >> + u8 *rpt = skb->data; >> + bool valid; >> + u16 min_rpt_time = 0x927c; >> + >> + dev_dbg(dev, "%s: len: %d items: %d\n", __func__, tx_rpt_len, items); >> + >> + for (macid = 0; macid < items; macid++) { >> + valid = false; >> + >> + if (macid < 64) >> + valid = macid_valid & BIT(macid); >> + >> + if (valid) { >> + ra->retry[0] = le16_to_cpu(*(__le16 *)rpt); >> + ra->retry[1] = rpt[2]; >> + ra->retry[2] = rpt[3]; >> + ra->retry[3] = rpt[4]; >> + ra->retry[4] = rpt[5]; >> + ra->drop = rpt[6]; >> + ra->total = ra->retry[0] + ra->retry[1] + ra->retry[2] + >> + ra->retry[3] + ra->retry[4] + ra->drop; >> + >> + if (ra->total > 0) { >> + if (ra->ra_stage < 5) >> + rtl8188e_rate_decision(ra); >> + else if (ra->ra_stage == 5) >> + rtl8188e_power_training_try_state(ra); >> + else /* ra->ra_stage == 6 */ >> + rtl8188e_power_training_decision(ra); >> + >> + if (ra->ra_stage <= 5) >> + ra->ra_stage++; >> + else >> + ra->ra_stage = 0; >> + } >> + } else if (macid == 0) { >> + dev_warn(dev, "%s: TX report item 0 not valid\n", __func__); >> + } >> + >> + dev_dbg(dev, "%s: valid: %d retry: %d %d %d %d %d drop: %d\n", >> + __func__, valid, >> + ra->retry[0], ra->retry[1], ra->retry[2], >> + ra->retry[3], ra->retry[4], ra->drop); >> + >> + if (min_rpt_time > ra->rpt_time) >> + min_rpt_time = ra->rpt_time; >> + >> + rpt += TX_RPT2_ITEM_SIZE; >> + >> + /* >> + * We only use macid 0, so only the first item is relevant. >> + * AP mode will use more of them if it's ever implemented. >> + */ >> + break; >> + } >> + >> + if (min_rpt_time != ra->pre_min_rpt_time) { >> + rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, min_rpt_time); >> + ra->pre_min_rpt_time = min_rpt_time; >> + } >> +} >> + > > [...] > >> + >> int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) >> { >> struct ieee80211_hw *hw = priv->hw; >> @@ -5823,38 +5884,46 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff >> *skb) >> >> skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc16)); >> >> - phy_stats = (struct rtl8723au_phy_stats *)skb->data; >> + if (rx_desc->rpt_sel) { >> + skb_queue_tail(&priv->c2hcmd_queue, skb); >> + schedule_work(&priv->c2hcmd_work); >> + } else { >> + phy_stats = (struct rtl8723au_phy_stats *)skb->data; >> >> - skb_pull(skb, drvinfo_sz + desc_shift); >> + skb_pull(skb, drvinfo_sz + desc_shift); >> >> - skb_trim(skb, pkt_len); >> + skb_trim(skb, pkt_len); >> >> - if (rx_desc->phy_stats) >> - rtl8xxxu_rx_parse_phystats(priv, rx_status, phy_stats, >> - rx_desc->rxmcs, (struct ieee80211_hdr *)skb- >>> data, >> - rx_desc->crc32 || rx_desc->icverr); >> + if (rx_desc->phy_stats) >> + rtl8xxxu_rx_parse_phystats( >> + priv, rx_status, phy_stats, >> + rx_desc->rxmcs, >> + (struct ieee80211_hdr *)skb->data, >> + rx_desc->crc32 || rx_desc->icverr >> + ); > > squash this parenthesis to previous line. > >> >> - rx_status->mactime = rx_desc->tsfl; >> - rx_status->flag |= RX_FLAG_MACTIME_START; >> + rx_status->mactime = rx_desc->tsfl; >> + rx_status->flag |= RX_FLAG_MACTIME_START; >> >> - if (!rx_desc->swdec) >> - rx_status->flag |= RX_FLAG_DECRYPTED; >> - if (rx_desc->crc32) >> - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; >> - if (rx_desc->bw) >> - rx_status->bw = RATE_INFO_BW_40; >> + if (!rx_desc->swdec) >> + rx_status->flag |= RX_FLAG_DECRYPTED; >> + if (rx_desc->crc32) >> + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; >> + if (rx_desc->bw) >> + rx_status->bw = RATE_INFO_BW_40; >> >> - if (rx_desc->rxht) { >> - rx_status->encoding = RX_ENC_HT; >> - rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; >> - } else { >> - rx_status->rate_idx = rx_desc->rxmcs; >> - } >> + if (rx_desc->rxht) { >> + rx_status->encoding = RX_ENC_HT; >> + rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; >> + } else { >> + rx_status->rate_idx = rx_desc->rxmcs; >> + } >> >> - rx_status->freq = hw->conf.chandef.chan->center_freq; >> - rx_status->band = hw->conf.chandef.chan->band; >> + rx_status->freq = hw->conf.chandef.chan->center_freq; >> + rx_status->band = hw->conf.chandef.chan->band; >> >> - ieee80211_rx_irqsafe(hw, skb); >> + ieee80211_rx_irqsafe(hw, skb); >> + } >> >> skb = next_skb; >> if (skb) >> > > [...] > > Only some minor comments. > > Thank you for the patches. > -- > Ping-Ke > I'll make the changes. Thank you for reviewing.
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 29f5dbee16b0..be9479f969b7 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -531,6 +531,7 @@ struct rtl8xxxu_txdesc40 { #define TXDESC32_CTS_SELF_ENABLE BIT(11) #define TXDESC32_RTS_CTS_ENABLE BIT(12) #define TXDESC32_HW_RTS_ENABLE BIT(13) +#define TXDESC32_PT_STAGE_MASK GENMASK(17, 15) #define TXDESC_PRIME_CH_OFF_LOWER BIT(20) #define TXDESC_PRIME_CH_OFF_UPPER BIT(21) #define TXDESC32_SHORT_PREAMBLE BIT(24) @@ -1376,6 +1377,39 @@ struct rtl8xxxu_ra_report { u8 desc_rate; }; +struct rtl8xxxu_ra_info { + u8 rate_id; + u32 rate_mask; + u32 ra_use_rate; + u8 rate_sgi; + u8 rssi_sta_ra; /* Percentage */ + u8 pre_rssi_sta_ra; + u8 sgi_enable; + u8 decision_rate; + u8 pre_rate; + u8 highest_rate; + u8 lowest_rate; + u32 nsc_up; + u32 nsc_down; + u32 total; + u16 retry[5]; + u16 drop; + u16 rpt_time; + u16 pre_min_rpt_time; + u8 dynamic_tx_rpt_timing_counter; + u8 ra_waiting_counter; + u8 ra_pending_counter; + u8 ra_drop_after_down; + u8 pt_try_state; /* 0 trying state, 1 for decision state */ + u8 pt_stage; /* 0~6 */ + u8 pt_stop_count; /* Stop PT counter */ + u8 pt_pre_rate; /* if rate change do PT */ + u8 pt_pre_rssi; /* if RSSI change 5% do PT */ + u8 pt_mode_ss; /* decide which rate should do PT */ + u8 ra_stage; /* StageRA, decide how many times RA will be done between PT */ + u8 pt_smooth_factor; +}; + #define CFO_TH_XTAL_HIGH 20 /* kHz */ #define CFO_TH_XTAL_LOW 10 /* kHz */ #define CFO_TH_ATC 80 /* kHz */ @@ -1509,6 +1543,7 @@ struct rtl8xxxu_priv { struct rtl8xxxu_btcoex bt_coex; struct rtl8xxxu_ra_report ra_report; struct rtl8xxxu_cfo_tracking cfo_tracking; + struct rtl8xxxu_ra_info ra_info; }; struct rtl8xxxu_rx_urb { @@ -1684,6 +1719,10 @@ void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv); void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap); void rtl8188f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap); s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt); +void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt, + u8 rate, u8 sgi, u8 bw); +void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra); +void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb); extern struct rtl8xxxu_fileops rtl8188fu_fops; extern struct rtl8xxxu_fileops rtl8188eu_fops; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c index 587555da9bce..f5693b2c1be6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c @@ -280,6 +280,132 @@ static const struct rtl8xxxu_rfregval rtl8188eu_radioa_init_table[] = { {0xff, 0xffffffff} }; +#define PERENTRY 23 +#define RETRYSIZE 5 +#define RATESIZE 28 +#define TX_RPT2_ITEM_SIZE 8 + +static const u8 retry_penalty[PERENTRY][RETRYSIZE + 1] = { + {5, 4, 3, 2, 0, 3}, /* 92 , idx=0 */ + {6, 5, 4, 3, 0, 4}, /* 86 , idx=1 */ + {6, 5, 4, 2, 0, 4}, /* 81 , idx=2 */ + {8, 7, 6, 4, 0, 6}, /* 75 , idx=3 */ + {10, 9, 8, 6, 0, 8}, /* 71 , idx=4 */ + {10, 9, 8, 4, 0, 8}, /* 66 , idx=5 */ + {10, 9, 8, 2, 0, 8}, /* 62 , idx=6 */ + {10, 9, 8, 0, 0, 8}, /* 59 , idx=7 */ + {18, 17, 16, 8, 0, 16}, /* 53 , idx=8 */ + {26, 25, 24, 16, 0, 24}, /* 50 , idx=9 */ + {34, 33, 32, 24, 0, 32}, /* 47 , idx=0x0a */ + {34, 31, 28, 20, 0, 32}, /* 43 , idx=0x0b */ + {34, 31, 27, 18, 0, 32}, /* 40 , idx=0x0c */ + {34, 31, 26, 16, 0, 32}, /* 37 , idx=0x0d */ + {34, 30, 22, 16, 0, 32}, /* 32 , idx=0x0e */ + {34, 30, 24, 16, 0, 32}, /* 26 , idx=0x0f */ + {49, 46, 40, 16, 0, 48}, /* 20 , idx=0x10 */ + {49, 45, 32, 0, 0, 48}, /* 17 , idx=0x11 */ + {49, 45, 22, 18, 0, 48}, /* 15 , idx=0x12 */ + {49, 40, 24, 16, 0, 48}, /* 12 , idx=0x13 */ + {49, 32, 18, 12, 0, 48}, /* 9 , idx=0x14 */ + {49, 22, 18, 14, 0, 48}, /* 6 , idx=0x15 */ + {49, 16, 16, 0, 0, 48} /* 3, idx=0x16 */ +}; + +static const u8 retry_penalty_up[RETRYSIZE + 1] = {49, 44, 16, 16, 0, 48}; /* 12% for rate up */ + +static const u8 pt_penalty[RETRYSIZE + 1] = {34, 31, 30, 24, 0, 32}; + +static const u8 retry_penalty_idx_normal[2][RATESIZE] = { + { /* RSSI>TH */ + 4, 4, 4, 5, + 4, 4, 5, 7, 7, 7, 8, 0x0a, + 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d, + 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f + }, + { /* RSSI<TH */ + 0x0a, 0x0a, 0x0b, 0x0c, + 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x13, 0x13, + 9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13 + } +}; + +static const u8 retry_penalty_idx_cut_i[2][RATESIZE] = { + { /* RSSI>TH */ + 4, 4, 4, 5, + 4, 4, 5, 7, 7, 7, 8, 0x0a, + 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d, + 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f + }, + { /* RSSI<TH */ + 0x0a, 0x0a, 0x0b, 0x0c, + 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13, + 0x06, 0x07, 0x08, 0x0d, 0x0e, 0x11, 0x11, 0x11, + 9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13 + } +}; + +static const u8 retry_penalty_up_idx_normal[RATESIZE] = { + 0x0c, 0x0d, 0x0d, 0x0f, + 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14, + 0x0f, 0x10, 0x10, 0x12, 0x12, 0x13, 0x14, 0x15, + 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15 +}; + +static const u8 retry_penalty_up_idx_cut_i[RATESIZE] = { + 0x0c, 0x0d, 0x0d, 0x0f, + 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14, + 0x0b, 0x0b, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, + 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15 +}; + +static const u8 rssi_threshold[RATESIZE] = { + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x24, 0x26, 0x2a, + 0x18, 0x1a, 0x1d, 0x1f, 0x21, 0x27, 0x29, 0x2a, + 0, 0, 0, 0x1f, 0x23, 0x28, 0x2a, 0x2c +}; + +static const u16 n_threshold_high[RATESIZE] = { + 4, 4, 8, 16, + 24, 36, 48, 72, 96, 144, 192, 216, + 60, 80, 100, 160, 240, 400, 600, 800, + 300, 320, 480, 720, 1000, 1200, 1600, 2000 +}; + +static const u16 n_threshold_low[RATESIZE] = { + 2, 2, 4, 8, + 12, 18, 24, 36, 48, 72, 96, 108, + 30, 40, 50, 80, 120, 200, 300, 400, + 150, 160, 240, 360, 500, 600, 800, 1000 +}; + +static const u8 trying_necessary[RATESIZE] = { + 2, 2, 2, 2, + 2, 2, 3, 3, 4, 4, 5, 7, + 4, 4, 7, 10, 10, 12, 12, 18, + 5, 7, 7, 8, 11, 18, 36, 60 +}; + +static const u8 dropping_necessary[RATESIZE] = { + 1, 1, 1, 1, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 5, 6, 7, 8, 9, 10, 11, 12 +}; + +static const u8 pending_for_rate_up_fail[5] = {2, 10, 24, 40, 60}; + +static const u16 dynamic_tx_rpt_timing[6] = { + 0x186a, 0x30d4, 0x493e, 0x61a8, 0x7a12, 0x927c /* 200ms-1200ms */ +}; + +enum rtl8188e_tx_rpt_timing { + DEFAULT_TIMING = 0, + INCREASE_TIMING, + DECREASE_TIMING +}; + static int rtl8188eu_identify_chip(struct rtl8xxxu_priv *priv) { struct device *dev = &priv->udev->dev; @@ -1239,6 +1365,479 @@ static s8 rtl8188e_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt) return rx_pwr_all; } +static void rtl8188e_set_tx_rpt_timing(struct rtl8xxxu_ra_info *ra, u8 timing) +{ + u8 idx; + + for (idx = 0; idx < 5; idx++) + if (dynamic_tx_rpt_timing[idx] == ra->rpt_time) + break; + + if (timing == DEFAULT_TIMING) { + idx = 0; /* 200ms */ + } else if (timing == INCREASE_TIMING) { + if (idx < 5) + idx++; + } else if (timing == DECREASE_TIMING) { + if (idx > 0) + idx--; + } + + ra->rpt_time = dynamic_tx_rpt_timing[idx]; +} + +static void rtl8188e_rate_down(struct rtl8xxxu_ra_info *ra) +{ + u8 rate_id = ra->pre_rate; + u8 lowest_rate = ra->lowest_rate; + u8 highest_rate = ra->highest_rate; + s8 i; + + if (rate_id > highest_rate) { + rate_id = highest_rate; + } else if (ra->rate_sgi) { + ra->rate_sgi = 0; + } else if (rate_id > lowest_rate) { + if (rate_id > 0) { + for (i = rate_id - 1; i >= lowest_rate; i--) { + if (ra->ra_use_rate & BIT(i)) { + rate_id = i; + goto rate_down_finish; + } + } + } + } else if (rate_id <= lowest_rate) { + rate_id = lowest_rate; + } + +rate_down_finish: + if (ra->ra_waiting_counter == 1) { + ra->ra_waiting_counter++; + ra->ra_pending_counter++; + } else if (ra->ra_waiting_counter > 1) { + ra->ra_waiting_counter = 0; + ra->ra_pending_counter = 0; + } + + if (ra->ra_pending_counter >= 4) + ra->ra_pending_counter = 4; + + ra->ra_drop_after_down = 1; + + ra->decision_rate = rate_id; + + rtl8188e_set_tx_rpt_timing(ra, DECREASE_TIMING); +} + +static void rtl8188e_rate_up(struct rtl8xxxu_ra_info *ra) +{ + u8 rate_id = ra->pre_rate; + u8 highest_rate = ra->highest_rate; + u8 i; + + if (ra->ra_waiting_counter == 1) { + ra->ra_waiting_counter = 0; + ra->ra_pending_counter = 0; + } else if (ra->ra_waiting_counter > 1) { + ra->pre_rssi_sta_ra = ra->rssi_sta_ra; + goto rate_up_finish; + } + + rtl8188e_set_tx_rpt_timing(ra, DEFAULT_TIMING); + + if (rate_id < highest_rate) { + for (i = rate_id + 1; i <= highest_rate; i++) { + if (ra->ra_use_rate & BIT(i)) { + rate_id = i; + goto rate_up_finish; + } + } + } else if (rate_id == highest_rate) { + if (ra->sgi_enable && !ra->rate_sgi) + ra->rate_sgi = 1; + else if (!ra->sgi_enable) + ra->rate_sgi = 0; + } else { /* rate_id > ra->highest_rate */ + rate_id = highest_rate; + } + +rate_up_finish: + if (ra->ra_waiting_counter == (4 + pending_for_rate_up_fail[ra->ra_pending_counter])) + ra->ra_waiting_counter = 0; + else + ra->ra_waiting_counter++; + + ra->decision_rate = rate_id; +} + +static void rtl8188e_reset_ra_counter(struct rtl8xxxu_ra_info *ra) +{ + u8 rate_id = ra->decision_rate; + + ra->nsc_up = (n_threshold_high[rate_id] + n_threshold_low[rate_id]) >> 1; + ra->nsc_down = (n_threshold_high[rate_id] + n_threshold_low[rate_id]) >> 1; +} + +static void rtl8188e_rate_decision(struct rtl8xxxu_ra_info *ra) +{ + struct rtl8xxxu_priv *priv = container_of(ra, struct rtl8xxxu_priv, ra_info); + const u8 *retry_penalty_idx_0; + const u8 *retry_penalty_idx_1; + const u8 *retry_penalty_up_idx; + u8 rate_id, penalty_id1, penalty_id2; + int i; + + if (ra->total == 0) + return; + + if (ra->ra_drop_after_down) { + ra->ra_drop_after_down--; + + rtl8188e_reset_ra_counter(ra); + + return; + } + + if (priv->chip_cut == 8) { /* cut I */ + retry_penalty_idx_0 = retry_penalty_idx_cut_i[0]; + retry_penalty_idx_1 = retry_penalty_idx_cut_i[1]; + retry_penalty_up_idx = retry_penalty_up_idx_cut_i; + } else { + retry_penalty_idx_0 = retry_penalty_idx_normal[0]; + retry_penalty_idx_1 = retry_penalty_idx_normal[1]; + retry_penalty_up_idx = retry_penalty_up_idx_normal; + } + + if (ra->rssi_sta_ra < (ra->pre_rssi_sta_ra - 3) || + ra->rssi_sta_ra > (ra->pre_rssi_sta_ra + 3)) { + ra->pre_rssi_sta_ra = ra->rssi_sta_ra; + ra->ra_waiting_counter = 0; + ra->ra_pending_counter = 0; + } + + /* Start RA decision */ + if (ra->pre_rate > ra->highest_rate) + rate_id = ra->highest_rate; + else + rate_id = ra->pre_rate; + + /* rate down */ + if (ra->rssi_sta_ra > rssi_threshold[rate_id]) + penalty_id1 = retry_penalty_idx_0[rate_id]; + else + penalty_id1 = retry_penalty_idx_1[rate_id]; + + for (i = 0; i < 5; i++) + ra->nsc_down += ra->retry[i] * retry_penalty[penalty_id1][i]; + + if (ra->nsc_down > (ra->total * retry_penalty[penalty_id1][5])) + ra->nsc_down -= ra->total * retry_penalty[penalty_id1][5]; + else + ra->nsc_down = 0; + + /* rate up */ + penalty_id2 = retry_penalty_up_idx[rate_id]; + + for (i = 0; i < 5; i++) + ra->nsc_up += ra->retry[i] * retry_penalty[penalty_id2][i]; + + if (ra->nsc_up > (ra->total * retry_penalty[penalty_id2][5])) + ra->nsc_up -= ra->total * retry_penalty[penalty_id2][5]; + else + ra->nsc_up = 0; + + if (ra->nsc_down < n_threshold_low[rate_id] || + ra->drop > dropping_necessary[rate_id]) { + rtl8188e_rate_down(ra); + + rtl8xxxu_update_ra_report(&priv->ra_report, ra->decision_rate, + ra->rate_sgi, priv->ra_report.txrate.bw); + } else if (ra->nsc_up > n_threshold_high[rate_id]) { + rtl8188e_rate_up(ra); + + rtl8xxxu_update_ra_report(&priv->ra_report, ra->decision_rate, + ra->rate_sgi, priv->ra_report.txrate.bw); + } + + if (ra->decision_rate == ra->pre_rate) + ra->dynamic_tx_rpt_timing_counter++; + else + ra->dynamic_tx_rpt_timing_counter = 0; + + if (ra->dynamic_tx_rpt_timing_counter >= 4) { + /* Rate didn't change 4 times, extend RPT timing */ + rtl8188e_set_tx_rpt_timing(ra, INCREASE_TIMING); + ra->dynamic_tx_rpt_timing_counter = 0; + } + + ra->pre_rate = ra->decision_rate; + + rtl8188e_reset_ra_counter(ra); +} + +static void rtl8188e_power_training_try_state(struct rtl8xxxu_ra_info *ra) +{ + ra->pt_try_state = 0; + switch (ra->pt_mode_ss) { + case 3: + if (ra->decision_rate >= DESC_RATE_MCS13) + ra->pt_try_state = 1; + break; + case 2: + if (ra->decision_rate >= DESC_RATE_MCS5) + ra->pt_try_state = 1; + break; + case 1: + if (ra->decision_rate >= DESC_RATE_48M) + ra->pt_try_state = 1; + break; + case 0: + if (ra->decision_rate >= DESC_RATE_11M) + ra->pt_try_state = 1; + break; + default: + ra->pt_try_state = 0; + break; + } + + if (ra->rssi_sta_ra < 48) { + ra->pt_stage = 0; + } else if (ra->pt_try_state == 1) { + if ((ra->pt_stop_count >= 10) || + (ra->pt_pre_rssi > ra->rssi_sta_ra + 5) || + (ra->pt_pre_rssi < ra->rssi_sta_ra - 5) || + (ra->decision_rate != ra->pt_pre_rate)) { + if (ra->pt_stage == 0) + ra->pt_stage = 1; + else if (ra->pt_stage == 1) + ra->pt_stage = 3; + else + ra->pt_stage = 5; + + ra->pt_pre_rssi = ra->rssi_sta_ra; + ra->pt_stop_count = 0; + } else { + ra->ra_stage = 0; + ra->pt_stop_count++; + } + } else { + ra->pt_stage = 0; + ra->ra_stage = 0; + } + + ra->pt_pre_rate = ra->decision_rate; + + /* TODO: implement the "false alarm" statistics for this */ + /* Disable power training when noisy environment */ + /* if (p_dm_odm->is_disable_power_training) { */ + if (1) { + ra->pt_stage = 0; + ra->ra_stage = 0; + ra->pt_stop_count = 0; + } +} + +static void rtl8188e_power_training_decision(struct rtl8xxxu_ra_info *ra) +{ + u8 temp_stage; + u32 numsc; + u32 num_total; + u8 stage_id; + u8 j; + + numsc = 0; + num_total = ra->total * pt_penalty[5]; + for (j = 0; j <= 4; j++) { + numsc += ra->retry[j] * pt_penalty[j]; + + if (numsc > num_total) + break; + } + + j = j >> 1; + temp_stage = (ra->pt_stage + 1) >> 1; + if (temp_stage > j) + stage_id = temp_stage - j; + else + stage_id = 0; + + ra->pt_smooth_factor = (ra->pt_smooth_factor >> 1) + + (ra->pt_smooth_factor >> 2) + + stage_id * 16 + 2; + if (ra->pt_smooth_factor > 192) + ra->pt_smooth_factor = 192; + stage_id = ra->pt_smooth_factor >> 6; + temp_stage = stage_id * 2; + if (temp_stage != 0) + temp_stage--; + if (ra->drop > 3) + temp_stage = 0; + ra->pt_stage = temp_stage; +} + +void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb) +{ + u32 *_rx_desc = (u32 *)(skb->data - sizeof(struct rtl8xxxu_rxdesc16)); + struct rtl8xxxu_rxdesc16 *rx_desc = (struct rtl8xxxu_rxdesc16 *)_rx_desc; + struct device *dev = &priv->udev->dev; + struct rtl8xxxu_ra_info *ra = &priv->ra_info; + + u32 tx_rpt_len = rx_desc->pktlen & 0x3ff; + u32 items = tx_rpt_len / TX_RPT2_ITEM_SIZE; + u64 macid_valid = ((u64)_rx_desc[5] << 32) | _rx_desc[4]; + u32 macid; + u8 *rpt = skb->data; + bool valid; + u16 min_rpt_time = 0x927c; + + dev_dbg(dev, "%s: len: %d items: %d\n", __func__, tx_rpt_len, items); + + for (macid = 0; macid < items; macid++) { + valid = false; + + if (macid < 64) + valid = macid_valid & BIT(macid); + + if (valid) { + ra->retry[0] = le16_to_cpu(*(__le16 *)rpt); + ra->retry[1] = rpt[2]; + ra->retry[2] = rpt[3]; + ra->retry[3] = rpt[4]; + ra->retry[4] = rpt[5]; + ra->drop = rpt[6]; + ra->total = ra->retry[0] + ra->retry[1] + ra->retry[2] + + ra->retry[3] + ra->retry[4] + ra->drop; + + if (ra->total > 0) { + if (ra->ra_stage < 5) + rtl8188e_rate_decision(ra); + else if (ra->ra_stage == 5) + rtl8188e_power_training_try_state(ra); + else /* ra->ra_stage == 6 */ + rtl8188e_power_training_decision(ra); + + if (ra->ra_stage <= 5) + ra->ra_stage++; + else + ra->ra_stage = 0; + } + } else if (macid == 0) { + dev_warn(dev, "%s: TX report item 0 not valid\n", __func__); + } + + dev_dbg(dev, "%s: valid: %d retry: %d %d %d %d %d drop: %d\n", + __func__, valid, + ra->retry[0], ra->retry[1], ra->retry[2], + ra->retry[3], ra->retry[4], ra->drop); + + if (min_rpt_time > ra->rpt_time) + min_rpt_time = ra->rpt_time; + + rpt += TX_RPT2_ITEM_SIZE; + + /* + * We only use macid 0, so only the first item is relevant. + * AP mode will use more of them if it's ever implemented. + */ + break; + } + + if (min_rpt_time != ra->pre_min_rpt_time) { + rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, min_rpt_time); + ra->pre_min_rpt_time = min_rpt_time; + } +} + +static void rtl8188e_arfb_refresh(struct rtl8xxxu_ra_info *ra) +{ + s8 i; + + ra->ra_use_rate = ra->rate_mask; + + /* Highest rate */ + if (ra->ra_use_rate) { + for (i = RATESIZE; i >= 0; i--) { + if (ra->ra_use_rate & BIT(i)) { + ra->highest_rate = i; + break; + } + } + } else { + ra->highest_rate = 0; + } + + /* Lowest rate */ + if (ra->ra_use_rate) { + for (i = 0; i < RATESIZE; i++) { + if (ra->ra_use_rate & BIT(i)) { + ra->lowest_rate = i; + break; + } + } + } else { + ra->lowest_rate = 0; + } + + if (ra->highest_rate > DESC_RATE_MCS7) + ra->pt_mode_ss = 3; + else if (ra->highest_rate > DESC_RATE_54M) + ra->pt_mode_ss = 2; + else if (ra->highest_rate > DESC_RATE_11M) + ra->pt_mode_ss = 1; + else + ra->pt_mode_ss = 0; +} + +static void +rtl8188e_update_rate_mask(struct rtl8xxxu_priv *priv, + u32 ramask, u8 rateid, int sgi, int txbw_40mhz) +{ + struct rtl8xxxu_ra_info *ra = &priv->ra_info; + + ra->rate_id = rateid; + ra->rate_mask = ramask; + ra->sgi_enable = sgi; + + rtl8188e_arfb_refresh(ra); +} + +void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra) +{ + ra->decision_rate = DESC_RATE_MCS7; + ra->pre_rate = DESC_RATE_MCS7; + ra->highest_rate = DESC_RATE_MCS7; + ra->lowest_rate = 0; + ra->rate_id = 0; + ra->rate_mask = 0xfffff; + ra->rssi_sta_ra = 0; + ra->pre_rssi_sta_ra = 0; + ra->sgi_enable = 0; + ra->ra_use_rate = 0xfffff; + ra->nsc_down = (n_threshold_high[DESC_RATE_MCS7] + n_threshold_low[DESC_RATE_MCS7]) / 2; + ra->nsc_up = (n_threshold_high[DESC_RATE_MCS7] + n_threshold_low[DESC_RATE_MCS7]) / 2; + ra->rate_sgi = 0; + ra->rpt_time = 0x927c; + ra->drop = 0; + ra->retry[0] = 0; + ra->retry[1] = 0; + ra->retry[2] = 0; + ra->retry[3] = 0; + ra->retry[4] = 0; + ra->total = 0; + ra->ra_waiting_counter = 0; + ra->ra_pending_counter = 0; + ra->ra_drop_after_down = 0; + + ra->pt_try_state = 0; + ra->pt_stage = 5; + ra->pt_smooth_factor = 192; + ra->pt_stop_count = 0; + ra->pt_pre_rate = 0; + ra->pt_pre_rssi = 0; + ra->pt_mode_ss = 0; + ra->ra_stage = 0; +} + struct rtl8xxxu_fileops rtl8188eu_fops = { .identify_chip = rtl8188eu_identify_chip, .parse_efuse = rtl8188eu_parse_efuse, @@ -1258,7 +1857,7 @@ struct rtl8xxxu_fileops rtl8188eu_fops = { .disable_rf = rtl8188e_disable_rf, .usb_quirks = rtl8188e_usb_quirks, .set_tx_power = rtl8188f_set_tx_power, - .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, + .update_rate_mask = rtl8188e_update_rate_mask, .report_connect = rtl8xxxu_gen2_report_connect, .fill_txdesc = rtl8xxxu_fill_txdesc_v3, .set_crystal_cap = rtl8188f_set_crystal_cap, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index daf70a6bc380..5b969759859c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -3982,7 +3982,25 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) * Enable TX report and TX report timer for 8723bu/8188eu/... */ if (fops->has_tx_report) { + /* + * The RTL8188EU has two types of TX reports: + * rpt_sel=1: + * One report for one frame. We can use this for frames + * with IEEE80211_TX_CTL_REQ_TX_STATUS. + * rpt_sel=2: + * One report for many frames transmitted over a period + * of time. (This is what REG_TX_REPORT_TIME is for.) The + * report includes the number of frames transmitted + * successfully, and the number of unsuccessful + * transmissions. We use this for software rate control. + * + * Bit 0 of REG_TX_REPORT_CTRL is required for both types. + * Bit 1 (TX_REPORT_CTRL_TIMER_ENABLE) is required for + * type 2. + */ val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL); + if (priv->rtl_chip == RTL8188E) + val8 |= BIT(0); val8 |= TX_REPORT_CTRL_TIMER_ENABLE; rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8); /* Set MAX RPT MACID */ @@ -4273,6 +4291,9 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) priv->cfo_tracking.crystal_cap = priv->default_crystal_cap; } + if (priv->rtl_chip == RTL8188E) + rtl8188e_ra_info_init_all(&priv->ra_info); + exit: return ret; } @@ -4636,8 +4657,8 @@ static void rtl8xxxu_set_aifs(struct rtl8xxxu_priv *priv, u8 slot_time) } } -static void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt, - u8 rate, u8 sgi, u8 bw) +void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt, + u8 rate, u8 sgi, u8 bw) { u8 mcs, nss; @@ -5121,6 +5142,7 @@ rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; + struct rtl8xxxu_ra_info *ra = &priv->ra_info; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; u32 rate; @@ -5136,9 +5158,10 @@ rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); if (ieee80211_is_data(hdr->frame_control)) { - rate = DESC_RATE_MCS7; /* TODO: software rate control */ + rate = ra->decision_rate; tx_desc->txdw5 = cpu_to_le32(rate); tx_desc->txdw4 |= cpu_to_le32(TXDESC32_USE_DRIVER_RATE); + tx_desc->txdw4 |= le32_encode_bits(ra->pt_stage, TXDESC32_PT_STAGE_MASK); /* Data/RTS rate FB limit */ tx_desc->txdw5 |= cpu_to_le32(0x0001ff00); } @@ -5177,7 +5200,7 @@ rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, if (short_preamble) tx_desc->txdw4 |= cpu_to_le32(TXDESC32_SHORT_PREAMBLE); - if (sgi) + if (sgi && ra->rate_sgi) tx_desc->txdw5 |= cpu_to_le32(TXDESC32_SHORT_GI); /* @@ -5768,6 +5791,44 @@ static void rtl8723bu_handle_c2h(struct rtl8xxxu_priv *priv, schedule_work(&priv->c2hcmd_work); } +static void rtl8188e_c2hcmd_callback(struct work_struct *work) +{ + struct rtl8xxxu_priv *priv = container_of(work, struct rtl8xxxu_priv, c2hcmd_work); + struct device *dev = &priv->udev->dev; + struct sk_buff *skb = NULL; + struct rtl8xxxu_rxdesc16 *rx_desc; + + while (!skb_queue_empty(&priv->c2hcmd_queue)) { + skb = skb_dequeue(&priv->c2hcmd_queue); + + rx_desc = (struct rtl8xxxu_rxdesc16 *)(skb->data - sizeof(struct rtl8xxxu_rxdesc16)); + + switch (rx_desc->rpt_sel) { + case 1: + dev_dbg(dev, "C2H TX report type 1\n"); + + break; + case 2: + dev_dbg(dev, "C2H TX report type 2\n"); + + rtl8188e_handle_ra_tx_report2(priv, skb); + + break; + case 3: + dev_dbg(dev, "C2H USB interrupt report\n"); + + break; + default: + dev_warn(dev, "%s: rpt_sel should not be %d\n", + __func__, rx_desc->rpt_sel); + + break; + } + + dev_kfree_skb(skb); + } +} + int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) { struct ieee80211_hw *hw = priv->hw; @@ -5823,38 +5884,46 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc16)); - phy_stats = (struct rtl8723au_phy_stats *)skb->data; + if (rx_desc->rpt_sel) { + skb_queue_tail(&priv->c2hcmd_queue, skb); + schedule_work(&priv->c2hcmd_work); + } else { + phy_stats = (struct rtl8723au_phy_stats *)skb->data; - skb_pull(skb, drvinfo_sz + desc_shift); + skb_pull(skb, drvinfo_sz + desc_shift); - skb_trim(skb, pkt_len); + skb_trim(skb, pkt_len); - if (rx_desc->phy_stats) - rtl8xxxu_rx_parse_phystats(priv, rx_status, phy_stats, - rx_desc->rxmcs, (struct ieee80211_hdr *)skb->data, - rx_desc->crc32 || rx_desc->icverr); + if (rx_desc->phy_stats) + rtl8xxxu_rx_parse_phystats( + priv, rx_status, phy_stats, + rx_desc->rxmcs, + (struct ieee80211_hdr *)skb->data, + rx_desc->crc32 || rx_desc->icverr + ); - rx_status->mactime = rx_desc->tsfl; - rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->mactime = rx_desc->tsfl; + rx_status->flag |= RX_FLAG_MACTIME_START; - if (!rx_desc->swdec) - rx_status->flag |= RX_FLAG_DECRYPTED; - if (rx_desc->crc32) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (rx_desc->bw) - rx_status->bw = RATE_INFO_BW_40; + if (!rx_desc->swdec) + rx_status->flag |= RX_FLAG_DECRYPTED; + if (rx_desc->crc32) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (rx_desc->bw) + rx_status->bw = RATE_INFO_BW_40; - if (rx_desc->rxht) { - rx_status->encoding = RX_ENC_HT; - rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; - } else { - rx_status->rate_idx = rx_desc->rxmcs; - } + if (rx_desc->rxht) { + rx_status->encoding = RX_ENC_HT; + rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; + } else { + rx_status->rate_idx = rx_desc->rxmcs; + } - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; - ieee80211_rx_irqsafe(hw, skb); + ieee80211_rx_irqsafe(hw, skb); + } skb = next_skb; if (skb) @@ -6941,7 +7010,6 @@ static int rtl8xxxu_probe(struct usb_interface *interface, spin_lock_init(&priv->rx_urb_lock); INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback); - INIT_WORK(&priv->c2hcmd_work, rtl8xxxu_c2hcmd_callback); skb_queue_head_init(&priv->c2hcmd_queue); usb_set_intfdata(interface, hw); @@ -6959,6 +7027,11 @@ static int rtl8xxxu_probe(struct usb_interface *interface, hw->wiphy->available_antennas_tx = BIT(priv->tx_paths) - 1; hw->wiphy->available_antennas_rx = BIT(priv->rx_paths) - 1; + if (priv->rtl_chip == RTL8188E) + INIT_WORK(&priv->c2hcmd_work, rtl8188e_c2hcmd_callback); + else + INIT_WORK(&priv->c2hcmd_work, rtl8xxxu_c2hcmd_callback); + ret = rtl8xxxu_read_efuse(priv); if (ret) { dev_err(&udev->dev, "Fatal - failed to read EFuse\n");
Copied from the newer vendor driver, v5.2.2.4. Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com> --- v2: - Implement suggestions from Ping-Ke Shih: - Add missing break in two switch statements. - Remove unnecessary initialisation of idx in rtl8188e_set_tx_rpt_timing(). --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 39 ++ .../realtek/rtl8xxxu/rtl8xxxu_8188e.c | 601 +++++++++++++++++- .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 131 +++- 3 files changed, 741 insertions(+), 30 deletions(-)