Skip to content

Commit d7b1956

Browse files
rjwysockiJeff Garzik
authored andcommitted
DMI: Introduce dmi_first_match to make the interface more flexible
Some notebooks from HP have the problem that their BIOSes attempt to spin down hard drives before entering ACPI system states S4 and S5. This leads to a yo-yo effect during system power-off shutdown and the last phase of hibernation when the disk is first spun down by the kernel and then almost immediately turned on and off by the BIOS. This, in turn, may result in shortening the disk's life times. To prevent this from happening we can blacklist the affected systems using DMI information. However, only the on-board controlles should be blacklisted and their PCI slot numbers can be used for this purpose. Unfortunately the existing interface for checking DMI information of the system is not very convenient for this purpose, because to use it, we would have to define special callback functions or create a separate struct dmi_system_id table for each blacklisted system. To overcome this difficulty introduce a new function dmi_first_match() returning a pointer to the first entry in an array of struct dmi_system_id elements that matches the system DMI information. Then, we can use this pointer to access the entry's .driver_data field containing the additional information, such as the PCI slot number, allowing us to do the desired blacklisting. Signed-off-by: Rafael J. Wysocki <[email protected]> Signed-off-by: Jeff Garzik <[email protected]>
1 parent abfe2d7 commit d7b1956

File tree

2 files changed

+56
-19
lines changed

2 files changed

+56
-19
lines changed

drivers/firmware/dmi_scan.c

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,29 @@ void __init dmi_scan_machine(void)
414414
dmi_initialized = 1;
415415
}
416416

417+
/**
418+
* dmi_matches - check if dmi_system_id structure matches system DMI data
419+
* @dmi: pointer to the dmi_system_id structure to check
420+
*/
421+
static bool dmi_matches(const struct dmi_system_id *dmi)
422+
{
423+
int i;
424+
425+
WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
426+
427+
for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
428+
int s = dmi->matches[i].slot;
429+
if (s == DMI_NONE)
430+
continue;
431+
if (dmi_ident[s]
432+
&& strstr(dmi_ident[s], dmi->matches[i].substr))
433+
continue;
434+
/* No match */
435+
return false;
436+
}
437+
return true;
438+
}
439+
417440
/**
418441
* dmi_check_system - check system DMI data
419442
* @list: array of dmi_system_id structures to match against
@@ -429,31 +452,44 @@ void __init dmi_scan_machine(void)
429452
*/
430453
int dmi_check_system(const struct dmi_system_id *list)
431454
{
432-
int i, count = 0;
433-
const struct dmi_system_id *d = list;
434-
435-
WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
436-
437-
while (d->ident) {
438-
for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
439-
int s = d->matches[i].slot;
440-
if (s == DMI_NONE)
441-
continue;
442-
if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
443-
continue;
444-
/* No match */
445-
goto fail;
455+
int count = 0;
456+
const struct dmi_system_id *d;
457+
458+
for (d = list; d->ident; d++)
459+
if (dmi_matches(d)) {
460+
count++;
461+
if (d->callback && d->callback(d))
462+
break;
446463
}
447-
count++;
448-
if (d->callback && d->callback(d))
449-
break;
450-
fail: d++;
451-
}
452464

453465
return count;
454466
}
455467
EXPORT_SYMBOL(dmi_check_system);
456468

469+
/**
470+
* dmi_first_match - find dmi_system_id structure matching system DMI data
471+
* @list: array of dmi_system_id structures to match against
472+
* All non-null elements of the list must match
473+
* their slot's (field index's) data (i.e., each
474+
* list string must be a substring of the specified
475+
* DMI slot's string data) to be considered a
476+
* successful match.
477+
*
478+
* Walk the blacklist table until the first match is found. Return the
479+
* pointer to the matching entry or NULL if there's no match.
480+
*/
481+
const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list)
482+
{
483+
const struct dmi_system_id *d;
484+
485+
for (d = list; d->ident; d++)
486+
if (dmi_matches(d))
487+
return d;
488+
489+
return NULL;
490+
}
491+
EXPORT_SYMBOL(dmi_first_match);
492+
457493
/**
458494
* dmi_get_system_info - return DMI data value
459495
* @field: data index (see enum dmi_field)

include/linux/dmi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct dmi_device {
3838
#ifdef CONFIG_DMI
3939

4040
extern int dmi_check_system(const struct dmi_system_id *list);
41+
const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
4142
extern const char * dmi_get_system_info(int field);
4243
extern const struct dmi_device * dmi_find_device(int type, const char *name,
4344
const struct dmi_device *from);

0 commit comments

Comments
 (0)