diff options
Diffstat (limited to 'drivers/char')
94 files changed, 3074 insertions, 1690 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 47c6be84fc8..929d4fa73fd 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -481,6 +481,34 @@ config BRIQ_PANEL It's safe to say N here. +config BFIN_OTP + tristate "Blackfin On-Chip OTP Memory Support" + depends on BLACKFIN && (BF52x || BF54x) + default y + help + If you say Y here, you will get support for a character device + interface into the One Time Programmable memory pages that are + stored on the Blackfin processor. This will not get you access + to the secure memory pages however. You will need to write your + own secure code and reader for that. + + To compile this driver as a module, choose M here: the module + will be called bfin-otp. + + If unsure, it is safe to say Y. + +config BFIN_OTP_WRITE_ENABLE + bool "Enable writing support of OTP pages" + depends on BFIN_OTP + default n + help + If you say Y here, you will enable support for writing of the + OTP pages. This is dangerous by nature as you can only program + the pages once, so only enable this option when you actually + need it so as to not inadvertently clobber data. + + If unsure, say N. + config PRINTER tristate "Parallel printer support" depends on PARPORT @@ -704,9 +732,16 @@ config NVRAM To compile this driver as a module, choose M here: the module will be called nvram. +# +# These legacy RTC drivers just cause too many conflicts with the generic +# RTC framework ... let's not even try to coexist any more. +# +if RTC_LIB=n + config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390 + depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \ + && !ARM && !SUPERH && !S390 && !AVR32 ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -776,7 +811,7 @@ config SGI_IP27_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" - depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH + depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -812,6 +847,8 @@ config DS1302 will get access to the real time clock (or hardware clock) built into your computer. +endif # RTC_LIB + config COBALT_LCD bool "Support for Cobalt LCD" depends on MIPS_COBALT diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 5407b761561..4c1c584e9eb 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_HVCS) += hvcs.o obj-$(CONFIG_SGI_MBCS) += mbcs.o obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o +obj-$(CONFIG_BFIN_OTP) += bfin-otp.o obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_TIPAR) += tipar.o diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index d2866999214..96bdb9296b0 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -436,8 +436,9 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, system controller may experience noise due to strong drive strengths */ if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) { - u8 cap_ptr=0; struct pci_dev *gfxcard=NULL; + + cap_ptr = 0; while (!cap_ptr) { gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard); if (!gfxcard) { diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 55d7a82bd07..857b26227d8 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -967,7 +967,7 @@ int agpioc_chipset_flush_wrap(struct agp_file_private *priv) return 0; } -static int agp_ioctl(struct inode *inode, struct file *file, +static long agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct agp_file_private *curr_priv = file->private_data; @@ -1058,7 +1058,7 @@ static const struct file_operations agp_fops = .llseek = no_llseek, .read = agp_read, .write = agp_write, - .ioctl = agp_ioctl, + .unlocked_ioctl = agp_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = compat_agp_ioctl, #endif diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c new file mode 100644 index 00000000000..0a01329451e --- /dev/null +++ b/drivers/char/bfin-otp.c @@ -0,0 +1,189 @@ +/* + * Blackfin On-Chip OTP Memory Interface + * Supports BF52x/BF54x + * + * Copyright 2007-2008 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/types.h> + +#include <asm/blackfin.h> +#include <asm/uaccess.h> + +#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) +#define stampit() stamp("here i am") +#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); }) + +#define DRIVER_NAME "bfin-otp" +#define PFX DRIVER_NAME ": " + +static DEFINE_MUTEX(bfin_otp_lock); + +/* OTP Boot ROM functions */ +#define _BOOTROM_OTP_COMMAND 0xEF000018 +#define _BOOTROM_OTP_READ 0xEF00001A +#define _BOOTROM_OTP_WRITE 0xEF00001C + +static u32 (* const otp_command)(u32 command, u32 value) = (void *)_BOOTROM_OTP_COMMAND; +static u32 (* const otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_READ; +static u32 (* const otp_write)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_WRITE; + +/* otp_command(): defines for "command" */ +#define OTP_INIT 0x00000001 +#define OTP_CLOSE 0x00000002 + +/* otp_{read,write}(): defines for "flags" */ +#define OTP_LOWER_HALF 0x00000000 /* select upper/lower 64-bit half (bit 0) */ +#define OTP_UPPER_HALF 0x00000001 +#define OTP_NO_ECC 0x00000010 /* do not use ECC */ +#define OTP_LOCK 0x00000020 /* sets page protection bit for page */ +#define OTP_ACCESS_READ 0x00001000 +#define OTP_ACCESS_READWRITE 0x00002000 + +/* Return values for all functions */ +#define OTP_SUCCESS 0x00000000 +#define OTP_MASTER_ERROR 0x001 +#define OTP_WRITE_ERROR 0x003 +#define OTP_READ_ERROR 0x005 +#define OTP_ACC_VIO_ERROR 0x009 +#define OTP_DATA_MULT_ERROR 0x011 +#define OTP_ECC_MULT_ERROR 0x021 +#define OTP_PREV_WR_ERROR 0x041 +#define OTP_DATA_SB_WARN 0x100 +#define OTP_ECC_SB_WARN 0x200 + +/** + * bfin_otp_read - Read OTP pages + * + * All reads must be in half page chunks (half page == 64 bits). + */ +static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count, loff_t *pos) +{ + ssize_t bytes_done; + u32 page, flags, ret; + u64 content; + + stampit(); + + if (count % sizeof(u64)) + return -EMSGSIZE; + + if (mutex_lock_interruptible(&bfin_otp_lock)) + return -ERESTARTSYS; + + bytes_done = 0; + page = *pos / (sizeof(u64) * 2); + while (bytes_done < count) { + flags = (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF); + stamp("processing page %i (%s)", page, (flags == OTP_UPPER_HALF ? "upper" : "lower")); + ret = otp_read(page, flags, &content); + if (ret & OTP_MASTER_ERROR) { + bytes_done = -EIO; + break; + } + if (copy_to_user(buff + bytes_done, &content, sizeof(content))) { + bytes_done = -EFAULT; + break; + } + if (flags == OTP_UPPER_HALF) + ++page; + bytes_done += sizeof(content); + *pos += sizeof(content); + } + + mutex_unlock(&bfin_otp_lock); + + return bytes_done; +} + +#ifdef CONFIG_BFIN_OTP_WRITE_ENABLE +/** + * bfin_otp_write - Write OTP pages + * + * All writes must be in half page chunks (half page == 64 bits). + */ +static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos) +{ + stampit(); + + if (count % sizeof(u64)) + return -EMSGSIZE; + + if (mutex_lock_interruptible(&bfin_otp_lock)) + return -ERESTARTSYS; + + /* need otp_init() documentation before this can be implemented */ + + mutex_unlock(&bfin_otp_lock); + + return -EINVAL; +} +#else +# define bfin_otp_write NULL +#endif + +static struct file_operations bfin_otp_fops = { + .owner = THIS_MODULE, + .read = bfin_otp_read, + .write = bfin_otp_write, +}; + +static struct miscdevice bfin_otp_misc_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = DRIVER_NAME, + .fops = &bfin_otp_fops, +}; + +/** + * bfin_otp_init - Initialize module + * + * Registers the device and notifier handler. Actual device + * initialization is handled by bfin_otp_open(). + */ +static int __init bfin_otp_init(void) +{ + int ret; + + stampit(); + + ret = misc_register(&bfin_otp_misc_device); + if (ret) { + pr_init(KERN_ERR PFX "unable to register a misc device\n"); + return ret; + } + + pr_init(KERN_INFO PFX "initialized\n"); + + return 0; +} + +/** + * bfin_otp_exit - Deinitialize module + * + * Unregisters the device and notifier handler. Actual device + * deinitialization is handled by bfin_otp_close(). + */ +static void __exit bfin_otp_exit(void) +{ + stampit(); + + misc_deregister(&bfin_otp_misc_device); +} + +module_init(bfin_otp_init); +module_exit(bfin_otp_exit); + +MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); +MODULE_DESCRIPTION("Blackfin OTP Memory Interface"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c index c2d23cae951..c0a4a0bb509 100644 --- a/drivers/char/cs5535_gpio.c +++ b/drivers/char/cs5535_gpio.c @@ -215,7 +215,7 @@ static int __init cs5535_gpio_init(void) else mask = 0x0b003c66; - if (request_region(gpio_base, CS5535_GPIO_SIZE, NAME) == 0) { + if (!request_region(gpio_base, CS5535_GPIO_SIZE, NAME)) { printk(KERN_ERR NAME ": can't allocate I/O for GPIO\n"); return -ENODEV; } diff --git a/drivers/char/defkeymap.c_shipped b/drivers/char/defkeymap.c_shipped index 0aa419a6176..d2208dfe3f6 100644 --- a/drivers/char/defkeymap.c_shipped +++ b/drivers/char/defkeymap.c_shipped @@ -223,40 +223,40 @@ char *func_table[MAX_NR_FUNC] = { }; struct kbdiacruc accent_table[MAX_DIACR] = { - {'`', 'A', '\300'}, {'`', 'a', '\340'}, - {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, - {'^', 'A', '\302'}, {'^', 'a', '\342'}, - {'~', 'A', '\303'}, {'~', 'a', '\343'}, - {'"', 'A', '\304'}, {'"', 'a', '\344'}, - {'O', 'A', '\305'}, {'o', 'a', '\345'}, - {'0', 'A', '\305'}, {'0', 'a', '\345'}, - {'A', 'A', '\305'}, {'a', 'a', '\345'}, - {'A', 'E', '\306'}, {'a', 'e', '\346'}, - {',', 'C', '\307'}, {',', 'c', '\347'}, - {'`', 'E', '\310'}, {'`', 'e', '\350'}, - {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, - {'^', 'E', '\312'}, {'^', 'e', '\352'}, - {'"', 'E', '\313'}, {'"', 'e', '\353'}, - {'`', 'I', '\314'}, {'`', 'i', '\354'}, - {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, - {'^', 'I', '\316'}, {'^', 'i', '\356'}, - {'"', 'I', '\317'}, {'"', 'i', '\357'}, - {'-', 'D', '\320'}, {'-', 'd', '\360'}, - {'~', 'N', '\321'}, {'~', 'n', '\361'}, - {'`', 'O', '\322'}, {'`', 'o', '\362'}, - {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, - {'^', 'O', '\324'}, {'^', 'o', '\364'}, - {'~', 'O', '\325'}, {'~', 'o', '\365'}, - {'"', 'O', '\326'}, {'"', 'o', '\366'}, - {'/', 'O', '\330'}, {'/', 'o', '\370'}, - {'`', 'U', '\331'}, {'`', 'u', '\371'}, - {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, - {'^', 'U', '\333'}, {'^', 'u', '\373'}, - {'"', 'U', '\334'}, {'"', 'u', '\374'}, - {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, - {'T', 'H', '\336'}, {'t', 'h', '\376'}, - {'s', 's', '\337'}, {'"', 'y', '\377'}, - {'s', 'z', '\337'}, {'i', 'j', '\377'}, + {'`', 'A', 0300}, {'`', 'a', 0340}, + {'\'', 'A', 0301}, {'\'', 'a', 0341}, + {'^', 'A', 0302}, {'^', 'a', 0342}, + {'~', 'A', 0303}, {'~', 'a', 0343}, + {'"', 'A', 0304}, {'"', 'a', 0344}, + {'O', 'A', 0305}, {'o', 'a', 0345}, + {'0', 'A', 0305}, {'0', 'a', 0345}, + {'A', 'A', 0305}, {'a', 'a', 0345}, + {'A', 'E', 0306}, {'a', 'e', 0346}, + {',', 'C', 0307}, {',', 'c', 0347}, + {'`', 'E', 0310}, {'`', 'e', 0350}, + {'\'', 'E', 0311}, {'\'', 'e', 0351}, + {'^', 'E', 0312}, {'^', 'e', 0352}, + {'"', 'E', 0313}, {'"', 'e', 0353}, + {'`', 'I', 0314}, {'`', 'i', 0354}, + {'\'', 'I', 0315}, {'\'', 'i', 0355}, + {'^', 'I', 0316}, {'^', 'i', 0356}, + {'"', 'I', 0317}, {'"', 'i', 0357}, + {'-', 'D', 0320}, {'-', 'd', 0360}, + {'~', 'N', 0321}, {'~', 'n', 0361}, + {'`', 'O', 0322}, {'`', 'o', 0362}, + {'\'', 'O', 0323}, {'\'', 'o', 0363}, + {'^', 'O', 0324}, {'^', 'o', 0364}, + {'~', 'O', 0325}, {'~', 'o', 0365}, + {'"', 'O', 0326}, {'"', 'o', 0366}, + {'/', 'O', 0330}, {'/', 'o', 0370}, + {'`', 'U', 0331}, {'`', 'u', 0371}, + {'\'', 'U', 0332}, {'\'', 'u', 0372}, + {'^', 'U', 0333}, {'^', 'u', 0373}, + {'"', 'U', 0334}, {'"', 'u', 0374}, + {'\'', 'Y', 0335}, {'\'', 'y', 0375}, + {'T', 'H', 0336}, {'t', 'h', 0376}, + {'s', 's', 0337}, {'"', 'y', 0377}, + {'s', 'z', 0337}, {'i', 'j', 0377}, }; unsigned int accent_table_size = 68; diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index d352dbb4ccf..b710426bab3 100644 --- a/drivers/char/drm/ati_pcigart.c +++ b/drivers/char/drm/ati_pcigart.c @@ -35,42 +35,23 @@ # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ -static void *drm_ati_alloc_pcigart_table(int order) +static int drm_ati_alloc_pcigart_table(struct drm_device *dev, + struct drm_ati_pcigart_info *gart_info) { - unsigned long address; - struct page *page; - int i; - - DRM_DEBUG("%d order\n", order); - - address = __get_free_pages(GFP_KERNEL | __GFP_COMP, - order); - if (address == 0UL) { - return NULL; - } - - page = virt_to_page(address); - - for (i = 0; i < order; i++, page++) - SetPageReserved(page); + gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size, + PAGE_SIZE, + gart_info->table_mask); + if (gart_info->table_handle == NULL) + return -ENOMEM; - DRM_DEBUG("returning 0x%08lx\n", address); - return (void *)address; + return 0; } -static void drm_ati_free_pcigart_table(void *address, int order) +static void drm_ati_free_pcigart_table(struct drm_device *dev, + struct drm_ati_pcigart_info *gart_info) { - struct page *page; - int i; - int num_pages = 1 << order; - DRM_DEBUG("\n"); - - page = virt_to_page((unsigned long)address); - - for (i = 0; i < num_pages; i++, page++) - ClearPageReserved(page); - - free_pages((unsigned long)address, order); + drm_pci_free(dev, gart_info->table_handle); + gart_info->table_handle = NULL; } int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) @@ -78,8 +59,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info struct drm_sg_mem *entry = dev->sg; unsigned long pages; int i; - int order; - int num_pages, max_pages; + int max_pages; /* we need to support large memory configurations */ if (!entry) { @@ -87,15 +67,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info return 0; } - order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE); - num_pages = 1 << order; - if (gart_info->bus_addr) { - if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { - pci_unmap_single(dev->pdev, gart_info->bus_addr, - num_pages * PAGE_SIZE, - PCI_DMA_TODEVICE); - } max_pages = (gart_info->table_size / sizeof(u32)); pages = (entry->pages <= max_pages) @@ -112,10 +84,9 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info gart_info->bus_addr = 0; } - if (gart_info->gart_table_location == DRM_ATI_GART_MAIN - && gart_info->addr) { - drm_ati_free_pcigart_table(gart_info->addr, order); - gart_info->addr = NULL; + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN && + gart_info->table_handle) { + drm_ati_free_pcigart_table(dev, gart_info); } return 1; @@ -127,11 +98,10 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga struct drm_sg_mem *entry = dev->sg; void *address = NULL; unsigned long pages; - u32 *pci_gart, page_base, bus_address = 0; + u32 *pci_gart, page_base; + dma_addr_t bus_address = 0; int i, j, ret = 0; - int order; int max_pages; - int num_pages; if (!entry) { DRM_ERROR("no scatter/gather memory!\n"); @@ -141,36 +111,20 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); - order = drm_order((gart_info->table_size + - (PAGE_SIZE-1)) / PAGE_SIZE); - num_pages = 1 << order; - address = drm_ati_alloc_pcigart_table(order); - if (!address) { + ret = drm_ati_alloc_pcigart_table(dev, gart_info); + if (ret) { DRM_ERROR("cannot allocate PCI GART page!\n"); goto done; } - if (!dev->pdev) { - DRM_ERROR("PCI device unknown!\n"); - goto done; - } - - bus_address = pci_map_single(dev->pdev, address, - num_pages * PAGE_SIZE, - PCI_DMA_TODEVICE); - if (bus_address == 0) { - DRM_ERROR("unable to map PCIGART pages!\n"); - order = drm_order((gart_info->table_size + - (PAGE_SIZE-1)) / PAGE_SIZE); - drm_ati_free_pcigart_table(address, order); - address = NULL; - goto done; - } + address = gart_info->table_handle->vaddr; + bus_address = gart_info->table_handle->busaddr; } else { address = gart_info->addr; bus_address = gart_info->bus_addr; - DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n", - bus_address, (unsigned long)address); + DRM_DEBUG("PCI: Gart Table: VRAM %08LX mapped at %08lX\n", + (unsigned long long)bus_address, + (unsigned long)address); } pci_gart = (u32 *) address; @@ -213,7 +167,6 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga page_base += ATI_PCIGART_PAGE_SIZE; } } - ret = 1; #if defined(__i386__) || defined(__x86_64__) diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h index 3a05c6d5ebe..6874f31ca8c 100644 --- a/drivers/char/drm/drm.h +++ b/drivers/char/drm/drm.h @@ -471,6 +471,7 @@ struct drm_irq_busid { enum drm_vblank_seq_type { _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ @@ -503,6 +504,21 @@ union drm_wait_vblank { struct drm_wait_vblank_reply reply; }; +enum drm_modeset_ctl_cmd { + _DRM_PRE_MODESET = 1, + _DRM_POST_MODESET = 2, +}; + +/** + * DRM_IOCTL_MODESET_CTL ioctl argument type + * + * \sa drmModesetCtl(). + */ +struct drm_modeset_ctl { + unsigned long arg; + enum drm_modeset_ctl_cmd cmd; +}; + /** * DRM_IOCTL_AGP_ENABLE ioctl argument type. * @@ -587,6 +603,7 @@ struct drm_set_version { #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) +#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index a6789f25009..ecee3547a13 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -54,6 +54,7 @@ #include <linux/pci.h> #include <linux/jiffies.h> #include <linux/smp_lock.h> /* For (un)lock_kernel */ +#include <linux/dma-mapping.h> #include <linux/mm.h> #include <linux/cdev.h> #include <linux/mutex.h> @@ -99,10 +100,8 @@ struct drm_device; #define DRIVER_HAVE_DMA 0x20 #define DRIVER_HAVE_IRQ 0x40 #define DRIVER_IRQ_SHARED 0x80 -#define DRIVER_IRQ_VBL 0x100 #define DRIVER_DMA_QUEUE 0x200 #define DRIVER_FB_DMA 0x400 -#define DRIVER_IRQ_VBL2 0x800 /***********************************************************************/ /** \name Begin the DRM... */ @@ -378,13 +377,12 @@ struct drm_buf_entry { struct drm_file { int authenticated; int master; - int minor; pid_t pid; uid_t uid; drm_magic_t magic; unsigned long ioctl_count; struct list_head lhead; - struct drm_head *head; + struct drm_minor *minor; int remove_auth_on_close; unsigned long lock_count; struct file *filp; @@ -551,6 +549,8 @@ struct drm_ati_pcigart_info { int gart_reg_if; void *addr; dma_addr_t bus_addr; + dma_addr_t table_mask; + struct drm_dma_handle *table_handle; drm_local_map_t mapping; int table_size; }; @@ -577,10 +577,52 @@ struct drm_driver { int (*context_dtor) (struct drm_device *dev, int context); int (*kernel_context_switch) (struct drm_device *dev, int old, int new); - void (*kernel_context_switch_unlock) (struct drm_device *dev); - int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence); - int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence); - int (*dri_library_name) (struct drm_device *dev, char *buf); + void (*kernel_context_switch_unlock) (struct drm_device * dev); + /** + * get_vblank_counter - get raw hardware vblank counter + * @dev: DRM device + * @crtc: counter to fetch + * + * Driver callback for fetching a raw hardware vblank counter + * for @crtc. If a device doesn't have a hardware counter, the + * driver can simply return the value of drm_vblank_count and + * make the enable_vblank() and disable_vblank() hooks into no-ops, + * leaving interrupts enabled at all times. + * + * Wraparound handling and loss of events due to modesetting is dealt + * with in the DRM core code. + * + * RETURNS + * Raw vblank counter value. + */ + u32 (*get_vblank_counter) (struct drm_device *dev, int crtc); + + /** + * enable_vblank - enable vblank interrupt events + * @dev: DRM device + * @crtc: which irq to enable + * + * Enable vblank interrupts for @crtc. If the device doesn't have + * a hardware vblank counter, this routine should be a no-op, since + * interrupts will have to stay on to keep the count accurate. + * + * RETURNS + * Zero on success, appropriate errno if the given @crtc's vblank + * interrupt cannot be enabled. + */ + int (*enable_vblank) (struct drm_device *dev, int crtc); + + /** + * disable_vblank - disable vblank interrupt events + * @dev: DRM device + * @crtc: which irq to enable + * + * Disable vblank interrupts for @crtc. If the device doesn't have + * a hardware vblank counter, this routine should be a no-op, since + * interrupts will have to stay on to keep the count accurate. + */ + void (*disable_vblank) (struct drm_device *dev, int crtc); + int (*dri_library_name) (struct drm_device *dev, char * buf); /** * Called by \c drm_device_is_agp. Typically used to determine if a @@ -599,7 +641,7 @@ struct drm_driver { irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); void (*irq_preinstall) (struct drm_device *dev); - void (*irq_postinstall) (struct drm_device *dev); + int (*irq_postinstall) (struct drm_device *dev); void (*irq_uninstall) (struct drm_device *dev); void (*reclaim_buffers) (struct drm_device *dev, struct drm_file * file_priv); @@ -627,17 +669,19 @@ struct drm_driver { struct pci_driver pci_driver; }; +#define DRM_MINOR_UNASSIGNED 0 +#define DRM_MINOR_LEGACY 1 + /** - * DRM head structure. This structure represent a video head on a card - * that may contain multiple heads. Embed one per head of these in the - * private drm_device structure. + * DRM minor structure. This structure represents a drm minor number. */ -struct drm_head { - int minor; /**< Minor device number */ +struct drm_minor { + int index; /**< Minor device number */ + int type; /**< Control or render */ + dev_t device; /**< Device number for mknod */ + struct device kdev; /**< Linux device */ struct drm_device *dev; struct proc_dir_entry *dev_root; /**< proc directory entry */ - dev_t device; /**< Device number for mknod */ - struct class_device *dev_class; }; /** @@ -645,7 +689,6 @@ struct drm_head { * may contain multiple heads. */ struct drm_device { - struct device dev; /**< Linux device */ char *unique; /**< Unique identifier: e.g., busid */ int unique_len; /**< Length of unique field */ char *devname; /**< For /proc/interrupts */ @@ -727,13 +770,21 @@ struct drm_device { /** \name VBLANK IRQ support */ /*@{ */ - wait_queue_head_t vbl_queue; /**< VBLANK wait queue */ - atomic_t vbl_received; - atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */ + wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */ + atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */ spinlock_t vbl_lock; - struct list_head vbl_sigs; /**< signal list to send on VBLANK */ - struct list_head vbl_sigs2; /**< signals to send on secondary VBLANK */ - unsigned int vbl_pending; + struct list_head *vbl_sigs; /**< signal list to send on VBLANK */ + atomic_t vbl_signal_pending; /* number of signals pending on all crtcs*/ + atomic_t *vblank_refcount; /* number of users of vblank interrupts per crtc */ + u32 *last_vblank; /* protected by dev->vbl_lock, used */ + /* for wraparound handling */ + u32 *vblank_offset; /* used to track how many vblanks */ + int *vblank_enabled; /* so we don't call enable more than + once per disable */ + u32 *vblank_premodeset; /* were lost during modeset */ + struct timer_list vblank_disable_timer; + + unsigned long max_vblank_count; /**< size of vblank counter register */ spinlock_t tasklet_lock; /**< For drm_locked_tasklet */ void (*locked_tasklet_func)(struct drm_device *dev); @@ -753,6 +804,7 @@ struct drm_device { #ifdef __alpha__ struct pci_controller *hose; #endif + int num_crtcs; /**< Number of CRTCs on this device */ struct drm_sg_mem *sg; /**< Scatter gather memory */ void *dev_private; /**< device private data */ struct drm_sigdata sigdata; /**< For block_all_signals */ @@ -761,7 +813,7 @@ struct drm_device { struct drm_driver *driver; drm_local_map_t *agp_buffer_map; unsigned int agp_buffer_token; - struct drm_head primary; /**< primary screen head */ + struct drm_minor *primary; /**< render type primary screen head */ /** \name Drawable information */ /*@{ */ @@ -987,11 +1039,19 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev); extern void drm_driver_irq_postinstall(struct drm_device *dev); extern void drm_driver_irq_uninstall(struct drm_device *dev); -extern int drm_wait_vblank(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); -extern void drm_vbl_send_signals(struct drm_device *dev); +extern int drm_vblank_init(struct drm_device *dev, int num_crtcs); +extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp); +extern int drm_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq); extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*)); +extern u32 drm_vblank_count(struct drm_device *dev, int crtc); +extern void drm_update_vblank_count(struct drm_device *dev, int crtc); +extern void drm_handle_vblank(struct drm_device *dev, int crtc); +extern int drm_vblank_get(struct drm_device *dev, int crtc); +extern void drm_vblank_put(struct drm_device *dev, int crtc); + + /* Modesetting support */ +extern int drm_modeset_ctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); /* AGP/GART support (drm_agpsupport.h) */ extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); @@ -1028,23 +1088,20 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle); extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver); extern int drm_put_dev(struct drm_device *dev); -extern int drm_put_head(struct drm_head *head); +extern int drm_put_minor(struct drm_minor **minor); extern unsigned int drm_debug; -extern unsigned int drm_cards_limit; -extern struct drm_head **drm_heads; + extern struct class *drm_class; extern struct proc_dir_entry *drm_proc_root; +extern struct idr drm_minors_idr; + extern drm_local_map_t *drm_getsarea(struct drm_device *dev); /* Proc support (drm_proc.h) */ -extern int drm_proc_init(struct drm_device *dev, - int minor, - struct proc_dir_entry *root, - struct proc_dir_entry **dev_root); -extern int drm_proc_cleanup(int minor, - struct proc_dir_entry *root, - struct proc_dir_entry *dev_root); +extern int drm_proc_init(struct drm_minor *minor, int minor_id, + struct proc_dir_entry *root); +extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root); /* Scatter Gather Support (drm_scatter.h) */ extern void drm_sg_cleanup(struct drm_sg_mem * entry); @@ -1069,8 +1126,8 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah); struct drm_sysfs_class; extern struct class *drm_sysfs_create(struct module *owner, char *name); extern void drm_sysfs_destroy(void); -extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head); -extern void drm_sysfs_device_remove(struct drm_device *dev); +extern int drm_sysfs_device_add(struct drm_minor *minor); +extern void drm_sysfs_device_remove(struct drm_minor *minor); /* * Basic memory manager support (drm_mm.c) diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c index 9468c7889ff..aefa5ac4c0b 100644 --- a/drivers/char/drm/drm_agpsupport.c +++ b/drivers/char/drm/drm_agpsupport.c @@ -122,7 +122,7 @@ EXPORT_SYMBOL(drm_agp_acquire); int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - return drm_agp_acquire((struct drm_device *) file_priv->head->dev); + return drm_agp_acquire((struct drm_device *) file_priv->minor->dev); } /** diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 0e7af53c87d..fc54140551a 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c @@ -313,35 +313,36 @@ static void drm_cleanup(struct drm_device * dev) drm_ht_remove(&dev->map_hash); drm_ctxbitmap_cleanup(dev); - drm_put_head(&dev->primary); + drm_put_minor(&dev->primary); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n"); } -void drm_exit(struct drm_driver *driver) +int drm_minors_cleanup(int id, void *ptr, void *data) { - int i; - struct drm_device *dev = NULL; - struct drm_head *head; + struct drm_minor *minor = ptr; + struct drm_device *dev; + struct drm_driver *driver = data; + + dev = minor->dev; + if (minor->dev->driver != driver) + return 0; + + if (minor->type != DRM_MINOR_LEGACY) + return 0; + if (dev) + pci_dev_put(dev->pdev); + drm_cleanup(dev); + return 1; +} + +void drm_exit(struct drm_driver *driver) +{ DRM_DEBUG("\n"); - for (i = 0; i < drm_cards_limit; i++) { - head = drm_heads[i]; - if (!head) - continue; - if (!head->dev) - continue; - if (head->dev->driver != driver) - continue; - dev = head->dev; - if (dev) { - /* release the pci driver */ - if (dev->pdev) - pci_dev_put(dev->pdev); - drm_cleanup(dev); - } - } + idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver); + DRM_INFO("Module unloaded\n"); } @@ -357,13 +358,7 @@ static int __init drm_core_init(void) { int ret = -ENOMEM; - drm_cards_limit = - (drm_cards_limit < - DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1); - drm_heads = - drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB); - if (!drm_heads) - goto err_p1; + idr_init(&drm_minors_idr); if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops)) goto err_p1; @@ -391,7 +386,8 @@ err_p3: drm_sysfs_destroy(); err_p2: unregister_chrdev(DRM_MAJOR, "drm"); - drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); + + idr_destroy(&drm_minors_idr); err_p1: return ret; } @@ -403,7 +399,7 @@ static void __exit drm_core_exit(void) unregister_chrdev(DRM_MAJOR, "drm"); - drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); + idr_destroy(&drm_minors_idr); } module_init(drm_core_init); @@ -452,7 +448,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; struct drm_ioctl_desc *ioctl; drm_ioctl_t *func; unsigned int nr = DRM_IOCTL_NR(cmd); @@ -465,7 +461,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", task_pid_nr(current), cmd, nr, - (long)old_encode_dev(file_priv->head->device), + (long)old_encode_dev(file_priv->minor->device), file_priv->authenticated); if ((nr >= DRM_CORE_IOCTL_COUNT) && diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 3992f73299c..68f0da801ed 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c @@ -129,16 +129,15 @@ static int drm_setup(struct drm_device * dev) int drm_open(struct inode *inode, struct file *filp) { struct drm_device *dev = NULL; - int minor = iminor(inode); + int minor_id = iminor(inode); + struct drm_minor *minor; int retcode = 0; - if (!((minor >= 0) && (minor < drm_cards_limit))) + minor = idr_find(&drm_minors_idr, minor_id); + if (!minor) return -ENODEV; - if (!drm_heads[minor]) - return -ENODEV; - - if (!(dev = drm_heads[minor]->dev)) + if (!(dev = minor->dev)) return -ENODEV; retcode = drm_open_helper(inode, filp, dev); @@ -168,19 +167,18 @@ EXPORT_SYMBOL(drm_open); int drm_stub_open(struct inode *inode, struct file *filp) { struct drm_device *dev = NULL; - int minor = iminor(inode); + struct drm_minor *minor; + int minor_id = iminor(inode); int err = -ENODEV; const struct file_operations *old_fops; DRM_DEBUG("\n"); - if (!((minor >= 0) && (minor < drm_cards_limit))) - return -ENODEV; - - if (!drm_heads[minor]) + minor = idr_find(&drm_minors_idr, minor_id); + if (!minor) return -ENODEV; - if (!(dev = drm_heads[minor]->dev)) + if (!(dev = minor->dev)) return -ENODEV; old_fops = filp->f_op; @@ -225,7 +223,7 @@ static int drm_cpu_valid(void) static int drm_open_helper(struct inode *inode, struct file *filp, struct drm_device * dev) { - int minor = iminor(inode); + int minor_id = iminor(inode); struct drm_file *priv; int ret; @@ -234,7 +232,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, if (!drm_cpu_valid()) return -EINVAL; - DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor); + DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id); priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES); if (!priv) @@ -245,8 +243,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, priv->filp = filp; priv->uid = current->euid; priv->pid = task_pid_nr(current); - priv->minor = minor; - priv->head = drm_heads[minor]; + priv->minor = idr_find(&drm_minors_idr, minor_id); priv->ioctl_count = 0; /* for compatibility root is always authenticated */ priv->authenticated = capable(CAP_SYS_ADMIN); @@ -297,11 +294,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp, int drm_fasync(int fd, struct file *filp, int on) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; int retcode; DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, - (long)old_encode_dev(priv->head->device)); + (long)old_encode_dev(priv->minor->device)); retcode = fasync_helper(fd, filp, on, &dev->buf_async); if (retcode < 0) return retcode; @@ -324,8 +321,9 @@ EXPORT_SYMBOL(drm_fasync); int drm_release(struct inode *inode, struct file *filp) { struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; int retcode = 0; + unsigned long irqflags; lock_kernel(); @@ -340,14 +338,14 @@ int drm_release(struct inode *inode, struct file *filp) DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", task_pid_nr(current), - (long)old_encode_dev(file_priv->head->device), + (long)old_encode_dev(file_priv->minor->device), dev->open_count); if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) { if (drm_i_have_hw_lock(dev, file_priv)) { dev->driver->reclaim_buffers_locked(dev, file_priv); } else { - unsigned long _end=jiffies + 3*DRM_HZ; + unsigned long endtime = jiffies + 3 * DRM_HZ; int locked = 0; drm_idlelock_take(&dev->lock); @@ -357,13 +355,15 @@ int drm_release(struct inode *inode, struct file *filp) */ do{ - spin_lock(&dev->lock.spinlock); + spin_lock_irqsave(&dev->lock.spinlock, + irqflags); locked = dev->lock.idle_has_lock; - spin_unlock(&dev->lock.spinlock); + spin_unlock_irqrestore(&dev->lock.spinlock, + irqflags); if (locked) break; schedule(); - } while (!time_after_eq(jiffies, _end)); + } while (!time_after_eq(jiffies, endtime)); if (!locked) { DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n" diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c index 089c015c01d..286f9d61e7d 100644 --- a/drivers/char/drm/drm_irq.c +++ b/drivers/char/drm/drm_irq.c @@ -71,6 +71,117 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, return 0; } +static void vblank_disable_fn(unsigned long arg) +{ + struct drm_device *dev = (struct drm_device *)arg; + unsigned long irqflags; + int i; + + for (i = 0; i < dev->num_crtcs; i++) { + spin_lock_irqsave(&dev->vbl_lock, irqflags); + if (atomic_read(&dev->vblank_refcount[i]) == 0 && + dev->vblank_enabled[i]) { + dev->driver->disable_vblank(dev, i); + dev->vblank_enabled[i] = 0; + } + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + } +} + +static void drm_vblank_cleanup(struct drm_device *dev) +{ + /* Bail if the driver didn't call drm_vblank_init() */ + if (dev->num_crtcs == 0) + return; + + del_timer(&dev->vblank_disable_timer); + + vblank_disable_fn((unsigned long)dev); + + drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs, + DRM_MEM_DRIVER); + drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs, + DRM_MEM_DRIVER); + drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) * + dev->num_crtcs, DRM_MEM_DRIVER); + drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) * + dev->num_crtcs, DRM_MEM_DRIVER); + drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) * + dev->num_crtcs, DRM_MEM_DRIVER); + drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs, + DRM_MEM_DRIVER); + drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) * + dev->num_crtcs, DRM_MEM_DRIVER); + drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs, + DRM_MEM_DRIVER); + + dev->num_crtcs = 0; +} + +int drm_vblank_init(struct drm_device *dev, int num_crtcs) +{ + int i, ret = -ENOMEM; + + setup_timer(&dev->vblank_disable_timer, vblank_disable_fn, + (unsigned long)dev); + spin_lock_init(&dev->vbl_lock); + atomic_set(&dev->vbl_signal_pending, 0); + dev->num_crtcs = num_crtcs; + + dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->vbl_queue) + goto err; + + dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->vbl_sigs) + goto err; + + dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->_vblank_count) + goto err; + + dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs, + DRM_MEM_DRIVER); + if (!dev->vblank_refcount) + goto err; + + dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int), + DRM_MEM_DRIVER); + if (!dev->vblank_enabled) + goto err; + + dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER); + if (!dev->last_vblank) + goto err; + + dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32), + DRM_MEM_DRIVER); + if (!dev->vblank_premodeset) + goto err; + + dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER); + if (!dev->vblank_offset) + goto err; + + /* Zero per-crtc vblank stuff */ + for (i = 0; i < num_crtcs; i++) { + init_waitqueue_head(&dev->vbl_queue[i]); + INIT_LIST_HEAD(&dev->vbl_sigs[i]); + atomic_set(&dev->_vblank_count[i], 0); + atomic_set(&dev->vblank_refcount[i], 0); + } + + return 0; + +err: + drm_vblank_cleanup(dev); + return ret; +} +EXPORT_SYMBOL(drm_vblank_init); + /** * Install IRQ handler. * @@ -109,17 +220,6 @@ static int drm_irq_install(struct drm_device * dev) DRM_DEBUG("irq=%d\n", dev->irq); - if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) { - init_waitqueue_head(&dev->vbl_queue); - - spin_lock_init(&dev->vbl_lock); - - INIT_LIST_HEAD(&dev->vbl_sigs); - INIT_LIST_HEAD(&dev->vbl_sigs2); - - dev->vbl_pending = 0; - } - /* Before installing handler */ dev->driver->irq_preinstall(dev); @@ -137,9 +237,14 @@ static int drm_irq_install(struct drm_device * dev) } /* After installing handler */ - dev->driver->irq_postinstall(dev); + ret = dev->driver->irq_postinstall(dev); + if (ret < 0) { + mutex_lock(&dev->struct_mutex); + dev->irq_enabled = 0; + mutex_unlock(&dev->struct_mutex); + } - return 0; + return ret; } /** @@ -170,6 +275,8 @@ int drm_irq_uninstall(struct drm_device * dev) free_irq(dev->irq, dev); + drm_vblank_cleanup(dev); + dev->locked_tasklet_func = NULL; return 0; @@ -214,6 +321,148 @@ int drm_control(struct drm_device *dev, void *data, } /** + * drm_vblank_count - retrieve "cooked" vblank counter value + * @dev: DRM device + * @crtc: which counter to retrieve + * + * Fetches the "cooked" vblank count value that represents the number of + * vblank events since the system was booted, including lost events due to + * modesetting activity. + */ +u32 drm_vblank_count(struct drm_device *dev, int crtc) +{ + return atomic_read(&dev->_vblank_count[crtc]) + + dev->vblank_offset[crtc]; +} +EXPORT_SYMBOL(drm_vblank_count); + +/** + * drm_update_vblank_count - update the master vblank counter + * @dev: DRM device + * @crtc: counter to update + * + * Call back into the driver to update the appropriate vblank counter + * (specified by @crtc). Deal with wraparound, if it occurred, and + * update the last read value so we can deal with wraparound on the next + * call if necessary. + */ +void drm_update_vblank_count(struct drm_device *dev, int crtc) +{ + unsigned long irqflags; + u32 cur_vblank, diff; + + /* + * Interrupts were disabled prior to this call, so deal with counter + * wrap if needed. + * NOTE! It's possible we lost a full dev->max_vblank_count events + * here if the register is small or we had vblank interrupts off for + * a long time. + */ + cur_vblank = dev->driver->get_vblank_counter(dev, crtc); + spin_lock_irqsave(&dev->vbl_lock, irqflags); + if (cur_vblank < dev->last_vblank[crtc]) { + diff = dev->max_vblank_count - + dev->last_vblank[crtc]; + diff += cur_vblank; + } else { + diff = cur_vblank - dev->last_vblank[crtc]; + } + dev->last_vblank[crtc] = cur_vblank; + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + + atomic_add(diff, &dev->_vblank_count[crtc]); +} +EXPORT_SYMBOL(drm_update_vblank_count); + +/** + * drm_vblank_get - get a reference count on vblank events + * @dev: DRM device + * @crtc: which CRTC to own + * + * Acquire a reference count on vblank events to avoid having them disabled + * while in use. Note callers will probably want to update the master counter + * using drm_update_vblank_count() above before calling this routine so that + * wakeups occur on the right vblank event. + * + * RETURNS + * Zero on success, nonzero on failure. + */ +int drm_vblank_get(struct drm_device *dev, int crtc) +{ + unsigned long irqflags; + int ret = 0; + + spin_lock_irqsave(&dev->vbl_lock, irqflags); + /* Going from 0->1 means we have to enable interrupts again */ + if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 && + !dev->vblank_enabled[crtc]) { + ret = dev->driver->enable_vblank(dev, crtc); + if (ret) + atomic_dec(&dev->vblank_refcount[crtc]); + else + dev->vblank_enabled[crtc] = 1; + } + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + + return ret; +} +EXPORT_SYMBOL(drm_vblank_get); + +/** + * drm_vblank_put - give up ownership of vblank events + * @dev: DRM device + * @crtc: which counter to give up + * + * Release ownership of a given vblank counter, turning off interrupts + * if possible. + */ +void drm_vblank_put(struct drm_device *dev, int crtc) +{ + /* Last user schedules interrupt disable */ + if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) + mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); +} +EXPORT_SYMBOL(drm_vblank_put); + +/** + * drm_modeset_ctl - handle vblank event counter changes across mode switch + * @DRM_IOCTL_ARGS: standard ioctl arguments + * + * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET + * ioctls around modesetting so that any lost vblank events are accounted for. + */ +int drm_modeset_ctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_modeset_ctl *modeset = data; + int crtc, ret = 0; + u32 new; + + crtc = modeset->arg; + if (crtc >= dev->num_crtcs) { + ret = -EINVAL; + goto out; + } + + switch (modeset->cmd) { + case _DRM_PRE_MODESET: + dev->vblank_premodeset[crtc] = + dev->driver->get_vblank_counter(dev, crtc); + break; + case _DRM_POST_MODESET: + new = dev->driver->get_vblank_counter(dev, crtc); + dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new; + break; + default: + ret = -EINVAL; + break; + } + +out: + return ret; +} + +/** * Wait for VBLANK. * * \param inode device inode. @@ -232,12 +481,13 @@ int drm_control(struct drm_device *dev, void *data, * * If a signal is not requested, then calls vblank_wait(). */ -int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) +int drm_wait_vblank(struct drm_device *dev, void *data, + struct drm_file *file_priv) { union drm_wait_vblank *vblwait = data; struct timeval now; int ret = 0; - unsigned int flags, seq; + unsigned int flags, seq, crtc; if ((!dev->irq) || (!dev->irq_enabled)) return -EINVAL; @@ -251,13 +501,13 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr } flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; + crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; - if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ? - DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL)) + if (crtc >= dev->num_crtcs) return -EINVAL; - seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 - : &dev->vbl_received); + drm_update_vblank_count(dev, crtc); + seq = drm_vblank_count(dev, crtc); switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { case _DRM_VBLANK_RELATIVE: @@ -276,8 +526,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr if (flags & _DRM_VBLANK_SIGNAL) { unsigned long irqflags; - struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY) - ? &dev->vbl_sigs2 : &dev->vbl_sigs; + struct list_head *vbl_sigs = &dev->vbl_sigs[crtc]; struct drm_vbl_sig *vbl_sig; spin_lock_irqsave(&dev->vbl_lock, irqflags); @@ -298,22 +547,26 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr } } - if (dev->vbl_pending >= 100) { + if (atomic_read(&dev->vbl_signal_pending) >= 100) { spin_unlock_irqrestore(&dev->vbl_lock, irqflags); return -EBUSY; } - dev->vbl_pending++; - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - if (! - (vbl_sig = - drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) { + vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig), + DRM_MEM_DRIVER); + if (!vbl_sig) return -ENOMEM; + + ret = drm_vblank_get(dev, crtc); + if (ret) { + drm_free(vbl_sig, sizeof(struct drm_vbl_sig), + DRM_MEM_DRIVER); + return ret; } - memset((void *)vbl_sig, 0, sizeof(*vbl_sig)); + atomic_inc(&dev->vbl_signal_pending); vbl_sig->sequence = vblwait->request.sequence; vbl_sig->info.si_signo = vblwait->request.signal; @@ -327,17 +580,20 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr vblwait->reply.sequence = seq; } else { - if (flags & _DRM_VBLANK_SECONDARY) { - if (dev->driver->vblank_wait2) - ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence); - } else if (dev->driver->vblank_wait) - ret = - dev->driver->vblank_wait(dev, - &vblwait->request.sequence); - + unsigned long cur_vblank; + + ret = drm_vblank_get(dev, crtc); + if (ret) + return ret; + DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, + (((cur_vblank = drm_vblank_count(dev, crtc)) + - vblwait->request.sequence) <= (1 << 23))); + drm_vblank_put(dev, crtc); do_gettimeofday(&now); + vblwait->reply.tval_sec = now.tv_sec; vblwait->reply.tval_usec = now.tv_usec; + vblwait->reply.sequence = cur_vblank; } done: @@ -348,44 +604,57 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr * Send the VBLANK signals. * * \param dev DRM device. + * \param crtc CRTC where the vblank event occurred * * Sends a signal for each task in drm_device::vbl_sigs and empties the list. * * If a signal is not requested, then calls vblank_wait(). */ -void drm_vbl_send_signals(struct drm_device * dev) +static void drm_vbl_send_signals(struct drm_device * dev, int crtc) { + struct drm_vbl_sig *vbl_sig, *tmp; + struct list_head *vbl_sigs; + unsigned int vbl_seq; unsigned long flags; - int i; spin_lock_irqsave(&dev->vbl_lock, flags); - for (i = 0; i < 2; i++) { - struct drm_vbl_sig *vbl_sig, *tmp; - struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs; - unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 : - &dev->vbl_received); + vbl_sigs = &dev->vbl_sigs[crtc]; + vbl_seq = drm_vblank_count(dev, crtc); - list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) { - if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { - vbl_sig->info.si_code = vbl_seq; - send_sig_info(vbl_sig->info.si_signo, - &vbl_sig->info, vbl_sig->task); + list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) { + if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { + vbl_sig->info.si_code = vbl_seq; + send_sig_info(vbl_sig->info.si_signo, + &vbl_sig->info, vbl_sig->task); - list_del(&vbl_sig->head); + list_del(&vbl_sig->head); - drm_free(vbl_sig, sizeof(*vbl_sig), - DRM_MEM_DRIVER); - - dev->vbl_pending--; - } - } + drm_free(vbl_sig, sizeof(*vbl_sig), + DRM_MEM_DRIVER); + atomic_dec(&dev->vbl_signal_pending); + drm_vblank_put(dev, crtc); + } } spin_unlock_irqrestore(&dev->vbl_lock, flags); } -EXPORT_SYMBOL(drm_vbl_send_signals); +/** + * drm_handle_vblank - handle a vblank event + * @dev: DRM device + * @crtc: where this event occurred + * + * Drivers should call this routine in their vblank interrupt handlers to + * update the vblank counter and send any signals that may be pending. + */ +void drm_handle_vblank(struct drm_device *dev, int crtc) +{ + drm_update_vblank_count(dev, crtc); + DRM_WAKEUP(&dev->vbl_queue[crtc]); + drm_vbl_send_signals(dev, crtc); +} +EXPORT_SYMBOL(drm_handle_vblank); /** * Tasklet wrapper function. diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index bea2a7d5b2b..12dcdd1832f 100644 --- a/drivers/char/drm/drm_lock.c +++ b/drivers/char/drm/drm_lock.c @@ -53,6 +53,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) DECLARE_WAITQUEUE(entry, current); struct drm_lock *lock = data; int ret = 0; + unsigned long irqflags; ++file_priv->lock_count; @@ -71,9 +72,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; add_wait_queue(&dev->lock.lock_queue, &entry); - spin_lock(&dev->lock.spinlock); + spin_lock_irqsave(&dev->lock.spinlock, irqflags); dev->lock.user_waiters++; - spin_unlock(&dev->lock.spinlock); + spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); if (!dev->lock.hw_lock) { @@ -95,9 +96,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) break; } } - spin_lock(&dev->lock.spinlock); + spin_lock_irqsave(&dev->lock.spinlock, irqflags); dev->lock.user_waiters--; - spin_unlock(&dev->lock.spinlock); + spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); __set_current_state(TASK_RUNNING); remove_wait_queue(&dev->lock.lock_queue, &entry); @@ -198,8 +199,9 @@ int drm_lock_take(struct drm_lock_data *lock_data, { unsigned int old, new, prev; volatile unsigned int *lock = &lock_data->hw_lock->lock; + unsigned long irqflags; - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); do { old = *lock; if (old & _DRM_LOCK_HELD) @@ -211,7 +213,7 @@ int drm_lock_take(struct drm_lock_data *lock_data, } prev = cmpxchg(lock, old, new); } while (prev != old); - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); if (_DRM_LOCKING_CONTEXT(old) == context) { if (old & _DRM_LOCK_HELD) { @@ -272,15 +274,16 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context) { unsigned int old, new, prev; volatile unsigned int *lock = &lock_data->hw_lock->lock; + unsigned long irqflags; - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); if (lock_data->kernel_waiters != 0) { drm_lock_transfer(lock_data, 0); lock_data->idle_has_lock = 1; - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); return 1; } - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); do { old = *lock; @@ -344,19 +347,20 @@ static int drm_notifier(void *priv) void drm_idlelock_take(struct drm_lock_data *lock_data) { int ret = 0; + unsigned long irqflags; - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); lock_data->kernel_waiters++; if (!lock_data->idle_has_lock) { - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT); - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); if (ret == 1) lock_data->idle_has_lock = 1; } - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); } EXPORT_SYMBOL(drm_idlelock_take); @@ -364,8 +368,9 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) { unsigned int old, prev; volatile unsigned int *lock = &lock_data->hw_lock->lock; + unsigned long irqflags; - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); if (--lock_data->kernel_waiters == 0) { if (lock_data->idle_has_lock) { do { @@ -376,7 +381,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) lock_data->idle_has_lock = 0; } } - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); } EXPORT_SYMBOL(drm_idlelock_release); diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 715b361f0c2..a6a499f97e2 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -205,9 +205,9 @@ {0x1002, 0x71D6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x71DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \ {0x1002, 0x71DE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7244, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \ @@ -238,6 +238,7 @@ {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x791e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \ + {0x1002, 0x791f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \ {0, 0, 0} #define r128_PCI_IDS \ diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index d9b560fe9bb..93b1e0475c9 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c @@ -87,34 +87,35 @@ static struct drm_proc_list { * "/proc/dri/%minor%/", and each entry in proc_list as * "/proc/dri/%minor%/%name%". */ -int drm_proc_init(struct drm_device * dev, int minor, - struct proc_dir_entry *root, struct proc_dir_entry **dev_root) +int drm_proc_init(struct drm_minor *minor, int minor_id, + struct proc_dir_entry *root) { struct proc_dir_entry *ent; int i, j; char name[64]; - sprintf(name, "%d", minor); - *dev_root = proc_mkdir(name, root); - if (!*dev_root) { + sprintf(name, "%d", minor_id); + minor->dev_root = proc_mkdir(name, root); + if (!minor->dev_root) { DRM_ERROR("Cannot create /proc/dri/%s\n", name); return -1; } for (i = 0; i < DRM_PROC_ENTRIES; i++) { ent = create_proc_entry(drm_proc_list[i].name, - S_IFREG | S_IRUGO, *dev_root); + S_IFREG | S_IRUGO, minor->dev_root); if (!ent) { DRM_ERROR("Cannot create /proc/dri/%s/%s\n", name, drm_proc_list[i].name); for (j = 0; j < i; j++) remove_proc_entry(drm_proc_list[i].name, - *dev_root); + minor->dev_root); remove_proc_entry(name, root); + minor->dev_root = NULL; return -1; } ent->read_proc = drm_proc_list[i].f; - ent->data = dev; + ent->data = minor; } return 0; @@ -130,18 +131,17 @@ int drm_proc_init(struct drm_device * dev, int minor, * * Remove all proc entries created by proc_init(). */ -int drm_proc_cleanup(int minor, struct proc_dir_entry *root, - struct proc_dir_entry *dev_root) +int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) { int i; char name[64]; - if (!root || !dev_root) + if (!root || !minor->dev_root) return 0; for (i = 0; i < DRM_PROC_ENTRIES; i++) - remove_proc_entry(drm_proc_list[i].name, dev_root); - sprintf(name, "%d", minor); + remove_proc_entry(drm_proc_list[i].name, minor->dev_root); + sprintf(name, "%d", minor->index); remove_proc_entry(name, root); return 0; @@ -163,7 +163,8 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root, static int drm_name_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; if (offset > DRM_PROC_LIMIT) { @@ -205,7 +206,8 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request, static int drm__vm_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_map *map; struct drm_map_list *r_list; @@ -261,7 +263,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request, static int drm_vm_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -284,7 +287,8 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request, static int drm__queues_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; int i; struct drm_queue *q; @@ -334,7 +338,8 @@ static int drm__queues_info(char *buf, char **start, off_t offset, static int drm_queues_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -357,7 +362,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request, static int drm__bufs_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_device_dma *dma = dev->dma; int i; @@ -406,7 +412,8 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request, static int drm_bufs_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -429,7 +436,8 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request, static int drm__clients_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_file *priv; @@ -445,7 +453,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset, list_for_each_entry(priv, &dev->filelist, lhead) { DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n", priv->authenticated ? 'y' : 'n', - priv->minor, + priv->minor->index, priv->pid, priv->uid, priv->magic, priv->ioctl_count); } @@ -462,7 +470,8 @@ static int drm__clients_info(char *buf, char **start, off_t offset, static int drm_clients_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); @@ -476,7 +485,8 @@ static int drm_clients_info(char *buf, char **start, off_t offset, static int drm__vma_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int len = 0; struct drm_vma_entry *pt; struct vm_area_struct *vma; @@ -535,7 +545,8 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, static int drm_vma_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - struct drm_device *dev = (struct drm_device *) data; + struct drm_minor *minor = (struct drm_minor *) data; + struct drm_device *dev = minor->dev; int ret; mutex_lock(&dev->struct_mutex); diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c index 26d8f675ed5..b2b0f3d4171 100644 --- a/drivers/char/drm/drm_scatter.c +++ b/drivers/char/drm/drm_scatter.c @@ -36,6 +36,15 @@ #define DEBUG_SCATTER 0 +static inline void *drm_vmalloc_dma(unsigned long size) +{ +#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE) + return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL | _PAGE_NO_CACHE); +#else + return vmalloc_32(size); +#endif +} + void drm_sg_cleanup(struct drm_sg_mem * entry) { struct page *page; @@ -104,7 +113,7 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) } memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr)); - entry->virtual = vmalloc_32(pages << PAGE_SHIFT); + entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT); if (!entry->virtual) { drm_free(entry->busaddr, entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES); diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index d93a217f856..c2f584f3b46 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c @@ -36,23 +36,49 @@ #include "drmP.h" #include "drm_core.h" -unsigned int drm_cards_limit = 16; /* Enough for one machine */ unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); -MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards"); MODULE_PARM_DESC(debug, "Enable debug output"); -module_param_named(cards_limit, drm_cards_limit, int, 0444); module_param_named(debug, drm_debug, int, 0600); -struct drm_head **drm_heads; +struct idr drm_minors_idr; + struct class *drm_class; struct proc_dir_entry *drm_proc_root; +static int drm_minor_get_id(struct drm_device *dev, int type) +{ + int new_id; + int ret; + int base = 0, limit = 63; + +again: + if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) { + DRM_ERROR("Out of memory expanding drawable idr\n"); + return -ENOMEM; + } + mutex_lock(&dev->struct_mutex); + ret = idr_get_new_above(&drm_minors_idr, NULL, + base, &new_id); + mutex_unlock(&dev->struct_mutex); + if (ret == -EAGAIN) { + goto again; + } else if (ret) { + return ret; + } + + if (new_id >= limit) { + idr_remove(&drm_minors_idr, new_id); + return -EINVAL; + } + return new_id; +} + static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) @@ -145,48 +171,60 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, * create the proc init entry via proc_init(). This routines assigns * minor numbers to secondary heads of multi-headed cards */ -static int drm_get_head(struct drm_device * dev, struct drm_head * head) +static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) { - struct drm_head **heads = drm_heads; + struct drm_minor *new_minor; int ret; - int minor; + int minor_id; DRM_DEBUG("\n"); - for (minor = 0; minor < drm_cards_limit; minor++, heads++) { - if (!*heads) { - - *head = (struct drm_head) { - .dev = dev,.device = - MKDEV(DRM_MAJOR, minor),.minor = minor,}; - - if ((ret = - drm_proc_init(dev, minor, drm_proc_root, - &head->dev_root))) { - printk(KERN_ERR - "DRM: Failed to initialize /proc/dri.\n"); - goto err_g1; - } - - ret = drm_sysfs_device_add(dev, head); - if (ret) { - printk(KERN_ERR - "DRM: Error sysfs_device_add.\n"); - goto err_g2; - } - *heads = head; - - DRM_DEBUG("new minor assigned %d\n", minor); - return 0; + minor_id = drm_minor_get_id(dev, type); + if (minor_id < 0) + return minor_id; + + new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL); + if (!new_minor) { + ret = -ENOMEM; + goto err_idr; + } + + new_minor->type = type; + new_minor->device = MKDEV(DRM_MAJOR, minor_id); + new_minor->dev = dev; + new_minor->index = minor_id; + + idr_replace(&drm_minors_idr, new_minor, minor_id); + + if (type == DRM_MINOR_LEGACY) { + ret = drm_proc_init(new_minor, minor_id, drm_proc_root); + if (ret) { + DRM_ERROR("DRM: Failed to initialize /proc/dri.\n"); + goto err_mem; } + } else + new_minor->dev_root = NULL; + + ret = drm_sysfs_device_add(new_minor); + if (ret) { + printk(KERN_ERR + "DRM: Error sysfs_device_add.\n"); + goto err_g2; } - DRM_ERROR("out of minors\n"); - return -ENOMEM; - err_g2: - drm_proc_cleanup(minor, drm_proc_root, head->dev_root); - err_g1: - *head = (struct drm_head) { - .dev = NULL}; + *minor = new_minor; + + DRM_DEBUG("new minor assigned %d\n", minor_id); + return 0; + + +err_g2: + if (new_minor->type == DRM_MINOR_LEGACY) + drm_proc_cleanup(new_minor, drm_proc_root); +err_mem: + kfree(new_minor); +err_idr: + idr_remove(&drm_minors_idr, minor_id); + *minor = NULL; return ret; } @@ -222,12 +260,12 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); goto err_g2; } - if ((ret = drm_get_head(dev, &dev->primary))) + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) goto err_g2; DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, - driver->date, dev->primary.minor); + driver->date, dev->primary->index); return 0; @@ -276,18 +314,18 @@ int drm_put_dev(struct drm_device * dev) * last minor released. * */ -int drm_put_head(struct drm_head * head) +int drm_put_minor(struct drm_minor **minor_p) { - int minor = head->minor; - - DRM_DEBUG("release secondary minor %d\n", minor); - - drm_proc_cleanup(minor, drm_proc_root, head->dev_root); - drm_sysfs_device_remove(head->dev); + struct drm_minor *minor = *minor_p; + DRM_DEBUG("release secondary minor %d\n", minor->index); - *head = (struct drm_head) {.dev = NULL}; + if (minor->type == DRM_MINOR_LEGACY) + drm_proc_cleanup(minor, drm_proc_root); + drm_sysfs_device_remove(minor); - drm_heads[minor] = NULL; + idr_remove(&drm_minors_idr, minor->index); + kfree(minor); + *minor_p = NULL; return 0; } diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 05ed5043254..7a1d9a782dd 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c @@ -19,7 +19,7 @@ #include "drm_core.h" #include "drmP.h" -#define to_drm_device(d) container_of(d, struct drm_device, dev) +#define to_drm_minor(d) container_of(d, struct drm_minor, kdev) /** * drm_sysfs_suspend - DRM class suspend hook @@ -31,7 +31,8 @@ */ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) { - struct drm_device *drm_dev = to_drm_device(dev); + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; printk(KERN_ERR "%s\n", __FUNCTION__); @@ -50,7 +51,8 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) */ static int drm_sysfs_resume(struct device *dev) { - struct drm_device *drm_dev = to_drm_device(dev); + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; if (drm_dev->driver->resume) return drm_dev->driver->resume(drm_dev); @@ -120,10 +122,11 @@ void drm_sysfs_destroy(void) static ssize_t show_dri(struct device *device, struct device_attribute *attr, char *buf) { - struct drm_device *dev = to_drm_device(device); - if (dev->driver->dri_library_name) - return dev->driver->dri_library_name(dev, buf); - return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name); + struct drm_minor *drm_minor = to_drm_minor(device); + struct drm_device *drm_dev = drm_minor->dev; + if (drm_dev->driver->dri_library_name) + return drm_dev->driver->dri_library_name(drm_dev, buf); + return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name); } static struct device_attribute device_attrs[] = { @@ -152,25 +155,28 @@ static void drm_sysfs_device_release(struct device *dev) * as the parent for the Linux device, and make sure it has a file containing * the driver we're using (for userspace compatibility). */ -int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head) +int drm_sysfs_device_add(struct drm_minor *minor) { int err; int i, j; + char *minor_str; - dev->dev.parent = &dev->pdev->dev; - dev->dev.class = drm_class; - dev->dev.release = drm_sysfs_device_release; - dev->dev.devt = head->device; - snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor); + minor->kdev.parent = &minor->dev->pdev->dev; + minor->kdev.class = drm_class; + minor->kdev.release = drm_sysfs_device_release; + minor->kdev.devt = minor->device; + minor_str = "card%d"; - err = device_register(&dev->dev); + snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index); + + err = device_register(&minor->kdev); if (err) { DRM_ERROR("device add failed: %d\n", err); goto err_out; } for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { - err = device_create_file(&dev->dev, &device_attrs[i]); + err = device_create_file(&minor->kdev, &device_attrs[i]); if (err) goto err_out_files; } @@ -180,8 +186,8 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head) err_out_files: if (i > 0) for (j = 0; j < i; j++) - device_remove_file(&dev->dev, &device_attrs[i]); - device_unregister(&dev->dev); + device_remove_file(&minor->kdev, &device_attrs[i]); + device_unregister(&minor->kdev); err_out: return err; @@ -194,11 +200,11 @@ err_out: * This call unregisters and cleans up a class device that was created with a * call to drm_sysfs_device_add() */ -void drm_sysfs_device_remove(struct drm_device *dev) +void drm_sysfs_device_remove(struct drm_minor *minor) { int i; for (i = 0; i < ARRAY_SIZE(device_attrs); i++) - device_remove_file(&dev->dev, &device_attrs[i]); - device_unregister(&dev->dev); + device_remove_file(&minor->kdev, &device_attrs[i]); + device_unregister(&minor->kdev); } diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 3d65c4dcd0c..c234c6f24a8 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -54,13 +54,24 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma) pgprot_val(tmp) |= _PAGE_NO_CACHE; if (map_type == _DRM_REGISTERS) pgprot_val(tmp) |= _PAGE_GUARDED; -#endif -#if defined(__ia64__) +#elif defined(__ia64__) if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) tmp = pgprot_writecombine(tmp); else tmp = pgprot_noncached(tmp); +#elif defined(__sparc__) + tmp = pgprot_noncached(tmp); +#endif + return tmp; +} + +static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma) +{ + pgprot_t tmp = vm_get_page_prot(vma->vm_flags); + +#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE) + tmp |= _PAGE_NO_CACHE; #endif return tmp; } @@ -79,7 +90,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma) static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_map *map = NULL; struct drm_map_list *r_list; struct drm_hash_item *hash; @@ -196,7 +207,7 @@ static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) static void drm_vm_shm_close(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_vma_entry *pt, *temp; struct drm_map *map; struct drm_map_list *r_list; @@ -275,7 +286,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_device_dma *dma = dev->dma; unsigned long offset; unsigned long page_nr; @@ -310,7 +321,7 @@ static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_map *map = (struct drm_map *) vma->vm_private_data; struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_sg_mem *entry = dev->sg; unsigned long offset; unsigned long map_offset; @@ -391,7 +402,7 @@ static struct vm_operations_struct drm_vm_sg_ops = { static void drm_vm_open_locked(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_vma_entry *vma_entry; DRM_DEBUG("0x%08lx,0x%08lx\n", @@ -409,7 +420,7 @@ static void drm_vm_open_locked(struct vm_area_struct *vma) static void drm_vm_open(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; mutex_lock(&dev->struct_mutex); drm_vm_open_locked(vma); @@ -427,7 +438,7 @@ static void drm_vm_open(struct vm_area_struct *vma) static void drm_vm_close(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_vma_entry *pt, *temp; DRM_DEBUG("0x%08lx,0x%08lx\n", @@ -462,7 +473,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) struct drm_device_dma *dma; unsigned long length = vma->vm_end - vma->vm_start; - dev = priv->head->dev; + dev = priv->minor->dev; dma = dev->dma; DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", vma->vm_start, vma->vm_end, vma->vm_pgoff); @@ -532,7 +543,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs); static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; struct drm_map *map = NULL; unsigned long offset = 0; struct drm_hash_item *hash; @@ -603,9 +614,6 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) offset = dev->driver->get_reg_ofs(dev); vma->vm_flags |= VM_IO; /* not in core dump */ vma->vm_page_prot = drm_io_prot(map->type, vma); -#ifdef __sparc__ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -#endif if (io_remap_pfn_range(vma, vma->vm_start, (map->offset + offset) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, @@ -624,6 +632,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) page_to_pfn(virt_to_page(map->handle)), vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; + vma->vm_page_prot = drm_dma_prot(map->type, vma); /* fall through to _DRM_SHM */ case _DRM_SHM: vma->vm_ops = &drm_vm_shm_ops; @@ -636,6 +645,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) vma->vm_ops = &drm_vm_sg_ops; vma->vm_private_data = (void *)map; vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = drm_dma_prot(map->type, vma); break; default: return -EINVAL; /* This should never happen. */ @@ -651,7 +661,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) int drm_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = priv->minor->dev; int ret; mutex_lock(&dev->struct_mutex); diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index 8d7ea81c4b6..e5de8ea4154 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -94,7 +94,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) drm_i810_buf_priv_t *buf_priv; lock_kernel(); - dev = priv->head->dev; + dev = priv->minor->dev; dev_priv = dev->dev_private; buf = dev_priv->mmap_buffer; buf_priv = buf->dev_private; @@ -122,7 +122,7 @@ static const struct file_operations i810_buffer_fops = { static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_private_t *dev_priv = dev->dev_private; const struct file_operations *old_fops; diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 9df08105f4f..60c9376be48 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c @@ -96,7 +96,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) drm_i830_buf_priv_t *buf_priv; lock_kernel(); - dev = priv->head->dev; + dev = priv->minor->dev; dev_priv = dev->dev_private; buf = dev_priv->mmap_buffer; buf_priv = buf->dev_private; @@ -124,7 +124,7 @@ static const struct file_operations i830_buffer_fops = { static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) { - struct drm_device *dev = file_priv->head->dev; + struct drm_device *dev = file_priv->minor->dev; drm_i830_buf_priv_t *buf_priv = buf->dev_private; drm_i830_private_t *dev_priv = dev->dev_private; const struct file_operations *old_fops; diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index e9d6663bec7..ef7bf143a80 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -415,10 +415,13 @@ static void i915_emit_breadcrumb(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; RING_LOCALS; - dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter; + if (++dev_priv->counter > BREADCRUMB_MASK) { + dev_priv->counter = 1; + DRM_DEBUG("Breadcrumb counter wrapped around\n"); + } - if (dev_priv->counter > 0x7FFFFFFFUL) - dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1; + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_enqueue = dev_priv->counter; BEGIN_LP_RING(4); OUT_RING(CMD_STORE_DWORD_IDX); @@ -428,6 +431,26 @@ static void i915_emit_breadcrumb(struct drm_device *dev) ADVANCE_LP_RING(); } +int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + uint32_t flush_cmd = CMD_MI_FLUSH; + RING_LOCALS; + + flush_cmd |= flush; + + i915_kernel_lost_context(dev); + + BEGIN_LP_RING(4); + OUT_RING(flush_cmd); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0); + ADVANCE_LP_RING(); + + return 0; +} + static int i915_dispatch_cmdbuffer(struct drm_device * dev, drm_i915_cmdbuffer_t * cmd) { @@ -511,52 +534,74 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, return 0; } -static int i915_dispatch_flip(struct drm_device * dev) +static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync) { drm_i915_private_t *dev_priv = dev->dev_private; + u32 num_pages, current_page, next_page, dspbase; + int shift = 2 * plane, x, y; RING_LOCALS; - DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", - __FUNCTION__, - dev_priv->current_page, - dev_priv->sarea_priv->pf_current_page); + /* Calculate display base offset */ + num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2; + current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3; + next_page = (current_page + 1) % num_pages; - i915_kernel_lost_context(dev); - - BEGIN_LP_RING(2); - OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); - OUT_RING(0); - ADVANCE_LP_RING(); + switch (next_page) { + default: + case 0: + dspbase = dev_priv->sarea_priv->front_offset; + break; + case 1: + dspbase = dev_priv->sarea_priv->back_offset; + break; + case 2: + dspbase = dev_priv->sarea_priv->third_offset; + break; + } - BEGIN_LP_RING(6); - OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP); - OUT_RING(0); - if (dev_priv->current_page == 0) { - OUT_RING(dev_priv->back_offset); - dev_priv->current_page = 1; + if (plane == 0) { + x = dev_priv->sarea_priv->planeA_x; + y = dev_priv->sarea_priv->planeA_y; } else { - OUT_RING(dev_priv->front_offset); - dev_priv->current_page = 0; + x = dev_priv->sarea_priv->planeB_x; + y = dev_priv->sarea_priv->planeB_y; } - OUT_RING(0); - ADVANCE_LP_RING(); - BEGIN_LP_RING(2); - OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); - OUT_RING(0); - ADVANCE_LP_RING(); + dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp; - dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; + DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page, + dspbase); BEGIN_LP_RING(4); - OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(20); - OUT_RING(dev_priv->counter); - OUT_RING(0); + OUT_RING(sync ? 0 : + (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP : + MI_WAIT_FOR_PLANE_A_FLIP))); + OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) | + (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A)); + OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp); + OUT_RING(dspbase); ADVANCE_LP_RING(); - dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; - return 0; + dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift); + dev_priv->sarea_priv->pf_current_page |= next_page << shift; +} + +void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + int i; + + DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n", + planes, dev_priv->sarea_priv->pf_current_page); + + i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH); + + for (i = 0; i < 2; i++) + if (planes & (1 << i)) + i915_do_dispatch_flip(dev, i, sync); + + i915_emit_breadcrumb(dev); + } static int i915_quiescent(struct drm_device * dev) @@ -579,7 +624,6 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 *hw_status = dev_priv->hw_status_page; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; drm_i915_batchbuffer_t *batch = data; @@ -602,7 +646,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, ret = i915_dispatch_batchbuffer(dev, batch); - sarea_priv->last_dispatch = (int)hw_status[5]; + sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); return ret; } @@ -610,7 +654,6 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 *hw_status = dev_priv->hw_status_page; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; drm_i915_cmdbuffer_t *cmdbuf = data; @@ -635,18 +678,51 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, return ret; } - sarea_priv->last_dispatch = (int)hw_status[5]; + sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + return 0; +} + +static int i915_do_cleanup_pageflip(struct drm_device * dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2; + + DRM_DEBUG("\n"); + + for (i = 0, planes = 0; i < 2; i++) + if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) { + dev_priv->sarea_priv->pf_current_page = + (dev_priv->sarea_priv->pf_current_page & + ~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i)); + + planes |= 1 << i; + } + + if (planes) + i915_dispatch_flip(dev, planes, 0); + return 0; } static int i915_flip_bufs(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEBUG("%s\n", __FUNCTION__); + drm_i915_flip_t *param = data; + + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); - return i915_dispatch_flip(dev); + /* This is really planes */ + if (param->pipes & ~0x3) { + DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n", + param->pipes); + return -EINVAL; + } + + i915_dispatch_flip(dev, param->pipes, 0); + + return 0; } static int i915_getparam(struct drm_device *dev, void *data, @@ -804,6 +880,11 @@ void i915_driver_lastclose(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; + if (!dev_priv) + return; + + if (drm_getsarea(dev) && dev_priv->sarea_priv) + i915_do_cleanup_pageflip(dev); if (dev_priv->agp_heap) i915_mem_takedown(&(dev_priv->agp_heap)); diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 05c66cf03a9..0431c00e228 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h @@ -105,14 +105,29 @@ typedef struct _drm_i915_sarea { unsigned int rotated_tiled; unsigned int rotated2_tiled; - int pipeA_x; - int pipeA_y; - int pipeA_w; - int pipeA_h; - int pipeB_x; - int pipeB_y; - int pipeB_w; - int pipeB_h; + int planeA_x; + int planeA_y; + int planeA_w; + int planeA_h; + int planeB_x; + int planeB_y; + int planeB_w; + int planeB_h; + + /* Triple buffering */ + drm_handle_t third_handle; + int third_offset; + int third_size; + unsigned int third_tiled; + + /* buffer object handles for the static buffers. May change + * over the lifetime of the client, though it doesn't in our current + * implementation. + */ + unsigned int front_bo_handle; + unsigned int back_bo_handle; + unsigned int third_bo_handle; + unsigned int depth_bo_handle; } drm_i915_sarea_t; /* Flags for perf_boxes @@ -146,7 +161,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) -#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP) +#define DRM_IOCTL_I915_FLIP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FLIP, drm_i915_flip_t) #define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t) #define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t) #define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t) @@ -161,6 +176,18 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) +/* Asynchronous page flipping: + */ +typedef struct drm_i915_flip { + /* + * This is really talking about planes, and we could rename it + * except for the fact that some of the duplicated i915_drm.h files + * out there check for HAVE_I915_FLIP and so might pick up this + * version. + */ + int pipes; +} drm_i915_flip_t; + /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. */ diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c index b2b451dc446..bb8f1b2fb38 100644 --- a/drivers/char/drm/i915_drv.c +++ b/drivers/char/drm/i915_drv.c @@ -533,8 +533,7 @@ static struct drm_driver driver = { */ .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/ - DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL | - DRIVER_IRQ_VBL2, + DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .load = i915_driver_load, .unload = i915_driver_unload, .lastclose = i915_driver_lastclose, @@ -542,8 +541,9 @@ static struct drm_driver driver = { .suspend = i915_suspend, .resume = i915_resume, .device_is_agp = i915_driver_device_is_agp, - .vblank_wait = i915_driver_vblank_wait, - .vblank_wait2 = i915_driver_vblank_wait2, + .get_vblank_counter = i915_get_vblank_counter, + .enable_vblank = i915_enable_vblank, + .disable_vblank = i915_disable_vblank, .irq_preinstall = i915_driver_irq_preinstall, .irq_postinstall = i915_driver_irq_postinstall, .irq_uninstall = i915_driver_irq_uninstall, diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index c10d128e34d..c614d78b3df 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h @@ -76,8 +76,9 @@ struct mem_block { typedef struct _drm_i915_vbl_swap { struct list_head head; drm_drawable_t drw_id; - unsigned int pipe; + unsigned int plane; unsigned int sequence; + int flip; } drm_i915_vbl_swap_t; typedef struct drm_i915_private { @@ -90,7 +91,7 @@ typedef struct drm_i915_private { drm_dma_handle_t *status_page_dmah; void *hw_status_page; dma_addr_t dma_status_page; - unsigned long counter; + uint32_t counter; unsigned int status_gfx_addr; drm_local_map_t hws_map; @@ -103,13 +104,18 @@ typedef struct drm_i915_private { wait_queue_head_t irq_queue; atomic_t irq_received; - atomic_t irq_emitted; + atomic_t irq_emited; int tex_lru_log_granularity; int allow_batchbuffer; struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; int vblank_pipe; + spinlock_t user_irq_lock; + int user_irq_refcount; + int fence_irq_on; + uint32_t irq_enable_reg; + int irq_enabled; spinlock_t swaps_lock; drm_i915_vbl_swap_t vbl_swaps; @@ -216,7 +222,7 @@ extern void i915_driver_preclose(struct drm_device *dev, extern int i915_driver_device_is_agp(struct drm_device * dev); extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); - +extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync); /* i915_irq.c */ extern int i915_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -227,7 +233,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence); extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern void i915_driver_irq_preinstall(struct drm_device * dev); -extern void i915_driver_irq_postinstall(struct drm_device * dev); +extern int i915_driver_irq_postinstall(struct drm_device * dev); extern void i915_driver_irq_uninstall(struct drm_device * dev); extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -235,6 +241,9 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int i915_enable_vblank(struct drm_device *dev, int crtc); +extern void i915_disable_vblank(struct drm_device *dev, int crtc); +extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); /* i915_mem.c */ extern int i915_mem_alloc(struct drm_device *dev, void *data, @@ -379,21 +388,91 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); /* Interrupt bits: */ -#define USER_INT_FLAG (1<<1) -#define VSYNC_PIPEB_FLAG (1<<5) -#define VSYNC_PIPEA_FLAG (1<<7) -#define HWB_OOM_FLAG (1<<13) /* binner out of memory */ +#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) +#define I915_DISPLAY_PORT_INTERRUPT (1<<17) +#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) +#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) +#define I915_HWB_OOM_INTERRUPT (1<<13) /* binner out of memory */ +#define I915_SYNC_STATUS_INTERRUPT (1<<12) +#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11) +#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10) +#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9) +#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8) +#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7) +#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6) +#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5) +#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4) +#define I915_DEBUG_INTERRUPT (1<<2) +#define I915_USER_INTERRUPT (1<<1) + #define I915REG_HWSTAM 0x02098 #define I915REG_INT_IDENTITY_R 0x020a4 #define I915REG_INT_MASK_R 0x020a8 #define I915REG_INT_ENABLE_R 0x020a0 +#define I915REG_INSTPM 0x020c0 + +#define PIPEADSL 0x70000 +#define PIPEBDSL 0x71000 #define I915REG_PIPEASTAT 0x70024 #define I915REG_PIPEBSTAT 0x71024 +/* + * The two pipe frame counter registers are not synchronized, so + * reading a stable value is somewhat tricky. The following code + * should work: + * + * do { + * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT; + * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >> + * PIPE_FRAME_LOW_SHIFT); + * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT); + * } while (high1 != high2); + * frame = (high1 << 8) | low1; + */ +#define PIPEAFRAMEHIGH 0x70040 +#define PIPEBFRAMEHIGH 0x71040 +#define PIPE_FRAME_HIGH_MASK 0x0000ffff +#define PIPE_FRAME_HIGH_SHIFT 0 +#define PIPEAFRAMEPIXEL 0x70044 +#define PIPEBFRAMEPIXEL 0x71044 -#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) -#define I915_VBLANK_CLEAR (1UL<<1) +#define PIPE_FRAME_LOW_MASK 0xff000000 +#define PIPE_FRAME_LOW_SHIFT 24 +/* + * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register + * and is 24 bits wide. + */ +#define PIPE_PIXEL_MASK 0x00ffffff +#define PIPE_PIXEL_SHIFT 0 + +#define I915_FIFO_UNDERRUN_STATUS (1UL<<31) +#define I915_CRC_ERROR_ENABLE (1UL<<29) +#define I915_CRC_DONE_ENABLE (1UL<<28) +#define I915_GMBUS_EVENT_ENABLE (1UL<<27) +#define I915_VSYNC_INTERRUPT_ENABLE (1UL<<25) +#define I915_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24) +#define I915_DPST_EVENT_ENABLE (1UL<<23) +#define I915_LEGACY_BLC_EVENT_ENABLE (1UL<<22) +#define I915_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21) +#define I915_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20) +#define I915_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */ +#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) +#define I915_OVERLAY_UPDATED_ENABLE (1UL<<16) +#define I915_CRC_ERROR_INTERRUPT_STATUS (1UL<<13) +#define I915_CRC_DONE_INTERRUPT_STATUS (1UL<<12) +#define I915_GMBUS_INTERRUPT_STATUS (1UL<<11) +#define I915_VSYNC_INTERRUPT_STATUS (1UL<<9) +#define I915_DISPLAY_LINE_COMPARE_STATUS (1UL<<8) +#define I915_DPST_EVENT_STATUS (1UL<<7) +#define I915_LEGACY_BLC_EVENT_STATUS (1UL<<6) +#define I915_ODD_FIELD_INTERRUPT_STATUS (1UL<<5) +#define I915_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4) +#define I915_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ +#define I915_VBLANK_INTERRUPT_STATUS (1UL<<1) +#define I915_OVERLAY_UPDATED_STATUS (1UL<<0) #define SRX_INDEX 0x3c4 #define SRX_DATA 0x3c5 @@ -566,6 +645,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) #define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) +#define XY_SRC_COPY_BLT_SRC_TILED (1<<15) +#define XY_SRC_COPY_BLT_DST_TILED (1<<11) #define MI_BATCH_BUFFER ((0x30<<23)|1) #define MI_BATCH_BUFFER_START (0x31<<23) @@ -1092,8 +1173,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a) #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) #define IS_I945G(dev) ((dev)->pci_device == 0x2772) -#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2) - +#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\ + (dev)->pci_device == 0x27AE) #define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \ (dev)->pci_device == 0x2982 || \ (dev)->pci_device == 0x2992 || \ diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index 92653b38e64..023ce66ef3a 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c @@ -38,6 +38,109 @@ #define MAX_NOPID ((u32)~0) /** + * i915_get_pipe - return the the pipe associated with a given plane + * @dev: DRM device + * @plane: plane to look for + * + * The Intel Mesa & 2D drivers call the vblank routines with a plane number + * rather than a pipe number, since they may not always be equal. This routine + * maps the given @plane back to a pipe number. + */ +static int +i915_get_pipe(struct drm_device *dev, int plane) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u32 dspcntr; + + dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR); + + return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0; +} + +/** + * i915_get_plane - return the the plane associated with a given pipe + * @dev: DRM device + * @pipe: pipe to look for + * + * The Intel Mesa & 2D drivers call the vblank routines with a plane number + * rather than a plane number, since they may not always be equal. This routine + * maps the given @pipe back to a plane number. + */ +static int +i915_get_plane(struct drm_device *dev, int pipe) +{ + if (i915_get_pipe(dev, 0) == pipe) + return 0; + return 1; +} + +/** + * i915_pipe_enabled - check if a pipe is enabled + * @dev: DRM device + * @pipe: pipe to check + * + * Reading certain registers when the pipe is disabled can hang the chip. + * Use this routine to make sure the PLL is running and the pipe is active + * before reading such registers if unsure. + */ +static int +i915_pipe_enabled(struct drm_device *dev, int pipe) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF; + + if (I915_READ(pipeconf) & PIPEACONF_ENABLE) + return 1; + + return 0; +} + +/** + * Emit a synchronous flip. + * + * This function must be called with the drawable spinlock held. + */ +static void +i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw, + int plane) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; + u16 x1, y1, x2, y2; + int pf_planes = 1 << plane; + + /* If the window is visible on the other plane, we have to flip on that + * plane as well. + */ + if (plane == 1) { + x1 = sarea_priv->planeA_x; + y1 = sarea_priv->planeA_y; + x2 = x1 + sarea_priv->planeA_w; + y2 = y1 + sarea_priv->planeA_h; + } else { + x1 = sarea_priv->planeB_x; + y1 = sarea_priv->planeB_y; + x2 = x1 + sarea_priv->planeB_w; + y2 = y1 + sarea_priv->planeB_h; + } + + if (x2 > 0 && y2 > 0) { + int i, num_rects = drw->num_rects; + struct drm_clip_rect *rect = drw->rects; + + for (i = 0; i < num_rects; i++) + if (!(rect[i].x1 >= x2 || rect[i].y1 >= y2 || + rect[i].x2 <= x1 || rect[i].y2 <= y1)) { + pf_planes = 0x3; + + break; + } + } + + i915_dispatch_flip(dev, pf_planes, 1); +} + +/** * Emit blits for scheduled buffer swaps. * * This function will be called with the HW lock held. @@ -45,40 +148,59 @@ static void i915_vblank_tasklet(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; struct list_head *list, *tmp, hits, *hit; - int nhits, nrects, slice[2], upper[2], lower[2], i; - unsigned counter[2] = { atomic_read(&dev->vbl_received), - atomic_read(&dev->vbl_received2) }; + int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages; + unsigned counter[2]; struct drm_drawable_info *drw; drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; - u32 cpp = dev_priv->cpp; + u32 cpp = dev_priv->cpp, offsets[3]; u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB) : XY_SRC_COPY_BLT_CMD; - u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) | - (cpp << 23) | (1 << 24); + u32 src_pitch = sarea_priv->pitch * cpp; + u32 dst_pitch = sarea_priv->pitch * cpp; + /* COPY rop (0xcc), map cpp to magic color depth constants */ + u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24); RING_LOCALS; + if (sarea_priv->front_tiled) { + cmd |= XY_SRC_COPY_BLT_DST_TILED; + dst_pitch >>= 2; + } + if (sarea_priv->back_tiled) { + cmd |= XY_SRC_COPY_BLT_SRC_TILED; + src_pitch >>= 2; + } + + counter[0] = drm_vblank_count(dev, 0); + counter[1] = drm_vblank_count(dev, 1); + DRM_DEBUG("\n"); INIT_LIST_HEAD(&hits); nhits = nrects = 0; - spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); + /* No irqsave/restore necessary. This tasklet may be run in an + * interrupt context or normal context, but we don't have to worry + * about getting interrupted by something acquiring the lock, because + * we are the interrupt context thing that acquires the lock. + */ + spin_lock(&dev_priv->swaps_lock); /* Find buffer swaps scheduled for this vertical blank */ list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { drm_i915_vbl_swap_t *vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); + int pipe = i915_get_pipe(dev, vbl_swap->plane); - if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23)) + if ((counter[pipe] - vbl_swap->sequence) > (1<<23)) continue; list_del(list); dev_priv->swaps_pending--; + drm_vblank_put(dev, pipe); spin_unlock(&dev_priv->swaps_lock); spin_lock(&dev->drw_lock); @@ -116,33 +238,23 @@ static void i915_vblank_tasklet(struct drm_device *dev) spin_lock(&dev_priv->swaps_lock); } - if (nhits == 0) { - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); - return; - } - spin_unlock(&dev_priv->swaps_lock); - i915_kernel_lost_context(dev); - - BEGIN_LP_RING(6); - - OUT_RING(GFX_OP_DRAWRECT_INFO); - OUT_RING(0); - OUT_RING(0); - OUT_RING(sarea_priv->width | sarea_priv->height << 16); - OUT_RING(sarea_priv->width | sarea_priv->height << 16); - OUT_RING(0); - - ADVANCE_LP_RING(); + if (nhits == 0) + return; - sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; + i915_kernel_lost_context(dev); upper[0] = upper[1] = 0; - slice[0] = max(sarea_priv->pipeA_h / nhits, 1); - slice[1] = max(sarea_priv->pipeB_h / nhits, 1); - lower[0] = sarea_priv->pipeA_y + slice[0]; - lower[1] = sarea_priv->pipeB_y + slice[0]; + slice[0] = max(sarea_priv->planeA_h / nhits, 1); + slice[1] = max(sarea_priv->planeB_h / nhits, 1); + lower[0] = sarea_priv->planeA_y + slice[0]; + lower[1] = sarea_priv->planeB_y + slice[0]; + + offsets[0] = sarea_priv->front_offset; + offsets[1] = sarea_priv->back_offset; + offsets[2] = sarea_priv->third_offset; + num_pages = sarea_priv->third_handle ? 3 : 2; spin_lock(&dev->drw_lock); @@ -154,6 +266,8 @@ static void i915_vblank_tasklet(struct drm_device *dev) for (i = 0; i++ < nhits; upper[0] = lower[0], lower[0] += slice[0], upper[1] = lower[1], lower[1] += slice[1]) { + int init_drawrect = 1; + if (i == nhits) lower[0] = lower[1] = sarea_priv->height; @@ -161,7 +275,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) drm_i915_vbl_swap_t *swap_hit = list_entry(hit, drm_i915_vbl_swap_t, head); struct drm_clip_rect *rect; - int num_rects, pipe; + int num_rects, plane, front, back; unsigned short top, bottom; drw = drm_get_drawable_info(dev, swap_hit->drw_id); @@ -169,10 +283,50 @@ static void i915_vblank_tasklet(struct drm_device *dev) if (!drw) continue; + plane = swap_hit->plane; + + if (swap_hit->flip) { + i915_dispatch_vsync_flip(dev, drw, plane); + continue; + } + + if (init_drawrect) { + int width = sarea_priv->width; + int height = sarea_priv->height; + if (IS_I965G(dev)) { + BEGIN_LP_RING(4); + + OUT_RING(GFX_OP_DRAWRECT_INFO_I965); + OUT_RING(0); + OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16)); + OUT_RING(0); + + ADVANCE_LP_RING(); + } else { + BEGIN_LP_RING(6); + + OUT_RING(GFX_OP_DRAWRECT_INFO); + OUT_RING(0); + OUT_RING(0); + OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16)); + OUT_RING(0); + OUT_RING(0); + + ADVANCE_LP_RING(); + } + + sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; + + init_drawrect = 0; + } + rect = drw->rects; - pipe = swap_hit->pipe; - top = upper[pipe]; - bottom = lower[pipe]; + top = upper[plane]; + bottom = lower[plane]; + + front = (dev_priv->sarea_priv->pf_current_page >> + (2 * plane)) & 0x3; + back = (front + 1) % num_pages; for (num_rects = drw->num_rects; num_rects--; rect++) { int y1 = max(rect->y1, top); @@ -184,20 +338,20 @@ static void i915_vblank_tasklet(struct drm_device *dev) BEGIN_LP_RING(8); OUT_RING(cmd); - OUT_RING(pitchropcpp); + OUT_RING(ropcpp | dst_pitch); OUT_RING((y1 << 16) | rect->x1); OUT_RING((y2 << 16) | rect->x2); - OUT_RING(sarea_priv->front_offset); + OUT_RING(offsets[front]); OUT_RING((y1 << 16) | rect->x1); - OUT_RING(pitchropcpp & 0xffff); - OUT_RING(sarea_priv->back_offset); + OUT_RING(src_pitch); + OUT_RING(offsets[back]); ADVANCE_LP_RING(); } } } - spin_unlock_irqrestore(&dev->drw_lock, irqflags); + spin_unlock(&dev->drw_lock); list_for_each_safe(hit, tmp, &hits) { drm_i915_vbl_swap_t *swap_hit = @@ -209,67 +363,112 @@ static void i915_vblank_tasklet(struct drm_device *dev) } } +u32 i915_get_vblank_counter(struct drm_device *dev, int plane) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long high_frame; + unsigned long low_frame; + u32 high1, high2, low, count; + int pipe; + + pipe = i915_get_pipe(dev, plane); + high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; + low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; + + if (!i915_pipe_enabled(dev, pipe)) { + printk(KERN_ERR "trying to get vblank count for disabled " + "pipe %d\n", pipe); + return 0; + } + + /* + * High & low register fields aren't synchronized, so make sure + * we get a low value that's stable across two reads of the high + * register. + */ + do { + high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> + PIPE_FRAME_HIGH_SHIFT); + low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> + PIPE_FRAME_LOW_SHIFT); + high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> + PIPE_FRAME_HIGH_SHIFT); + } while (high1 != high2); + + count = (high1 << 8) | low; + + /* count may be reset by other driver(e.g. 2D driver), + we have no way to know if it is wrapped or resetted + when count is zero. do a rough guess. + */ + if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2) + dev->last_vblank[pipe] = 0; + + return count; +} + irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u16 temp; + u32 iir; u32 pipea_stats, pipeb_stats; - - pipea_stats = I915_READ(I915REG_PIPEASTAT); - pipeb_stats = I915_READ(I915REG_PIPEBSTAT); - - temp = I915_READ16(I915REG_INT_IDENTITY_R); - - temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG); - - DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); - - if (temp == 0) + int vblank = 0; + + iir = I915_READ(I915REG_INT_IDENTITY_R); + if (iir == 0) { + DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n", + iir, + I915_READ(I915REG_INT_MASK_R), + I915_READ(I915REG_INT_ENABLE_R), + I915_READ(I915REG_PIPEASTAT), + I915_READ(I915REG_PIPEBSTAT)); return IRQ_NONE; + } - I915_WRITE16(I915REG_INT_IDENTITY_R, temp); - (void) I915_READ16(I915REG_INT_IDENTITY_R); - DRM_READMEMORYBARRIER(); - - dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + /* + * Clear the PIPE(A|B)STAT regs before the IIR otherwise + * we may get extra interrupts. + */ + if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { + pipea_stats = I915_READ(I915REG_PIPEASTAT); + if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS| + I915_VBLANK_INTERRUPT_STATUS)) + { + vblank++; + drm_handle_vblank(dev, i915_get_plane(dev, 0)); + } + I915_WRITE(I915REG_PIPEASTAT, pipea_stats); + } + if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { + pipeb_stats = I915_READ(I915REG_PIPEBSTAT); + if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS| + I915_VBLANK_INTERRUPT_STATUS)) + { + vblank++; + drm_handle_vblank(dev, i915_get_plane(dev, 1)); + } + I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats); + } - if (temp & USER_INT_FLAG) - DRM_WAKEUP(&dev_priv->irq_queue); + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { - int vblank_pipe = dev_priv->vblank_pipe; - - if ((vblank_pipe & - (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) - == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) { - if (temp & VSYNC_PIPEA_FLAG) - atomic_inc(&dev->vbl_received); - if (temp & VSYNC_PIPEB_FLAG) - atomic_inc(&dev->vbl_received2); - } else if (((temp & VSYNC_PIPEA_FLAG) && - (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) || - ((temp & VSYNC_PIPEB_FLAG) && - (vblank_pipe & DRM_I915_VBLANK_PIPE_B))) - atomic_inc(&dev->vbl_received); - - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + I915_WRITE(I915REG_INT_IDENTITY_R, iir); + (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */ + if (iir & I915_USER_INTERRUPT) { + DRM_WAKEUP(&dev_priv->irq_queue); + } + if (vblank) { if (dev_priv->swaps_pending > 0) drm_locked_tasklet(dev, i915_vblank_tasklet); - I915_WRITE(I915REG_PIPEASTAT, - pipea_stats|I915_VBLANK_INTERRUPT_ENABLE| - I915_VBLANK_CLEAR); - I915_WRITE(I915REG_PIPEBSTAT, - pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE| - I915_VBLANK_CLEAR); } return IRQ_HANDLED; } -static int i915_emit_irq(struct drm_device * dev) +static int i915_emit_irq(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; RING_LOCALS; @@ -316,42 +515,12 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); } - dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - return ret; -} - -static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence, - atomic_t *counter) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - unsigned int cur_vblank; - int ret = 0; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(counter)) - - *sequence) <= (1<<23))); - - *sequence = cur_vblank; - + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); return ret; } - -int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence) -{ - return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received); -} - -int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) -{ - return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2); -} - /* Needs the lock as it touches the ring. */ int i915_irq_emit(struct drm_device *dev, void *data, @@ -394,18 +563,96 @@ int i915_irq_wait(struct drm_device *dev, void *data, return i915_wait_irq(dev, irqwait->irq_seq); } +int i915_enable_vblank(struct drm_device *dev, int plane) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + int pipe = i915_get_pipe(dev, plane); + u32 pipestat_reg = 0; + u32 pipestat; + + switch (pipe) { + case 0: + pipestat_reg = I915REG_PIPEASTAT; + dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; + break; + case 1: + pipestat_reg = I915REG_PIPEBSTAT; + dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; + break; + default: + DRM_ERROR("tried to enable vblank on non-existent pipe %d\n", + pipe); + break; + } + + if (pipestat_reg) + { + pipestat = I915_READ (pipestat_reg); + /* + * Older chips didn't have the start vblank interrupt, + * but + */ + if (IS_I965G (dev)) + pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE; + else + pipestat |= I915_VBLANK_INTERRUPT_ENABLE; + /* + * Clear any pending status + */ + pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS | + I915_VBLANK_INTERRUPT_STATUS); + I915_WRITE(pipestat_reg, pipestat); + } + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + + return 0; +} + +void i915_disable_vblank(struct drm_device *dev, int plane) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + int pipe = i915_get_pipe(dev, plane); + u32 pipestat_reg = 0; + u32 pipestat; + + switch (pipe) { + case 0: + pipestat_reg = I915REG_PIPEASTAT; + dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; + break; + case 1: + pipestat_reg = I915REG_PIPEBSTAT; + dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; + break; + default: + DRM_ERROR("tried to disable vblank on non-existent pipe %d\n", + pipe); + break; + } + + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + if (pipestat_reg) + { + pipestat = I915_READ (pipestat_reg); + pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE | + I915_VBLANK_INTERRUPT_ENABLE); + /* + * Clear any pending status + */ + pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS | + I915_VBLANK_INTERRUPT_STATUS); + I915_WRITE(pipestat_reg, pipestat); + } +} + static void i915_enable_interrupt (struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u16 flag; - flag = 0; - if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) - flag |= VSYNC_PIPEA_FLAG; - if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) - flag |= VSYNC_PIPEB_FLAG; + dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; - I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + dev_priv->irq_enabled = 1; } /* Set the vblank monitor pipe @@ -428,8 +675,6 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data, dev_priv->vblank_pipe = pipe->pipe; - i915_enable_interrupt (dev); - return 0; } @@ -447,9 +692,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data, flag = I915_READ(I915REG_INT_ENABLE_R); pipe->pipe = 0; - if (flag & VSYNC_PIPEA_FLAG) + if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) pipe->pipe |= DRM_I915_VBLANK_PIPE_A; - if (flag & VSYNC_PIPEB_FLAG) + if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) pipe->pipe |= DRM_I915_VBLANK_PIPE_B; return 0; @@ -464,27 +709,30 @@ int i915_vblank_swap(struct drm_device *dev, void *data, drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_vblank_swap_t *swap = data; drm_i915_vbl_swap_t *vbl_swap; - unsigned int pipe, seqtype, curseq; + unsigned int pipe, seqtype, curseq, plane; unsigned long irqflags; struct list_head *list; + int ret; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __func__); return -EINVAL; } - if (dev_priv->sarea_priv->rotation) { + if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) { DRM_DEBUG("Rotation not supported\n"); return -EINVAL; } if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | - _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) { + _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS | + _DRM_VBLANK_FLIP)) { DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype); return -EINVAL; } - pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; + plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; + pipe = i915_get_pipe(dev, plane); seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); @@ -495,6 +743,11 @@ int i915_vblank_swap(struct drm_device *dev, void *data, spin_lock_irqsave(&dev->drw_lock, irqflags); + /* It makes no sense to schedule a swap for a drawable that doesn't have + * valid information at this point. E.g. this could mean that the X + * server is too old to push drawable information to the DRM, in which + * case all such swaps would become ineffective. + */ if (!drm_get_drawable_info(dev, swap->drawable)) { spin_unlock_irqrestore(&dev->drw_lock, irqflags); DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable); @@ -503,7 +756,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data, spin_unlock_irqrestore(&dev->drw_lock, irqflags); - curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); + drm_update_vblank_count(dev, pipe); + curseq = drm_vblank_count(dev, pipe); if (seqtype == _DRM_VBLANK_RELATIVE) swap->sequence += curseq; @@ -517,14 +771,43 @@ int i915_vblank_swap(struct drm_device *dev, void *data, } } + if (swap->seqtype & _DRM_VBLANK_FLIP) { + swap->sequence--; + + if ((curseq - swap->sequence) <= (1<<23)) { + struct drm_drawable_info *drw; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + + spin_lock_irqsave(&dev->drw_lock, irqflags); + + drw = drm_get_drawable_info(dev, swap->drawable); + + if (!drw) { + spin_unlock_irqrestore(&dev->drw_lock, + irqflags); + DRM_DEBUG("Invalid drawable ID %d\n", + swap->drawable); + return -EINVAL; + } + + i915_dispatch_vsync_flip(dev, drw, plane); + + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + + return 0; + } + } + spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); list_for_each(list, &dev_priv->vbl_swaps.head) { vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); if (vbl_swap->drw_id == swap->drawable && - vbl_swap->pipe == pipe && + vbl_swap->plane == plane && vbl_swap->sequence == swap->sequence) { + vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP); spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); DRM_DEBUG("Already scheduled\n"); return 0; @@ -547,9 +830,19 @@ int i915_vblank_swap(struct drm_device *dev, void *data, DRM_DEBUG("\n"); + ret = drm_vblank_get(dev, pipe); + if (ret) { + drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); + return ret; + } + vbl_swap->drw_id = swap->drawable; - vbl_swap->pipe = pipe; + vbl_swap->plane = plane; vbl_swap->sequence = swap->sequence; + vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP); + + if (vbl_swap->flip) + swap->sequence++; spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); @@ -567,37 +860,57 @@ void i915_driver_irq_preinstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - I915_WRITE16(I915REG_HWSTAM, 0xfffe); + I915_WRITE16(I915REG_HWSTAM, 0xeffe); I915_WRITE16(I915REG_INT_MASK_R, 0x0); I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); } -void i915_driver_irq_postinstall(struct drm_device * dev) +int i915_driver_irq_postinstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + int ret, num_pipes = 2; spin_lock_init(&dev_priv->swaps_lock); INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); dev_priv->swaps_pending = 0; - if (!dev_priv->vblank_pipe) - dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A; + dev_priv->user_irq_refcount = 0; + dev_priv->irq_enable_reg = 0; + + ret = drm_vblank_init(dev, num_pipes); + if (ret) + return ret; + + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ + i915_enable_interrupt(dev); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); + + /* + * Initialize the hardware status page IRQ location. + */ + + I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21)); + return 0; } void i915_driver_irq_uninstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u16 temp; + u32 temp; if (!dev_priv) return; - I915_WRITE16(I915REG_HWSTAM, 0xffff); - I915_WRITE16(I915REG_INT_MASK_R, 0xffff); - I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); - - temp = I915_READ16(I915REG_INT_IDENTITY_R); - I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + dev_priv->irq_enabled = 0; + I915_WRITE(I915REG_HWSTAM, 0xffffffff); + I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); + I915_WRITE(I915REG_INT_ENABLE_R, 0x0); + + temp = I915_READ(I915REG_PIPEASTAT); + I915_WRITE(I915REG_PIPEASTAT, temp); + temp = I915_READ(I915REG_PIPEBSTAT); + I915_WRITE(I915REG_PIPEBSTAT, temp); + temp = I915_READ(I915REG_INT_IDENTITY_R); + I915_WRITE(I915REG_INT_IDENTITY_R, temp); } diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index 5572939fc7d..6b3790939e7 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c @@ -45,15 +45,16 @@ static struct pci_device_id pciidlist[] = { static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | - DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | - DRIVER_IRQ_VBL, + DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .dev_priv_size = sizeof(drm_mga_buf_priv_t), .load = mga_driver_load, .unload = mga_driver_unload, .lastclose = mga_driver_lastclose, .dma_quiescent = mga_driver_dma_quiescent, .device_is_agp = mga_driver_device_is_agp, - .vblank_wait = mga_driver_vblank_wait, + .get_vblank_counter = mga_get_vblank_counter, + .enable_vblank = mga_enable_vblank, + .disable_vblank = mga_disable_vblank, .irq_preinstall = mga_driver_irq_preinstall, .irq_postinstall = mga_driver_irq_postinstall, .irq_uninstall = mga_driver_irq_uninstall, diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h index f6ebd24bd58..8f7291f3636 100644 --- a/drivers/char/drm/mga_drv.h +++ b/drivers/char/drm/mga_drv.h @@ -120,6 +120,7 @@ typedef struct drm_mga_private { u32 clear_cmd; u32 maccess; + atomic_t vbl_received; /**< Number of vblanks received. */ wait_queue_head_t fence_queue; atomic_t last_fence_retired; u32 next_fence_to_post; @@ -181,11 +182,14 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv); extern int mga_warp_init(drm_mga_private_t * dev_priv); /* mga_irq.c */ +extern int mga_enable_vblank(struct drm_device *dev, int crtc); +extern void mga_disable_vblank(struct drm_device *dev, int crtc); +extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc); extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence); extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence); extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS); extern void mga_driver_irq_preinstall(struct drm_device * dev); -extern void mga_driver_irq_postinstall(struct drm_device * dev); +extern int mga_driver_irq_postinstall(struct drm_device * dev); extern void mga_driver_irq_uninstall(struct drm_device * dev); extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c index 9302cb8f0f8..06852fb4b27 100644 --- a/drivers/char/drm/mga_irq.c +++ b/drivers/char/drm/mga_irq.c @@ -35,6 +35,20 @@ #include "mga_drm.h" #include "mga_drv.h" +u32 mga_get_vblank_counter(struct drm_device *dev, int crtc) +{ + const drm_mga_private_t *const dev_priv = + (drm_mga_private_t *) dev->dev_private; + + if (crtc != 0) { + return 0; + } + + + return atomic_read(&dev_priv->vbl_received); +} + + irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -47,9 +61,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) /* VBLANK interrupt */ if (status & MGA_VLINEPEN) { MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); - atomic_inc(&dev->vbl_received); - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + atomic_inc(&dev_priv->vbl_received); + drm_handle_vblank(dev, 0); handled = 1; } @@ -78,22 +91,34 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) return IRQ_NONE; } -int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) +int mga_enable_vblank(struct drm_device *dev, int crtc) { - unsigned int cur_vblank; - int ret = 0; + drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) - - *sequence) <= (1 << 23))); + if (crtc != 0) { + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + return 0; + } - *sequence = cur_vblank; + MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); + return 0; +} - return ret; + +void mga_disable_vblank(struct drm_device *dev, int crtc) +{ + if (crtc != 0) { + DRM_ERROR("tried to disable vblank on non-existent crtc %d\n", + crtc); + } + + /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have + * a nice hardware counter that tracks the number of refreshes when + * the interrupt is disabled, and the kernel doesn't know the refresh + * rate to calculate an estimate. + */ + /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */ } int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence) @@ -125,14 +150,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev) MGA_WRITE(MGA_ICLEAR, ~0); } -void mga_driver_irq_postinstall(struct drm_device * dev) +int mga_driver_irq_postinstall(struct drm_device * dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; + int ret; + + ret = drm_vblank_init(dev, 1); + if (ret) + return ret; DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); - /* Turn on vertical blank interrupt and soft trap interrupt. */ - MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); + /* Turn on soft trap interrupt. Vertical blank interrupts are enabled + * in mga_enable_vblank. + */ + MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN); + return 0; } void mga_driver_irq_uninstall(struct drm_device * dev) diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c index 892e0a58984..c31afbde62e 100644 --- a/drivers/char/drm/r128_cce.c +++ b/drivers/char/drm/r128_cce.c @@ -558,6 +558,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) #if __OS_HAS_AGP if (dev_priv->is_pci) { #endif + dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; dev_priv->gart_info.addr = NULL; @@ -816,7 +817,7 @@ static struct drm_buf *r128_freelist_get(struct drm_device * dev) for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; - if (buf->file_priv == 0) + if (!buf->file_priv) return buf; } diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c index 6108e7587e1..2888aa01ebc 100644 --- a/drivers/char/drm/r128_drv.c +++ b/drivers/char/drm/r128_drv.c @@ -43,12 +43,13 @@ static struct pci_device_id pciidlist[] = { static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | - DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | - DRIVER_IRQ_VBL, + DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .dev_priv_size = sizeof(drm_r128_buf_priv_t), .preclose = r128_driver_preclose, .lastclose = r128_driver_lastclose, - .vblank_wait = r128_driver_vblank_wait, + .get_vblank_counter = r128_get_vblank_counter, + .enable_vblank = r128_enable_vblank, + .disable_vblank = r128_disable_vblank, .irq_preinstall = r128_driver_irq_preinstall, .irq_postinstall = r128_driver_irq_postinstall, .irq_uninstall = r128_driver_irq_uninstall, diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h index 011105e51ac..80af9e09e75 100644 --- a/drivers/char/drm/r128_drv.h +++ b/drivers/char/drm/r128_drv.h @@ -97,6 +97,8 @@ typedef struct drm_r128_private { u32 crtc_offset; u32 crtc_offset_cntl; + atomic_t vbl_received; + u32 color_fmt; unsigned int front_offset; unsigned int front_pitch; @@ -149,11 +151,12 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n); extern int r128_do_cce_idle(drm_r128_private_t * dev_priv); extern int r128_do_cleanup_cce(struct drm_device * dev); -extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence); - +extern int r128_enable_vblank(struct drm_device *dev, int crtc); +extern void r128_disable_vblank(struct drm_device *dev, int crtc); +extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc); extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS); extern void r128_driver_irq_preinstall(struct drm_device * dev); -extern void r128_driver_irq_postinstall(struct drm_device * dev); +extern int r128_driver_irq_postinstall(struct drm_device * dev); extern void r128_driver_irq_uninstall(struct drm_device * dev); extern void r128_driver_lastclose(struct drm_device * dev); extern void r128_driver_preclose(struct drm_device * dev, diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c index c76fdca7662..5b95bd898f9 100644 --- a/drivers/char/drm/r128_irq.c +++ b/drivers/char/drm/r128_irq.c @@ -35,6 +35,16 @@ #include "r128_drm.h" #include "r128_drv.h" +u32 r128_get_vblank_counter(struct drm_device *dev, int crtc) +{ + const drm_r128_private_t *dev_priv = dev->dev_private; + + if (crtc != 0) + return 0; + + return atomic_read(&dev_priv->vbl_received); +} + irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -46,30 +56,38 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) /* VBLANK interrupt */ if (status & R128_CRTC_VBLANK_INT) { R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); - atomic_inc(&dev->vbl_received); - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + atomic_inc(&dev_priv->vbl_received); + drm_handle_vblank(dev, 0); return IRQ_HANDLED; } return IRQ_NONE; } -int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) +int r128_enable_vblank(struct drm_device *dev, int crtc) { - unsigned int cur_vblank; - int ret = 0; + drm_r128_private_t *dev_priv = dev->dev_private; - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) - - *sequence) <= (1 << 23))); + if (crtc != 0) { + DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); + return -EINVAL; + } - *sequence = cur_vblank; + R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); + return 0; +} + +void r128_disable_vblank(struct drm_device *dev, int crtc) +{ + if (crtc != 0) + DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); - return ret; + /* + * FIXME: implement proper interrupt disable by using the vblank + * counter register (if available) + * + * R128_WRITE(R128_GEN_INT_CNTL, + * R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN); + */ } void r128_driver_irq_preinstall(struct drm_device * dev) @@ -82,12 +100,9 @@ void r128_driver_irq_preinstall(struct drm_device * dev) R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); } -void r128_driver_irq_postinstall(struct drm_device * dev) +int r128_driver_irq_postinstall(struct drm_device * dev) { - drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; - - /* Turn on VBL interrupt */ - R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); + return drm_vblank_init(dev, 1); } void r128_driver_irq_uninstall(struct drm_device * dev) diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 0f4afc44245..f535812e405 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -729,6 +729,47 @@ static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf) buf->used = 0; } +static void r300_cmd_wait(drm_radeon_private_t * dev_priv, + drm_r300_cmd_header_t header) +{ + u32 wait_until; + RING_LOCALS; + + if (!header.wait.flags) + return; + + wait_until = 0; + + switch(header.wait.flags) { + case R300_WAIT_2D: + wait_until = RADEON_WAIT_2D_IDLE; + break; + case R300_WAIT_3D: + wait_until = RADEON_WAIT_3D_IDLE; + break; + case R300_NEW_WAIT_2D_3D: + wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE; + break; + case R300_NEW_WAIT_2D_2D_CLEAN: + wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; + break; + case R300_NEW_WAIT_3D_3D_CLEAN: + wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; + break; + case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN: + wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; + wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; + break; + default: + return; + } + + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(wait_until); + ADVANCE_RING(); +} + static int r300_scratch(drm_radeon_private_t *dev_priv, drm_radeon_kcmd_buffer_t *cmdbuf, drm_r300_cmd_header_t header) @@ -909,19 +950,8 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, break; case R300_CMD_WAIT: - /* simple enough, we can do it here */ DRM_DEBUG("R300_CMD_WAIT\n"); - if (header.wait.flags == 0) - break; /* nothing to do */ - - { - RING_LOCALS; - - BEGIN_RING(2); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING((header.wait.flags & 0xf) << 14); - ADVANCE_RING(); - } + r300_cmd_wait(dev_priv, header); break; case R300_CMD_SCRATCH: diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 833abc7e55f..9072e4a1894 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -1807,6 +1807,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) } else #endif { + dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); /* if we have an offset set from userspace */ if (dev_priv->pcigart_offset_set) { dev_priv->gart_info.bus_addr = diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index 71e5b21fad2..aab82e121e0 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h @@ -225,8 +225,20 @@ typedef union { #define R300_CMD_WAIT 7 # define R300_WAIT_2D 0x1 # define R300_WAIT_3D 0x2 +/* these two defines are DOING IT WRONG - however + * we have userspace which relies on using these. + * The wait interface is backwards compat new + * code should use the NEW_WAIT defines below + * THESE ARE NOT BIT FIELDS + */ # define R300_WAIT_2D_CLEAN 0x3 # define R300_WAIT_3D_CLEAN 0x4 + +# define R300_NEW_WAIT_2D_3D 0x3 +# define R300_NEW_WAIT_2D_2D_CLEAN 0x4 +# define R300_NEW_WAIT_3D_3D_CLEAN 0x6 +# define R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN 0x8 + #define R300_CMD_SCRATCH 8 typedef union { diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c index 349ac3d3b84..a2610319624 100644 --- a/drivers/char/drm/radeon_drv.c +++ b/drivers/char/drm/radeon_drv.c @@ -59,8 +59,7 @@ static struct pci_device_id pciidlist[] = { static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | - DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | - DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2, + DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED, .dev_priv_size = sizeof(drm_radeon_buf_priv_t), .load = radeon_driver_load, .firstopen = radeon_driver_firstopen, @@ -69,8 +68,9 @@ static struct drm_driver driver = { .postclose = radeon_driver_postclose, .lastclose = radeon_driver_lastclose, .unload = radeon_driver_unload, - .vblank_wait = radeon_driver_vblank_wait, - .vblank_wait2 = radeon_driver_vblank_wait2, + .get_vblank_counter = radeon_get_vblank_counter, + .enable_vblank = radeon_enable_vblank, + .disable_vblank = radeon_disable_vblank, .dri_library_name = dri_library_name, .irq_preinstall = radeon_driver_irq_preinstall, .irq_postinstall = radeon_driver_irq_postinstall, diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 173ae620223..b791420bd3d 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -304,6 +304,9 @@ typedef struct drm_radeon_private { u32 scratch_ages[5]; + unsigned int crtc_last_cnt; + unsigned int crtc2_last_cnt; + /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ unsigned long fb_aper_offset; @@ -374,13 +377,13 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file * extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); extern void radeon_do_release(struct drm_device * dev); -extern int radeon_driver_vblank_wait(struct drm_device * dev, - unsigned int *sequence); -extern int radeon_driver_vblank_wait2(struct drm_device * dev, - unsigned int *sequence); +extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc); +extern int radeon_enable_vblank(struct drm_device *dev, int crtc); +extern void radeon_disable_vblank(struct drm_device *dev, int crtc); +extern void radeon_do_release(struct drm_device * dev); extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); extern void radeon_driver_irq_preinstall(struct drm_device * dev); -extern void radeon_driver_irq_postinstall(struct drm_device * dev); +extern int radeon_driver_irq_postinstall(struct drm_device * dev); extern void radeon_driver_irq_uninstall(struct drm_device * dev); extern int radeon_vblank_crtc_get(struct drm_device *dev); extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value); @@ -558,6 +561,12 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev, ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \ : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) +#define RADEON_CRTC_CRNT_FRAME 0x0214 +#define RADEON_CRTC2_CRNT_FRAME 0x0314 + +#define RADEON_CRTC_STATUS 0x005c +#define RADEON_CRTC2_STATUS 0x03fc + #define RADEON_GEN_INT_CNTL 0x0040 # define RADEON_CRTC_VBLANK_MASK (1 << 0) # define RADEON_CRTC2_VBLANK_MASK (1 << 9) diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c index 009af3814b6..507d6b747a1 100644 --- a/drivers/char/drm/radeon_irq.c +++ b/drivers/char/drm/radeon_irq.c @@ -35,12 +35,61 @@ #include "radeon_drm.h" #include "radeon_drv.h" -static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, - u32 mask) +static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) { - u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask; + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (state) + dev_priv->irq_enable_reg |= mask; + else + dev_priv->irq_enable_reg &= ~mask; + + RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); +} + +int radeon_enable_vblank(struct drm_device *dev, int crtc) +{ + switch (crtc) { + case 0: + radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1); + break; + case 1: + radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + return EINVAL; + } + + return 0; +} + +void radeon_disable_vblank(struct drm_device *dev, int crtc) +{ + switch (crtc) { + case 0: + radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0); + break; + case 1: + radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + break; + } +} + +static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv) +{ + u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & + (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | + RADEON_CRTC2_VBLANK_STAT); + if (irqs) RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); + return irqs; } @@ -72,39 +121,21 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) /* Only consider the bits we're interested in - others could be used * outside the DRM */ - stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | - RADEON_CRTC_VBLANK_STAT | - RADEON_CRTC2_VBLANK_STAT)); + stat = radeon_acknowledge_irqs(dev_priv); if (!stat) return IRQ_NONE; stat &= dev_priv->irq_enable_reg; /* SW interrupt */ - if (stat & RADEON_SW_INT_TEST) { + if (stat & RADEON_SW_INT_TEST) DRM_WAKEUP(&dev_priv->swi_queue); - } /* VBLANK interrupt */ - if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) { - int vblank_crtc = dev_priv->vblank_crtc; - - if ((vblank_crtc & - (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) == - (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { - if (stat & RADEON_CRTC_VBLANK_STAT) - atomic_inc(&dev->vbl_received); - if (stat & RADEON_CRTC2_VBLANK_STAT) - atomic_inc(&dev->vbl_received2); - } else if (((stat & RADEON_CRTC_VBLANK_STAT) && - (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) || - ((stat & RADEON_CRTC2_VBLANK_STAT) && - (vblank_crtc & DRM_RADEON_VBLANK_CRTC2))) - atomic_inc(&dev->vbl_received); - - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); - } + if (stat & RADEON_CRTC_VBLANK_STAT) + drm_handle_vblank(dev, 0); + if (stat & RADEON_CRTC2_VBLANK_STAT) + drm_handle_vblank(dev, 1); return IRQ_HANDLED; } @@ -144,54 +175,27 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr) return ret; } -static int radeon_driver_vblank_do_wait(struct drm_device * dev, - unsigned int *sequence, int crtc) +u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) { - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - unsigned int cur_vblank; - int ret = 0; - int ack = 0; - atomic_t *counter; + drm_radeon_private_t *dev_priv = dev->dev_private; + u32 crtc_cnt_reg, crtc_status_reg; + if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } - if (crtc == DRM_RADEON_VBLANK_CRTC1) { - counter = &dev->vbl_received; - ack |= RADEON_CRTC_VBLANK_STAT; - } else if (crtc == DRM_RADEON_VBLANK_CRTC2) { - counter = &dev->vbl_received2; - ack |= RADEON_CRTC2_VBLANK_STAT; - } else + if (crtc == 0) { + crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME; + crtc_status_reg = RADEON_CRTC_STATUS; + } else if (crtc == 1) { + crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME; + crtc_status_reg = RADEON_CRTC2_STATUS; + } else { return -EINVAL; + } - radeon_acknowledge_irqs(dev_priv, ack); - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(counter)) - - *sequence) <= (1 << 23))); - - *sequence = cur_vblank; - - return ret; -} - -int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence) -{ - return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1); -} - -int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) -{ - return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2); + return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1); } /* Needs the lock as it touches the ring. @@ -234,21 +238,6 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr return radeon_wait_irq(dev, irqwait->irq_seq); } -static void radeon_enable_interrupt(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; - - dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE; - if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1) - dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK; - - if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2) - dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK; - - RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); - dev_priv->irq_enabled = 1; -} - /* drm_dma.h hooks */ void radeon_driver_irq_preinstall(struct drm_device * dev) @@ -260,20 +249,27 @@ void radeon_driver_irq_preinstall(struct drm_device * dev) RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); /* Clear bits if they're already high */ - radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | - RADEON_CRTC_VBLANK_STAT | - RADEON_CRTC2_VBLANK_STAT)); + radeon_acknowledge_irqs(dev_priv); } -void radeon_driver_irq_postinstall(struct drm_device * dev) +int radeon_driver_irq_postinstall(struct drm_device * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; + int ret; atomic_set(&dev_priv->swi_emitted, 0); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); - radeon_enable_interrupt(dev); + ret = drm_vblank_init(dev, 2); + if (ret) + return ret; + + dev->max_vblank_count = 0x001fffff; + + radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); + + return 0; } void radeon_driver_irq_uninstall(struct drm_device * dev) @@ -315,6 +311,5 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value) return -EINVAL; } dev_priv->vblank_crtc = (unsigned int)value; - radeon_enable_interrupt(dev); return 0; } diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c index 78b34fa7c89..4af5286a36f 100644 --- a/drivers/char/drm/radeon_mem.c +++ b/drivers/char/drm/radeon_mem.c @@ -88,7 +88,7 @@ static struct mem_block *alloc_block(struct mem_block *heap, int size, list_for_each(p, heap) { int start = (p->start + mask) & ~mask; - if (p->file_priv == 0 && start + size <= p->start + p->size) + if (p->file_priv == NULL && start + size <= p->start + p->size) return split_block(p, start, size, file_priv); } @@ -113,7 +113,7 @@ static void free_block(struct mem_block *p) /* Assumes a single contiguous range. Needs a special file_priv in * 'heap' to stop it being subsumed. */ - if (p->next->file_priv == 0) { + if (p->next->file_priv == NULL) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; @@ -121,7 +121,7 @@ static void free_block(struct mem_block *p) drm_free(q, sizeof(*q), DRM_MEM_BUFS); } - if (p->prev->file_priv == 0) { + if (p->prev->file_priv == NULL) { struct mem_block *q = p->prev; q->size += p->size; q->next = p->next; @@ -174,7 +174,7 @@ void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap) * 'heap' to stop it being subsumed. */ list_for_each(p, heap) { - while (p->file_priv == 0 && p->next->file_priv == 0) { + while (p->file_priv == NULL && p->next->file_priv == NULL) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index 94baec692b5..7a339dba6a6 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c @@ -126,6 +126,8 @@ via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size) hw_addr, cur_addr, next_addr); return -1; } + if ((cur_addr < hw_addr) && (next_addr >= hw_addr)) + msleep(1); } while ((cur_addr < hw_addr) && (next_addr >= hw_addr)); return 0; } @@ -416,27 +418,50 @@ static int via_hook_segment(drm_via_private_t * dev_priv, int paused, count; volatile uint32_t *paused_at = dev_priv->last_pause_ptr; uint32_t reader,ptr; + uint32_t diff; paused = 0; via_flush_write_combine(); (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1); + *paused_at = pause_addr_lo; via_flush_write_combine(); (void) *paused_at; + reader = *(dev_priv->hw_addr_ptr); ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; + dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; - if ((ptr - reader) <= dev_priv->dma_diff ) { - count = 10000000; - while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--); + /* + * If there is a possibility that the command reader will + * miss the new pause address and pause on the old one, + * In that case we need to program the new start address + * using PCI. + */ + + diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; + count = 10000000; + while(diff == 0 && count--) { + paused = (VIA_READ(0x41c) & 0x80000000); + if (paused) + break; + reader = *(dev_priv->hw_addr_ptr); + diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; } + paused = VIA_READ(0x41c) & 0x80000000; + if (paused && !no_pci_fire) { reader = *(dev_priv->hw_addr_ptr); - if ((ptr - reader) == dev_priv->dma_diff) { - + diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; + diff &= (dev_priv->dma_high - 1); + if (diff != 0 && diff < (dev_priv->dma_high >> 1)) { + DRM_ERROR("Paused at incorrect address. " + "0x%08x, 0x%08x 0x%08x\n", + ptr, reader, dev_priv->dma_diff); + } else if (diff == 0) { /* * There is a concern that these writes may stall the PCI bus * if the GPU is not idle. However, idling the GPU first @@ -577,6 +602,7 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) uint32_t pause_addr_lo, pause_addr_hi; uint32_t jump_addr_lo, jump_addr_hi; volatile uint32_t *last_pause_ptr; + uint32_t dma_low_save1, dma_low_save2; agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, @@ -603,8 +629,29 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) &pause_addr_lo, 0); *last_pause_ptr = pause_addr_lo; + dma_low_save1 = dev_priv->dma_low; - via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0); + /* + * Now, set a trap that will pause the regulator if it tries to rerun the old + * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause + * and reissues the jump command over PCI, while the regulator has already taken the jump + * and actually paused at the current buffer end). + * There appears to be no other way to detect this condition, since the hw_addr_pointer + * does not seem to get updated immediately when a jump occurs. + */ + + last_pause_ptr = + via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, + &pause_addr_lo, 0) - 1; + via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, + &pause_addr_lo, 0); + *last_pause_ptr = pause_addr_lo; + + dma_low_save2 = dev_priv->dma_low; + dev_priv->dma_low = dma_low_save1; + via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); + dev_priv->dma_low = dma_low_save2; + via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); } diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 33c5197b73c..409e00afdd0 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c @@ -603,7 +603,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli * (Not a big limitation anyway.) */ - if ((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) { + if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) { DRM_ERROR("Too large system memory stride. Stride: %d, " "Length: %d\n", xfer->mem_stride, xfer->line_length); return -EINVAL; diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c index 80c01cdfa37..37870a4a3dc 100644 --- a/drivers/char/drm/via_drv.c +++ b/drivers/char/drm/via_drv.c @@ -40,11 +40,13 @@ static struct pci_device_id pciidlist[] = { static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | - DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, + DRIVER_IRQ_SHARED, .load = via_driver_load, .unload = via_driver_unload, .context_dtor = via_final_context, - .vblank_wait = via_driver_vblank_wait, + .get_vblank_counter = via_get_vblank_counter, + .enable_vblank = via_enable_vblank, + .disable_vblank = via_disable_vblank, .irq_preinstall = via_driver_irq_preinstall, .irq_postinstall = via_driver_irq_postinstall, .irq_uninstall = via_driver_irq_uninstall, diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index 2daae81874c..fe67030e39a 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h @@ -75,6 +75,7 @@ typedef struct drm_via_private { struct timeval last_vblank; int last_vblank_valid; unsigned usec_per_vblank; + atomic_t vbl_received; drm_via_state_t hc_state; char pci_buf[VIA_PCI_BUF_SIZE]; const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; @@ -130,11 +131,13 @@ extern int via_init_context(struct drm_device * dev, int context); extern int via_final_context(struct drm_device * dev, int context); extern int via_do_cleanup_map(struct drm_device * dev); -extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence); +extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc); +extern int via_enable_vblank(struct drm_device *dev, int crtc); +extern void via_disable_vblank(struct drm_device *dev, int crtc); extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS); extern void via_driver_irq_preinstall(struct drm_device * dev); -extern void via_driver_irq_postinstall(struct drm_device * dev); +extern int via_driver_irq_postinstall(struct drm_device * dev); extern void via_driver_irq_uninstall(struct drm_device * dev); extern int via_dma_cleanup(struct drm_device * dev); diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index c6bb978a110..f1ab6fc7c07 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c @@ -92,8 +92,17 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; static unsigned time_diff(struct timeval *now, struct timeval *then) { return (now->tv_usec >= then->tv_usec) ? - now->tv_usec - then->tv_usec : - 1000000 - (then->tv_usec - now->tv_usec); + now->tv_usec - then->tv_usec : + 1000000 - (then->tv_usec - now->tv_usec); +} + +u32 via_get_vblank_counter(struct drm_device *dev, int crtc) +{ + drm_via_private_t *dev_priv = dev->dev_private; + if (crtc != 0) + return 0; + + return atomic_read(&dev_priv->vbl_received); } irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) @@ -108,8 +117,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) status = VIA_READ(VIA_REG_INTERRUPT); if (status & VIA_IRQ_VBLANK_PENDING) { - atomic_inc(&dev->vbl_received); - if (!(atomic_read(&dev->vbl_received) & 0x0F)) { + atomic_inc(&dev_priv->vbl_received); + if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { do_gettimeofday(&cur_vblank); if (dev_priv->last_vblank_valid) { dev_priv->usec_per_vblank = @@ -119,12 +128,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) dev_priv->last_vblank = cur_vblank; dev_priv->last_vblank_valid = 1; } - if (!(atomic_read(&dev->vbl_received) & 0xFF)) { + if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { DRM_DEBUG("US per vblank is: %u\n", dev_priv->usec_per_vblank); } - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + drm_handle_vblank(dev, 0); handled = 1; } @@ -163,31 +171,34 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv) } } -int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) +int via_enable_vblank(struct drm_device *dev, int crtc) { - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - unsigned int cur_vblank; - int ret = 0; + drm_via_private_t *dev_priv = dev->dev_private; + u32 status; - DRM_DEBUG("\n"); - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); + if (crtc != 0) { + DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); return -EINVAL; } - viadrv_acknowledge_irqs(dev_priv); + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE); - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ + VIA_WRITE8(0x83d4, 0x11); + VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) - - *sequence) <= (1 << 23))); + return 0; +} - *sequence = cur_vblank; - return ret; +void via_disable_vblank(struct drm_device *dev, int crtc) +{ + drm_via_private_t *dev_priv = dev->dev_private; + + VIA_WRITE8(0x83d4, 0x11); + VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); + + if (crtc != 0) + DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); } static int @@ -292,23 +303,25 @@ void via_driver_irq_preinstall(struct drm_device * dev) } } -void via_driver_irq_postinstall(struct drm_device * dev) +int via_driver_irq_postinstall(struct drm_device * dev) { drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; u32 status; - DRM_DEBUG("\n"); - if (dev_priv) { - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL - | dev_priv->irq_enable_mask); + DRM_DEBUG("via_driver_irq_postinstall\n"); + if (!dev_priv) + return -EINVAL; - /* Some magic, oh for some data sheets ! */ + drm_vblank_init(dev, 1); + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL + | dev_priv->irq_enable_mask); - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); + /* Some magic, oh for some data sheets ! */ + VIA_WRITE8(0x83d4, 0x11); + VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); - } + return 0; } void via_driver_irq_uninstall(struct drm_device * dev) diff --git a/drivers/char/esp.c b/drivers/char/esp.c index c01e26d9ee5..f3fe6206734 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -2484,6 +2484,7 @@ static int __init espserial_init(void) return 0; } + spin_lock_init(&info->lock); /* rx_trigger, tx_trigger are needed by autoconfig */ info->config.rx_trigger = rx_trigger; info->config.tx_trigger = tx_trigger; diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 8facf3e25c4..7ed7da1d99c 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -28,7 +28,6 @@ #include <linux/interrupt.h> #include <linux/tty_flip.h> #include <linux/delay.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #define DEBUG diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 465ad35ed38..1399971be68 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -731,14 +731,14 @@ static unsigned long hpet_calibrate(struct hpets *hpetp) int hpet_alloc(struct hpet_data *hdp) { - u64 cap, mcfg, hpet_config; + u64 cap, mcfg; struct hpet_dev *devp; - u32 i, ntimer, irq; + u32 i, ntimer; struct hpets *hpetp; size_t siz; struct hpet __iomem *hpet; static struct hpets *last = NULL; - unsigned long period, irq_bitmap; + unsigned long period; unsigned long long temp; /* @@ -765,47 +765,11 @@ int hpet_alloc(struct hpet_data *hdp) hpetp->hp_hpet_phys = hdp->hd_phys_address; hpetp->hp_ntimer = hdp->hd_nirqs; - hpet = hpetp->hp_hpet; - - /* Assign IRQs statically for legacy devices */ - hpetp->hp_dev[0].hd_hdwirq = hdp->hd_irq[0]; - hpetp->hp_dev[1].hd_hdwirq = hdp->hd_irq[1]; - - /* Assign IRQs dynamically for the others */ - for (i = 2, devp = &hpetp->hp_dev[2]; i < hdp->hd_nirqs; i++, devp++) { - struct hpet_timer __iomem *timer; - timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; + for (i = 0; i < hdp->hd_nirqs; i++) + hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; - /* Check if there's already an IRQ assigned to the timer */ - if (hdp->hd_irq[i]) { - hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; - continue; - } - - hpet_config = readq(&timer->hpet_config); - irq_bitmap = (hpet_config & Tn_INT_ROUTE_CAP_MASK) - >> Tn_INT_ROUTE_CAP_SHIFT; - if (!irq_bitmap) - irq = 0; /* No valid IRQ Assignable */ - else { - irq = find_first_bit(&irq_bitmap, 32); - do { - hpet_config |= irq << Tn_INT_ROUTE_CNF_SHIFT; - writeq(hpet_config, &timer->hpet_config); - - /* - * Verify whether we have written a valid - * IRQ number by reading it back again - */ - hpet_config = readq(&timer->hpet_config); - if (irq == (hpet_config & Tn_INT_ROUTE_CNF_MASK) - >> Tn_INT_ROUTE_CNF_SHIFT) - break; /* Success */ - } while ((irq = (find_next_bit(&irq_bitmap, 32, irq)))); - } - hpetp->hp_dev[i].hd_hdwirq = irq; - } + hpet = hpetp->hp_hpet; cap = readq(&hpet->hpet_cap); @@ -836,8 +800,7 @@ int hpet_alloc(struct hpet_data *hdp) hpetp->hp_which, hdp->hd_phys_address, hpetp->hp_ntimer > 1 ? "s" : ""); for (i = 0; i < hpetp->hp_ntimer; i++) - printk("%s %d", i > 0 ? "," : "", - hpetp->hp_dev[i].hd_hdwirq); + printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); printk("\n"); printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c index e74bb949c28..91cdb35a920 100644 --- a/drivers/char/hvc_beat.c +++ b/drivers/char/hvc_beat.c @@ -78,8 +78,8 @@ static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt) for (rest = cnt; rest > 0; rest -= nlen) { nlen = (rest > 16) ? 16 : rest; memcpy(kb, buf, nlen); - beat_put_term_char(vtermno, rest, kb[0], kb[1]); - rest -= nlen; + beat_put_term_char(vtermno, nlen, kb[0], kb[1]); + buf += nlen; } return cnt; } diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 6bbd4fa50f3..8d6c2089d2a 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -9,7 +9,14 @@ config HW_RANDOM Hardware Random Number Generator Core infrastructure. To compile this driver as a module, choose M here: the - module will be called rng-core. + module will be called rng-core. This provides a device + that's usually called /dev/hw_random, and which exposes one + of possibly several hardware random number generators. + + These hardware random number generators do not feed directly + into the kernel's random number generator. That is usually + handled by the "rngd" daemon. Documentation/hw_random.txt + has more information. If unsure, say Y. diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 84cdf902573..662d60e44e9 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -116,6 +116,10 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, err = -EAGAIN; if (!bytes_read && (filp->f_flags & O_NONBLOCK)) goto out; + if (bytes_read < 0) { + err = bytes_read; + goto out; + } err = -EFAULT; while (bytes_read && size) { @@ -234,11 +238,11 @@ static DEVICE_ATTR(rng_available, S_IRUGO, NULL); -static void unregister_miscdev(bool suspended) +static void unregister_miscdev(void) { device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available); device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current); - __misc_deregister(&rng_miscdev, suspended); + misc_deregister(&rng_miscdev); } static int register_miscdev(void) @@ -313,7 +317,7 @@ out: } EXPORT_SYMBOL_GPL(hwrng_register); -void __hwrng_unregister(struct hwrng *rng, bool suspended) +void hwrng_unregister(struct hwrng *rng) { int err; @@ -332,11 +336,11 @@ void __hwrng_unregister(struct hwrng *rng, bool suspended) } } if (list_empty(&rng_list)) - unregister_miscdev(suspended); + unregister_miscdev(); mutex_unlock(&rng_mutex); } -EXPORT_SYMBOL_GPL(__hwrng_unregister); +EXPORT_SYMBOL_GPL(hwrng_unregister); MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver"); diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 7e319951fa4..51738bdd834 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -1,7 +1,5 @@ /* - * drivers/char/hw_random/omap-rng.c - * - * RNG driver for TI OMAP CPU family + * omap-rng.c - RNG driver for TI OMAP CPU family * * Author: Deepak Saxena <dsaxena@plexity.net> * @@ -15,11 +13,6 @@ * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. - * - * TODO: - * - * - Make status updated be interrupt driven so we don't poll - * */ #include <linux/module.h> @@ -55,17 +48,16 @@ static void __iomem *rng_base; static struct clk *rng_ick; static struct platform_device *rng_dev; -static u32 omap_rng_read_reg(int reg) +static inline u32 omap_rng_read_reg(int reg) { return __raw_readl(rng_base + reg); } -static void omap_rng_write_reg(int reg, u32 val) +static inline void omap_rng_write_reg(int reg, u32 val) { __raw_writel(val, rng_base + reg); } -/* REVISIT: Does the status bit really work on 16xx? */ static int omap_rng_data_present(struct hwrng *rng, int wait) { int data, i; @@ -74,6 +66,11 @@ static int omap_rng_data_present(struct hwrng *rng, int wait) data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1; if (data || !wait) break; + /* RNG produces data fast enough (2+ MBit/sec, even + * during "rngtest" loads, that these delays don't + * seem to trigger. We *could* use the RNG IRQ, but + * that'd be higher overhead ... so why bother? + */ udelay(10); } return data; @@ -101,7 +98,8 @@ static int __init omap_rng_probe(struct platform_device *pdev) * A bit ugly, and it will never actually happen but there can * be only one RNG and this catches any bork */ - BUG_ON(rng_dev); + if (rng_dev) + return -EBUSY; if (cpu_is_omap24xx()) { rng_ick = clk_get(NULL, "rng_ick"); @@ -124,7 +122,7 @@ static int __init omap_rng_probe(struct platform_device *pdev) return -EBUSY; dev_set_drvdata(&pdev->dev, mem); - rng_base = (u32 __iomem *)io_p2v(res->start); + rng_base = (u32 __force __iomem *)io_p2v(res->start); ret = hwrng_register(&omap_rng_ops); if (ret) { @@ -182,6 +180,8 @@ static int omap_rng_resume(struct platform_device *pdev) #endif +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:omap_rng"); static struct platform_driver omap_rng_driver = { .driver = { diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index d6567b32fb5..9c25320121e 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c @@ -644,12 +644,12 @@ i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands, // Normal Expected path - We still hold LOCK break; /* from for()- Enough room: goto proceed */ } - } - - ip2trace (CHANN, ITRC_QUEUE, 3, 1, totalsize ); + ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); + WRITE_UNLOCK_IRQRESTORE(lock_var_p, flags); + } else + ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); - // Prepare to wait for buffers to empty - WRITE_UNLOCK_IRQRESTORE(lock_var_p,flags); + /* Prepare to wait for buffers to empty */ serviceOutgoingFifo(pB); // Dump what we got if (timeout == 0) { @@ -1830,6 +1830,8 @@ i2StripFifo(i2eBordStrPtr pB) default: // Neither packet? should be impossible ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1, PTYPE_OF(pB->i2eLeadoffWord) ); + WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, + bflags); break; } // End of switch on type of packets diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 85d596a3c18..eba2883b630 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1527,7 +1527,7 @@ static int __devinit reset_card(struct pci_dev *pdev, msleep(10); portcount = inw(base + 0x2); - if (!inw(base + 0xe) & 0x1 || (portcount != 0 && portcount != 4 && + if (!(inw(base + 0xe) & 0x1) || (portcount != 0 && portcount != 4 && portcount != 8 && portcount != 16)) { dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n", card + 1); diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 4dbd3425e92..60b934adea6 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -42,6 +42,7 @@ #include <linux/input.h> #include <linux/reboot.h> #include <linux/notifier.h> +#include <linux/jiffies.h> extern void ctrl_alt_del(void); @@ -928,7 +929,8 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag) if (up_flag) { if (brl_timeout) { if (!committing || - jiffies - releasestart > (brl_timeout * HZ) / 1000) { + time_after(jiffies, + releasestart + msecs_to_jiffies(brl_timeout))) { committing = pressed; releasestart = jiffies; } @@ -1033,7 +1035,8 @@ DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ - (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) + (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\ + defined(CONFIG_AVR32) #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\ ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001)) @@ -1237,6 +1240,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) } param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate; + param.ledstate = kbd->ledflagstate; key_map = key_maps[shift_final]; if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, ¶m) == NOTIFY_STOP || !key_map) { @@ -1285,6 +1289,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) (*k_handler[type])(vc, keysym & 0xff, !down); + param.ledstate = kbd->ledflagstate; atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, ¶m); if (type != KT_SLOCK) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 20070b7c573..e83623ead44 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -41,36 +41,7 @@ */ static inline int uncached_access(struct file *file, unsigned long addr) { -#if defined(__i386__) && !defined(__arch_um__) - /* - * On the PPro and successors, the MTRRs are used to set - * memory types for physical addresses outside main memory, - * so blindly setting PCD or PWT on those pages is wrong. - * For Pentiums and earlier, the surround logic should disable - * caching for the high addresses through the KEN pin, but - * we maintain the tradition of paranoia in this code. - */ - if (file->f_flags & O_SYNC) - return 1; - return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) || - test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) || - test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) || - test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) ) - && addr >= __pa(high_memory); -#elif defined(__x86_64__) && !defined(__arch_um__) - /* - * This is broken because it can generate memory type aliases, - * which can cause cache corruptions - * But it is only available for root and we have to be bug-to-bug - * compatible with i386. - */ - if (file->f_flags & O_SYNC) - return 1; - /* same behaviour as i386. PAT always set to cached and MTRRs control the - caching behaviour. - Hopefully a full PAT implementation will fix that soon. */ - return 0; -#elif defined(CONFIG_IA64) +#if defined(CONFIG_IA64) /* * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases. */ @@ -108,6 +79,36 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) } #endif +#ifdef CONFIG_NONPROMISC_DEVMEM +static inline int range_is_allowed(unsigned long pfn, unsigned long size) +{ + u64 from = ((u64)pfn) << PAGE_SHIFT; + u64 to = from + size; + u64 cursor = from; + + while (cursor < to) { + if (!devmem_is_allowed(pfn)) { + printk(KERN_INFO + "Program %s tried to access /dev/mem between %Lx->%Lx.\n", + current->comm, from, to); + return 0; + } + cursor += PAGE_SIZE; + pfn++; + } + return 1; +} +#else +static inline int range_is_allowed(unsigned long pfn, unsigned long size) +{ + return 1; +} +#endif + +void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr) +{ +} + /* * This funcion reads the *physical* memory. The f_pos points directly to the * memory location. @@ -150,15 +151,25 @@ static ssize_t read_mem(struct file * file, char __user * buf, sz = min_t(unsigned long, sz, count); + if (!range_is_allowed(p >> PAGE_SHIFT, count)) + return -EPERM; + /* * On ia64 if a page has been mapped somewhere as * uncached, then it must also be accessed uncached * by the kernel or data corruption may occur */ ptr = xlate_dev_mem_ptr(p); + if (!ptr) + return -EFAULT; - if (copy_to_user(buf, ptr, sz)) + if (copy_to_user(buf, ptr, sz)) { + unxlate_dev_mem_ptr(p, ptr); return -EFAULT; + } + + unxlate_dev_mem_ptr(p, ptr); + buf += sz; p += sz; count -= sz; @@ -207,20 +218,32 @@ static ssize_t write_mem(struct file * file, const char __user * buf, sz = min_t(unsigned long, sz, count); + if (!range_is_allowed(p >> PAGE_SHIFT, sz)) + return -EPERM; + /* * On ia64 if a page has been mapped somewhere as * uncached, then it must also be accessed uncached * by the kernel or data corruption may occur */ ptr = xlate_dev_mem_ptr(p); + if (!ptr) { + if (written) + break; + return -EFAULT; + } copied = copy_from_user(ptr, buf, sz); if (copied) { written += sz - copied; + unxlate_dev_mem_ptr(p, ptr); if (written) break; return -EFAULT; } + + unxlate_dev_mem_ptr(p, ptr); + buf += sz; p += sz; count -= sz; @@ -231,6 +254,12 @@ static ssize_t write_mem(struct file * file, const char __user * buf, return written; } +int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file, + unsigned long pfn, unsigned long size, pgprot_t *vma_prot) +{ + return 1; +} + #ifndef __HAVE_PHYS_MEM_ACCESS_PROT static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, pgprot_t vma_prot) @@ -271,6 +300,35 @@ static inline int private_mapping_ok(struct vm_area_struct *vma) } #endif +void __attribute__((weak)) +map_devmem(unsigned long pfn, unsigned long len, pgprot_t prot) +{ + /* nothing. architectures can override. */ +} + +void __attribute__((weak)) +unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t prot) +{ + /* nothing. architectures can override. */ +} + +static void mmap_mem_open(struct vm_area_struct *vma) +{ + map_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start, + vma->vm_page_prot); +} + +static void mmap_mem_close(struct vm_area_struct *vma) +{ + unmap_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start, + vma->vm_page_prot); +} + +static struct vm_operations_struct mmap_mem_ops = { + .open = mmap_mem_open, + .close = mmap_mem_close +}; + static int mmap_mem(struct file * file, struct vm_area_struct * vma) { size_t size = vma->vm_end - vma->vm_start; @@ -281,17 +339,28 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) if (!private_mapping_ok(vma)) return -ENOSYS; + if (!range_is_allowed(vma->vm_pgoff, size)) + return -EPERM; + + if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size, + &vma->vm_page_prot)) + return -EINVAL; + vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, size, vma->vm_page_prot); + vma->vm_ops = &mmap_mem_ops; + /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, size, - vma->vm_page_prot)) + vma->vm_page_prot)) { + unmap_devmem(vma->vm_pgoff, size, vma->vm_page_prot); return -EAGAIN; + } return 0; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index a39101feb2e..4d058dadbfc 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -232,9 +232,8 @@ int misc_register(struct miscdevice * misc) } /** - * __misc_deregister - unregister a miscellaneous device + * misc_deregister - unregister a miscellaneous device * @misc: device to unregister - * @suspended: to be set if the function is used during suspend/resume * * Unregister a miscellaneous device that was previously * successfully registered with misc_register(). Success @@ -242,7 +241,7 @@ int misc_register(struct miscdevice * misc) * indicates an error. */ -int __misc_deregister(struct miscdevice *misc, bool suspended) +int misc_deregister(struct miscdevice *misc) { int i = misc->minor; @@ -251,11 +250,7 @@ int __misc_deregister(struct miscdevice *misc, bool suspended) mutex_lock(&misc_mtx); list_del(&misc->list); - if (suspended) - destroy_suspended_device(misc_class, - MKDEV(MISC_MAJOR, misc->minor)); - else - device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); + device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); if (i < DYNAMIC_MINORS && i>0) { misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); } @@ -264,7 +259,7 @@ int __misc_deregister(struct miscdevice *misc, bool suspended) } EXPORT_SYMBOL(misc_register); -EXPORT_SYMBOL(__misc_deregister); +EXPORT_SYMBOL(misc_deregister); static int __init misc_init(void) { diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 82bcfb9c839..06803ed5568 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -501,7 +501,7 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, __FILE__,__LINE__, count); /* This can happen if stuff comes in on the backup tty */ - if (n_hdlc == 0 || tty != n_hdlc->tty) + if (!n_hdlc || tty != n_hdlc->tty) return; /* verify line is using HDLC discipline */ diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 46b2a1cc8b5..0c09409fa45 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -1183,7 +1183,7 @@ static int copy_from_read_buf(struct tty_struct *tty, return retval; } -extern ssize_t redirected_tty_write(struct file *, const char *, +extern ssize_t redirected_tty_write(struct file *, const char __user *, size_t, loff_t *); /** diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index dfaab2322de..6a6843a0a67 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -190,6 +190,14 @@ enum card_type { F32_8 = 8192, /* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */ }; +/* Initialization states a card can be in */ +enum card_state { + NOZOMI_STATE_UKNOWN = 0, + NOZOMI_STATE_ENABLED = 1, /* pci device enabled */ + NOZOMI_STATE_ALLOCATED = 2, /* config setup done */ + NOZOMI_STATE_READY = 3, /* flowcontrols received */ +}; + /* Two different toggle channels exist */ enum channel_type { CH_A = 0, @@ -385,6 +393,7 @@ struct nozomi { spinlock_t spin_mutex; /* secures access to registers and tty */ unsigned int index_start; + enum card_state state; u32 open_ttys; }; @@ -429,7 +438,7 @@ static void read_mem32(u32 *buf, const void __iomem *mem_addr_start, u32 size_bytes) { u32 i = 0; - const u32 *ptr = (__force u32 *) mem_addr_start; + const u32 __iomem *ptr = mem_addr_start; u16 *buf16; if (unlikely(!ptr || !buf)) @@ -439,11 +448,11 @@ static void read_mem32(u32 *buf, const void __iomem *mem_addr_start, switch (size_bytes) { case 2: /* 2 bytes */ buf16 = (u16 *) buf; - *buf16 = __le16_to_cpu(readw((void __iomem *)ptr)); + *buf16 = __le16_to_cpu(readw(ptr)); goto out; break; case 4: /* 4 bytes */ - *(buf) = __le32_to_cpu(readl((void __iomem *)ptr)); + *(buf) = __le32_to_cpu(readl(ptr)); goto out; break; } @@ -452,11 +461,11 @@ static void read_mem32(u32 *buf, const void __iomem *mem_addr_start, if (size_bytes - i == 2) { /* Handle 2 bytes in the end */ buf16 = (u16 *) buf; - *(buf16) = __le16_to_cpu(readw((void __iomem *)ptr)); + *(buf16) = __le16_to_cpu(readw(ptr)); i += 2; } else { /* Read 4 bytes */ - *(buf) = __le32_to_cpu(readl((void __iomem *)ptr)); + *(buf) = __le32_to_cpu(readl(ptr)); i += 4; } buf++; @@ -475,7 +484,7 @@ static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf, u32 size_bytes) { u32 i = 0; - u32 *ptr = (__force u32 *) mem_addr_start; + u32 __iomem *ptr = mem_addr_start; const u16 *buf16; if (unlikely(!ptr || !buf)) @@ -485,7 +494,7 @@ static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf, switch (size_bytes) { case 2: /* 2 bytes */ buf16 = (const u16 *)buf; - writew(__cpu_to_le16(*buf16), (void __iomem *)ptr); + writew(__cpu_to_le16(*buf16), ptr); return 2; break; case 1: /* @@ -493,7 +502,7 @@ static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf, * so falling through.. */ case 4: /* 4 bytes */ - writel(__cpu_to_le32(*buf), (void __iomem *)ptr); + writel(__cpu_to_le32(*buf), ptr); return 4; break; } @@ -502,11 +511,11 @@ static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf, if (size_bytes - i == 2) { /* 2 bytes */ buf16 = (const u16 *)buf; - writew(__cpu_to_le16(*buf16), (void __iomem *)ptr); + writew(__cpu_to_le16(*buf16), ptr); i += 2; } else { /* 4 bytes */ - writel(__cpu_to_le32(*buf), (void __iomem *)ptr); + writel(__cpu_to_le32(*buf), ptr); i += 4; } buf++; @@ -686,6 +695,7 @@ static int nozomi_read_config_table(struct nozomi *dc) dc->last_ier = dc->last_ier | CTRL_DL; writew(dc->last_ier, dc->reg_ier); + dc->state = NOZOMI_STATE_ALLOCATED; dev_info(&dc->pdev->dev, "Initialization OK!\n"); return 1; } @@ -944,6 +954,14 @@ static int receive_flow_control(struct nozomi *dc) case CTRL_APP2: port = PORT_APP2; enable_ier = APP2_DL; + if (dc->state == NOZOMI_STATE_ALLOCATED) { + /* + * After card initialization the flow control + * received for APP2 is always the last + */ + dc->state = NOZOMI_STATE_READY; + dev_info(&dc->pdev->dev, "Device READY!\n"); + } break; default: dev_err(&dc->pdev->dev, @@ -1366,22 +1384,12 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, dc->pdev = pdev; - /* Find out what card type it is */ - nozomi_get_card_type(dc); - ret = pci_enable_device(dc->pdev); if (ret) { dev_err(&pdev->dev, "Failed to enable PCI Device\n"); goto err_free; } - start = pci_resource_start(dc->pdev, 0); - if (start == 0) { - dev_err(&pdev->dev, "No I/O address for card detected\n"); - ret = -ENODEV; - goto err_disable_device; - } - ret = pci_request_regions(dc->pdev, NOZOMI_NAME); if (ret) { dev_err(&pdev->dev, "I/O address 0x%04x already in use\n", @@ -1389,6 +1397,16 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, goto err_disable_device; } + start = pci_resource_start(dc->pdev, 0); + if (start == 0) { + dev_err(&pdev->dev, "No I/O address for card detected\n"); + ret = -ENODEV; + goto err_rel_regs; + } + + /* Find out what card type it is */ + nozomi_get_card_type(dc); + dc->base_addr = ioremap(start, dc->card_type); if (!dc->base_addr) { dev_err(&pdev->dev, "Unable to map card MMIO\n"); @@ -1425,6 +1443,14 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, dc->index_start = ndev_idx * MAX_PORT; ndevs[ndev_idx] = dc; + pci_set_drvdata(pdev, dc); + + /* Enable RESET interrupt */ + dc->last_ier = RESET; + iowrite16(dc->last_ier, dc->reg_ier); + + dc->state = NOZOMI_STATE_ENABLED; + for (i = 0; i < MAX_PORT; i++) { mutex_init(&dc->port[i].tty_sem); dc->port[i].tty_open_count = 0; @@ -1433,12 +1459,6 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, &pdev->dev); } - /* Enable RESET interrupt. */ - dc->last_ier = RESET; - writew(dc->last_ier, dc->reg_ier); - - pci_set_drvdata(pdev, dc); - return 0; err_free_sbuf: @@ -1553,7 +1573,7 @@ static int ntty_open(struct tty_struct *tty, struct file *file) struct nozomi *dc = get_dc_by_tty(tty); unsigned long flags; - if (!port || !dc) + if (!port || !dc || dc->state != NOZOMI_STATE_READY) return -ENODEV; if (mutex_lock_interruptible(&port->tty_sem)) @@ -1716,6 +1736,10 @@ static int ntty_tiocmget(struct tty_struct *tty, struct file *file) static int ntty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct nozomi *dc = get_dc_by_tty(tty); + unsigned long flags; + + spin_lock_irqsave(&dc->spin_mutex, flags); if (set & TIOCM_RTS) set_rts(tty, 1); else if (clear & TIOCM_RTS) @@ -1725,6 +1749,7 @@ static int ntty_tiocmset(struct tty_struct *tty, struct file *file, set_dtr(tty, 1); else if (clear & TIOCM_DTR) set_dtr(tty, 0); + spin_unlock_irqrestore(&dc->spin_mutex, flags); return 0; } @@ -1762,7 +1787,7 @@ static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp) icount.brk = cnow.brk; icount.buf_overrun = cnow.buf_overrun; - return copy_to_user(argp, &icount, sizeof(icount)); + return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0; } static int ntty_ioctl(struct tty_struct *tty, struct file *file, diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c index ff35230058d..d793e68b3e0 100644 --- a/drivers/char/pcmcia/ipwireless/network.c +++ b/drivers/char/pcmcia/ipwireless/network.c @@ -377,13 +377,16 @@ void ipwireless_network_packet_received(struct ipw_network *network, for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) { struct ipw_tty *tty = network->associated_ttys[channel_idx][i]; + if (!tty) + continue; + /* * If it's associated with a tty (other than the RAS channel * when we're online), then send the data to that tty. The RAS * channel's data is handled above - it always goes through * ppp_generic. */ - if (tty && channel_idx == IPW_CHANNEL_RAS + if (channel_idx == IPW_CHANNEL_RAS && (network->ras_control_lines & IPW_CONTROL_LINE_DCD) != 0 && ipwireless_tty_is_modem(tty)) { diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 279ff5005ce..583356426df 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -189,20 +189,20 @@ typedef struct _mgslpc_info { u32 pending_bh; - int bh_running; - int bh_requested; + bool bh_running; + bool bh_requested; int dcd_chkcount; /* check counts to prevent */ int cts_chkcount; /* too many IRQs if a signal */ int dsr_chkcount; /* is floating */ int ri_chkcount; - int rx_enabled; - int rx_overflow; + bool rx_enabled; + bool rx_overflow; - int tx_enabled; - int tx_active; - int tx_aborting; + bool tx_enabled; + bool tx_active; + bool tx_aborting; u32 idle_mode; int if_mode; /* serial interface selection (RS-232, v.35 etc) */ @@ -216,12 +216,12 @@ typedef struct _mgslpc_info { unsigned char serial_signals; /* current serial signal states */ - char irq_occurred; /* for diagnostics use */ + bool irq_occurred; /* for diagnostics use */ char testing_irq; unsigned int init_error; /* startup error (DIAGS) */ char flag_buf[MAX_ASYNC_BUFFER_SIZE]; - BOOLEAN drop_rts_on_tx_done; + bool drop_rts_on_tx_done; struct _input_signal_events input_signal_events; @@ -402,8 +402,8 @@ static void hdlcdev_exit(MGSLPC_INFO *info); static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit); -static BOOLEAN register_test(MGSLPC_INFO *info); -static BOOLEAN irq_test(MGSLPC_INFO *info); +static bool register_test(MGSLPC_INFO *info); +static bool irq_test(MGSLPC_INFO *info); static int adapter_test(MGSLPC_INFO *info); static int claim_resources(MGSLPC_INFO *info); @@ -411,7 +411,7 @@ static void release_resources(MGSLPC_INFO *info); static void mgslpc_add_device(MGSLPC_INFO *info); static void mgslpc_remove_device(MGSLPC_INFO *info); -static int rx_get_frame(MGSLPC_INFO *info); +static bool rx_get_frame(MGSLPC_INFO *info); static void rx_reset_buffers(MGSLPC_INFO *info); static int rx_alloc_buffers(MGSLPC_INFO *info); static void rx_free_buffers(MGSLPC_INFO *info); @@ -719,7 +719,7 @@ static int mgslpc_resume(struct pcmcia_device *link) } -static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, +static inline bool mgslpc_paranoia_check(MGSLPC_INFO *info, char *name, const char *routine) { #ifdef MGSLPC_PARANOIA_CHECK @@ -730,17 +730,17 @@ static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, if (!info) { printk(badinfo, name, routine); - return 1; + return true; } if (info->magic != MGSLPC_MAGIC) { printk(badmagic, name, routine); - return 1; + return true; } #else if (!info) - return 1; + return true; #endif - return 0; + return false; } @@ -752,16 +752,16 @@ static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, #define CMD_TXEOM BIT1 // transmit end message #define CMD_TXRESET BIT0 // transmit reset -static BOOLEAN wait_command_complete(MGSLPC_INFO *info, unsigned char channel) +static bool wait_command_complete(MGSLPC_INFO *info, unsigned char channel) { int i = 0; /* wait for command completion */ while (read_reg(info, (unsigned char)(channel+STAR)) & BIT2) { udelay(1); if (i++ == 1000) - return FALSE; + return false; } - return TRUE; + return true; } static void issue_command(MGSLPC_INFO *info, unsigned char channel, unsigned char cmd) @@ -825,8 +825,8 @@ static int bh_action(MGSLPC_INFO *info) if (!rc) { /* Mark BH routine as complete */ - info->bh_running = 0; - info->bh_requested = 0; + info->bh_running = false; + info->bh_requested = false; } spin_unlock_irqrestore(&info->lock,flags); @@ -846,7 +846,7 @@ static void bh_handler(struct work_struct *work) printk( "%s(%d):bh_handler(%s) entry\n", __FILE__,__LINE__,info->device_name); - info->bh_running = 1; + info->bh_running = true; while((action = bh_action(info)) != 0) { @@ -913,7 +913,7 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom) /* no more free buffers */ issue_command(info, CHA, CMD_RXRESET); info->pending_bh |= BH_RECEIVE; - info->rx_overflow = 1; + info->rx_overflow = true; info->icount.buf_overrun++; return; } @@ -1032,8 +1032,8 @@ static void tx_done(MGSLPC_INFO *info) if (!info->tx_active) return; - info->tx_active = 0; - info->tx_aborting = 0; + info->tx_active = false; + info->tx_aborting = false; if (info->params.mode == MGSL_MODE_ASYNC) return; @@ -1047,7 +1047,7 @@ static void tx_done(MGSLPC_INFO *info) info->serial_signals &= ~SerialSignal_RTS; set_signals(info); } - info->drop_rts_on_tx_done = 0; + info->drop_rts_on_tx_done = false; } #if SYNCLINK_GENERIC_HDLC @@ -1081,7 +1081,7 @@ static void tx_ready(MGSLPC_INFO *info) return; } if (!info->tx_count) - info->tx_active = 0; + info->tx_active = false; } if (!info->tx_count) @@ -1225,17 +1225,15 @@ static void ri_change(MGSLPC_INFO *info) * irq interrupt number that caused interrupt * dev_id device ID supplied during interrupt registration */ -static irqreturn_t mgslpc_isr(int irq, void *dev_id) +static irqreturn_t mgslpc_isr(int dummy, void *dev_id) { - MGSLPC_INFO * info = (MGSLPC_INFO *)dev_id; + MGSLPC_INFO *info = dev_id; unsigned short isr; unsigned char gis, pis; int count=0; if (debug_level >= DEBUG_LEVEL_ISR) - printk("mgslpc_isr(%d) entry.\n", irq); - if (!info) - return IRQ_NONE; + printk("mgslpc_isr(%d) entry.\n", info->irq_level); if (!(info->p_dev->_locked)) return IRQ_HANDLED; @@ -1263,7 +1261,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id) { isr = read_reg16(info, CHA + ISR); if (isr & IRQ_TIMER) { - info->irq_occurred = 1; + info->irq_occurred = true; irq_disable(info, CHA, IRQ_TIMER); } @@ -1320,14 +1318,14 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id) printk("%s(%d):%s queueing bh task.\n", __FILE__,__LINE__,info->device_name); schedule_work(&info->task); - info->bh_requested = 1; + info->bh_requested = true; } spin_unlock(&info->lock); if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):mgslpc_isr(%d)exit.\n", - __FILE__,__LINE__,irq); + __FILE__, __LINE__, info->irq_level); return IRQ_HANDLED; } @@ -1992,7 +1990,7 @@ static int tx_abort(MGSLPC_INFO * info) * This results in underrun and abort transmission. */ info->tx_count = info->tx_put = info->tx_get = 0; - info->tx_aborting = TRUE; + info->tx_aborting = true; } spin_unlock_irqrestore(&info->lock,flags); return 0; @@ -2591,7 +2589,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, { DECLARE_WAITQUEUE(wait, current); int retval; - int do_clocal = 0, extra_count = 0; + bool do_clocal = false; + bool extra_count = false; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -2606,7 +2605,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, } if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; + do_clocal = true; /* Wait for carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -2624,7 +2623,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, spin_lock_irqsave(&info->lock, flags); if (!tty_hung_up_p(filp)) { - extra_count = 1; + extra_count = true; info->count--; } spin_unlock_irqrestore(&info->lock, flags); @@ -3495,8 +3494,8 @@ static void rx_stop(MGSLPC_INFO *info) /* MODE:03 RAC Receiver Active, 0=inactive */ clear_reg_bits(info, CHA + MODE, BIT3); - info->rx_enabled = 0; - info->rx_overflow = 0; + info->rx_enabled = false; + info->rx_overflow = false; } static void rx_start(MGSLPC_INFO *info) @@ -3506,13 +3505,13 @@ static void rx_start(MGSLPC_INFO *info) __FILE__,__LINE__, info->device_name ); rx_reset_buffers(info); - info->rx_enabled = 0; - info->rx_overflow = 0; + info->rx_enabled = false; + info->rx_overflow = false; /* MODE:03 RAC Receiver Active, 1=active */ set_reg_bits(info, CHA + MODE, BIT3); - info->rx_enabled = 1; + info->rx_enabled = true; } static void tx_start(MGSLPC_INFO *info) @@ -3525,24 +3524,24 @@ static void tx_start(MGSLPC_INFO *info) /* If auto RTS enabled and RTS is inactive, then assert */ /* RTS and set a flag indicating that the driver should */ /* negate RTS when the transmission completes. */ - info->drop_rts_on_tx_done = 0; + info->drop_rts_on_tx_done = false; if (info->params.flags & HDLC_FLAG_AUTO_RTS) { get_signals(info); if (!(info->serial_signals & SerialSignal_RTS)) { info->serial_signals |= SerialSignal_RTS; set_signals(info); - info->drop_rts_on_tx_done = 1; + info->drop_rts_on_tx_done = true; } } if (info->params.mode == MGSL_MODE_ASYNC) { if (!info->tx_active) { - info->tx_active = 1; + info->tx_active = true; tx_ready(info); } } else { - info->tx_active = 1; + info->tx_active = true; tx_ready(info); mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000)); @@ -3550,7 +3549,7 @@ static void tx_start(MGSLPC_INFO *info) } if (!info->tx_enabled) - info->tx_enabled = 1; + info->tx_enabled = true; } static void tx_stop(MGSLPC_INFO *info) @@ -3561,8 +3560,8 @@ static void tx_stop(MGSLPC_INFO *info) del_timer(&info->tx_timer); - info->tx_enabled = 0; - info->tx_active = 0; + info->tx_enabled = false; + info->tx_active = false; } /* Reset the adapter to a known state and prepare it for further use. @@ -3862,19 +3861,19 @@ static void rx_reset_buffers(MGSLPC_INFO *info) /* Attempt to return a received HDLC frame * Only frames received without errors are returned. * - * Returns 1 if frame returned, otherwise 0 + * Returns true if frame returned, otherwise false */ -static int rx_get_frame(MGSLPC_INFO *info) +static bool rx_get_frame(MGSLPC_INFO *info) { unsigned short status; RXBUF *buf; unsigned int framesize = 0; unsigned long flags; struct tty_struct *tty = info->tty; - int return_frame = 0; + bool return_frame = false; if (info->rx_frame_count == 0) - return 0; + return false; buf = (RXBUF*)(info->rx_buf + (info->rx_get * info->rx_buf_size)); @@ -3893,7 +3892,7 @@ static int rx_get_frame(MGSLPC_INFO *info) else if (!(status & BIT5)) { info->icount.rxcrc++; if (info->params.crc_type & HDLC_CRC_RETURN_EX) - return_frame = 1; + return_frame = true; } framesize = 0; #if SYNCLINK_GENERIC_HDLC @@ -3904,7 +3903,7 @@ static int rx_get_frame(MGSLPC_INFO *info) } #endif } else - return_frame = 1; + return_frame = true; if (return_frame) framesize = buf->count; @@ -3947,16 +3946,16 @@ static int rx_get_frame(MGSLPC_INFO *info) info->rx_get = 0; spin_unlock_irqrestore(&info->lock,flags); - return 1; + return true; } -static BOOLEAN register_test(MGSLPC_INFO *info) +static bool register_test(MGSLPC_INFO *info) { static unsigned char patterns[] = { 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f }; static unsigned int count = ARRAY_SIZE(patterns); unsigned int i; - BOOLEAN rc = TRUE; + bool rc = true; unsigned long flags; spin_lock_irqsave(&info->lock,flags); @@ -3967,7 +3966,7 @@ static BOOLEAN register_test(MGSLPC_INFO *info) write_reg(info, XAD2, patterns[(i + 1) % count]); if ((read_reg(info, XAD1) != patterns[i]) || (read_reg(info, XAD2) != patterns[(i + 1) % count])) { - rc = FALSE; + rc = false; break; } } @@ -3976,7 +3975,7 @@ static BOOLEAN register_test(MGSLPC_INFO *info) return rc; } -static BOOLEAN irq_test(MGSLPC_INFO *info) +static bool irq_test(MGSLPC_INFO *info) { unsigned long end_time; unsigned long flags; @@ -3984,10 +3983,10 @@ static BOOLEAN irq_test(MGSLPC_INFO *info) spin_lock_irqsave(&info->lock,flags); reset_device(info); - info->testing_irq = TRUE; + info->testing_irq = true; hdlc_mode(info); - info->irq_occurred = FALSE; + info->irq_occurred = false; /* init hdlc mode */ @@ -4002,13 +4001,13 @@ static BOOLEAN irq_test(MGSLPC_INFO *info) msleep_interruptible(10); } - info->testing_irq = FALSE; + info->testing_irq = false; spin_lock_irqsave(&info->lock,flags); reset_device(info); spin_unlock_irqrestore(&info->lock,flags); - return info->irq_occurred ? TRUE : FALSE; + return info->irq_occurred; } static int adapter_test(MGSLPC_INFO *info) @@ -4081,7 +4080,7 @@ static void tx_timeout(unsigned long context) info->icount.txtimeout++; } spin_lock_irqsave(&info->lock,flags); - info->tx_active = 0; + info->tx_active = false; info->tx_count = info->tx_put = info->tx_get = 0; spin_unlock_irqrestore(&info->lock,flags); diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index eca2b95343e..d956dd31600 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c @@ -35,7 +35,6 @@ #include <linux/termios.h> #include <linux/serial.h> #include <linux/vmalloc.h> -#include <asm/semaphore.h> #include <linux/generic_serial.h> #include <linux/errno.h> #include <linux/interrupt.h> diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 7321d002c34..bf36959fc12 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -41,7 +41,6 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; #include <asm/io.h> #include <asm/system.h> #include <asm/string.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <linux/termios.h> diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index 7ce77619707..d8eb2bcbe01 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c @@ -40,7 +40,6 @@ static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3"; #include <asm/io.h> #include <asm/system.h> #include <asm/string.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <linux/termios.h> diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index 0794844369d..add1718295e 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -40,7 +40,6 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3"; #include <asm/io.h> #include <asm/system.h> #include <asm/string.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <linux/termios.h> diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c index ebc76342712..4734e26e1cc 100644 --- a/drivers/char/rio/riointr.c +++ b/drivers/char/rio/riointr.c @@ -42,7 +42,6 @@ static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2"; #include <asm/io.h> #include <asm/system.h> #include <asm/string.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <linux/termios.h> diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c index bb498d24adc..da276ed57b3 100644 --- a/drivers/char/rio/rioparam.c +++ b/drivers/char/rio/rioparam.c @@ -41,7 +41,6 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; #include <asm/io.h> #include <asm/system.h> #include <asm/string.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <linux/termios.h> diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c index a99f3d9d7d6..7a9df7dcf9a 100644 --- a/drivers/char/rio/rioroute.c +++ b/drivers/char/rio/rioroute.c @@ -39,7 +39,6 @@ static char *_rioroute_c_sccs_ = "@(#)rioroute.c 1.3"; #include <asm/io.h> #include <asm/system.h> #include <asm/string.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <linux/termios.h> @@ -527,7 +526,7 @@ void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit) ** If RTA is not powered on, the tx packets will be ** unset, so go no further. */ - if (PortP->TxStart == 0) { + if (!PortP->TxStart) { rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n"); rio_spin_unlock_irqrestore(&PortP->portSem, flags); break; diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c index 991119c9f47..2b24488e95f 100644 --- a/drivers/char/rio/riotable.c +++ b/drivers/char/rio/riotable.c @@ -42,7 +42,6 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2"; #include <asm/io.h> #include <asm/system.h> #include <asm/string.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <linux/termios.h> @@ -425,8 +424,10 @@ int RIOApel(struct rio_info *p) MapP = &p->RIOConnectTable[Next++]; MapP->HostUniqueNum = HostP->UniqueNum; - if ((HostP->Flags & RUN_STATE) != RC_RUNNING) + if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { + rio_spin_unlock_irqrestore(&HostP->HostLock, flags); continue; + } MapP->RtaUniqueNum = 0; MapP->ID = 0; MapP->Flags = SLOT_IN_USE; diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c index a4f0b1e3e7f..1cb8580a161 100644 --- a/drivers/char/rio/riotty.c +++ b/drivers/char/rio/riotty.c @@ -44,7 +44,6 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3"; #include <asm/io.h> #include <asm/system.h> #include <asm/string.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <linux/termios.h> @@ -319,6 +318,7 @@ int riotopen(struct tty_struct *tty, struct file *filp) PortP->State |= RIO_WOPEN; rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { + rio_spin_lock_irqsave(&PortP->portSem, flags); /* ** ACTION: verify that this is a good thing ** to do here. -- ??? @@ -334,6 +334,7 @@ int riotopen(struct tty_struct *tty, struct file *filp) func_exit(); return -EINTR; } + rio_spin_lock_irqsave(&PortP->portSem, flags); } PortP->State &= ~RIO_WOPEN; } @@ -493,6 +494,7 @@ int riotclose(void *ptr) if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) { RIOPreemptiveCmd(p, PortP, FCLOSE); + rio_spin_lock_irqsave(&PortP->portSem, flags); goto close_end; } @@ -508,6 +510,7 @@ int riotclose(void *ptr) if (p->RIOHalted) { RIOClearUp(PortP); + rio_spin_lock_irqsave(&PortP->portSem, flags); goto close_end; } if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 8fc4fe4e38f..3f9d0a9ac36 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1620,14 +1620,8 @@ static int __init rc_init_drivers(void) static void rc_release_drivers(void) { - unsigned long flags; - - spin_lock_irqsave(&riscom_lock, flags); - tty_unregister_driver(riscom_driver); put_tty_driver(riscom_driver); - - spin_unlock_irqrestore(&riscom_lock, flags); } #ifndef MODULE @@ -1715,7 +1709,7 @@ static int __init riscom8_init_module (void) if (iobase || iobase1 || iobase2 || iobase3) { for(i = 0; i < RC_NBOARD; i++) - rc_board[0].base = 0; + rc_board[i].base = 0; } if (iobase) diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 72f289279d8..f585bc8579e 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -83,6 +83,7 @@ #include <linux/pci.h> #include <asm/uaccess.h> #include <asm/atomic.h> +#include <asm/unaligned.h> #include <linux/bitops.h> #include <linux/spinlock.h> #include <linux/init.h> @@ -1312,7 +1313,7 @@ static int rp_tiocmset(struct tty_struct *tty, struct file *file, if (clear & TIOCM_DTR) info->channel.TxControl[3] &= ~SET_DTR; - sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0])); + out32(info->channel.IndexAddr, info->channel.TxControl); return 0; } @@ -1748,7 +1749,7 @@ static int rp_write(struct tty_struct *tty, /* Write remaining data into the port's xmit_buf */ while (1) { - if (info->tty == 0) /* Seemingly obligatory check... */ + if (!info->tty) /* Seemingly obligatory check... */ goto end; c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head)); @@ -2798,7 +2799,7 @@ static int sReadAiopNumChan(WordIO_t io) static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 }; /* write to chan 0 SRAM */ - sOutDW((DWordIO_t) io + _INDX_ADDR, *((DWord_t *) & R[0])); + out32((DWordIO_t) io + _INDX_ADDR, R); sOutW(io + _INDX_ADDR, 0); /* read from SRAM, chan 0 */ x = sInW(io + _INDX_DATA); sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */ @@ -2864,7 +2865,7 @@ static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, R[1] = RData[i + 1] + 0x10 * ChanNum; R[2] = RData[i + 2]; R[3] = RData[i + 3]; - sOutDW(ChP->IndexAddr, *((DWord_t *) & R[0])); + out32(ChP->IndexAddr, R); } ChR = ChP->R; @@ -2887,43 +2888,43 @@ static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8); ChP->BaudDiv[2] = (Byte_t) brd9600; ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->BaudDiv[0]); + out32(ChP->IndexAddr, ChP->BaudDiv); ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL); ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8); ChP->TxControl[2] = 0; ChP->TxControl[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]); + out32(ChP->IndexAddr, ChP->TxControl); ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL); ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8); ChP->RxControl[2] = 0; ChP->RxControl[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]); + out32(ChP->IndexAddr, ChP->RxControl); ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS); ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8); ChP->TxEnables[2] = 0; ChP->TxEnables[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxEnables[0]); + out32(ChP->IndexAddr, ChP->TxEnables); ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1); ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8); ChP->TxCompare[2] = 0; ChP->TxCompare[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxCompare[0]); + out32(ChP->IndexAddr, ChP->TxCompare); ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1); ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8); ChP->TxReplace1[2] = 0; ChP->TxReplace1[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace1[0]); + out32(ChP->IndexAddr, ChP->TxReplace1); ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2); ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8); ChP->TxReplace2[2] = 0; ChP->TxReplace2[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace2[0]); + out32(ChP->IndexAddr, ChP->TxReplace2); ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; ChP->TxFIFO = ChOff + _TX_FIFO; @@ -2979,7 +2980,7 @@ static void sStopRxProcessor(CHANNEL_T * ChP) R[1] = ChP->R[1]; R[2] = 0x0a; R[3] = ChP->R[3]; - sOutDW(ChP->IndexAddr, *(DWord_t *) & R[0]); + out32(ChP->IndexAddr, R); } /*************************************************************************** @@ -3094,13 +3095,13 @@ static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data) *WordPtr = ChP->TxPrioBuf; /* data byte address */ DWBuf[2] = Data; /* data byte value */ - sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */ + out32(IndexAddr, DWBuf); /* write it out */ *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */ DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ DWBuf[3] = 0; /* priority buffer pointer */ - sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */ + out32(IndexAddr, DWBuf); /* write it out */ } else { /* write it to Tx FIFO */ sWriteTxByte(sGetTxRxDataIO(ChP), Data); @@ -3147,11 +3148,11 @@ static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags) ChP->RxControl[2] |= ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]); + out32(ChP->IndexAddr, ChP->RxControl); ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]); + out32(ChP->IndexAddr, ChP->TxControl); if (Flags & CHANINT_EN) { Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum]; @@ -3190,9 +3191,9 @@ static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags) ChP->RxControl[2] &= ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]); + out32(ChP->IndexAddr, ChP->RxControl); ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]); + out32(ChP->IndexAddr, ChP->TxControl); if (Flags & CHANINT_EN) { Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum]; diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h index f3a75791b81..b01d38125a8 100644 --- a/drivers/char/rocket_int.h +++ b/drivers/char/rocket_int.h @@ -26,7 +26,6 @@ typedef unsigned int ByteIO_t; typedef unsigned int Word_t; typedef unsigned int WordIO_t; -typedef unsigned long DWord_t; typedef unsigned int DWordIO_t; /* @@ -38,7 +37,6 @@ typedef unsigned int DWordIO_t; * instruction. */ -#ifdef ROCKET_DEBUG_IO static inline void sOutB(unsigned short port, unsigned char value) { #ifdef ROCKET_DEBUG_IO @@ -55,12 +53,13 @@ static inline void sOutW(unsigned short port, unsigned short value) outw_p(value, port); } -static inline void sOutDW(unsigned short port, unsigned long value) +static inline void out32(unsigned short port, Byte_t *p) { + u32 value = le32_to_cpu(get_unaligned((__le32 *)p)); #ifdef ROCKET_DEBUG_IO - printk(KERN_DEBUG "sOutDW(%x, %lx)...\n", port, value); + printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value); #endif - outl_p(cpu_to_le32(value), port); + outl_p(value, port); } static inline unsigned char sInB(unsigned short port) @@ -73,14 +72,6 @@ static inline unsigned short sInW(unsigned short port) return inw_p(port); } -#else /* !ROCKET_DEBUG_IO */ -#define sOutB(a, b) outb_p(b, a) -#define sOutW(a, b) outw_p(b, a) -#define sOutDW(port, value) outl_p(cpu_to_le32(value), port) -#define sInB(a) (inb_p(a)) -#define sInW(a) (inw_p(a)) -#endif /* ROCKET_DEBUG_IO */ - /* This is used to move arrays of bytes so byte swapping isn't appropriate. */ #define sOutStrW(port, addr, count) if (count) outsw(port, addr, count) #define sInStrW(port, addr, count) if (count) insw(port, addr, count) @@ -390,7 +381,7 @@ Call: sClrBreak(ChP) #define sClrBreak(ChP) \ do { \ (ChP)->TxControl[3] &= ~SETBREAK; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -402,7 +393,7 @@ Call: sClrDTR(ChP) #define sClrDTR(ChP) \ do { \ (ChP)->TxControl[3] &= ~SET_DTR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -415,7 +406,7 @@ Call: sClrRTS(ChP) do { \ if ((ChP)->rtsToggle) break; \ (ChP)->TxControl[3] &= ~SET_RTS; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -489,7 +480,7 @@ Call: sDisCTSFlowCtl(ChP) #define sDisCTSFlowCtl(ChP) \ do { \ (ChP)->TxControl[2] &= ~CTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -501,7 +492,7 @@ Call: sDisIXANY(ChP) #define sDisIXANY(ChP) \ do { \ (ChP)->R[0x0e] = 0x86; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x0c]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \ } while (0) /*************************************************************************** @@ -515,7 +506,7 @@ Comments: Function sSetParity() can be used in place of functions sEnParity(), #define sDisParity(ChP) \ do { \ (ChP)->TxControl[2] &= ~PARITY_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -527,7 +518,7 @@ Call: sDisRTSToggle(ChP) #define sDisRTSToggle(ChP) \ do { \ (ChP)->TxControl[2] &= ~RTSTOG_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ (ChP)->rtsToggle = 0; \ } while (0) @@ -540,7 +531,7 @@ Call: sDisRxFIFO(ChP) #define sDisRxFIFO(ChP) \ do { \ (ChP)->R[0x32] = 0x0a; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x30]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \ } while (0) /*************************************************************************** @@ -567,7 +558,7 @@ Call: sDisTransmit(ChP) #define sDisTransmit(ChP) \ do { \ (ChP)->TxControl[3] &= ~TX_ENABLE; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -579,7 +570,7 @@ Call: sDisTxSoftFlowCtl(ChP) #define sDisTxSoftFlowCtl(ChP) \ do { \ (ChP)->R[0x06] = 0x8a; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ } while (0) /*************************************************************************** @@ -604,7 +595,7 @@ Call: sEnCTSFlowCtl(ChP) #define sEnCTSFlowCtl(ChP) \ do { \ (ChP)->TxControl[2] |= CTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -616,7 +607,7 @@ Call: sEnIXANY(ChP) #define sEnIXANY(ChP) \ do { \ (ChP)->R[0x0e] = 0x21; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x0c]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \ } while (0) /*************************************************************************** @@ -633,7 +624,7 @@ Warnings: Before enabling parity odd or even parity should be chosen using #define sEnParity(ChP) \ do { \ (ChP)->TxControl[2] |= PARITY_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -647,10 +638,10 @@ Comments: This function will disable RTS flow control and clear the RTS #define sEnRTSToggle(ChP) \ do { \ (ChP)->RxControl[2] &= ~RTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->RxControl); \ (ChP)->TxControl[2] |= RTSTOG_EN; \ (ChP)->TxControl[3] &= ~SET_RTS; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ (ChP)->rtsToggle = 1; \ } while (0) @@ -663,7 +654,7 @@ Call: sEnRxFIFO(ChP) #define sEnRxFIFO(ChP) \ do { \ (ChP)->R[0x32] = 0x08; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x30]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \ } while (0) /*************************************************************************** @@ -684,7 +675,7 @@ Warnings: This function must be called after valid microcode has been #define sEnRxProcessor(ChP) \ do { \ (ChP)->RxControl[2] |= RXPROC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->RxControl); \ } while (0) /*************************************************************************** @@ -708,7 +699,7 @@ Call: sEnTransmit(ChP) #define sEnTransmit(ChP) \ do { \ (ChP)->TxControl[3] |= TX_ENABLE; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -720,7 +711,7 @@ Call: sEnTxSoftFlowCtl(ChP) #define sEnTxSoftFlowCtl(ChP) \ do { \ (ChP)->R[0x06] = 0xc5; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ } while (0) /*************************************************************************** @@ -927,7 +918,7 @@ Call: sSendBreak(ChP) #define sSendBreak(ChP) \ do { \ (ChP)->TxControl[3] |= SETBREAK; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -941,7 +932,7 @@ Call: sSetBaud(ChP,Divisor) do { \ (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \ (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->BaudDiv[0]); \ + out32((ChP)->IndexAddr,(ChP)->BaudDiv); \ } while (0) /*************************************************************************** @@ -953,7 +944,7 @@ Call: sSetData7(ChP) #define sSetData7(ChP) \ do { \ (ChP)->TxControl[2] &= ~DATA8BIT; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -965,7 +956,7 @@ Call: sSetData8(ChP) #define sSetData8(ChP) \ do { \ (ChP)->TxControl[2] |= DATA8BIT; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -977,7 +968,7 @@ Call: sSetDTR(ChP) #define sSetDTR(ChP) \ do { \ (ChP)->TxControl[3] |= SET_DTR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -994,7 +985,7 @@ Warnings: This function has no effect unless parity is enabled with function #define sSetEvenParity(ChP) \ do { \ (ChP)->TxControl[2] |= EVEN_PAR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1011,7 +1002,7 @@ Warnings: This function has no effect unless parity is enabled with function #define sSetOddParity(ChP) \ do { \ (ChP)->TxControl[2] &= ~EVEN_PAR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1024,7 +1015,7 @@ Call: sSetRTS(ChP) do { \ if ((ChP)->rtsToggle) break; \ (ChP)->TxControl[3] |= SET_RTS; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1050,7 +1041,7 @@ Comments: An interrupt will be generated when the trigger level is reached do { \ (ChP)->RxControl[2] &= ~TRIG_MASK; \ (ChP)->RxControl[2] |= LEVEL; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->RxControl); \ } while (0) /*************************************************************************** @@ -1062,7 +1053,7 @@ Call: sSetStop1(ChP) #define sSetStop1(ChP) \ do { \ (ChP)->TxControl[2] &= ~STOP2; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1074,7 +1065,7 @@ Call: sSetStop2(ChP) #define sSetStop2(ChP) \ do { \ (ChP)->TxControl[2] |= STOP2; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1087,7 +1078,7 @@ Call: sSetTxXOFFChar(ChP,Ch) #define sSetTxXOFFChar(ChP,CH) \ do { \ (ChP)->R[0x07] = (CH); \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ } while (0) /*************************************************************************** @@ -1100,7 +1091,7 @@ Call: sSetTxXONChar(ChP,Ch) #define sSetTxXONChar(ChP,CH) \ do { \ (ChP)->R[0x0b] = (CH); \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x08]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x08]); \ } while (0) /*************************************************************************** @@ -1113,7 +1104,7 @@ Comments: This function is used to start a Rx processor after it was will restart both the Rx processor and software input flow control. */ -#define sStartRxProcessor(ChP) sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0]) +#define sStartRxProcessor(ChP) out32((ChP)->IndexAddr,&(ChP)->R[0]) /*************************************************************************** Function: sWriteTxByte diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 78b151c4d20..e2ec2ee4cf7 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -88,6 +88,7 @@ #ifdef CONFIG_SPARC32 #include <linux/pci.h> +#include <linux/jiffies.h> #include <asm/ebus.h> static unsigned long rtc_port; @@ -110,8 +111,8 @@ static int rtc_has_irq = 1; #define hpet_set_rtc_irq_bit(arg) 0 #define hpet_rtc_timer_init() do { } while (0) #define hpet_rtc_dropped_irq() 0 -#define hpet_register_irq_handler(h) 0 -#define hpet_unregister_irq_handler(h) 0 +#define hpet_register_irq_handler(h) ({ 0; }) +#define hpet_unregister_irq_handler(h) ({ 0; }) #ifdef RTC_IRQ static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) { @@ -1316,7 +1317,8 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) * Once the read clears, read the RTC time (again via ioctl). Easy. */ - while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) + while (rtc_is_updating() != 0 && + time_before(jiffies, uip_watchdog + 2*HZ/100)) cpu_relax(); /* diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h index 8a98169b60c..4be62eda9fb 100644 --- a/drivers/char/snsc.h +++ b/drivers/char/snsc.h @@ -22,8 +22,8 @@ #include <linux/kobject.h> #include <linux/fs.h> #include <linux/cdev.h> +#include <linux/semaphore.h> #include <asm/sn/types.h> -#include <asm/semaphore.h> #define CHUNKSIZE 127 diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 921c6d2bc8f..c03ad164c39 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1147,7 +1147,7 @@ static int sonypi_acpi_remove(struct acpi_device *device, int type) return 0; } -const static struct acpi_device_id sonypi_device_ids[] = { +static const struct acpi_device_id sonypi_device_ids[] = { {"SNY6001", 0}, {"", 0}, }; diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index c0e08c7bca2..4b5b5b78acb 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -443,8 +443,7 @@ void missed_irq (unsigned long data) spin_unlock_irqrestore(&bp->lock, flags); if (irq) { printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); - sx_interrupt (((struct specialix_board *)data)->irq, - (void*)data); + sx_interrupt (-1, bp); } mod_timer(&missed_irq_timer, jiffies + sx_poll); } @@ -862,23 +861,22 @@ static inline void sx_check_modem(struct specialix_board * bp) /* The main interrupt processing routine */ -static irqreturn_t sx_interrupt(int irq, void *dev_id) +static irqreturn_t sx_interrupt(int dummy, void *dev_id) { unsigned char status; unsigned char ack; - struct specialix_board *bp; + struct specialix_board *bp = dev_id; unsigned long loop = 0; int saved_reg; unsigned long flags; func_enter(); - bp = dev_id; spin_lock_irqsave(&bp->lock, flags); dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); if (!(bp->flags & SX_BOARD_ACTIVE)) { - dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq); + dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq); spin_unlock_irqrestore(&bp->lock, flags); func_exit(); return IRQ_NONE; @@ -2109,7 +2107,6 @@ static void sx_throttle(struct tty_struct * tty) sx_out(bp, CD186x_CAR, port_No(port)); spin_unlock_irqrestore(&bp->lock, flags); if (I_IXOFF(tty)) { - spin_unlock_irqrestore(&bp->lock, flags); sx_wait_CCR(bp); spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CCR, CCR_SSCH2); diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index feac54e32a1..874aaa08e95 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -1645,7 +1645,7 @@ static irqreturn_t stl_intr(int irq, void *dev_id) { struct stlbrd *brdp = dev_id; - pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq); + pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq); return IRQ_RETVAL((* brdp->isr)(brdp)); } diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index ddc74d1f4f1..fadab1d9510 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -218,9 +218,9 @@ struct mgsl_struct { u32 pending_bh; - int bh_running; /* Protection from multiple */ + bool bh_running; /* Protection from multiple */ int isr_overflow; - int bh_requested; + bool bh_requested; int dcd_chkcount; /* check counts to prevent */ int cts_chkcount; /* too many IRQs if a signal */ @@ -250,12 +250,12 @@ struct mgsl_struct { int tx_holding_count; /* number of tx holding buffers waiting */ struct tx_holding_buffer tx_holding_buffers[MAX_TX_HOLDING_BUFFERS]; - int rx_enabled; - int rx_overflow; - int rx_rcc_underrun; + bool rx_enabled; + bool rx_overflow; + bool rx_rcc_underrun; - int tx_enabled; - int tx_active; + bool tx_enabled; + bool tx_active; u32 idle_mode; u16 cmr_value; @@ -269,14 +269,14 @@ struct mgsl_struct { unsigned int io_base; /* base I/O address of adapter */ unsigned int io_addr_size; /* size of the I/O address range */ - int io_addr_requested; /* nonzero if I/O address requested */ + bool io_addr_requested; /* true if I/O address requested */ unsigned int irq_level; /* interrupt level */ unsigned long irq_flags; - int irq_requested; /* nonzero if IRQ requested */ + bool irq_requested; /* true if IRQ requested */ unsigned int dma_level; /* DMA channel */ - int dma_requested; /* nonzero if dma channel requested */ + bool dma_requested; /* true if dma channel requested */ u16 mbre_bit; u16 loopback_bits; @@ -286,27 +286,27 @@ struct mgsl_struct { unsigned char serial_signals; /* current serial signal states */ - int irq_occurred; /* for diagnostics use */ + bool irq_occurred; /* for diagnostics use */ unsigned int init_error; /* Initialization startup error (DIAGS) */ int fDiagnosticsmode; /* Driver in Diagnostic mode? (DIAGS) */ u32 last_mem_alloc; unsigned char* memory_base; /* shared memory address (PCI only) */ u32 phys_memory_base; - int shared_mem_requested; + bool shared_mem_requested; unsigned char* lcr_base; /* local config registers (PCI only) */ u32 phys_lcr_base; u32 lcr_offset; - int lcr_mem_requested; + bool lcr_mem_requested; u32 misc_ctrl_value; char flag_buf[MAX_ASYNC_BUFFER_SIZE]; char char_buf[MAX_ASYNC_BUFFER_SIZE]; - BOOLEAN drop_rts_on_tx_done; + bool drop_rts_on_tx_done; - BOOLEAN loopmode_insert_requested; - BOOLEAN loopmode_send_done_requested; + bool loopmode_insert_requested; + bool loopmode_send_done_requested; struct _input_signal_events input_signal_events; @@ -752,10 +752,10 @@ static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int coun /* * Adapter diagnostic routines */ -static BOOLEAN mgsl_register_test( struct mgsl_struct *info ); -static BOOLEAN mgsl_irq_test( struct mgsl_struct *info ); -static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ); -static BOOLEAN mgsl_memory_test( struct mgsl_struct *info ); +static bool mgsl_register_test( struct mgsl_struct *info ); +static bool mgsl_irq_test( struct mgsl_struct *info ); +static bool mgsl_dma_test( struct mgsl_struct *info ); +static bool mgsl_memory_test( struct mgsl_struct *info ); static int mgsl_adapter_test( struct mgsl_struct *info ); /* @@ -770,8 +770,8 @@ static struct mgsl_struct* mgsl_allocate_device(void); * DMA buffer manupulation functions. */ static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ); -static int mgsl_get_rx_frame( struct mgsl_struct *info ); -static int mgsl_get_raw_rx_frame( struct mgsl_struct *info ); +static bool mgsl_get_rx_frame( struct mgsl_struct *info ); +static bool mgsl_get_raw_rx_frame( struct mgsl_struct *info ); static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ); static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ); static int num_free_tx_dma_buffers(struct mgsl_struct *info); @@ -791,7 +791,7 @@ static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info); static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info); static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info); static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info); -static int load_next_tx_holding_buffer(struct mgsl_struct *info); +static bool load_next_tx_holding_buffer(struct mgsl_struct *info); static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize); /* @@ -847,7 +847,7 @@ static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask); static int mgsl_loopmode_send_done( struct mgsl_struct * info ); /* set non-zero on successful registration with PCI subsystem */ -static int pci_registered; +static bool pci_registered; /* * Global linked list of SyncLink devices @@ -1054,8 +1054,8 @@ static int mgsl_bh_action(struct mgsl_struct *info) if (!rc) { /* Mark BH routine as complete */ - info->bh_running = 0; - info->bh_requested = 0; + info->bh_running = false; + info->bh_requested = false; } spin_unlock_irqrestore(&info->irq_spinlock,flags); @@ -1079,7 +1079,7 @@ static void mgsl_bh_handler(struct work_struct *work) printk( "%s(%d):mgsl_bh_handler(%s) entry\n", __FILE__,__LINE__,info->device_name); - info->bh_running = 1; + info->bh_running = true; while((action = mgsl_bh_action(info)) != 0) { @@ -1113,7 +1113,7 @@ static void mgsl_bh_handler(struct work_struct *work) static void mgsl_bh_receive(struct mgsl_struct *info) { - int (*get_rx_frame)(struct mgsl_struct *info) = + bool (*get_rx_frame)(struct mgsl_struct *info) = (info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame); if ( debug_level >= DEBUG_LEVEL_BH ) @@ -1187,7 +1187,7 @@ static void mgsl_isr_receive_status( struct mgsl_struct *info ) usc_loopmode_active(info) ) { ++info->icount.rxabort; - info->loopmode_insert_requested = FALSE; + info->loopmode_insert_requested = false; /* clear CMR:13 to start echoing RxD to TxD */ info->cmr_value &= ~BIT13; @@ -1257,7 +1257,7 @@ static void mgsl_isr_transmit_status( struct mgsl_struct *info ) else info->icount.txunder++; - info->tx_active = 0; + info->tx_active = false; info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; del_timer(&info->tx_timer); @@ -1267,7 +1267,7 @@ static void mgsl_isr_transmit_status( struct mgsl_struct *info ) info->serial_signals &= ~SerialSignal_RTS; usc_set_serial_signals( info ); } - info->drop_rts_on_tx_done = 0; + info->drop_rts_on_tx_done = false; } #if SYNCLINK_GENERIC_HDLC @@ -1403,7 +1403,7 @@ static void mgsl_isr_io_pin( struct mgsl_struct *info ) usc_OutReg( info, SICR, (unsigned short)(usc_InReg(info,SICR) & ~(SICR_TXC_ACTIVE+SICR_TXC_INACTIVE)) ); usc_UnlatchIostatusBits( info, MISCSTATUS_TXC_LATCHED ); - info->irq_occurred = 1; + info->irq_occurred = true; } } /* end of mgsl_isr_io_pin() */ @@ -1431,7 +1431,7 @@ static void mgsl_isr_transmit_data( struct mgsl_struct *info ) if ( info->xmit_cnt ) usc_load_txfifo( info ); else - info->tx_active = 0; + info->tx_active = false; if (info->xmit_cnt < WAKEUP_CHARS) info->pending_bh |= BH_TRANSMIT; @@ -1568,7 +1568,7 @@ static void mgsl_isr_misc( struct mgsl_struct *info ) /* schedule BH handler to restart receiver */ info->pending_bh |= BH_RECEIVE; - info->rx_rcc_underrun = 1; + info->rx_rcc_underrun = true; } usc_ClearIrqPendingBits( info, MISC ); @@ -1626,7 +1626,7 @@ static void mgsl_isr_receive_dma( struct mgsl_struct *info ) info->pending_bh |= BH_RECEIVE; if ( status & BIT3 ) { - info->rx_overflow = 1; + info->rx_overflow = true; info->icount.buf_overrun++; } @@ -1695,20 +1695,16 @@ static void mgsl_isr_transmit_dma( struct mgsl_struct *info ) * * Return Value: None */ -static irqreturn_t mgsl_interrupt(int irq, void *dev_id) +static irqreturn_t mgsl_interrupt(int dummy, void *dev_id) { - struct mgsl_struct * info; + struct mgsl_struct *info = dev_id; u16 UscVector; u16 DmaVector; if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_interrupt(%d)entry.\n", - __FILE__,__LINE__,irq); + printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)entry.\n", + __FILE__, __LINE__, info->irq_level); - info = (struct mgsl_struct *)dev_id; - if (!info) - return IRQ_NONE; - spin_lock(&info->irq_spinlock); for(;;) { @@ -1732,8 +1728,8 @@ static irqreturn_t mgsl_interrupt(int irq, void *dev_id) mgsl_isr_receive_dma(info); if ( info->isr_overflow ) { - printk(KERN_ERR"%s(%d):%s isr overflow irq=%d\n", - __FILE__,__LINE__,info->device_name, irq); + printk(KERN_ERR "%s(%d):%s isr overflow irq=%d\n", + __FILE__, __LINE__, info->device_name, info->irq_level); usc_DisableMasterIrqBit(info); usc_DisableDmaInterrupts(info,DICR_MASTER); break; @@ -1749,14 +1745,15 @@ static irqreturn_t mgsl_interrupt(int irq, void *dev_id) printk("%s(%d):%s queueing bh task.\n", __FILE__,__LINE__,info->device_name); schedule_work(&info->task); - info->bh_requested = 1; + info->bh_requested = true; } spin_unlock(&info->irq_spinlock); if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):mgsl_interrupt(%d)exit.\n", - __FILE__,__LINE__,irq); + printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)exit.\n", + __FILE__, __LINE__, info->irq_level); + return IRQ_HANDLED; } /* end of mgsl_interrupt() */ @@ -3306,7 +3303,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, { DECLARE_WAITQUEUE(wait, current); int retval; - int do_clocal = 0, extra_count = 0; + bool do_clocal = false; + bool extra_count = false; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -3320,7 +3318,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; + do_clocal = true; /* Wait for carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -3338,7 +3336,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, spin_lock_irqsave(&info->irq_spinlock, flags); if (!tty_hung_up_p(filp)) { - extra_count = 1; + extra_count = true; info->count--; } spin_unlock_irqrestore(&info->irq_spinlock, flags); @@ -4046,13 +4044,13 @@ static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info) * * info pointer to device instance data * - * Return Value: 1 if next buffered tx request loaded + * Return Value: true if next buffered tx request loaded * into adapter's tx dma buffer, - * 0 otherwise + * false otherwise */ -static int load_next_tx_holding_buffer(struct mgsl_struct *info) +static bool load_next_tx_holding_buffer(struct mgsl_struct *info) { - int ret = 0; + bool ret = false; if ( info->tx_holding_count ) { /* determine if we have enough tx dma buffers @@ -4076,7 +4074,7 @@ static int load_next_tx_holding_buffer(struct mgsl_struct *info) /* restart transmit timer */ mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000)); - ret = 1; + ret = true; } } @@ -4122,7 +4120,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) __FILE__,__LINE__,info->device_name, info->io_base); return -ENODEV; } - info->io_addr_requested = 1; + info->io_addr_requested = true; if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags, info->device_name, info ) < 0 ) { @@ -4130,7 +4128,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) __FILE__,__LINE__,info->device_name, info->irq_level ); goto errout; } - info->irq_requested = 1; + info->irq_requested = true; if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { @@ -4138,13 +4136,13 @@ static int mgsl_claim_resources(struct mgsl_struct *info) __FILE__,__LINE__,info->device_name, info->phys_memory_base); goto errout; } - info->shared_mem_requested = 1; + info->shared_mem_requested = true; if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) { printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset); goto errout; } - info->lcr_mem_requested = 1; + info->lcr_mem_requested = true; info->memory_base = ioremap(info->phys_memory_base,0x40000); if (!info->memory_base) { @@ -4175,7 +4173,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) mgsl_release_resources( info ); return -ENODEV; } - info->dma_requested = 1; + info->dma_requested = true; /* ISA adapter uses bus master DMA */ set_dma_mode(info->dma_level,DMA_MODE_CASCADE); @@ -4203,12 +4201,12 @@ static void mgsl_release_resources(struct mgsl_struct *info) if ( info->irq_requested ) { free_irq(info->irq_level, info); - info->irq_requested = 0; + info->irq_requested = false; } if ( info->dma_requested ) { disable_dma(info->dma_level); free_dma(info->dma_level); - info->dma_requested = 0; + info->dma_requested = false; } mgsl_free_dma_buffers(info); mgsl_free_intermediate_rxbuffer_memory(info); @@ -4216,15 +4214,15 @@ static void mgsl_release_resources(struct mgsl_struct *info) if ( info->io_addr_requested ) { release_region(info->io_base,info->io_addr_size); - info->io_addr_requested = 0; + info->io_addr_requested = false; } if ( info->shared_mem_requested ) { release_mem_region(info->phys_memory_base,0x40000); - info->shared_mem_requested = 0; + info->shared_mem_requested = false; } if ( info->lcr_mem_requested ) { release_mem_region(info->phys_lcr_base + info->lcr_offset,128); - info->lcr_mem_requested = 0; + info->lcr_mem_requested = false; } if (info->memory_base){ iounmap(info->memory_base); @@ -4489,7 +4487,7 @@ static int __init synclink_init(void) if ((rc = pci_register_driver(&synclink_pci_driver)) < 0) printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc); else - pci_registered = 1; + pci_registered = true; if ((rc = mgsl_init_tty()) < 0) goto error; @@ -4682,7 +4680,7 @@ static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr ) static void usc_set_sdlc_mode( struct mgsl_struct *info ) { u16 RegValue; - int PreSL1660; + bool PreSL1660; /* * determine if the IUSC on the adapter is pre-SL1660. If @@ -4695,11 +4693,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) */ usc_OutReg(info,TMCR,0x1f); RegValue=usc_InReg(info,TMDR); - if ( RegValue == IUSC_PRE_SL1660 ) - PreSL1660 = 1; - else - PreSL1660 = 0; - + PreSL1660 = (RegValue == IUSC_PRE_SL1660); if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) { @@ -5385,9 +5379,9 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info ) int start_index; int end_index; int frame_start_index; - int start_of_frame_found = FALSE; - int end_of_frame_found = FALSE; - int reprogram_dma = FALSE; + bool start_of_frame_found = false; + bool end_of_frame_found = false; + bool reprogram_dma = false; DMABUFFERENTRY *buffer_list = info->rx_buffer_list; u32 phys_addr; @@ -5413,9 +5407,9 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info ) if ( !start_of_frame_found ) { - start_of_frame_found = TRUE; + start_of_frame_found = true; frame_start_index = end_index; - end_of_frame_found = FALSE; + end_of_frame_found = false; } if ( buffer_list[end_index].status ) @@ -5426,8 +5420,8 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info ) /* We want to leave the buffers for this frame intact. */ /* Move on to next possible frame. */ - start_of_frame_found = FALSE; - end_of_frame_found = TRUE; + start_of_frame_found = false; + end_of_frame_found = true; } /* advance to next buffer entry in linked list */ @@ -5442,8 +5436,8 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info ) /* completely screwed, reset all receive buffers! */ mgsl_reset_rx_dma_buffers( info ); frame_start_index = 0; - start_of_frame_found = FALSE; - reprogram_dma = TRUE; + start_of_frame_found = false; + reprogram_dma = true; break; } } @@ -5469,7 +5463,7 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info ) } while( start_index != end_index ); - reprogram_dma = TRUE; + reprogram_dma = true; } if ( reprogram_dma ) @@ -5539,9 +5533,9 @@ static void usc_stop_receiver( struct mgsl_struct *info ) usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) ); usc_RTCmd( info, RTCmd_PurgeRxFifo ); - info->rx_enabled = 0; - info->rx_overflow = 0; - info->rx_rcc_underrun = 0; + info->rx_enabled = false; + info->rx_overflow = false; + info->rx_rcc_underrun = false; } /* end of stop_receiver() */ @@ -5604,7 +5598,7 @@ static void usc_start_receiver( struct mgsl_struct *info ) usc_OutReg( info, CCSR, 0x1020 ); - info->rx_enabled = 1; + info->rx_enabled = true; } /* end of usc_start_receiver() */ @@ -5631,14 +5625,14 @@ static void usc_start_transmitter( struct mgsl_struct *info ) /* RTS and set a flag indicating that the driver should */ /* negate RTS when the transmission completes. */ - info->drop_rts_on_tx_done = 0; + info->drop_rts_on_tx_done = false; if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) { usc_get_serial_signals( info ); if ( !(info->serial_signals & SerialSignal_RTS) ) { info->serial_signals |= SerialSignal_RTS; usc_set_serial_signals( info ); - info->drop_rts_on_tx_done = 1; + info->drop_rts_on_tx_done = true; } } @@ -5702,11 +5696,11 @@ static void usc_start_transmitter( struct mgsl_struct *info ) mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000)); } - info->tx_active = 1; + info->tx_active = true; } if ( !info->tx_enabled ) { - info->tx_enabled = 1; + info->tx_enabled = true; if ( info->params.flags & HDLC_FLAG_AUTO_CTS ) usc_EnableTransmitter(info,ENABLE_AUTO_CTS); else @@ -5738,8 +5732,8 @@ static void usc_stop_transmitter( struct mgsl_struct *info ) usc_DmaCmd( info, DmaCmd_ResetTxChannel ); usc_RTCmd( info, RTCmd_PurgeTxFifo ); - info->tx_enabled = 0; - info->tx_active = 0; + info->tx_enabled = false; + info->tx_active = false; } /* end of usc_stop_transmitter() */ @@ -6523,7 +6517,7 @@ static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ) */ static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ) { - int Done = 0; + bool Done = false; DMABUFFERENTRY *pBufEntry; unsigned int Index; @@ -6537,7 +6531,7 @@ static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int S if ( Index == EndIndex ) { /* This is the last buffer of the frame! */ - Done = 1; + Done = true; } /* reset current buffer for reuse */ @@ -6562,18 +6556,18 @@ static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int S * receive DMA buffers. Only frames received without errors are returned. * * Arguments: info pointer to device extension - * Return Value: 1 if frame returned, otherwise 0 + * Return Value: true if frame returned, otherwise false */ -static int mgsl_get_rx_frame(struct mgsl_struct *info) +static bool mgsl_get_rx_frame(struct mgsl_struct *info) { unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */ unsigned short status; DMABUFFERENTRY *pBufEntry; unsigned int framesize = 0; - int ReturnCode = 0; + bool ReturnCode = false; unsigned long flags; struct tty_struct *tty = info->tty; - int return_frame = 0; + bool return_frame = false; /* * current_rx_buffer points to the 1st buffer of the next available @@ -6632,7 +6626,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info) else { info->icount.rxcrc++; if ( info->params.crc_type & HDLC_CRC_RETURN_EX ) - return_frame = 1; + return_frame = true; } framesize = 0; #if SYNCLINK_GENERIC_HDLC @@ -6643,7 +6637,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info) } #endif } else - return_frame = 1; + return_frame = true; if ( return_frame ) { /* receive frame has no errors, get frame size. @@ -6722,7 +6716,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info) /* Free the buffers used by this frame. */ mgsl_free_rx_frame_buffers( info, StartIndex, EndIndex ); - ReturnCode = 1; + ReturnCode = true; Cleanup: @@ -6761,15 +6755,15 @@ Cleanup: * last Rx DMA buffer and return that last portion of the frame. * * Arguments: info pointer to device extension - * Return Value: 1 if frame returned, otherwise 0 + * Return Value: true if frame returned, otherwise false */ -static int mgsl_get_raw_rx_frame(struct mgsl_struct *info) +static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info) { unsigned int CurrentIndex, NextIndex; unsigned short status; DMABUFFERENTRY *pBufEntry; unsigned int framesize = 0; - int ReturnCode = 0; + bool ReturnCode = false; unsigned long flags; struct tty_struct *tty = info->tty; @@ -6894,7 +6888,7 @@ static int mgsl_get_raw_rx_frame(struct mgsl_struct *info) /* Free the buffers used by this frame. */ mgsl_free_rx_frame_buffers( info, CurrentIndex, CurrentIndex ); - ReturnCode = 1; + ReturnCode = true; } @@ -7003,15 +6997,15 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, * Performs a register test of the 16C32. * * Arguments: info pointer to device instance data - * Return Value: TRUE if test passed, otherwise FALSE + * Return Value: true if test passed, otherwise false */ -static BOOLEAN mgsl_register_test( struct mgsl_struct *info ) +static bool mgsl_register_test( struct mgsl_struct *info ) { static unsigned short BitPatterns[] = { 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f }; static unsigned int Patterncount = ARRAY_SIZE(BitPatterns); unsigned int i; - BOOLEAN rc = TRUE; + bool rc = true; unsigned long flags; spin_lock_irqsave(&info->irq_spinlock,flags); @@ -7022,10 +7016,10 @@ static BOOLEAN mgsl_register_test( struct mgsl_struct *info ) if ( (usc_InReg( info, SICR ) != 0) || (usc_InReg( info, IVR ) != 0) || (usc_InDmaReg( info, DIVR ) != 0) ){ - rc = FALSE; + rc = false; } - if ( rc == TRUE ){ + if ( rc ){ /* Write bit patterns to various registers but do it out of */ /* sync, then read back and verify values. */ @@ -7043,7 +7037,7 @@ static BOOLEAN mgsl_register_test( struct mgsl_struct *info ) (usc_InReg( info, RCLR ) != BitPatterns[(i+3)%Patterncount]) || (usc_InReg( info, RSR ) != BitPatterns[(i+4)%Patterncount]) || (usc_InDmaReg( info, TBCR ) != BitPatterns[(i+5)%Patterncount]) ){ - rc = FALSE; + rc = false; break; } } @@ -7059,9 +7053,9 @@ static BOOLEAN mgsl_register_test( struct mgsl_struct *info ) /* mgsl_irq_test() Perform interrupt test of the 16C32. * * Arguments: info pointer to device instance data - * Return Value: TRUE if test passed, otherwise FALSE + * Return Value: true if test passed, otherwise false */ -static BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) +static bool mgsl_irq_test( struct mgsl_struct *info ) { unsigned long EndTime; unsigned long flags; @@ -7071,10 +7065,10 @@ static BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) /* * Setup 16C32 to interrupt on TxC pin (14MHz clock) transition. - * The ISR sets irq_occurred to 1. + * The ISR sets irq_occurred to true. */ - info->irq_occurred = FALSE; + info->irq_occurred = false; /* Enable INTEN gate for ISA adapter (Port 6, Bit12) */ /* Enable INTEN (Port 6, Bit12) */ @@ -7100,10 +7094,7 @@ static BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) usc_reset(info); spin_unlock_irqrestore(&info->irq_spinlock,flags); - if ( !info->irq_occurred ) - return FALSE; - else - return TRUE; + return info->irq_occurred; } /* end of mgsl_irq_test() */ @@ -7114,16 +7105,16 @@ static BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) * using single buffer DMA mode. * * Arguments: info pointer to device instance data - * Return Value: TRUE if test passed, otherwise FALSE + * Return Value: true if test passed, otherwise false */ -static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) +static bool mgsl_dma_test( struct mgsl_struct *info ) { unsigned short FifoLevel; unsigned long phys_addr; unsigned int FrameSize; unsigned int i; char *TmpPtr; - BOOLEAN rc = TRUE; + bool rc = true; unsigned short status=0; unsigned long EndTime; unsigned long flags; @@ -7236,7 +7227,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) for(;;) { if (time_after(jiffies, EndTime)) { - rc = FALSE; + rc = false; break; } @@ -7292,7 +7283,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) for(;;) { if (time_after(jiffies, EndTime)) { - rc = FALSE; + rc = false; break; } @@ -7312,7 +7303,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) } - if ( rc == TRUE ) + if ( rc ) { /* Enable 16C32 transmitter. */ @@ -7340,7 +7331,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) { if (time_after(jiffies, EndTime)) { - rc = FALSE; + rc = false; break; } @@ -7351,13 +7342,13 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) } - if ( rc == TRUE ){ + if ( rc ){ /* CHECK FOR TRANSMIT ERRORS */ if ( status & (BIT5 + BIT1) ) - rc = FALSE; + rc = false; } - if ( rc == TRUE ) { + if ( rc ) { /* WAIT FOR RECEIVE COMPLETE */ /* Wait 100ms */ @@ -7367,7 +7358,7 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) status=info->rx_buffer_list[0].status; while ( status == 0 ) { if (time_after(jiffies, EndTime)) { - rc = FALSE; + rc = false; break; } status=info->rx_buffer_list[0].status; @@ -7375,17 +7366,17 @@ static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) } - if ( rc == TRUE ) { + if ( rc ) { /* CHECK FOR RECEIVE ERRORS */ status = info->rx_buffer_list[0].status; if ( status & (BIT8 + BIT3 + BIT1) ) { /* receive error has occurred */ - rc = FALSE; + rc = false; } else { if ( memcmp( info->tx_buffer_list[0].virt_addr , info->rx_buffer_list[0].virt_addr, FrameSize ) ){ - rc = FALSE; + rc = false; } } } @@ -7448,9 +7439,9 @@ static int mgsl_adapter_test( struct mgsl_struct *info ) * Test the shared memory on a PCI adapter. * * Arguments: info pointer to device instance data - * Return Value: TRUE if test passed, otherwise FALSE + * Return Value: true if test passed, otherwise false */ -static BOOLEAN mgsl_memory_test( struct mgsl_struct *info ) +static bool mgsl_memory_test( struct mgsl_struct *info ) { static unsigned long BitPatterns[] = { 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 }; @@ -7460,7 +7451,7 @@ static BOOLEAN mgsl_memory_test( struct mgsl_struct *info ) unsigned long * TestAddr; if ( info->bus_type != MGSL_BUS_TYPE_PCI ) - return TRUE; + return true; TestAddr = (unsigned long *)info->memory_base; @@ -7469,7 +7460,7 @@ static BOOLEAN mgsl_memory_test( struct mgsl_struct *info ) for ( i = 0 ; i < Patterncount ; i++ ) { *TestAddr = BitPatterns[i]; if ( *TestAddr != BitPatterns[i] ) - return FALSE; + return false; } /* Test address lines with incrementing pattern over */ @@ -7484,13 +7475,13 @@ static BOOLEAN mgsl_memory_test( struct mgsl_struct *info ) for ( i = 0 ; i < TestLimit ; i++ ) { if ( *TestAddr != i * 4 ) - return FALSE; + return false; TestAddr++; } memset( info->memory_base, 0, SHARED_MEM_ADDRESS_SIZE ); - return TRUE; + return true; } /* End Of mgsl_memory_test() */ @@ -7607,7 +7598,7 @@ static void mgsl_tx_timeout(unsigned long context) info->icount.txtimeout++; } spin_lock_irqsave(&info->irq_spinlock,flags); - info->tx_active = 0; + info->tx_active = false; info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE ) @@ -7635,7 +7626,7 @@ static int mgsl_loopmode_send_done( struct mgsl_struct * info ) spin_lock_irqsave(&info->irq_spinlock,flags); if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) { if (info->tx_active) - info->loopmode_send_done_requested = TRUE; + info->loopmode_send_done_requested = true; else usc_loopmode_send_done(info); } @@ -7649,7 +7640,7 @@ static int mgsl_loopmode_send_done( struct mgsl_struct * info ) */ static void usc_loopmode_send_done( struct mgsl_struct * info ) { - info->loopmode_send_done_requested = FALSE; + info->loopmode_send_done_requested = false; /* clear CMR:13 to 0 to start echoing RxData to TxData */ info->cmr_value &= ~BIT13; usc_OutReg(info, CMR, info->cmr_value); @@ -7671,7 +7662,7 @@ static void usc_loopmode_cancel_transmit( struct mgsl_struct * info ) */ static void usc_loopmode_insert_request( struct mgsl_struct * info ) { - info->loopmode_insert_requested = TRUE; + info->loopmode_insert_requested = true; /* enable RxAbort irq. On next RxAbort, clear CMR:13 to * begin repeating TxData on RxData (complete insertion) diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 1f954acf2ba..f3d8d72e5ea 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -117,7 +117,7 @@ static struct pci_driver pci_driver = { .remove = __devexit_p(remove_one), }; -static int pci_registered; +static bool pci_registered; /* * module configuration and status @@ -289,12 +289,12 @@ struct slgt_info { struct work_struct task; u32 pending_bh; - int bh_requested; - int bh_running; + bool bh_requested; + bool bh_running; int isr_overflow; - int irq_requested; /* nonzero if IRQ requested */ - int irq_occurred; /* for diagnostics use */ + bool irq_requested; /* true if IRQ requested */ + bool irq_occurred; /* for diagnostics use */ /* device configuration */ @@ -304,7 +304,7 @@ struct slgt_info { unsigned char __iomem * reg_addr; /* memory mapped registers address */ u32 phys_reg_addr; - int reg_addr_requested; + bool reg_addr_requested; MGSL_PARAMS params; /* communications parameters */ u32 idle_mode; @@ -315,11 +315,11 @@ struct slgt_info { /* device status */ - int rx_enabled; - int rx_restart; + bool rx_enabled; + bool rx_restart; - int tx_enabled; - int tx_active; + bool tx_enabled; + bool tx_active; unsigned char signals; /* serial signal states */ int init_error; /* initialization error */ @@ -329,7 +329,7 @@ struct slgt_info { char flag_buf[MAX_ASYNC_BUFFER_SIZE]; char char_buf[MAX_ASYNC_BUFFER_SIZE]; - BOOLEAN drop_rts_on_tx_done; + bool drop_rts_on_tx_done; struct _input_signal_events input_signal_events; int dcd_chkcount; /* check counts to prevent */ @@ -467,8 +467,8 @@ static void rx_start(struct slgt_info *info); static void reset_rbufs(struct slgt_info *info); static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last); static void rdma_reset(struct slgt_info *info); -static int rx_get_frame(struct slgt_info *info); -static int rx_get_buf(struct slgt_info *info); +static bool rx_get_frame(struct slgt_info *info); +static bool rx_get_buf(struct slgt_info *info); static void tx_start(struct slgt_info *info); static void tx_stop(struct slgt_info *info); @@ -491,7 +491,6 @@ static void isr_serial(struct slgt_info *info); static void isr_rdma(struct slgt_info *info); static void isr_txeom(struct slgt_info *info, unsigned short status); static void isr_tdma(struct slgt_info *info); -static irqreturn_t slgt_interrupt(int irq, void *dev_id); static int alloc_dma_bufs(struct slgt_info *info); static void free_dma_bufs(struct slgt_info *info); @@ -1969,8 +1968,8 @@ static int bh_action(struct slgt_info *info) rc = BH_STATUS; } else { /* Mark BH routine as complete */ - info->bh_running = 0; - info->bh_requested = 0; + info->bh_running = false; + info->bh_requested = false; rc = 0; } @@ -1989,7 +1988,7 @@ static void bh_handler(struct work_struct *work) if (!info) return; - info->bh_running = 1; + info->bh_running = true; while((action = bh_action(info))) { switch (action) { @@ -2159,7 +2158,7 @@ static void isr_serial(struct slgt_info *info) wr_reg16(info, SSR, status); /* clear pending */ - info->irq_occurred = 1; + info->irq_occurred = true; if (info->params.mode == MGSL_MODE_ASYNC) { if (status & IRQ_TXIDLE) { @@ -2226,7 +2225,7 @@ static void isr_rdma(struct slgt_info *info) if (status & (BIT5 + BIT4)) { DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name)); - info->rx_restart = 1; + info->rx_restart = true; } info->pending_bh |= BH_RECEIVE; } @@ -2277,14 +2276,14 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) info->icount.txok++; } - info->tx_active = 0; + info->tx_active = false; info->tx_count = 0; del_timer(&info->tx_timer); if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) { info->signals &= ~SerialSignal_RTS; - info->drop_rts_on_tx_done = 0; + info->drop_rts_on_tx_done = false; set_signals(info); } @@ -2326,23 +2325,19 @@ static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int * irq interrupt number * dev_id device ID supplied during interrupt registration */ -static irqreturn_t slgt_interrupt(int irq, void *dev_id) +static irqreturn_t slgt_interrupt(int dummy, void *dev_id) { - struct slgt_info *info; + struct slgt_info *info = dev_id; unsigned int gsr; unsigned int i; - DBGISR(("slgt_interrupt irq=%d entry\n", irq)); - - info = dev_id; - if (!info) - return IRQ_NONE; + DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level)); spin_lock(&info->lock); while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); - info->irq_occurred = 1; + info->irq_occurred = true; for(i=0; i < info->port_count ; i++) { if (info->port_array[i] == NULL) continue; @@ -2379,13 +2374,13 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id) !port->bh_requested) { DBGISR(("%s bh queued\n", port->device_name)); schedule_work(&port->task); - port->bh_requested = 1; + port->bh_requested = true; } } spin_unlock(&info->lock); - DBGISR(("slgt_interrupt irq=%d exit\n", irq)); + DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level)); return IRQ_HANDLED; } @@ -3115,7 +3110,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, { DECLARE_WAITQUEUE(wait, current); int retval; - int do_clocal = 0, extra_count = 0; + bool do_clocal = false; + bool extra_count = false; unsigned long flags; DBGINFO(("%s block_til_ready\n", tty->driver->name)); @@ -3127,7 +3123,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, } if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; + do_clocal = true; /* Wait for carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -3141,7 +3137,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, spin_lock_irqsave(&info->lock, flags); if (!tty_hung_up_p(filp)) { - extra_count = 1; + extra_count = true; info->count--; } spin_unlock_irqrestore(&info->lock, flags); @@ -3326,7 +3322,7 @@ static int claim_resources(struct slgt_info *info) goto errout; } else - info->reg_addr_requested = 1; + info->reg_addr_requested = true; info->reg_addr = ioremap(info->phys_reg_addr, SLGT_REG_SIZE); if (!info->reg_addr) { @@ -3346,12 +3342,12 @@ static void release_resources(struct slgt_info *info) { if (info->irq_requested) { free_irq(info->irq_level, info); - info->irq_requested = 0; + info->irq_requested = false; } if (info->reg_addr_requested) { release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE); - info->reg_addr_requested = 0; + info->reg_addr_requested = false; } if (info->reg_addr) { @@ -3516,7 +3512,7 @@ static void device_init(int adapter_num, struct pci_dev *pdev) port_array[0]->device_name, port_array[0]->irq_level)); } else { - port_array[0]->irq_requested = 1; + port_array[0]->irq_requested = true; adapter_test(port_array[0]); for (i=1 ; i < port_count ; i++) { port_array[i]->init_error = port_array[0]->init_error; @@ -3659,7 +3655,7 @@ static int __init slgt_init(void) printk("%s pci_register_driver error=%d\n", driver_name, rc); goto error; } - pci_registered = 1; + pci_registered = true; if (!slgt_device_list) printk("%s no devices found\n",driver_name); @@ -3817,8 +3813,8 @@ static void rx_stop(struct slgt_info *info) rdma_reset(info); - info->rx_enabled = 0; - info->rx_restart = 0; + info->rx_enabled = false; + info->rx_restart = false; } static void rx_start(struct slgt_info *info) @@ -3854,8 +3850,8 @@ static void rx_start(struct slgt_info *info) /* enable receiver */ wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1)); - info->rx_restart = 0; - info->rx_enabled = 1; + info->rx_restart = false; + info->rx_enabled = true; } static void tx_start(struct slgt_info *info) @@ -3863,11 +3859,11 @@ static void tx_start(struct slgt_info *info) if (!info->tx_enabled) { wr_reg16(info, TCR, (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2)); - info->tx_enabled = TRUE; + info->tx_enabled = true; } if (info->tx_count) { - info->drop_rts_on_tx_done = 0; + info->drop_rts_on_tx_done = false; if (info->params.mode != MGSL_MODE_ASYNC) { if (info->params.flags & HDLC_FLAG_AUTO_RTS) { @@ -3875,7 +3871,7 @@ static void tx_start(struct slgt_info *info) if (!(info->signals & SerialSignal_RTS)) { info->signals |= SerialSignal_RTS; set_signals(info); - info->drop_rts_on_tx_done = 1; + info->drop_rts_on_tx_done = true; } } @@ -3893,7 +3889,7 @@ static void tx_start(struct slgt_info *info) wr_reg16(info, SSR, IRQ_TXIDLE); } tdma_start(info); - info->tx_active = 1; + info->tx_active = true; } } @@ -3954,8 +3950,8 @@ static void tx_stop(struct slgt_info *info) reset_tbufs(info); - info->tx_enabled = 0; - info->tx_active = 0; + info->tx_enabled = false; + info->tx_active = false; } static void reset_port(struct slgt_info *info) @@ -4475,14 +4471,13 @@ static void reset_rbufs(struct slgt_info *info) /* * pass receive HDLC frame to upper layer * - * return 1 if frame available, otherwise 0 + * return true if frame available, otherwise false */ -static int rx_get_frame(struct slgt_info *info) +static bool rx_get_frame(struct slgt_info *info) { unsigned int start, end; unsigned short status; unsigned int framesize = 0; - int rc = 0; unsigned long flags; struct tty_struct *tty = info->tty; unsigned char addr_field = 0xff; @@ -4606,23 +4601,23 @@ check_again: } } free_rbufs(info, start, end); - rc = 1; + return true; cleanup: - return rc; + return false; } /* * pass receive buffer (RAW synchronous mode) to tty layer - * return 1 if buffer available, otherwise 0 + * return true if buffer available, otherwise false */ -static int rx_get_buf(struct slgt_info *info) +static bool rx_get_buf(struct slgt_info *info) { unsigned int i = info->rbuf_current; unsigned int count; if (!desc_complete(info->rbufs[i])) - return 0; + return false; count = desc_count(info->rbufs[i]); switch(info->params.mode) { case MGSL_MODE_MONOSYNC: @@ -4638,7 +4633,7 @@ static int rx_get_buf(struct slgt_info *info) ldisc_receive_buf(info->tty, info->rbufs[i].buf, info->flag_buf, count); free_rbufs(info, i, i); - return 1; + return true; } static void reset_tbufs(struct slgt_info *info) @@ -4763,7 +4758,7 @@ static int irq_test(struct slgt_info *info) /* assume failure */ info->init_error = DiagStatus_IrqFailure; - info->irq_occurred = FALSE; + info->irq_occurred = false; spin_unlock_irqrestore(&info->lock, flags); @@ -4896,7 +4891,7 @@ static void tx_timeout(unsigned long context) info->icount.txtimeout++; } spin_lock_irqsave(&info->lock,flags); - info->tx_active = 0; + info->tx_active = false; info->tx_count = 0; spin_unlock_irqrestore(&info->lock,flags); diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index f3e7807f78d..e98c3e6f821 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -188,9 +188,9 @@ typedef struct _synclinkmp_info { u32 pending_bh; - int bh_running; /* Protection from multiple */ + bool bh_running; /* Protection from multiple */ int isr_overflow; - int bh_requested; + bool bh_requested; int dcd_chkcount; /* check counts to prevent */ int cts_chkcount; /* too many IRQs if a signal */ @@ -213,11 +213,11 @@ typedef struct _synclinkmp_info { unsigned char *tmp_rx_buf; unsigned int tmp_rx_buf_count; - int rx_enabled; - int rx_overflow; + bool rx_enabled; + bool rx_overflow; - int tx_enabled; - int tx_active; + bool tx_enabled; + bool tx_active; u32 idle_mode; unsigned char ie0_value; @@ -238,13 +238,13 @@ typedef struct _synclinkmp_info { unsigned int irq_level; /* interrupt level */ unsigned long irq_flags; - int irq_requested; /* nonzero if IRQ requested */ + bool irq_requested; /* true if IRQ requested */ MGSL_PARAMS params; /* communications parameters */ unsigned char serial_signals; /* current serial signal states */ - int irq_occurred; /* for diagnostics use */ + bool irq_occurred; /* for diagnostics use */ unsigned int init_error; /* Initialization startup error */ u32 last_mem_alloc; @@ -255,7 +255,7 @@ typedef struct _synclinkmp_info { unsigned char* sca_base; /* HD64570 SCA Memory address */ u32 phys_sca_base; u32 sca_offset; - int sca_base_requested; + bool sca_base_requested; unsigned char* lcr_base; /* local config registers (PCI only) */ u32 phys_lcr_base; @@ -265,12 +265,12 @@ typedef struct _synclinkmp_info { unsigned char* statctrl_base; /* status/control register memory */ u32 phys_statctrl_base; u32 statctrl_offset; - int sca_statctrl_requested; + bool sca_statctrl_requested; u32 misc_ctrl_value; char flag_buf[MAX_ASYNC_BUFFER_SIZE]; char char_buf[MAX_ASYNC_BUFFER_SIZE]; - BOOLEAN drop_rts_on_tx_done; + bool drop_rts_on_tx_done; struct _input_signal_events input_signal_events; @@ -571,12 +571,12 @@ static void shutdown(SLMP_INFO *info); static void program_hw(SLMP_INFO *info); static void change_params(SLMP_INFO *info); -static int init_adapter(SLMP_INFO *info); -static int register_test(SLMP_INFO *info); -static int irq_test(SLMP_INFO *info); -static int loopback_test(SLMP_INFO *info); +static bool init_adapter(SLMP_INFO *info); +static bool register_test(SLMP_INFO *info); +static bool irq_test(SLMP_INFO *info); +static bool loopback_test(SLMP_INFO *info); static int adapter_test(SLMP_INFO *info); -static int memory_test(SLMP_INFO *info); +static bool memory_test(SLMP_INFO *info); static void reset_adapter(SLMP_INFO *info); static void reset_port(SLMP_INFO *info); @@ -587,7 +587,7 @@ static void rx_stop(SLMP_INFO *info); static void rx_start(SLMP_INFO *info); static void rx_reset_buffers(SLMP_INFO *info); static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last); -static int rx_get_frame(SLMP_INFO *info); +static bool rx_get_frame(SLMP_INFO *info); static void tx_start(SLMP_INFO *info); static void tx_stop(SLMP_INFO *info); @@ -1473,7 +1473,7 @@ static inline int line_info(char *buf, SLMP_INFO *info) /* Called to print information about devices */ -int read_proc(char *page, char **start, off_t off, int count, +static int read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = 0, l; @@ -2024,7 +2024,7 @@ static void hdlcdev_exit(SLMP_INFO *info) /* Return next bottom half action to perform. * Return Value: BH action code or 0 if nothing to do. */ -int bh_action(SLMP_INFO *info) +static int bh_action(SLMP_INFO *info) { unsigned long flags; int rc = 0; @@ -2044,8 +2044,8 @@ int bh_action(SLMP_INFO *info) if (!rc) { /* Mark BH routine as complete */ - info->bh_running = 0; - info->bh_requested = 0; + info->bh_running = false; + info->bh_requested = false; } spin_unlock_irqrestore(&info->lock,flags); @@ -2055,7 +2055,7 @@ int bh_action(SLMP_INFO *info) /* Perform bottom half processing of work items queued by ISR. */ -void bh_handler(struct work_struct *work) +static void bh_handler(struct work_struct *work) { SLMP_INFO *info = container_of(work, SLMP_INFO, task); int action; @@ -2067,7 +2067,7 @@ void bh_handler(struct work_struct *work) printk( "%s(%d):%s bh_handler() entry\n", __FILE__,__LINE__,info->device_name); - info->bh_running = 1; + info->bh_running = true; while((action = bh_action(info)) != 0) { @@ -2100,7 +2100,7 @@ void bh_handler(struct work_struct *work) __FILE__,__LINE__,info->device_name); } -void bh_receive(SLMP_INFO *info) +static void bh_receive(SLMP_INFO *info) { if ( debug_level >= DEBUG_LEVEL_BH ) printk( "%s(%d):%s bh_receive()\n", @@ -2109,7 +2109,7 @@ void bh_receive(SLMP_INFO *info) while( rx_get_frame(info) ); } -void bh_transmit(SLMP_INFO *info) +static void bh_transmit(SLMP_INFO *info) { struct tty_struct *tty = info->tty; @@ -2121,7 +2121,7 @@ void bh_transmit(SLMP_INFO *info) tty_wakeup(tty); } -void bh_status(SLMP_INFO *info) +static void bh_status(SLMP_INFO *info) { if ( debug_level >= DEBUG_LEVEL_BH ) printk( "%s(%d):%s bh_status() entry\n", @@ -2133,7 +2133,7 @@ void bh_status(SLMP_INFO *info) info->cts_chkcount = 0; } -void isr_timer(SLMP_INFO * info) +static void isr_timer(SLMP_INFO * info) { unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0; @@ -2152,14 +2152,14 @@ void isr_timer(SLMP_INFO * info) */ write_reg(info, (unsigned char)(timer + TMCS), 0); - info->irq_occurred = TRUE; + info->irq_occurred = true; if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):%s isr_timer()\n", __FILE__,__LINE__,info->device_name); } -void isr_rxint(SLMP_INFO * info) +static void isr_rxint(SLMP_INFO * info) { struct tty_struct *tty = info->tty; struct mgsl_icount *icount = &info->icount; @@ -2218,7 +2218,7 @@ void isr_rxint(SLMP_INFO * info) /* * handle async rx data interrupts */ -void isr_rxrdy(SLMP_INFO * info) +static void isr_rxrdy(SLMP_INFO * info) { u16 status; unsigned char DataByte; @@ -2232,7 +2232,7 @@ void isr_rxrdy(SLMP_INFO * info) while((status = read_reg(info,CST0)) & BIT0) { int flag = 0; - int over = 0; + bool over = false; DataByte = read_reg(info,TRB); icount->rx++; @@ -2265,7 +2265,7 @@ void isr_rxrdy(SLMP_INFO * info) * reported immediately, and doesn't * affect the current character */ - over = 1; + over = true; } } } /* end of if (error) */ @@ -2318,14 +2318,14 @@ static void isr_txeom(SLMP_INFO * info, unsigned char status) info->icount.txok++; } - info->tx_active = 0; + info->tx_active = false; info->tx_count = info->tx_put = info->tx_get = 0; del_timer(&info->tx_timer); if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done ) { info->serial_signals &= ~SerialSignal_RTS; - info->drop_rts_on_tx_done = 0; + info->drop_rts_on_tx_done = false; set_signals(info); } @@ -2348,7 +2348,7 @@ static void isr_txeom(SLMP_INFO * info, unsigned char status) /* * handle tx status interrupts */ -void isr_txint(SLMP_INFO * info) +static void isr_txint(SLMP_INFO * info) { unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS); @@ -2376,7 +2376,7 @@ void isr_txint(SLMP_INFO * info) /* * handle async tx data interrupts */ -void isr_txrdy(SLMP_INFO * info) +static void isr_txrdy(SLMP_INFO * info) { if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):%s isr_txrdy() tx_count=%d\n", @@ -2398,7 +2398,7 @@ void isr_txrdy(SLMP_INFO * info) if ( info->tx_count ) tx_load_fifo( info ); else { - info->tx_active = 0; + info->tx_active = false; info->ie0_value &= ~TXRDYE; write_reg(info, IE0, info->ie0_value); } @@ -2407,7 +2407,7 @@ void isr_txrdy(SLMP_INFO * info) info->pending_bh |= BH_TRANSMIT; } -void isr_rxdmaok(SLMP_INFO * info) +static void isr_rxdmaok(SLMP_INFO * info) { /* BIT7 = EOT (end of transfer) * BIT6 = EOM (end of message/frame) @@ -2424,7 +2424,7 @@ void isr_rxdmaok(SLMP_INFO * info) info->pending_bh |= BH_RECEIVE; } -void isr_rxdmaerror(SLMP_INFO * info) +static void isr_rxdmaerror(SLMP_INFO * info) { /* BIT5 = BOF (buffer overflow) * BIT4 = COF (counter overflow) @@ -2438,11 +2438,11 @@ void isr_rxdmaerror(SLMP_INFO * info) printk("%s(%d):%s isr_rxdmaerror(), status=%02x\n", __FILE__,__LINE__,info->device_name,status); - info->rx_overflow = TRUE; + info->rx_overflow = true; info->pending_bh |= BH_RECEIVE; } -void isr_txdmaok(SLMP_INFO * info) +static void isr_txdmaok(SLMP_INFO * info) { unsigned char status_reg1 = read_reg(info, SR1); @@ -2460,7 +2460,7 @@ void isr_txdmaok(SLMP_INFO * info) write_reg(info, IE0, info->ie0_value); } -void isr_txdmaerror(SLMP_INFO * info) +static void isr_txdmaerror(SLMP_INFO * info) { /* BIT5 = BOF (buffer overflow) * BIT4 = COF (counter overflow) @@ -2477,7 +2477,7 @@ void isr_txdmaerror(SLMP_INFO * info) /* handle input serial signal changes */ -void isr_io_pin( SLMP_INFO *info, u16 status ) +static void isr_io_pin( SLMP_INFO *info, u16 status ) { struct mgsl_icount *icount; @@ -2586,9 +2586,9 @@ void isr_io_pin( SLMP_INFO *info, u16 status ) * dev_id device ID supplied during interrupt registration * regs interrupted processor context */ -static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id) +static irqreturn_t synclinkmp_interrupt(int dummy, void *dev_id) { - SLMP_INFO * info; + SLMP_INFO *info = dev_id; unsigned char status, status0, status1=0; unsigned char dmastatus, dmastatus0, dmastatus1=0; unsigned char timerstatus0, timerstatus1=0; @@ -2597,12 +2597,8 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id) unsigned short tmp; if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d): synclinkmp_interrupt(%d)entry.\n", - __FILE__,__LINE__,irq); - - info = (SLMP_INFO *)dev_id; - if (!info) - return IRQ_NONE; + printk(KERN_DEBUG "%s(%d): synclinkmp_interrupt(%d)entry.\n", + __FILE__, __LINE__, info->irq_level); spin_lock(&info->lock); @@ -2615,9 +2611,9 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id) timerstatus0 = read_reg(info, ISR2); if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n", - __FILE__,__LINE__,info->device_name, - status0,dmastatus0,timerstatus0); + printk(KERN_DEBUG "%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n", + __FILE__, __LINE__, info->device_name, + status0, dmastatus0, timerstatus0); if (info->port_count == 4) { /* get status for SCA1 (ports 2-3) */ @@ -2695,15 +2691,15 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id) printk("%s(%d):%s queueing bh task.\n", __FILE__,__LINE__,port->device_name); schedule_work(&port->task); - port->bh_requested = 1; + port->bh_requested = true; } } spin_unlock(&info->lock); if ( debug_level >= DEBUG_LEVEL_ISR ) - printk("%s(%d):synclinkmp_interrupt(%d)exit.\n", - __FILE__,__LINE__,irq); + printk(KERN_DEBUG "%s(%d):synclinkmp_interrupt(%d)exit.\n", + __FILE__, __LINE__, info->irq_level); return IRQ_HANDLED; } @@ -3324,7 +3320,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, { DECLARE_WAITQUEUE(wait, current); int retval; - int do_clocal = 0, extra_count = 0; + bool do_clocal = false; + bool extra_count = false; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -3339,7 +3336,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, } if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; + do_clocal = true; /* Wait for carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -3357,7 +3354,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, spin_lock_irqsave(&info->lock, flags); if (!tty_hung_up_p(filp)) { - extra_count = 1; + extra_count = true; info->count--; } spin_unlock_irqrestore(&info->lock, flags); @@ -3417,7 +3414,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, return retval; } -int alloc_dma_bufs(SLMP_INFO *info) +static int alloc_dma_bufs(SLMP_INFO *info) { unsigned short BuffersPerFrame; unsigned short BufferCount; @@ -3491,7 +3488,7 @@ int alloc_dma_bufs(SLMP_INFO *info) /* Allocate DMA buffers for the transmit and receive descriptor lists. */ -int alloc_buf_list(SLMP_INFO *info) +static int alloc_buf_list(SLMP_INFO *info) { unsigned int i; @@ -3550,7 +3547,7 @@ int alloc_buf_list(SLMP_INFO *info) /* Allocate the frame DMA buffers used by the specified buffer list. */ -int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,int count) +static int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,int count) { int i; unsigned long phys_addr; @@ -3567,7 +3564,7 @@ int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex, return 0; } -void free_dma_bufs(SLMP_INFO *info) +static void free_dma_bufs(SLMP_INFO *info) { info->buffer_list = NULL; info->rx_buf_list = NULL; @@ -3577,7 +3574,7 @@ void free_dma_bufs(SLMP_INFO *info) /* allocate buffer large enough to hold max_frame_size. * This buffer is used to pass an assembled frame to the line discipline. */ -int alloc_tmp_rx_buf(SLMP_INFO *info) +static int alloc_tmp_rx_buf(SLMP_INFO *info) { info->tmp_rx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); if (info->tmp_rx_buf == NULL) @@ -3585,13 +3582,13 @@ int alloc_tmp_rx_buf(SLMP_INFO *info) return 0; } -void free_tmp_rx_buf(SLMP_INFO *info) +static void free_tmp_rx_buf(SLMP_INFO *info) { kfree(info->tmp_rx_buf); info->tmp_rx_buf = NULL; } -int claim_resources(SLMP_INFO *info) +static int claim_resources(SLMP_INFO *info) { if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) { printk( "%s(%d):%s mem addr conflict, Addr=%08X\n", @@ -3600,7 +3597,7 @@ int claim_resources(SLMP_INFO *info) goto errout; } else - info->shared_mem_requested = 1; + info->shared_mem_requested = true; if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) { printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n", @@ -3609,7 +3606,7 @@ int claim_resources(SLMP_INFO *info) goto errout; } else - info->lcr_mem_requested = 1; + info->lcr_mem_requested = true; if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) { printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n", @@ -3618,7 +3615,7 @@ int claim_resources(SLMP_INFO *info) goto errout; } else - info->sca_base_requested = 1; + info->sca_base_requested = true; if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) { printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n", @@ -3627,7 +3624,7 @@ int claim_resources(SLMP_INFO *info) goto errout; } else - info->sca_statctrl_requested = 1; + info->sca_statctrl_requested = true; info->memory_base = ioremap(info->phys_memory_base,SCA_MEM_SIZE); if (!info->memory_base) { @@ -3678,7 +3675,7 @@ errout: return -ENODEV; } -void release_resources(SLMP_INFO *info) +static void release_resources(SLMP_INFO *info) { if ( debug_level >= DEBUG_LEVEL_INFO ) printk( "%s(%d):%s release_resources() entry\n", @@ -3686,24 +3683,24 @@ void release_resources(SLMP_INFO *info) if ( info->irq_requested ) { free_irq(info->irq_level, info); - info->irq_requested = 0; + info->irq_requested = false; } if ( info->shared_mem_requested ) { release_mem_region(info->phys_memory_base,SCA_MEM_SIZE); - info->shared_mem_requested = 0; + info->shared_mem_requested = false; } if ( info->lcr_mem_requested ) { release_mem_region(info->phys_lcr_base + info->lcr_offset,128); - info->lcr_mem_requested = 0; + info->lcr_mem_requested = false; } if ( info->sca_base_requested ) { release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE); - info->sca_base_requested = 0; + info->sca_base_requested = false; } if ( info->sca_statctrl_requested ) { release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE); - info->sca_statctrl_requested = 0; + info->sca_statctrl_requested = false; } if (info->memory_base){ @@ -3734,7 +3731,7 @@ void release_resources(SLMP_INFO *info) /* Add the specified device instance data structure to the * global linked list of devices and increment the device count. */ -void add_device(SLMP_INFO *info) +static void add_device(SLMP_INFO *info) { info->next_device = NULL; info->line = synclinkmp_device_count; @@ -3857,7 +3854,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) return info; } -void device_init(int adapter_num, struct pci_dev *pdev) +static void device_init(int adapter_num, struct pci_dev *pdev) { SLMP_INFO *port_array[SCA_MAX_PORTS]; int port; @@ -3906,7 +3903,7 @@ void device_init(int adapter_num, struct pci_dev *pdev) port_array[0]->irq_level ); } else { - port_array[0]->irq_requested = 1; + port_array[0]->irq_requested = true; adapter_test(port_array[0]); } } @@ -4051,7 +4048,7 @@ module_exit(synclinkmp_exit); * The TxCLK and RxCLK signals are generated from the BRG and * the TxD is looped back to the RxD internally. */ -void enable_loopback(SLMP_INFO *info, int enable) +static void enable_loopback(SLMP_INFO *info, int enable) { if (enable) { /* MD2 (Mode Register 2) @@ -4098,7 +4095,7 @@ void enable_loopback(SLMP_INFO *info, int enable) * data_rate data rate of clock in bits per second * A data rate of 0 disables the AUX clock. */ -void set_rate( SLMP_INFO *info, u32 data_rate ) +static void set_rate( SLMP_INFO *info, u32 data_rate ) { u32 TMCValue; unsigned char BRValue; @@ -4144,7 +4141,7 @@ void set_rate( SLMP_INFO *info, u32 data_rate ) /* Disable receiver */ -void rx_stop(SLMP_INFO *info) +static void rx_stop(SLMP_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):%s rx_stop()\n", @@ -4159,13 +4156,13 @@ void rx_stop(SLMP_INFO *info) write_reg(info, RXDMA + DCMD, SWABORT); /* reset/init Rx DMA */ write_reg(info, RXDMA + DIR, 0); /* disable Rx DMA interrupts */ - info->rx_enabled = 0; - info->rx_overflow = 0; + info->rx_enabled = false; + info->rx_overflow = false; } /* enable the receiver */ -void rx_start(SLMP_INFO *info) +static void rx_start(SLMP_INFO *info) { int i; @@ -4215,14 +4212,14 @@ void rx_start(SLMP_INFO *info) write_reg(info, CMD, RXENABLE); - info->rx_overflow = FALSE; - info->rx_enabled = 1; + info->rx_overflow = false; + info->rx_enabled = true; } /* Enable the transmitter and send a transmit frame if * one is loaded in the DMA buffers. */ -void tx_start(SLMP_INFO *info) +static void tx_start(SLMP_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):%s tx_start() tx_count=%d\n", @@ -4231,7 +4228,7 @@ void tx_start(SLMP_INFO *info) if (!info->tx_enabled ) { write_reg(info, CMD, TXRESET); write_reg(info, CMD, TXENABLE); - info->tx_enabled = TRUE; + info->tx_enabled = true; } if ( info->tx_count ) { @@ -4240,7 +4237,7 @@ void tx_start(SLMP_INFO *info) /* RTS and set a flag indicating that the driver should */ /* negate RTS when the transmission completes. */ - info->drop_rts_on_tx_done = 0; + info->drop_rts_on_tx_done = false; if (info->params.mode != MGSL_MODE_ASYNC) { @@ -4249,7 +4246,7 @@ void tx_start(SLMP_INFO *info) if ( !(info->serial_signals & SerialSignal_RTS) ) { info->serial_signals |= SerialSignal_RTS; set_signals( info ); - info->drop_rts_on_tx_done = 1; + info->drop_rts_on_tx_done = true; } } @@ -4286,13 +4283,13 @@ void tx_start(SLMP_INFO *info) write_reg(info, IE0, info->ie0_value); } - info->tx_active = 1; + info->tx_active = true; } } /* stop the transmitter and DMA */ -void tx_stop( SLMP_INFO *info ) +static void tx_stop( SLMP_INFO *info ) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):%s tx_stop()\n", @@ -4312,14 +4309,14 @@ void tx_stop( SLMP_INFO *info ) info->ie0_value &= ~TXRDYE; write_reg(info, IE0, info->ie0_value); /* disable tx data interrupts */ - info->tx_enabled = 0; - info->tx_active = 0; + info->tx_enabled = false; + info->tx_active = false; } /* Fill the transmit FIFO until the FIFO is full or * there is no more data to load. */ -void tx_load_fifo(SLMP_INFO *info) +static void tx_load_fifo(SLMP_INFO *info) { u8 TwoBytes[2]; @@ -4368,7 +4365,7 @@ void tx_load_fifo(SLMP_INFO *info) /* Reset a port to a known state */ -void reset_port(SLMP_INFO *info) +static void reset_port(SLMP_INFO *info) { if (info->sca_base) { @@ -4392,7 +4389,7 @@ void reset_port(SLMP_INFO *info) /* Reset all the ports to a known state. */ -void reset_adapter(SLMP_INFO *info) +static void reset_adapter(SLMP_INFO *info) { int i; @@ -4404,7 +4401,7 @@ void reset_adapter(SLMP_INFO *info) /* Program port for asynchronous communications. */ -void async_mode(SLMP_INFO *info) +static void async_mode(SLMP_INFO *info) { unsigned char RegValue; @@ -4543,7 +4540,7 @@ void async_mode(SLMP_INFO *info) /* Program the SCA for HDLC communications. */ -void hdlc_mode(SLMP_INFO *info) +static void hdlc_mode(SLMP_INFO *info) { unsigned char RegValue; u32 DpllDivisor; @@ -4745,7 +4742,7 @@ void hdlc_mode(SLMP_INFO *info) /* Set the transmit HDLC idle mode */ -void tx_set_idle(SLMP_INFO *info) +static void tx_set_idle(SLMP_INFO *info) { unsigned char RegValue = 0xff; @@ -4765,7 +4762,7 @@ void tx_set_idle(SLMP_INFO *info) /* Query the adapter for the state of the V24 status (input) signals. */ -void get_signals(SLMP_INFO *info) +static void get_signals(SLMP_INFO *info) { u16 status = read_reg(info, SR3); u16 gpstatus = read_status_reg(info); @@ -4794,7 +4791,7 @@ void get_signals(SLMP_INFO *info) /* Set the state of DTR and RTS based on contents of * serial_signals member of device context. */ -void set_signals(SLMP_INFO *info) +static void set_signals(SLMP_INFO *info) { unsigned char RegValue; u16 EnableBit; @@ -4823,7 +4820,7 @@ void set_signals(SLMP_INFO *info) * and set the current buffer to the first buffer. This effectively * makes all buffers free and discards any data in buffers. */ -void rx_reset_buffers(SLMP_INFO *info) +static void rx_reset_buffers(SLMP_INFO *info) { rx_free_frame_buffers(info, 0, info->rx_buf_count - 1); } @@ -4834,16 +4831,16 @@ void rx_reset_buffers(SLMP_INFO *info) * first index of 1st receive buffer of frame * last index of last receive buffer of frame */ -void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last) +static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last) { - int done = 0; + bool done = false; while(!done) { /* reset current buffer for reuse */ info->rx_buf_list[first].status = 0xff; if (first == last) { - done = 1; + done = true; /* set new last rx descriptor address */ write_reg16(info, RXDMA + EDA, info->rx_buf_list_ex[first].phys_entry); } @@ -4860,14 +4857,14 @@ void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int las /* Return a received frame from the receive DMA buffers. * Only frames received without errors are returned. * - * Return Value: 1 if frame returned, otherwise 0 + * Return Value: true if frame returned, otherwise false */ -int rx_get_frame(SLMP_INFO *info) +static bool rx_get_frame(SLMP_INFO *info) { unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */ unsigned short status; unsigned int framesize = 0; - int ReturnCode = 0; + bool ReturnCode = false; unsigned long flags; struct tty_struct *tty = info->tty; unsigned char addr_field = 0xff; @@ -5018,7 +5015,7 @@ CheckAgain: /* Free the buffers used by this frame. */ rx_free_frame_buffers( info, StartIndex, EndIndex ); - ReturnCode = 1; + ReturnCode = true; Cleanup: if ( info->rx_enabled && info->rx_overflow ) { @@ -5037,7 +5034,7 @@ Cleanup: /* load the transmit DMA buffer with data */ -void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count) +static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count) { unsigned short copy_count; unsigned int i = 0; @@ -5077,12 +5074,12 @@ void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count) info->last_tx_buf = ++i; } -int register_test(SLMP_INFO *info) +static bool register_test(SLMP_INFO *info) { static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96}; static unsigned int count = ARRAY_SIZE(testval); unsigned int i; - int rc = TRUE; + bool rc = true; unsigned long flags; spin_lock_irqsave(&info->lock,flags); @@ -5105,7 +5102,7 @@ int register_test(SLMP_INFO *info) (read_reg(info, SA0) != testval[(i+2)%count]) || (read_reg(info, SA1) != testval[(i+3)%count]) ) { - rc = FALSE; + rc = false; break; } } @@ -5116,7 +5113,7 @@ int register_test(SLMP_INFO *info) return rc; } -int irq_test(SLMP_INFO *info) +static bool irq_test(SLMP_INFO *info) { unsigned long timeout; unsigned long flags; @@ -5128,7 +5125,7 @@ int irq_test(SLMP_INFO *info) /* assume failure */ info->init_error = DiagStatus_IrqFailure; - info->irq_occurred = FALSE; + info->irq_occurred = false; /* setup timer0 on SCA0 to interrupt */ @@ -5167,7 +5164,7 @@ int irq_test(SLMP_INFO *info) /* initialize individual SCA device (2 ports) */ -static int sca_init(SLMP_INFO *info) +static bool sca_init(SLMP_INFO *info) { /* set wait controller to single mem partition (low), no wait states */ write_reg(info, PABR0, 0); /* wait controller addr boundary 0 */ @@ -5203,12 +5200,12 @@ static int sca_init(SLMP_INFO *info) */ write_reg(info, ITCR, 0); - return TRUE; + return true; } /* initialize adapter hardware */ -int init_adapter(SLMP_INFO *info) +static bool init_adapter(SLMP_INFO *info) { int i; @@ -5261,20 +5258,20 @@ int init_adapter(SLMP_INFO *info) sca_init(info->port_array[0]); sca_init(info->port_array[2]); - return TRUE; + return true; } /* Loopback an HDLC frame to test the hardware * interrupt and DMA functions. */ -int loopback_test(SLMP_INFO *info) +static bool loopback_test(SLMP_INFO *info) { #define TESTFRAMESIZE 20 unsigned long timeout; u16 count = TESTFRAMESIZE; unsigned char buf[TESTFRAMESIZE]; - int rc = FALSE; + bool rc = false; unsigned long flags; struct tty_struct *oldtty = info->tty; @@ -5308,16 +5305,16 @@ int loopback_test(SLMP_INFO *info) msleep_interruptible(10); if (rx_get_frame(info)) { - rc = TRUE; + rc = true; break; } } /* verify received frame length and contents */ - if (rc == TRUE && - ( info->tmp_rx_buf_count != count || - memcmp(buf, info->tmp_rx_buf,count))) { - rc = FALSE; + if (rc && + ( info->tmp_rx_buf_count != count || + memcmp(buf, info->tmp_rx_buf,count))) { + rc = false; } spin_lock_irqsave(&info->lock,flags); @@ -5332,7 +5329,7 @@ int loopback_test(SLMP_INFO *info) /* Perform diagnostics on hardware */ -int adapter_test( SLMP_INFO *info ) +static int adapter_test( SLMP_INFO *info ) { unsigned long flags; if ( debug_level >= DEBUG_LEVEL_INFO ) @@ -5394,7 +5391,7 @@ int adapter_test( SLMP_INFO *info ) /* Test the shared memory on a PCI adapter. */ -int memory_test(SLMP_INFO *info) +static bool memory_test(SLMP_INFO *info) { static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 }; @@ -5408,7 +5405,7 @@ int memory_test(SLMP_INFO *info) for ( i = 0 ; i < count ; i++ ) { *addr = testval[i]; if ( *addr != testval[i] ) - return FALSE; + return false; } /* Test address lines with incrementing pattern over */ @@ -5423,12 +5420,12 @@ int memory_test(SLMP_INFO *info) for ( i = 0 ; i < limit ; i++ ) { if ( *addr != i * 4 ) - return FALSE; + return false; addr++; } memset( info->memory_base, 0, SCA_MEM_SIZE ); - return TRUE; + return true; } /* Load data into PCI adapter shared memory. @@ -5446,7 +5443,7 @@ int memory_test(SLMP_INFO *info) * the write transation. This allows any pending DMA request to gain control * of the local bus in a timely fasion. */ -void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count) +static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count) { /* A load interval of 16 allows for 4 32-bit writes at */ /* 136ns each for a maximum latency of 542ns on the local bus.*/ @@ -5465,7 +5462,7 @@ void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned shor memcpy(dest, src, count % sca_pci_load_interval); } -void trace_block(SLMP_INFO *info,const char* data, int count, int xmit) +static void trace_block(SLMP_INFO *info,const char* data, int count, int xmit) { int i; int linecount; @@ -5500,7 +5497,7 @@ void trace_block(SLMP_INFO *info,const char* data, int count, int xmit) /* called when HDLC frame times out * update stats and do tx completion processing */ -void tx_timeout(unsigned long context) +static void tx_timeout(unsigned long context) { SLMP_INFO *info = (SLMP_INFO*)context; unsigned long flags; @@ -5512,7 +5509,7 @@ void tx_timeout(unsigned long context) info->icount.txtimeout++; } spin_lock_irqsave(&info->lock,flags); - info->tx_active = 0; + info->tx_active = false; info->tx_count = info->tx_put = info->tx_get = 0; spin_unlock_irqrestore(&info->lock,flags); @@ -5527,7 +5524,7 @@ void tx_timeout(unsigned long context) /* called to periodically check the DSR/RI modem signal input status */ -void status_timeout(unsigned long context) +static void status_timeout(unsigned long context) { u16 status = 0; SLMP_INFO *info = (SLMP_INFO*)context; @@ -5578,36 +5575,36 @@ void status_timeout(unsigned long context) } -unsigned char read_reg(SLMP_INFO * info, unsigned char Addr) +static unsigned char read_reg(SLMP_INFO * info, unsigned char Addr) { CALC_REGADDR(); return *RegAddr; } -void write_reg(SLMP_INFO * info, unsigned char Addr, unsigned char Value) +static void write_reg(SLMP_INFO * info, unsigned char Addr, unsigned char Value) { CALC_REGADDR(); *RegAddr = Value; } -u16 read_reg16(SLMP_INFO * info, unsigned char Addr) +static u16 read_reg16(SLMP_INFO * info, unsigned char Addr) { CALC_REGADDR(); return *((u16 *)RegAddr); } -void write_reg16(SLMP_INFO * info, unsigned char Addr, u16 Value) +static void write_reg16(SLMP_INFO * info, unsigned char Addr, u16 Value) { CALC_REGADDR(); *((u16 *)RegAddr) = Value; } -unsigned char read_status_reg(SLMP_INFO * info) +static unsigned char read_status_reg(SLMP_INFO * info) { unsigned char *RegAddr = (unsigned char *)info->statctrl_base; return *RegAddr; } -void write_control_reg(SLMP_INFO * info) +static void write_control_reg(SLMP_INFO * info) { unsigned char *RegAddr = (unsigned char *)info->statctrl_base; *RegAddr = info->port_array[0]->ctrlreg_value; diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index de60e1ea4fb..1ade193c912 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -271,8 +271,7 @@ static struct sysrq_key_op sysrq_term_op = { static void moom_callback(struct work_struct *ignored) { - out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], - GFP_KERNEL, 0); + out_of_memory(node_zonelist(0, GFP_KERNEL), GFP_KERNEL, 0); } static DECLARE_WORK(moom_work, moom_callback); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 81503d94fec..13a4bdd4e4d 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -399,7 +399,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t tis_int_handler(int irq, void *dev_id) +static irqreturn_t tis_int_handler(int dummy, void *dev_id) { struct tpm_chip *chip = dev_id; u32 interrupt; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 613ec816ce6..98b65a23099 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1155,6 +1155,48 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index) return NULL; } +#ifdef CONFIG_CONSOLE_POLL + +/** + * tty_find_polling_driver - find device of a polled tty + * @name: name string to match + * @line: pointer to resulting tty line nr + * + * This routine returns a tty driver structure, given a name + * and the condition that the tty driver is capable of polled + * operation. + */ +struct tty_driver *tty_find_polling_driver(char *name, int *line) +{ + struct tty_driver *p, *res = NULL; + int tty_line = 0; + char *str; + + mutex_lock(&tty_mutex); + /* Search through the tty devices to look for a match */ + list_for_each_entry(p, &tty_drivers, tty_drivers) { + str = name + strlen(p->name); + tty_line = simple_strtoul(str, &str, 10); + if (*str == ',') + str++; + if (*str == '\0') + str = NULL; + + if (tty_line >= 0 && tty_line <= p->num && p->poll_init && + !p->poll_init(p, tty_line, str)) { + + res = p; + *line = tty_line; + break; + } + } + mutex_unlock(&tty_mutex); + + return res; +} +EXPORT_SYMBOL_GPL(tty_find_polling_driver); +#endif + /** * tty_check_change - check for POSIX terminal changes * @tty: tty to check @@ -3850,6 +3892,11 @@ void tty_set_operations(struct tty_driver *driver, driver->write_proc = op->write_proc; driver->tiocmget = op->tiocmget; driver->tiocmset = op->tiocmset; +#ifdef CONFIG_CONSOLE_POLL + driver->poll_init = op->poll_init; + driver->poll_get_char = op->poll_get_char; + driver->poll_put_char = op->poll_put_char; +#endif } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 367be917506..df4c3ead9e2 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -702,6 +702,7 @@ void redraw_screen(struct vc_data *vc, int is_switch) if (is_switch) { set_leds(); compute_shiftstate(); + notify_update(vc); } } @@ -2053,6 +2054,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co unsigned long draw_from = 0, draw_to = 0; struct vc_data *vc; unsigned char vc_attr; + struct vt_notifier_param param; uint8_t rescan; uint8_t inverse; uint8_t width; @@ -2112,6 +2114,8 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co if (IS_FG(vc)) hide_cursor(vc); + param.vc = vc; + while (!tty->stopped && count) { int orig = *buf; c = orig; @@ -2200,6 +2204,11 @@ rescan_last_byte: tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; } + param.c = tc; + if (atomic_notifier_call_chain(&vt_notifier_list, VT_PREWRITE, + ¶m) == NOTIFY_STOP) + continue; + /* If the original code was a control character we * only allow a glyph to be displayed if the code is * not normally used (such as for cursor movement) or diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c index dfea2bde162..aa7f7962a9a 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.c +++ b/drivers/char/xilinx_hwicap/buffer_icap.c @@ -73,8 +73,8 @@ #define XHI_BUFFER_START 0 /** - * buffer_icap_get_status: Get the contents of the status register. - * @parameter base_address: is the base address of the device + * buffer_icap_get_status - Get the contents of the status register. + * @drvdata: a pointer to the drvdata. * * The status register contains the ICAP status and the done bit. * @@ -88,15 +88,15 @@ * D1 - Always 1 * D0 - Done bit **/ -static inline u32 buffer_icap_get_status(void __iomem *base_address) +u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata) { - return in_be32(base_address + XHI_STATUS_REG_OFFSET); + return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET); } /** - * buffer_icap_get_bram: Reads data from the storage buffer bram. - * @parameter base_address: contains the base address of the component. - * @parameter offset: The word offset from which the data should be read. + * buffer_icap_get_bram - Reads data from the storage buffer bram. + * @base_address: contains the base address of the component. + * @offset: The word offset from which the data should be read. * * A bram is used as a configuration memory cache. One frame of data can * be stored in this "storage buffer". @@ -108,8 +108,8 @@ static inline u32 buffer_icap_get_bram(void __iomem *base_address, } /** - * buffer_icap_busy: Return true if the icap device is busy - * @parameter base_address: is the base address of the device + * buffer_icap_busy - Return true if the icap device is busy + * @base_address: is the base address of the device * * The queries the low order bit of the status register, which * indicates whether the current configuration or readback operation @@ -117,26 +117,14 @@ static inline u32 buffer_icap_get_bram(void __iomem *base_address, **/ static inline bool buffer_icap_busy(void __iomem *base_address) { - return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED; + u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET); + return (status & 1) == XHI_NOT_FINISHED; } /** - * buffer_icap_busy: Return true if the icap device is not busy - * @parameter base_address: is the base address of the device - * - * The queries the low order bit of the status register, which - * indicates whether the current configuration or readback operation - * has completed. - **/ -static inline bool buffer_icap_done(void __iomem *base_address) -{ - return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED; -} - -/** - * buffer_icap_set_size: Set the size register. - * @parameter base_address: is the base address of the device - * @parameter data: The size in bytes. + * buffer_icap_set_size - Set the size register. + * @base_address: is the base address of the device + * @data: The size in bytes. * * The size register holds the number of 8 bit bytes to transfer between * bram and the icap (or icap to bram). @@ -148,9 +136,9 @@ static inline void buffer_icap_set_size(void __iomem *base_address, } /** - * buffer_icap_mSetoffsetReg: Set the bram offset register. - * @parameter base_address: contains the base address of the device. - * @parameter data: is the value to be written to the data register. + * buffer_icap_set_offset - Set the bram offset register. + * @base_address: contains the base address of the device. + * @data: is the value to be written to the data register. * * The bram offset register holds the starting bram address to transfer * data from during configuration or write data to during readback. @@ -162,9 +150,9 @@ static inline void buffer_icap_set_offset(void __iomem *base_address, } /** - * buffer_icap_set_rnc: Set the RNC (Readback not Configure) register. - * @parameter base_address: contains the base address of the device. - * @parameter data: is the value to be written to the data register. + * buffer_icap_set_rnc - Set the RNC (Readback not Configure) register. + * @base_address: contains the base address of the device. + * @data: is the value to be written to the data register. * * The RNC register determines the direction of the data transfer. It * controls whether a configuration or readback take place. Writing to @@ -178,10 +166,10 @@ static inline void buffer_icap_set_rnc(void __iomem *base_address, } /** - * buffer_icap_set_bram: Write data to the storage buffer bram. - * @parameter base_address: contains the base address of the component. - * @parameter offset: The word offset at which the data should be written. - * @parameter data: The value to be written to the bram offset. + * buffer_icap_set_bram - Write data to the storage buffer bram. + * @base_address: contains the base address of the component. + * @offset: The word offset at which the data should be written. + * @data: The value to be written to the bram offset. * * A bram is used as a configuration memory cache. One frame of data can * be stored in this "storage buffer". @@ -193,10 +181,10 @@ static inline void buffer_icap_set_bram(void __iomem *base_address, } /** - * buffer_icap_device_read: Transfer bytes from ICAP to the storage buffer. - * @parameter drvdata: a pointer to the drvdata. - * @parameter offset: The storage buffer start address. - * @parameter count: The number of words (32 bit) to read from the + * buffer_icap_device_read - Transfer bytes from ICAP to the storage buffer. + * @drvdata: a pointer to the drvdata. + * @offset: The storage buffer start address. + * @count: The number of words (32 bit) to read from the * device (ICAP). **/ static int buffer_icap_device_read(struct hwicap_drvdata *drvdata, @@ -227,10 +215,10 @@ static int buffer_icap_device_read(struct hwicap_drvdata *drvdata, }; /** - * buffer_icap_device_write: Transfer bytes from ICAP to the storage buffer. - * @parameter drvdata: a pointer to the drvdata. - * @parameter offset: The storage buffer start address. - * @parameter count: The number of words (32 bit) to read from the + * buffer_icap_device_write - Transfer bytes from ICAP to the storage buffer. + * @drvdata: a pointer to the drvdata. + * @offset: The storage buffer start address. + * @count: The number of words (32 bit) to read from the * device (ICAP). **/ static int buffer_icap_device_write(struct hwicap_drvdata *drvdata, @@ -261,8 +249,8 @@ static int buffer_icap_device_write(struct hwicap_drvdata *drvdata, }; /** - * buffer_icap_reset: Reset the logic of the icap device. - * @parameter drvdata: a pointer to the drvdata. + * buffer_icap_reset - Reset the logic of the icap device. + * @drvdata: a pointer to the drvdata. * * Writing to the status register resets the ICAP logic in an internal * version of the core. For the version of the core published in EDK, @@ -274,10 +262,10 @@ void buffer_icap_reset(struct hwicap_drvdata *drvdata) } /** - * buffer_icap_set_configuration: Load a partial bitstream from system memory. - * @parameter drvdata: a pointer to the drvdata. - * @parameter data: Kernel address of the partial bitstream. - * @parameter size: the size of the partial bitstream in 32 bit words. + * buffer_icap_set_configuration - Load a partial bitstream from system memory. + * @drvdata: a pointer to the drvdata. + * @data: Kernel address of the partial bitstream. + * @size: the size of the partial bitstream in 32 bit words. **/ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, u32 size) @@ -333,10 +321,10 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, }; /** - * buffer_icap_get_configuration: Read configuration data from the device. - * @parameter drvdata: a pointer to the drvdata. - * @parameter data: Address of the data representing the partial bitstream - * @parameter size: the size of the partial bitstream in 32 bit words. + * buffer_icap_get_configuration - Read configuration data from the device. + * @drvdata: a pointer to the drvdata. + * @data: Address of the data representing the partial bitstream + * @size: the size of the partial bitstream in 32 bit words. **/ int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data, u32 size) diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h index 03184959fa0..c5b1840906b 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.h +++ b/drivers/char/xilinx_hwicap/buffer_icap.h @@ -44,8 +44,6 @@ #include <asm/io.h> #include "xilinx_hwicap.h" -void buffer_icap_reset(struct hwicap_drvdata *drvdata); - /* Loads a partial bitstream from system memory. */ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, u32 Size); @@ -54,4 +52,7 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data, u32 Size); +u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata); +void buffer_icap_reset(struct hwicap_drvdata *drvdata); + #endif diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c index 0988314694a..776b5052847 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.c +++ b/drivers/char/xilinx_hwicap/fifo_icap.c @@ -78,13 +78,6 @@ #define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */ #define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */ -/* Status Register (SR) */ -#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */ -#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */ -#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */ -#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */ -#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */ - #define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */ #define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */ @@ -94,9 +87,9 @@ /** - * fifo_icap_fifo_write: Write data to the write FIFO. - * @parameter drvdata: a pointer to the drvdata. - * @parameter data: the 32-bit value to be written to the FIFO. + * fifo_icap_fifo_write - Write data to the write FIFO. + * @drvdata: a pointer to the drvdata. + * @data: the 32-bit value to be written to the FIFO. * * This function will silently fail if the fifo is full. **/ @@ -108,8 +101,8 @@ static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata, } /** - * fifo_icap_fifo_read: Read data from the Read FIFO. - * @parameter drvdata: a pointer to the drvdata. + * fifo_icap_fifo_read - Read data from the Read FIFO. + * @drvdata: a pointer to the drvdata. * * This function will silently fail if the fifo is empty. **/ @@ -121,9 +114,9 @@ static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata) } /** - * fifo_icap_set_read_size: Set the the size register. - * @parameter drvdata: a pointer to the drvdata. - * @parameter data: the size of the following read transaction, in words. + * fifo_icap_set_read_size - Set the the size register. + * @drvdata: a pointer to the drvdata. + * @data: the size of the following read transaction, in words. **/ static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata, u32 data) @@ -132,8 +125,8 @@ static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata, } /** - * fifo_icap_start_config: Initiate a configuration (write) to the device. - * @parameter drvdata: a pointer to the drvdata. + * fifo_icap_start_config - Initiate a configuration (write) to the device. + * @drvdata: a pointer to the drvdata. **/ static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata) { @@ -142,8 +135,8 @@ static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata) } /** - * fifo_icap_start_readback: Initiate a readback from the device. - * @parameter drvdata: a pointer to the drvdata. + * fifo_icap_start_readback - Initiate a readback from the device. + * @drvdata: a pointer to the drvdata. **/ static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata) { @@ -152,19 +145,41 @@ static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata) } /** - * fifo_icap_busy: Return true if the ICAP is still processing a transaction. - * @parameter drvdata: a pointer to the drvdata. + * fifo_icap_get_status - Get the contents of the status register. + * @drvdata: a pointer to the drvdata. + * + * The status register contains the ICAP status and the done bit. + * + * D8 - cfgerr + * D7 - dalign + * D6 - rip + * D5 - in_abort_l + * D4 - Always 1 + * D3 - Always 1 + * D2 - Always 1 + * D1 - Always 1 + * D0 - Done bit **/ -static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata) +u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata) { u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET); dev_dbg(drvdata->dev, "Getting status = %x\n", status); + return status; +} + +/** + * fifo_icap_busy - Return true if the ICAP is still processing a transaction. + * @drvdata: a pointer to the drvdata. + **/ +static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata) +{ + u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET); return (status & XHI_SR_DONE_MASK) ? 0 : 1; } /** - * fifo_icap_write_fifo_vacancy: Query the write fifo available space. - * @parameter drvdata: a pointer to the drvdata. + * fifo_icap_write_fifo_vacancy - Query the write fifo available space. + * @drvdata: a pointer to the drvdata. * * Return the number of words that can be safely pushed into the write fifo. **/ @@ -175,8 +190,8 @@ static inline u32 fifo_icap_write_fifo_vacancy( } /** - * fifo_icap_read_fifo_occupancy: Query the read fifo available data. - * @parameter drvdata: a pointer to the drvdata. + * fifo_icap_read_fifo_occupancy - Query the read fifo available data. + * @drvdata: a pointer to the drvdata. * * Return the number of words that can be safely read from the read fifo. **/ @@ -187,11 +202,11 @@ static inline u32 fifo_icap_read_fifo_occupancy( } /** - * fifo_icap_set_configuration: Send configuration data to the ICAP. - * @parameter drvdata: a pointer to the drvdata. - * @parameter frame_buffer: a pointer to the data to be written to the + * fifo_icap_set_configuration - Send configuration data to the ICAP. + * @drvdata: a pointer to the drvdata. + * @frame_buffer: a pointer to the data to be written to the * ICAP device. - * @parameter num_words: the number of words (32 bit) to write to the ICAP + * @num_words: the number of words (32 bit) to write to the ICAP * device. * This function writes the given user data to the Write FIFO in @@ -266,10 +281,10 @@ int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata, } /** - * fifo_icap_get_configuration: Read configuration data from the device. - * @parameter drvdata: a pointer to the drvdata. - * @parameter data: Address of the data representing the partial bitstream - * @parameter size: the size of the partial bitstream in 32 bit words. + * fifo_icap_get_configuration - Read configuration data from the device. + * @drvdata: a pointer to the drvdata. + * @data: Address of the data representing the partial bitstream + * @size: the size of the partial bitstream in 32 bit words. * * This function reads the specified number of words from the ICAP device in * the polled mode. @@ -335,8 +350,8 @@ int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata, } /** - * buffer_icap_reset: Reset the logic of the icap device. - * @parameter drvdata: a pointer to the drvdata. + * buffer_icap_reset - Reset the logic of the icap device. + * @drvdata: a pointer to the drvdata. * * This function forces the software reset of the complete HWICAP device. * All the registers will return to the default value and the FIFO is also @@ -360,8 +375,8 @@ void fifo_icap_reset(struct hwicap_drvdata *drvdata) } /** - * fifo_icap_flush_fifo: This function flushes the FIFOs in the device. - * @parameter drvdata: a pointer to the drvdata. + * fifo_icap_flush_fifo - This function flushes the FIFOs in the device. + * @drvdata: a pointer to the drvdata. */ void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata) { diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h index 4d3068dd040..ffabd3ba2bd 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.h +++ b/drivers/char/xilinx_hwicap/fifo_icap.h @@ -56,6 +56,7 @@ int fifo_icap_set_configuration( u32 *FrameBuffer, u32 NumWords); +u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata); void fifo_icap_reset(struct hwicap_drvdata *drvdata); void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata); diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 24f6aef0fd3..dfe6907ae15 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -36,7 +36,7 @@ *****************************************************************************/ /* - * This is the code behind /dev/xilinx_icap -- it allows a user-space + * This is the code behind /dev/icap* -- it allows a user-space * application to use the Xilinx ICAP subsystem. * * The following operations are possible: @@ -67,7 +67,7 @@ * user-space application code that uses this device. The simplest * way to use this interface is simply: * - * cp foo.bit /dev/xilinx_icap + * cp foo.bit /dev/icap0 * * Note that unless foo.bit is an appropriately constructed partial * bitstream, this has a high likelyhood of overwriting the design @@ -84,7 +84,7 @@ #include <linux/init.h> #include <linux/poll.h> #include <linux/proc_fs.h> -#include <asm/semaphore.h> +#include <linux/mutex.h> #include <linux/sysctl.h> #include <linux/version.h> #include <linux/fs.h> @@ -105,20 +105,17 @@ #include "buffer_icap.h" #include "fifo_icap.h" -#define DRIVER_NAME "xilinx_icap" +#define DRIVER_NAME "icap" #define HWICAP_REGS (0x10000) -/* dynamically allocate device number */ -static int xhwicap_major; -static int xhwicap_minor; +#define XHWICAP_MAJOR 259 +#define XHWICAP_MINOR 0 #define HWICAP_DEVICES 1 -module_param(xhwicap_major, int, S_IRUGO); -module_param(xhwicap_minor, int, S_IRUGO); - /* An array, which is set to true when the device is registered. */ static bool probed_devices[HWICAP_DEVICES]; +static struct mutex icap_sem; static struct class *icap_class; @@ -199,14 +196,14 @@ static const struct config_registers v5_config_registers = { }; /** - * hwicap_command_desync: Send a DESYNC command to the ICAP port. - * @parameter drvdata: a pointer to the drvdata. + * hwicap_command_desync - Send a DESYNC command to the ICAP port. + * @drvdata: a pointer to the drvdata. * * This command desynchronizes the ICAP After this command, a * bitstream containing a NULL packet, followed by a SYNCH packet is * required before the ICAP will recognize commands. */ -int hwicap_command_desync(struct hwicap_drvdata *drvdata) +static int hwicap_command_desync(struct hwicap_drvdata *drvdata) { u32 buffer[4]; u32 index = 0; @@ -228,51 +225,18 @@ int hwicap_command_desync(struct hwicap_drvdata *drvdata) } /** - * hwicap_command_capture: Send a CAPTURE command to the ICAP port. - * @parameter drvdata: a pointer to the drvdata. - * - * This command captures all of the flip flop states so they will be - * available during readback. One can use this command instead of - * enabling the CAPTURE block in the design. - */ -int hwicap_command_capture(struct hwicap_drvdata *drvdata) -{ - u32 buffer[7]; - u32 index = 0; - - /* - * Create the data to be written to the ICAP. - */ - buffer[index++] = XHI_DUMMY_PACKET; - buffer[index++] = XHI_SYNC_PACKET; - buffer[index++] = XHI_NOOP_PACKET; - buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1; - buffer[index++] = XHI_CMD_GCAPTURE; - buffer[index++] = XHI_DUMMY_PACKET; - buffer[index++] = XHI_DUMMY_PACKET; - - /* - * Write the data to the FIFO and intiate the transfer of data - * present in the FIFO to the ICAP device. - */ - return drvdata->config->set_configuration(drvdata, - &buffer[0], index); - -} - -/** - * hwicap_get_configuration_register: Query a configuration register. - * @parameter drvdata: a pointer to the drvdata. - * @parameter reg: a constant which represents the configuration + * hwicap_get_configuration_register - Query a configuration register. + * @drvdata: a pointer to the drvdata. + * @reg: a constant which represents the configuration * register value to be returned. * Examples: XHI_IDCODE, XHI_FLR. - * @parameter RegData: returns the value of the register. + * @reg_data: returns the value of the register. * * Sends a query packet to the ICAP and then receives the response. * The icap is left in Synched state. */ -int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata, - u32 reg, u32 *RegData) +static int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata, + u32 reg, u32 *reg_data) { int status; u32 buffer[6]; @@ -282,8 +246,26 @@ int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata, * Create the data to be written to the ICAP. */ buffer[index++] = XHI_DUMMY_PACKET; + buffer[index++] = XHI_NOOP_PACKET; buffer[index++] = XHI_SYNC_PACKET; buffer[index++] = XHI_NOOP_PACKET; + buffer[index++] = XHI_NOOP_PACKET; + + /* + * Write the data to the FIFO and initiate the transfer of data present + * in the FIFO to the ICAP device. + */ + status = drvdata->config->set_configuration(drvdata, + &buffer[0], index); + if (status) + return status; + + /* If the syncword was not found, then we need to start over. */ + status = drvdata->config->get_status(drvdata); + if ((status & XHI_SR_DALIGN_MASK) != XHI_SR_DALIGN_MASK) + return -EIO; + + index = 0; buffer[index++] = hwicap_type_1_read(reg) | 1; buffer[index++] = XHI_NOOP_PACKET; buffer[index++] = XHI_NOOP_PACKET; @@ -300,14 +282,14 @@ int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata, /* * Read the configuration register */ - status = drvdata->config->get_configuration(drvdata, RegData, 1); + status = drvdata->config->get_configuration(drvdata, reg_data, 1); if (status) return status; return 0; } -int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata) +static int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata) { int status; u32 idcode; @@ -344,7 +326,7 @@ int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata) } static ssize_t -hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos) +hwicap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct hwicap_drvdata *drvdata = file->private_data; ssize_t bytes_to_read = 0; @@ -353,8 +335,9 @@ hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos) u32 bytes_remaining; int status; - if (down_interruptible(&drvdata->sem)) - return -ERESTARTSYS; + status = mutex_lock_interruptible(&drvdata->sem); + if (status) + return status; if (drvdata->read_buffer_in_use) { /* If there are leftover bytes in the buffer, just */ @@ -370,8 +353,9 @@ hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos) goto error; } drvdata->read_buffer_in_use -= bytes_to_read; - memcpy(drvdata->read_buffer + bytes_to_read, - drvdata->read_buffer, 4 - bytes_to_read); + memmove(drvdata->read_buffer, + drvdata->read_buffer + bytes_to_read, + 4 - bytes_to_read); } else { /* Get new data from the ICAP, and return was was requested. */ kbuf = (u32 *) get_zeroed_page(GFP_KERNEL); @@ -414,18 +398,20 @@ hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos) status = -EFAULT; goto error; } - memcpy(kbuf, drvdata->read_buffer, bytes_remaining); + memcpy(drvdata->read_buffer, + kbuf, + bytes_remaining); drvdata->read_buffer_in_use = bytes_remaining; free_page((unsigned long)kbuf); } status = bytes_to_read; error: - up(&drvdata->sem); + mutex_unlock(&drvdata->sem); return status; } static ssize_t -hwicap_write(struct file *file, const char *buf, +hwicap_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct hwicap_drvdata *drvdata = file->private_data; @@ -435,8 +421,9 @@ hwicap_write(struct file *file, const char *buf, ssize_t len; ssize_t status; - if (down_interruptible(&drvdata->sem)) - return -ERESTARTSYS; + status = mutex_lock_interruptible(&drvdata->sem); + if (status) + return status; left += drvdata->write_buffer_in_use; @@ -465,7 +452,7 @@ hwicap_write(struct file *file, const char *buf, memcpy(kbuf, drvdata->write_buffer, drvdata->write_buffer_in_use); if (copy_from_user( - (((char *)kbuf) + (drvdata->write_buffer_in_use)), + (((char *)kbuf) + drvdata->write_buffer_in_use), buf + written, len - (drvdata->write_buffer_in_use))) { free_page((unsigned long)kbuf); @@ -508,7 +495,7 @@ hwicap_write(struct file *file, const char *buf, free_page((unsigned long)kbuf); status = written; error: - up(&drvdata->sem); + mutex_unlock(&drvdata->sem); return status; } @@ -519,8 +506,9 @@ static int hwicap_open(struct inode *inode, struct file *file) drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev); - if (down_interruptible(&drvdata->sem)) - return -ERESTARTSYS; + status = mutex_lock_interruptible(&drvdata->sem); + if (status) + return status; if (drvdata->is_open) { status = -EBUSY; @@ -539,7 +527,7 @@ static int hwicap_open(struct inode *inode, struct file *file) drvdata->is_open = 1; error: - up(&drvdata->sem); + mutex_unlock(&drvdata->sem); return status; } @@ -549,8 +537,7 @@ static int hwicap_release(struct inode *inode, struct file *file) int i; int status = 0; - if (down_interruptible(&drvdata->sem)) - return -ERESTARTSYS; + mutex_lock(&drvdata->sem); if (drvdata->write_buffer_in_use) { /* Flush write buffer. */ @@ -569,7 +556,7 @@ static int hwicap_release(struct inode *inode, struct file *file) error: drvdata->is_open = 0; - up(&drvdata->sem); + mutex_unlock(&drvdata->sem); return status; } @@ -592,31 +579,36 @@ static int __devinit hwicap_setup(struct device *dev, int id, dev_info(dev, "Xilinx icap port driver\n"); + mutex_lock(&icap_sem); + if (id < 0) { for (id = 0; id < HWICAP_DEVICES; id++) if (!probed_devices[id]) break; } if (id < 0 || id >= HWICAP_DEVICES) { + mutex_unlock(&icap_sem); dev_err(dev, "%s%i too large\n", DRIVER_NAME, id); return -EINVAL; } if (probed_devices[id]) { + mutex_unlock(&icap_sem); dev_err(dev, "cannot assign to %s%i; it is already in use\n", DRIVER_NAME, id); return -EBUSY; } probed_devices[id] = 1; + mutex_unlock(&icap_sem); - devt = MKDEV(xhwicap_major, xhwicap_minor + id); + devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id); - drvdata = kmalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL); + drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL); if (!drvdata) { dev_err(dev, "Couldn't allocate device private record\n"); - return -ENOMEM; + retval = -ENOMEM; + goto failed0; } - memset((void *)drvdata, 0, sizeof(struct hwicap_drvdata)); dev_set_drvdata(dev, (void *)drvdata); if (!regs_res) { @@ -648,7 +640,7 @@ static int __devinit hwicap_setup(struct device *dev, int id, drvdata->config = config; drvdata->config_regs = config_regs; - init_MUTEX(&drvdata->sem); + mutex_init(&drvdata->sem); drvdata->is_open = 0; dev_info(dev, "ioremap %lx to %p with size %x\n", @@ -663,7 +655,7 @@ static int __devinit hwicap_setup(struct device *dev, int id, goto failed3; } /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */ - class_device_create(icap_class, NULL, devt, NULL, DRIVER_NAME); + device_create(icap_class, dev, devt, "%s%d", DRIVER_NAME, id); return 0; /* success */ failed3: @@ -675,18 +667,25 @@ static int __devinit hwicap_setup(struct device *dev, int id, failed1: kfree(drvdata); + failed0: + mutex_lock(&icap_sem); + probed_devices[id] = 0; + mutex_unlock(&icap_sem); + return retval; } static struct hwicap_driver_config buffer_icap_config = { .get_configuration = buffer_icap_get_configuration, .set_configuration = buffer_icap_set_configuration, + .get_status = buffer_icap_get_status, .reset = buffer_icap_reset, }; static struct hwicap_driver_config fifo_icap_config = { .get_configuration = fifo_icap_get_configuration, .set_configuration = fifo_icap_set_configuration, + .get_status = fifo_icap_get_status, .reset = fifo_icap_reset, }; @@ -699,14 +698,16 @@ static int __devexit hwicap_remove(struct device *dev) if (!drvdata) return 0; - class_device_destroy(icap_class, drvdata->devt); + device_destroy(icap_class, drvdata->devt); cdev_del(&drvdata->cdev); iounmap(drvdata->base_address); release_mem_region(drvdata->mem_start, drvdata->mem_size); kfree(drvdata); dev_set_drvdata(dev, NULL); - probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0; + mutex_lock(&icap_sem); + probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0; + mutex_unlock(&icap_sem); return 0; /* success */ } @@ -802,7 +803,7 @@ static int __devexit hwicap_of_remove(struct of_device *op) } /* Match table for of_platform binding */ -static const struct of_device_id __devinit hwicap_of_match[] = { +static const struct of_device_id __devinitconst hwicap_of_match[] = { { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config}, { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config}, {}, @@ -821,46 +822,36 @@ static struct of_platform_driver hwicap_of_driver = { }; /* Registration helpers to keep the number of #ifdefs to a minimum */ -static inline int __devinit hwicap_of_register(void) +static inline int __init hwicap_of_register(void) { pr_debug("hwicap: calling of_register_platform_driver()\n"); return of_register_platform_driver(&hwicap_of_driver); } -static inline void __devexit hwicap_of_unregister(void) +static inline void __exit hwicap_of_unregister(void) { of_unregister_platform_driver(&hwicap_of_driver); } #else /* CONFIG_OF */ /* CONFIG_OF not enabled; do nothing helpers */ -static inline int __devinit hwicap_of_register(void) { return 0; } -static inline void __devexit hwicap_of_unregister(void) { } +static inline int __init hwicap_of_register(void) { return 0; } +static inline void __exit hwicap_of_unregister(void) { } #endif /* CONFIG_OF */ -static int __devinit hwicap_module_init(void) +static int __init hwicap_module_init(void) { dev_t devt; int retval; icap_class = class_create(THIS_MODULE, "xilinx_config"); + mutex_init(&icap_sem); - if (xhwicap_major) { - devt = MKDEV(xhwicap_major, xhwicap_minor); - retval = register_chrdev_region( - devt, - HWICAP_DEVICES, - DRIVER_NAME); - if (retval < 0) - return retval; - } else { - retval = alloc_chrdev_region(&devt, - xhwicap_minor, - HWICAP_DEVICES, - DRIVER_NAME); - if (retval < 0) - return retval; - xhwicap_major = MAJOR(devt); - } + devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR); + retval = register_chrdev_region(devt, + HWICAP_DEVICES, + DRIVER_NAME); + if (retval < 0) + return retval; retval = platform_driver_register(&hwicap_platform_driver); @@ -883,9 +874,9 @@ static int __devinit hwicap_module_init(void) return retval; } -static void __devexit hwicap_module_cleanup(void) +static void __exit hwicap_module_cleanup(void) { - dev_t devt = MKDEV(xhwicap_major, xhwicap_minor); + dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR); class_destroy(icap_class); diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h index ae771cac162..1f9c8b082db 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h @@ -48,9 +48,9 @@ struct hwicap_drvdata { u8 write_buffer[4]; u32 read_buffer_in_use; /* Always in [0,3] */ u8 read_buffer[4]; - u32 mem_start; /* phys. address of the control registers */ - u32 mem_end; /* phys. address of the control registers */ - u32 mem_size; + resource_size_t mem_start;/* phys. address of the control registers */ + resource_size_t mem_end; /* phys. address of the control registers */ + resource_size_t mem_size; void __iomem *base_address;/* virt. address of the control registers */ struct device *dev; @@ -61,14 +61,31 @@ struct hwicap_drvdata { const struct config_registers *config_regs; void *private_data; bool is_open; - struct semaphore sem; + struct mutex sem; }; struct hwicap_driver_config { + /* Read configuration data given by size into the data buffer. + Return 0 if successful. */ int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data, u32 size); + /* Write configuration data given by size from the data buffer. + Return 0 if successful. */ int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data, u32 size); + /* Get the status register, bit pattern given by: + * D8 - 0 = configuration error + * D7 - 1 = alignment found + * D6 - 1 = readback in progress + * D5 - 0 = abort in progress + * D4 - Always 1 + * D3 - Always 1 + * D2 - Always 1 + * D1 - Always 1 + * D0 - 1 = operation completed + */ + u32 (*get_status)(struct hwicap_drvdata *drvdata); + /* Reset the hw */ void (*reset)(struct hwicap_drvdata *drvdata); }; @@ -163,30 +180,37 @@ struct config_registers { /* Constant to use for CRC check when CRC has been disabled */ #define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL +/* Meanings of the bits returned by get_status */ +#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */ +#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */ +#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */ +#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */ +#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */ + /** - * hwicap_type_1_read: Generates a Type 1 read packet header. - * @parameter: Register is the address of the register to be read back. + * hwicap_type_1_read - Generates a Type 1 read packet header. + * @reg: is the address of the register to be read back. * * Generates a Type 1 read packet header, which is used to indirectly * read registers in the configuration logic. This packet must then * be sent through the icap device, and a return packet received with * the information. **/ -static inline u32 hwicap_type_1_read(u32 Register) +static inline u32 hwicap_type_1_read(u32 reg) { return (XHI_TYPE_1 << XHI_TYPE_SHIFT) | - (Register << XHI_REGISTER_SHIFT) | + (reg << XHI_REGISTER_SHIFT) | (XHI_OP_READ << XHI_OP_SHIFT); } /** - * hwicap_type_1_write: Generates a Type 1 write packet header - * @parameter: Register is the address of the register to be read back. + * hwicap_type_1_write - Generates a Type 1 write packet header + * @reg: is the address of the register to be read back. **/ -static inline u32 hwicap_type_1_write(u32 Register) +static inline u32 hwicap_type_1_write(u32 reg) { return (XHI_TYPE_1 << XHI_TYPE_SHIFT) | - (Register << XHI_REGISTER_SHIFT) | + (reg << XHI_REGISTER_SHIFT) | (XHI_OP_WRITE << XHI_OP_SHIFT); } |