diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2007-11-05 11:43:31 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-11-14 12:14:28 -0500 |
commit | ff102ea99099c36250e93a87a9794b5233801020 (patch) | |
tree | 19cf2ac073458b8337e9514589ad2c284407f50b | |
parent | f51e83916a0a022d3d0ea39ae2f877c703032923 (diff) |
ACPI: video - remove unsafe uses of list_for_each_safe()
list_for_each_safe() only protects list from list alterations
performed by the same thread. One still needs to implement
proper locking when list is being accessed from several threads.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Acked-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/video.c | 71 |
1 files changed, 34 insertions, 37 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index be66a7c04d38..36b64a751676 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -1462,12 +1462,14 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1462 | 1462 | ||
1463 | static void acpi_video_device_rebind(struct acpi_video_bus *video) | 1463 | static void acpi_video_device_rebind(struct acpi_video_bus *video) |
1464 | { | 1464 | { |
1465 | struct list_head *node, *next; | 1465 | struct acpi_video_device *dev; |
1466 | list_for_each_safe(node, next, &video->video_device_list) { | 1466 | |
1467 | struct acpi_video_device *dev = | 1467 | down(&video->sem); |
1468 | container_of(node, struct acpi_video_device, entry); | 1468 | |
1469 | list_for_each_entry(dev, &video->video_device_list, entry) | ||
1469 | acpi_video_device_bind(video, dev); | 1470 | acpi_video_device_bind(video, dev); |
1470 | } | 1471 | |
1472 | up(&video->sem); | ||
1471 | } | 1473 | } |
1472 | 1474 | ||
1473 | /* | 1475 | /* |
@@ -1592,30 +1594,33 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1592 | 1594 | ||
1593 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event) | 1595 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event) |
1594 | { | 1596 | { |
1595 | struct list_head *node, *next; | 1597 | struct list_head *node; |
1596 | struct acpi_video_device *dev = NULL; | 1598 | struct acpi_video_device *dev = NULL; |
1597 | struct acpi_video_device *dev_next = NULL; | 1599 | struct acpi_video_device *dev_next = NULL; |
1598 | struct acpi_video_device *dev_prev = NULL; | 1600 | struct acpi_video_device *dev_prev = NULL; |
1599 | unsigned long state; | 1601 | unsigned long state; |
1600 | int status = 0; | 1602 | int status = 0; |
1601 | 1603 | ||
1604 | down(&video->sem); | ||
1602 | 1605 | ||
1603 | list_for_each_safe(node, next, &video->video_device_list) { | 1606 | list_for_each(node, &video->video_device_list) { |
1604 | dev = container_of(node, struct acpi_video_device, entry); | 1607 | dev = container_of(node, struct acpi_video_device, entry); |
1605 | status = acpi_video_device_get_state(dev, &state); | 1608 | status = acpi_video_device_get_state(dev, &state); |
1606 | if (state & 0x2) { | 1609 | if (state & 0x2) { |
1607 | dev_next = | 1610 | dev_next = container_of(node->next, |
1608 | container_of(node->next, struct acpi_video_device, | 1611 | struct acpi_video_device, entry); |
1609 | entry); | 1612 | dev_prev = container_of(node->prev, |
1610 | dev_prev = | 1613 | struct acpi_video_device, entry); |
1611 | container_of(node->prev, struct acpi_video_device, | ||
1612 | entry); | ||
1613 | goto out; | 1614 | goto out; |
1614 | } | 1615 | } |
1615 | } | 1616 | } |
1617 | |||
1616 | dev_next = container_of(node->next, struct acpi_video_device, entry); | 1618 | dev_next = container_of(node->next, struct acpi_video_device, entry); |
1617 | dev_prev = container_of(node->prev, struct acpi_video_device, entry); | 1619 | dev_prev = container_of(node->prev, struct acpi_video_device, entry); |
1618 | out: | 1620 | |
1621 | out: | ||
1622 | up(&video->sem); | ||
1623 | |||
1619 | switch (event) { | 1624 | switch (event) { |
1620 | case ACPI_VIDEO_NOTIFY_CYCLE: | 1625 | case ACPI_VIDEO_NOTIFY_CYCLE: |
1621 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: | 1626 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: |
@@ -1691,24 +1696,17 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, | |||
1691 | struct acpi_device *device) | 1696 | struct acpi_device *device) |
1692 | { | 1697 | { |
1693 | int status = 0; | 1698 | int status = 0; |
1694 | struct list_head *node, *next; | 1699 | struct acpi_device *dev; |
1695 | |||
1696 | 1700 | ||
1697 | acpi_video_device_enumerate(video); | 1701 | acpi_video_device_enumerate(video); |
1698 | 1702 | ||
1699 | list_for_each_safe(node, next, &device->children) { | 1703 | list_for_each_entry(dev, &device->children, node) { |
1700 | struct acpi_device *dev = | ||
1701 | list_entry(node, struct acpi_device, node); | ||
1702 | |||
1703 | if (!dev) | ||
1704 | continue; | ||
1705 | 1704 | ||
1706 | status = acpi_video_bus_get_one_device(dev, video); | 1705 | status = acpi_video_bus_get_one_device(dev, video); |
1707 | if (ACPI_FAILURE(status)) { | 1706 | if (ACPI_FAILURE(status)) { |
1708 | ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); | 1707 | ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); |
1709 | continue; | 1708 | continue; |
1710 | } | 1709 | } |
1711 | |||
1712 | } | 1710 | } |
1713 | return status; | 1711 | return status; |
1714 | } | 1712 | } |
@@ -1724,9 +1722,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
1724 | 1722 | ||
1725 | video = device->video; | 1723 | video = device->video; |
1726 | 1724 | ||
1727 | down(&video->sem); | ||
1728 | list_del(&device->entry); | ||
1729 | up(&video->sem); | ||
1730 | acpi_video_device_remove_fs(device->dev); | 1725 | acpi_video_device_remove_fs(device->dev); |
1731 | 1726 | ||
1732 | status = acpi_remove_notify_handler(device->dev->handle, | 1727 | status = acpi_remove_notify_handler(device->dev->handle, |
@@ -1734,32 +1729,34 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
1734 | acpi_video_device_notify); | 1729 | acpi_video_device_notify); |
1735 | backlight_device_unregister(device->backlight); | 1730 | backlight_device_unregister(device->backlight); |
1736 | video_output_unregister(device->output_dev); | 1731 | video_output_unregister(device->output_dev); |
1732 | |||
1737 | return 0; | 1733 | return 0; |
1738 | } | 1734 | } |
1739 | 1735 | ||
1740 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) | 1736 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) |
1741 | { | 1737 | { |
1742 | int status; | 1738 | int status; |
1743 | struct list_head *node, *next; | 1739 | struct acpi_video_device *dev, *next; |
1744 | 1740 | ||
1741 | down(&video->sem); | ||
1745 | 1742 | ||
1746 | list_for_each_safe(node, next, &video->video_device_list) { | 1743 | list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { |
1747 | struct acpi_video_device *data = | ||
1748 | list_entry(node, struct acpi_video_device, entry); | ||
1749 | if (!data) | ||
1750 | continue; | ||
1751 | 1744 | ||
1752 | status = acpi_video_bus_put_one_device(data); | 1745 | status = acpi_video_bus_put_one_device(dev); |
1753 | if (ACPI_FAILURE(status)) | 1746 | if (ACPI_FAILURE(status)) |
1754 | printk(KERN_WARNING PREFIX | 1747 | printk(KERN_WARNING PREFIX |
1755 | "hhuuhhuu bug in acpi video driver.\n"); | 1748 | "hhuuhhuu bug in acpi video driver.\n"); |
1756 | 1749 | ||
1757 | if (data->brightness) | 1750 | if (dev->brightness) { |
1758 | kfree(data->brightness->levels); | 1751 | kfree(dev->brightness->levels); |
1759 | kfree(data->brightness); | 1752 | kfree(dev->brightness); |
1760 | kfree(data); | 1753 | } |
1754 | list_del(&dev->entry); | ||
1755 | kfree(dev); | ||
1761 | } | 1756 | } |
1762 | 1757 | ||
1758 | up(&video->sem); | ||
1759 | |||
1763 | return 0; | 1760 | return 0; |
1764 | } | 1761 | } |
1765 | 1762 | ||