drivers/net/wireless/intel/ipw2x00/libipw_crypto.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/ipw2x00/libipw_crypto.c
Extension
.c
Size
6297 bytes
Lines
247
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 libipw_crypto_alg {
	struct list_head list;
	const struct libipw_crypto_ops *ops;
};

static LIST_HEAD(libipw_crypto_algs);
static DEFINE_SPINLOCK(libipw_crypto_lock);

static void libipw_crypt_deinit_entries(struct libipw_crypt_info *info,
					  int force);
static void libipw_crypt_quiescing(struct libipw_crypt_info *info);
static void libipw_crypt_deinit_handler(struct timer_list *t);

int libipw_crypt_info_init(struct libipw_crypt_info *info, char *name,
				spinlock_t *lock)
{
	memset(info, 0, sizeof(*info));

	info->name = name;
	info->lock = lock;

	INIT_LIST_HEAD(&info->crypt_deinit_list);
	timer_setup(&info->crypt_deinit_timer, libipw_crypt_deinit_handler,
		    0);

	return 0;
}
EXPORT_SYMBOL(libipw_crypt_info_init);

void libipw_crypt_info_free(struct libipw_crypt_info *info)
{
	int i;

        libipw_crypt_quiescing(info);
        timer_delete_sync(&info->crypt_deinit_timer);
        libipw_crypt_deinit_entries(info, 1);

        for (i = 0; i < NUM_WEP_KEYS; i++) {
                struct libipw_crypt_data *crypt = info->crypt[i];
                if (crypt) {
                        if (crypt->ops) {
                                crypt->ops->deinit(crypt->priv);
                                module_put(crypt->ops->owner);
                        }
                        kfree(crypt);
                        info->crypt[i] = NULL;
                }
        }
}
EXPORT_SYMBOL(libipw_crypt_info_free);

static void libipw_crypt_deinit_entries(struct libipw_crypt_info *info,
					int force)
{
	struct libipw_crypt_data *entry, *next;
	unsigned long flags;

	spin_lock_irqsave(info->lock, flags);
	list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) {
		if (atomic_read(&entry->refcnt) != 0 && !force)
			continue;

		list_del(&entry->list);

		if (entry->ops) {
			entry->ops->deinit(entry->priv);
			module_put(entry->ops->owner);
		}
		kfree(entry);
	}
	spin_unlock_irqrestore(info->lock, flags);
}

/* After this, crypt_deinit_list won't accept new members */
static void libipw_crypt_quiescing(struct libipw_crypt_info *info)
{
	unsigned long flags;

	spin_lock_irqsave(info->lock, flags);
	info->crypt_quiesced = 1;
	spin_unlock_irqrestore(info->lock, flags);
}

static void libipw_crypt_deinit_handler(struct timer_list *t)
{
	struct libipw_crypt_info *info = timer_container_of(info, t,
							    crypt_deinit_timer);
	unsigned long flags;

	libipw_crypt_deinit_entries(info, 0);

Annotation

Implementation Notes