root/drivers/net/wireless/realtek/rtw88/fw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtw_fw_c2h_cmd_handle_ext
  2. rtw_fw_c2h_cmd_handle
  3. rtw_fw_c2h_cmd_rx_irqsafe
  4. rtw_fw_send_h2c_command
  5. rtw_fw_send_h2c_packet
  6. rtw_fw_send_general_info
  7. rtw_fw_send_phydm_info
  8. rtw_fw_do_iqk
  9. rtw_fw_query_bt_info
  10. rtw_fw_wl_ch_info
  11. rtw_fw_query_bt_mp_info
  12. rtw_fw_force_bt_tx_power
  13. rtw_fw_bt_ignore_wlan_action
  14. rtw_fw_coex_tdma_type
  15. rtw_fw_bt_wifi_control
  16. rtw_fw_send_rssi_info
  17. rtw_fw_send_ra_info
  18. rtw_fw_media_status_report
  19. rtw_fw_set_pwr_mode
  20. rtw_get_rsvd_page_location
  21. rtw_send_rsvd_page_h2c
  22. rtw_beacon_get
  23. rtw_get_rsvd_page_skb
  24. rtw_fill_rsvd_page_desc
  25. rtw_len_to_page
  26. rtw_rsvd_page_list_to_buf
  27. rtw_add_rsvd_page
  28. rtw_reset_rsvd_page
  29. rtw_fw_write_data_rsvd_page
  30. rtw_download_drv_rsvd_page
  31. rtw_build_rsvd_page
  32. rtw_download_beacon
  33. rtw_fw_download_rsvd_page
  34. rtw_dump_drv_rsvd_page

   1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2 /* Copyright(c) 2018-2019  Realtek Corporation
   3  */
   4 
   5 #include "main.h"
   6 #include "coex.h"
   7 #include "fw.h"
   8 #include "tx.h"
   9 #include "reg.h"
  10 #include "debug.h"
  11 
  12 static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
  13                                       struct sk_buff *skb)
  14 {
  15         struct rtw_c2h_cmd *c2h;
  16         u8 sub_cmd_id;
  17 
  18         c2h = get_c2h_from_skb(skb);
  19         sub_cmd_id = c2h->payload[0];
  20 
  21         switch (sub_cmd_id) {
  22         case C2H_CCX_RPT:
  23                 rtw_tx_report_handle(rtwdev, skb);
  24                 break;
  25         default:
  26                 break;
  27         }
  28 }
  29 
  30 void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
  31 {
  32         struct rtw_c2h_cmd *c2h;
  33         u32 pkt_offset;
  34         u8 len;
  35 
  36         pkt_offset = *((u32 *)skb->cb);
  37         c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
  38         len = skb->len - pkt_offset - 2;
  39 
  40         mutex_lock(&rtwdev->mutex);
  41 
  42         switch (c2h->id) {
  43         case C2H_BT_INFO:
  44                 rtw_coex_bt_info_notify(rtwdev, c2h->payload, len);
  45                 break;
  46         case C2H_WLAN_INFO:
  47                 rtw_coex_wl_fwdbginfo_notify(rtwdev, c2h->payload, len);
  48                 break;
  49         case C2H_HALMAC:
  50                 rtw_fw_c2h_cmd_handle_ext(rtwdev, skb);
  51                 break;
  52         default:
  53                 break;
  54         }
  55 
  56         mutex_unlock(&rtwdev->mutex);
  57 }
  58 
  59 void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
  60                                struct sk_buff *skb)
  61 {
  62         struct rtw_c2h_cmd *c2h;
  63         u8 len;
  64 
  65         c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
  66         len = skb->len - pkt_offset - 2;
  67         *((u32 *)skb->cb) = pkt_offset;
  68 
  69         rtw_dbg(rtwdev, RTW_DBG_FW, "recv C2H, id=0x%02x, seq=0x%02x, len=%d\n",
  70                 c2h->id, c2h->seq, len);
  71 
  72         switch (c2h->id) {
  73         case C2H_BT_MP_INFO:
  74                 rtw_coex_info_response(rtwdev, skb);
  75                 break;
  76         default:
  77                 /* pass offset for further operation */
  78                 *((u32 *)skb->cb) = pkt_offset;
  79                 skb_queue_tail(&rtwdev->c2h_queue, skb);
  80                 ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work);
  81                 break;
  82         }
  83 }
  84 EXPORT_SYMBOL(rtw_fw_c2h_cmd_rx_irqsafe);
  85 
  86 static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
  87                                     u8 *h2c)
  88 {
  89         u8 box;
  90         u8 box_state;
  91         u32 box_reg, box_ex_reg;
  92         u32 h2c_wait;
  93         int idx;
  94 
  95         rtw_dbg(rtwdev, RTW_DBG_FW,
  96                 "send H2C content %02x%02x%02x%02x %02x%02x%02x%02x\n",
  97                 h2c[3], h2c[2], h2c[1], h2c[0],
  98                 h2c[7], h2c[6], h2c[5], h2c[4]);
  99 
 100         spin_lock(&rtwdev->h2c.lock);
 101 
 102         box = rtwdev->h2c.last_box_num;
 103         switch (box) {
 104         case 0:
 105                 box_reg = REG_HMEBOX0;
 106                 box_ex_reg = REG_HMEBOX0_EX;
 107                 break;
 108         case 1:
 109                 box_reg = REG_HMEBOX1;
 110                 box_ex_reg = REG_HMEBOX1_EX;
 111                 break;
 112         case 2:
 113                 box_reg = REG_HMEBOX2;
 114                 box_ex_reg = REG_HMEBOX2_EX;
 115                 break;
 116         case 3:
 117                 box_reg = REG_HMEBOX3;
 118                 box_ex_reg = REG_HMEBOX3_EX;
 119                 break;
 120         default:
 121                 WARN(1, "invalid h2c mail box number\n");
 122                 goto out;
 123         }
 124 
 125         h2c_wait = 20;
 126         do {
 127                 box_state = rtw_read8(rtwdev, REG_HMETFR);
 128         } while ((box_state >> box) & 0x1 && --h2c_wait > 0);
 129 
 130         if (!h2c_wait) {
 131                 rtw_err(rtwdev, "failed to send h2c command\n");
 132                 goto out;
 133         }
 134 
 135         for (idx = 0; idx < 4; idx++)
 136                 rtw_write8(rtwdev, box_reg + idx, h2c[idx]);
 137         for (idx = 0; idx < 4; idx++)
 138                 rtw_write8(rtwdev, box_ex_reg + idx, h2c[idx + 4]);
 139 
 140         if (++rtwdev->h2c.last_box_num >= 4)
 141                 rtwdev->h2c.last_box_num = 0;
 142 
 143 out:
 144         spin_unlock(&rtwdev->h2c.lock);
 145 }
 146 
 147 static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt)
 148 {
 149         int ret;
 150 
 151         spin_lock(&rtwdev->h2c.lock);
 152 
 153         FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, rtwdev->h2c.seq);
 154         ret = rtw_hci_write_data_h2c(rtwdev, h2c_pkt, H2C_PKT_SIZE);
 155         if (ret)
 156                 rtw_err(rtwdev, "failed to send h2c packet\n");
 157         rtwdev->h2c.seq++;
 158 
 159         spin_unlock(&rtwdev->h2c.lock);
 160 }
 161 
 162 void
 163 rtw_fw_send_general_info(struct rtw_dev *rtwdev)
 164 {
 165         struct rtw_fifo_conf *fifo = &rtwdev->fifo;
 166         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 167         u16 total_size = H2C_PKT_HDR_SIZE + 4;
 168 
 169         rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_GENERAL_INFO);
 170 
 171         SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
 172 
 173         GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_pkt,
 174                                         fifo->rsvd_fw_txbuf_addr -
 175                                         fifo->rsvd_boundary);
 176 
 177         rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
 178 }
 179 
 180 void
 181 rtw_fw_send_phydm_info(struct rtw_dev *rtwdev)
 182 {
 183         struct rtw_hal *hal = &rtwdev->hal;
 184         struct rtw_efuse *efuse = &rtwdev->efuse;
 185         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 186         u16 total_size = H2C_PKT_HDR_SIZE + 8;
 187         u8 fw_rf_type = 0;
 188 
 189         if (hal->rf_type == RF_1T1R)
 190                 fw_rf_type = FW_RF_1T1R;
 191         else if (hal->rf_type == RF_2T2R)
 192                 fw_rf_type = FW_RF_2T2R;
 193 
 194         rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_PHYDM_INFO);
 195 
 196         SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
 197         PHYDM_INFO_SET_REF_TYPE(h2c_pkt, efuse->rfe_option);
 198         PHYDM_INFO_SET_RF_TYPE(h2c_pkt, fw_rf_type);
 199         PHYDM_INFO_SET_CUT_VER(h2c_pkt, hal->cut_version);
 200         PHYDM_INFO_SET_RX_ANT_STATUS(h2c_pkt, hal->antenna_tx);
 201         PHYDM_INFO_SET_TX_ANT_STATUS(h2c_pkt, hal->antenna_rx);
 202 
 203         rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
 204 }
 205 
 206 void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para)
 207 {
 208         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 209         u16 total_size = H2C_PKT_HDR_SIZE + 1;
 210 
 211         rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_IQK);
 212         SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
 213         IQK_SET_CLEAR(h2c_pkt, para->clear);
 214         IQK_SET_SEGMENT_IQK(h2c_pkt, para->segment_iqk);
 215 
 216         rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
 217 }
 218 
 219 void rtw_fw_query_bt_info(struct rtw_dev *rtwdev)
 220 {
 221         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 222 
 223         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_INFO);
 224 
 225         SET_QUERY_BT_INFO(h2c_pkt, true);
 226 
 227         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 228 }
 229 
 230 void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw)
 231 {
 232         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 233 
 234         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WL_CH_INFO);
 235 
 236         SET_WL_CH_INFO_LINK(h2c_pkt, link);
 237         SET_WL_CH_INFO_CHNL(h2c_pkt, ch);
 238         SET_WL_CH_INFO_BW(h2c_pkt, bw);
 239 
 240         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 241 }
 242 
 243 void rtw_fw_query_bt_mp_info(struct rtw_dev *rtwdev,
 244                              struct rtw_coex_info_req *req)
 245 {
 246         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 247 
 248         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_MP_INFO);
 249 
 250         SET_BT_MP_INFO_SEQ(h2c_pkt, req->seq);
 251         SET_BT_MP_INFO_OP_CODE(h2c_pkt, req->op_code);
 252         SET_BT_MP_INFO_PARA1(h2c_pkt, req->para1);
 253         SET_BT_MP_INFO_PARA2(h2c_pkt, req->para2);
 254         SET_BT_MP_INFO_PARA3(h2c_pkt, req->para3);
 255 
 256         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 257 }
 258 
 259 void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
 260 {
 261         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 262         u8 index = 0 - bt_pwr_dec_lvl;
 263 
 264         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_FORCE_BT_TX_POWER);
 265 
 266         SET_BT_TX_POWER_INDEX(h2c_pkt, index);
 267 
 268         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 269 }
 270 
 271 void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable)
 272 {
 273         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 274 
 275         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_IGNORE_WLAN_ACTION);
 276 
 277         SET_IGNORE_WLAN_ACTION_EN(h2c_pkt, enable);
 278 
 279         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 280 }
 281 
 282 void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
 283                            u8 para1, u8 para2, u8 para3, u8 para4, u8 para5)
 284 {
 285         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 286 
 287         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_COEX_TDMA_TYPE);
 288 
 289         SET_COEX_TDMA_TYPE_PARA1(h2c_pkt, para1);
 290         SET_COEX_TDMA_TYPE_PARA2(h2c_pkt, para2);
 291         SET_COEX_TDMA_TYPE_PARA3(h2c_pkt, para3);
 292         SET_COEX_TDMA_TYPE_PARA4(h2c_pkt, para4);
 293         SET_COEX_TDMA_TYPE_PARA5(h2c_pkt, para5);
 294 
 295         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 296 }
 297 
 298 void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data)
 299 {
 300         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 301 
 302         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BT_WIFI_CONTROL);
 303 
 304         SET_BT_WIFI_CONTROL_OP_CODE(h2c_pkt, op_code);
 305 
 306         SET_BT_WIFI_CONTROL_DATA1(h2c_pkt, *data);
 307         SET_BT_WIFI_CONTROL_DATA2(h2c_pkt, *(data + 1));
 308         SET_BT_WIFI_CONTROL_DATA3(h2c_pkt, *(data + 2));
 309         SET_BT_WIFI_CONTROL_DATA4(h2c_pkt, *(data + 3));
 310         SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, *(data + 4));
 311 
 312         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 313 }
 314 
 315 void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
 316 {
 317         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 318         u8 rssi = ewma_rssi_read(&si->avg_rssi);
 319         bool stbc_en = si->stbc_en ? true : false;
 320 
 321         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RSSI_MONITOR);
 322 
 323         SET_RSSI_INFO_MACID(h2c_pkt, si->mac_id);
 324         SET_RSSI_INFO_RSSI(h2c_pkt, rssi);
 325         SET_RSSI_INFO_STBC(h2c_pkt, stbc_en);
 326 
 327         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 328 }
 329 
 330 void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
 331 {
 332         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 333         bool no_update = si->updated;
 334         bool disable_pt = true;
 335 
 336         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO);
 337 
 338         SET_RA_INFO_MACID(h2c_pkt, si->mac_id);
 339         SET_RA_INFO_RATE_ID(h2c_pkt, si->rate_id);
 340         SET_RA_INFO_INIT_RA_LVL(h2c_pkt, si->init_ra_lv);
 341         SET_RA_INFO_SGI_EN(h2c_pkt, si->sgi_enable);
 342         SET_RA_INFO_BW_MODE(h2c_pkt, si->bw_mode);
 343         SET_RA_INFO_LDPC(h2c_pkt, si->ldpc_en);
 344         SET_RA_INFO_NO_UPDATE(h2c_pkt, no_update);
 345         SET_RA_INFO_VHT_EN(h2c_pkt, si->vht_enable);
 346         SET_RA_INFO_DIS_PT(h2c_pkt, disable_pt);
 347         SET_RA_INFO_RA_MASK0(h2c_pkt, (si->ra_mask & 0xff));
 348         SET_RA_INFO_RA_MASK1(h2c_pkt, (si->ra_mask & 0xff00) >> 8);
 349         SET_RA_INFO_RA_MASK2(h2c_pkt, (si->ra_mask & 0xff0000) >> 16);
 350         SET_RA_INFO_RA_MASK3(h2c_pkt, (si->ra_mask & 0xff000000) >> 24);
 351 
 352         si->init_ra_lv = 0;
 353         si->updated = true;
 354 
 355         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 356 }
 357 
 358 void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool connect)
 359 {
 360         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 361 
 362         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_MEDIA_STATUS_RPT);
 363         MEDIA_STATUS_RPT_SET_OP_MODE(h2c_pkt, connect);
 364         MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, mac_id);
 365 
 366         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 367 }
 368 
 369 void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev)
 370 {
 371         struct rtw_lps_conf *conf = &rtwdev->lps_conf;
 372         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 373 
 374         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_SET_PWR_MODE);
 375 
 376         SET_PWR_MODE_SET_MODE(h2c_pkt, conf->mode);
 377         SET_PWR_MODE_SET_RLBM(h2c_pkt, conf->rlbm);
 378         SET_PWR_MODE_SET_SMART_PS(h2c_pkt, conf->smart_ps);
 379         SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_pkt, conf->awake_interval);
 380         SET_PWR_MODE_SET_PORT_ID(h2c_pkt, conf->port_id);
 381         SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, conf->state);
 382 
 383         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 384 }
 385 
 386 static u8 rtw_get_rsvd_page_location(struct rtw_dev *rtwdev,
 387                                      enum rtw_rsvd_packet_type type)
 388 {
 389         struct rtw_rsvd_page *rsvd_pkt;
 390         u8 location = 0;
 391 
 392         list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
 393                 if (type == rsvd_pkt->type)
 394                         location = rsvd_pkt->page;
 395         }
 396 
 397         return location;
 398 }
 399 
 400 void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev)
 401 {
 402         u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 403         u8 location = 0;
 404 
 405         SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RSVD_PAGE);
 406 
 407         location = rtw_get_rsvd_page_location(rtwdev, RSVD_PROBE_RESP);
 408         *(h2c_pkt + 1) = location;
 409         rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_PROBE_RESP loc: %d\n", location);
 410 
 411         location = rtw_get_rsvd_page_location(rtwdev, RSVD_PS_POLL);
 412         *(h2c_pkt + 2) = location;
 413         rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_PS_POLL loc: %d\n", location);
 414 
 415         location = rtw_get_rsvd_page_location(rtwdev, RSVD_NULL);
 416         *(h2c_pkt + 3) = location;
 417         rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_NULL loc: %d\n", location);
 418 
 419         location = rtw_get_rsvd_page_location(rtwdev, RSVD_QOS_NULL);
 420         *(h2c_pkt + 4) = location;
 421         rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_QOS_NULL loc: %d\n", location);
 422 
 423         rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 424 }
 425 
 426 static struct sk_buff *
 427 rtw_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 428 {
 429         struct sk_buff *skb_new;
 430 
 431         if (vif->type != NL80211_IFTYPE_AP &&
 432             vif->type != NL80211_IFTYPE_ADHOC &&
 433             !ieee80211_vif_is_mesh(vif)) {
 434                 skb_new = alloc_skb(1, GFP_KERNEL);
 435                 if (!skb_new)
 436                         return NULL;
 437                 skb_put(skb_new, 1);
 438         } else {
 439                 skb_new = ieee80211_beacon_get(hw, vif);
 440         }
 441 
 442         return skb_new;
 443 }
 444 
 445 static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
 446                                              struct ieee80211_vif *vif,
 447                                              enum rtw_rsvd_packet_type type)
 448 {
 449         struct sk_buff *skb_new;
 450 
 451         switch (type) {
 452         case RSVD_BEACON:
 453                 skb_new = rtw_beacon_get(hw, vif);
 454                 break;
 455         case RSVD_PS_POLL:
 456                 skb_new = ieee80211_pspoll_get(hw, vif);
 457                 break;
 458         case RSVD_PROBE_RESP:
 459                 skb_new = ieee80211_proberesp_get(hw, vif);
 460                 break;
 461         case RSVD_NULL:
 462                 skb_new = ieee80211_nullfunc_get(hw, vif, false);
 463                 break;
 464         case RSVD_QOS_NULL:
 465                 skb_new = ieee80211_nullfunc_get(hw, vif, true);
 466                 break;
 467         default:
 468                 return NULL;
 469         }
 470 
 471         if (!skb_new)
 472                 return NULL;
 473 
 474         return skb_new;
 475 }
 476 
 477 static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb)
 478 {
 479         struct rtw_tx_pkt_info pkt_info;
 480         struct rtw_chip_info *chip = rtwdev->chip;
 481         u8 *pkt_desc;
 482 
 483         memset(&pkt_info, 0, sizeof(pkt_info));
 484         rtw_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb);
 485         pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
 486         memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
 487         rtw_tx_fill_tx_desc(&pkt_info, skb);
 488 }
 489 
 490 static inline u8 rtw_len_to_page(unsigned int len, u8 page_size)
 491 {
 492         return DIV_ROUND_UP(len, page_size);
 493 }
 494 
 495 static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u8 page_size,
 496                                       u8 page_margin, u32 page, u8 *buf,
 497                                       struct rtw_rsvd_page *rsvd_pkt)
 498 {
 499         struct sk_buff *skb = rsvd_pkt->skb;
 500 
 501         if (page >= 1)
 502                 memcpy(buf + page_margin + page_size * (page - 1),
 503                        skb->data, skb->len);
 504         else
 505                 memcpy(buf, skb->data, skb->len);
 506 }
 507 
 508 void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type,
 509                        bool txdesc)
 510 {
 511         struct rtw_rsvd_page *rsvd_pkt;
 512 
 513         lockdep_assert_held(&rtwdev->mutex);
 514 
 515         list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
 516                 if (rsvd_pkt->type == type)
 517                         return;
 518         }
 519 
 520         rsvd_pkt = kmalloc(sizeof(*rsvd_pkt), GFP_KERNEL);
 521         if (!rsvd_pkt)
 522                 return;
 523 
 524         rsvd_pkt->type = type;
 525         rsvd_pkt->add_txdesc = txdesc;
 526         list_add_tail(&rsvd_pkt->list, &rtwdev->rsvd_page_list);
 527 }
 528 
 529 void rtw_reset_rsvd_page(struct rtw_dev *rtwdev)
 530 {
 531         struct rtw_rsvd_page *rsvd_pkt, *tmp;
 532 
 533         lockdep_assert_held(&rtwdev->mutex);
 534 
 535         list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) {
 536                 if (rsvd_pkt->type == RSVD_BEACON)
 537                         continue;
 538                 list_del(&rsvd_pkt->list);
 539                 kfree(rsvd_pkt);
 540         }
 541 }
 542 
 543 int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
 544                                 u8 *buf, u32 size)
 545 {
 546         u8 bckp[2];
 547         u8 val;
 548         u16 rsvd_pg_head;
 549         int ret;
 550 
 551         lockdep_assert_held(&rtwdev->mutex);
 552 
 553         if (!size)
 554                 return -EINVAL;
 555 
 556         pg_addr &= BIT_MASK_BCN_HEAD_1_V1;
 557         rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, pg_addr | BIT_BCN_VALID_V1);
 558 
 559         val = rtw_read8(rtwdev, REG_CR + 1);
 560         bckp[0] = val;
 561         val |= BIT_ENSWBCN >> 8;
 562         rtw_write8(rtwdev, REG_CR + 1, val);
 563 
 564         val = rtw_read8(rtwdev, REG_FWHW_TXQ_CTRL + 2);
 565         bckp[1] = val;
 566         val &= ~(BIT_EN_BCNQ_DL >> 16);
 567         rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, val);
 568 
 569         ret = rtw_hci_write_data_rsvd_page(rtwdev, buf, size);
 570         if (ret) {
 571                 rtw_err(rtwdev, "failed to write data to rsvd page\n");
 572                 goto restore;
 573         }
 574 
 575         if (!check_hw_ready(rtwdev, REG_FIFOPAGE_CTRL_2, BIT_BCN_VALID_V1, 1)) {
 576                 rtw_err(rtwdev, "error beacon valid\n");
 577                 ret = -EBUSY;
 578         }
 579 
 580 restore:
 581         rsvd_pg_head = rtwdev->fifo.rsvd_boundary;
 582         rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2,
 583                     rsvd_pg_head | BIT_BCN_VALID_V1);
 584         rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, bckp[1]);
 585         rtw_write8(rtwdev, REG_CR + 1, bckp[0]);
 586 
 587         return ret;
 588 }
 589 
 590 static int rtw_download_drv_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
 591 {
 592         u32 pg_size;
 593         u32 pg_num = 0;
 594         u16 pg_addr = 0;
 595 
 596         pg_size = rtwdev->chip->page_size;
 597         pg_num = size / pg_size + ((size & (pg_size - 1)) ? 1 : 0);
 598         if (pg_num > rtwdev->fifo.rsvd_drv_pg_num)
 599                 return -ENOMEM;
 600 
 601         pg_addr = rtwdev->fifo.rsvd_drv_addr;
 602 
 603         return rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, size);
 604 }
 605 
 606 static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev,
 607                                struct ieee80211_vif *vif, u32 *size)
 608 {
 609         struct ieee80211_hw *hw = rtwdev->hw;
 610         struct rtw_chip_info *chip = rtwdev->chip;
 611         struct sk_buff *iter;
 612         struct rtw_rsvd_page *rsvd_pkt;
 613         u32 page = 0;
 614         u8 total_page = 0;
 615         u8 page_size, page_margin, tx_desc_sz;
 616         u8 *buf;
 617 
 618         page_size = chip->page_size;
 619         tx_desc_sz = chip->tx_pkt_desc_sz;
 620         page_margin = page_size - tx_desc_sz;
 621 
 622         list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
 623                 iter = rtw_get_rsvd_page_skb(hw, vif, rsvd_pkt->type);
 624                 if (!iter) {
 625                         rtw_err(rtwdev, "failed to build rsvd packet\n");
 626                         goto release_skb;
 627                 }
 628 
 629                 /* Fill the tx_desc for the rsvd pkt that requires one.
 630                  * And iter->len will be added with size of tx_desc_sz.
 631                  */
 632                 if (rsvd_pkt->add_txdesc)
 633                         rtw_fill_rsvd_page_desc(rtwdev, iter);
 634 
 635                 rsvd_pkt->skb = iter;
 636                 rsvd_pkt->page = total_page;
 637 
 638                 /* Reserved page is downloaded via TX path, and TX path will
 639                  * generate a tx_desc at the header to describe length of
 640                  * the buffer. If we are not counting page numbers with the
 641                  * size of tx_desc added at the first rsvd_pkt (usually a
 642                  * beacon, firmware default refer to the first page as the
 643                  * content of beacon), we could generate a buffer which size
 644                  * is smaller than the actual size of the whole rsvd_page
 645                  */
 646                 if (total_page == 0) {
 647                         if (rsvd_pkt->type != RSVD_BEACON) {
 648                                 rtw_err(rtwdev, "first page should be a beacon\n");
 649                                 goto release_skb;
 650                         }
 651                         total_page += rtw_len_to_page(iter->len + tx_desc_sz,
 652                                                       page_size);
 653                 } else {
 654                         total_page += rtw_len_to_page(iter->len, page_size);
 655                 }
 656         }
 657 
 658         if (total_page > rtwdev->fifo.rsvd_drv_pg_num) {
 659                 rtw_err(rtwdev, "rsvd page over size: %d\n", total_page);
 660                 goto release_skb;
 661         }
 662 
 663         *size = (total_page - 1) * page_size + page_margin;
 664         buf = kzalloc(*size, GFP_KERNEL);
 665         if (!buf)
 666                 goto release_skb;
 667 
 668         /* Copy the content of each rsvd_pkt to the buf, and they should
 669          * be aligned to the pages.
 670          *
 671          * Note that the first rsvd_pkt is a beacon no matter what vif->type.
 672          * And that rsvd_pkt does not require tx_desc because when it goes
 673          * through TX path, the TX path will generate one for it.
 674          */
 675         list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
 676                 rtw_rsvd_page_list_to_buf(rtwdev, page_size, page_margin,
 677                                           page, buf, rsvd_pkt);
 678                 if (page == 0)
 679                         page += rtw_len_to_page(rsvd_pkt->skb->len +
 680                                                 tx_desc_sz, page_size);
 681                 else
 682                         page += rtw_len_to_page(rsvd_pkt->skb->len, page_size);
 683 
 684                 kfree_skb(rsvd_pkt->skb);
 685         }
 686 
 687         return buf;
 688 
 689 release_skb:
 690         list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list)
 691                 kfree_skb(rsvd_pkt->skb);
 692 
 693         return NULL;
 694 }
 695 
 696 static int
 697 rtw_download_beacon(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
 698 {
 699         struct ieee80211_hw *hw = rtwdev->hw;
 700         struct sk_buff *skb;
 701         int ret = 0;
 702 
 703         skb = rtw_beacon_get(hw, vif);
 704         if (!skb) {
 705                 rtw_err(rtwdev, "failed to get beacon skb\n");
 706                 ret = -ENOMEM;
 707                 goto out;
 708         }
 709 
 710         ret = rtw_download_drv_rsvd_page(rtwdev, skb->data, skb->len);
 711         if (ret)
 712                 rtw_err(rtwdev, "failed to download drv rsvd page\n");
 713 
 714         dev_kfree_skb(skb);
 715 
 716 out:
 717         return ret;
 718 }
 719 
 720 int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
 721 {
 722         u8 *buf;
 723         u32 size;
 724         int ret;
 725 
 726         buf = rtw_build_rsvd_page(rtwdev, vif, &size);
 727         if (!buf) {
 728                 rtw_err(rtwdev, "failed to build rsvd page pkt\n");
 729                 return -ENOMEM;
 730         }
 731 
 732         ret = rtw_download_drv_rsvd_page(rtwdev, buf, size);
 733         if (ret) {
 734                 rtw_err(rtwdev, "failed to download drv rsvd page\n");
 735                 goto free;
 736         }
 737 
 738         /* The last thing is to download the *ONLY* beacon again, because
 739          * the previous tx_desc is to describe the total rsvd page. Download
 740          * the beacon again to replace the TX desc header, and we will get
 741          * a correct tx_desc for the beacon in the rsvd page.
 742          */
 743         ret = rtw_download_beacon(rtwdev, vif);
 744         if (ret) {
 745                 rtw_err(rtwdev, "failed to download beacon\n");
 746                 goto free;
 747         }
 748 
 749 free:
 750         kfree(buf);
 751 
 752         return ret;
 753 }
 754 
 755 int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
 756                            u32 offset, u32 size, u32 *buf)
 757 {
 758         struct rtw_fifo_conf *fifo = &rtwdev->fifo;
 759         u32 residue, i;
 760         u16 start_pg;
 761         u16 idx = 0;
 762         u16 ctl;
 763         u8 rcr;
 764 
 765         if (size & 0x3) {
 766                 rtw_warn(rtwdev, "should be 4-byte aligned\n");
 767                 return -EINVAL;
 768         }
 769 
 770         offset += fifo->rsvd_boundary << TX_PAGE_SIZE_SHIFT;
 771         residue = offset & (FIFO_PAGE_SIZE - 1);
 772         start_pg = offset >> FIFO_PAGE_SIZE_SHIFT;
 773         start_pg += RSVD_PAGE_START_ADDR;
 774 
 775         rcr = rtw_read8(rtwdev, REG_RCR + 2);
 776         ctl = rtw_read16(rtwdev, REG_PKTBUF_DBG_CTRL) & 0xf000;
 777 
 778         /* disable rx clock gate */
 779         rtw_write8(rtwdev, REG_RCR, rcr | BIT(3));
 780 
 781         do {
 782                 rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, start_pg | ctl);
 783 
 784                 for (i = FIFO_DUMP_ADDR + residue;
 785                      i < FIFO_DUMP_ADDR + FIFO_PAGE_SIZE; i += 4) {
 786                         buf[idx++] = rtw_read32(rtwdev, i);
 787                         size -= 4;
 788                         if (size == 0)
 789                                 goto out;
 790                 }
 791 
 792                 residue = 0;
 793                 start_pg++;
 794         } while (size);
 795 
 796 out:
 797         rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, ctl);
 798         rtw_write8(rtwdev, REG_RCR + 2, rcr);
 799         return 0;
 800 }

/* [<][>][^][v][top][bottom][index][help] */