diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/Kconfig | 11 | ||||
-rw-r--r-- | drivers/char/Makefile | 2 | ||||
-rw-r--r-- | drivers/char/ramoops.c | 8 | ||||
-rw-r--r-- | drivers/char/random.c | 349 | ||||
-rw-r--r-- | drivers/char/tile-srom.c | 481 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 7 |
6 files changed, 516 insertions, 342 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 49502bc5360a..423fd56bf612 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -616,5 +616,16 @@ config MSM_SMD_PKT | |||
616 | Enables userspace clients to read and write to some packet SMD | 616 | Enables userspace clients to read and write to some packet SMD |
617 | ports via device interface for MSM chipset. | 617 | ports via device interface for MSM chipset. |
618 | 618 | ||
619 | config TILE_SROM | ||
620 | bool "Character-device access via hypervisor to the Tilera SPI ROM" | ||
621 | depends on TILE | ||
622 | default y | ||
623 | ---help--- | ||
624 | This device provides character-level read-write access | ||
625 | to the SROM, typically via the "0", "1", and "2" devices | ||
626 | in /dev/srom/. The Tilera hypervisor makes the flash | ||
627 | device appear much like a simple EEPROM, and knows | ||
628 | how to partition a single ROM for multiple purposes. | ||
629 | |||
619 | endmenu | 630 | endmenu |
620 | 631 | ||
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 7a00672bd85d..32762ba769c2 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -63,3 +63,5 @@ obj-$(CONFIG_RAMOOPS) += ramoops.o | |||
63 | 63 | ||
64 | obj-$(CONFIG_JS_RTC) += js-rtc.o | 64 | obj-$(CONFIG_JS_RTC) += js-rtc.o |
65 | js-rtc-y = rtc.o | 65 | js-rtc-y = rtc.o |
66 | |||
67 | obj-$(CONFIG_TILE_SROM) += tile-srom.o | ||
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c index fca0c51bbc90..810aff9e750f 100644 --- a/drivers/char/ramoops.c +++ b/drivers/char/ramoops.c | |||
@@ -147,6 +147,14 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
147 | cxt->phys_addr = pdata->mem_address; | 147 | cxt->phys_addr = pdata->mem_address; |
148 | cxt->record_size = pdata->record_size; | 148 | cxt->record_size = pdata->record_size; |
149 | cxt->dump_oops = pdata->dump_oops; | 149 | cxt->dump_oops = pdata->dump_oops; |
150 | /* | ||
151 | * Update the module parameter variables as well so they are visible | ||
152 | * through /sys/module/ramoops/parameters/ | ||
153 | */ | ||
154 | mem_size = pdata->mem_size; | ||
155 | mem_address = pdata->mem_address; | ||
156 | record_size = pdata->record_size; | ||
157 | dump_oops = pdata->dump_oops; | ||
150 | 158 | ||
151 | if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { | 159 | if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { |
152 | pr_err("request mem region failed\n"); | 160 | pr_err("request mem region failed\n"); |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 729281961f22..c35a785005b0 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1300,345 +1300,14 @@ ctl_table random_table[] = { | |||
1300 | }; | 1300 | }; |
1301 | #endif /* CONFIG_SYSCTL */ | 1301 | #endif /* CONFIG_SYSCTL */ |
1302 | 1302 | ||
1303 | /******************************************************************** | 1303 | static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; |
1304 | * | ||
1305 | * Random functions for networking | ||
1306 | * | ||
1307 | ********************************************************************/ | ||
1308 | |||
1309 | /* | ||
1310 | * TCP initial sequence number picking. This uses the random number | ||
1311 | * generator to pick an initial secret value. This value is hashed | ||
1312 | * along with the TCP endpoint information to provide a unique | ||
1313 | * starting point for each pair of TCP endpoints. This defeats | ||
1314 | * attacks which rely on guessing the initial TCP sequence number. | ||
1315 | * This algorithm was suggested by Steve Bellovin. | ||
1316 | * | ||
1317 | * Using a very strong hash was taking an appreciable amount of the total | ||
1318 | * TCP connection establishment time, so this is a weaker hash, | ||
1319 | * compensated for by changing the secret periodically. | ||
1320 | */ | ||
1321 | |||
1322 | /* F, G and H are basic MD4 functions: selection, majority, parity */ | ||
1323 | #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) | ||
1324 | #define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) | ||
1325 | #define H(x, y, z) ((x) ^ (y) ^ (z)) | ||
1326 | |||
1327 | /* | ||
1328 | * The generic round function. The application is so specific that | ||
1329 | * we don't bother protecting all the arguments with parens, as is generally | ||
1330 | * good macro practice, in favor of extra legibility. | ||
1331 | * Rotation is separate from addition to prevent recomputation | ||
1332 | */ | ||
1333 | #define ROUND(f, a, b, c, d, x, s) \ | ||
1334 | (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s))) | ||
1335 | #define K1 0 | ||
1336 | #define K2 013240474631UL | ||
1337 | #define K3 015666365641UL | ||
1338 | |||
1339 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1340 | |||
1341 | static __u32 twothirdsMD4Transform(__u32 const buf[4], __u32 const in[12]) | ||
1342 | { | ||
1343 | __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; | ||
1344 | |||
1345 | /* Round 1 */ | ||
1346 | ROUND(F, a, b, c, d, in[ 0] + K1, 3); | ||
1347 | ROUND(F, d, a, b, c, in[ 1] + K1, 7); | ||
1348 | ROUND(F, c, d, a, b, in[ 2] + K1, 11); | ||
1349 | ROUND(F, b, c, d, a, in[ 3] + K1, 19); | ||
1350 | ROUND(F, a, b, c, d, in[ 4] + K1, 3); | ||
1351 | ROUND(F, d, a, b, c, in[ 5] + K1, 7); | ||
1352 | ROUND(F, c, d, a, b, in[ 6] + K1, 11); | ||
1353 | ROUND(F, b, c, d, a, in[ 7] + K1, 19); | ||
1354 | ROUND(F, a, b, c, d, in[ 8] + K1, 3); | ||
1355 | ROUND(F, d, a, b, c, in[ 9] + K1, 7); | ||
1356 | ROUND(F, c, d, a, b, in[10] + K1, 11); | ||
1357 | ROUND(F, b, c, d, a, in[11] + K1, 19); | ||
1358 | |||
1359 | /* Round 2 */ | ||
1360 | ROUND(G, a, b, c, d, in[ 1] + K2, 3); | ||
1361 | ROUND(G, d, a, b, c, in[ 3] + K2, 5); | ||
1362 | ROUND(G, c, d, a, b, in[ 5] + K2, 9); | ||
1363 | ROUND(G, b, c, d, a, in[ 7] + K2, 13); | ||
1364 | ROUND(G, a, b, c, d, in[ 9] + K2, 3); | ||
1365 | ROUND(G, d, a, b, c, in[11] + K2, 5); | ||
1366 | ROUND(G, c, d, a, b, in[ 0] + K2, 9); | ||
1367 | ROUND(G, b, c, d, a, in[ 2] + K2, 13); | ||
1368 | ROUND(G, a, b, c, d, in[ 4] + K2, 3); | ||
1369 | ROUND(G, d, a, b, c, in[ 6] + K2, 5); | ||
1370 | ROUND(G, c, d, a, b, in[ 8] + K2, 9); | ||
1371 | ROUND(G, b, c, d, a, in[10] + K2, 13); | ||
1372 | |||
1373 | /* Round 3 */ | ||
1374 | ROUND(H, a, b, c, d, in[ 3] + K3, 3); | ||
1375 | ROUND(H, d, a, b, c, in[ 7] + K3, 9); | ||
1376 | ROUND(H, c, d, a, b, in[11] + K3, 11); | ||
1377 | ROUND(H, b, c, d, a, in[ 2] + K3, 15); | ||
1378 | ROUND(H, a, b, c, d, in[ 6] + K3, 3); | ||
1379 | ROUND(H, d, a, b, c, in[10] + K3, 9); | ||
1380 | ROUND(H, c, d, a, b, in[ 1] + K3, 11); | ||
1381 | ROUND(H, b, c, d, a, in[ 5] + K3, 15); | ||
1382 | ROUND(H, a, b, c, d, in[ 9] + K3, 3); | ||
1383 | ROUND(H, d, a, b, c, in[ 0] + K3, 9); | ||
1384 | ROUND(H, c, d, a, b, in[ 4] + K3, 11); | ||
1385 | ROUND(H, b, c, d, a, in[ 8] + K3, 15); | ||
1386 | |||
1387 | return buf[1] + b; /* "most hashed" word */ | ||
1388 | /* Alternative: return sum of all words? */ | ||
1389 | } | ||
1390 | #endif | ||
1391 | |||
1392 | #undef ROUND | ||
1393 | #undef F | ||
1394 | #undef G | ||
1395 | #undef H | ||
1396 | #undef K1 | ||
1397 | #undef K2 | ||
1398 | #undef K3 | ||
1399 | |||
1400 | /* This should not be decreased so low that ISNs wrap too fast. */ | ||
1401 | #define REKEY_INTERVAL (300 * HZ) | ||
1402 | /* | ||
1403 | * Bit layout of the tcp sequence numbers (before adding current time): | ||
1404 | * bit 24-31: increased after every key exchange | ||
1405 | * bit 0-23: hash(source,dest) | ||
1406 | * | ||
1407 | * The implementation is similar to the algorithm described | ||
1408 | * in the Appendix of RFC 1185, except that | ||
1409 | * - it uses a 1 MHz clock instead of a 250 kHz clock | ||
1410 | * - it performs a rekey every 5 minutes, which is equivalent | ||
1411 | * to a (source,dest) tulple dependent forward jump of the | ||
1412 | * clock by 0..2^(HASH_BITS+1) | ||
1413 | * | ||
1414 | * Thus the average ISN wraparound time is 68 minutes instead of | ||
1415 | * 4.55 hours. | ||
1416 | * | ||
1417 | * SMP cleanup and lock avoidance with poor man's RCU. | ||
1418 | * Manfred Spraul <manfred@colorfullife.com> | ||
1419 | * | ||
1420 | */ | ||
1421 | #define COUNT_BITS 8 | ||
1422 | #define COUNT_MASK ((1 << COUNT_BITS) - 1) | ||
1423 | #define HASH_BITS 24 | ||
1424 | #define HASH_MASK ((1 << HASH_BITS) - 1) | ||
1425 | 1304 | ||
1426 | static struct keydata { | 1305 | static int __init random_int_secret_init(void) |
1427 | __u32 count; /* already shifted to the final position */ | ||
1428 | __u32 secret[12]; | ||
1429 | } ____cacheline_aligned ip_keydata[2]; | ||
1430 | |||
1431 | static unsigned int ip_cnt; | ||
1432 | |||
1433 | static void rekey_seq_generator(struct work_struct *work); | ||
1434 | |||
1435 | static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator); | ||
1436 | |||
1437 | /* | ||
1438 | * Lock avoidance: | ||
1439 | * The ISN generation runs lockless - it's just a hash over random data. | ||
1440 | * State changes happen every 5 minutes when the random key is replaced. | ||
1441 | * Synchronization is performed by having two copies of the hash function | ||
1442 | * state and rekey_seq_generator always updates the inactive copy. | ||
1443 | * The copy is then activated by updating ip_cnt. | ||
1444 | * The implementation breaks down if someone blocks the thread | ||
1445 | * that processes SYN requests for more than 5 minutes. Should never | ||
1446 | * happen, and even if that happens only a not perfectly compliant | ||
1447 | * ISN is generated, nothing fatal. | ||
1448 | */ | ||
1449 | static void rekey_seq_generator(struct work_struct *work) | ||
1450 | { | 1306 | { |
1451 | struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)]; | 1307 | get_random_bytes(random_int_secret, sizeof(random_int_secret)); |
1452 | |||
1453 | get_random_bytes(keyptr->secret, sizeof(keyptr->secret)); | ||
1454 | keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS; | ||
1455 | smp_wmb(); | ||
1456 | ip_cnt++; | ||
1457 | schedule_delayed_work(&rekey_work, | ||
1458 | round_jiffies_relative(REKEY_INTERVAL)); | ||
1459 | } | ||
1460 | |||
1461 | static inline struct keydata *get_keyptr(void) | ||
1462 | { | ||
1463 | struct keydata *keyptr = &ip_keydata[ip_cnt & 1]; | ||
1464 | |||
1465 | smp_rmb(); | ||
1466 | |||
1467 | return keyptr; | ||
1468 | } | ||
1469 | |||
1470 | static __init int seqgen_init(void) | ||
1471 | { | ||
1472 | rekey_seq_generator(NULL); | ||
1473 | return 0; | 1308 | return 0; |
1474 | } | 1309 | } |
1475 | late_initcall(seqgen_init); | 1310 | late_initcall(random_int_secret_init); |
1476 | |||
1477 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1478 | __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr, | ||
1479 | __be16 sport, __be16 dport) | ||
1480 | { | ||
1481 | __u32 seq; | ||
1482 | __u32 hash[12]; | ||
1483 | struct keydata *keyptr = get_keyptr(); | ||
1484 | |||
1485 | /* The procedure is the same as for IPv4, but addresses are longer. | ||
1486 | * Thus we must use twothirdsMD4Transform. | ||
1487 | */ | ||
1488 | |||
1489 | memcpy(hash, saddr, 16); | ||
1490 | hash[4] = ((__force u16)sport << 16) + (__force u16)dport; | ||
1491 | memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7); | ||
1492 | |||
1493 | seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK; | ||
1494 | seq += keyptr->count; | ||
1495 | |||
1496 | seq += ktime_to_ns(ktime_get_real()); | ||
1497 | |||
1498 | return seq; | ||
1499 | } | ||
1500 | EXPORT_SYMBOL(secure_tcpv6_sequence_number); | ||
1501 | #endif | ||
1502 | |||
1503 | /* The code below is shamelessly stolen from secure_tcp_sequence_number(). | ||
1504 | * All blames to Andrey V. Savochkin <saw@msu.ru>. | ||
1505 | */ | ||
1506 | __u32 secure_ip_id(__be32 daddr) | ||
1507 | { | ||
1508 | struct keydata *keyptr; | ||
1509 | __u32 hash[4]; | ||
1510 | |||
1511 | keyptr = get_keyptr(); | ||
1512 | |||
1513 | /* | ||
1514 | * Pick a unique starting offset for each IP destination. | ||
1515 | * The dest ip address is placed in the starting vector, | ||
1516 | * which is then hashed with random data. | ||
1517 | */ | ||
1518 | hash[0] = (__force __u32)daddr; | ||
1519 | hash[1] = keyptr->secret[9]; | ||
1520 | hash[2] = keyptr->secret[10]; | ||
1521 | hash[3] = keyptr->secret[11]; | ||
1522 | |||
1523 | return half_md4_transform(hash, keyptr->secret); | ||
1524 | } | ||
1525 | |||
1526 | __u32 secure_ipv6_id(const __be32 daddr[4]) | ||
1527 | { | ||
1528 | const struct keydata *keyptr; | ||
1529 | __u32 hash[4]; | ||
1530 | |||
1531 | keyptr = get_keyptr(); | ||
1532 | |||
1533 | hash[0] = (__force __u32)daddr[0]; | ||
1534 | hash[1] = (__force __u32)daddr[1]; | ||
1535 | hash[2] = (__force __u32)daddr[2]; | ||
1536 | hash[3] = (__force __u32)daddr[3]; | ||
1537 | |||
1538 | return half_md4_transform(hash, keyptr->secret); | ||
1539 | } | ||
1540 | |||
1541 | #ifdef CONFIG_INET | ||
1542 | |||
1543 | __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, | ||
1544 | __be16 sport, __be16 dport) | ||
1545 | { | ||
1546 | __u32 seq; | ||
1547 | __u32 hash[4]; | ||
1548 | struct keydata *keyptr = get_keyptr(); | ||
1549 | |||
1550 | /* | ||
1551 | * Pick a unique starting offset for each TCP connection endpoints | ||
1552 | * (saddr, daddr, sport, dport). | ||
1553 | * Note that the words are placed into the starting vector, which is | ||
1554 | * then mixed with a partial MD4 over random data. | ||
1555 | */ | ||
1556 | hash[0] = (__force u32)saddr; | ||
1557 | hash[1] = (__force u32)daddr; | ||
1558 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; | ||
1559 | hash[3] = keyptr->secret[11]; | ||
1560 | |||
1561 | seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK; | ||
1562 | seq += keyptr->count; | ||
1563 | /* | ||
1564 | * As close as possible to RFC 793, which | ||
1565 | * suggests using a 250 kHz clock. | ||
1566 | * Further reading shows this assumes 2 Mb/s networks. | ||
1567 | * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate. | ||
1568 | * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but | ||
1569 | * we also need to limit the resolution so that the u32 seq | ||
1570 | * overlaps less than one time per MSL (2 minutes). | ||
1571 | * Choosing a clock of 64 ns period is OK. (period of 274 s) | ||
1572 | */ | ||
1573 | seq += ktime_to_ns(ktime_get_real()) >> 6; | ||
1574 | |||
1575 | return seq; | ||
1576 | } | ||
1577 | |||
1578 | /* Generate secure starting point for ephemeral IPV4 transport port search */ | ||
1579 | u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) | ||
1580 | { | ||
1581 | struct keydata *keyptr = get_keyptr(); | ||
1582 | u32 hash[4]; | ||
1583 | |||
1584 | /* | ||
1585 | * Pick a unique starting offset for each ephemeral port search | ||
1586 | * (saddr, daddr, dport) and 48bits of random data. | ||
1587 | */ | ||
1588 | hash[0] = (__force u32)saddr; | ||
1589 | hash[1] = (__force u32)daddr; | ||
1590 | hash[2] = (__force u32)dport ^ keyptr->secret[10]; | ||
1591 | hash[3] = keyptr->secret[11]; | ||
1592 | |||
1593 | return half_md4_transform(hash, keyptr->secret); | ||
1594 | } | ||
1595 | EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); | ||
1596 | |||
1597 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1598 | u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, | ||
1599 | __be16 dport) | ||
1600 | { | ||
1601 | struct keydata *keyptr = get_keyptr(); | ||
1602 | u32 hash[12]; | ||
1603 | |||
1604 | memcpy(hash, saddr, 16); | ||
1605 | hash[4] = (__force u32)dport; | ||
1606 | memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7); | ||
1607 | |||
1608 | return twothirdsMD4Transform((const __u32 *)daddr, hash); | ||
1609 | } | ||
1610 | #endif | ||
1611 | |||
1612 | #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) | ||
1613 | /* Similar to secure_tcp_sequence_number but generate a 48 bit value | ||
1614 | * bit's 32-47 increase every key exchange | ||
1615 | * 0-31 hash(source, dest) | ||
1616 | */ | ||
1617 | u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, | ||
1618 | __be16 sport, __be16 dport) | ||
1619 | { | ||
1620 | u64 seq; | ||
1621 | __u32 hash[4]; | ||
1622 | struct keydata *keyptr = get_keyptr(); | ||
1623 | |||
1624 | hash[0] = (__force u32)saddr; | ||
1625 | hash[1] = (__force u32)daddr; | ||
1626 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; | ||
1627 | hash[3] = keyptr->secret[11]; | ||
1628 | |||
1629 | seq = half_md4_transform(hash, keyptr->secret); | ||
1630 | seq |= ((u64)keyptr->count) << (32 - HASH_BITS); | ||
1631 | |||
1632 | seq += ktime_to_ns(ktime_get_real()); | ||
1633 | seq &= (1ull << 48) - 1; | ||
1634 | |||
1635 | return seq; | ||
1636 | } | ||
1637 | EXPORT_SYMBOL(secure_dccp_sequence_number); | ||
1638 | #endif | ||
1639 | |||
1640 | #endif /* CONFIG_INET */ | ||
1641 | |||
1642 | 1311 | ||
1643 | /* | 1312 | /* |
1644 | * Get a random word for internal kernel use only. Similar to urandom but | 1313 | * Get a random word for internal kernel use only. Similar to urandom but |
@@ -1646,17 +1315,15 @@ EXPORT_SYMBOL(secure_dccp_sequence_number); | |||
1646 | * value is not cryptographically secure but for several uses the cost of | 1315 | * value is not cryptographically secure but for several uses the cost of |
1647 | * depleting entropy is too high | 1316 | * depleting entropy is too high |
1648 | */ | 1317 | */ |
1649 | DEFINE_PER_CPU(__u32 [4], get_random_int_hash); | 1318 | DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash); |
1650 | unsigned int get_random_int(void) | 1319 | unsigned int get_random_int(void) |
1651 | { | 1320 | { |
1652 | struct keydata *keyptr; | ||
1653 | __u32 *hash = get_cpu_var(get_random_int_hash); | 1321 | __u32 *hash = get_cpu_var(get_random_int_hash); |
1654 | int ret; | 1322 | unsigned int ret; |
1655 | 1323 | ||
1656 | keyptr = get_keyptr(); | ||
1657 | hash[0] += current->pid + jiffies + get_cycles(); | 1324 | hash[0] += current->pid + jiffies + get_cycles(); |
1658 | 1325 | md5_transform(hash, random_int_secret); | |
1659 | ret = half_md4_transform(hash, keyptr->secret); | 1326 | ret = hash[0]; |
1660 | put_cpu_var(get_random_int_hash); | 1327 | put_cpu_var(get_random_int_hash); |
1661 | 1328 | ||
1662 | return ret; | 1329 | return ret; |
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c new file mode 100644 index 000000000000..cf3ee008dca2 --- /dev/null +++ b/drivers/char/tile-srom.c | |||
@@ -0,0 +1,481 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * SPI Flash ROM driver | ||
15 | * | ||
16 | * This source code is derived from code provided in "Linux Device | ||
17 | * Drivers, Third Edition", by Jonathan Corbet, Alessandro Rubini, and | ||
18 | * Greg Kroah-Hartman, published by O'Reilly Media, Inc. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/kernel.h> /* printk() */ | ||
25 | #include <linux/slab.h> /* kmalloc() */ | ||
26 | #include <linux/fs.h> /* everything... */ | ||
27 | #include <linux/errno.h> /* error codes */ | ||
28 | #include <linux/types.h> /* size_t */ | ||
29 | #include <linux/proc_fs.h> | ||
30 | #include <linux/fcntl.h> /* O_ACCMODE */ | ||
31 | #include <linux/aio.h> | ||
32 | #include <linux/pagemap.h> | ||
33 | #include <linux/hugetlb.h> | ||
34 | #include <linux/uaccess.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | #include <hv/hypervisor.h> | ||
37 | #include <linux/ioctl.h> | ||
38 | #include <linux/cdev.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <hv/drv_srom_intf.h> | ||
41 | |||
42 | /* | ||
43 | * Size of our hypervisor I/O requests. We break up large transfers | ||
44 | * so that we don't spend large uninterrupted spans of time in the | ||
45 | * hypervisor. Erasing an SROM sector takes a significant fraction of | ||
46 | * a second, so if we allowed the user to, say, do one I/O to write the | ||
47 | * entire ROM, we'd get soft lockup timeouts, or worse. | ||
48 | */ | ||
49 | #define SROM_CHUNK_SIZE ((size_t)4096) | ||
50 | |||
51 | /* | ||
52 | * When hypervisor is busy (e.g. erasing), poll the status periodically. | ||
53 | */ | ||
54 | |||
55 | /* | ||
56 | * Interval to poll the state in msec | ||
57 | */ | ||
58 | #define SROM_WAIT_TRY_INTERVAL 20 | ||
59 | |||
60 | /* | ||
61 | * Maximum times to poll the state | ||
62 | */ | ||
63 | #define SROM_MAX_WAIT_TRY_TIMES 1000 | ||
64 | |||
65 | struct srom_dev { | ||
66 | int hv_devhdl; /* Handle for hypervisor device */ | ||
67 | u32 total_size; /* Size of this device */ | ||
68 | u32 sector_size; /* Size of a sector */ | ||
69 | u32 page_size; /* Size of a page */ | ||
70 | struct mutex lock; /* Allow only one accessor at a time */ | ||
71 | }; | ||
72 | |||
73 | static int srom_major; /* Dynamic major by default */ | ||
74 | module_param(srom_major, int, 0); | ||
75 | MODULE_AUTHOR("Tilera Corporation"); | ||
76 | MODULE_LICENSE("GPL"); | ||
77 | |||
78 | static int srom_devs; /* Number of SROM partitions */ | ||
79 | static struct cdev srom_cdev; | ||
80 | static struct class *srom_class; | ||
81 | static struct srom_dev *srom_devices; | ||
82 | |||
83 | /* | ||
84 | * Handle calling the hypervisor and managing EAGAIN/EBUSY. | ||
85 | */ | ||
86 | |||
87 | static ssize_t _srom_read(int hv_devhdl, void *buf, | ||
88 | loff_t off, size_t count) | ||
89 | { | ||
90 | int retval, retries = SROM_MAX_WAIT_TRY_TIMES; | ||
91 | for (;;) { | ||
92 | retval = hv_dev_pread(hv_devhdl, 0, (HV_VirtAddr)buf, | ||
93 | count, off); | ||
94 | if (retval >= 0) | ||
95 | return retval; | ||
96 | if (retval == HV_EAGAIN) | ||
97 | continue; | ||
98 | if (retval == HV_EBUSY && --retries > 0) { | ||
99 | msleep(SROM_WAIT_TRY_INTERVAL); | ||
100 | continue; | ||
101 | } | ||
102 | pr_err("_srom_read: error %d\n", retval); | ||
103 | return -EIO; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static ssize_t _srom_write(int hv_devhdl, const void *buf, | ||
108 | loff_t off, size_t count) | ||
109 | { | ||
110 | int retval, retries = SROM_MAX_WAIT_TRY_TIMES; | ||
111 | for (;;) { | ||
112 | retval = hv_dev_pwrite(hv_devhdl, 0, (HV_VirtAddr)buf, | ||
113 | count, off); | ||
114 | if (retval >= 0) | ||
115 | return retval; | ||
116 | if (retval == HV_EAGAIN) | ||
117 | continue; | ||
118 | if (retval == HV_EBUSY && --retries > 0) { | ||
119 | msleep(SROM_WAIT_TRY_INTERVAL); | ||
120 | continue; | ||
121 | } | ||
122 | pr_err("_srom_write: error %d\n", retval); | ||
123 | return -EIO; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * srom_open() - Device open routine. | ||
129 | * @inode: Inode for this device. | ||
130 | * @filp: File for this specific open of the device. | ||
131 | * | ||
132 | * Returns zero, or an error code. | ||
133 | */ | ||
134 | static int srom_open(struct inode *inode, struct file *filp) | ||
135 | { | ||
136 | filp->private_data = &srom_devices[iminor(inode)]; | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | |||
141 | /** | ||
142 | * srom_release() - Device release routine. | ||
143 | * @inode: Inode for this device. | ||
144 | * @filp: File for this specific open of the device. | ||
145 | * | ||
146 | * Returns zero, or an error code. | ||
147 | */ | ||
148 | static int srom_release(struct inode *inode, struct file *filp) | ||
149 | { | ||
150 | struct srom_dev *srom = filp->private_data; | ||
151 | char dummy; | ||
152 | |||
153 | /* Make sure we've flushed anything written to the ROM. */ | ||
154 | mutex_lock(&srom->lock); | ||
155 | if (srom->hv_devhdl >= 0) | ||
156 | _srom_write(srom->hv_devhdl, &dummy, SROM_FLUSH_OFF, 1); | ||
157 | mutex_unlock(&srom->lock); | ||
158 | |||
159 | filp->private_data = NULL; | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | |||
165 | /** | ||
166 | * srom_read() - Read data from the device. | ||
167 | * @filp: File for this specific open of the device. | ||
168 | * @buf: User's data buffer. | ||
169 | * @count: Number of bytes requested. | ||
170 | * @f_pos: File position. | ||
171 | * | ||
172 | * Returns number of bytes read, or an error code. | ||
173 | */ | ||
174 | static ssize_t srom_read(struct file *filp, char __user *buf, | ||
175 | size_t count, loff_t *f_pos) | ||
176 | { | ||
177 | int retval = 0; | ||
178 | void *kernbuf; | ||
179 | struct srom_dev *srom = filp->private_data; | ||
180 | |||
181 | kernbuf = kmalloc(SROM_CHUNK_SIZE, GFP_KERNEL); | ||
182 | if (!kernbuf) | ||
183 | return -ENOMEM; | ||
184 | |||
185 | if (mutex_lock_interruptible(&srom->lock)) { | ||
186 | retval = -ERESTARTSYS; | ||
187 | kfree(kernbuf); | ||
188 | return retval; | ||
189 | } | ||
190 | |||
191 | while (count) { | ||
192 | int hv_retval; | ||
193 | int bytes_this_pass = min(count, SROM_CHUNK_SIZE); | ||
194 | |||
195 | hv_retval = _srom_read(srom->hv_devhdl, kernbuf, | ||
196 | *f_pos, bytes_this_pass); | ||
197 | if (hv_retval > 0) { | ||
198 | if (copy_to_user(buf, kernbuf, hv_retval) != 0) { | ||
199 | retval = -EFAULT; | ||
200 | break; | ||
201 | } | ||
202 | } else if (hv_retval <= 0) { | ||
203 | if (retval == 0) | ||
204 | retval = hv_retval; | ||
205 | break; | ||
206 | } | ||
207 | |||
208 | retval += hv_retval; | ||
209 | *f_pos += hv_retval; | ||
210 | buf += hv_retval; | ||
211 | count -= hv_retval; | ||
212 | } | ||
213 | |||
214 | mutex_unlock(&srom->lock); | ||
215 | kfree(kernbuf); | ||
216 | |||
217 | return retval; | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * srom_write() - Write data to the device. | ||
222 | * @filp: File for this specific open of the device. | ||
223 | * @buf: User's data buffer. | ||
224 | * @count: Number of bytes requested. | ||
225 | * @f_pos: File position. | ||
226 | * | ||
227 | * Returns number of bytes written, or an error code. | ||
228 | */ | ||
229 | static ssize_t srom_write(struct file *filp, const char __user *buf, | ||
230 | size_t count, loff_t *f_pos) | ||
231 | { | ||
232 | int retval = 0; | ||
233 | void *kernbuf; | ||
234 | struct srom_dev *srom = filp->private_data; | ||
235 | |||
236 | kernbuf = kmalloc(SROM_CHUNK_SIZE, GFP_KERNEL); | ||
237 | if (!kernbuf) | ||
238 | return -ENOMEM; | ||
239 | |||
240 | if (mutex_lock_interruptible(&srom->lock)) { | ||
241 | retval = -ERESTARTSYS; | ||
242 | kfree(kernbuf); | ||
243 | return retval; | ||
244 | } | ||
245 | |||
246 | while (count) { | ||
247 | int hv_retval; | ||
248 | int bytes_this_pass = min(count, SROM_CHUNK_SIZE); | ||
249 | |||
250 | if (copy_from_user(kernbuf, buf, bytes_this_pass) != 0) { | ||
251 | retval = -EFAULT; | ||
252 | break; | ||
253 | } | ||
254 | |||
255 | hv_retval = _srom_write(srom->hv_devhdl, kernbuf, | ||
256 | *f_pos, bytes_this_pass); | ||
257 | if (hv_retval <= 0) { | ||
258 | if (retval == 0) | ||
259 | retval = hv_retval; | ||
260 | break; | ||
261 | } | ||
262 | |||
263 | retval += hv_retval; | ||
264 | *f_pos += hv_retval; | ||
265 | buf += hv_retval; | ||
266 | count -= hv_retval; | ||
267 | } | ||
268 | |||
269 | mutex_unlock(&srom->lock); | ||
270 | kfree(kernbuf); | ||
271 | |||
272 | return retval; | ||
273 | } | ||
274 | |||
275 | /* Provide our own implementation so we can use srom->total_size. */ | ||
276 | loff_t srom_llseek(struct file *filp, loff_t offset, int origin) | ||
277 | { | ||
278 | struct srom_dev *srom = filp->private_data; | ||
279 | |||
280 | if (mutex_lock_interruptible(&srom->lock)) | ||
281 | return -ERESTARTSYS; | ||
282 | |||
283 | switch (origin) { | ||
284 | case SEEK_END: | ||
285 | offset += srom->total_size; | ||
286 | break; | ||
287 | case SEEK_CUR: | ||
288 | offset += filp->f_pos; | ||
289 | break; | ||
290 | } | ||
291 | |||
292 | if (offset < 0 || offset > srom->total_size) { | ||
293 | offset = -EINVAL; | ||
294 | } else { | ||
295 | filp->f_pos = offset; | ||
296 | filp->f_version = 0; | ||
297 | } | ||
298 | |||
299 | mutex_unlock(&srom->lock); | ||
300 | |||
301 | return offset; | ||
302 | } | ||
303 | |||
304 | static ssize_t total_show(struct device *dev, | ||
305 | struct device_attribute *attr, char *buf) | ||
306 | { | ||
307 | struct srom_dev *srom = dev_get_drvdata(dev); | ||
308 | return sprintf(buf, "%u\n", srom->total_size); | ||
309 | } | ||
310 | |||
311 | static ssize_t sector_show(struct device *dev, | ||
312 | struct device_attribute *attr, char *buf) | ||
313 | { | ||
314 | struct srom_dev *srom = dev_get_drvdata(dev); | ||
315 | return sprintf(buf, "%u\n", srom->sector_size); | ||
316 | } | ||
317 | |||
318 | static ssize_t page_show(struct device *dev, | ||
319 | struct device_attribute *attr, char *buf) | ||
320 | { | ||
321 | struct srom_dev *srom = dev_get_drvdata(dev); | ||
322 | return sprintf(buf, "%u\n", srom->page_size); | ||
323 | } | ||
324 | |||
325 | static struct device_attribute srom_dev_attrs[] = { | ||
326 | __ATTR(total_size, S_IRUGO, total_show, NULL), | ||
327 | __ATTR(sector_size, S_IRUGO, sector_show, NULL), | ||
328 | __ATTR(page_size, S_IRUGO, page_show, NULL), | ||
329 | __ATTR_NULL | ||
330 | }; | ||
331 | |||
332 | static char *srom_devnode(struct device *dev, mode_t *mode) | ||
333 | { | ||
334 | *mode = S_IRUGO | S_IWUSR; | ||
335 | return kasprintf(GFP_KERNEL, "srom/%s", dev_name(dev)); | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | * The fops | ||
340 | */ | ||
341 | static const struct file_operations srom_fops = { | ||
342 | .owner = THIS_MODULE, | ||
343 | .llseek = srom_llseek, | ||
344 | .read = srom_read, | ||
345 | .write = srom_write, | ||
346 | .open = srom_open, | ||
347 | .release = srom_release, | ||
348 | }; | ||
349 | |||
350 | /** | ||
351 | * srom_setup_minor() - Initialize per-minor information. | ||
352 | * @srom: Per-device SROM state. | ||
353 | * @index: Device to set up. | ||
354 | */ | ||
355 | static int srom_setup_minor(struct srom_dev *srom, int index) | ||
356 | { | ||
357 | struct device *dev; | ||
358 | int devhdl = srom->hv_devhdl; | ||
359 | |||
360 | mutex_init(&srom->lock); | ||
361 | |||
362 | if (_srom_read(devhdl, &srom->total_size, | ||
363 | SROM_TOTAL_SIZE_OFF, sizeof(srom->total_size)) < 0) | ||
364 | return -EIO; | ||
365 | if (_srom_read(devhdl, &srom->sector_size, | ||
366 | SROM_SECTOR_SIZE_OFF, sizeof(srom->sector_size)) < 0) | ||
367 | return -EIO; | ||
368 | if (_srom_read(devhdl, &srom->page_size, | ||
369 | SROM_PAGE_SIZE_OFF, sizeof(srom->page_size)) < 0) | ||
370 | return -EIO; | ||
371 | |||
372 | dev = device_create(srom_class, &platform_bus, | ||
373 | MKDEV(srom_major, index), srom, "%d", index); | ||
374 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; | ||
375 | } | ||
376 | |||
377 | /** srom_init() - Initialize the driver's module. */ | ||
378 | static int srom_init(void) | ||
379 | { | ||
380 | int result, i; | ||
381 | dev_t dev = MKDEV(srom_major, 0); | ||
382 | |||
383 | /* | ||
384 | * Start with a plausible number of partitions; the krealloc() call | ||
385 | * below will yield about log(srom_devs) additional allocations. | ||
386 | */ | ||
387 | srom_devices = kzalloc(4 * sizeof(struct srom_dev), GFP_KERNEL); | ||
388 | |||
389 | /* Discover the number of srom partitions. */ | ||
390 | for (i = 0; ; i++) { | ||
391 | int devhdl; | ||
392 | char buf[20]; | ||
393 | struct srom_dev *new_srom_devices = | ||
394 | krealloc(srom_devices, (i+1) * sizeof(struct srom_dev), | ||
395 | GFP_KERNEL | __GFP_ZERO); | ||
396 | if (!new_srom_devices) { | ||
397 | result = -ENOMEM; | ||
398 | goto fail_mem; | ||
399 | } | ||
400 | srom_devices = new_srom_devices; | ||
401 | sprintf(buf, "srom/0/%d", i); | ||
402 | devhdl = hv_dev_open((HV_VirtAddr)buf, 0); | ||
403 | if (devhdl < 0) { | ||
404 | if (devhdl != HV_ENODEV) | ||
405 | pr_notice("srom/%d: hv_dev_open failed: %d.\n", | ||
406 | i, devhdl); | ||
407 | break; | ||
408 | } | ||
409 | srom_devices[i].hv_devhdl = devhdl; | ||
410 | } | ||
411 | srom_devs = i; | ||
412 | |||
413 | /* Bail out early if we have no partitions at all. */ | ||
414 | if (srom_devs == 0) { | ||
415 | result = -ENODEV; | ||
416 | goto fail_mem; | ||
417 | } | ||
418 | |||
419 | /* Register our major, and accept a dynamic number. */ | ||
420 | if (srom_major) | ||
421 | result = register_chrdev_region(dev, srom_devs, "srom"); | ||
422 | else { | ||
423 | result = alloc_chrdev_region(&dev, 0, srom_devs, "srom"); | ||
424 | srom_major = MAJOR(dev); | ||
425 | } | ||
426 | if (result < 0) | ||
427 | goto fail_mem; | ||
428 | |||
429 | /* Register a character device. */ | ||
430 | cdev_init(&srom_cdev, &srom_fops); | ||
431 | srom_cdev.owner = THIS_MODULE; | ||
432 | srom_cdev.ops = &srom_fops; | ||
433 | result = cdev_add(&srom_cdev, dev, srom_devs); | ||
434 | if (result < 0) | ||
435 | goto fail_chrdev; | ||
436 | |||
437 | /* Create a sysfs class. */ | ||
438 | srom_class = class_create(THIS_MODULE, "srom"); | ||
439 | if (IS_ERR(srom_class)) { | ||
440 | result = PTR_ERR(srom_class); | ||
441 | goto fail_cdev; | ||
442 | } | ||
443 | srom_class->dev_attrs = srom_dev_attrs; | ||
444 | srom_class->devnode = srom_devnode; | ||
445 | |||
446 | /* Do per-partition initialization */ | ||
447 | for (i = 0; i < srom_devs; i++) { | ||
448 | result = srom_setup_minor(srom_devices + i, i); | ||
449 | if (result < 0) | ||
450 | goto fail_class; | ||
451 | } | ||
452 | |||
453 | return 0; | ||
454 | |||
455 | fail_class: | ||
456 | for (i = 0; i < srom_devs; i++) | ||
457 | device_destroy(srom_class, MKDEV(srom_major, i)); | ||
458 | class_destroy(srom_class); | ||
459 | fail_cdev: | ||
460 | cdev_del(&srom_cdev); | ||
461 | fail_chrdev: | ||
462 | unregister_chrdev_region(dev, srom_devs); | ||
463 | fail_mem: | ||
464 | kfree(srom_devices); | ||
465 | return result; | ||
466 | } | ||
467 | |||
468 | /** srom_cleanup() - Clean up the driver's module. */ | ||
469 | static void srom_cleanup(void) | ||
470 | { | ||
471 | int i; | ||
472 | for (i = 0; i < srom_devs; i++) | ||
473 | device_destroy(srom_class, MKDEV(srom_major, i)); | ||
474 | class_destroy(srom_class); | ||
475 | cdev_del(&srom_cdev); | ||
476 | unregister_chrdev_region(MKDEV(srom_major, 0), srom_devs); | ||
477 | kfree(srom_devices); | ||
478 | } | ||
479 | |||
480 | module_init(srom_init); | ||
481 | module_exit(srom_cleanup); | ||
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 7fc2f108f490..3f4051a7c5a7 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -80,7 +80,7 @@ enum tis_defaults { | |||
80 | static LIST_HEAD(tis_chips); | 80 | static LIST_HEAD(tis_chips); |
81 | static DEFINE_SPINLOCK(tis_lock); | 81 | static DEFINE_SPINLOCK(tis_lock); |
82 | 82 | ||
83 | #ifdef CONFIG_PNP | 83 | #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) |
84 | static int is_itpm(struct pnp_dev *dev) | 84 | static int is_itpm(struct pnp_dev *dev) |
85 | { | 85 | { |
86 | struct acpi_device *acpi = pnp_acpi_device(dev); | 86 | struct acpi_device *acpi = pnp_acpi_device(dev); |
@@ -93,6 +93,11 @@ static int is_itpm(struct pnp_dev *dev) | |||
93 | 93 | ||
94 | return 0; | 94 | return 0; |
95 | } | 95 | } |
96 | #else | ||
97 | static inline int is_itpm(struct pnp_dev *dev) | ||
98 | { | ||
99 | return 0; | ||
100 | } | ||
96 | #endif | 101 | #endif |
97 | 102 | ||
98 | static int check_locality(struct tpm_chip *chip, int l) | 103 | static int check_locality(struct tpm_chip *chip, int l) |