diff options
55 files changed, 821 insertions, 799 deletions
@@ -611,8 +611,7 @@ S: USA N: Randolph Chung E: tausq@debian.org D: Linux/PA-RISC hacker -S: Los Altos, CA 94022 -S: USA +S: Hong Kong N: Juan Jose Ciarlante W: http://juanjox.kernelnotes.org/ @@ -3405,6 +3404,15 @@ S: Chudenicka 8 S: 10200 Prague 10, Hostivar S: Czech Republic +N: Thibaut Varene +E: T-Bone@parisc-linux.org +W: http://www.parisc-linux.org/ +P: 1024D/B7D2F063 E67C 0D43 A75E 12A5 BB1C FA2F 1E32 C3DA B7D2 F063 +D: PA-RISC port minion, PDC and GSCPS2 drivers, debuglocks and other bits +D: Some bits in an ARM port, S1D13XXX FB driver, random patches here and there +D: AD1889 sound driver +S: Paris, France + N: Heikki Vatiainen E: hessu@cs.tut.fi D: Co-author of Multi-Protocol Over ATM (MPOA), some LANE hacks diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 988844a169e..d016d672ec2 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -499,8 +499,12 @@ alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) dev = create_parisc_device(mod_path); if (dev->id.hw_type != HPHW_FAULTY) { - printk("Two devices have hardware path %s. Please file a bug with HP.\n" - "In the meantime, you could try rearranging your cards.\n", parisc_pathname(dev)); + printk(KERN_ERR "Two devices have hardware path [%s]. " + "IODC data for second device: " + "%02x%02x%02x%02x%02x%02x\n" + "Rearranging GSC cards sometimes helps\n", + parisc_pathname(dev), iodc_data[0], iodc_data[1], + iodc_data[3], iodc_data[4], iodc_data[5], iodc_data[6]); return NULL; } diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index c7e66ee5b08..9af4b22a6d7 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -1846,6 +1846,7 @@ sys_clone_wrapper: ldo -16(%r30),%r29 /* Reference param save area */ #endif + /* WARNING - Clobbers r19 and r21, userspace must save these! */ STREG %r2,PT_GR19(%r1) /* save for child */ STREG %r30,PT_GR21(%r1) BL sys_clone,%r2 diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index 1a1c6642273..8f563871e83 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c @@ -188,7 +188,7 @@ pat_query_module(ulong pcell_loc, ulong mod_index) temp = pa_pdc_cell.cba; dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path); if (!dev) { - return PDC_NE_MOD; + return PDC_OK; } /* alloc_pa_dev sets dev->hpa */ diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c index 0a331104ad5..4eada1bb27f 100644 --- a/arch/parisc/kernel/ioctl32.c +++ b/arch/parisc/kernel/ioctl32.c @@ -19,536 +19,6 @@ #define CODE #include "compat_ioctl.c" -/* Use this to get at 32-bit user passed pointers. - See sys_sparc32.c for description about these. */ -#define A(__x) ((unsigned long)(__x)) -/* The same for use with copy_from_user() and copy_to_user(). */ -#define B(__x) ((void *)(unsigned long)(__x)) - -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -/* This really belongs in include/linux/drm.h -DaveM */ -#include "../../../drivers/char/drm/drm.h" - -typedef struct drm32_version { - int version_major; /* Major version */ - int version_minor; /* Minor version */ - int version_patchlevel;/* Patch level */ - int name_len; /* Length of name buffer */ - u32 name; /* Name of driver */ - int date_len; /* Length of date buffer */ - u32 date; /* User-space buffer to hold date */ - int desc_len; /* Length of desc buffer */ - u32 desc; /* User-space buffer to hold desc */ -} drm32_version_t; -#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t) - -static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_version_t *uversion = (drm32_version_t *)arg; - char *name_ptr, *date_ptr, *desc_ptr; - u32 tmp1, tmp2, tmp3; - drm_version_t kversion; - mm_segment_t old_fs; - int ret; - - memset(&kversion, 0, sizeof(kversion)); - if (get_user(kversion.name_len, &uversion->name_len) || - get_user(kversion.date_len, &uversion->date_len) || - get_user(kversion.desc_len, &uversion->desc_len) || - get_user(tmp1, &uversion->name) || - get_user(tmp2, &uversion->date) || - get_user(tmp3, &uversion->desc)) - return -EFAULT; - - name_ptr = (char *) A(tmp1); - date_ptr = (char *) A(tmp2); - desc_ptr = (char *) A(tmp3); - - ret = -ENOMEM; - if (kversion.name_len && name_ptr) { - kversion.name = kmalloc(kversion.name_len, GFP_KERNEL); - if (!kversion.name) - goto out; - } - if (kversion.date_len && date_ptr) { - kversion.date = kmalloc(kversion.date_len, GFP_KERNEL); - if (!kversion.date) - goto out; - } - if (kversion.desc_len && desc_ptr) { - kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL); - if (!kversion.desc) - goto out; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion); - set_fs(old_fs); - - if (!ret) { - if ((kversion.name && - copy_to_user(name_ptr, kversion.name, kversion.name_len)) || - (kversion.date && - copy_to_user(date_ptr, kversion.date, kversion.date_len)) || - (kversion.desc && - copy_to_user(desc_ptr, kversion.desc, kversion.desc_len))) - ret = -EFAULT; - if (put_user(kversion.version_major, &uversion->version_major) || - put_user(kversion.version_minor, &uversion->version_minor) || - put_user(kversion.version_patchlevel, &uversion->version_patchlevel) || - put_user(kversion.name_len, &uversion->name_len) || - put_user(kversion.date_len, &uversion->date_len) || - put_user(kversion.desc_len, &uversion->desc_len)) - ret = -EFAULT; - } - -out: - kfree(kversion.name); - kfree(kversion.date); - kfree(kversion.desc); - return ret; -} - -typedef struct drm32_unique { - int unique_len; /* Length of unique */ - u32 unique; /* Unique name for driver instantiation */ -} drm32_unique_t; -#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t) -#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t) - -static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_unique_t *uarg = (drm32_unique_t *)arg; - drm_unique_t karg; - mm_segment_t old_fs; - char *uptr; - u32 tmp; - int ret; - - if (get_user(karg.unique_len, &uarg->unique_len)) - return -EFAULT; - karg.unique = NULL; - - if (get_user(tmp, &uarg->unique)) - return -EFAULT; - - uptr = (char *) A(tmp); - - if (uptr) { - karg.unique = kmalloc(karg.unique_len, GFP_KERNEL); - if (!karg.unique) - return -ENOMEM; - if (cmd == DRM32_IOCTL_SET_UNIQUE && - copy_from_user(karg.unique, uptr, karg.unique_len)) { - kfree(karg.unique); - return -EFAULT; - } - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - if (cmd == DRM32_IOCTL_GET_UNIQUE) - ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg); - else - ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg); - set_fs(old_fs); - - if (!ret) { - if (cmd == DRM32_IOCTL_GET_UNIQUE && - uptr != NULL && - copy_to_user(uptr, karg.unique, karg.unique_len)) - ret = -EFAULT; - if (put_user(karg.unique_len, &uarg->unique_len)) - ret = -EFAULT; - } - - kfree(karg.unique); - return ret; -} - -typedef struct drm32_map { - u32 offset; /* Requested physical address (0 for SAREA)*/ - u32 size; /* Requested physical size (bytes) */ - drm_map_type_t type; /* Type of memory to map */ - drm_map_flags_t flags; /* Flags */ - u32 handle; /* User-space: "Handle" to pass to mmap */ - /* Kernel-space: kernel-virtual address */ - int mtrr; /* MTRR slot used */ - /* Private data */ -} drm32_map_t; -#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t) - -static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_map_t *uarg = (drm32_map_t *) arg; - drm_map_t karg; - mm_segment_t old_fs; - u32 tmp; - int ret; - - ret = get_user(karg.offset, &uarg->offset); - ret |= get_user(karg.size, &uarg->size); - ret |= get_user(karg.type, &uarg->type); - ret |= get_user(karg.flags, &uarg->flags); - ret |= get_user(tmp, &uarg->handle); - ret |= get_user(karg.mtrr, &uarg->mtrr); - if (ret) - return -EFAULT; - - karg.handle = (void *) A(tmp); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - ret = put_user(karg.offset, &uarg->offset); - ret |= put_user(karg.size, &uarg->size); - ret |= put_user(karg.type, &uarg->type); - ret |= put_user(karg.flags, &uarg->flags); - tmp = (u32) (long)karg.handle; - ret |= put_user(tmp, &uarg->handle); - ret |= put_user(karg.mtrr, &uarg->mtrr); - if (ret) - ret = -EFAULT; - } - - return ret; -} - -typedef struct drm32_buf_info { - int count; /* Entries in list */ - u32 list; /* (drm_buf_desc_t *) */ -} drm32_buf_info_t; -#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t) - -static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg; - drm_buf_desc_t *ulist; - drm_buf_info_t karg; - mm_segment_t old_fs; - int orig_count, ret; - u32 tmp; - - if (get_user(karg.count, &uarg->count) || - get_user(tmp, &uarg->list)) - return -EFAULT; - - ulist = (drm_buf_desc_t *) A(tmp); - - orig_count = karg.count; - - karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL); - if (!karg.list) - return -EFAULT; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - if (karg.count <= orig_count && - (copy_to_user(ulist, karg.list, - karg.count * sizeof(drm_buf_desc_t)))) - ret = -EFAULT; - if (put_user(karg.count, &uarg->count)) - ret = -EFAULT; - } - - kfree(karg.list); - return ret; -} - -typedef struct drm32_buf_free { - int count; - u32 list; /* (int *) */ -} drm32_buf_free_t; -#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t) - -static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg; - drm_buf_free_t karg; - mm_segment_t old_fs; - int *ulist; - int ret; - u32 tmp; - - if (get_user(karg.count, &uarg->count) || - get_user(tmp, &uarg->list)) - return -EFAULT; - - ulist = (int *) A(tmp); - - karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL); - if (!karg.list) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int)))) - goto out; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg); - set_fs(old_fs); - -out: - kfree(karg.list); - return ret; -} - -typedef struct drm32_buf_pub { - int idx; /* Index into master buflist */ - int total; /* Buffer size */ - int used; /* Amount of buffer in use (for DMA) */ - u32 address; /* Address of buffer (void *) */ -} drm32_buf_pub_t; - -typedef struct drm32_buf_map { - int count; /* Length of buflist */ - u32 virtual; /* Mmaped area in user-virtual (void *) */ - u32 list; /* Buffer information (drm_buf_pub_t *) */ -} drm32_buf_map_t; -#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t) - -static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg; - drm32_buf_pub_t *ulist; - drm_buf_map_t karg; - mm_segment_t old_fs; - int orig_count, ret, i; - u32 tmp1, tmp2; - - if (get_user(karg.count, &uarg->count) || - get_user(tmp1, &uarg->virtual) || - get_user(tmp2, &uarg->list)) - return -EFAULT; - - karg.virtual = (void *) A(tmp1); - ulist = (drm32_buf_pub_t *) A(tmp2); - - orig_count = karg.count; - - karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL); - if (!karg.list) - return -ENOMEM; - - ret = -EFAULT; - for (i = 0; i < karg.count; i++) { - if (get_user(karg.list[i].idx, &ulist[i].idx) || - get_user(karg.list[i].total, &ulist[i].total) || - get_user(karg.list[i].used, &ulist[i].used) || - get_user(tmp1, &ulist[i].address)) - goto out; - - karg.list[i].address = (void *) A(tmp1); - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - for (i = 0; i < orig_count; i++) { - tmp1 = (u32) (long) karg.list[i].address; - if (put_user(karg.list[i].idx, &ulist[i].idx) || - put_user(karg.list[i].total, &ulist[i].total) || - put_user(karg.list[i].used, &ulist[i].used) || - put_user(tmp1, &ulist[i].address)) { - ret = -EFAULT; - goto out; - } - } - if (put_user(karg.count, &uarg->count)) - ret = -EFAULT; - } - -out: - kfree(karg.list); - return ret; -} - -typedef struct drm32_dma { - /* Indices here refer to the offset into - buflist in drm_buf_get_t. */ - int context; /* Context handle */ - int send_count; /* Number of buffers to send */ - u32 send_indices; /* List of handles to buffers (int *) */ - u32 send_sizes; /* Lengths of data to send (int *) */ - drm_dma_flags_t flags; /* Flags */ - int request_count; /* Number of buffers requested */ - int request_size; /* Desired size for buffers */ - u32 request_indices; /* Buffer information (int *) */ - u32 request_sizes; /* (int *) */ - int granted_count; /* Number of buffers granted */ -} drm32_dma_t; -#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t) - -/* RED PEN The DRM layer blindly dereferences the send/request - * indice/size arrays even though they are userland - * pointers. -DaveM - */ -static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_dma_t *uarg = (drm32_dma_t *) arg; - int *u_si, *u_ss, *u_ri, *u_rs; - drm_dma_t karg; - mm_segment_t old_fs; - int ret; - u32 tmp1, tmp2, tmp3, tmp4; - - karg.send_indices = karg.send_sizes = NULL; - karg.request_indices = karg.request_sizes = NULL; - - if (get_user(karg.context, &uarg->context) || - get_user(karg.send_count, &uarg->send_count) || - get_user(tmp1, &uarg->send_indices) || - get_user(tmp2, &uarg->send_sizes) || - get_user(karg.flags, &uarg->flags) || - get_user(karg.request_count, &uarg->request_count) || - get_user(karg.request_size, &uarg->request_size) || - get_user(tmp3, &uarg->request_indices) || - get_user(tmp4, &uarg->request_sizes) || - get_user(karg.granted_count, &uarg->granted_count)) - return -EFAULT; - - u_si = (int *) A(tmp1); - u_ss = (int *) A(tmp2); - u_ri = (int *) A(tmp3); - u_rs = (int *) A(tmp4); - - if (karg.send_count) { - karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); - karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); - - ret = -ENOMEM; - if (!karg.send_indices || !karg.send_sizes) - goto out; - - ret = -EFAULT; - if (copy_from_user(karg.send_indices, u_si, - (karg.send_count * sizeof(int))) || - copy_from_user(karg.send_sizes, u_ss, - (karg.send_count * sizeof(int)))) - goto out; - } - - if (karg.request_count) { - karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); - karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); - - ret = -ENOMEM; - if (!karg.request_indices || !karg.request_sizes) - goto out; - - ret = -EFAULT; - if (copy_from_user(karg.request_indices, u_ri, - (karg.request_count * sizeof(int))) || - copy_from_user(karg.request_sizes, u_rs, - (karg.request_count * sizeof(int)))) - goto out; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - if (put_user(karg.context, &uarg->context) || - put_user(karg.send_count, &uarg->send_count) || - put_user(karg.flags, &uarg->flags) || - put_user(karg.request_count, &uarg->request_count) || - put_user(karg.request_size, &uarg->request_size) || - put_user(karg.granted_count, &uarg->granted_count)) - ret = -EFAULT; - - if (karg.send_count) { - if (copy_to_user(u_si, karg.send_indices, - (karg.send_count * sizeof(int))) || - copy_to_user(u_ss, karg.send_sizes, - (karg.send_count * sizeof(int)))) - ret = -EFAULT; - } - if (karg.request_count) { - if (copy_to_user(u_ri, karg.request_indices, - (karg.request_count * sizeof(int))) || - copy_to_user(u_rs, karg.request_sizes, - (karg.request_count * sizeof(int)))) - ret = -EFAULT; - } - } - -out: - kfree(karg.send_indices); - kfree(karg.send_sizes); - kfree(karg.request_indices); - kfree(karg.request_sizes); - return ret; -} - -typedef struct drm32_ctx_res { - int count; - u32 contexts; /* (drm_ctx_t *) */ -} drm32_ctx_res_t; -#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t) - -static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg; - drm_ctx_t *ulist; - drm_ctx_res_t karg; - mm_segment_t old_fs; - int orig_count, ret; - u32 tmp; - - karg.contexts = NULL; - if (get_user(karg.count, &uarg->count) || - get_user(tmp, &uarg->contexts)) - return -EFAULT; - - ulist = (drm_ctx_t *) A(tmp); - - orig_count = karg.count; - if (karg.count && ulist) { - karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL); - if (!karg.contexts) - return -ENOMEM; - if (copy_from_user(karg.contexts, ulist, - (karg.count * sizeof(drm_ctx_t)))) { - kfree(karg.contexts); - return -EFAULT; - } - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - if (orig_count) { - if (copy_to_user(ulist, karg.contexts, - (orig_count * sizeof(drm_ctx_t)))) - ret = -EFAULT; - } - if (put_user(karg.count, &uarg->count)) - ret = -EFAULT; - } - - kfree(karg.contexts); - return ret; -} - -#endif - #define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, NULL }, #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl) @@ -561,11 +31,6 @@ IOCTL_TABLE_START #define DECLARES #include "compat_ioctl.c" -/* PA-specific ioctls */ -COMPATIBLE_IOCTL(PA_PERF_ON) -COMPATIBLE_IOCTL(PA_PERF_OFF) -COMPATIBLE_IOCTL(PA_PERF_VERSION) - /* And these ioctls need translation */ HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc) HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc) @@ -590,17 +55,6 @@ HANDLE_IOCTL(RTC_EPOCH_READ, w_long) COMPATIBLE_IOCTL(RTC_EPOCH_SET) #endif -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version); -HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique); -HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique); -HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap); -HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs); -HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs); -HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs); -HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma); -HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx); -#endif /* DRM */ IOCTL_TABLE_END int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 006385dbee6..197936d9359 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -30,6 +30,9 @@ #include <linux/seq_file.h> #include <linux/spinlock.h> #include <linux/types.h> +#include <asm/io.h> + +#include <asm/smp.h> #undef PARISC_IRQ_CR16_COUNTS @@ -43,26 +46,34 @@ extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *); */ static volatile unsigned long cpu_eiem = 0; -static void cpu_set_eiem(void *info) -{ - set_eiem((unsigned long) info); -} - -static inline void cpu_disable_irq(unsigned int irq) +static void cpu_disable_irq(unsigned int irq) { unsigned long eirr_bit = EIEM_MASK(irq); cpu_eiem &= ~eirr_bit; - on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1); + /* Do nothing on the other CPUs. If they get this interrupt, + * The & cpu_eiem in the do_cpu_irq_mask() ensures they won't + * handle it, and the set_eiem() at the bottom will ensure it + * then gets disabled */ } static void cpu_enable_irq(unsigned int irq) { unsigned long eirr_bit = EIEM_MASK(irq); - mtctl(eirr_bit, 23); /* clear EIRR bit before unmasking */ cpu_eiem |= eirr_bit; - on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1); + + /* FIXME: while our interrupts aren't nested, we cannot reset + * the eiem mask if we're already in an interrupt. Once we + * implement nested interrupts, this can go away + */ + if (!in_interrupt()) + set_eiem(cpu_eiem); + + /* This is just a simple NOP IPI. But what it does is cause + * all the other CPUs to do a set_eiem(cpu_eiem) at the end + * of the interrupt handler */ + smp_send_all_nop(); } static unsigned int cpu_startup_irq(unsigned int irq) @@ -74,6 +85,35 @@ static unsigned int cpu_startup_irq(unsigned int irq) void no_ack_irq(unsigned int irq) { } void no_end_irq(unsigned int irq) { } +#ifdef CONFIG_SMP +int cpu_check_affinity(unsigned int irq, cpumask_t *dest) +{ + int cpu_dest; + + /* timer and ipi have to always be received on all CPUs */ + if (irq == TIMER_IRQ || irq == IPI_IRQ) { + /* Bad linux design decision. The mask has already + * been set; we must reset it */ + irq_affinity[irq] = CPU_MASK_ALL; + return -EINVAL; + } + + /* whatever mask they set, we just allow one CPU */ + cpu_dest = first_cpu(*dest); + *dest = cpumask_of_cpu(cpu_dest); + + return 0; +} + +static void cpu_set_affinity_irq(unsigned int irq, cpumask_t dest) +{ + if (cpu_check_affinity(irq, &dest)) + return; + + irq_affinity[irq] = dest; +} +#endif + static struct hw_interrupt_type cpu_interrupt_type = { .typename = "CPU", .startup = cpu_startup_irq, @@ -82,7 +122,9 @@ static struct hw_interrupt_type cpu_interrupt_type = { .disable = cpu_disable_irq, .ack = no_ack_irq, .end = no_end_irq, -// .set_affinity = cpu_set_affinity_irq, +#ifdef CONFIG_SMP + .set_affinity = cpu_set_affinity_irq, +#endif }; int show_interrupts(struct seq_file *p, void *v) @@ -219,6 +261,17 @@ int txn_alloc_irq(unsigned int bits_wide) return -1; } + +unsigned long txn_affinity_addr(unsigned int irq, int cpu) +{ +#ifdef CONFIG_SMP + irq_affinity[irq] = cpumask_of_cpu(cpu); +#endif + + return cpu_data[cpu].txn_addr; +} + + unsigned long txn_alloc_addr(unsigned int virt_irq) { static int next_cpu = -1; @@ -233,7 +286,7 @@ unsigned long txn_alloc_addr(unsigned int virt_irq) if (next_cpu >= NR_CPUS) next_cpu = 0; /* nothing else, assign monarch */ - return cpu_data[next_cpu].txn_addr; + return txn_affinity_addr(virt_irq, next_cpu); } @@ -250,10 +303,11 @@ void do_cpu_irq_mask(struct pt_regs *regs) irq_enter(); /* - * Only allow interrupt processing to be interrupted by the - * timer tick + * Don't allow TIMER or IPI nested interrupts. + * Allowing any single interrupt to nest can lead to that CPU + * handling interrupts with all enabled interrupts unmasked. */ - set_eiem(EIEM_MASK(TIMER_IRQ)); + set_eiem(0UL); /* 1) only process IRQs that are enabled/unmasked (cpu_eiem) * 2) We loop here on EIRR contents in order to avoid @@ -267,23 +321,41 @@ void do_cpu_irq_mask(struct pt_regs *regs) if (!eirr_val) break; - if (eirr_val & EIEM_MASK(TIMER_IRQ)) - set_eiem(0); - mtctl(eirr_val, 23); /* reset bits we are going to process */ /* Work our way from MSb to LSb...same order we alloc EIRs */ for (irq = TIMER_IRQ; eirr_val && bit; bit>>=1, irq++) { +#ifdef CONFIG_SMP + cpumask_t dest = irq_affinity[irq]; +#endif if (!(bit & eirr_val)) continue; /* clear bit in mask - can exit loop sooner */ eirr_val &= ~bit; +#ifdef CONFIG_SMP + /* FIXME: because generic set affinity mucks + * with the affinity before sending it to us + * we can get the situation where the affinity is + * wrong for our CPU type interrupts */ + if (irq != TIMER_IRQ && irq != IPI_IRQ && + !cpu_isset(smp_processor_id(), dest)) { + int cpu = first_cpu(dest); + + printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n", + irq, smp_processor_id(), cpu); + gsc_writel(irq + CPU_IRQ_BASE, + cpu_data[cpu].hpa); + continue; + } +#endif + __do_IRQ(irq, regs); } } - set_eiem(cpu_eiem); + + set_eiem(cpu_eiem); /* restore original mask */ irq_exit(); } @@ -291,12 +363,14 @@ void do_cpu_irq_mask(struct pt_regs *regs) static struct irqaction timer_action = { .handler = timer_interrupt, .name = "timer", + .flags = SA_INTERRUPT, }; #ifdef CONFIG_SMP static struct irqaction ipi_action = { .handler = ipi_interrupt, .name = "IPI", + .flags = SA_INTERRUPT, }; #endif diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index 44670d6e06f..f6fec62b6a2 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -196,8 +196,7 @@ static int perf_open(struct inode *inode, struct file *file); static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos); static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos); -static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg); +static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static void perf_start_counters(void); static int perf_stop_counters(uint32_t *raddr); static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num); @@ -438,48 +437,56 @@ static void perf_patch_images(void) * must be running on the processor that you wish to change. */ -static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long error_start; - uint32_t raddr[4]; + uint32_t raddr[4]; + int error = 0; + lock_kernel(); switch (cmd) { case PA_PERF_ON: /* Start the counters */ perf_start_counters(); - return 0; + break; case PA_PERF_OFF: error_start = perf_stop_counters(raddr); if (error_start != 0) { printk(KERN_ERR "perf_off: perf_stop_counters = %ld\n", error_start); - return -EFAULT; + error = -EFAULT; + break; } /* copy out the Counters */ if (copy_to_user((void __user *)arg, raddr, sizeof (raddr)) != 0) { - return -EFAULT; + error = -EFAULT; + break; } - return 0; + break; case PA_PERF_VERSION: /* Return the version # */ - return put_user(PERF_VERSION, (int *)arg); + error = put_user(PERF_VERSION, (int *)arg); + break; default: - break; + error = -ENOTTY; } - return -ENOTTY; + + unlock_kernel(); + + return error; } static struct file_operations perf_fops = { .llseek = no_llseek, .read = perf_read, .write = perf_write, - .ioctl = perf_ioctl, + .unlocked_ioctl = perf_ioctl, + .compat_ioctl = perf_ioctl, .open = perf_open, .release = perf_release }; diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index b6fe202a620..27160e8bf15 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -264,6 +264,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * sigkill. perhaps it should be put in the status * that it wants to exit. */ + ret = 0; DBG("sys_ptrace(KILL)\n"); if (child->exit_state == EXIT_ZOMBIE) /* already dead */ goto out_tsk; @@ -344,11 +345,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned int __user *) data); - goto out; + goto out_tsk; default: ret = ptrace_request(child, request, addr, data); - goto out; + goto out_tsk; } out_wake_notrap: diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 82c24e62ab6..3a25a7bd673 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -296,7 +296,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; unsigned long rp, usp; unsigned long haddr, sigframe_size; - struct siginfo si; int err = 0; #ifdef __LP64__ compat_int_t compat_val; diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index a9ecf646578..ce89da0f654 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -181,12 +181,19 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) while (ops) { unsigned long which = ffz(~ops); + ops &= ~(1 << which); + switch (which) { + case IPI_NOP: +#if (kDEBUG>=100) + printk(KERN_DEBUG "CPU%d IPI_NOP\n",this_cpu); +#endif /* kDEBUG */ + break; + case IPI_RESCHEDULE: #if (kDEBUG>=100) printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu); #endif /* kDEBUG */ - ops &= ~(1 << IPI_RESCHEDULE); /* * Reschedule callback. Everything to be * done is done by the interrupt return path. @@ -197,7 +204,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) #if (kDEBUG>=100) printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu); #endif /* kDEBUG */ - ops &= ~(1 << IPI_CALL_FUNC); { volatile struct smp_call_struct *data; void (*func)(void *info); @@ -231,7 +237,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) #if (kDEBUG>=100) printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu); #endif /* kDEBUG */ - ops &= ~(1 << IPI_CPU_START); #ifdef ENTRY_SYS_CPUS p->state = STATE_RUNNING; #endif @@ -241,7 +246,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) #if (kDEBUG>=100) printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu); #endif /* kDEBUG */ - ops &= ~(1 << IPI_CPU_STOP); #ifdef ENTRY_SYS_CPUS #else halt_processor(); @@ -252,13 +256,11 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) #if (kDEBUG>=100) printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu); #endif /* kDEBUG */ - ops &= ~(1 << IPI_CPU_TEST); break; default: printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n", this_cpu, which); - ops &= ~(1 << which); return IRQ_NONE; } /* Switch */ } /* while (ops) */ @@ -312,6 +314,12 @@ smp_send_start(void) { send_IPI_allbutself(IPI_CPU_START); } void smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); } +void +smp_send_all_nop(void) +{ + send_IPI_allbutself(IPI_NOP); +} + /** * Run a function on all other CPUs. @@ -338,6 +346,10 @@ smp_call_function (void (*func) (void *info), void *info, int retry, int wait) /* Can deadlock when called with interrupts disabled */ WARN_ON(irqs_disabled()); + + /* can also deadlock if IPIs are disabled */ + WARN_ON((get_eiem() & (1UL<<(CPU_IRQ_MAX - IPI_IRQ))) == 0); + data.func = func; data.info = info; diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index b29b76b42bb..d6616349289 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -164,7 +164,7 @@ linux_gateway_entry: #endif STREG %r2, TASK_PT_GR30(%r1) /* ... and save it */ - STREG %r20, TASK_PT_GR20(%r1) + STREG %r20, TASK_PT_GR20(%r1) /* Syscall number */ STREG %r21, TASK_PT_GR21(%r1) STREG %r22, TASK_PT_GR22(%r1) STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */ @@ -527,6 +527,7 @@ lws_compare_and_swap: We *must* giveup this call and fail. */ ldw 4(%sr2,%r20), %r28 /* Load thread register */ + /* WARNING: If cr27 cycles to the same value we have problems */ mfctl %cr27, %r21 /* Get current thread register */ cmpb,<>,n %r21, %r28, cas_lock /* Called recursive? */ b lws_exit /* Return error! */ diff --git a/block/as-iosched.c b/block/as-iosched.c index a78e160b59a..fbe050124ec 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/as-iosched.c - * * Anticipatory & deadline i/o scheduler. * * Copyright (C) 2002 Jens Axboe <axboe@suse.de> diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 2b64f5852bf..ee0bb41694b 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/cfq-iosched.c - * * CFQ, or complete fairness queueing, disk scheduler. * * Based on ideas from a previously unfinished io diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index 7929471d7df..9cbec09e841 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/deadline-iosched.c - * * Deadline i/o scheduler. * * Copyright (C) 2002 Jens Axboe <axboe@suse.de> diff --git a/block/elevator.c b/block/elevator.c index e4c58827bb4..6c3fc8a10bf 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/elevator.c - * * Block device elevator/IO-scheduler. * * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 5f52e30b43f..99c9ca6d599 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/ll_rw_blk.c - * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994, Karl Keyte: Added support for disk statistics * Elevator latency, (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e239a6c2923..a9e33db46e6 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1017,10 +1017,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, status = -ENOMEM; goto cleanup1; } - if (ioc->Request.Type.Direction == XFER_WRITE && - copy_from_user(buff[sg_used], data_ptr, sz)) { + if (ioc->Request.Type.Direction == XFER_WRITE) { + if (copy_from_user(buff[sg_used], data_ptr, sz)) { status = -ENOMEM; - goto cleanup1; + goto cleanup1; + } } else { memset(buff[sg_used], 0, sz); } @@ -1138,8 +1139,15 @@ static int revalidate_allvol(ctlr_info_t *host) for(i=0; i< NWD; i++) { struct gendisk *disk = host->gendisk[i]; - if (disk->flags & GENHD_FL_UP) - del_gendisk(disk); + if (disk) { + request_queue_t *q = disk->queue; + + if (disk->flags & GENHD_FL_UP) + del_gendisk(disk); + if (q) + blk_cleanup_queue(q); + put_disk(disk); + } } /* @@ -1453,10 +1461,13 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, * allows us to delete disk zero but keep the controller registered. */ if (h->gendisk[0] != disk){ - if (disk->flags & GENHD_FL_UP){ - blk_cleanup_queue(disk->queue); - del_gendisk(disk); - drv->queue = NULL; + if (disk) { + request_queue_t *q = disk->queue; + if (disk->flags & GENHD_FL_UP) + del_gendisk(disk); + if (q) + blk_cleanup_queue(q); + put_disk(disk); } } @@ -3225,9 +3236,14 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) /* remove it from the disk list */ for (j = 0; j < NWD; j++) { struct gendisk *disk = hba[i]->gendisk[j]; - if (disk->flags & GENHD_FL_UP) { - del_gendisk(disk); - blk_cleanup_queue(disk->queue); + if (disk) { + request_queue_t *q = disk->queue; + + if (disk->flags & GENHD_FL_UP) + del_gendisk(disk); + if (q) + blk_cleanup_queue(q); + put_disk(disk); } } diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index ed2bc87f475..31e649a9ff7 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -625,7 +625,7 @@ config BLK_DEV_NS87415 tristate "NS87415 chipset support" help This driver adds detection and support for the NS87415 chip - (used in SPARC64, among others). + (used mainly on SPARC64 and PA-RISC machines). Please read the comments at the top of <file:drivers/ide/pci/ns87415.c>. diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 5ea741f47fc..e73f81c2238 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -312,7 +312,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, int ret, length, hdr_len, copy_offset; int rmpp_active = 0; - if (count < sizeof (struct ib_user_mad)) + if (count < sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR) return -EINVAL; length = count - sizeof (struct ib_user_mad); diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 760c418d5bc..dd4e13303e9 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -730,15 +730,16 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) } if (attr_mask & IB_QP_ACCESS_FLAGS) { + qp_context->params2 |= + cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE ? + MTHCA_QP_BIT_RWE : 0); + /* - * Only enable RDMA/atomics if we have responder - * resources set to a non-zero value. + * Only enable RDMA reads and atomics if we have + * responder resources set to a non-zero value. */ if (qp->resp_depth) { qp_context->params2 |= - cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE ? - MTHCA_QP_BIT_RWE : 0); - qp_context->params2 |= cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_READ ? MTHCA_QP_BIT_RRE : 0); qp_context->params2 |= @@ -759,31 +760,27 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) if (qp->resp_depth && !attr->max_dest_rd_atomic) { /* * Lowering our responder resources to zero. - * Turn off RDMA/atomics as responder. - * (RWE/RRE/RAE in params2 already zero) + * Turn off reads RDMA and atomics as responder. + * (RRE/RAE in params2 already zero) */ - qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE | - MTHCA_QP_OPTPAR_RRE | + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE | MTHCA_QP_OPTPAR_RAE); } if (!qp->resp_depth && attr->max_dest_rd_atomic) { /* * Increasing our responder resources from - * zero. Turn on RDMA/atomics as appropriate. + * zero. Turn on RDMA reads and atomics as + * appropriate. */ qp_context->params2 |= - cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_WRITE ? - MTHCA_QP_BIT_RWE : 0); - qp_context->params2 |= cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_READ ? MTHCA_QP_BIT_RRE : 0); qp_context->params2 |= cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_ATOMIC ? MTHCA_QP_BIT_RAE : 0); - qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE | - MTHCA_QP_OPTPAR_RRE | + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE | MTHCA_QP_OPTPAR_RAE); } @@ -921,10 +918,12 @@ static void mthca_adjust_qp_caps(struct mthca_dev *dev, else qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE; - qp->sq.max_gs = max_data_size / sizeof (struct mthca_data_seg); - qp->rq.max_gs = (min(dev->limits.max_desc_sz, 1 << qp->rq.wqe_shift) - - sizeof (struct mthca_next_seg)) / - sizeof (struct mthca_data_seg); + qp->sq.max_gs = min_t(int, dev->limits.max_sg, + max_data_size / sizeof (struct mthca_data_seg)); + qp->rq.max_gs = min_t(int, dev->limits.max_sg, + (min(dev->limits.max_desc_sz, 1 << qp->rq.wqe_shift) - + sizeof (struct mthca_next_seg)) / + sizeof (struct mthca_data_seg)); } /* diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 321a3a10e69..ee9fe226ae9 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -802,13 +802,21 @@ static int srp_post_recv(struct srp_target_port *target) /* * Must be called with target->scsi_host->host_lock held to protect - * req_lim and tx_head. + * req_lim and tx_head. Lock cannot be dropped between call here and + * call to __srp_post_send(). */ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target) { if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE) return NULL; + if (unlikely(target->req_lim < 1)) { + if (printk_ratelimit()) + printk(KERN_DEBUG PFX "Target has req_lim %d\n", + target->req_lim); + return NULL; + } + return target->tx_ring[target->tx_head & SRP_SQ_SIZE]; } @@ -823,11 +831,6 @@ static int __srp_post_send(struct srp_target_port *target, struct ib_send_wr wr, *bad_wr; int ret = 0; - if (target->req_lim < 1) { - printk(KERN_ERR PFX "Target has req_lim %d\n", target->req_lim); - return -EAGAIN; - } - list.addr = iu->dma; list.length = len; list.lkey = target->srp_host->mr->lkey; @@ -1417,6 +1420,8 @@ static ssize_t srp_create_target(struct class_device *class_dev, if (!target_host) return -ENOMEM; + target_host->max_lun = SRP_MAX_LUN; + target = host_to_target(target_host); memset(target, 0, sizeof *target); diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index 4fec28a7136..b564f18caf7 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -54,6 +54,7 @@ enum { SRP_PORT_REDIRECT = 1, SRP_DLID_REDIRECT = 2, + SRP_MAX_LUN = 512, SRP_MAX_IU_LEN = 256, SRP_RQ_SHIFT = 6, diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 801c98f30e5..c82105920d7 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig @@ -110,7 +110,7 @@ config HISAX_16_3 config HISAX_TELESPCI bool "Teles PCI" - depends on PCI && (BROKEN || !(SPARC64 || PPC)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the Teles PCI. See <file:Documentation/isdn/README.HiSax> on how to configure it. @@ -238,7 +238,7 @@ config HISAX_MIC config HISAX_NETJET bool "NETjet card" - depends on PCI && (BROKEN || !(SPARC64 || PPC)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the NetJet from Traverse Technologies. @@ -249,7 +249,7 @@ config HISAX_NETJET config HISAX_NETJET_U bool "NETspider U card" - depends on PCI && (BROKEN || !(SPARC64 || PPC)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the Netspider U interface ISDN card from Traverse Technologies. @@ -317,7 +317,7 @@ config HISAX_GAZEL config HISAX_HFC_PCI bool "HFC PCI-Bus cards" - depends on PCI && (BROKEN || !(SPARC64 || PPC)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the HFC-S PCI 2BDS0 based cards. @@ -344,14 +344,14 @@ config HISAX_HFC_SX config HISAX_ENTERNOW_PCI bool "Formula-n enter:now PCI card" - depends on PCI && (BROKEN || !(SPARC64 || PPC)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the Formula-n enter:now PCI ISDN card. config HISAX_AMD7930 bool "Am7930 (EXPERIMENTAL)" - depends on EXPERIMENTAL && (SPARC32 || SPARC64) + depends on EXPERIMENTAL && SPARC help This enables HiSax support for the AMD7930 chips on some SPARCs. This code is not finished yet. diff --git a/drivers/isdn/pcbit/Kconfig b/drivers/isdn/pcbit/Kconfig index f06997faef1..0933881ab0c 100644 --- a/drivers/isdn/pcbit/Kconfig +++ b/drivers/isdn/pcbit/Kconfig @@ -3,7 +3,7 @@ # config ISDN_DRV_PCBIT tristate "PCBIT-D support" - depends on ISDN_I4L && ISA && (BROKEN || !PPC) + depends on ISDN_I4L && ISA && (BROKEN || X86) help This enables support for the PCBIT ISDN-card. This card is manufactured in Portugal by Octal. For running this card, diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 332e9953c55..cd0b1dccfb6 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -32,6 +32,7 @@ * */ +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 7a6aeae2c9f..22cd0455670 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -156,7 +156,7 @@ #define DRV_NAME "e100" #define DRV_EXT "-NAPI" -#define DRV_VERSION "3.4.14-k2"DRV_EXT +#define DRV_VERSION "3.4.14-k4"DRV_EXT #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 1999-2005 Intel Corporation" #define PFX DRV_NAME ": " @@ -903,8 +903,8 @@ static void mdio_write(struct net_device *netdev, int addr, int reg, int data) static void e100_get_defaults(struct nic *nic) { - struct param_range rfds = { .min = 16, .max = 256, .count = 64 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 64 }; + struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; + struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id); /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ @@ -1007,25 +1007,264 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); } +/********************************************************/ +/* Micro code for 8086:1229 Rev 8 */ +/********************************************************/ + +/* Parameter values for the D101M B-step */ +#define D101M_CPUSAVER_TIMER_DWORD 78 +#define D101M_CPUSAVER_BUNDLE_DWORD 65 +#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 + +#define D101M_B_RCVBUNDLE_UCODE \ +{\ +0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ +0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ +0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ +0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ +0x00380438, 0x00000000, 0x00140000, 0x00380555, \ +0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ +0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ +0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ +0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ +0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ +0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ +0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ +0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ +0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ +0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ +0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ +0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ +0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ +0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ +0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ +0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ +0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ +0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ +0x00380559, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ +0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ +0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ +} + +/********************************************************/ +/* Micro code for 8086:1229 Rev 9 */ +/********************************************************/ + +/* Parameter values for the D101S */ +#define D101S_CPUSAVER_TIMER_DWORD 78 +#define D101S_CPUSAVER_BUNDLE_DWORD 67 +#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 + +#define D101S_RCVBUNDLE_UCODE \ +{\ +0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ +0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ +0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ +0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ +0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ +0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ +0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ +0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ +0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ +0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ +0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ +0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ +0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ +0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ +0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ +0x00101313, 0x00380700, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ +0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ +0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ +0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ +0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ +0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ +0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ +0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ +0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ +0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00130831, \ +0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ +0x00041000, 0x00010004, 0x00380700 \ +} + +/********************************************************/ +/* Micro code for the 8086:1229 Rev F/10 */ +/********************************************************/ + +/* Parameter values for the D102 E-step */ +#define D102_E_CPUSAVER_TIMER_DWORD 42 +#define D102_E_CPUSAVER_BUNDLE_DWORD 54 +#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 + +#define D102_E_RCVBUNDLE_UCODE \ +{\ +0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ +0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ +0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ +0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ +0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ +0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ +0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ +0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ +0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +} + static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) { - int i; - static const u32 ucode[UCODE_SIZE] = { - /* NFS packets are misinterpreted as TCO packets and - * incorrectly routed to the BMC over SMBus. This - * microcode patch checks the fragmented IP bit in the - * NFS/UDP header to distinguish between NFS and TCO. */ - 0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, - 0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, - 0x00906EFD, 0x00900EFD, 0x00E00EF8, - }; - - if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) { - for(i = 0; i < UCODE_SIZE; i++) +/* *INDENT-OFF* */ + static struct { + u32 ucode[UCODE_SIZE + 1]; + u8 mac; + u8 timer_dword; + u8 bundle_dword; + u8 min_size_dword; + } ucode_opts[] = { + { D101M_B_RCVBUNDLE_UCODE, + mac_82559_D101M, + D101M_CPUSAVER_TIMER_DWORD, + D101M_CPUSAVER_BUNDLE_DWORD, + D101M_CPUSAVER_MIN_SIZE_DWORD }, + { D101S_RCVBUNDLE_UCODE, + mac_82559_D101S, + D101S_CPUSAVER_TIMER_DWORD, + D101S_CPUSAVER_BUNDLE_DWORD, + D101S_CPUSAVER_MIN_SIZE_DWORD }, + { D102_E_RCVBUNDLE_UCODE, + mac_82551_F, + D102_E_CPUSAVER_TIMER_DWORD, + D102_E_CPUSAVER_BUNDLE_DWORD, + D102_E_CPUSAVER_MIN_SIZE_DWORD }, + { D102_E_RCVBUNDLE_UCODE, + mac_82551_10, + D102_E_CPUSAVER_TIMER_DWORD, + D102_E_CPUSAVER_BUNDLE_DWORD, + D102_E_CPUSAVER_MIN_SIZE_DWORD }, + { {0}, 0, 0, 0, 0} + }, *opts; +/* *INDENT-ON* */ + +/************************************************************************* +* CPUSaver parameters +* +* All CPUSaver parameters are 16-bit literals that are part of a +* "move immediate value" instruction. By changing the value of +* the literal in the instruction before the code is loaded, the +* driver can change the algorithm. +* +* INTDELAY - This loads the dead-man timer with its inital value. +* When this timer expires the interrupt is asserted, and the +* timer is reset each time a new packet is received. (see +* BUNDLEMAX below to set the limit on number of chained packets) +* The current default is 0x600 or 1536. Experiments show that +* the value should probably stay within the 0x200 - 0x1000. +* +* BUNDLEMAX - +* This sets the maximum number of frames that will be bundled. In +* some situations, such as the TCP windowing algorithm, it may be +* better to limit the growth of the bundle size than let it go as +* high as it can, because that could cause too much added latency. +* The default is six, because this is the number of packets in the +* default TCP window size. A value of 1 would make CPUSaver indicate +* an interrupt for every frame received. If you do not want to put +* a limit on the bundle size, set this value to xFFFF. +* +* BUNDLESMALL - +* This contains a bit-mask describing the minimum size frame that +* will be bundled. The default masks the lower 7 bits, which means +* that any frame less than 128 bytes in length will not be bundled, +* but will instead immediately generate an interrupt. This does +* not affect the current bundle in any way. Any frame that is 128 +* bytes or large will be bundled normally. This feature is meant +* to provide immediate indication of ACK frames in a TCP environment. +* Customers were seeing poor performance when a machine with CPUSaver +* enabled was sending but not receiving. The delay introduced when +* the ACKs were received was enough to reduce total throughput, because +* the sender would sit idle until the ACK was finally seen. +* +* The current default is 0xFF80, which masks out the lower 7 bits. +* This means that any frame which is x7F (127) bytes or smaller +* will cause an immediate interrupt. Because this value must be a +* bit mask, there are only a few valid values that can be used. To +* turn this feature off, the driver can write the value xFFFF to the +* lower word of this instruction (in the same way that the other +* parameters are used). Likewise, a value of 0xF800 (2047) would +* cause an interrupt to be generated for every frame, because all +* standard Ethernet frames are <= 2047 bytes in length. +*************************************************************************/ + +/* if you wish to disable the ucode functionality, while maintaining the + * workarounds it provides, set the following defines to: + * BUNDLESMALL 0 + * BUNDLEMAX 1 + * INTDELAY 1 + */ +#define BUNDLESMALL 1 +#define BUNDLEMAX (u16)6 +#define INTDELAY (u16)1536 /* 0x600 */ + + /* do not load u-code for ICH devices */ + if (nic->flags & ich) + goto noloaducode; + + /* Search for ucode match against h/w rev_id */ + for (opts = ucode_opts; opts->mac; opts++) { + int i; + u32 *ucode = opts->ucode; + if (nic->mac != opts->mac) + continue; + + /* Insert user-tunable settings */ + ucode[opts->timer_dword] &= 0xFFFF0000; + ucode[opts->timer_dword] |= INTDELAY; + ucode[opts->bundle_dword] &= 0xFFFF0000; + ucode[opts->bundle_dword] |= BUNDLEMAX; + ucode[opts->min_size_dword] &= 0xFFFF0000; + ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; + + for (i = 0; i < UCODE_SIZE; i++) cb->u.ucode[i] = cpu_to_le32(ucode[i]); cb->command = cpu_to_le16(cb_ucode); - } else - cb->command = cpu_to_le16(cb_nop); + return; + } + +noloaducode: + cb->command = cpu_to_le16(cb_nop); } static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig index 94e7a9af870..a84c232395e 100644 --- a/drivers/net/fec_8xx/Kconfig +++ b/drivers/net/fec_8xx/Kconfig @@ -1,6 +1,6 @@ config FEC_8XX tristate "Motorola 8xx FEC driver" - depends on NET_ETHERNET && FEC + depends on NET_ETHERNET && 8xx select MII config FEC_8XX_GENERIC_PHY diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 6a3129bc15a..9b8295ee06e 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1360,7 +1360,7 @@ static struct pci_driver ioc3_driver = { static int __init ioc3_init_module(void) { - return pci_module_init(&ioc3_driver); + return pci_register_driver(&ioc3_driver); } static void __exit ioc3_cleanup_module(void) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 159b56a56ef..14a76f7cf90 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1346,10 +1346,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, } else { if (netif_msg_probe(tp)) { printk(KERN_ERR PFX - "Cannot find PowerManagement capability. " - "Aborting.\n"); + "PowerManagement capability not found.\n"); } - goto err_out_mwi; } /* make sure PCI base addr 1 is MMIO */ @@ -2516,7 +2514,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) } while (boguscnt > 0); if (boguscnt <= 0) { - if (net_ratelimit() && netif_msg_intr(tp)) { + if (netif_msg_intr(tp) && net_ratelimit() ) { printk(KERN_WARNING "%s: Too much work at interrupt!\n", dev->name); } diff --git a/drivers/net/saa9730.h b/drivers/net/saa9730.h index 9e9da6b4080..a7e9d29a86a 100644 --- a/drivers/net/saa9730.h +++ b/drivers/net/saa9730.h @@ -1,6 +1,7 @@ /* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2000, 2005 MIPS Technologies, Inc. All rights reserved. + * Authors: Carsten Langgaard <carstenl@mips.com> + * Maciej W. Rozycki <macro@mips.com> * * ######################################################################## * @@ -265,6 +266,7 @@ /* The SAA9730 (LAN) controller register map, as seen via the PCI-bus. */ #define SAA9730_LAN_REGS_ADDR 0x20400 +#define SAA9730_LAN_REGS_SIZE 0x00400 struct lan_saa9730_regmap { volatile unsigned int TxBuffA; /* 0x20400 */ @@ -309,6 +311,7 @@ typedef volatile struct lan_saa9730_regmap t_lan_saa9730_regmap; /* The SAA9730 (EVM) controller register map, as seen via the PCI-bus. */ #define SAA9730_EVM_REGS_ADDR 0x02000 +#define SAA9730_EVM_REGS_SIZE 0x00400 struct evm_saa9730_regmap { volatile unsigned int InterruptStatus1; /* 0x2000 */ @@ -329,16 +332,32 @@ typedef volatile struct evm_saa9730_regmap t_evm_saa9730_regmap; struct lan_saa9730_private { + /* + * Rx/Tx packet buffers. + * The Rx and Tx packets must be PACKET_SIZE aligned. + */ + void *buffer_start; + unsigned int buffer_size; + + /* + * DMA address of beginning of this object, returned + * by pci_alloc_consistent(). + */ + dma_addr_t dma_addr; + + /* Pointer to the associated pci device structure */ + struct pci_dev *pci_dev; + /* Pointer for the SAA9730 LAN controller register set. */ t_lan_saa9730_regmap *lan_saa9730_regs; /* Pointer to the SAA9730 EVM register. */ t_evm_saa9730_regmap *evm_saa9730_regs; - /* TRUE if the next buffer to write is RxBuffA, FALSE if RxBuffB. */ - unsigned char NextRcvToUseIsA; /* Rcv buffer Index. */ unsigned char NextRcvPacketIndex; + /* Next buffer index. */ + unsigned char NextRcvBufferIndex; /* Index of next packet to use in that buffer. */ unsigned char NextTxmPacketIndex; @@ -353,13 +372,8 @@ struct lan_saa9730_private { unsigned char DmaRcvPackets; unsigned char DmaTxmPackets; - unsigned char RcvAIndex; /* index into RcvBufferSpace[] for Blk A */ - unsigned char RcvBIndex; /* index into RcvBufferSpace[] for Blk B */ - - unsigned int - TxmBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_TXM_Q_SIZE]; - unsigned int - RcvBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_RCV_Q_SIZE]; + void *TxmBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_TXM_Q_SIZE]; + void *RcvBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_RCV_Q_SIZE]; unsigned int TxBufferFree[LAN_SAA9730_BUFFERS]; unsigned char PhysicalAddress[LAN_SAA9730_CAM_ENTRIES][6]; diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index c91e2e81f13..28bf2e69eb5 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -155,6 +155,12 @@ MODULE_LICENSE("GPL"); #define MEMORY_WAIT_TIME 16 /* + * The maximum number of processing loops allowed for each call to the + * IRQ handler. + */ +#define MAX_IRQ_LOOPS 8 + +/* * This selects whether TX packets are sent one by one to the SMC91x internal * memory and throttled until transmission completes. This may prevent * RX overruns a litle by keeping much of the memory free for RX packets @@ -684,7 +690,6 @@ static void smc_hardware_send_pkt(unsigned long data) /* queue the packet for TX */ SMC_SET_MMU_CMD(MC_ENQUEUE); - SMC_ACK_INT(IM_TX_EMPTY_INT); smc_special_unlock(&lp->lock); dev->trans_start = jiffies; @@ -1207,6 +1212,7 @@ static void smc_phy_configure(void *data) smc_phy_check_media(dev, 1); smc_phy_configure_exit: + SMC_SELECT_BANK(2); spin_unlock_irq(&lp->lock); lp->work_pending = 0; } @@ -1305,7 +1311,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) SMC_SET_INT_MASK(0); /* set a timeout value, so I don't stay here forever */ - timeout = 8; + timeout = MAX_IRQ_LOOPS; do { status = SMC_GET_INT(); @@ -1372,10 +1378,13 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* restore register states */ SMC_SET_PTR(saved_pointer); SMC_SET_INT_MASK(mask); - spin_unlock(&lp->lock); - DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); + if (timeout == MAX_IRQ_LOOPS) + PRINTK("%s: spurious interrupt (mask = 0x%02x)\n", + dev->name, mask); + DBG(3, "%s: Interrupt done (%d loops)\n", + dev->name, MAX_IRQ_LOOPS - timeout); /* * We return IRQ_HANDLED unconditionally here even if there was diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index a01efa6d5c6..1fd04662c4f 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -192,7 +192,9 @@ static int cisco_rx(struct sk_buff *skb) "uptime %ud%uh%um%us)\n", dev->name, days, hrs, min, sec); +#if 0 netif_carrier_on(dev); +#endif hdlc->state.cisco.up = 1; } } @@ -225,7 +227,9 @@ static void cisco_timer(unsigned long arg) hdlc->state.cisco.settings.timeout * HZ)) { hdlc->state.cisco.up = 0; printk(KERN_INFO "%s: Link down\n", dev->name); +#if 0 netif_carrier_off(dev); +#endif } cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, @@ -261,8 +265,10 @@ static void cisco_stop(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); del_timer_sync(&hdlc->state.cisco.timer); +#if 0 if (netif_carrier_ok(dev)) netif_carrier_off(dev); +#endif hdlc->state.cisco.up = 0; hdlc->state.cisco.request_sent = 0; } diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index e1601d35dce..523afe17564 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -545,8 +545,10 @@ static void fr_set_link_state(int reliable, struct net_device *dev) hdlc->state.fr.reliable = reliable; if (reliable) { +#if 0 if (!netif_carrier_ok(dev)) netif_carrier_on(dev); +#endif hdlc->state.fr.n391cnt = 0; /* Request full status */ hdlc->state.fr.dce_changed = 1; @@ -560,8 +562,10 @@ static void fr_set_link_state(int reliable, struct net_device *dev) } } } else { +#if 0 if (netif_carrier_ok(dev)) netif_carrier_off(dev); +#endif while (pvc) { /* Deactivate all PVCs */ pvc_carrier(0, pvc); diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c index cdd4c09c2d9..46cef8f9213 100644 --- a/drivers/net/wan/hdlc_generic.c +++ b/drivers/net/wan/hdlc_generic.c @@ -79,11 +79,13 @@ static void __hdlc_set_carrier_on(struct net_device *dev) hdlc_device *hdlc = dev_to_hdlc(dev); if (hdlc->proto.start) return hdlc->proto.start(dev); +#if 0 #ifdef DEBUG_LINK if (netif_carrier_ok(dev)) printk(KERN_ERR "hdlc_set_carrier_on(): already on\n"); #endif netif_carrier_on(dev); +#endif } @@ -94,11 +96,13 @@ static void __hdlc_set_carrier_off(struct net_device *dev) if (hdlc->proto.stop) return hdlc->proto.stop(dev); +#if 0 #ifdef DEBUG_LINK if (!netif_carrier_ok(dev)) printk(KERN_ERR "hdlc_set_carrier_off(): already off\n"); #endif netif_carrier_off(dev); +#endif } @@ -294,8 +298,10 @@ int register_hdlc_device(struct net_device *dev) if (result != 0) return -EIO; +#if 0 if (netif_carrier_ok(dev)) netif_carrier_off(dev); /* no carrier until DCD goes up */ +#endif return 0; } diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c index 579480dad37..346c6febb03 100644 --- a/drivers/net/wireless/hermes.c +++ b/drivers/net/wireless/hermes.c @@ -398,7 +398,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) * * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware */ -int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len, +int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, u16 id, u16 offset) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; @@ -424,7 +424,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len, * * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware */ -int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len, +int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, u16 id, u16 offset) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; @@ -450,7 +450,7 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len, * * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware */ -int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, unsigned len, +int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, int len, u16 id, u16 offset) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h index a6bd472d75d..7644f72a9f4 100644 --- a/drivers/net/wireless/hermes.h +++ b/drivers/net/wireless/hermes.h @@ -372,12 +372,12 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, struct hermes_response *resp); int hermes_allocate(hermes_t *hw, u16 size, u16 *fid); -int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len, +int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, u16 id, u16 offset); -int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len, +int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, u16 id, u16 offset); int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, - unsigned data_len, unsigned len, u16 id, u16 offset); + unsigned data_len, int len, u16 id, u16 offset); int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen, u16 *length, void *buf); int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, diff --git a/drivers/net/wireless/i82593.h b/drivers/net/wireless/i82593.h index 33acb8add4d..afac5c7a323 100644 --- a/drivers/net/wireless/i82593.h +++ b/drivers/net/wireless/i82593.h @@ -7,11 +7,16 @@ * * Copyright 1994, Anders Klemets <klemets@it.kth.se> * - * This software may be freely distributed for noncommercial purposes - * as long as this notice is retained. - * * HISTORY * i82593.h,v + * Revision 1.4 2005/11/4 09:15:00 baroniunas + * Modified copyright with permission of author as follows: + * + * "If I82539.H is the only file with my copyright statement + * that is included in the Source Forge project, then you have + * my approval to change the copyright statement to be a GPL + * license, in the way you proposed on October 10." + * * Revision 1.1 1996/07/17 15:23:12 root * Initial revision * diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index a2e6214169e..77d2a21d4cd 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -6344,7 +6344,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, dev->ethtool_ops = &ipw2100_ethtool_ops; dev->tx_timeout = ipw2100_tx_timeout; dev->wireless_handlers = &ipw2100_wx_handler_def; - dev->get_wireless_stats = ipw2100_wx_wireless_stats; + priv->wireless_data.ieee80211 = priv->ieee; + dev->wireless_data = &priv->wireless_data; dev->set_mac_address = ipw2100_set_address; dev->watchdog_timeo = 3 * HZ; dev->irq = 0; @@ -7178,6 +7179,11 @@ static int ipw2100_wx_get_range(struct net_device *dev, } range->num_frequency = val; + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWAP)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + IPW_DEBUG_WX("GET Range\n"); return 0; @@ -8446,16 +8452,6 @@ static iw_handler ipw2100_private_handler[] = { #endif /* CONFIG_IPW2100_MONITOR */ }; -static struct iw_handler_def ipw2100_wx_handler_def = { - .standard = ipw2100_wx_handlers, - .num_standard = sizeof(ipw2100_wx_handlers) / sizeof(iw_handler), - .num_private = sizeof(ipw2100_private_handler) / sizeof(iw_handler), - .num_private_args = sizeof(ipw2100_private_args) / - sizeof(struct iw_priv_args), - .private = (iw_handler *) ipw2100_private_handler, - .private_args = (struct iw_priv_args *)ipw2100_private_args, -}; - /* * Get wireless statistics. * Called by /proc/net/wireless @@ -8597,6 +8593,17 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev) return (struct iw_statistics *)NULL; } +static struct iw_handler_def ipw2100_wx_handler_def = { + .standard = ipw2100_wx_handlers, + .num_standard = sizeof(ipw2100_wx_handlers) / sizeof(iw_handler), + .num_private = sizeof(ipw2100_private_handler) / sizeof(iw_handler), + .num_private_args = sizeof(ipw2100_private_args) / + sizeof(struct iw_priv_args), + .private = (iw_handler *) ipw2100_private_handler, + .private_args = (struct iw_priv_args *)ipw2100_private_args, + .get_wireless_stats = ipw2100_wx_wireless_stats, +}; + static void ipw2100_wx_event_work(struct ipw2100_priv *priv) { union iwreq_data wrqu; diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 140fdf2a0a0..7c65b10bb16 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -571,6 +571,8 @@ struct ipw2100_priv { struct net_device *net_dev; struct iw_statistics wstats; + struct iw_public_data wireless_data; + struct tasklet_struct irq_tasklet; struct workqueue_struct *workqueue; diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index 109a96d9000..23deee69974 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -164,12 +164,12 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) /* assert the Wakeup interrupt in the Device Interrupt Register */ isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_WAKEUP, ISL38XX_DEV_INT_REG); + +#if VERBOSE > SHOW_ERROR_MESSAGES udelay(ISL38XX_WRITEIO_DELAY); /* perform another read on the Device Status Register */ reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - -#if VERBOSE > SHOW_ERROR_MESSAGES do_gettimeofday(¤t_time); DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", current_time.tv_sec, (long)current_time.tv_usec, reg); diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index a39fbfef789..19657efa8dc 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -700,6 +700,28 @@ static unsigned int iosapic_startup_irq(unsigned int irq) return 0; } +#ifdef CONFIG_SMP +static void iosapic_set_affinity_irq(unsigned int irq, cpumask_t dest) +{ + struct vector_info *vi = iosapic_get_vector(irq); + u32 d0, d1, dummy_d0; + unsigned long flags; + + if (cpu_check_affinity(irq, &dest)) + return; + + vi->txn_addr = txn_affinity_addr(irq, first_cpu(dest)); + + spin_lock_irqsave(&iosapic_lock, flags); + /* d1 contains the destination CPU, so only want to set that + * entry */ + iosapic_rd_irt_entry(vi, &d0, &d1); + iosapic_set_irt_data(vi, &dummy_d0, &d1); + iosapic_wr_irt_entry(vi, d0, d1); + spin_unlock_irqrestore(&iosapic_lock, flags); +} +#endif + static struct hw_interrupt_type iosapic_interrupt_type = { .typename = "IO-SAPIC-level", .startup = iosapic_startup_irq, @@ -708,7 +730,9 @@ static struct hw_interrupt_type iosapic_interrupt_type = { .disable = iosapic_disable_irq, .ack = no_ack_irq, .end = iosapic_end_irq, -// .set_affinity = iosapic_set_affinity_irq, +#ifdef CONFIG_SMP + .set_affinity = iosapic_set_affinity_irq, +#endif }; int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev) diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index bab3bcabcb6..d14888e149b 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -24,6 +24,9 @@ * Major changes to get basic interrupt infrastructure working to * hopefully be able to support all SuperIO devices. Currently * works with serial. -- John Marvin <jsm@fc.hp.com> + * + * Converted superio_init() to be a PCI_FIXUP_FINAL callee. + * -- Kyle McMartin <kyle@parisc-linux.org> */ @@ -141,10 +144,10 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) } /* Initialize Super I/O device */ - -static void __devinit -superio_init(struct superio_device *sio) +static void +superio_init(struct pci_dev *pcidev) { + struct superio_device *sio = &sio_dev; struct pci_dev *pdev = sio->lio_pdev; u16 word; @@ -160,8 +163,8 @@ superio_init(struct superio_device *sio) /* ...then properly fixup the USB to point at suckyio PIC */ sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev); - printk (KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n", - pci_name(pdev),pdev->irq); + printk(KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n", + pci_name(pdev), pdev->irq); pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base); sio->sp1_base &= ~1; @@ -274,7 +277,7 @@ superio_init(struct superio_device *sio) sio->suckyio_irq_enabled = 1; } - +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init); static void superio_disable_irq(unsigned int irq) { @@ -452,8 +455,10 @@ static void superio_fixup_pci(struct pci_dev *pdev) DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci); -static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int __devinit +superio_probe(struct pci_dev *dev, const struct pci_device_id *id) { + struct superio_device *sio = &sio_dev; /* ** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a @@ -466,7 +471,8 @@ static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_ dev->subsystem_vendor, dev->subsystem_device, dev->class); - superio_init(&sio_dev); + if (!sio->suckyio_irq_enabled) + BUG(); /* Enabled by PCI_FIXUP_FINAL */ if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) { /* Function 1 */ superio_parport_init(); @@ -481,19 +487,21 @@ static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_ DBG_INIT("superio_probe: WTF? Fire Extinguisher?\n"); } - /* Let appropriate other driver claim this device. */ + /* Let appropriate other driver claim this device. */ return -ENODEV; } static struct pci_device_id superio_tbl[] = { - { PCI_VENDOR_ID_NS, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) }, { 0, } }; static struct pci_driver superio_driver = { - .name = "SuperIO", - .id_table = superio_tbl, - .probe = superio_probe, + .name = "SuperIO", + .id_table = superio_tbl, + .probe = superio_probe, }; static int __init superio_modinit(void) @@ -506,6 +514,5 @@ static void __exit superio_exit(void) pci_unregister_driver(&superio_driver); } - module_init(superio_modinit); module_exit(superio_exit); diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index ac184e60797..ab7432a5778 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -2,6 +2,7 @@ * sata_mv.c - Marvell SATA support * * Copyright 2005: EMC Corporation, all rights reserved. + * Copyright 2005 Red Hat, Inc. All rights reserved. * * Please ALWAYS copy linux-ide@vger.kernel.org on emails. * @@ -36,7 +37,7 @@ #include <asm/io.h> #define DRV_NAME "sata_mv" -#define DRV_VERSION "0.25" +#define DRV_VERSION "0.5" enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index cb1933a3bd5..e0d6f194f54 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -5,17 +5,6 @@ * * Based on preview driver from Silicon Image. * - * NOTE: No NCQ/ATAPI support yet. The preview driver didn't support - * NCQ nor ATAPI, and, unfortunately, I couldn't find out how to make - * those work. Enabling those shouldn't be difficult. Basic - * structure is all there (in libata-dev tree). If you have any - * information about this hardware, please contact me or linux-ide. - * Info is needed on... - * - * - How to issue tagged commands and turn on sactive on issue accordingly. - * - Where to put an ATAPI command and how to tell the device to send it. - * - How to enable/use 64bit. - * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any @@ -42,7 +31,7 @@ #include <asm/io.h> #define DRV_NAME "sata_sil24" -#define DRV_VERSION "0.22" /* Silicon Image's preview driver was 0.10 */ +#define DRV_VERSION "0.23" /* * Port request block (PRB) 32 bytes @@ -221,11 +210,22 @@ enum { IRQ_STAT_4PORTS = 0xf, }; -struct sil24_cmd_block { +struct sil24_ata_block { struct sil24_prb prb; struct sil24_sge sge[LIBATA_MAX_PRD]; }; +struct sil24_atapi_block { + struct sil24_prb prb; + u8 cdb[16]; + struct sil24_sge sge[LIBATA_MAX_PRD - 1]; +}; + +union sil24_cmd_block { + struct sil24_ata_block ata; + struct sil24_atapi_block atapi; +}; + /* * ap->private_data * @@ -233,7 +233,7 @@ struct sil24_cmd_block { * here from the previous interrupt. */ struct sil24_port_priv { - struct sil24_cmd_block *cmd_block; /* 32 cmd blocks */ + union sil24_cmd_block *cmd_block; /* 32 cmd blocks */ dma_addr_t cmd_block_dma; /* DMA base addr for them */ struct ata_taskfile tf; /* Cached taskfile registers */ }; @@ -244,6 +244,7 @@ struct sil24_host_priv { void __iomem *port_base; /* port registers (4 * 8192 bytes @BAR2) */ }; +static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev); static u8 sil24_check_status(struct ata_port *ap); static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); @@ -297,6 +298,8 @@ static struct scsi_host_template sil24_sht = { static const struct ata_port_operations sil24_ops = { .port_disable = ata_port_disable, + .dev_config = sil24_dev_config, + .check_status = sil24_check_status, .check_altstatus = sil24_check_status, .dev_select = ata_noop_dev_select, @@ -333,7 +336,7 @@ static struct ata_port_info sil24_port_info[] = { { .sht = &sil24_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ @@ -344,7 +347,7 @@ static struct ata_port_info sil24_port_info[] = { { .sht = &sil24_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ @@ -355,7 +358,7 @@ static struct ata_port_info sil24_port_info[] = { { .sht = &sil24_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ @@ -364,6 +367,16 @@ static struct ata_port_info sil24_port_info[] = { }, }; +static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) +{ + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + + if (ap->cdb_len == 16) + writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); + else + writel(PORT_CS_CDB16, port + PORT_CTRL_CLR); +} + static inline void sil24_update_tf(struct ata_port *ap) { struct sil24_port_priv *pp = ap->private_data; @@ -415,22 +428,73 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) *tf = pp->tf; } -static void sil24_phy_reset(struct ata_port *ap) +static int sil24_issue_SRST(struct ata_port *ap) { - __sata_phy_reset(ap); + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + struct sil24_port_priv *pp = ap->private_data; + struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; + dma_addr_t paddr = pp->cmd_block_dma; + u32 irq_enable, irq_stat; + int cnt; + + /* temporarily turn off IRQs during SRST */ + irq_enable = readl(port + PORT_IRQ_ENABLE_SET); + writel(irq_enable, port + PORT_IRQ_ENABLE_CLR); + /* - * No ATAPI yet. Just unconditionally indicate ATA device. - * If ATAPI device is attached, it will fail ATA_CMD_ID_ATA - * and libata core will ignore the device. + * XXX: Not sure whether the following sleep is needed or not. + * The original driver had it. So.... */ - if (!(ap->flags & ATA_FLAG_PORT_DISABLED)) - ap->device[0].class = ATA_DEV_ATA; + msleep(10); + + prb->ctrl = PRB_CTRL_SRST; + prb->fis[1] = 0; /* no PM yet */ + + writel((u32)paddr, port + PORT_CMD_ACTIVATE); + + for (cnt = 0; cnt < 100; cnt++) { + irq_stat = readl(port + PORT_IRQ_STAT); + writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ + + irq_stat >>= PORT_IRQ_RAW_SHIFT; + if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR)) + break; + + msleep(1); + } + + /* restore IRQs */ + writel(irq_enable, port + PORT_IRQ_ENABLE_SET); + + if (!(irq_stat & PORT_IRQ_COMPLETE)) + return -1; + + /* update TF */ + sil24_update_tf(ap); + return 0; +} + +static void sil24_phy_reset(struct ata_port *ap) +{ + struct sil24_port_priv *pp = ap->private_data; + + __sata_phy_reset(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) + return; + + if (sil24_issue_SRST(ap) < 0) { + printk(KERN_ERR DRV_NAME + " ata%u: SRST failed, disabling port\n", ap->id); + ap->ops->port_disable(ap); + return; + } + + ap->device->class = ata_dev_classify(&pp->tf); } static inline void sil24_fill_sg(struct ata_queued_cmd *qc, - struct sil24_cmd_block *cb) + struct sil24_sge *sge) { - struct sil24_sge *sge = cb->sge; struct scatterlist *sg; unsigned int idx = 0; @@ -451,23 +515,47 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct sil24_port_priv *pp = ap->private_data; - struct sil24_cmd_block *cb = pp->cmd_block + qc->tag; - struct sil24_prb *prb = &cb->prb; + union sil24_cmd_block *cb = pp->cmd_block + qc->tag; + struct sil24_prb *prb; + struct sil24_sge *sge; switch (qc->tf.protocol) { case ATA_PROT_PIO: case ATA_PROT_DMA: case ATA_PROT_NODATA: + prb = &cb->ata.prb; + sge = cb->ata.sge; + prb->ctrl = 0; + break; + + case ATA_PROT_ATAPI: + case ATA_PROT_ATAPI_DMA: + case ATA_PROT_ATAPI_NODATA: + prb = &cb->atapi.prb; + sge = cb->atapi.sge; + memset(cb->atapi.cdb, 0, 32); + memcpy(cb->atapi.cdb, qc->cdb, ap->cdb_len); + + if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { + if (qc->tf.flags & ATA_TFLAG_WRITE) + prb->ctrl = PRB_CTRL_PACKET_WRITE; + else + prb->ctrl = PRB_CTRL_PACKET_READ; + } else + prb->ctrl = 0; + break; + default: - /* ATAPI isn't supported yet */ + prb = NULL; /* shut up, gcc */ + sge = NULL; BUG(); } ata_tf_to_fis(&qc->tf, prb->fis, 0); if (qc->flags & ATA_QCFLAG_DMAMAP) - sil24_fill_sg(qc, cb); + sil24_fill_sg(qc, sge); } static int sil24_qc_issue(struct ata_queued_cmd *qc) @@ -486,6 +574,31 @@ static void sil24_irq_clear(struct ata_port *ap) /* unused */ } +static int __sil24_restart_controller(void __iomem *port) +{ + u32 tmp; + int cnt; + + writel(PORT_CS_INIT, port + PORT_CTRL_STAT); + + /* Max ~10ms */ + for (cnt = 0; cnt < 10000; cnt++) { + tmp = readl(port + PORT_CTRL_STAT); + if (tmp & PORT_CS_RDY) + return 0; + udelay(1); + } + + return -1; +} + +static void sil24_restart_controller(struct ata_port *ap) +{ + if (__sil24_restart_controller((void __iomem *)ap->ioaddr.cmd_addr)) + printk(KERN_ERR DRV_NAME + " ata%u: failed to restart controller\n", ap->id); +} + static int __sil24_reset_controller(void __iomem *port) { int cnt; @@ -505,7 +618,11 @@ static int __sil24_reset_controller(void __iomem *port) if (tmp & PORT_CS_DEV_RST) return -1; - return 0; + + if (tmp & PORT_CS_RDY) + return 0; + + return __sil24_restart_controller(port); } static void sil24_reset_controller(struct ata_port *ap) @@ -567,9 +684,15 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) if (serror) writel(serror, port + PORT_SERROR); - printk(KERN_ERR DRV_NAME " ata%u: error interrupt on port%d\n" - " stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n", - ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror); + /* + * Don't log ATAPI device errors. They're supposed to happen + * and any serious errors will be logged using sense data by + * the SCSI layer. + */ + if (ap->device[0].class != ATA_DEV_ATAPI || cmd_err > PORT_CERR_SDB) + printk("ata%u: error interrupt on port%d\n" + " stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n", + ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror); if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) { /* @@ -577,6 +700,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) */ sil24_update_tf(ap); err_mask = ac_err_mask(pp->tf.command); + sil24_restart_controller(ap); } else { /* * Other errors. libata currently doesn't have any @@ -584,12 +708,11 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) * ATA_ERR. */ err_mask = AC_ERR_OTHER; + sil24_reset_controller(ap); } if (qc) ata_qc_complete(qc, err_mask); - - sil24_reset_controller(ap); } static inline void sil24_host_intr(struct ata_port *ap) @@ -665,7 +788,7 @@ static int sil24_port_start(struct ata_port *ap) { struct device *dev = ap->host_set->dev; struct sil24_port_priv *pp; - struct sil24_cmd_block *cb; + union sil24_cmd_block *cb; size_t cb_size = sizeof(*cb); dma_addr_t cb_dma; int rc = -ENOMEM; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ff36f0c9fda..ad47c1b84c3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -507,7 +507,7 @@ config SERIAL_SUNSU_CONSOLE config SERIAL_MUX tristate "Serial MUX support" - depends on PARISC + depends on GSC select SERIAL_CORE default y ---help--- diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 660bae5ba17..7633132a10a 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -65,8 +65,8 @@ static struct uart_driver mux_driver = { static struct timer_list mux_timer; -#define UART_PUT_CHAR(p, c) __raw_writel((c), (unsigned long)(p)->membase + IO_DATA_REG_OFFSET) -#define UART_GET_FIFO_CNT(p) __raw_readl((unsigned long)(p)->membase + IO_DCOUNT_REG_OFFSET) +#define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) +#define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET) #define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8 /** @@ -79,10 +79,7 @@ static struct timer_list mux_timer; */ static unsigned int mux_tx_empty(struct uart_port *port) { - unsigned int cnt = __raw_readl((unsigned long)port->membase - + IO_DCOUNT_REG_OFFSET); - - return cnt ? 0 : TIOCSER_TEMT; + return UART_GET_FIFO_CNT(port) ? 0 : TIOCSER_TEMT; } /** @@ -218,8 +215,7 @@ static void mux_read(struct uart_port *port) __u32 start_count = port->icount.rx; while(1) { - data = __raw_readl((unsigned long)port->membase - + IO_DATA_REG_OFFSET); + data = __raw_readl(port->membase + IO_DATA_REG_OFFSET); if (MUX_STATUS(data)) continue; @@ -481,6 +477,13 @@ static int __init mux_probe(struct parisc_device *dev) port->ops = &mux_pops; port->flags = UPF_BOOT_AUTOCONF; port->line = port_cnt; + + /* The port->timeout needs to match what is present in + * uart_wait_until_sent in serial_core.c. Otherwise + * the time spent in msleep_interruptable will be very + * long, causing the appearance of a console hang. + */ + port->timeout = HZ / 50; spin_lock_init(&port->lock); status = uart_add_one_port(&mux_driver, port); BUG_ON(status); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 991c00de5c4..31b7efd94d6 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -137,7 +137,7 @@ #define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) #define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) #define EXT3_IOC32_GETVERSION _IOR('f', 3, int) -#define EXT3_IOC32_SETVERSION _IOR('f', 4, int) +#define EXT3_IOC32_SETVERSION _IOW('f', 4, int) #define EXT3_IOC32_GETRSVSZ _IOR('f', 5, int) #define EXT3_IOC32_SETRSVSZ _IOW('f', 6, int) #define EXT3_IOC32_GROUP_EXTEND _IOW('f', 7, unsigned int) diff --git a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h index f876bdf2205..b0a30e2c981 100644 --- a/include/asm-parisc/irq.h +++ b/include/asm-parisc/irq.h @@ -8,6 +8,7 @@ #define _ASM_PARISC_IRQ_H #include <linux/config.h> +#include <linux/cpumask.h> #include <asm/types.h> #define NO_IRQ (-1) @@ -49,10 +50,10 @@ extern int txn_alloc_irq(unsigned int nbits); extern int txn_claim_irq(int); extern unsigned int txn_alloc_data(unsigned int); extern unsigned long txn_alloc_addr(unsigned int); +extern unsigned long txn_affinity_addr(unsigned int irq, int cpu); extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *); - -extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *); +extern int cpu_check_affinity(unsigned int irq, cpumask_t *dest); /* soft power switch support (power.c) */ extern struct tasklet_struct power_tasklet; diff --git a/include/asm-parisc/smp.h b/include/asm-parisc/smp.h index 9413f67a540..dbdbd2e9fdf 100644 --- a/include/asm-parisc/smp.h +++ b/include/asm-parisc/smp.h @@ -29,6 +29,7 @@ extern cpumask_t cpu_online_map; #define cpu_logical_map(cpu) (cpu) extern void smp_send_reschedule(int cpu); +extern void smp_send_all_nop(void); #endif /* !ASSEMBLY */ @@ -53,7 +54,11 @@ extern unsigned long cpu_present_mask; #define raw_smp_processor_id() (current_thread_info()->cpu) -#endif /* CONFIG_SMP */ +#else /* CONFIG_SMP */ + +static inline void smp_send_all_nop(void) { return; } + +#endif #define NO_PROC_ID 0xFF /* No processor magic marker */ #define ANY_PROC_ID 0xFF /* Any processor magic marker */ diff --git a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h index 7c3f406a746..16c2ac075fc 100644 --- a/include/asm-parisc/spinlock.h +++ b/include/asm-parisc/spinlock.h @@ -11,18 +11,25 @@ static inline int __raw_spin_is_locked(raw_spinlock_t *x) return *a == 0; } -#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) +#define __raw_spin_lock(lock) __raw_spin_lock_flags(lock, 0) #define __raw_spin_unlock_wait(x) \ do { cpu_relax(); } while (__raw_spin_is_locked(x)) -static inline void __raw_spin_lock(raw_spinlock_t *x) +static inline void __raw_spin_lock_flags(raw_spinlock_t *x, + unsigned long flags) { volatile unsigned int *a; mb(); a = __ldcw_align(x); while (__ldcw(a) == 0) - while (*a == 0); + while (*a == 0) + if (flags & PSW_SM_I) { + local_irq_enable(); + cpu_relax(); + local_irq_disable(); + } else + cpu_relax(); mb(); } @@ -60,26 +67,20 @@ static inline int __raw_spin_trylock(raw_spinlock_t *x) static __inline__ void __raw_read_lock(raw_rwlock_t *rw) { - unsigned long flags; - local_irq_save(flags); __raw_spin_lock(&rw->lock); rw->counter++; __raw_spin_unlock(&rw->lock); - local_irq_restore(flags); } static __inline__ void __raw_read_unlock(raw_rwlock_t *rw) { - unsigned long flags; - local_irq_save(flags); __raw_spin_lock(&rw->lock); rw->counter--; __raw_spin_unlock(&rw->lock); - local_irq_restore(flags); } /* write_lock is less trivial. We optimistically grab the lock and check diff --git a/include/asm-parisc/tlbflush.h b/include/asm-parisc/tlbflush.h index e97aa8d1eff..c9ec39c6fc6 100644 --- a/include/asm-parisc/tlbflush.h +++ b/include/asm-parisc/tlbflush.h @@ -12,21 +12,15 @@ * N class systems, only one PxTLB inter processor broadcast can be * active at any one time on the Merced bus. This tlb purge * synchronisation is fairly lightweight and harmless so we activate - * it on all SMP systems not just the N class. */ -#ifdef CONFIG_SMP + * it on all SMP systems not just the N class. We also need to have + * preemption disabled on uniprocessor machines, and spin_lock does that + * nicely. + */ extern spinlock_t pa_tlb_lock; #define purge_tlb_start(x) spin_lock(&pa_tlb_lock) #define purge_tlb_end(x) spin_unlock(&pa_tlb_lock) -#else - -#define purge_tlb_start(x) do { } while(0) -#define purge_tlb_end(x) do { } while (0) - -#endif - - extern void flush_tlb_all(void); /* @@ -88,7 +82,6 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */ flush_tlb_all(); else { - preempt_disable(); mtsp(vma->vm_mm->context,1); purge_tlb_start(); if (split_tlb) { @@ -102,7 +95,6 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, pdtlb(start); start += PAGE_SIZE; } - preempt_enable(); } purge_tlb_end(); } diff --git a/include/linux/cciss_ioctl.h b/include/linux/cciss_ioctl.h index 424d5e622b4..6e27f42e3a5 100644 --- a/include/linux/cciss_ioctl.h +++ b/include/linux/cciss_ioctl.h @@ -10,8 +10,8 @@ typedef struct _cciss_pci_info_struct { unsigned char bus; - unsigned short domain; unsigned char dev_fn; + unsigned short domain; __u32 board_id; } cciss_pci_info_struct; diff --git a/include/linux/mm.h b/include/linux/mm.h index 1013a42d10b..0986d19be0b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -940,7 +940,9 @@ unsigned long max_sane_readahead(unsigned long nr); /* Do stack extension */ extern int expand_stack(struct vm_area_struct *vma, unsigned long address); +#ifdef CONFIG_IA64 extern int expand_upwards(struct vm_area_struct *vma, unsigned long address); +#endif /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr); diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index b93fd8c1d88..cde2f4f4f50 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -1042,7 +1042,7 @@ static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr) case IEEE80211_4ADDR_LEN: return ((struct ieee80211_hdr_4addr *)hdr)->payload; } - + return NULL; } static inline int ieee80211_is_ofdm_rate(u8 rate) diff --git a/mm/mmap.c b/mm/mmap.c index 6c997b15960..4f8def03428 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1501,7 +1501,7 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un * PA-RISC uses this for its stack; IA64 for its Register Backing Store. * vma is the last one with address > vma->vm_end. Have to extend vma. */ -#ifdef CONFIG_STACK_GROWSUP +#ifndef CONFIG_IA64 static inline #endif int expand_upwards(struct vm_area_struct *vma, unsigned long address) |