Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71c0cd70 authored by Michael Buesch's avatar Michael Buesch Committed by Linus Torvalds
Browse files

[PATCH] Add bcm43xx HW RNG support



Signed-off-by: default avatarMichael Buesch <mb@bu3sch.de>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ebc915ad
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ config BCM43XX
	tristate "Broadcom BCM43xx wireless support"
	depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
	select FW_LOADER
	select HW_RANDOM
	---help---
	  This is an experimental driver for the Broadcom 43xx wireless chip,
	  found in the Apple Airport Extreme and various other devices.
+6 −0
Original line number Diff line number Diff line
#ifndef BCM43xx_H_
#define BCM43xx_H_

#include <linux/hw_random.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
@@ -82,6 +83,7 @@
#define BCM43xx_MMIO_TSF_1		0x634 /* core rev < 3 only */
#define BCM43xx_MMIO_TSF_2		0x636 /* core rev < 3 only */
#define BCM43xx_MMIO_TSF_3		0x638 /* core rev < 3 only */
#define BCM43xx_MMIO_RNG		0x65A
#define BCM43xx_MMIO_POWERUP_DELAY	0x6A8

/* SPROM offsets. */
@@ -750,6 +752,10 @@ struct bcm43xx_private {
	const struct firmware *initvals0;
	const struct firmware *initvals1;

	/* Random Number Generator. */
	struct hwrng rng;
	char rng_name[20 + 1];

	/* Debugging stuff follows. */
#ifdef CONFIG_BCM43XX_DEBUG
	struct bcm43xx_dfsentry *dfsentry;
+37 −0
Original line number Diff line number Diff line
@@ -3237,6 +3237,39 @@ static void bcm43xx_security_init(struct bcm43xx_private *bcm)
	bcm43xx_clear_keys(bcm);
}

static int bcm43xx_rng_read(struct hwrng *rng, u32 *data)
{
	struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
	unsigned long flags;

	bcm43xx_lock_irqonly(bcm, flags);
	*data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
	bcm43xx_unlock_irqonly(bcm, flags);

	return (sizeof(u16));
}

static void bcm43xx_rng_exit(struct bcm43xx_private *bcm)
{
	hwrng_unregister(&bcm->rng);
}

static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
{
	int err;

	snprintf(bcm->rng_name, ARRAY_SIZE(bcm->rng_name),
		 "%s_%s", KBUILD_MODNAME, bcm->net_dev->name);
	bcm->rng.name = bcm->rng_name;
	bcm->rng.data_read = bcm43xx_rng_read;
	bcm->rng.priv = (unsigned long)bcm;
	err = hwrng_register(&bcm->rng);
	if (err)
		printk(KERN_ERR PFX "RNG init failed (%d)\n", err);

	return err;
}

/* This is the opposite of bcm43xx_init_board() */
static void bcm43xx_free_board(struct bcm43xx_private *bcm)
{
@@ -3248,6 +3281,7 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm)

	bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);

	bcm43xx_rng_exit(bcm);
	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
		if (!bcm->core_80211[i].available)
			continue;
@@ -3325,6 +3359,9 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm)
		bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
		bcm43xx_mac_enable(bcm);
	}
	err = bcm43xx_rng_init(bcm);
	if (err)
		goto err_80211_unwind;
	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
	dprintk(KERN_INFO PFX "80211 cores initialized\n");