Skip to content

Commit

Permalink
iwlwifi: Add TLVs and fields for 16.0 uCode
Browse files Browse the repository at this point in the history
New TLVs for ucode sections that are not known as
instruction or data.

New TLVs for phy-configuration and default calibrations.

Add default calib and phy config fields to iwl_fw.

Signed-off-by: David Spinadel <david.spinadel@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
David Spinadel authored and John W. Linville committed Mar 12, 2012
1 parent 0cedacc commit ed8c836
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 16 deletions.
84 changes: 84 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,25 @@ struct fw_img_parsing {
int sec_counter;
};

/*
* struct fw_sec_parsing: to extract fw section and it's offset from tlv
*/
struct fw_sec_parsing {
__le32 offset;
const u8 data[];
} __packed;

/**
* struct iwl_tlv_calib_data - parse the default calib data from TLV
*
* @ucode_type: the uCode to which the following default calib relates.
* @calib: default calibrations.
*/
struct iwl_tlv_calib_data {
__le32 ucode_type;
__le64 calib;
} __packed;

struct iwl_firmware_pieces {
struct fw_img_parsing img[IWL_UCODE_TYPE_MAX];

Expand Down Expand Up @@ -257,6 +276,47 @@ static void set_sec_offset(struct iwl_firmware_pieces *pieces,
pieces->img[type].sec[sec].offset = offset;
}

/*
* Gets uCode section from tlv.
*/
static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces,
const void *data, enum iwl_ucode_type type,
int size)
{
struct fw_img_parsing *img;
struct fw_sec *sec;
struct fw_sec_parsing *sec_parse;

if (WARN_ON(!pieces || !data || type >= IWL_UCODE_TYPE_MAX))
return -1;

sec_parse = (struct fw_sec_parsing *)data;

img = &pieces->img[type];
sec = &img->sec[img->sec_counter];

sec->offset = le32_to_cpu(sec_parse->offset);
sec->data = sec_parse->data;

++img->sec_counter;

return 0;
}

static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data)
{
struct iwl_tlv_calib_data *def_calib =
(struct iwl_tlv_calib_data *)data;
u32 ucode_type = le32_to_cpu(def_calib->ucode_type);
if (ucode_type >= IWL_UCODE_TYPE_MAX) {
IWL_ERR(drv, "Wrong ucode_type %u for default calibration.\n",
ucode_type);
return -EINVAL;
}
drv->fw.default_calib[ucode_type] = le64_to_cpu(def_calib->calib);
return 0;
}

static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
const struct firmware *ucode_raw,
struct iwl_firmware_pieces *pieces)
Expand Down Expand Up @@ -586,6 +646,29 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
capa->standard_phy_calibration_size =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_SEC_RT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
tlv_len);
break;
case IWL_UCODE_TLV_SEC_INIT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
tlv_len);
break;
case IWL_UCODE_TLV_SEC_WOWLAN:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
tlv_len);
break;
case IWL_UCODE_TLV_DEF_CALIB:
if (tlv_len != sizeof(struct iwl_tlv_calib_data))
goto invalid_tlv_len;
if (iwl_set_default_calib(drv, tlv_data))
goto tlv_error;
break;
case IWL_UCODE_TLV_PHY_SKU:
if (tlv_len != sizeof(u32))
goto invalid_tlv_len;
drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data);
break;
default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;
Expand All @@ -602,6 +685,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,

invalid_tlv_len:
IWL_ERR(drv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
tlv_error:
iwl_print_hex_dump(drv, IWL_DL_FW, tlv_data, tlv_len);

return -EINVAL;
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-fw-file.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_WOWLAN_INST = 16,
IWL_UCODE_TLV_WOWLAN_DATA = 17,
IWL_UCODE_TLV_FLAGS = 18,
IWL_UCODE_TLV_SEC_RT = 19,
IWL_UCODE_TLV_SEC_INIT = 20,
IWL_UCODE_TLV_SEC_WOWLAN = 21,
IWL_UCODE_TLV_DEF_CALIB = 22,
IWL_UCODE_TLV_PHY_SKU = 23,
};

struct iwl_ucode_tlv {
Expand Down
19 changes: 19 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ enum iwl_ucode_tlv_flag {
#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19
#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253

/**
* enum iwl_ucode_type
*
* The type of ucode.
*
* @IWL_UCODE_REGULAR: Normal runtime ucode
* @IWL_UCODE_INIT: Initial ucode
* @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
*/
enum iwl_ucode_type {
IWL_UCODE_REGULAR,
IWL_UCODE_INIT,
IWL_UCODE_WOWLAN,
IWL_UCODE_TYPE_MAX,
};

struct iwl_ucode_capabilities {
u32 max_probe_length;
u32 standard_phy_calibration_size;
Expand Down Expand Up @@ -142,6 +158,9 @@ struct iwl_fw {

u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;

u64 default_calib[IWL_UCODE_TYPE_MAX];
u32 phy_config;
};

#endif /* __iwl_fw_h__ */
16 changes: 0 additions & 16 deletions drivers/net/wireless/iwlwifi/iwl-shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,22 +192,6 @@ struct iwl_hw_params {
const struct iwl_sensitivity_ranges *sens;
};

/**
* enum iwl_ucode_type
*
* The type of ucode.
*
* @IWL_UCODE_REGULAR: Normal runtime ucode
* @IWL_UCODE_INIT: Initial ucode
* @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
*/
enum iwl_ucode_type {
IWL_UCODE_REGULAR,
IWL_UCODE_INIT,
IWL_UCODE_WOWLAN,
IWL_UCODE_TYPE_MAX,
};

/*
* LED mode
* IWL_LED_DEFAULT: use device default
Expand Down

0 comments on commit ed8c836

Please sign in to comment.