drivers/net/wireless/intel/iwlwifi/iwl-utils.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/iwl-utils.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/iwl-utils.c
Extension
.c
Size
5480 bytes
Lines
196
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (tcp_payload_len > mss) {
			skb_shinfo(tmp)->gso_size = mss;
			skb_shinfo(tmp)->gso_type = ipv4 ? SKB_GSO_TCPV4 :
							   SKB_GSO_TCPV6;
		} else {
			if (qos) {
				u8 *qc;

				if (ipv4)
					ip_send_check(ip_hdr(tmp));

				qc = ieee80211_get_qos_ctl((void *)tmp->data);
				*qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
			}
			skb_shinfo(tmp)->gso_size = 0;
		}

		skb_mark_not_on_list(tmp);
		__skb_queue_tail(mpdus_skbs, tmp);
		i++;
	}

	return 0;
}
IWL_EXPORT_SYMBOL(iwl_tx_tso_segment);
#endif /* CONFIG_INET */

static u32 iwl_div_by_db(u32 value, u8 db)
{
	/*
	 * 2^32 * 10**(i / 10) for i = [1, 10], skipping 0 and simply stopping
	 * at 10 dB and looping instead of using a much larger table.
	 *
	 * Using 64 bit math is overkill, but means the helper does not require
	 * a limit on the input range.
	 */
	static const u32 db_to_val[] = {
		0xcb59185e, 0xa1866ba8, 0x804dce7a, 0x65ea59fe, 0x50f44d89,
		0x404de61f, 0x331426af, 0x2892c18b, 0x203a7e5b, 0x1999999a,
	};

	while (value && db > 0) {
		u8 change = min_t(u8, db, ARRAY_SIZE(db_to_val));

		value = (((u64)value) * db_to_val[change - 1]) >> 32;

		db -= change;
	}

	return value;
}

s8 iwl_average_neg_dbm(const u8 *neg_dbm_values, u8 len)
{
	int average_magnitude;
	u32 average_factor;
	int sum_magnitude = -128;
	u32 sum_factor = 0;
	int i, count = 0;

	/*
	 * To properly average the decibel values (signal values given in dBm)
	 * we need to do the math in linear space.  Doing a linear average of
	 * dB (dBm) values is a bit annoying though due to the large range of
	 * at least -10 to -110 dBm that will not fit into a 32 bit integer.
	 *
	 * A 64 bit integer should be sufficient, but then we still have the
	 * problem that there are no directly usable utility functions
	 * available.
	 *
	 * So, lets not deal with that and instead do much of the calculation
	 * with a 16.16 fixed point integer along with a base in dBm. 16.16 bit
	 * gives us plenty of head-room for adding up a few values and even
	 * doing some math on it. And the tail should be accurate enough too
	 * (1/2^16 is somewhere around -48 dB, so effectively zero).
	 *
	 * i.e. the real value of sum is:
	 *      sum = sum_factor / 2^16 * 10^(sum_magnitude / 10) mW
	 *
	 * However, that does mean we need to be able to bring two values to
	 * a common base, so we need a helper for that.
	 *
	 * Note that this function takes an input with unsigned negative dBm
	 * values but returns a signed dBm (i.e. a negative value).
	 */

	for (i = 0; i < len; i++) {
		int val_magnitude;
		u32 val_factor;

Annotation

Implementation Notes