18e99ea8dSJohannes Berg // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 28e99ea8dSJohannes Berg /* 3fd1c3318SJohannes Berg * Copyright (C) 2005-2014, 2020 Intel Corporation 48e99ea8dSJohannes Berg * Copyright (C) 2016 Intel Deutschland GmbH 58e99ea8dSJohannes Berg */ 6e705c121SKalle Valo #include <linux/slab.h> 7e705c121SKalle Valo #include <linux/string.h> 8e705c121SKalle Valo #include <linux/export.h> 9e705c121SKalle Valo 10e705c121SKalle Valo #include "iwl-drv.h" 11e705c121SKalle Valo #include "iwl-phy-db.h" 12e705c121SKalle Valo #include "iwl-debug.h" 13e705c121SKalle Valo #include "iwl-op-mode.h" 14e705c121SKalle Valo #include "iwl-trans.h" 15e705c121SKalle Valo 16e705c121SKalle Valo #define CHANNEL_NUM_SIZE 4 /* num of channels in calib_ch size */ 17e705c121SKalle Valo 18e705c121SKalle Valo struct iwl_phy_db_entry { 19e705c121SKalle Valo u16 size; 20e705c121SKalle Valo u8 *data; 21e705c121SKalle Valo }; 22e705c121SKalle Valo 23e705c121SKalle Valo /** 24e705c121SKalle Valo * struct iwl_phy_db - stores phy configuration and calibration data. 25e705c121SKalle Valo * 26e705c121SKalle Valo * @cfg: phy configuration. 27e705c121SKalle Valo * @calib_nch: non channel specific calibration data. 280ec84d1dSSara Sharon * @n_group_papd: number of entries in papd channel group. 29e705c121SKalle Valo * @calib_ch_group_papd: calibration data related to papd channel group. 300ec84d1dSSara Sharon * @n_group_txp: number of entries in tx power channel group. 31e705c121SKalle Valo * @calib_ch_group_txp: calibration data related to tx power chanel group. 32*5a2e2f91SLee Jones * @trans: transport layer 33e705c121SKalle Valo */ 34e705c121SKalle Valo struct iwl_phy_db { 35e705c121SKalle Valo struct iwl_phy_db_entry cfg; 36e705c121SKalle Valo struct iwl_phy_db_entry calib_nch; 370ec84d1dSSara Sharon int n_group_papd; 380ec84d1dSSara Sharon struct iwl_phy_db_entry *calib_ch_group_papd; 390ec84d1dSSara Sharon int n_group_txp; 400ec84d1dSSara Sharon struct iwl_phy_db_entry *calib_ch_group_txp; 41e705c121SKalle Valo 42e705c121SKalle Valo struct iwl_trans *trans; 43e705c121SKalle Valo }; 44e705c121SKalle Valo 45e705c121SKalle Valo enum iwl_phy_db_section_type { 46e705c121SKalle Valo IWL_PHY_DB_CFG = 1, 47e705c121SKalle Valo IWL_PHY_DB_CALIB_NCH, 48e705c121SKalle Valo IWL_PHY_DB_UNUSED, 49e705c121SKalle Valo IWL_PHY_DB_CALIB_CHG_PAPD, 50e705c121SKalle Valo IWL_PHY_DB_CALIB_CHG_TXP, 51e705c121SKalle Valo IWL_PHY_DB_MAX 52e705c121SKalle Valo }; 53e705c121SKalle Valo 54176aa60bSSara Sharon #define PHY_DB_CMD 0x6c 55e705c121SKalle Valo 56e705c121SKalle Valo /* for parsing of tx power channel group data that comes from the firmware*/ 57e705c121SKalle Valo struct iwl_phy_db_chg_txp { 58e705c121SKalle Valo __le32 space; 59e705c121SKalle Valo __le16 max_channel_idx; 60e705c121SKalle Valo } __packed; 61e705c121SKalle Valo 62e705c121SKalle Valo struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) 63e705c121SKalle Valo { 64e705c121SKalle Valo struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), 65e705c121SKalle Valo GFP_KERNEL); 66e705c121SKalle Valo 67e705c121SKalle Valo if (!phy_db) 68e705c121SKalle Valo return phy_db; 69e705c121SKalle Valo 70e705c121SKalle Valo phy_db->trans = trans; 71e705c121SKalle Valo 720ec84d1dSSara Sharon phy_db->n_group_txp = -1; 730ec84d1dSSara Sharon phy_db->n_group_papd = -1; 740ec84d1dSSara Sharon 75e705c121SKalle Valo /* TODO: add default values of the phy db. */ 76e705c121SKalle Valo return phy_db; 77e705c121SKalle Valo } 78e705c121SKalle Valo IWL_EXPORT_SYMBOL(iwl_phy_db_init); 79e705c121SKalle Valo 80e705c121SKalle Valo /* 81e705c121SKalle Valo * get phy db section: returns a pointer to a phy db section specified by 82e705c121SKalle Valo * type and channel group id. 83e705c121SKalle Valo */ 84e705c121SKalle Valo static struct iwl_phy_db_entry * 85e705c121SKalle Valo iwl_phy_db_get_section(struct iwl_phy_db *phy_db, 86e705c121SKalle Valo enum iwl_phy_db_section_type type, 87e705c121SKalle Valo u16 chg_id) 88e705c121SKalle Valo { 89e705c121SKalle Valo if (!phy_db || type >= IWL_PHY_DB_MAX) 90e705c121SKalle Valo return NULL; 91e705c121SKalle Valo 92e705c121SKalle Valo switch (type) { 93e705c121SKalle Valo case IWL_PHY_DB_CFG: 94e705c121SKalle Valo return &phy_db->cfg; 95e705c121SKalle Valo case IWL_PHY_DB_CALIB_NCH: 96e705c121SKalle Valo return &phy_db->calib_nch; 97e705c121SKalle Valo case IWL_PHY_DB_CALIB_CHG_PAPD: 980ec84d1dSSara Sharon if (chg_id >= phy_db->n_group_papd) 99e705c121SKalle Valo return NULL; 100e705c121SKalle Valo return &phy_db->calib_ch_group_papd[chg_id]; 101e705c121SKalle Valo case IWL_PHY_DB_CALIB_CHG_TXP: 1020ec84d1dSSara Sharon if (chg_id >= phy_db->n_group_txp) 103e705c121SKalle Valo return NULL; 104e705c121SKalle Valo return &phy_db->calib_ch_group_txp[chg_id]; 105e705c121SKalle Valo default: 106e705c121SKalle Valo return NULL; 107e705c121SKalle Valo } 108e705c121SKalle Valo return NULL; 109e705c121SKalle Valo } 110e705c121SKalle Valo 111e705c121SKalle Valo static void iwl_phy_db_free_section(struct iwl_phy_db *phy_db, 112e705c121SKalle Valo enum iwl_phy_db_section_type type, 113e705c121SKalle Valo u16 chg_id) 114e705c121SKalle Valo { 115e705c121SKalle Valo struct iwl_phy_db_entry *entry = 116e705c121SKalle Valo iwl_phy_db_get_section(phy_db, type, chg_id); 117e705c121SKalle Valo if (!entry) 118e705c121SKalle Valo return; 119e705c121SKalle Valo 120e705c121SKalle Valo kfree(entry->data); 121e705c121SKalle Valo entry->data = NULL; 122e705c121SKalle Valo entry->size = 0; 123e705c121SKalle Valo } 124e705c121SKalle Valo 125e705c121SKalle Valo void iwl_phy_db_free(struct iwl_phy_db *phy_db) 126e705c121SKalle Valo { 127e705c121SKalle Valo int i; 128e705c121SKalle Valo 129e705c121SKalle Valo if (!phy_db) 130e705c121SKalle Valo return; 131e705c121SKalle Valo 132e705c121SKalle Valo iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CFG, 0); 133e705c121SKalle Valo iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_NCH, 0); 1340ec84d1dSSara Sharon 1350ec84d1dSSara Sharon for (i = 0; i < phy_db->n_group_papd; i++) 136e705c121SKalle Valo iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_PAPD, i); 1370ec84d1dSSara Sharon kfree(phy_db->calib_ch_group_papd); 1380ec84d1dSSara Sharon 1390ec84d1dSSara Sharon for (i = 0; i < phy_db->n_group_txp; i++) 140e705c121SKalle Valo iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_TXP, i); 1410ec84d1dSSara Sharon kfree(phy_db->calib_ch_group_txp); 142e705c121SKalle Valo 143e705c121SKalle Valo kfree(phy_db); 144e705c121SKalle Valo } 145e705c121SKalle Valo IWL_EXPORT_SYMBOL(iwl_phy_db_free); 146e705c121SKalle Valo 147ce1f2778SSara Sharon int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, 148ce1f2778SSara Sharon struct iwl_rx_packet *pkt) 149e705c121SKalle Valo { 150fd1c3318SJohannes Berg unsigned int pkt_len = iwl_rx_packet_payload_len(pkt); 151e705c121SKalle Valo struct iwl_calib_res_notif_phy_db *phy_db_notif = 152e705c121SKalle Valo (struct iwl_calib_res_notif_phy_db *)pkt->data; 153fd1c3318SJohannes Berg enum iwl_phy_db_section_type type; 154fd1c3318SJohannes Berg u16 size; 155e705c121SKalle Valo struct iwl_phy_db_entry *entry; 156e705c121SKalle Valo u16 chg_id = 0; 157e705c121SKalle Valo 158fd1c3318SJohannes Berg if (pkt_len < sizeof(*phy_db_notif)) 159fd1c3318SJohannes Berg return -EINVAL; 160fd1c3318SJohannes Berg 161fd1c3318SJohannes Berg type = le16_to_cpu(phy_db_notif->type); 162fd1c3318SJohannes Berg size = le16_to_cpu(phy_db_notif->length); 163fd1c3318SJohannes Berg 164fd1c3318SJohannes Berg if (pkt_len < sizeof(*phy_db_notif) + size) 165fd1c3318SJohannes Berg return -EINVAL; 166fd1c3318SJohannes Berg 167e705c121SKalle Valo if (!phy_db) 168e705c121SKalle Valo return -EINVAL; 169e705c121SKalle Valo 1700ec84d1dSSara Sharon if (type == IWL_PHY_DB_CALIB_CHG_PAPD) { 171e705c121SKalle Valo chg_id = le16_to_cpup((__le16 *)phy_db_notif->data); 1720ec84d1dSSara Sharon if (phy_db && !phy_db->calib_ch_group_papd) { 1730ec84d1dSSara Sharon /* 1740ec84d1dSSara Sharon * Firmware sends the largest index first, so we can use 1750ec84d1dSSara Sharon * it to know how much we should allocate. 1760ec84d1dSSara Sharon */ 1770ec84d1dSSara Sharon phy_db->calib_ch_group_papd = kcalloc(chg_id + 1, 1780ec84d1dSSara Sharon sizeof(struct iwl_phy_db_entry), 1790ec84d1dSSara Sharon GFP_ATOMIC); 1800ec84d1dSSara Sharon if (!phy_db->calib_ch_group_papd) 1810ec84d1dSSara Sharon return -ENOMEM; 1820ec84d1dSSara Sharon phy_db->n_group_papd = chg_id + 1; 1830ec84d1dSSara Sharon } 1840ec84d1dSSara Sharon } else if (type == IWL_PHY_DB_CALIB_CHG_TXP) { 1850ec84d1dSSara Sharon chg_id = le16_to_cpup((__le16 *)phy_db_notif->data); 1860ec84d1dSSara Sharon if (phy_db && !phy_db->calib_ch_group_txp) { 1870ec84d1dSSara Sharon /* 1880ec84d1dSSara Sharon * Firmware sends the largest index first, so we can use 1890ec84d1dSSara Sharon * it to know how much we should allocate. 1900ec84d1dSSara Sharon */ 1910ec84d1dSSara Sharon phy_db->calib_ch_group_txp = kcalloc(chg_id + 1, 1920ec84d1dSSara Sharon sizeof(struct iwl_phy_db_entry), 1930ec84d1dSSara Sharon GFP_ATOMIC); 1940ec84d1dSSara Sharon if (!phy_db->calib_ch_group_txp) 1950ec84d1dSSara Sharon return -ENOMEM; 1960ec84d1dSSara Sharon phy_db->n_group_txp = chg_id + 1; 1970ec84d1dSSara Sharon } 1980ec84d1dSSara Sharon } 199e705c121SKalle Valo 200e705c121SKalle Valo entry = iwl_phy_db_get_section(phy_db, type, chg_id); 201e705c121SKalle Valo if (!entry) 202e705c121SKalle Valo return -EINVAL; 203e705c121SKalle Valo 204e705c121SKalle Valo kfree(entry->data); 205ce1f2778SSara Sharon entry->data = kmemdup(phy_db_notif->data, size, GFP_ATOMIC); 206e705c121SKalle Valo if (!entry->data) { 207e705c121SKalle Valo entry->size = 0; 208e705c121SKalle Valo return -ENOMEM; 209e705c121SKalle Valo } 210e705c121SKalle Valo 211e705c121SKalle Valo entry->size = size; 212e705c121SKalle Valo 213e705c121SKalle Valo IWL_DEBUG_INFO(phy_db->trans, 214e705c121SKalle Valo "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", 215e705c121SKalle Valo __func__, __LINE__, type, size); 216e705c121SKalle Valo 217e705c121SKalle Valo return 0; 218e705c121SKalle Valo } 219e705c121SKalle Valo IWL_EXPORT_SYMBOL(iwl_phy_db_set_section); 220e705c121SKalle Valo 221e705c121SKalle Valo static int is_valid_channel(u16 ch_id) 222e705c121SKalle Valo { 223e705c121SKalle Valo if (ch_id <= 14 || 224e705c121SKalle Valo (36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) || 225e705c121SKalle Valo (100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) || 226e705c121SKalle Valo (145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1)) 227e705c121SKalle Valo return 1; 228e705c121SKalle Valo return 0; 229e705c121SKalle Valo } 230e705c121SKalle Valo 231e705c121SKalle Valo static u8 ch_id_to_ch_index(u16 ch_id) 232e705c121SKalle Valo { 233e705c121SKalle Valo if (WARN_ON(!is_valid_channel(ch_id))) 234e705c121SKalle Valo return 0xff; 235e705c121SKalle Valo 236e705c121SKalle Valo if (ch_id <= 14) 237e705c121SKalle Valo return ch_id - 1; 238e705c121SKalle Valo if (ch_id <= 64) 239e705c121SKalle Valo return (ch_id + 20) / 4; 240e705c121SKalle Valo if (ch_id <= 140) 241e705c121SKalle Valo return (ch_id - 12) / 4; 242e705c121SKalle Valo return (ch_id - 13) / 4; 243e705c121SKalle Valo } 244e705c121SKalle Valo 245e705c121SKalle Valo 246e705c121SKalle Valo static u16 channel_id_to_papd(u16 ch_id) 247e705c121SKalle Valo { 248e705c121SKalle Valo if (WARN_ON(!is_valid_channel(ch_id))) 249e705c121SKalle Valo return 0xff; 250e705c121SKalle Valo 251e705c121SKalle Valo if (1 <= ch_id && ch_id <= 14) 252e705c121SKalle Valo return 0; 253e705c121SKalle Valo if (36 <= ch_id && ch_id <= 64) 254e705c121SKalle Valo return 1; 255e705c121SKalle Valo if (100 <= ch_id && ch_id <= 140) 256e705c121SKalle Valo return 2; 257e705c121SKalle Valo return 3; 258e705c121SKalle Valo } 259e705c121SKalle Valo 260e705c121SKalle Valo static u16 channel_id_to_txp(struct iwl_phy_db *phy_db, u16 ch_id) 261e705c121SKalle Valo { 262e705c121SKalle Valo struct iwl_phy_db_chg_txp *txp_chg; 263e705c121SKalle Valo int i; 264e705c121SKalle Valo u8 ch_index = ch_id_to_ch_index(ch_id); 265e705c121SKalle Valo if (ch_index == 0xff) 266e705c121SKalle Valo return 0xff; 267e705c121SKalle Valo 2680ec84d1dSSara Sharon for (i = 0; i < phy_db->n_group_txp; i++) { 269e705c121SKalle Valo txp_chg = (void *)phy_db->calib_ch_group_txp[i].data; 270e705c121SKalle Valo if (!txp_chg) 271e705c121SKalle Valo return 0xff; 272e705c121SKalle Valo /* 273e705c121SKalle Valo * Looking for the first channel group that its max channel is 274e705c121SKalle Valo * higher then wanted channel. 275e705c121SKalle Valo */ 276e705c121SKalle Valo if (le16_to_cpu(txp_chg->max_channel_idx) >= ch_index) 277e705c121SKalle Valo return i; 278e705c121SKalle Valo } 279e705c121SKalle Valo return 0xff; 280e705c121SKalle Valo } 281e705c121SKalle Valo static 282e705c121SKalle Valo int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, 283e705c121SKalle Valo u32 type, u8 **data, u16 *size, u16 ch_id) 284e705c121SKalle Valo { 285e705c121SKalle Valo struct iwl_phy_db_entry *entry; 286e705c121SKalle Valo u16 ch_group_id = 0; 287e705c121SKalle Valo 288e705c121SKalle Valo if (!phy_db) 289e705c121SKalle Valo return -EINVAL; 290e705c121SKalle Valo 291e705c121SKalle Valo /* find wanted channel group */ 292e705c121SKalle Valo if (type == IWL_PHY_DB_CALIB_CHG_PAPD) 293e705c121SKalle Valo ch_group_id = channel_id_to_papd(ch_id); 294e705c121SKalle Valo else if (type == IWL_PHY_DB_CALIB_CHG_TXP) 295e705c121SKalle Valo ch_group_id = channel_id_to_txp(phy_db, ch_id); 296e705c121SKalle Valo 297e705c121SKalle Valo entry = iwl_phy_db_get_section(phy_db, type, ch_group_id); 298e705c121SKalle Valo if (!entry) 299e705c121SKalle Valo return -EINVAL; 300e705c121SKalle Valo 301e705c121SKalle Valo *data = entry->data; 302e705c121SKalle Valo *size = entry->size; 303e705c121SKalle Valo 304e705c121SKalle Valo IWL_DEBUG_INFO(phy_db->trans, 305e705c121SKalle Valo "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", 306e705c121SKalle Valo __func__, __LINE__, type, *size); 307e705c121SKalle Valo 308e705c121SKalle Valo return 0; 309e705c121SKalle Valo } 310e705c121SKalle Valo 311e705c121SKalle Valo static int iwl_send_phy_db_cmd(struct iwl_phy_db *phy_db, u16 type, 312e705c121SKalle Valo u16 length, void *data) 313e705c121SKalle Valo { 314e705c121SKalle Valo struct iwl_phy_db_cmd phy_db_cmd; 315e705c121SKalle Valo struct iwl_host_cmd cmd = { 316e705c121SKalle Valo .id = PHY_DB_CMD, 317e705c121SKalle Valo }; 318e705c121SKalle Valo 319e705c121SKalle Valo IWL_DEBUG_INFO(phy_db->trans, 320e705c121SKalle Valo "Sending PHY-DB hcmd of type %d, of length %d\n", 321e705c121SKalle Valo type, length); 322e705c121SKalle Valo 323e705c121SKalle Valo /* Set phy db cmd variables */ 324e705c121SKalle Valo phy_db_cmd.type = cpu_to_le16(type); 325e705c121SKalle Valo phy_db_cmd.length = cpu_to_le16(length); 326e705c121SKalle Valo 327e705c121SKalle Valo /* Set hcmd variables */ 328e705c121SKalle Valo cmd.data[0] = &phy_db_cmd; 329e705c121SKalle Valo cmd.len[0] = sizeof(struct iwl_phy_db_cmd); 330e705c121SKalle Valo cmd.data[1] = data; 331e705c121SKalle Valo cmd.len[1] = length; 332e705c121SKalle Valo cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; 333e705c121SKalle Valo 334e705c121SKalle Valo return iwl_trans_send_cmd(phy_db->trans, &cmd); 335e705c121SKalle Valo } 336e705c121SKalle Valo 337e705c121SKalle Valo static int iwl_phy_db_send_all_channel_groups( 338e705c121SKalle Valo struct iwl_phy_db *phy_db, 339e705c121SKalle Valo enum iwl_phy_db_section_type type, 340e705c121SKalle Valo u8 max_ch_groups) 341e705c121SKalle Valo { 342e705c121SKalle Valo u16 i; 343e705c121SKalle Valo int err; 344e705c121SKalle Valo struct iwl_phy_db_entry *entry; 345e705c121SKalle Valo 346e705c121SKalle Valo /* Send all the channel specific groups to operational fw */ 347e705c121SKalle Valo for (i = 0; i < max_ch_groups; i++) { 348e705c121SKalle Valo entry = iwl_phy_db_get_section(phy_db, 349e705c121SKalle Valo type, 350e705c121SKalle Valo i); 351e705c121SKalle Valo if (!entry) 352e705c121SKalle Valo return -EINVAL; 353e705c121SKalle Valo 354e705c121SKalle Valo if (!entry->size) 355e705c121SKalle Valo continue; 356e705c121SKalle Valo 357e705c121SKalle Valo /* Send the requested PHY DB section */ 358e705c121SKalle Valo err = iwl_send_phy_db_cmd(phy_db, 359e705c121SKalle Valo type, 360e705c121SKalle Valo entry->size, 361e705c121SKalle Valo entry->data); 362e705c121SKalle Valo if (err) { 363e705c121SKalle Valo IWL_ERR(phy_db->trans, 364e705c121SKalle Valo "Can't SEND phy_db section %d (%d), err %d\n", 365e705c121SKalle Valo type, i, err); 366e705c121SKalle Valo return err; 367e705c121SKalle Valo } 368e705c121SKalle Valo 369e705c121SKalle Valo IWL_DEBUG_INFO(phy_db->trans, 370e705c121SKalle Valo "Sent PHY_DB HCMD, type = %d num = %d\n", 371e705c121SKalle Valo type, i); 372e705c121SKalle Valo } 373e705c121SKalle Valo 374e705c121SKalle Valo return 0; 375e705c121SKalle Valo } 376e705c121SKalle Valo 377e705c121SKalle Valo int iwl_send_phy_db_data(struct iwl_phy_db *phy_db) 378e705c121SKalle Valo { 379e705c121SKalle Valo u8 *data = NULL; 380e705c121SKalle Valo u16 size = 0; 381e705c121SKalle Valo int err; 382e705c121SKalle Valo 383e705c121SKalle Valo IWL_DEBUG_INFO(phy_db->trans, 384e705c121SKalle Valo "Sending phy db data and configuration to runtime image\n"); 385e705c121SKalle Valo 386e705c121SKalle Valo /* Send PHY DB CFG section */ 387e705c121SKalle Valo err = iwl_phy_db_get_section_data(phy_db, IWL_PHY_DB_CFG, 388e705c121SKalle Valo &data, &size, 0); 389e705c121SKalle Valo if (err) { 390e705c121SKalle Valo IWL_ERR(phy_db->trans, "Cannot get Phy DB cfg section\n"); 391e705c121SKalle Valo return err; 392e705c121SKalle Valo } 393e705c121SKalle Valo 394e705c121SKalle Valo err = iwl_send_phy_db_cmd(phy_db, IWL_PHY_DB_CFG, size, data); 395e705c121SKalle Valo if (err) { 396e705c121SKalle Valo IWL_ERR(phy_db->trans, 397e705c121SKalle Valo "Cannot send HCMD of Phy DB cfg section\n"); 398e705c121SKalle Valo return err; 399e705c121SKalle Valo } 400e705c121SKalle Valo 401e705c121SKalle Valo err = iwl_phy_db_get_section_data(phy_db, IWL_PHY_DB_CALIB_NCH, 402e705c121SKalle Valo &data, &size, 0); 403e705c121SKalle Valo if (err) { 404e705c121SKalle Valo IWL_ERR(phy_db->trans, 405e705c121SKalle Valo "Cannot get Phy DB non specific channel section\n"); 406e705c121SKalle Valo return err; 407e705c121SKalle Valo } 408e705c121SKalle Valo 409e705c121SKalle Valo err = iwl_send_phy_db_cmd(phy_db, IWL_PHY_DB_CALIB_NCH, size, data); 410e705c121SKalle Valo if (err) { 411e705c121SKalle Valo IWL_ERR(phy_db->trans, 412e705c121SKalle Valo "Cannot send HCMD of Phy DB non specific channel section\n"); 413e705c121SKalle Valo return err; 414e705c121SKalle Valo } 415e705c121SKalle Valo 416e705c121SKalle Valo /* Send all the TXP channel specific data */ 417e705c121SKalle Valo err = iwl_phy_db_send_all_channel_groups(phy_db, 418e705c121SKalle Valo IWL_PHY_DB_CALIB_CHG_PAPD, 4190ec84d1dSSara Sharon phy_db->n_group_papd); 420e705c121SKalle Valo if (err) { 421e705c121SKalle Valo IWL_ERR(phy_db->trans, 422e705c121SKalle Valo "Cannot send channel specific PAPD groups\n"); 423e705c121SKalle Valo return err; 424e705c121SKalle Valo } 425e705c121SKalle Valo 426e705c121SKalle Valo /* Send all the TXP channel specific data */ 427e705c121SKalle Valo err = iwl_phy_db_send_all_channel_groups(phy_db, 428e705c121SKalle Valo IWL_PHY_DB_CALIB_CHG_TXP, 4290ec84d1dSSara Sharon phy_db->n_group_txp); 430e705c121SKalle Valo if (err) { 431e705c121SKalle Valo IWL_ERR(phy_db->trans, 432e705c121SKalle Valo "Cannot send channel specific TX power groups\n"); 433e705c121SKalle Valo return err; 434e705c121SKalle Valo } 435e705c121SKalle Valo 436e705c121SKalle Valo IWL_DEBUG_INFO(phy_db->trans, 437e705c121SKalle Valo "Finished sending phy db non channel data\n"); 438e705c121SKalle Valo return 0; 439e705c121SKalle Valo } 440e705c121SKalle Valo IWL_EXPORT_SYMBOL(iwl_send_phy_db_data); 441