diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/drm/ati_pcigart.c | 91 | ||||
-rw-r--r-- | drivers/char/drm/drmP.h | 3 | ||||
-rw-r--r-- | drivers/char/drm/drm_fops.c | 7 | ||||
-rw-r--r-- | drivers/char/drm/drm_lock.c | 35 | ||||
-rw-r--r-- | drivers/char/drm/drm_pciids.h | 7 | ||||
-rw-r--r-- | drivers/char/drm/r128_cce.c | 1 | ||||
-rw-r--r-- | drivers/char/drm/radeon_cp.c | 1 | ||||
-rw-r--r-- | drivers/char/drm/via_dma.c | 59 | ||||
-rw-r--r-- | drivers/char/drm/via_dmablit.c | 2 | ||||
-rw-r--r-- | drivers/char/nozomi.c | 61 | ||||
-rw-r--r-- | drivers/char/riscom8.c | 8 |
11 files changed, 154 insertions, 121 deletions
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index d352dbb4ccf7..e5a0e97cfdda 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); + 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; - for (i = 0; i < order; i++, page++) - SetPageReserved(page); - - 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,31 +111,14 @@ 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; diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index a6789f25009b..8ea9dd1717a9 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> @@ -551,6 +552,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; }; diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 3992f73299cc..f09d4b5002b0 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c @@ -326,6 +326,7 @@ 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; int retcode = 0; + unsigned long irqflags; lock_kernel(); @@ -357,9 +358,11 @@ 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(); diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index bea2a7d5b2b2..12dcdd1832f0 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 715b361f0c2b..a6a499f97e22 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/r128_cce.c b/drivers/char/drm/r128_cce.c index 892e0a589846..f36adbd3aaf5 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; diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 833abc7e55fb..9072e4a1894e 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/via_dma.c b/drivers/char/drm/via_dma.c index 94baec692b57..7a339dba6a69 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 33c5197b73c4..409e00afdd07 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/nozomi.c b/drivers/char/nozomi.c index dfaab2322de3..6d0dc5f9b6bb 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; }; @@ -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/riscom8.c b/drivers/char/riscom8.c index 8fc4fe4e38f1..3f9d0a9ac36d 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) |