Skip to content

Commit

Permalink
ACPI: thinkpad-acpi: store ThinkPad model information
Browse files Browse the repository at this point in the history
Keep note of ThinkPad model, BIOS and EC firmware information, and log it
on startup.  Makes for far more readable code in places, too.

This patch also adds Lenovo's PCI ID to the pci ids table.

Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Henrique de Moraes Holschuh authored and Len Brown committed Jul 22, 2007
1 parent 86cc944 commit d5a2f2f
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 30 deletions.
98 changes: 70 additions & 28 deletions drivers/misc/thinkpad_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,9 +717,19 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
printk(IBM_INFO "%s\n", IBM_URL);

if (ibm_thinkpad_ec_found)
printk(IBM_INFO "ThinkPad EC firmware %s\n",
ibm_thinkpad_ec_found);
printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n",
(thinkpad_id.bios_version_str) ?
thinkpad_id.bios_version_str : "unknown",
(thinkpad_id.ec_version_str) ?
thinkpad_id.ec_version_str : "unknown");

if (thinkpad_id.vendor && thinkpad_id.model_str)
printk(IBM_INFO "%s %s\n",
(thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
"IBM" : ((thinkpad_id.vendor ==
PCI_VENDOR_ID_LENOVO) ?
"Lenovo" : "Unknown vendor"),
thinkpad_id.model_str);

return 0;
}
Expand Down Expand Up @@ -2648,7 +2658,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)

acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");

if (ibm_thinkpad_ec_found && experimental) {
if (thinkpad_id.ec_model && experimental) {
/*
* Direct EC access mode: sensors at registers
* 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for
Expand Down Expand Up @@ -3532,20 +3542,19 @@ static int __init fan_init(struct ibm_init_struct *iibm)
* Enable for TP-1Y (T43), TP-78 (R51e),
* TP-76 (R52), TP-70 (T43, R52), which are known
* to be buggy. */
if (fan_control_initial_status == 0x07 &&
ibm_thinkpad_ec_found &&
((ibm_thinkpad_ec_found[0] == '1' &&
ibm_thinkpad_ec_found[1] == 'Y') ||
(ibm_thinkpad_ec_found[0] == '7' &&
(ibm_thinkpad_ec_found[1] == '6' ||
ibm_thinkpad_ec_found[1] == '8' ||
ibm_thinkpad_ec_found[1] == '0'))
)) {
printk(IBM_NOTICE
"fan_init: initial fan status is "
"unknown, assuming it is in auto "
"mode\n");
tp_features.fan_ctrl_status_undef = 1;
if (fan_control_initial_status == 0x07) {
switch (thinkpad_id.ec_model) {
case 0x5931: /* TP-1Y */
case 0x3837: /* TP-78 */
case 0x3637: /* TP-76 */
case 0x3037: /* TP-70 */
printk(IBM_NOTICE
"fan_init: initial fan status is "
"unknown, assuming it is in auto "
"mode\n");
tp_features.fan_ctrl_status_undef = 1;
;;
}
}
} else {
printk(IBM_ERR
Expand Down Expand Up @@ -4279,13 +4288,30 @@ static void ibm_exit(struct ibm_struct *ibm)

/* Probing */

static char *ibm_thinkpad_ec_found;

static char* __init check_dmi_for_ec(void)
static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
{
struct dmi_device *dev = NULL;
char ec_fw_string[18];

if (!tp)
return;

memset(tp, 0, sizeof(*tp));

if (dmi_name_in_vendors("IBM"))
tp->vendor = PCI_VENDOR_ID_IBM;
else if (dmi_name_in_vendors("LENOVO"))
tp->vendor = PCI_VENDOR_ID_LENOVO;
else
return;

tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION),
GFP_KERNEL);
if (!tp->bios_version_str)
return;
tp->bios_model = tp->bios_version_str[0]
| (tp->bios_version_str[1] << 8);

/*
* ThinkPad T23 or newer, A31 or newer, R50e or newer,
* X32 or newer, all Z series; Some models must have an
Expand All @@ -4299,10 +4325,20 @@ static char* __init check_dmi_for_ec(void)
ec_fw_string) == 1) {
ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
return kstrdup(ec_fw_string, GFP_KERNEL);

tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
tp->ec_model = ec_fw_string[0]
| (ec_fw_string[1] << 8);
break;
}
}
return NULL;

tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION),
GFP_KERNEL);
if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) {
kfree(tp->model_str);
tp->model_str = NULL;
}
}

static int __init probe_for_thinkpad(void)
Expand All @@ -4316,7 +4352,7 @@ static int __init probe_for_thinkpad(void)
* Non-ancient models have better DMI tagging, but very old models
* don't.
*/
is_thinkpad = dmi_name_in_vendors("ThinkPad");
is_thinkpad = (thinkpad_id.model_str != NULL);

/* ec is required because many other handles are relative to it */
IBM_ACPIHANDLE_INIT(ec);
Expand All @@ -4332,7 +4368,7 @@ static int __init probe_for_thinkpad(void)
* false positives a damn great deal
*/
if (!is_thinkpad)
is_thinkpad = dmi_name_in_vendors("IBM");
is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM);

if (!is_thinkpad && !force_load)
return -ENODEV;
Expand Down Expand Up @@ -4475,12 +4511,16 @@ static int __init thinkpad_acpi_module_init(void)
int ret, i;

/* Driver-level probe */

get_thinkpad_model_data(&thinkpad_id);
ret = probe_for_thinkpad();
if (ret)
if (ret) {
thinkpad_acpi_module_exit();
return ret;
}

/* Driver initialization */
ibm_thinkpad_ec_found = check_dmi_for_ec();

IBM_ACPIHANDLE_INIT(ecrd);
IBM_ACPIHANDLE_INIT(ecwr);

Expand Down Expand Up @@ -4590,7 +4630,9 @@ static void thinkpad_acpi_module_exit(void)
if (proc_dir)
remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);

kfree(ibm_thinkpad_ec_found);
kfree(thinkpad_id.bios_version_str);
kfree(thinkpad_id.ec_version_str);
kfree(thinkpad_id.model_str);
}

module_init(thinkpad_acpi_module_init);
Expand Down
17 changes: 15 additions & 2 deletions drivers/misc/thinkpad_acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv);
static int experimental;
static u32 dbg_level;
static int force_load;
static char *ibm_thinkpad_ec_found;

static char* check_dmi_for_ec(void);
static int thinkpad_acpi_module_init(void);
static void thinkpad_acpi_module_exit(void);

Expand Down Expand Up @@ -244,6 +242,21 @@ static struct {
u16 input_device_registered:1;
} tp_features;

struct thinkpad_id_data {
unsigned int vendor; /* ThinkPad vendor:
* PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */

char *bios_version_str; /* Something like 1ZET51WW (1.03z) */
char *ec_version_str; /* Something like 1ZHT51WW-1.04a */

u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */
u16 ec_model;

char *model_str;
};

static struct thinkpad_id_data thinkpad_id;

static struct list_head tpacpi_all_drivers;

static struct ibm_init_struct ibms_init[];
Expand Down
2 changes: 2 additions & 0 deletions include/linux/pci_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -2040,6 +2040,8 @@
#define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea
#define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb

#define PCI_VENDOR_ID_LENOVO 0x17aa

#define PCI_VENDOR_ID_ARECA 0x17d3
#define PCI_DEVICE_ID_ARECA_1110 0x1110
#define PCI_DEVICE_ID_ARECA_1120 0x1120
Expand Down

0 comments on commit d5a2f2f

Please sign in to comment.