]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.drivers/dmi-introduce-dmi_first_match
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / dmi-introduce-dmi_first_match
1 From 2969c7df1c1808d2a38a9adfbb158de7632a0cfb Mon Sep 17 00:00:00 2001
2 From: Rafael J. Wysocki <rjw@sisk.pl>
3 Date: Mon, 3 Nov 2008 19:01:03 +0900
4 Subject: [PATCH] DMI: Introduce dmi_first_match to make the interface more flexible
5 References: bnc#441721
6
7 Some notebooks from HP have the problem that their BIOSes attempt to
8 spin down hard drives before entering ACPI system states S4 and S5.
9 This leads to a yo-yo effect during system power-off shutdown and the
10 last phase of hibernation when the disk is first spun down by the
11 kernel and then almost immediately turned on and off by the BIOS.
12 This, in turn, may result in shortening the disk's life times.
13
14 To prevent this from happening we can blacklist the affected systems
15 using DMI information. However, only the on-board controlles should
16 be blacklisted and their PCI slot numbers can be used for this
17 purpose. Unfortunately the existing interface for checking DMI
18 information of the system is not very convenient for this purpose,
19 because to use it, we would have to define special callback functions
20 or create a separate struct dmi_system_id table for each blacklisted
21 system.
22
23 To overcome this difficulty introduce a new function
24 dmi_first_match() returning a pointer to the first entry in an array
25 of struct dmi_system_id elements that matches the system DMI
26 information. Then, we can use this pointer to access the entry's
27 .driver_data field containing the additional information, such as
28 the PCI slot number, allowing us to do the desired blacklisting.
29
30 Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
31 Signed-off-by: Tejun Heo <tj@kernel.org>
32 Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
33 Signed-off-by: Tejun Heo <teheo@suse.de>
34 ---
35 drivers/firmware/dmi_scan.c | 68 +++++++++++++++++++++++++++++++++-----------
36 include/linux/dmi.h | 3 +
37 2 files changed, 55 insertions(+), 16 deletions(-)
38
39 --- a/drivers/firmware/dmi_scan.c
40 +++ b/drivers/firmware/dmi_scan.c
41 @@ -407,6 +407,27 @@ void __init dmi_scan_machine(void)
42 }
43
44 /**
45 + * dmi_match - check if dmi_system_id structure matches system DMI data
46 + * @dmi: pointer to the dmi_system_id structure to check
47 + */
48 +static bool dmi_match(const struct dmi_system_id *dmi)
49 +{
50 + int i;
51 +
52 + for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
53 + int s = dmi->matches[i].slot;
54 + if (s == DMI_NONE)
55 + continue;
56 + if (dmi_ident[s]
57 + && strstr(dmi_ident[s], dmi->matches[i].substr))
58 + continue;
59 + /* No match */
60 + return false;
61 + }
62 + return true;
63 +}
64 +
65 +/**
66 * dmi_check_system - check system DMI data
67 * @list: array of dmi_system_id structures to match against
68 * All non-null elements of the list must match
69 @@ -421,30 +442,45 @@ void __init dmi_scan_machine(void)
70 */
71 int dmi_check_system(const struct dmi_system_id *list)
72 {
73 - int i, count = 0;
74 - const struct dmi_system_id *d = list;
75 + int count = 0;
76 + const struct dmi_system_id *d;
77
78 - while (d->ident) {
79 - for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
80 - int s = d->matches[i].slot;
81 - if (s == DMI_NONE)
82 - continue;
83 - if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
84 - continue;
85 - /* No match */
86 - goto fail;
87 + for (d = list; d->ident; d++)
88 + if (dmi_match(d)) {
89 + count++;
90 + if (d->callback && d->callback(d))
91 + break;
92 }
93 - count++;
94 - if (d->callback && d->callback(d))
95 - break;
96 -fail: d++;
97 - }
98
99 return count;
100 }
101 EXPORT_SYMBOL(dmi_check_system);
102
103 /**
104 + * dmi_first_match - find dmi_system_id structure matching system DMI data
105 + * @list: array of dmi_system_id structures to match against
106 + * All non-null elements of the list must match
107 + * their slot's (field index's) data (i.e., each
108 + * list string must be a substring of the specified
109 + * DMI slot's string data) to be considered a
110 + * successful match.
111 + *
112 + * Walk the blacklist table until the first match is found. Return the
113 + * pointer to the matching entry or NULL if there's no match.
114 + */
115 +const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list)
116 +{
117 + const struct dmi_system_id *d;
118 +
119 + for (d = list; d->ident; d++)
120 + if (dmi_match(d))
121 + return d;
122 +
123 + return NULL;
124 +}
125 +EXPORT_SYMBOL(dmi_first_match);
126 +
127 +/**
128 * dmi_get_system_info - return DMI data value
129 * @field: data index (see enum dmi_field)
130 *
131 --- a/include/linux/dmi.h
132 +++ b/include/linux/dmi.h
133 @@ -75,6 +75,7 @@ struct dmi_device {
134 #ifdef CONFIG_DMI
135
136 extern int dmi_check_system(const struct dmi_system_id *list);
137 +const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
138 extern const char * dmi_get_system_info(int field);
139 extern const struct dmi_device * dmi_find_device(int type, const char *name,
140 const struct dmi_device *from);
141 @@ -88,6 +89,8 @@ extern int dmi_walk(void (*decode)(const
142 #else
143
144 static inline int dmi_check_system(const struct dmi_system_id *list) { return 0; }
145 +static inline const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list)
146 + { return NULL; }
147 static inline const char * dmi_get_system_info(int field) { return NULL; }
148 static inline const struct dmi_device * dmi_find_device(int type, const char *name,
149 const struct dmi_device *from) { return NULL; }