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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/iwl-trans.c
Extension
.c
Size
21493 bytes
Lines
841
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

struct iwl_trans_dev_restart_data {
	struct list_head list;
	unsigned int restart_count;
	time64_t last_error;
	bool backoff;
	char name[];
};

static LIST_HEAD(restart_data_list);
static DEFINE_SPINLOCK(restart_data_lock);

static struct iwl_trans_dev_restart_data *
iwl_trans_get_restart_data(struct device *dev)
{
	struct iwl_trans_dev_restart_data *tmp, *data = NULL;
	const char *name = dev_name(dev);

	spin_lock(&restart_data_lock);
	list_for_each_entry(tmp, &restart_data_list, list) {
		if (strcmp(tmp->name, name))
			continue;
		data = tmp;
		break;
	}
	spin_unlock(&restart_data_lock);

	if (data)
		return data;

	data = kzalloc_flex(*data, name, strlen(name) + 1, GFP_ATOMIC);
	if (!data)
		return NULL;

	strcpy(data->name, name);
	spin_lock(&restart_data_lock);
	list_add_tail(&data->list, &restart_data_list);
	spin_unlock(&restart_data_lock);

	return data;
}

static void iwl_trans_inc_restart_count(struct device *dev)
{
	struct iwl_trans_dev_restart_data *data;

	data = iwl_trans_get_restart_data(dev);
	if (data) {
		data->last_error = ktime_get_boottime_seconds();
		data->restart_count++;
	}
}

void iwl_trans_free_restart_list(void)
{
	struct iwl_trans_dev_restart_data *tmp;

	while ((tmp = list_first_entry_or_null(&restart_data_list,
					       typeof(*tmp), list))) {
		list_del(&tmp->list);
		kfree(tmp);
	}
}

struct iwl_trans_reprobe {
	struct device *dev;
	struct delayed_work work;
};

static void iwl_trans_reprobe_wk(struct work_struct *wk)
{
	struct iwl_trans_reprobe *reprobe;

	reprobe = container_of(wk, typeof(*reprobe), work.work);

	if (device_reprobe(reprobe->dev))
		dev_err(reprobe->dev, "reprobe failed!\n");
	put_device(reprobe->dev);
	kfree(reprobe);
	module_put(THIS_MODULE);
}

static void iwl_trans_schedule_reprobe(struct iwl_trans *trans,
				       unsigned int delay_ms)
{
	struct iwl_trans_reprobe *reprobe;

	/*
	 * get a module reference to avoid doing this while unloading
	 * anyway and to avoid scheduling a work with code that's
	 * being removed.

Annotation

Implementation Notes