aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/carl9170
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2011-08-15 14:09:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-24 14:41:42 -0400
commit00044f17afd36bf6397b9a2a12f242a057449e9a (patch)
tree5b216a3fa13357b352bebd28272e0698380a2b54 /drivers/net/wireless/ath/carl9170
parentacf1771221f2877ab5d36487930cd6a2ecaa73e6 (diff)
carl9170: export HW random number generator
All AR9170 hardware have a 16-Bit random number generator. The documentation claims the values are suitable for "security keys". The "throughput" is around 320Kibit/s. It's slow, but it does work without introducing any special offload firmware commands. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/carl9170')
-rw-r--r--drivers/net/wireless/ath/carl9170/Kconfig14
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h12
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c113
3 files changed, 139 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
index 2d1b821b440..267d5dcf82d 100644
--- a/drivers/net/wireless/ath/carl9170/Kconfig
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
@@ -39,3 +39,17 @@ config CARL9170_WPC
39 bool 39 bool
40 depends on CARL9170 && (INPUT = y || INPUT = CARL9170) 40 depends on CARL9170 && (INPUT = y || INPUT = CARL9170)
41 default y 41 default y
42
43config CARL9170_HWRNG
44 bool "Random number generator"
45 depends on CARL9170 && (HW_RANDOM = y || HW_RANDOM = CARL9170)
46 default n
47 help
48 Provides a hardware random number generator to the kernel.
49
50 SECURITY WARNING: It's relatively easy to eavesdrop all
51 generated random numbers from the transport stream with
52 usbmon [software] or special usb sniffer hardware.
53
54 Say N, unless your setup[i.e.: embedded system] has no
55 other rng source and you can afford to take the risk.
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 74350d63f68..6cfbb419e2f 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -43,6 +43,7 @@
43#include <linux/firmware.h> 43#include <linux/firmware.h>
44#include <linux/completion.h> 44#include <linux/completion.h>
45#include <linux/spinlock.h> 45#include <linux/spinlock.h>
46#include <linux/hw_random.h>
46#include <net/cfg80211.h> 47#include <net/cfg80211.h>
47#include <net/mac80211.h> 48#include <net/mac80211.h>
48#include <linux/usb.h> 49#include <linux/usb.h>
@@ -449,6 +450,17 @@ struct ar9170 {
449 unsigned int off_override; 450 unsigned int off_override;
450 bool state; 451 bool state;
451 } ps; 452 } ps;
453
454#ifdef CONFIG_CARL9170_HWRNG
455# define CARL9170_HWRNG_CACHE_SIZE CARL9170_MAX_CMD_PAYLOAD_LEN
456 struct {
457 struct hwrng rng;
458 bool initialized;
459 char name[30 + 1];
460 u16 cache[CARL9170_HWRNG_CACHE_SIZE / sizeof(u16)];
461 unsigned int cache_idx;
462 } rng;
463#endif /* CONFIG_CARL9170_HWRNG */
452}; 464};
453 465
454enum carl9170_ps_off_override_reasons { 466enum carl9170_ps_off_override_reasons {
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 85cb1bdebaa..782b8f3ae58 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1468,6 +1468,109 @@ static int carl9170_register_wps_button(struct ar9170 *ar)
1468} 1468}
1469#endif /* CONFIG_CARL9170_WPC */ 1469#endif /* CONFIG_CARL9170_WPC */
1470 1470
1471#ifdef CONFIG_CARL9170_HWRNG
1472static int carl9170_rng_get(struct ar9170 *ar)
1473{
1474
1475#define RW (CARL9170_MAX_CMD_PAYLOAD_LEN / sizeof(u32))
1476#define RB (CARL9170_MAX_CMD_PAYLOAD_LEN)
1477
1478 static const __le32 rng_load[RW] = {
1479 [0 ... (RW - 1)] = cpu_to_le32(AR9170_RAND_REG_NUM)};
1480
1481 u32 buf[RW];
1482
1483 unsigned int i, off = 0, transfer, count;
1484 int err;
1485
1486 BUILD_BUG_ON(RB > CARL9170_MAX_CMD_PAYLOAD_LEN);
1487
1488 if (!IS_ACCEPTING_CMD(ar) || !ar->rng.initialized)
1489 return -EAGAIN;
1490
1491 count = ARRAY_SIZE(ar->rng.cache);
1492 while (count) {
1493 err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
1494 RB, (u8 *) rng_load,
1495 RB, (u8 *) buf);
1496 if (err)
1497 return err;
1498
1499 transfer = min_t(unsigned int, count, RW);
1500 for (i = 0; i < transfer; i++)
1501 ar->rng.cache[off + i] = buf[i];
1502
1503 off += transfer;
1504 count -= transfer;
1505 }
1506
1507 ar->rng.cache_idx = 0;
1508
1509#undef RW
1510#undef RB
1511 return 0;
1512}
1513
1514static int carl9170_rng_read(struct hwrng *rng, u32 *data)
1515{
1516 struct ar9170 *ar = (struct ar9170 *)rng->priv;
1517 int ret = -EIO;
1518
1519 mutex_lock(&ar->mutex);
1520 if (ar->rng.cache_idx >= ARRAY_SIZE(ar->rng.cache)) {
1521 ret = carl9170_rng_get(ar);
1522 if (ret) {
1523 mutex_unlock(&ar->mutex);
1524 return ret;
1525 }
1526 }
1527
1528 *data = ar->rng.cache[ar->rng.cache_idx++];
1529 mutex_unlock(&ar->mutex);
1530
1531 return sizeof(u16);
1532}
1533
1534static void carl9170_unregister_hwrng(struct ar9170 *ar)
1535{
1536 if (ar->rng.initialized) {
1537 hwrng_unregister(&ar->rng.rng);
1538 ar->rng.initialized = false;
1539 }
1540}
1541
1542static int carl9170_register_hwrng(struct ar9170 *ar)
1543{
1544 int err;
1545
1546 snprintf(ar->rng.name, ARRAY_SIZE(ar->rng.name),
1547 "%s_%s", KBUILD_MODNAME, wiphy_name(ar->hw->wiphy));
1548 ar->rng.rng.name = ar->rng.name;
1549 ar->rng.rng.data_read = carl9170_rng_read;
1550 ar->rng.rng.priv = (unsigned long)ar;
1551
1552 if (WARN_ON(ar->rng.initialized))
1553 return -EALREADY;
1554
1555 err = hwrng_register(&ar->rng.rng);
1556 if (err) {
1557 dev_err(&ar->udev->dev, "Failed to register the random "
1558 "number generator (%d)\n", err);
1559 return err;
1560 }
1561
1562 ar->rng.initialized = true;
1563
1564 err = carl9170_rng_get(ar);
1565 if (err) {
1566 carl9170_unregister_hwrng(ar);
1567 return err;
1568 }
1569
1570 return 0;
1571}
1572#endif /* CONFIG_CARL9170_HWRNG */
1573
1471static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, 1574static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
1472 struct survey_info *survey) 1575 struct survey_info *survey)
1473{ 1576{
@@ -1878,6 +1981,12 @@ int carl9170_register(struct ar9170 *ar)
1878 goto err_unreg; 1981 goto err_unreg;
1879#endif /* CONFIG_CARL9170_WPC */ 1982#endif /* CONFIG_CARL9170_WPC */
1880 1983
1984#ifdef CONFIG_CARL9170_HWRNG
1985 err = carl9170_register_hwrng(ar);
1986 if (err)
1987 goto err_unreg;
1988#endif /* CONFIG_CARL9170_HWRNG */
1989
1881 dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n", 1990 dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n",
1882 wiphy_name(ar->hw->wiphy)); 1991 wiphy_name(ar->hw->wiphy));
1883 1992
@@ -1910,6 +2019,10 @@ void carl9170_unregister(struct ar9170 *ar)
1910 } 2019 }
1911#endif /* CONFIG_CARL9170_WPC */ 2020#endif /* CONFIG_CARL9170_WPC */
1912 2021
2022#ifdef CONFIG_CARL9170_HWRNG
2023 carl9170_unregister_hwrng(ar);
2024#endif /* CONFIG_CARL9170_HWRNG */
2025
1913 carl9170_cancel_worker(ar); 2026 carl9170_cancel_worker(ar);
1914 cancel_work_sync(&ar->restart_work); 2027 cancel_work_sync(&ar->restart_work);
1915 2028