Commit 4a99b33d authored by Patrick Mochel's avatar Patrick Mochel

Merge bk://linus.bkbits.net/linux-2.5

into hostme.bitkeeper.com:/ua/repos/l/ldm/linux-2.5
parents f6bec0e6 0de4d503
...@@ -91,9 +91,9 @@ CFLAGS := $(CFLAGS) -Wa,-mev6 ...@@ -91,9 +91,9 @@ CFLAGS := $(CFLAGS) -Wa,-mev6
HEAD := arch/alpha/kernel/head.o HEAD := arch/alpha/kernel/head.o
core-y := arch/alpha/kernel/ arch/alpha/mm/ core-y += arch/alpha/kernel/ arch/alpha/mm/
core-$(CONFIG_MATHEMU) += arch/alpha/math-emu/built-in.o core-$(CONFIG_MATHEMU) += arch/alpha/math-emu/
libs-y := arch/alpha/lib libs-y += arch/alpha/lib/
MAKEBOOT = $(MAKE) -C arch/alpha/boot MAKEBOOT = $(MAKE) -C arch/alpha/boot
......
...@@ -1119,3 +1119,27 @@ sys_call_table: ...@@ -1119,3 +1119,27 @@ sys_call_table:
.quad sys_readahead .quad sys_readahead
.quad sys_ni_syscall /* 380, sys_security */ .quad sys_ni_syscall /* 380, sys_security */
.quad sys_tkill .quad sys_tkill
.quad sys_setxattr
.quad sys_lsetxattr
.quad sys_fsetxattr
.quad sys_getxattr
.quad sys_lgetxattr
.quad sys_fgetxattr
.quad sys_listxattr
.quad sys_llistxattr
.quad sys_flistxattr /* 390 */
.quad sys_removexattr
.quad sys_lremovexattr
.quad sys_fremovexattr
.quad sys_futex
.quad sys_sched_setaffinity
.quad sys_sched_getaffinity
.quad sys_ni_syscall /* 397, tux */
.quad sys_io_setup
.quad sys_io_destroy
.quad sys_io_getevents /* 400 */
.quad sys_io_submit
.quad sys_io_cancel
.quad sys_ni_syscall /* 403, sys_alloc_hugepages */
.quad sys_ni_syscall /* 404, sys_free_hugepages */
.quad sys_exit_group
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for alpha-specific library files.. # Makefile for alpha-specific library files..
# #
EXTRA_AFLAGS := $(CFLAGS) L_TARGET := lib.a
# Many of these routines have implementations tuned for ev6. # Many of these routines have implementations tuned for ev6.
# Choose them iff we're targeting ev6 specifically. # Choose them iff we're targeting ev6 specifically.
...@@ -17,7 +17,7 @@ ifeq ($(CONFIG_ALPHA_EV67),y) ...@@ -17,7 +17,7 @@ ifeq ($(CONFIG_ALPHA_EV67),y)
ev67 := ev67- ev67 := ev67-
endif endif
OBJS = __divqu.o __remqu.o __divlu.o __remlu.o \ obj-y = __divqu.o __remqu.o __divlu.o __remlu.o \
udelay.o \ udelay.o \
$(ev6)memset.o \ $(ev6)memset.o \
$(ev6)memcpy.o \ $(ev6)memcpy.o \
...@@ -46,12 +46,9 @@ OBJS = __divqu.o __remqu.o __divlu.o __remlu.o \ ...@@ -46,12 +46,9 @@ OBJS = __divqu.o __remqu.o __divlu.o __remlu.o \
fpreg.o \ fpreg.o \
callback_srm.o srm_puts.o srm_printk.o callback_srm.o srm_puts.o srm_printk.o
ifeq ($(CONFIG_SMP),y) obj-$(CONFIG_SMP) += dec_and_lock.o
OBJS += dec_and_lock.o
endif
lib.a: $(OBJS) include $(TOPDIR)/Rules.make
$(AR) rcs lib.a $(OBJS)
__divqu.o: $(ev6)divide.S __divqu.o: $(ev6)divide.S
$(CC) $(AFLAGS) -DDIV -c -o __divqu.o $(ev6)divide.S $(CC) $(AFLAGS) -DDIV -c -o __divqu.o $(ev6)divide.S
...@@ -64,5 +61,3 @@ __divlu.o: $(ev6)divide.S ...@@ -64,5 +61,3 @@ __divlu.o: $(ev6)divide.S
__remlu.o: $(ev6)divide.S __remlu.o: $(ev6)divide.S
$(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o $(ev6)divide.S $(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o $(ev6)divide.S
include $(TOPDIR)/Rules.make
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
# Makefile for the FPU instruction emulation. # Makefile for the FPU instruction emulation.
# #
obj-$(CONFIG_MATHEMU) += math-emu.o
math-emu-objs := math.o qrnnd.o
CFLAGS += -I. -I$(TOPDIR)/include/math-emu -w CFLAGS += -I. -I$(TOPDIR)/include/math-emu -w
obj-$(CONFIG_MATHEMU) += math.o qrnnd.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
...@@ -157,13 +157,20 @@ inline int elv_try_last_merge(request_queue_t *q, struct request **req, ...@@ -157,13 +157,20 @@ inline int elv_try_last_merge(request_queue_t *q, struct request **req,
return ret; return ret;
} }
static int bio_rq_before(struct bio *bio, struct request *rq)
{
if (!kdev_same(to_kdev_t(bio->bi_bdev->bd_dev), rq->rq_dev))
return 0;
return bio->bi_sector < rq->sector;
}
/* /*
* elevator_linux starts here * elevator_linux starts here
*/ */
int elevator_linus_merge(request_queue_t *q, struct request **req, int elevator_linus_merge(request_queue_t *q, struct request **req,
struct bio *bio) struct bio *bio)
{ {
struct list_head *entry; struct list_head *entry, *good;
struct request *__rq; struct request *__rq;
int ret; int ret;
...@@ -171,6 +178,7 @@ int elevator_linus_merge(request_queue_t *q, struct request **req, ...@@ -171,6 +178,7 @@ int elevator_linus_merge(request_queue_t *q, struct request **req,
return ret; return ret;
entry = &q->queue_head; entry = &q->queue_head;
good = &q->queue_head;
ret = ELEVATOR_NO_MERGE; ret = ELEVATOR_NO_MERGE;
while ((entry = entry->prev) != &q->queue_head) { while ((entry = entry->prev) != &q->queue_head) {
__rq = list_entry_rq(entry); __rq = list_entry_rq(entry);
...@@ -178,37 +186,31 @@ int elevator_linus_merge(request_queue_t *q, struct request **req, ...@@ -178,37 +186,31 @@ int elevator_linus_merge(request_queue_t *q, struct request **req,
if (__rq->flags & (REQ_BARRIER | REQ_STARTED)) if (__rq->flags & (REQ_BARRIER | REQ_STARTED))
break; break;
if (!(__rq->flags & REQ_CMD)) if (!(__rq->flags & REQ_CMD))
continue;
if (elv_linus_sequence(__rq) < bio_sectors(bio))
break; break;
if (!*req && bio_rq_in_between(bio, __rq, &q->queue_head)) if (bio_data_dir(bio) != rq_data_dir(__rq)) {
*req = __rq; if (bio_data_dir(bio) == WRITE)
break;
good = entry->prev;
continue;
}
if ((ret = elv_try_merge(__rq, bio))) { ret = elv_try_merge(__rq, bio);
if (ret == ELEVATOR_FRONT_MERGE) if (ret) {
elv_linus_sequence(__rq) -= bio_sectors(bio);
*req = __rq; *req = __rq;
q->last_merge = &__rq->queuelist; q->last_merge = &__rq->queuelist;
break; return ret;
} }
}
/* if (bio_rq_before(bio, __rq))
* if *req, it's either a seek or merge in the middle of the queue good = entry->prev;
*/
if (*req) {
struct list_head *entry = &(*req)->queuelist;
int cost = ret ? 1 : ELV_LINUS_SEEK_COST;
while ((entry = entry->next) != &q->queue_head) {
__rq = list_entry_rq(entry);
elv_linus_sequence(__rq) -= cost;
}
} }
return ret; if (good != &q->queue_head)
*req = list_entry_rq(good);
return ELEVATOR_NO_MERGE;
} }
void elevator_linus_merge_req(request_queue_t *q, struct request *req, void elevator_linus_merge_req(request_queue_t *q, struct request *req,
......
...@@ -8,7 +8,7 @@ r128-objs := r128_drv.o r128_cce.o r128_state.o ...@@ -8,7 +8,7 @@ r128-objs := r128_drv.o r128_cce.o r128_state.o
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o
i810-objs := i810_drv.o i810_dma.o i810-objs := i810_drv.o i810_dma.o
i830-objs := i830_drv.o i830_dma.o i830-objs := i830_drv.o i830_dma.o
radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
ffb-objs := ffb_drv.o ffb_context.o ffb-objs := ffb_drv.o ffb_context.o
obj-$(CONFIG_DRM_GAMMA) += gamma.o obj-$(CONFIG_DRM_GAMMA) += gamma.o
......
...@@ -165,7 +165,7 @@ ...@@ -165,7 +165,7 @@
#define pte_unmap(pte) #define pte_unmap(pte)
#endif #endif
#if LINUX_VERSION_CODE < 0x020413 /* KERNEL_VERSION(2,4,19) */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
static inline struct page * vmalloc_to_page(void * vmalloc_addr) static inline struct page * vmalloc_to_page(void * vmalloc_addr)
{ {
unsigned long addr = (unsigned long) vmalloc_addr; unsigned long addr = (unsigned long) vmalloc_addr;
...@@ -190,7 +190,7 @@ static inline struct page * vmalloc_to_page(void * vmalloc_addr) ...@@ -190,7 +190,7 @@ static inline struct page * vmalloc_to_page(void * vmalloc_addr)
} }
#endif #endif
#if LINUX_VERSION_CODE < 0x020500 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define DRM_RPR_ARG(vma) #define DRM_RPR_ARG(vma)
#else #else
#define DRM_RPR_ARG(vma) vma, #define DRM_RPR_ARG(vma) vma,
...@@ -597,7 +597,7 @@ typedef struct drm_device { ...@@ -597,7 +597,7 @@ typedef struct drm_device {
#endif #endif
struct pci_dev *pdev; struct pci_dev *pdev;
#ifdef __alpha__ #ifdef __alpha__
#if LINUX_VERSION_CODE < 0x020403 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
struct pci_controler *hose; struct pci_controler *hose;
#else #else
struct pci_controller *hose; struct pci_controller *hose;
......
...@@ -137,6 +137,7 @@ int DRM(addmap)( struct inode *inode, struct file *filp, ...@@ -137,6 +137,7 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
} }
map->offset = (unsigned long)map->handle; map->offset = (unsigned long)map->handle;
if ( map->flags & _DRM_CONTAINS_LOCK ) { if ( map->flags & _DRM_CONTAINS_LOCK ) {
dev->sigdata.lock =
dev->lock.hw_lock = map->handle; /* Pointer to lock */ dev->lock.hw_lock = map->handle; /* Pointer to lock */
} }
break; break;
......
...@@ -306,7 +306,7 @@ static int DRM(setup)( drm_device_t *dev ) ...@@ -306,7 +306,7 @@ static int DRM(setup)( drm_device_t *dev )
dev->map_count = 0; dev->map_count = 0;
dev->vmalist = NULL; dev->vmalist = NULL;
dev->lock.hw_lock = NULL; dev->sigdata.lock = dev->lock.hw_lock = NULL;
init_waitqueue_head( &dev->lock.lock_queue ); init_waitqueue_head( &dev->lock.lock_queue );
dev->queue_count = 0; dev->queue_count = 0;
dev->queue_reserved = 0; dev->queue_reserved = 0;
...@@ -491,7 +491,7 @@ static int DRM(takedown)( drm_device_t *dev ) ...@@ -491,7 +491,7 @@ static int DRM(takedown)( drm_device_t *dev )
DRM(dma_takedown)( dev ); DRM(dma_takedown)( dev );
#endif #endif
if ( dev->lock.hw_lock ) { if ( dev->lock.hw_lock ) {
dev->lock.hw_lock = NULL; /* SHM removed */ dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
dev->lock.pid = 0; dev->lock.pid = 0;
wake_up_interruptible( &dev->lock.lock_queue ); wake_up_interruptible( &dev->lock.lock_queue );
} }
......
...@@ -237,7 +237,7 @@ int DRM(notifier)(void *priv) ...@@ -237,7 +237,7 @@ int DRM(notifier)(void *priv)
/* Allow signal delivery if lock isn't held */ /* Allow signal delivery if lock isn't held */
if (!_DRM_LOCK_IS_HELD(s->lock->lock) if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
|| _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1; || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
/* Otherwise, set flag to force call to /* Otherwise, set flag to force call to
......
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
#define DRM_DEVICE drm_file_t *priv = filp->private_data; \ #define DRM_DEVICE drm_file_t *priv = filp->private_data; \
drm_device_t *dev = priv->dev drm_device_t *dev = priv->dev
#define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs
#define DRM_TASKQUEUE_ARGS void *arg
/* For data going from/to the kernel through the ioctl argument */ /* For data going from/to the kernel through the ioctl argument */
#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \ #define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
if ( copy_from_user(&arg1, arg2, arg3) ) \ if ( copy_from_user(&arg1, arg2, arg3) ) \
......
...@@ -45,11 +45,11 @@ ...@@ -45,11 +45,11 @@
#define DRIVER_NAME "i830" #define DRIVER_NAME "i830"
#define DRIVER_DESC "Intel 830M" #define DRIVER_DESC "Intel 830M"
#define DRIVER_DATE "20011004" #define DRIVER_DATE "20020828"
#define DRIVER_MAJOR 1 #define DRIVER_MAJOR 1
#define DRIVER_MINOR 2 #define DRIVER_MINOR 2
#define DRIVER_PATCHLEVEL 0 #define DRIVER_PATCHLEVEL 1
#define DRIVER_IOCTLS \ #define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)] = { i830_dma_init, 1, 1 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)] = { i830_dma_init, 1, 1 }, \
...@@ -87,50 +87,10 @@ ...@@ -87,50 +87,10 @@
i830_dma_quiescent( dev ); \ i830_dma_quiescent( dev ); \
} while (0) } while (0)
#define __HAVE_DMA_IRQ 1 /* Don't need an irq any more. The template code will make sure that
#define __HAVE_DMA_IRQ_BH 1 * a noop stub is generated for compatibility.
#define __HAVE_SHARED_IRQ 1 */
#define DRIVER_PREINSTALL() do { \ #define __HAVE_DMA_IRQ 0
drm_i830_private_t *dev_priv = \
(drm_i830_private_t *)dev->dev_private; \
u16 tmp; \
tmp = I830_READ16( I830REG_HWSTAM ); \
tmp = tmp & 0x6000; \
I830_WRITE16( I830REG_HWSTAM, tmp ); \
\
tmp = I830_READ16( I830REG_INT_MASK_R ); \
tmp = tmp & 0x6000; /* Unmask interrupts */ \
I830_WRITE16( I830REG_INT_MASK_R, tmp ); \
tmp = I830_READ16( I830REG_INT_ENABLE_R ); \
tmp = tmp & 0x6000; /* Disable all interrupts */ \
I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \
} while (0)
#define DRIVER_POSTINSTALL() do { \
drm_i830_private_t *dev_priv = \
(drm_i830_private_t *)dev->dev_private; \
u16 tmp; \
tmp = I830_READ16( I830REG_INT_ENABLE_R ); \
tmp = tmp & 0x6000; \
tmp = tmp | 0x0003; /* Enable bp & user interrupts */ \
I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \
} while (0)
#define DRIVER_UNINSTALL() do { \
drm_i830_private_t *dev_priv = \
(drm_i830_private_t *)dev->dev_private; \
u16 tmp; \
if ( dev_priv ) { \
tmp = I830_READ16( I830REG_INT_IDENTITY_R ); \
tmp = tmp & ~(0x6000); /* Clear all interrupts */ \
if ( tmp != 0 ) \
I830_WRITE16( I830REG_INT_IDENTITY_R, tmp ); \
\
tmp = I830_READ16( I830REG_INT_ENABLE_R ); \
tmp = tmp & 0x6000; /* Disable all interrupts */ \
I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \
} \
} while (0)
/* Buffer customization: /* Buffer customization:
*/ */
......
This diff is collapsed.
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
* Jeff Hartmann <jhartmann@valinux.com> * Jeff Hartmann <jhartmann@valinux.com>
* Gareth Hughes <gareth@valinux.com> * Gareth Hughes <gareth@valinux.com>
* Abraham vd Merwe <abraham@2d3d.co.za> * Abraham vd Merwe <abraham@2d3d.co.za>
* Keith Whitwell <keith@tungstengraphics.com>
*/ */
#include <linux/config.h> #include <linux/config.h>
......
...@@ -64,14 +64,13 @@ typedef struct drm_i830_private { ...@@ -64,14 +64,13 @@ typedef struct drm_i830_private {
unsigned long hw_status_page; unsigned long hw_status_page;
unsigned long counter; unsigned long counter;
atomic_t flush_done;
wait_queue_head_t flush_queue; /* Processes waiting until flush */
drm_buf_t *mmap_buffer; drm_buf_t *mmap_buffer;
u32 front_di1, back_di1, zi1; u32 front_di1, back_di1, zi1;
int back_offset; int back_offset;
int depth_offset; int depth_offset;
int front_offset;
int w, h; int w, h;
int pitch; int pitch;
int back_pitch; int back_pitch;
...@@ -107,14 +106,13 @@ extern int i830_swap_bufs(struct inode *inode, struct file *filp, ...@@ -107,14 +106,13 @@ extern int i830_swap_bufs(struct inode *inode, struct file *filp,
extern int i830_clear_bufs(struct inode *inode, struct file *filp, extern int i830_clear_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
#define I830_VERBOSE 0
#define I830_BASE(reg) ((unsigned long) \ #define I830_BASE(reg) ((unsigned long) \
dev_priv->mmio_map->handle) dev_priv->mmio_map->handle)
#define I830_ADDR(reg) (I830_BASE(reg) + reg) #define I830_ADDR(reg) (I830_BASE(reg) + reg)
#define I830_DEREF(reg) *(__volatile__ int *)I830_ADDR(reg) #define I830_DEREF(reg) *(__volatile__ unsigned int *)I830_ADDR(reg)
#define I830_READ(reg) I830_DEREF(reg) #define I830_READ(reg) readl((volatile u32 *)I830_ADDR(reg))
#define I830_WRITE(reg,val) do { I830_DEREF(reg) = val; } while (0) #define I830_WRITE(reg,val) writel(val, (volatile u32 *)I830_ADDR(reg))
#define I830_DEREF16(reg) *(__volatile__ u16 *)I830_ADDR(reg) #define I830_DEREF16(reg) *(__volatile__ u16 *)I830_ADDR(reg)
#define I830_READ16(reg) I830_DEREF16(reg) #define I830_READ16(reg) I830_DEREF16(reg)
#define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0) #define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0)
...@@ -143,15 +141,15 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp, ...@@ -143,15 +141,15 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define LP_RING 0x2030 #define LP_RING 0x2030
#define HP_RING 0x2040 #define HP_RING 0x2040
#define RING_TAIL 0x00 #define RING_TAIL 0x00
#define TAIL_ADDR 0x000FFFF8 #define TAIL_ADDR 0x001FFFF8
#define RING_HEAD 0x04 #define RING_HEAD 0x04
#define HEAD_WRAP_COUNT 0xFFE00000 #define HEAD_WRAP_COUNT 0xFFE00000
#define HEAD_WRAP_ONE 0x00200000 #define HEAD_WRAP_ONE 0x00200000
#define HEAD_ADDR 0x001FFFFC #define HEAD_ADDR 0x001FFFFC
#define RING_START 0x08 #define RING_START 0x08
#define START_ADDR 0x00FFFFF8 #define START_ADDR 0x0xFFFFF000
#define RING_LEN 0x0C #define RING_LEN 0x0C
#define RING_NR_PAGES 0x000FF000 #define RING_NR_PAGES 0x001FF000
#define RING_REPORT_MASK 0x00000006 #define RING_REPORT_MASK 0x00000006
#define RING_REPORT_64K 0x00000002 #define RING_REPORT_64K 0x00000002
#define RING_REPORT_128K 0x00000004 #define RING_REPORT_128K 0x00000004
...@@ -182,6 +180,9 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp, ...@@ -182,6 +180,9 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) #define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
#define CMD_3D (0x3<<29)
#define STATE3D_CONST_BLEND_COLOR_CMD (CMD_3D|(0x1d<<24)|(0x88<<16))
#define STATE3D_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16))
#define BR00_BITBLT_CLIENT 0x40000000 #define BR00_BITBLT_CLIENT 0x40000000
#define BR00_OP_COLOR_BLT 0x10000000 #define BR00_OP_COLOR_BLT 0x10000000
...@@ -206,6 +207,8 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp, ...@@ -206,6 +207,8 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
#define MI_BATCH_BUFFER ((0x30<<23)|1) #define MI_BATCH_BUFFER ((0x30<<23)|1)
#define MI_BATCH_BUFFER_START (0x31<<23)
#define MI_BATCH_BUFFER_END (0xA<<23)
#define MI_BATCH_NON_SECURE (1) #define MI_BATCH_NON_SECURE (1)
......
...@@ -48,10 +48,10 @@ ...@@ -48,10 +48,10 @@
#define DRIVER_NAME "radeon" #define DRIVER_NAME "radeon"
#define DRIVER_DESC "ATI Radeon" #define DRIVER_DESC "ATI Radeon"
#define DRIVER_DATE "20020611" #define DRIVER_DATE "20020828"
#define DRIVER_MAJOR 1 #define DRIVER_MAJOR 1
#define DRIVER_MINOR 5 #define DRIVER_MINOR 6
#define DRIVER_PATCHLEVEL 0 #define DRIVER_PATCHLEVEL 0
/* Interface history: /* Interface history:
...@@ -68,6 +68,11 @@ ...@@ -68,6 +68,11 @@
* 1.5 - Add r200 packets to cmdbuf ioctl * 1.5 - Add r200 packets to cmdbuf ioctl
* - Add r200 function to init ioctl * - Add r200 function to init ioctl
* - Add 'scalar2' instruction to cmdbuf * - Add 'scalar2' instruction to cmdbuf
* 1.6 - Add static agp memory manager
* Add irq handler (won't be turned on unless X server knows to)
* Add irq ioctls and irq_active getparam.
* Add wait command for cmdbuf ioctl
* Add agp offset query for getparam
*/ */
#define DRIVER_IOCTLS \ #define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
...@@ -88,9 +93,18 @@ ...@@ -88,9 +93,18 @@
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)] = { radeon_mem_free, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)] = { radeon_mem_init_heap, 1, 1 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 },
/* Driver customization: /* When a client dies:
* - Check for and clean up flipped page state
* - Free any alloced agp memory.
*
* DRM infrastructure takes care of reclaiming dma buffers.
*/ */
#define DRIVER_PRERELEASE() do { \ #define DRIVER_PRERELEASE() do { \
if ( dev->dev_private ) { \ if ( dev->dev_private ) { \
...@@ -98,22 +112,78 @@ ...@@ -98,22 +112,78 @@
if ( dev_priv->page_flipping ) { \ if ( dev_priv->page_flipping ) { \
radeon_do_cleanup_pageflip( dev ); \ radeon_do_cleanup_pageflip( dev ); \
} \ } \
radeon_mem_release( dev_priv->agp_heap ); \
} \ } \
} while (0) } while (0)
/* On unloading the module:
* - Free memory heap structure
* - Remove mappings made at startup and free dev_private.
*/
#define DRIVER_PRETAKEDOWN() do { \ #define DRIVER_PRETAKEDOWN() do { \
if ( dev->dev_private ) radeon_do_cleanup_cp( dev ); \ if ( dev->dev_private ) { \
drm_radeon_private_t *dev_priv = dev->dev_private; \
radeon_mem_takedown( &(dev_priv->agp_heap) ); \
radeon_do_cleanup_cp( dev ); \
} \
} while (0) } while (0)
/* DMA customization: /* DMA customization:
*/ */
#define __HAVE_DMA 1 #define __HAVE_DMA 1
#define __HAVE_DMA_IRQ 1
#define __HAVE_DMA_IRQ_BH 1
#define __HAVE_SHARED_IRQ 1
#define DRIVER_PREINSTALL() do { \
drm_radeon_private_t *dev_priv = \
(drm_radeon_private_t *)dev->dev_private; \
u32 tmp; \
\
/* Clear bit if it's already high: */ \
tmp = RADEON_READ( RADEON_GEN_INT_STATUS ); \
tmp = tmp & RADEON_SW_INT_TEST_ACK; \
RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); \
\
/* Disable *all* interrupts */ \
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); \
} while (0)
#ifdef __linux__
#define IWH(x) init_waitqueue_head(x)
#else
#define IWH(x)
#endif
#define DRIVER_POSTINSTALL() do { \
drm_radeon_private_t *dev_priv = \
(drm_radeon_private_t *)dev->dev_private; \
\
atomic_set(&dev_priv->irq_received, 0); \
atomic_set(&dev_priv->irq_emitted, 0); \
IWH(&dev_priv->irq_queue); \
\
/* Turn on SW_INT only */ \
RADEON_WRITE( RADEON_GEN_INT_CNTL, \
RADEON_SW_INT_ENABLE ); \
} while (0)
#define DRIVER_UNINSTALL() do { \
drm_radeon_private_t *dev_priv = \
(drm_radeon_private_t *)dev->dev_private; \
if ( dev_priv ) { \
/* Disable *all* interrupts */ \
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); \
} \
} while (0)
/* Buffer customization: /* Buffer customization:
*/ */
#define DRIVER_BUF_PRIV_T drm_radeon_buf_priv_t #define DRIVER_BUF_PRIV_T drm_radeon_buf_priv_t
#define DRIVER_AGP_BUFFERS_MAP( dev ) \ #define DRIVER_AGP_BUFFERS_MAP( dev ) \
((drm_radeon_private_t *)((dev)->dev_private))->buffers ((drm_radeon_private_t *)((dev)->dev_private))->buffers
#endif #endif
...@@ -1412,6 +1412,9 @@ int radeon_cp_idle( DRM_IOCTL_ARGS ) ...@@ -1412,6 +1412,9 @@ int radeon_cp_idle( DRM_IOCTL_ARGS )
LOCK_TEST_WITH_RETURN( dev ); LOCK_TEST_WITH_RETURN( dev );
/* if (dev->irq) */
/* radeon_emit_and_wait_irq( dev ); */
return radeon_do_cp_idle( dev_priv ); return radeon_do_cp_idle( dev_priv );
} }
......
...@@ -142,6 +142,9 @@ ...@@ -142,6 +142,9 @@
#define RADEON_CMD_PACKET3 5 /* emit hw packet */ #define RADEON_CMD_PACKET3 5 /* emit hw packet */
#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */ #define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */ #define RADEON_CMD_SCALARS2 7 /* r200 stopgap */
#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note:
* doesn't make the cpu wait, just
* the graphics hardware */
typedef union { typedef union {
...@@ -161,8 +164,14 @@ typedef union { ...@@ -161,8 +164,14 @@ typedef union {
struct { struct {
unsigned char cmd_type, buf_idx, pad0, pad1; unsigned char cmd_type, buf_idx, pad0, pad1;
} dma; } dma;
struct {
unsigned char cmd_type, flags, pad0, pad1;
} wait;
} drm_radeon_cmd_header_t; } drm_radeon_cmd_header_t;
#define RADEON_WAIT_2D 0x1
#define RADEON_WAIT_3D 0x2
#define RADEON_FRONT 0x1 #define RADEON_FRONT 0x1
#define RADEON_BACK 0x2 #define RADEON_BACK 0x2
...@@ -364,6 +373,11 @@ typedef struct { ...@@ -364,6 +373,11 @@ typedef struct {
#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t) #define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t)
#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t) #define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t)
#define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52) #define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52)
#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR( 0x53, drm_radeon_mem_alloc_t)
#define DRM_IOCTL_RADEON_FREE DRM_IOW( 0x54, drm_radeon_mem_free_t)
#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( 0x55, drm_radeon_mem_init_heap_t)
#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR( 0x56, drm_radeon_irq_emit_t)
#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t)
typedef struct drm_radeon_init { typedef struct drm_radeon_init {
enum { enum {
...@@ -499,14 +513,51 @@ typedef struct drm_radeon_indirect { ...@@ -499,14 +513,51 @@ typedef struct drm_radeon_indirect {
/* 1.3: An ioctl to get parameters that aren't available to the 3d /* 1.3: An ioctl to get parameters that aren't available to the 3d
* client any other way. * client any other way.
*/ */
#define RADEON_PARAM_AGP_BUFFER_OFFSET 0x1 #define RADEON_PARAM_AGP_BUFFER_OFFSET 1 /* card offset of 1st agp buffer */
#define RADEON_PARAM_LAST_FRAME 0x2 #define RADEON_PARAM_LAST_FRAME 2
#define RADEON_PARAM_LAST_DISPATCH 0x3 #define RADEON_PARAM_LAST_DISPATCH 3
#define RADEON_PARAM_LAST_CLEAR 0x4 #define RADEON_PARAM_LAST_CLEAR 4
#define RADEON_PARAM_IRQ_ACTIVE 5
#define RADEON_PARAM_AGP_BASE 6 /* card offset of agp base */
typedef struct drm_radeon_getparam { typedef struct drm_radeon_getparam {
int param; int param;
int *value; int *value;
} drm_radeon_getparam_t; } drm_radeon_getparam_t;
/* 1.6: Set up a memory manager for regions of shared memory:
*/
#define RADEON_MEM_REGION_AGP 1
#define RADEON_MEM_REGION_FB 2
typedef struct drm_radeon_mem_alloc {
int region;
int alignment;
int size;
int *region_offset; /* offset from start of fb or agp */
} drm_radeon_mem_alloc_t;
typedef struct drm_radeon_mem_free {
int region;
int region_offset;
} drm_radeon_mem_free_t;
typedef struct drm_radeon_mem_init_heap {
int region;
int size;
int start;
} drm_radeon_mem_init_heap_t;
/* 1.6: Userspace can request & wait on irq's:
*/
typedef struct drm_radeon_irq_emit {
int *irq_seq;
} drm_radeon_irq_emit_t;
typedef struct drm_radeon_irq_wait {
int irq_seq;
} drm_radeon_irq_wait_t;
#endif #endif
...@@ -61,6 +61,15 @@ typedef struct drm_radeon_depth_clear_t { ...@@ -61,6 +61,15 @@ typedef struct drm_radeon_depth_clear_t {
u32 se_cntl; u32 se_cntl;
} drm_radeon_depth_clear_t; } drm_radeon_depth_clear_t;
struct mem_block {
struct mem_block *next;
struct mem_block *prev;
int start;
int size;
int pid; /* 0: free, -1: heap, other: real pids */
};
typedef struct drm_radeon_private { typedef struct drm_radeon_private {
drm_radeon_ring_buffer_t ring; drm_radeon_ring_buffer_t ring;
drm_radeon_sarea_t *sarea_priv; drm_radeon_sarea_t *sarea_priv;
...@@ -126,6 +135,14 @@ typedef struct drm_radeon_private { ...@@ -126,6 +135,14 @@ typedef struct drm_radeon_private {
drm_map_t *ring_rptr; drm_map_t *ring_rptr;
drm_map_t *buffers; drm_map_t *buffers;
drm_map_t *agp_textures; drm_map_t *agp_textures;
struct mem_block *agp_heap;
struct mem_block *fb_heap;
wait_queue_head_t irq_queue;
atomic_t irq_received;
atomic_t irq_emitted;
} drm_radeon_private_t; } drm_radeon_private_t;
typedef struct drm_radeon_buf_priv { typedef struct drm_radeon_buf_priv {
...@@ -164,6 +181,20 @@ extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ); ...@@ -164,6 +181,20 @@ extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS );
extern int radeon_cp_getparam( DRM_IOCTL_ARGS ); extern int radeon_cp_getparam( DRM_IOCTL_ARGS );
extern int radeon_cp_flip( DRM_IOCTL_ARGS ); extern int radeon_cp_flip( DRM_IOCTL_ARGS );
extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
extern int radeon_mem_free( DRM_IOCTL_ARGS );
extern int radeon_mem_init_heap( DRM_IOCTL_ARGS );
extern void radeon_mem_takedown( struct mem_block **heap );
extern void radeon_mem_release( struct mem_block *heap );
extern int radeon_irq_emit( DRM_IOCTL_ARGS );
extern int radeon_irq_wait( DRM_IOCTL_ARGS );
extern int radeon_emit_and_wait_irq(drm_device_t *dev);
extern int radeon_wait_irq(drm_device_t *dev, int irq_nr);
extern int radeon_emit_irq(drm_device_t *dev);
/* Flags for stats.boxes /* Flags for stats.boxes
*/ */
#define RADEON_BOX_DMA_IDLE 0x1 #define RADEON_BOX_DMA_IDLE 0x1
...@@ -238,6 +269,16 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS ); ...@@ -238,6 +269,16 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS );
? DRM_READ32( &dev_priv->scratch[(x)] ) \ ? DRM_READ32( &dev_priv->scratch[(x)] ) \
: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
#define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
# define RADEON_SW_INT_ENABLE (1 << 25)
#define RADEON_GEN_INT_STATUS 0x0044
# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19)
# define RADEON_SW_INT_TEST_ACK (1 << 25)
# define RADEON_SW_INT_FIRE (1 << 26)
#define RADEON_HOST_PATH_CNTL 0x0130 #define RADEON_HOST_PATH_CNTL 0x0130
# define RADEON_HDP_SOFT_RESET (1 << 26) # define RADEON_HDP_SOFT_RESET (1 << 26)
# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) # define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28)
...@@ -526,6 +567,8 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS ); ...@@ -526,6 +567,8 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS );
#define RADEON_TXFORMAT_ARGB4444 5 #define RADEON_TXFORMAT_ARGB4444 5
#define RADEON_TXFORMAT_ARGB8888 6 #define RADEON_TXFORMAT_ARGB8888 6
#define RADEON_TXFORMAT_RGBA8888 7 #define RADEON_TXFORMAT_RGBA8888 7
#define RADEON_TXFORMAT_VYUY422 10
#define RADEON_TXFORMAT_YVYU422 11
#define R200_PP_TXCBLEND_0 0x2f00 #define R200_PP_TXCBLEND_0 0x2f00
#define R200_PP_TXCBLEND_1 0x2f10 #define R200_PP_TXCBLEND_1 0x2f10
......
/* radeon_mem.c -- Simple agp/fb memory manager for radeon -*- linux-c -*-
*
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
*
* The Weather Channel (TM) funded Tungsten Graphics to develop the
* initial release of the Radeon 8500 driver under the XFree86 license.
* This notice must be preserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "radeon.h"
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
/* Interrupts - Used for device synchronization and flushing in the
* following circumstances:
*
* - Exclusive FB access with hw idle:
* - Wait for GUI Idle (?) interrupt, then do normal flush.
*
* - Frame throttling, NV_fence:
* - Drop marker irq's into command stream ahead of time.
* - Wait on irq's with lock *not held*
* - Check each for termination condition
*
* - Internally in cp_getbuffer, etc:
* - as above, but wait with lock held???
*
* NOTE: These functions are misleadingly named -- the irq's aren't
* tied to dma at all, this is just a hangover from dri prehistory.
*/
void DRM(dma_service)( DRM_IRQ_ARGS )
{
drm_device_t *dev = (drm_device_t *) arg;
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
u32 temp;
/* Need to wait for fifo to drain?
*/
temp = RADEON_READ(RADEON_GEN_INT_STATUS);
temp = temp & RADEON_SW_INT_TEST_ACK;
if (temp == 0) return;
RADEON_WRITE(RADEON_GEN_INT_STATUS, temp);
atomic_inc(&dev_priv->irq_received);
#ifdef __linux__
queue_task(&dev->tq, &tq_immediate);
mark_bh(IMMEDIATE_BH);
#endif /* __linux__ */
#ifdef __FreeBSD__
taskqueue_enqueue(taskqueue_swi, &dev->task);
#endif /* __FreeBSD__ */
}
void DRM(dma_immediate_bh)( DRM_TASKQUEUE_ARGS )
{
drm_device_t *dev = (drm_device_t *) arg;
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
#ifdef __linux__
wake_up_interruptible(&dev_priv->irq_queue);
#endif /* __linux__ */
#ifdef __FreeBSD__
wakeup( &dev_priv->irq_queue );
#endif
}
int radeon_emit_irq(drm_device_t *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
atomic_inc(&dev_priv->irq_emitted);
BEGIN_RING(2);
OUT_RING( CP_PACKET0( RADEON_GEN_INT_STATUS, 0 ) );
OUT_RING( RADEON_SW_INT_FIRE );
ADVANCE_RING();
COMMIT_RING();
return atomic_read(&dev_priv->irq_emitted);
}
int radeon_wait_irq(drm_device_t *dev, int irq_nr)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
#ifdef __linux__
DECLARE_WAITQUEUE(entry, current);
unsigned long end = jiffies + HZ*3;
#endif /* __linux__ */
int ret = 0;
if (atomic_read(&dev_priv->irq_received) >= irq_nr)
return 0;
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
#ifdef __linux__
add_wait_queue(&dev_priv->irq_queue, &entry);
for (;;) {
current->state = TASK_INTERRUPTIBLE;
if (atomic_read(&dev_priv->irq_received) >= irq_nr)
break;
if((signed)(end - jiffies) <= 0) {
ret = -EBUSY; /* Lockup? Missed irq? */
break;
}
schedule_timeout(HZ*3);
if (signal_pending(current)) {
ret = -EINTR;
break;
}
}
current->state = TASK_RUNNING;
remove_wait_queue(&dev_priv->irq_queue, &entry);
return ret;
#endif /* __linux__ */
#ifdef __FreeBSD__
ret = tsleep( &dev_priv->irq_queue, PZERO | PCATCH, \
"rdnirq", 3*hz );
if ( (ret == EWOULDBLOCK) || (ret == EINTR) )
return DRM_ERR(EBUSY);
return ret;
#endif /* __FreeBSD__ */
}
int radeon_emit_and_wait_irq(drm_device_t *dev)
{
return radeon_wait_irq( dev, radeon_emit_irq(dev) );
}
/* Needs the lock as it touches the ring.
*/
int radeon_irq_emit( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_irq_emit_t emit;
int result;
LOCK_TEST_WITH_RETURN( dev );
if ( !dev_priv ) {
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
return DRM_ERR(EINVAL);
}
DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t *)data,
sizeof(emit) );
result = radeon_emit_irq( dev );
if ( DRM_COPY_TO_USER( emit.irq_seq, &result, sizeof(int) ) ) {
DRM_ERROR( "copy_to_user\n" );
return DRM_ERR(EFAULT);
}
return 0;
}
/* Doesn't need the hardware lock.
*/
int radeon_irq_wait( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_irq_wait_t irqwait;
if ( !dev_priv ) {
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
return DRM_ERR(EINVAL);
}
DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t *)data,
sizeof(irqwait) );
return radeon_wait_irq( dev, irqwait.irq_seq );
}
/* radeon_mem.c -- Simple agp/fb memory manager for radeon -*- linux-c -*-
*
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
*
* The Weather Channel (TM) funded Tungsten Graphics to develop the
* initial release of the Radeon 8500 driver under the XFree86 license.
* This notice must be preserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "radeon.h"
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
/* Very simple allocator for agp memory, working on a static range
* already mapped into each client's address space.
*/
static struct mem_block *split_block(struct mem_block *p, int start, int size,
int pid )
{
/* Maybe cut off the start of an existing block */
if (start > p->start) {
struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock));
if (!newblock)
goto out;
newblock->start = start;
newblock->size = p->size - (start - p->start);
newblock->pid = 0;
newblock->next = p->next;
newblock->prev = p;
p->next->prev = newblock;
p->next = newblock;
p->size -= newblock->size;
p = newblock;
}
/* Maybe cut off the end of an existing block */
if (size < p->size) {
struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock));
if (!newblock)
goto out;
newblock->start = start + size;
newblock->size = p->size - size;
newblock->pid = 0;
newblock->next = p->next;
newblock->prev = p;
p->next->prev = newblock;
p->next = newblock;
p->size = size;
}
out:
/* Our block is in the middle */
p->pid = pid;
return p;
}
static struct mem_block *alloc_block( struct mem_block *heap, int size,
int align2, int pid )
{
struct mem_block *p;
int mask = (1 << align2)-1;
for (p = heap->next ; p != heap ; p = p->next) {
int start = (p->start + mask) & ~mask;
if (p->pid == 0 && start + size <= p->start + p->size)
return split_block( p, start, size, pid );
}
return NULL;
}
static struct mem_block *find_block( struct mem_block *heap, int start )
{
struct mem_block *p;
for (p = heap->next ; p != heap ; p = p->next)
if (p->start == start)
return p;
return NULL;
}
static void free_block( struct mem_block *p )
{
p->pid = 0;
/* Assumes a single contiguous range. Needs a special pid in
* 'heap' to stop it being subsumed.
*/
if (p->next->pid == 0) {
struct mem_block *q = p->next;
p->size += q->size;
p->next = q->next;
p->next->prev = p;
DRM_FREE(p);
}
if (p->prev->pid == 0) {
struct mem_block *q = p->prev;
q->size += p->size;
q->next = p->next;
q->next->prev = q;
DRM_FREE(p);
}
}
static void print_heap( struct mem_block *heap )
{
struct mem_block *p;
for (p = heap->next ; p != heap ; p = p->next)
DRM_DEBUG("0x%x..0x%x (0x%x) -- owner %d\n",
p->start, p->start + p->size,
p->size, p->pid);
}
/* Initialize. How to check for an uninitialized heap?
*/
static int init_heap(struct mem_block **heap, int start, int size)
{
struct mem_block *blocks = DRM_MALLOC(sizeof(*blocks));
if (!blocks)
return -ENOMEM;
*heap = DRM_MALLOC(sizeof(**heap));
if (!*heap) {
DRM_FREE( blocks );
return -ENOMEM;
}
blocks->start = start;
blocks->size = size;
blocks->pid = 0;
blocks->next = blocks->prev = *heap;
memset( *heap, 0, sizeof(**heap) );
(*heap)->pid = -1;
(*heap)->next = (*heap)->prev = blocks;
return 0;
}
/* Free all blocks associated with the releasing pid.
*/
void radeon_mem_release( struct mem_block *heap )
{
int pid = DRM_CURRENTPID;
struct mem_block *p;
if (!heap || !heap->next)
return;
for (p = heap->next ; p != heap ; p = p->next) {
if (p->pid == pid)
p->pid = 0;
}
/* Assumes a single contiguous range. Needs a special pid in
* 'heap' to stop it being subsumed.
*/
for (p = heap->next ; p != heap ; p = p->next) {
while (p->pid == 0 && p->next->pid == 0) {
struct mem_block *q = p->next;
p->size += q->size;
p->next = q->next;
p->next->prev = p;
DRM_FREE(q);
}
}
}
/* Shutdown.
*/
void radeon_mem_takedown( struct mem_block **heap )
{
struct mem_block *p;
if (!*heap)
return;
for (p = (*heap)->next ; p != *heap ; ) {
struct mem_block *q = p;
p = p->next;
DRM_FREE(q);
}
DRM_FREE( *heap );
*heap = 0;
}
/* IOCTL HANDLERS */
static struct mem_block **get_heap( drm_radeon_private_t *dev_priv,
int region )
{
switch( region ) {
case RADEON_MEM_REGION_AGP:
return &dev_priv->agp_heap;
case RADEON_MEM_REGION_FB:
return &dev_priv->fb_heap;
default:
return 0;
}
}
int radeon_mem_alloc( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_mem_alloc_t alloc;
struct mem_block *block, **heap;
if ( !dev_priv ) {
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
return DRM_ERR(EINVAL);
}
DRM_COPY_FROM_USER_IOCTL( alloc, (drm_radeon_mem_alloc_t *)data,
sizeof(alloc) );
heap = get_heap( dev_priv, alloc.region );
if (!heap || !*heap)
return DRM_ERR(EFAULT);
/* Make things easier on ourselves: all allocations at least
* 4k aligned.
*/
if (alloc.alignment < 12)
alloc.alignment = 12;
block = alloc_block( *heap, alloc.size, alloc.alignment,
DRM_CURRENTPID );
if (!block)
return DRM_ERR(ENOMEM);
if ( DRM_COPY_TO_USER( alloc.region_offset, &block->start,
sizeof(int) ) ) {
DRM_ERROR( "copy_to_user\n" );
return DRM_ERR(EFAULT);
}
return 0;
}
int radeon_mem_free( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_mem_free_t memfree;
struct mem_block *block, **heap;
if ( !dev_priv ) {
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
return DRM_ERR(EINVAL);
}
DRM_COPY_FROM_USER_IOCTL( memfree, (drm_radeon_mem_free_t *)data,
sizeof(memfree) );
heap = get_heap( dev_priv, memfree.region );
if (!heap || !*heap)
return DRM_ERR(EFAULT);
block = find_block( *heap, memfree.region_offset );
if (!block)
return DRM_ERR(EFAULT);
if (block->pid != DRM_CURRENTPID)
return DRM_ERR(EPERM);
free_block( block );
return 0;
}
int radeon_mem_init_heap( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_mem_init_heap_t initheap;
struct mem_block **heap;
if ( !dev_priv ) {
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
return DRM_ERR(EINVAL);
}
DRM_COPY_FROM_USER_IOCTL( initheap, (drm_radeon_mem_init_heap_t *)data,
sizeof(initheap) );
heap = get_heap( dev_priv, initheap.region );
if (!heap)
return DRM_ERR(EFAULT);
if (*heap) {
DRM_ERROR("heap already initialized?");
return DRM_ERR(EFAULT);
}
return init_heap( heap, initheap.start, initheap.size );
}
...@@ -719,7 +719,6 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) ...@@ -719,7 +719,6 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev )
RING_LOCALS; RING_LOCALS;
DRM_DEBUG( "\n" ); DRM_DEBUG( "\n" );
/* Do some trivial performance monitoring... /* Do some trivial performance monitoring...
*/ */
if (dev_priv->do_boxes) if (dev_priv->do_boxes)
...@@ -1088,6 +1087,8 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, ...@@ -1088,6 +1087,8 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev,
case RADEON_TXFORMAT_ARGB1555: case RADEON_TXFORMAT_ARGB1555:
case RADEON_TXFORMAT_RGB565: case RADEON_TXFORMAT_RGB565:
case RADEON_TXFORMAT_ARGB4444: case RADEON_TXFORMAT_ARGB4444:
case RADEON_TXFORMAT_VYUY422:
case RADEON_TXFORMAT_YVYU422:
format = RADEON_COLOR_FORMAT_RGB565; format = RADEON_COLOR_FORMAT_RGB565;
tex_width = tex->width * 2; tex_width = tex->width * 2;
blit_width = image->width * 2; blit_width = image->width * 2;
...@@ -1226,6 +1227,7 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, ...@@ -1226,6 +1227,7 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev,
return ret; return ret;
} }
static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple ) static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
...@@ -1306,6 +1308,9 @@ static int radeon_do_init_pageflip( drm_device_t *dev ) ...@@ -1306,6 +1308,9 @@ static int radeon_do_init_pageflip( drm_device_t *dev )
return 0; return 0;
} }
/* Called whenever a client dies, from DRM(release).
* NOTE: Lock isn't necessarily held when this is called!
*/
int radeon_do_cleanup_pageflip( drm_device_t *dev ) int radeon_do_cleanup_pageflip( drm_device_t *dev )
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
...@@ -1936,14 +1941,18 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev, ...@@ -1936,14 +1941,18 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
if ( i < cmdbuf->nbox ) { if ( i < cmdbuf->nbox ) {
if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) )) if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
return DRM_ERR(EFAULT); return DRM_ERR(EFAULT);
/* FIXME The second and subsequent times round this loop, send a /* FIXME The second and subsequent times round
* WAIT_UNTIL_3D_IDLE before calling emit_clip_rect(). This * this loop, send a WAIT_UNTIL_3D_IDLE before
* fixes a lockup on fast machines when sending several * calling emit_clip_rect(). This fixes a
* cliprects with a cmdbuf, as when waving a 2D window over * lockup on fast machines when sending
* a 3D window. Something in the commands from user space * several cliprects with a cmdbuf, as when
* seems to hang the card when they're sent several times * waving a 2D window over a 3D
* in a row. That would be the correct place to fix it but * window. Something in the commands from user
* this works around it until I can figure that out - Tim Smith */ * space seems to hang the card when they're
* sent several times in a row. That would be
* the correct place to fix it but this works
* around it until I can figure that out - Tim
* Smith */
if ( i ) { if ( i ) {
BEGIN_RING( 2 ); BEGIN_RING( 2 );
RADEON_WAIT_UNTIL_3D_IDLE(); RADEON_WAIT_UNTIL_3D_IDLE();
...@@ -1967,6 +1976,34 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev, ...@@ -1967,6 +1976,34 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
} }
static int radeon_emit_wait( drm_device_t *dev, int flags )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
switch (flags) {
case RADEON_WAIT_2D:
BEGIN_RING( 2 );
RADEON_WAIT_UNTIL_2D_IDLE();
ADVANCE_RING();
break;
case RADEON_WAIT_3D:
BEGIN_RING( 2 );
RADEON_WAIT_UNTIL_3D_IDLE();
ADVANCE_RING();
break;
case RADEON_WAIT_2D|RADEON_WAIT_3D:
BEGIN_RING( 2 );
RADEON_WAIT_UNTIL_IDLE();
ADVANCE_RING();
break;
default:
return DRM_ERR(EINVAL);
}
return 0;
}
int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
{ {
...@@ -1989,7 +2026,6 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) ...@@ -1989,7 +2026,6 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data, DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data,
sizeof(cmdbuf) ); sizeof(cmdbuf) );
DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
RING_SPACE_TEST_WITH_RETURN( dev_priv ); RING_SPACE_TEST_WITH_RETURN( dev_priv );
VB_AGE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv );
...@@ -2080,6 +2116,14 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) ...@@ -2080,6 +2116,14 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
break; break;
case RADEON_CMD_WAIT:
DRM_DEBUG("RADEON_CMD_WAIT\n");
if (radeon_emit_wait( dev, header.wait.flags )) {
DRM_ERROR("radeon_emit_wait failed\n");
return DRM_ERR(EINVAL);
}
break;
default: default:
DRM_ERROR("bad cmd_type %d at %p\n", DRM_ERROR("bad cmd_type %d at %p\n",
header.header.cmd_type, header.header.cmd_type,
...@@ -2128,6 +2172,12 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS ) ...@@ -2128,6 +2172,12 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
dev_priv->stats.last_clear_reads++; dev_priv->stats.last_clear_reads++;
value = GET_SCRATCH( 2 ); value = GET_SCRATCH( 2 );
break; break;
case RADEON_PARAM_IRQ_ACTIVE:
value = dev->irq ? 1 : 0;
break;
case RADEON_PARAM_AGP_BASE:
value = dev_priv->agp_vm_start;
break;
default: default:
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
......
...@@ -980,7 +980,7 @@ static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) ...@@ -980,7 +980,7 @@ static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
best = NULL; best = NULL;
drive = hwgroup->drive; drive = hwgroup->drive;
do { do {
if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) { if (!blk_queue_empty(&drive->queue) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) {
if (!best if (!best
|| (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
|| (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
......
...@@ -380,18 +380,21 @@ static ssize_t mousedev_read(struct file * file, char * buffer, size_t count, lo ...@@ -380,18 +380,21 @@ static ssize_t mousedev_read(struct file * file, char * buffer, size_t count, lo
if (!list->ready && !list->buffer) { if (!list->ready && !list->buffer) {
add_wait_queue(&list->mousedev->wait, &wait); add_wait_queue(&list->mousedev->wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
while (!list->ready) { for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (file->f_flags & O_NONBLOCK) { retval = 0;
retval = -EAGAIN; if (list->ready || list->buffer)
break; break;
}
if (signal_pending(current)) { retval = -EAGAIN;
retval = -ERESTARTSYS; if (file->f_flags & O_NONBLOCK)
break;
retval = -ERESTARTSYS;
if (signal_pending(current))
break; break;
}
schedule(); schedule();
} }
......
...@@ -648,7 +648,7 @@ int dbNextAG(struct inode *ipbmap) ...@@ -648,7 +648,7 @@ int dbNextAG(struct inode *ipbmap)
agpref = bmp->db_agpref; agpref = bmp->db_agpref;
if ((atomic_read(&bmp->db_active[agpref]) == 0) && if ((atomic_read(&bmp->db_active[agpref]) == 0) &&
(bmp->db_agfree[agpref] >= avgfree)) (bmp->db_agfree[agpref] >= avgfree))
goto found; goto unlock;
/* From the last preferred ag, find the next one with at least /* From the last preferred ag, find the next one with at least
* average free space. * average free space.
...@@ -660,9 +660,12 @@ int dbNextAG(struct inode *ipbmap) ...@@ -660,9 +660,12 @@ int dbNextAG(struct inode *ipbmap)
if (atomic_read(&bmp->db_active[agpref])) if (atomic_read(&bmp->db_active[agpref]))
/* open file is currently growing in this ag */ /* open file is currently growing in this ag */
continue; continue;
if (bmp->db_agfree[agpref] >= avgfree) if (bmp->db_agfree[agpref] >= avgfree) {
goto found; /* Return this one */
else if (bmp->db_agfree[agpref] > hwm) { bmp->db_agpref = agpref;
goto unlock;
} else if (bmp->db_agfree[agpref] > hwm) {
/* Less than avg. freespace, but best so far */
hwm = bmp->db_agfree[agpref]; hwm = bmp->db_agfree[agpref];
next_best = agpref; next_best = agpref;
} }
...@@ -673,12 +676,9 @@ int dbNextAG(struct inode *ipbmap) ...@@ -673,12 +676,9 @@ int dbNextAG(struct inode *ipbmap)
* next best * next best
*/ */
if (next_best != -1) if (next_best != -1)
agpref = next_best; bmp->db_agpref = next_best;
/* else leave db_agpref unchanged */
/* else agpref should be back to its original value */ unlock:
found:
bmp->db_agpref = agpref;
BMAP_UNLOCK(bmp); BMAP_UNLOCK(bmp);
/* return the preferred group. /* return the preferred group.
......
...@@ -253,7 +253,7 @@ static int flock_make_lock(struct file *filp, ...@@ -253,7 +253,7 @@ static int flock_make_lock(struct file *filp,
fl->fl_file = filp; fl->fl_file = filp;
fl->fl_pid = current->pid; fl->fl_pid = current->pid;
fl->fl_flags = FL_FLOCK; fl->fl_flags = (cmd & LOCK_NB) ? FL_FLOCK : FL_FLOCK | FL_SLEEP;
fl->fl_type = type; fl->fl_type = type;
fl->fl_end = OFFSET_MAX; fl->fl_end = OFFSET_MAX;
......
...@@ -80,17 +80,6 @@ static __inline__ void ide_init_default_hwifs(void) ...@@ -80,17 +80,6 @@ static __inline__ void ide_init_default_hwifs(void)
#endif #endif
} }
#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
#define ide_check_region(from,extent) check_region((from), (extent))
#define ide_request_region(from,extent,name) request_region((from), (extent), (name))
#define ide_release_region(from,extent) release_region((from), (extent))
#define ide_ack_intr(hwif) (1)
#define ide_fix_driveid(id) do {} while (0)
#define ide_release_lock(lock) do {} while (0)
#define ide_get_lock(lock, hdlr, data) do {} while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __ASMalpha_IDE_H */ #endif /* __ASMalpha_IDE_H */
...@@ -93,14 +93,16 @@ static inline void __down_read(struct rw_semaphore *sem) ...@@ -93,14 +93,16 @@ static inline void __down_read(struct rw_semaphore *sem)
*/ */
static inline int __down_read_trylock(struct rw_semaphore *sem) static inline int __down_read_trylock(struct rw_semaphore *sem)
{ {
long res, tmp; long old, new, res;
res = sem->count; res = sem->count;
do { do {
tmp = res + RWSEM_ACTIVE_READ_BIAS; new = res + RWSEM_ACTIVE_READ_BIAS;
if (tmp <= 0) if (new <= 0)
break; break;
} while (cmpxchg(&sem->count, res, tmp) != res); old = res;
res = cmpxchg(&sem->count, old, new);
} while (res != old);
return res >= 0 ? 1 : 0; return res >= 0 ? 1 : 0;
} }
......
...@@ -331,6 +331,18 @@ ...@@ -331,6 +331,18 @@
#define __NR_removexattr 391 #define __NR_removexattr 391
#define __NR_lremovexattr 392 #define __NR_lremovexattr 392
#define __NR_fremovexattr 393 #define __NR_fremovexattr 393
#define __NR_futex 394
#define __NR_sched_setaffinity 395
#define __NR_sched_getaffinity 396
#define __NR_tuxcall 397
#define __NR_io_setup 398
#define __NR_io_destroy 399
#define __NR_io_getevents 400
#define __NR_io_submit 401
#define __NR_io_cancel 402
#define __NR_alloc_hugepages 403
#define __NR_free_hugepages 404
#define __NR_exit_group 405
#if defined(__GNUC__) #if defined(__GNUC__)
......
...@@ -85,7 +85,8 @@ static inline void br_read_lock (enum brlock_indices idx) ...@@ -85,7 +85,8 @@ static inline void br_read_lock (enum brlock_indices idx)
if (idx >= __BR_END) if (idx >= __BR_END)
__br_lock_usage_bug(); __br_lock_usage_bug();
read_lock(&__brlock_array[smp_processor_id()][idx]); preempt_disable();
_raw_read_lock(&__brlock_array[smp_processor_id()][idx]);
} }
static inline void br_read_unlock (enum brlock_indices idx) static inline void br_read_unlock (enum brlock_indices idx)
...@@ -109,6 +110,7 @@ static inline void br_read_lock (enum brlock_indices idx) ...@@ -109,6 +110,7 @@ static inline void br_read_lock (enum brlock_indices idx)
if (idx >= __BR_END) if (idx >= __BR_END)
__br_lock_usage_bug(); __br_lock_usage_bug();
preempt_disable();
ctr = &__brlock_array[smp_processor_id()][idx]; ctr = &__brlock_array[smp_processor_id()][idx];
lock = &__br_write_locks[idx].lock; lock = &__br_write_locks[idx].lock;
again: again:
...@@ -147,6 +149,7 @@ static inline void br_read_unlock (enum brlock_indices idx) ...@@ -147,6 +149,7 @@ static inline void br_read_unlock (enum brlock_indices idx)
wmb(); wmb();
(*ctr)--; (*ctr)--;
preempt_enable();
} }
#endif /* __BRLOCK_USE_ATOMICS */ #endif /* __BRLOCK_USE_ATOMICS */
......
...@@ -514,9 +514,10 @@ static inline void __netif_schedule(struct net_device *dev) ...@@ -514,9 +514,10 @@ static inline void __netif_schedule(struct net_device *dev)
{ {
if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) { if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) {
unsigned long flags; unsigned long flags;
int cpu = smp_processor_id(); int cpu;
local_irq_save(flags); local_irq_save(flags);
cpu = smp_processor_id();
dev->next_sched = softnet_data[cpu].output_queue; dev->next_sched = softnet_data[cpu].output_queue;
softnet_data[cpu].output_queue = dev; softnet_data[cpu].output_queue = dev;
cpu_raise_softirq(cpu, NET_TX_SOFTIRQ); cpu_raise_softirq(cpu, NET_TX_SOFTIRQ);
...@@ -563,10 +564,11 @@ static inline int netif_running(struct net_device *dev) ...@@ -563,10 +564,11 @@ static inline int netif_running(struct net_device *dev)
static inline void dev_kfree_skb_irq(struct sk_buff *skb) static inline void dev_kfree_skb_irq(struct sk_buff *skb)
{ {
if (atomic_dec_and_test(&skb->users)) { if (atomic_dec_and_test(&skb->users)) {
int cpu =smp_processor_id(); int cpu;
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
cpu = smp_processor_id();
skb->next = softnet_data[cpu].completion_queue; skb->next = softnet_data[cpu].completion_queue;
softnet_data[cpu].completion_queue = skb; softnet_data[cpu].completion_queue = skb;
cpu_raise_softirq(cpu, NET_TX_SOFTIRQ); cpu_raise_softirq(cpu, NET_TX_SOFTIRQ);
...@@ -726,9 +728,10 @@ static inline int netif_rx_schedule_prep(struct net_device *dev) ...@@ -726,9 +728,10 @@ static inline int netif_rx_schedule_prep(struct net_device *dev)
static inline void __netif_rx_schedule(struct net_device *dev) static inline void __netif_rx_schedule(struct net_device *dev)
{ {
unsigned long flags; unsigned long flags;
int cpu = smp_processor_id(); int cpu;
local_irq_save(flags); local_irq_save(flags);
cpu = smp_processor_id();
dev_hold(dev); dev_hold(dev);
list_add_tail(&dev->poll_list, &softnet_data[cpu].poll_list); list_add_tail(&dev->poll_list, &softnet_data[cpu].poll_list);
if (dev->quota < 0) if (dev->quota < 0)
...@@ -754,11 +757,12 @@ static inline int netif_rx_reschedule(struct net_device *dev, int undo) ...@@ -754,11 +757,12 @@ static inline int netif_rx_reschedule(struct net_device *dev, int undo)
{ {
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev)) {
unsigned long flags; unsigned long flags;
int cpu = smp_processor_id(); int cpu;
dev->quota += undo; dev->quota += undo;
local_irq_save(flags); local_irq_save(flags);
cpu = smp_processor_id();
list_add_tail(&dev->poll_list, &softnet_data[cpu].poll_list); list_add_tail(&dev->poll_list, &softnet_data[cpu].poll_list);
__cpu_raise_softirq(cpu, NET_RX_SOFTIRQ); __cpu_raise_softirq(cpu, NET_RX_SOFTIRQ);
local_irq_restore(flags); local_irq_restore(flags);
......
...@@ -86,9 +86,9 @@ extern void get_page_state(struct page_state *ret); ...@@ -86,9 +86,9 @@ extern void get_page_state(struct page_state *ret);
#define mod_page_state(member, delta) \ #define mod_page_state(member, delta) \
do { \ do { \
preempt_disable(); \ int cpu = get_cpu(); \
page_states[smp_processor_id()].member += (delta); \ page_states[cpu].member += (delta); \
preempt_enable(); \ put_cpu(); \
} while (0) } while (0)
#define inc_page_state(member) mod_page_state(member, 1UL) #define inc_page_state(member) mod_page_state(member, 1UL)
......
...@@ -131,9 +131,14 @@ int session_of_pgrp(int pgrp) ...@@ -131,9 +131,14 @@ int session_of_pgrp(int pgrp)
for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid)
if (p->session > 0) { if (p->session > 0) {
sid = p->session; sid = p->session;
break; goto out;
} }
p = find_task_by_pid(pgrp);
if (p)
sid = p->session;
out:
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
return sid; return sid;
} }
...@@ -621,7 +626,7 @@ NORET_TYPE void do_exit(long code) ...@@ -621,7 +626,7 @@ NORET_TYPE void do_exit(long code)
tsk->flags |= PF_EXITING; tsk->flags |= PF_EXITING;
del_timer_sync(&tsk->real_timer); del_timer_sync(&tsk->real_timer);
if (unlikely(preempt_count())) if (unlikely(in_atomic()))
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
current->comm, current->pid, current->comm, current->pid,
preempt_count()); preempt_count());
......
...@@ -472,6 +472,7 @@ void check_highmem_ptes(void) ...@@ -472,6 +472,7 @@ void check_highmem_ptes(void)
{ {
int idx, type; int idx, type;
preempt_disable();
for (type = 0; type < KM_TYPE_NR; type++) { for (type = 0; type < KM_TYPE_NR; type++) {
idx = type + KM_TYPE_NR*smp_processor_id(); idx = type + KM_TYPE_NR*smp_processor_id();
if (!pte_none(*(kmap_pte-idx))) { if (!pte_none(*(kmap_pte-idx))) {
...@@ -479,6 +480,7 @@ void check_highmem_ptes(void) ...@@ -479,6 +480,7 @@ void check_highmem_ptes(void)
BUG(); BUG();
} }
} }
preempt_enable();
} }
#endif #endif
...@@ -193,6 +193,11 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, ...@@ -193,6 +193,11 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
if (error) if (error)
goto fail; goto fail;
} }
/*
* Unless it returns an error, this function always sets *pprev to
* the first vma for which vma->vm_end >= end.
*/
*pprev = vma;
if (end != vma->vm_end) { if (end != vma->vm_end) {
error = split_vma(mm, vma, end, 0); error = split_vma(mm, vma, end, 0);
......
...@@ -1357,11 +1357,7 @@ void* kmem_cache_alloc_batch(kmem_cache_t* cachep, int flags) ...@@ -1357,11 +1357,7 @@ void* kmem_cache_alloc_batch(kmem_cache_t* cachep, int flags)
cc_entry(cc)[cc->avail++] = cc_entry(cc)[cc->avail++] =
kmem_cache_alloc_one_tail(cachep, slabp); kmem_cache_alloc_one_tail(cachep, slabp);
} }
/* spin_unlock(&cachep->spinlock);
* CAREFUL: do not enable preemption yet, the per-CPU
* entries rely on us being atomic.
*/
_raw_spin_unlock(&cachep->spinlock);
if (cc->avail) if (cc->avail)
return cc_entry(cc)[--cc->avail]; return cc_entry(cc)[--cc->avail];
...@@ -1389,8 +1385,6 @@ static inline void * __kmem_cache_alloc (kmem_cache_t *cachep, int flags) ...@@ -1389,8 +1385,6 @@ static inline void * __kmem_cache_alloc (kmem_cache_t *cachep, int flags)
STATS_INC_ALLOCMISS(cachep); STATS_INC_ALLOCMISS(cachep);
objp = kmem_cache_alloc_batch(cachep,flags); objp = kmem_cache_alloc_batch(cachep,flags);
local_irq_restore(save_flags); local_irq_restore(save_flags);
/* end of non-preemptible region */
preempt_enable();
if (!objp) if (!objp)
goto alloc_new_slab_nolock; goto alloc_new_slab_nolock;
return objp; return objp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment