diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2009-09-12 14:22:12 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-09-19 00:52:33 -0400 |
commit | 600a99fa3b4ce4a54375fb089e5ce0f3a1c9a7e1 (patch) | |
tree | b6e680f65204a9508ba9f14f52a40fb23a673753 /drivers/platform | |
parent | 6da25bf51689a5cc60370d30275dbb9e6852e0cb (diff) |
thinkpad-acpi: firmware version checks
Use the quirk infrastructure to warn of outdated firmware and also of
firmware versions that are known to cause problems.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d287283b8aa5..cc4155c3620e 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -1601,6 +1601,187 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv) | |||
1601 | #endif | 1601 | #endif |
1602 | } | 1602 | } |
1603 | 1603 | ||
1604 | /************************************************************************* | ||
1605 | * Firmware Data | ||
1606 | */ | ||
1607 | |||
1608 | /* | ||
1609 | * Table of recommended minimum BIOS versions | ||
1610 | * | ||
1611 | * Reasons for listing: | ||
1612 | * 1. Stable BIOS, listed because the unknown ammount of | ||
1613 | * bugs and bad ACPI behaviour on older versions | ||
1614 | * | ||
1615 | * 2. BIOS or EC fw with known bugs that trigger on Linux | ||
1616 | * | ||
1617 | * 3. BIOS with known reduced functionality in older versions | ||
1618 | * | ||
1619 | * We recommend the latest BIOS and EC version. | ||
1620 | * We only support the latest BIOS and EC fw version as a rule. | ||
1621 | * | ||
1622 | * Sources: IBM ThinkPad Public Web Documents (update changelogs), | ||
1623 | * Information from users in ThinkWiki | ||
1624 | */ | ||
1625 | |||
1626 | #define TPV_Q(__v, __id1, __id2, __bv1, __bv2) \ | ||
1627 | { .vendor = (__v), \ | ||
1628 | .bios = TPID(__id1, __id2), \ | ||
1629 | .ec = TPACPI_MATCH_ANY, \ | ||
1630 | .quirks = TPACPI_MATCH_ANY << 16 \ | ||
1631 | | (__bv1) << 8 | (__bv2) } | ||
1632 | |||
1633 | #define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \ | ||
1634 | __eid1, __eid2, __ev1, __ev2) \ | ||
1635 | { .vendor = (__v), \ | ||
1636 | .bios = TPID(__bid1, __bid2), \ | ||
1637 | .ec = TPID(__eid1, __eid2), \ | ||
1638 | .quirks = (__ev1) << 24 | (__ev2) << 16 \ | ||
1639 | | (__bv1) << 8 | (__bv2) } | ||
1640 | |||
1641 | #define TPV_QI0(__id1, __id2, __bv1, __bv2) \ | ||
1642 | TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2) | ||
1643 | |||
1644 | #define TPV_QI1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \ | ||
1645 | TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \ | ||
1646 | __bv1, __bv2, __id1, __id2, __ev1, __ev2) | ||
1647 | |||
1648 | #define TPV_QI2(__bid1, __bid2, __bv1, __bv2, \ | ||
1649 | __eid1, __eid2, __ev1, __ev2) \ | ||
1650 | TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \ | ||
1651 | __bv1, __bv2, __eid1, __eid2, __ev1, __ev2) | ||
1652 | |||
1653 | #define TPV_QL0(__id1, __id2, __bv1, __bv2) \ | ||
1654 | TPV_Q(PCI_VENDOR_ID_LENOVO, __id1, __id2, __bv1, __bv2) | ||
1655 | |||
1656 | #define TPV_QL1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \ | ||
1657 | TPV_Q_X(PCI_VENDOR_ID_LENOVO, __id1, __id2, \ | ||
1658 | __bv1, __bv2, __id1, __id2, __ev1, __ev2) | ||
1659 | |||
1660 | #define TPV_QL2(__bid1, __bid2, __bv1, __bv2, \ | ||
1661 | __eid1, __eid2, __ev1, __ev2) \ | ||
1662 | TPV_Q_X(PCI_VENDOR_ID_LENOVO, __bid1, __bid2, \ | ||
1663 | __bv1, __bv2, __eid1, __eid2, __ev1, __ev2) | ||
1664 | |||
1665 | static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = { | ||
1666 | /* Numeric models ------------------ */ | ||
1667 | /* FW MODEL BIOS VERS */ | ||
1668 | TPV_QI0('I', 'M', '6', '5'), /* 570 */ | ||
1669 | TPV_QI0('I', 'U', '2', '6'), /* 570E */ | ||
1670 | TPV_QI0('I', 'B', '5', '4'), /* 600 */ | ||
1671 | TPV_QI0('I', 'H', '4', '7'), /* 600E */ | ||
1672 | TPV_QI0('I', 'N', '3', '6'), /* 600E */ | ||
1673 | TPV_QI0('I', 'T', '5', '5'), /* 600X */ | ||
1674 | TPV_QI0('I', 'D', '4', '8'), /* 770, 770E, 770ED */ | ||
1675 | TPV_QI0('I', 'I', '4', '2'), /* 770X */ | ||
1676 | TPV_QI0('I', 'O', '2', '3'), /* 770Z */ | ||
1677 | |||
1678 | /* A-series ------------------------- */ | ||
1679 | /* FW MODEL BIOS VERS EC VERS */ | ||
1680 | TPV_QI0('I', 'W', '5', '9'), /* A20m */ | ||
1681 | TPV_QI0('I', 'V', '6', '9'), /* A20p */ | ||
1682 | TPV_QI0('1', '0', '2', '6'), /* A21e, A22e */ | ||
1683 | TPV_QI0('K', 'U', '3', '6'), /* A21e */ | ||
1684 | TPV_QI0('K', 'X', '3', '6'), /* A21m, A22m */ | ||
1685 | TPV_QI0('K', 'Y', '3', '8'), /* A21p, A22p */ | ||
1686 | TPV_QI0('1', 'B', '1', '7'), /* A22e */ | ||
1687 | TPV_QI0('1', '3', '2', '0'), /* A22m */ | ||
1688 | TPV_QI0('1', 'E', '7', '3'), /* A30/p (0) */ | ||
1689 | TPV_QI1('1', 'G', '4', '1', '1', '7'), /* A31/p (0) */ | ||
1690 | TPV_QI1('1', 'N', '1', '6', '0', '7'), /* A31/p (0) */ | ||
1691 | |||
1692 | /* G-series ------------------------- */ | ||
1693 | /* FW MODEL BIOS VERS */ | ||
1694 | TPV_QI0('1', 'T', 'A', '6'), /* G40 */ | ||
1695 | TPV_QI0('1', 'X', '5', '7'), /* G41 */ | ||
1696 | |||
1697 | /* R-series, T-series --------------- */ | ||
1698 | /* FW MODEL BIOS VERS EC VERS */ | ||
1699 | TPV_QI0('1', 'C', 'F', '0'), /* R30 */ | ||
1700 | TPV_QI0('1', 'F', 'F', '1'), /* R31 */ | ||
1701 | TPV_QI0('1', 'M', '9', '7'), /* R32 */ | ||
1702 | TPV_QI0('1', 'O', '6', '1'), /* R40 */ | ||
1703 | TPV_QI0('1', 'P', '6', '5'), /* R40 */ | ||
1704 | TPV_QI0('1', 'S', '7', '0'), /* R40e */ | ||
1705 | TPV_QI1('1', 'R', 'D', 'R', '7', '1'), /* R50/p, R51, | ||
1706 | T40/p, T41/p, T42/p (1) */ | ||
1707 | TPV_QI1('1', 'V', '7', '1', '2', '8'), /* R50e, R51 (1) */ | ||
1708 | TPV_QI1('7', '8', '7', '1', '0', '6'), /* R51e (1) */ | ||
1709 | TPV_QI1('7', '6', '6', '9', '1', '6'), /* R52 (1) */ | ||
1710 | TPV_QI1('7', '0', '6', '9', '2', '8'), /* R52, T43 (1) */ | ||
1711 | |||
1712 | TPV_QI0('I', 'Y', '6', '1'), /* T20 */ | ||
1713 | TPV_QI0('K', 'Z', '3', '4'), /* T21 */ | ||
1714 | TPV_QI0('1', '6', '3', '2'), /* T22 */ | ||
1715 | TPV_QI1('1', 'A', '6', '4', '2', '3'), /* T23 (0) */ | ||
1716 | TPV_QI1('1', 'I', '7', '1', '2', '0'), /* T30 (0) */ | ||
1717 | TPV_QI1('1', 'Y', '6', '5', '2', '9'), /* T43/p (1) */ | ||
1718 | |||
1719 | TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */ | ||
1720 | TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */ | ||
1721 | TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */ | ||
1722 | |||
1723 | /* BIOS FW BIOS VERS EC FW EC VERS */ | ||
1724 | TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */ | ||
1725 | TPV_QL2('7', 'I', '3', '4', '7', '9', '5', '0'), /* T60/p wide */ | ||
1726 | |||
1727 | /* X-series ------------------------- */ | ||
1728 | /* FW MODEL BIOS VERS EC VERS */ | ||
1729 | TPV_QI0('I', 'Z', '9', 'D'), /* X20, X21 */ | ||
1730 | TPV_QI0('1', 'D', '7', '0'), /* X22, X23, X24 */ | ||
1731 | TPV_QI1('1', 'K', '4', '8', '1', '8'), /* X30 (0) */ | ||
1732 | TPV_QI1('1', 'Q', '9', '7', '2', '3'), /* X31, X32 (0) */ | ||
1733 | TPV_QI1('1', 'U', 'D', '3', 'B', '2'), /* X40 (0) */ | ||
1734 | TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */ | ||
1735 | TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */ | ||
1736 | |||
1737 | TPV_QL0('7', 'B', 'D', '7'), /* X60/s */ | ||
1738 | TPV_QL0('7', 'J', '3', '0'), /* X60t */ | ||
1739 | |||
1740 | /* (0) - older versions lack DMI EC fw string and functionality */ | ||
1741 | /* (1) - older versions known to lack functionality */ | ||
1742 | }; | ||
1743 | |||
1744 | #undef TPV_QL1 | ||
1745 | #undef TPV_QL0 | ||
1746 | #undef TPV_QI2 | ||
1747 | #undef TPV_QI1 | ||
1748 | #undef TPV_QI0 | ||
1749 | #undef TPV_Q_X | ||
1750 | #undef TPV_Q | ||
1751 | |||
1752 | static void __init tpacpi_check_outdated_fw(void) | ||
1753 | { | ||
1754 | unsigned long fwvers; | ||
1755 | u16 ec_version, bios_version; | ||
1756 | |||
1757 | fwvers = tpacpi_check_quirks(tpacpi_bios_version_qtable, | ||
1758 | ARRAY_SIZE(tpacpi_bios_version_qtable)); | ||
1759 | |||
1760 | if (!fwvers) | ||
1761 | return; | ||
1762 | |||
1763 | bios_version = fwvers & 0xffffU; | ||
1764 | ec_version = (fwvers >> 16) & 0xffffU; | ||
1765 | |||
1766 | /* note that unknown versions are set to 0x0000 and we use that */ | ||
1767 | if ((bios_version > thinkpad_id.bios_release) || | ||
1768 | (ec_version > thinkpad_id.ec_release && | ||
1769 | ec_version != TPACPI_MATCH_ANY)) { | ||
1770 | /* | ||
1771 | * The changelogs would let us track down the exact | ||
1772 | * reason, but it is just too much of a pain to track | ||
1773 | * it. We only list BIOSes that are either really | ||
1774 | * broken, or really stable to begin with, so it is | ||
1775 | * best if the user upgrades the firmware anyway. | ||
1776 | */ | ||
1777 | printk(TPACPI_WARN | ||
1778 | "WARNING: Outdated ThinkPad BIOS/EC firmware\n"); | ||
1779 | printk(TPACPI_WARN | ||
1780 | "WARNING: This firmware may be missing critical bug " | ||
1781 | "fixes and/or important features\n"); | ||
1782 | } | ||
1783 | } | ||
1784 | |||
1604 | /**************************************************************************** | 1785 | /**************************************************************************** |
1605 | **************************************************************************** | 1786 | **************************************************************************** |
1606 | * | 1787 | * |
@@ -1634,6 +1815,7 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) | |||
1634 | (thinkpad_id.nummodel_str) ? | 1815 | (thinkpad_id.nummodel_str) ? |
1635 | thinkpad_id.nummodel_str : "unknown"); | 1816 | thinkpad_id.nummodel_str : "unknown"); |
1636 | 1817 | ||
1818 | tpacpi_check_outdated_fw(); | ||
1637 | return 0; | 1819 | return 0; |
1638 | } | 1820 | } |
1639 | 1821 | ||