diff options
-rw-r--r-- | drivers/ata/libahci.c | 21 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 123 | ||||
-rw-r--r-- | mm/shmem.c | 10 |
3 files changed, 75 insertions, 79 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index ff9d832a163d..d38c40fe4ddb 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c | |||
@@ -561,27 +561,6 @@ void ahci_start_engine(struct ata_port *ap) | |||
561 | { | 561 | { |
562 | void __iomem *port_mmio = ahci_port_base(ap); | 562 | void __iomem *port_mmio = ahci_port_base(ap); |
563 | u32 tmp; | 563 | u32 tmp; |
564 | u8 status; | ||
565 | |||
566 | status = readl(port_mmio + PORT_TFDATA) & 0xFF; | ||
567 | |||
568 | /* | ||
569 | * At end of section 10.1 of AHCI spec (rev 1.3), it states | ||
570 | * Software shall not set PxCMD.ST to 1 until it is determined | ||
571 | * that a functoinal device is present on the port as determined by | ||
572 | * PxTFD.STS.BSY=0, PxTFD.STS.DRQ=0 and PxSSTS.DET=3h | ||
573 | * | ||
574 | * Even though most AHCI host controllers work without this check, | ||
575 | * specific controller will fail under this condition | ||
576 | */ | ||
577 | if (status & (ATA_BUSY | ATA_DRQ)) | ||
578 | return; | ||
579 | else { | ||
580 | ahci_scr_read(&ap->link, SCR_STATUS, &tmp); | ||
581 | |||
582 | if ((tmp & 0xf) != 0x3) | ||
583 | return; | ||
584 | } | ||
585 | 564 | ||
586 | /* start DMA */ | 565 | /* start DMA */ |
587 | tmp = readl(port_mmio + PORT_CMD); | 566 | tmp = readl(port_mmio + PORT_CMD); |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index ea16e654a9b6..5aac00eb1830 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1537,8 +1537,10 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena, | |||
1537 | return false; | 1537 | return false; |
1538 | } | 1538 | } |
1539 | 1539 | ||
1540 | static int do_unregister_framebuffer(struct fb_info *fb_info); | ||
1541 | |||
1540 | #define VGA_FB_PHYS 0xA0000 | 1542 | #define VGA_FB_PHYS 0xA0000 |
1541 | void remove_conflicting_framebuffers(struct apertures_struct *a, | 1543 | static void do_remove_conflicting_framebuffers(struct apertures_struct *a, |
1542 | const char *name, bool primary) | 1544 | const char *name, bool primary) |
1543 | { | 1545 | { |
1544 | int i; | 1546 | int i; |
@@ -1560,39 +1562,26 @@ void remove_conflicting_framebuffers(struct apertures_struct *a, | |||
1560 | printk(KERN_INFO "fb: conflicting fb hw usage " | 1562 | printk(KERN_INFO "fb: conflicting fb hw usage " |
1561 | "%s vs %s - removing generic driver\n", | 1563 | "%s vs %s - removing generic driver\n", |
1562 | name, registered_fb[i]->fix.id); | 1564 | name, registered_fb[i]->fix.id); |
1563 | unregister_framebuffer(registered_fb[i]); | 1565 | do_unregister_framebuffer(registered_fb[i]); |
1564 | } | 1566 | } |
1565 | } | 1567 | } |
1566 | } | 1568 | } |
1567 | EXPORT_SYMBOL(remove_conflicting_framebuffers); | ||
1568 | |||
1569 | /** | ||
1570 | * register_framebuffer - registers a frame buffer device | ||
1571 | * @fb_info: frame buffer info structure | ||
1572 | * | ||
1573 | * Registers a frame buffer device @fb_info. | ||
1574 | * | ||
1575 | * Returns negative errno on error, or zero for success. | ||
1576 | * | ||
1577 | */ | ||
1578 | 1569 | ||
1579 | int | 1570 | static int do_register_framebuffer(struct fb_info *fb_info) |
1580 | register_framebuffer(struct fb_info *fb_info) | ||
1581 | { | 1571 | { |
1582 | int i; | 1572 | int i; |
1583 | struct fb_event event; | 1573 | struct fb_event event; |
1584 | struct fb_videomode mode; | 1574 | struct fb_videomode mode; |
1585 | 1575 | ||
1586 | if (num_registered_fb == FB_MAX) | ||
1587 | return -ENXIO; | ||
1588 | |||
1589 | if (fb_check_foreignness(fb_info)) | 1576 | if (fb_check_foreignness(fb_info)) |
1590 | return -ENOSYS; | 1577 | return -ENOSYS; |
1591 | 1578 | ||
1592 | remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, | 1579 | do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, |
1593 | fb_is_primary_device(fb_info)); | 1580 | fb_is_primary_device(fb_info)); |
1594 | 1581 | ||
1595 | mutex_lock(®istration_lock); | 1582 | if (num_registered_fb == FB_MAX) |
1583 | return -ENXIO; | ||
1584 | |||
1596 | num_registered_fb++; | 1585 | num_registered_fb++; |
1597 | for (i = 0 ; i < FB_MAX; i++) | 1586 | for (i = 0 ; i < FB_MAX; i++) |
1598 | if (!registered_fb[i]) | 1587 | if (!registered_fb[i]) |
@@ -1635,7 +1624,6 @@ register_framebuffer(struct fb_info *fb_info) | |||
1635 | fb_var_to_videomode(&mode, &fb_info->var); | 1624 | fb_var_to_videomode(&mode, &fb_info->var); |
1636 | fb_add_videomode(&mode, &fb_info->modelist); | 1625 | fb_add_videomode(&mode, &fb_info->modelist); |
1637 | registered_fb[i] = fb_info; | 1626 | registered_fb[i] = fb_info; |
1638 | mutex_unlock(®istration_lock); | ||
1639 | 1627 | ||
1640 | event.info = fb_info; | 1628 | event.info = fb_info; |
1641 | if (!lock_fb_info(fb_info)) | 1629 | if (!lock_fb_info(fb_info)) |
@@ -1645,37 +1633,14 @@ register_framebuffer(struct fb_info *fb_info) | |||
1645 | return 0; | 1633 | return 0; |
1646 | } | 1634 | } |
1647 | 1635 | ||
1648 | 1636 | static int do_unregister_framebuffer(struct fb_info *fb_info) | |
1649 | /** | ||
1650 | * unregister_framebuffer - releases a frame buffer device | ||
1651 | * @fb_info: frame buffer info structure | ||
1652 | * | ||
1653 | * Unregisters a frame buffer device @fb_info. | ||
1654 | * | ||
1655 | * Returns negative errno on error, or zero for success. | ||
1656 | * | ||
1657 | * This function will also notify the framebuffer console | ||
1658 | * to release the driver. | ||
1659 | * | ||
1660 | * This is meant to be called within a driver's module_exit() | ||
1661 | * function. If this is called outside module_exit(), ensure | ||
1662 | * that the driver implements fb_open() and fb_release() to | ||
1663 | * check that no processes are using the device. | ||
1664 | */ | ||
1665 | |||
1666 | int | ||
1667 | unregister_framebuffer(struct fb_info *fb_info) | ||
1668 | { | 1637 | { |
1669 | struct fb_event event; | 1638 | struct fb_event event; |
1670 | int i, ret = 0; | 1639 | int i, ret = 0; |
1671 | 1640 | ||
1672 | mutex_lock(®istration_lock); | ||
1673 | i = fb_info->node; | 1641 | i = fb_info->node; |
1674 | if (!registered_fb[i]) { | 1642 | if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) |
1675 | ret = -EINVAL; | 1643 | return -EINVAL; |
1676 | goto done; | ||
1677 | } | ||
1678 | |||
1679 | 1644 | ||
1680 | if (!lock_fb_info(fb_info)) | 1645 | if (!lock_fb_info(fb_info)) |
1681 | return -ENODEV; | 1646 | return -ENODEV; |
@@ -1683,10 +1648,8 @@ unregister_framebuffer(struct fb_info *fb_info) | |||
1683 | ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); | 1648 | ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); |
1684 | unlock_fb_info(fb_info); | 1649 | unlock_fb_info(fb_info); |
1685 | 1650 | ||
1686 | if (ret) { | 1651 | if (ret) |
1687 | ret = -EINVAL; | 1652 | return -EINVAL; |
1688 | goto done; | ||
1689 | } | ||
1690 | 1653 | ||
1691 | if (fb_info->pixmap.addr && | 1654 | if (fb_info->pixmap.addr && |
1692 | (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) | 1655 | (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) |
@@ -1701,8 +1664,64 @@ unregister_framebuffer(struct fb_info *fb_info) | |||
1701 | 1664 | ||
1702 | /* this may free fb info */ | 1665 | /* this may free fb info */ |
1703 | put_fb_info(fb_info); | 1666 | put_fb_info(fb_info); |
1704 | done: | 1667 | return 0; |
1668 | } | ||
1669 | |||
1670 | void remove_conflicting_framebuffers(struct apertures_struct *a, | ||
1671 | const char *name, bool primary) | ||
1672 | { | ||
1673 | mutex_lock(®istration_lock); | ||
1674 | do_remove_conflicting_framebuffers(a, name, primary); | ||
1675 | mutex_unlock(®istration_lock); | ||
1676 | } | ||
1677 | EXPORT_SYMBOL(remove_conflicting_framebuffers); | ||
1678 | |||
1679 | /** | ||
1680 | * register_framebuffer - registers a frame buffer device | ||
1681 | * @fb_info: frame buffer info structure | ||
1682 | * | ||
1683 | * Registers a frame buffer device @fb_info. | ||
1684 | * | ||
1685 | * Returns negative errno on error, or zero for success. | ||
1686 | * | ||
1687 | */ | ||
1688 | int | ||
1689 | register_framebuffer(struct fb_info *fb_info) | ||
1690 | { | ||
1691 | int ret; | ||
1692 | |||
1693 | mutex_lock(®istration_lock); | ||
1694 | ret = do_register_framebuffer(fb_info); | ||
1695 | mutex_unlock(®istration_lock); | ||
1696 | |||
1697 | return ret; | ||
1698 | } | ||
1699 | |||
1700 | /** | ||
1701 | * unregister_framebuffer - releases a frame buffer device | ||
1702 | * @fb_info: frame buffer info structure | ||
1703 | * | ||
1704 | * Unregisters a frame buffer device @fb_info. | ||
1705 | * | ||
1706 | * Returns negative errno on error, or zero for success. | ||
1707 | * | ||
1708 | * This function will also notify the framebuffer console | ||
1709 | * to release the driver. | ||
1710 | * | ||
1711 | * This is meant to be called within a driver's module_exit() | ||
1712 | * function. If this is called outside module_exit(), ensure | ||
1713 | * that the driver implements fb_open() and fb_release() to | ||
1714 | * check that no processes are using the device. | ||
1715 | */ | ||
1716 | int | ||
1717 | unregister_framebuffer(struct fb_info *fb_info) | ||
1718 | { | ||
1719 | int ret; | ||
1720 | |||
1721 | mutex_lock(®istration_lock); | ||
1722 | ret = do_unregister_framebuffer(fb_info); | ||
1705 | mutex_unlock(®istration_lock); | 1723 | mutex_unlock(®istration_lock); |
1724 | |||
1706 | return ret; | 1725 | return ret; |
1707 | } | 1726 | } |
1708 | 1727 | ||
diff --git a/mm/shmem.c b/mm/shmem.c index 9e755c166cc5..dfc7069102ee 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1037,7 +1037,6 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) | |||
1037 | struct address_space *mapping; | 1037 | struct address_space *mapping; |
1038 | unsigned long index; | 1038 | unsigned long index; |
1039 | struct inode *inode; | 1039 | struct inode *inode; |
1040 | bool unlock_mutex = false; | ||
1041 | 1040 | ||
1042 | BUG_ON(!PageLocked(page)); | 1041 | BUG_ON(!PageLocked(page)); |
1043 | mapping = page->mapping; | 1042 | mapping = page->mapping; |
@@ -1072,15 +1071,14 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) | |||
1072 | * we've taken the spinlock, because shmem_unuse_inode() will | 1071 | * we've taken the spinlock, because shmem_unuse_inode() will |
1073 | * prune a !swapped inode from the swaplist under both locks. | 1072 | * prune a !swapped inode from the swaplist under both locks. |
1074 | */ | 1073 | */ |
1075 | if (swap.val && list_empty(&info->swaplist)) { | 1074 | if (swap.val) { |
1076 | mutex_lock(&shmem_swaplist_mutex); | 1075 | mutex_lock(&shmem_swaplist_mutex); |
1077 | /* move instead of add in case we're racing */ | 1076 | if (list_empty(&info->swaplist)) |
1078 | list_move_tail(&info->swaplist, &shmem_swaplist); | 1077 | list_add_tail(&info->swaplist, &shmem_swaplist); |
1079 | unlock_mutex = true; | ||
1080 | } | 1078 | } |
1081 | 1079 | ||
1082 | spin_lock(&info->lock); | 1080 | spin_lock(&info->lock); |
1083 | if (unlock_mutex) | 1081 | if (swap.val) |
1084 | mutex_unlock(&shmem_swaplist_mutex); | 1082 | mutex_unlock(&shmem_swaplist_mutex); |
1085 | 1083 | ||
1086 | if (index >= info->next_index) { | 1084 | if (index >= info->next_index) { |