Pārlūkot izejas kodu

[PATCH] Add bcm43xx HW RNG support

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Michael Buesch 19 gadi atpakaļ
vecāks
revīzija
71c0cd7042

+ 1 - 0
drivers/net/wireless/bcm43xx/Kconfig

@@ -2,6 +2,7 @@ config BCM43XX
 	tristate "Broadcom BCM43xx wireless support"
 	tristate "Broadcom BCM43xx wireless support"
 	depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
 	depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
 	select FW_LOADER
 	select FW_LOADER
+	select HW_RANDOM
 	---help---
 	---help---
 	  This is an experimental driver for the Broadcom 43xx wireless chip,
 	  This is an experimental driver for the Broadcom 43xx wireless chip,
 	  found in the Apple Airport Extreme and various other devices.
 	  found in the Apple Airport Extreme and various other devices.

+ 6 - 0
drivers/net/wireless/bcm43xx/bcm43xx.h

@@ -1,6 +1,7 @@
 #ifndef BCM43xx_H_
 #ifndef BCM43xx_H_
 #define BCM43xx_H_
 #define BCM43xx_H_
 
 
+#include <linux/hw_random.h>
 #include <linux/version.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
@@ -82,6 +83,7 @@
 #define BCM43xx_MMIO_TSF_1		0x634 /* core rev < 3 only */
 #define BCM43xx_MMIO_TSF_1		0x634 /* core rev < 3 only */
 #define BCM43xx_MMIO_TSF_2		0x636 /* 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_TSF_3		0x638 /* core rev < 3 only */
+#define BCM43xx_MMIO_RNG		0x65A
 #define BCM43xx_MMIO_POWERUP_DELAY	0x6A8
 #define BCM43xx_MMIO_POWERUP_DELAY	0x6A8
 
 
 /* SPROM offsets. */
 /* SPROM offsets. */
@@ -750,6 +752,10 @@ struct bcm43xx_private {
 	const struct firmware *initvals0;
 	const struct firmware *initvals0;
 	const struct firmware *initvals1;
 	const struct firmware *initvals1;
 
 
+	/* Random Number Generator. */
+	struct hwrng rng;
+	char rng_name[20 + 1];
+
 	/* Debugging stuff follows. */
 	/* Debugging stuff follows. */
 #ifdef CONFIG_BCM43XX_DEBUG
 #ifdef CONFIG_BCM43XX_DEBUG
 	struct bcm43xx_dfsentry *dfsentry;
 	struct bcm43xx_dfsentry *dfsentry;

+ 37 - 0
drivers/net/wireless/bcm43xx/bcm43xx_main.c

@@ -3237,6 +3237,39 @@ static void bcm43xx_security_init(struct bcm43xx_private *bcm)
 	bcm43xx_clear_keys(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() */
 /* This is the opposite of bcm43xx_init_board() */
 static void bcm43xx_free_board(struct bcm43xx_private *bcm)
 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_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
 
 
+	bcm43xx_rng_exit(bcm);
 	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
 	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
 		if (!bcm->core_80211[i].available)
 		if (!bcm->core_80211[i].available)
 			continue;
 			continue;
@@ -3325,6 +3359,9 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm)
 		bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
 		bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
 		bcm43xx_mac_enable(bcm);
 		bcm43xx_mac_enable(bcm);
 	}
 	}
+	err = bcm43xx_rng_init(bcm);
+	if (err)
+		goto err_80211_unwind;
 	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
 	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
 	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
 	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
 	dprintk(KERN_INFO PFX "80211 cores initialized\n");
 	dprintk(KERN_INFO PFX "80211 cores initialized\n");