diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 11:30:39 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 11:30:39 -0800 |
commit | 46f7b635569731ff81a3b72d1bcd4415b293b637 (patch) | |
tree | e97e5e28d1768bb281116d92292851758ea20024 /drivers/staging | |
parent | 9682ec9692e5ac11c6caebd079324e727b19e7ce (diff) | |
parent | 533e80b1ea709577ec5cf73b8b566569bc711259 (diff) |
Merge tag 'staging-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging drivers patches from Greg KH:
"Here's the big staging driver tree update for 3.20-rc1.
Lots of little things in here, adding up to lots of overall cleanups.
The IIO driver updates are also in here as they cross the staging tree
boundry a lot. I2O has moved into staging as well, as a plan to drop
it from the tree eventually as that's a dead subsystem.
All of this has been in linux-next with no reported issues for a
while"
* tag 'staging-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (740 commits)
staging: lustre: lustre: libcfs: define symbols as static
staging: rtl8712: Do coding style cleanup
staging: lustre: make obd_updatemax_lock static
staging: rtl8188eu: core: switch with redundant cases
staging: rtl8188eu: odm: conditional setting with no effect
staging: rtl8188eu: odm: condition with no effect
staging: ft1000: fix braces warning
staging: sm7xxfb: fix remaining CamelCase
staging: sm7xxfb: fix CamelCase
staging: rtl8723au: multiple condition with no effect - if identical to else
staging: sm7xxfb: make smtc_scr_info static
staging/lustre/mdc: Initialize req in mdc_enqueue for !it case
staging/lustre/clio: Do not allow group locks with gid 0
staging/lustre/llite: don't add to page cache upon failure
staging/lustre/llite: Add exception entry check after radix_tree
staging/lustre/libcfs: protect kkuc_groups from write access
staging/lustre/fld: refer to MDT0 for fld lookup in some cases
staging/lustre/llite: Solve a race to access lli_has_smd in read case
staging/lustre/ptlrpc: hold rq_lock when modify rq_flags
staging/lustre/lnet: portal spreading rotor should be unsigned
...
Diffstat (limited to 'drivers/staging')
437 files changed, 31805 insertions, 14074 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 9049dd91b56..45baa83be7c 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -56,6 +56,8 @@ source "drivers/staging/vt6656/Kconfig" source "drivers/staging/iio/Kconfig" +source "drivers/staging/sm7xxfb/Kconfig" + source "drivers/staging/xgifb/Kconfig" source "drivers/staging/emxx_udc/Kconfig" @@ -64,8 +66,6 @@ source "drivers/staging/ft1000/Kconfig" source "drivers/staging/speakup/Kconfig" -source "drivers/staging/cptm1217/Kconfig" - source "drivers/staging/ste_rmi4/Kconfig" source "drivers/staging/nvec/Kconfig" @@ -104,4 +104,8 @@ source "drivers/staging/unisys/Kconfig" source "drivers/staging/clocking-wizard/Kconfig" +source "drivers/staging/fbtft/Kconfig" + +source "drivers/staging/i2o/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index fe26ff162b4..29160790841 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -22,11 +22,11 @@ obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_IIO) += iio/ +obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ obj-$(CONFIG_FB_XGI) += xgifb/ obj-$(CONFIG_USB_EMXX) += emxx_udc/ obj-$(CONFIG_FT1000) += ft1000/ obj-$(CONFIG_SPEAKUP) += speakup/ -obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_ANDROID) += android/ @@ -44,3 +44,5 @@ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ obj-$(CONFIG_UNISYSSPAR) += unisys/ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ +obj-$(CONFIG_FB_TFT) += fbtft/ +obj-$(CONFIG_I2O) += i2o/ diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 7e012f37792..8feb9048e62 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -14,23 +14,6 @@ config ASHMEM It is, in theory, a good memory allocator for low-memory devices, because it can discard shared memory units when under memory pressure. -config ANDROID_LOGGER - tristate "Android log driver" - default n - ---help--- - This adds support for system-wide logging using four log buffers. - - These are: - - 1: main - 2: events - 3: radio - 4: system - - Log reading and writing is performed via normal Linux reads and - optimized writes. This optimization avoids logging having too - much overhead in the system. - config ANDROID_TIMED_OUTPUT bool "Timed output class driver" default y @@ -45,15 +28,6 @@ config ANDROID_LOW_MEMORY_KILLER ---help--- Registers processes to be killed when memory is low -config ANDROID_INTF_ALARM_DEV - tristate "Android alarm driver" - depends on RTC_CLASS - default n - ---help--- - Provides non-wakeup and rtc backed wakeup alarms based on rtc or - elapsed realtime, and a non-wakeup alarm on the monotonic clock. - Also exports the alarm interface to user-space. - config SYNC bool "Synchronization framework" default n diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 479b2b86f8c..c7b6c99cc5c 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -3,10 +3,8 @@ ccflags-y += -I$(src) # needed for trace events obj-y += ion/ obj-$(CONFIG_ASHMEM) += ashmem.o -obj-$(CONFIG_ANDROID_LOGGER) += logger.o obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o -obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o obj-$(CONFIG_SYNC) += sync.o sync_debug.o obj-$(CONFIG_SW_SYNC) += sw_sync.o diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c deleted file mode 100644 index ff4b3e8758a..00000000000 --- a/drivers/staging/android/alarm-dev.c +++ /dev/null @@ -1,446 +0,0 @@ -/* drivers/rtc/alarm-dev.c - * - * Copyright (C) 2007-2009 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/time.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/miscdevice.h> -#include <linux/fs.h> -#include <linux/platform_device.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/uaccess.h> -#include <linux/alarmtimer.h> -#include "android_alarm.h" - -#define ANDROID_ALARM_PRINT_INFO (1U << 0) -#define ANDROID_ALARM_PRINT_IO (1U << 1) -#define ANDROID_ALARM_PRINT_INT (1U << 2) - -static int debug_mask = ANDROID_ALARM_PRINT_INFO; -module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); - -#define alarm_dbg(debug_level_mask, fmt, ...) \ -do { \ - if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) \ - pr_info(fmt, ##__VA_ARGS__); \ -} while (0) - -#define ANDROID_ALARM_WAKEUP_MASK ( \ - ANDROID_ALARM_RTC_WAKEUP_MASK | \ - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) - -static int alarm_opened; -static DEFINE_SPINLOCK(alarm_slock); -static struct wakeup_source alarm_wake_lock; -static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue); -static uint32_t alarm_pending; -static uint32_t alarm_enabled; -static uint32_t wait_pending; - -struct devalarm { - union { - struct hrtimer hrt; - struct alarm alrm; - } u; - enum android_alarm_type type; -}; - -static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT]; - -/** - * is_wakeup() - Checks to see if this alarm can wake the device - * @type: The type of alarm being checked - * - * Return: 1 if this is a wakeup alarm, otherwise 0 - */ -static int is_wakeup(enum android_alarm_type type) -{ - return type == ANDROID_ALARM_RTC_WAKEUP || - type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP; -} - -static void devalarm_start(struct devalarm *alrm, ktime_t exp) -{ - if (is_wakeup(alrm->type)) - alarm_start(&alrm->u.alrm, exp); - else - hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS); -} - -static int devalarm_try_to_cancel(struct devalarm *alrm) -{ - if (is_wakeup(alrm->type)) - return alarm_try_to_cancel(&alrm->u.alrm); - return hrtimer_try_to_cancel(&alrm->u.hrt); -} - -static void devalarm_cancel(struct devalarm *alrm) -{ - if (is_wakeup(alrm->type)) - alarm_cancel(&alrm->u.alrm); - else - hrtimer_cancel(&alrm->u.hrt); -} - -static void alarm_clear(enum android_alarm_type alarm_type) -{ - uint32_t alarm_type_mask = 1U << alarm_type; - unsigned long flags; - - spin_lock_irqsave(&alarm_slock, flags); - alarm_dbg(IO, "alarm %d clear\n", alarm_type); - devalarm_try_to_cancel(&alarms[alarm_type]); - if (alarm_pending) { - alarm_pending &= ~alarm_type_mask; - if (!alarm_pending && !wait_pending) - __pm_relax(&alarm_wake_lock); - } - alarm_enabled &= ~alarm_type_mask; - spin_unlock_irqrestore(&alarm_slock, flags); -} - -static void alarm_set(enum android_alarm_type alarm_type, - struct timespec *ts) -{ - uint32_t alarm_type_mask = 1U << alarm_type; - unsigned long flags; - - spin_lock_irqsave(&alarm_slock, flags); - alarm_dbg(IO, "alarm %d set %ld.%09ld\n", - alarm_type, ts->tv_sec, ts->tv_nsec); - alarm_enabled |= alarm_type_mask; - devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts)); - spin_unlock_irqrestore(&alarm_slock, flags); -} - -static int alarm_wait(void) -{ - unsigned long flags; - int rv = 0; - - spin_lock_irqsave(&alarm_slock, flags); - alarm_dbg(IO, "alarm wait\n"); - if (!alarm_pending && wait_pending) { - __pm_relax(&alarm_wake_lock); - wait_pending = 0; - } - spin_unlock_irqrestore(&alarm_slock, flags); - - rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); - if (rv) - return rv; - - spin_lock_irqsave(&alarm_slock, flags); - rv = alarm_pending; - wait_pending = 1; - alarm_pending = 0; - spin_unlock_irqrestore(&alarm_slock, flags); - - return rv; -} - -static int alarm_set_rtc(struct timespec *ts) -{ - struct rtc_time new_rtc_tm; - struct rtc_device *rtc_dev; - unsigned long flags; - int rv = 0; - - rtc_time_to_tm(ts->tv_sec, &new_rtc_tm); - rtc_dev = alarmtimer_get_rtcdev(); - rv = do_settimeofday(ts); - if (rv < 0) - return rv; - if (rtc_dev) - rv = rtc_set_time(rtc_dev, &new_rtc_tm); - - spin_lock_irqsave(&alarm_slock, flags); - alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; - wake_up(&alarm_wait_queue); - spin_unlock_irqrestore(&alarm_slock, flags); - - return rv; -} - -static int alarm_get_time(enum android_alarm_type alarm_type, - struct timespec *ts) -{ - int rv = 0; - - switch (alarm_type) { - case ANDROID_ALARM_RTC_WAKEUP: - case ANDROID_ALARM_RTC: - getnstimeofday(ts); - break; - case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: - case ANDROID_ALARM_ELAPSED_REALTIME: - get_monotonic_boottime(ts); - break; - case ANDROID_ALARM_SYSTEMTIME: - ktime_get_ts(ts); - break; - default: - rv = -EINVAL; - } - return rv; -} - -static long alarm_do_ioctl(struct file *file, unsigned int cmd, - struct timespec *ts) -{ - int rv = 0; - unsigned long flags; - enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); - - if (alarm_type >= ANDROID_ALARM_TYPE_COUNT) - return -EINVAL; - - if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) { - if ((file->f_flags & O_ACCMODE) == O_RDONLY) - return -EPERM; - if (file->private_data == NULL && - cmd != ANDROID_ALARM_SET_RTC) { - spin_lock_irqsave(&alarm_slock, flags); - if (alarm_opened) { - spin_unlock_irqrestore(&alarm_slock, flags); - return -EBUSY; - } - alarm_opened = 1; - file->private_data = (void *)1; - spin_unlock_irqrestore(&alarm_slock, flags); - } - } - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_CLEAR(0): - alarm_clear(alarm_type); - break; - case ANDROID_ALARM_SET(0): - alarm_set(alarm_type, ts); - break; - case ANDROID_ALARM_SET_AND_WAIT(0): - alarm_set(alarm_type, ts); - /* fall though */ - case ANDROID_ALARM_WAIT: - rv = alarm_wait(); - break; - case ANDROID_ALARM_SET_RTC: - rv = alarm_set_rtc(ts); - break; - case ANDROID_ALARM_GET_TIME(0): - rv = alarm_get_time(alarm_type, ts); - break; - - default: - rv = -EINVAL; - } - return rv; -} - -static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - - struct timespec ts; - int rv; - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_SET_AND_WAIT(0): - case ANDROID_ALARM_SET(0): - case ANDROID_ALARM_SET_RTC: - if (copy_from_user(&ts, (void __user *)arg, sizeof(ts))) - return -EFAULT; - break; - } - - rv = alarm_do_ioctl(file, cmd, &ts); - if (rv) - return rv; - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_GET_TIME(0): - if (copy_to_user((void __user *)arg, &ts, sizeof(ts))) - return -EFAULT; - break; - } - - return 0; -} - -#ifdef CONFIG_COMPAT -static long alarm_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - - struct timespec ts; - int rv; - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0): - case ANDROID_ALARM_SET_COMPAT(0): - case ANDROID_ALARM_SET_RTC_COMPAT: - if (compat_get_timespec(&ts, (void __user *)arg)) - return -EFAULT; - /* fall through */ - case ANDROID_ALARM_GET_TIME_COMPAT(0): - cmd = ANDROID_ALARM_COMPAT_TO_NORM(cmd); - break; - } - - rv = alarm_do_ioctl(file, cmd, &ts); - if (rv) - return rv; - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_GET_TIME(0): /* NOTE: we modified cmd above */ - if (compat_put_timespec(&ts, (void __user *)arg)) - return -EFAULT; - break; - } - - return 0; -} -#endif - -static int alarm_open(struct inode *inode, struct file *file) -{ - file->private_data = NULL; - return 0; -} - -static int alarm_release(struct inode *inode, struct file *file) -{ - int i; - unsigned long flags; - - spin_lock_irqsave(&alarm_slock, flags); - if (file->private_data) { - for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { - uint32_t alarm_type_mask = 1U << i; - - if (alarm_enabled & alarm_type_mask) { - alarm_dbg(INFO, - "%s: clear alarm, pending %d\n", - __func__, - !!(alarm_pending & alarm_type_mask)); - alarm_enabled &= ~alarm_type_mask; - } - spin_unlock_irqrestore(&alarm_slock, flags); - devalarm_cancel(&alarms[i]); - spin_lock_irqsave(&alarm_slock, flags); - } - if (alarm_pending | wait_pending) { - if (alarm_pending) - alarm_dbg(INFO, "%s: clear pending alarms %x\n", - __func__, alarm_pending); - __pm_relax(&alarm_wake_lock); - wait_pending = 0; - alarm_pending = 0; - } - alarm_opened = 0; - } - spin_unlock_irqrestore(&alarm_slock, flags); - return 0; -} - -static void devalarm_triggered(struct devalarm *alarm) -{ - unsigned long flags; - uint32_t alarm_type_mask = 1U << alarm->type; - - alarm_dbg(INT, "%s: type %d\n", __func__, alarm->type); - spin_lock_irqsave(&alarm_slock, flags); - if (alarm_enabled & alarm_type_mask) { - __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */ - alarm_enabled &= ~alarm_type_mask; - alarm_pending |= alarm_type_mask; - wake_up(&alarm_wait_queue); - } - spin_unlock_irqrestore(&alarm_slock, flags); -} - -static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt) -{ - struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt); - - devalarm_triggered(devalrm); - return HRTIMER_NORESTART; -} - -static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm, - ktime_t now) -{ - struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm); - - devalarm_triggered(devalrm); - return ALARMTIMER_NORESTART; -} - - -static const struct file_operations alarm_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = alarm_ioctl, - .open = alarm_open, - .release = alarm_release, -#ifdef CONFIG_COMPAT - .compat_ioctl = alarm_compat_ioctl, -#endif -}; - -static struct miscdevice alarm_device = { - .minor = MISC_DYNAMIC_MINOR, - .name = "alarm", - .fops = &alarm_fops, -}; - -static int __init alarm_dev_init(void) -{ - int err; - int i; - - err = misc_register(&alarm_device); - if (err) - return err; - - alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm, - ALARM_REALTIME, devalarm_alarmhandler); - hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt, - CLOCK_REALTIME, HRTIMER_MODE_ABS); - alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm, - ALARM_BOOTTIME, devalarm_alarmhandler); - hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt, - CLOCK_BOOTTIME, HRTIMER_MODE_ABS); - hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt, - CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - - for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { - alarms[i].type = i; - if (!is_wakeup(i)) - alarms[i].u.hrt.function = devalarm_hrthandler; - } - - wakeup_source_init(&alarm_wake_lock, "alarm"); - return 0; -} - -static void __exit alarm_dev_exit(void) -{ - misc_deregister(&alarm_device); - wakeup_source_trash(&alarm_wake_lock); -} - -module_init(alarm_dev_init); -module_exit(alarm_dev_exit); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h deleted file mode 100644 index 495b20cf3bf..00000000000 --- a/drivers/staging/android/android_alarm.h +++ /dev/null @@ -1,41 +0,0 @@ -/* include/linux/android_alarm.h - * - * Copyright (C) 2006-2007 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _LINUX_ANDROID_ALARM_H -#define _LINUX_ANDROID_ALARM_H - -#include <linux/compat.h> -#include <linux/ioctl.h> - -#include "uapi/android_alarm.h" - -#ifdef CONFIG_COMPAT -#define ANDROID_ALARM_SET_COMPAT(type) ALARM_IOW(2, type, \ - struct compat_timespec) -#define ANDROID_ALARM_SET_AND_WAIT_COMPAT(type) ALARM_IOW(3, type, \ - struct compat_timespec) -#define ANDROID_ALARM_GET_TIME_COMPAT(type) ALARM_IOW(4, type, \ - struct compat_timespec) -#define ANDROID_ALARM_SET_RTC_COMPAT _IOW('a', 5, \ - struct compat_timespec) -#define ANDROID_ALARM_IOCTL_NR(cmd) (_IOC_NR(cmd) & ((1<<4)-1)) -#define ANDROID_ALARM_COMPAT_TO_NORM(cmd) \ - ALARM_IOW(ANDROID_ALARM_IOCTL_NR(cmd), \ - ANDROID_ALARM_IOCTL_TO_TYPE(cmd), \ - struct timespec) - -#endif - -#endif diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 8c7852742f4..d140b733940 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -447,8 +447,8 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) loff_t end = (range->pgend + 1) * PAGE_SIZE; vfs_fallocate(range->asma->file, - FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, - start, end - start); + FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + start, end - start); range->purged = ASHMEM_WAS_PURGED; lru_del(range); @@ -549,7 +549,6 @@ static int get_name(struct ashmem_area *asma, void __user *name) mutex_lock(&ashmem_mutex); if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') { - /* * Copying only `len', instead of ASHMEM_NAME_LEN, bytes * prevents us from revealing one user's stack to another. @@ -751,10 +750,10 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (cmd) { case ASHMEM_SET_NAME: - ret = set_name(asma, (void __user *) arg); + ret = set_name(asma, (void __user *)arg); break; case ASHMEM_GET_NAME: - ret = get_name(asma, (void __user *) arg); + ret = get_name(asma, (void __user *)arg); break; case ASHMEM_SET_SIZE: ret = -EINVAL; @@ -775,7 +774,7 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case ASHMEM_PIN: case ASHMEM_UNPIN: case ASHMEM_GET_PIN_STATUS: - ret = ashmem_pin_unpin(asma, cmd, (void __user *) arg); + ret = ashmem_pin_unpin(asma, cmd, (void __user *)arg); break; case ASHMEM_PURGE_ALL_CACHES: ret = -EPERM; @@ -798,7 +797,6 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static long compat_ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - switch (cmd) { case COMPAT_ASHMEM_SET_SIZE: cmd = ASHMEM_SET_SIZE; diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 296d347660f..b8f1c491553 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1508,6 +1508,9 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) pr_err("%s: can not add heap with invalid ops struct.\n", __func__); + spin_lock_init(&heap->free_lock); + heap->free_list_size = 0; + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_init_deferred_free(heap); diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index f8cabcbc39e..f4211f1be48 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -39,24 +39,6 @@ struct ion_cma_buffer_info { struct sg_table *table; }; -/* - * Create scatter-list for the already allocated DMA buffer. - * This function could be replaced by dma_common_get_sgtable - * as soon as it will avalaible. - */ -static int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt, - void *cpu_addr, dma_addr_t handle, size_t size) -{ - struct page *page = virt_to_page(cpu_addr); - int ret; - - ret = sg_alloc_table(sgt, 1, GFP_KERNEL); - if (unlikely(ret)) - return ret; - - sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); - return 0; -} /* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, @@ -91,7 +73,7 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, if (!info->table) goto free_mem; - if (ion_cma_get_sgtable + if (dma_common_get_sgtable (dev, info->table, info->cpu_addr, info->handle, len)) goto free_table; /* keep this for memory release */ diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 4605e04712a..fd13d05b538 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -253,8 +253,6 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) struct sched_param param = { .sched_priority = 0 }; INIT_LIST_HEAD(&heap->free_list); - heap->free_list_size = 0; - spin_lock_init(&heap->free_lock); init_waitqueue_head(&heap->waitqueue); heap->task = kthread_run(ion_heap_deferred_free, heap, "%s", heap->name); diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c deleted file mode 100644 index a673ffa34aa..00000000000 --- a/drivers/staging/android/logger.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * drivers/misc/logger.c - * - * A Logging Subsystem - * - * Copyright (C) 2007-2008 Google, Inc. - * - * Robert Love <rlove@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "logger: " fmt - -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/uaccess.h> -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/time.h> -#include <linux/vmalloc.h> -#include <linux/aio.h> -#include "logger.h" - -#include <asm/ioctls.h> - -/** - * struct logger_log - represents a specific log, such as 'main' or 'radio' - * @buffer: The actual ring buffer - * @misc: The "misc" device representing the log - * @wq: The wait queue for @readers - * @readers: This log's readers - * @mutex: The mutex that protects the @buffer - * @w_off: The current write head offset - * @head: The head, or location that readers start reading at. - * @size: The size of the log - * @logs: The list of log channels - * - * This structure lives from module insertion until module removal, so it does - * not need additional reference counting. The structure is protected by the - * mutex 'mutex'. - */ -struct logger_log { - unsigned char *buffer; - struct miscdevice misc; - wait_queue_head_t wq; - struct list_head readers; - struct mutex mutex; - size_t w_off; - size_t head; - size_t size; - struct list_head logs; -}; - -static LIST_HEAD(log_list); - - -/** - * struct logger_reader - a logging device open for reading - * @log: The associated log - * @list: The associated entry in @logger_log's list - * @r_off: The current read head offset. - * @r_all: Reader can read all entries - * @r_ver: Reader ABI version - * - * This object lives from open to release, so we don't need additional - * reference counting. The structure is protected by log->mutex. - */ -struct logger_reader { - struct logger_log *log; - struct list_head list; - size_t r_off; - bool r_all; - int r_ver; -}; - -/* logger_offset - returns index 'n' into the log via (optimized) modulus */ -static size_t logger_offset(struct logger_log *log, size_t n) -{ - return n & (log->size - 1); -} - - -/* - * file_get_log - Given a file structure, return the associated log - * - * This isn't aesthetic. We have several goals: - * - * 1) Need to quickly obtain the associated log during an I/O operation - * 2) Readers need to maintain state (logger_reader) - * 3) Writers need to be very fast (open() should be a near no-op) - * - * In the reader case, we can trivially go file->logger_reader->logger_log. - * For a writer, we don't want to maintain a logger_reader, so we just go - * file->logger_log. Thus what file->private_data points at depends on whether - * or not the file was opened for reading. This function hides that dirtiness. - */ -static inline struct logger_log *file_get_log(struct file *file) -{ - if (file->f_mode & FMODE_READ) { - struct logger_reader *reader = file->private_data; - - return reader->log; - } - return file->private_data; -} - -/* - * get_entry_header - returns a pointer to the logger_entry header within - * 'log' starting at offset 'off'. A temporary logger_entry 'scratch' must - * be provided. Typically the return value will be a pointer within - * 'logger->buf'. However, a pointer to 'scratch' may be returned if - * the log entry spans the end and beginning of the circular buffer. - */ -static struct logger_entry *get_entry_header(struct logger_log *log, - size_t off, struct logger_entry *scratch) -{ - size_t len = min(sizeof(struct logger_entry), log->size - off); - - if (len != sizeof(struct logger_entry)) { - memcpy(((void *) scratch), log->buffer + off, len); - memcpy(((void *) scratch) + len, log->buffer, - sizeof(struct logger_entry) - len); - return scratch; - } - - return (struct logger_entry *) (log->buffer + off); -} - -/* - * get_entry_msg_len - Grabs the length of the message of the entry - * starting from from 'off'. - * - * An entry length is 2 bytes (16 bits) in host endian order. - * In the log, the length does not include the size of the log entry structure. - * This function returns the size including the log entry structure. - * - * Caller needs to hold log->mutex. - */ -static __u32 get_entry_msg_len(struct logger_log *log, size_t off) -{ - struct logger_entry scratch; - struct logger_entry *entry; - - entry = get_entry_header(log, off, &scratch); - return entry->len; -} - -static size_t get_user_hdr_len(int ver) -{ - if (ver < 2) - return sizeof(struct user_logger_entry_compat); - return sizeof(struct logger_entry); -} - -static ssize_t copy_header_to_user(int ver, struct logger_entry *entry, - char __user *buf) -{ - void *hdr; - size_t hdr_len; - struct user_logger_entry_compat v1; - - if (ver < 2) { - v1.len = entry->len; - v1.__pad = 0; - v1.pid = entry->pid; - v1.tid = entry->tid; - v1.sec = entry->sec; - v1.nsec = entry->nsec; - hdr = &v1; - hdr_len = sizeof(struct user_logger_entry_compat); - } else { - hdr = entry; - hdr_len = sizeof(struct logger_entry); - } - - return copy_to_user(buf, hdr, hdr_len); -} - -/* - * do_read_log_to_user - reads exactly 'count' bytes from 'log' into the - * user-space buffer 'buf'. Returns 'count' on success. - * - * Caller must hold log->mutex. - */ -static ssize_t do_read_log_to_user(struct logger_log *log, - struct logger_reader *reader, - char __user *buf, - size_t count) -{ - struct logger_entry scratch; - struct logger_entry *entry; - size_t len; - size_t msg_start; - - /* - * First, copy the header to userspace, using the version of - * the header requested - */ - entry = get_entry_header(log, reader->r_off, &scratch); - if (copy_header_to_user(reader->r_ver, entry, buf)) - return -EFAULT; - - count -= get_user_hdr_len(reader->r_ver); - buf += get_user_hdr_len(reader->r_ver); - msg_start = logger_offset(log, - reader->r_off + sizeof(struct logger_entry)); - - /* - * We read from the msg in two disjoint operations. First, we read from - * the current msg head offset up to 'count' bytes or to the end of - * the log, whichever comes first. - */ - len = min(count, log->size - msg_start); - if (copy_to_user(buf, log->buffer + msg_start, len)) - return -EFAULT; - - /* - * Second, we read any remaining bytes, starting back at the head of - * the log. - */ - if (count != len) - if (copy_to_user(buf + len, log->buffer, count - len)) - return -EFAULT; - - reader->r_off = logger_offset(log, reader->r_off + - sizeof(struct logger_entry) + count); - - return count + get_user_hdr_len(reader->r_ver); -} - -/* - * get_next_entry_by_uid - Starting at 'off', returns an offset into - * 'log->buffer' which contains the first entry readable by 'euid' - */ -static size_t get_next_entry_by_uid(struct logger_log *log, - size_t off, kuid_t euid) -{ - while (off != log->w_off) { - struct logger_entry *entry; - struct logger_entry scratch; - size_t next_len; - - entry = get_entry_header(log, off, &scratch); - - if (uid_eq(entry->euid, euid)) - return off; - - next_len = sizeof(struct logger_entry) + entry->len; - off = logger_offset(log, off + next_len); - } - - return off; -} - -/* - * logger_read - our log's read() method - * - * Behavior: - * - * - O_NONBLOCK works - * - If there are no log entries to read, blocks until log is written to - * - Atomically reads exactly one log entry - * - * Will set errno to EINVAL if read - * buffer is insufficient to hold next entry. - */ -static ssize_t logger_read(struct file *file, char __user *buf, - size_t count, loff_t *pos) -{ - struct logger_reader *reader = file->private_data; - struct logger_log *log = reader->log; - ssize_t ret; - DEFINE_WAIT(wait); - -start: - while (1) { - mutex_lock(&log->mutex); - - prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE); - - ret = (log->w_off == reader->r_off); - mutex_unlock(&log->mutex); - if (!ret) - break; - - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - if (signal_pending(current)) { - ret = -EINTR; - break; - } - - schedule(); - } - - finish_wait(&log->wq, &wait); - if (ret) - return ret; - - mutex_lock(&log->mutex); - - if (!reader->r_all) - reader->r_off = get_next_entry_by_uid(log, - reader->r_off, current_euid()); - - /* is there still something to read or did we race? */ - if (unlikely(log->w_off == reader->r_off)) { - mutex_unlock(&log->mutex); - goto start; - } - - /* get the size of the next entry */ - ret = get_user_hdr_len(reader->r_ver) + - get_entry_msg_len(log, reader->r_off); - if (count < ret) { - ret = -EINVAL; - goto out; - } - - /* get exactly one entry from the log */ - ret = do_read_log_to_user(log, reader, buf, ret); - -out: - mutex_unlock(&log->mutex); - - return ret; -} - -/* - * get_next_entry - return the offset of the first valid entry at least 'len' - * bytes after 'off'. - * - * Caller must hold log->mutex. - */ -static size_t get_next_entry(struct logger_log *log, size_t off, size_t len) -{ - size_t count = 0; - - do { - size_t nr = sizeof(struct logger_entry) + - get_entry_msg_len(log, off); - off = logger_offset(log, off + nr); - count += nr; - } while (count < len); - - return off; -} - -/* - * is_between - is a < c < b, accounting for wrapping of a, b, and c - * positions in the buffer - * - * That is, if a<b, check for c between a and b - * and if a>b, check for c outside (not between) a and b - * - * |------- a xxxxxxxx b --------| - * c^ - * - * |xxxxx b --------- a xxxxxxxxx| - * c^ - * or c^ - */ -static inline int is_between(size_t a, size_t b, size_t c) -{ - if (a < b) { - /* is c between a and b? */ - if (a < c && c <= b) - return 1; - } else { - /* is c outside of b through a? */ - if (c <= b || a < c) - return 1; - } - - return 0; -} - -/* - * fix_up_readers - walk the list of all readers and "fix up" any who were - * lapped by the writer; also do the same for the default "start head". - * We do this by "pulling forward" the readers and start head to the first - * entry after the new write head. - * - * The caller needs to hold log->mutex. - */ -static void fix_up_readers(struct logger_log *log, size_t len) -{ - size_t old = log->w_off; - size_t new = logger_offset(log, old + len); - struct logger_reader *reader; - - if (is_between(old, new, log->head)) - log->head = get_next_entry(log, log->head, len); - - list_for_each_entry(reader, &log->readers, list) - if (is_between(old, new, reader->r_off)) - reader->r_off = get_next_entry(log, reader->r_off, len); -} - -/* - * logger_write_iter - our write method, implementing support for write(), - * writev(), and aio_write(). Writes are our fast path, and we try to optimize - * them above all else. - */ -static ssize_t logger_write_iter(struct kiocb *iocb, struct iov_iter *from) -{ - struct logger_log *log = file_get_log(iocb->ki_filp); - struct logger_entry header; - struct timespec now; - size_t len, count, w_off; - - count = min_t(size_t, iocb->ki_nbytes, LOGGER_ENTRY_MAX_PAYLOAD); - - now = current_kernel_time(); - - header.pid = current->tgid; - header.tid = current->pid; - header.sec = now.tv_sec; - header.nsec = now.tv_nsec; - header.euid = current_euid(); - header.len = count; - header.hdr_size = sizeof(struct logger_entry); - - /* null writes succeed, return zero */ - if (unlikely(!header.len)) - return 0; - - mutex_lock(&log->mutex); - - /* - * Fix up any readers, pulling them forward to the first readable - * entry after (what will be) the new write offset. We do this now - * because if we partially fail, we can end up with clobbered log - * entries that encroach on readable buffer. - */ - fix_up_readers(log, sizeof(struct logger_entry) + header.len); - - len = min(sizeof(header), log->size - log->w_off); - memcpy(log->buffer + log->w_off, &header, len); - memcpy(log->buffer, (char *)&header + len, sizeof(header) - len); - - /* Work with a copy until we are ready to commit the whole entry */ - w_off = logger_offset(log, log->w_off + sizeof(struct logger_entry)); - - len = min(count, log->size - w_off); - - if (copy_from_iter(log->buffer + w_off, len, from) != len) { - /* - * Note that by not updating log->w_off, this abandons the - * portion of the new entry that *was* successfully - * copied, just above. This is intentional to avoid - * message corruption from missing fragments. - */ - mutex_unlock(&log->mutex); - return -EFAULT; - } - - if (copy_from_iter(log->buffer, count - len, from) != count - len) { - mutex_unlock(&log->mutex); - return -EFAULT; - } - - log->w_off = logger_offset(log, w_off + count); - mutex_unlock(&log->mutex); - - /* wake up any blocked readers */ - wake_up_interruptible(&log->wq); - - return len; -} - -static struct logger_log *get_log_from_minor(int minor) -{ - struct logger_log *log; - - list_for_each_entry(log, &log_list, logs) - if (log->misc.minor == minor) - return log; - return NULL; -} - -/* - * logger_open - the log's open() file operation - * - * Note how near a no-op this is in the write-only case. Keep it that way! - */ -static int logger_open(struct inode *inode, struct file *file) -{ - struct logger_log *log; - int ret; - - ret = nonseekable_open(inode, file); - if (ret) - return ret; - - log = get_log_from_minor(MINOR(inode->i_rdev)); - if (!log) - return -ENODEV; - - if (file->f_mode & FMODE_READ) { - struct logger_reader *reader; - - reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL); - if (!reader) - return -ENOMEM; - - reader->log = log; - reader->r_ver = 1; - reader->r_all = in_egroup_p(inode->i_gid) || - capable(CAP_SYSLOG); - - INIT_LIST_HEAD(&reader->list); - - mutex_lock(&log->mutex); - reader->r_off = log->head; - list_add_tail(&reader->list, &log->readers); - mutex_unlock(&log->mutex); - - file->private_data = reader; - } else - file->private_data = log; - - return 0; -} - -/* - * logger_release - the log's release file operation - * - * Note this is a total no-op in the write-only case. Keep it that way! - */ -static int logger_release(struct inode *ignored, struct file *file) -{ - if (file->f_mode & FMODE_READ) { - struct logger_reader *reader = file->private_data; - struct logger_log *log = reader->log; - - mutex_lock(&log->mutex); - list_del(&reader->list); - mutex_unlock(&log->mutex); - - kfree(reader); - } - - return 0; -} - -/* - * logger_poll - the log's poll file operation, for poll/select/epoll - * - * Note we always return POLLOUT, because you can always write() to the log. - * Note also that, strictly speaking, a return value of POLLIN does not - * guarantee that the log is readable without blocking, as there is a small - * chance that the writer can lap the reader in the interim between poll() - * returning and the read() request. - */ -static unsigned int logger_poll(struct file *file, poll_table *wait) -{ - struct logger_reader *reader; - struct logger_log *log; - unsigned int ret = POLLOUT | POLLWRNORM; - - if (!(file->f_mode & FMODE_READ)) - return ret; - - reader = file->private_data; - log = reader->log; - - poll_wait(file, &log->wq, wait); - - mutex_lock(&log->mutex); - if (!reader->r_all) - reader->r_off = get_next_entry_by_uid(log, - reader->r_off, current_euid()); - - if (log->w_off != reader->r_off) - ret |= POLLIN | POLLRDNORM; - mutex_unlock(&log->mutex); - - return ret; -} - -static long logger_set_version(struct logger_reader *reader, void __user *arg) -{ - int version; - - if (copy_from_user(&version, arg, sizeof(int))) - return -EFAULT; - - if ((version < 1) || (version > 2)) - return -EINVAL; - - reader->r_ver = version; - return 0; -} - -static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct logger_log *log = file_get_log(file); - struct logger_reader *reader; - long ret = -EINVAL; - void __user *argp = (void __user *) arg; - - mutex_lock(&log->mutex); - - switch (cmd) { - case LOGGER_GET_LOG_BUF_SIZE: - ret = log->size; - break; - case LOGGER_GET_LOG_LEN: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - if (log->w_off >= reader->r_off) - ret = log->w_off - reader->r_off; - else - ret = (log->size - reader->r_off) + log->w_off; - break; - case LOGGER_GET_NEXT_ENTRY_LEN: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - - if (!reader->r_all) - reader->r_off = get_next_entry_by_uid(log, - reader->r_off, current_euid()); - - if (log->w_off != reader->r_off) - ret = get_user_hdr_len(reader->r_ver) + - get_entry_msg_len(log, reader->r_off); - else - ret = 0; - break; - case LOGGER_FLUSH_LOG: - if (!(file->f_mode & FMODE_WRITE)) { - ret = -EBADF; - break; - } - if (!(in_egroup_p(file_inode(file)->i_gid) || - capable(CAP_SYSLOG))) { - ret = -EPERM; - break; - } - list_for_each_entry(reader, &log->readers, list) - reader->r_off = log->w_off; - log->head = log->w_off; - ret = 0; - break; - case LOGGER_GET_VERSION: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - ret = reader->r_ver; - break; - case LOGGER_SET_VERSION: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - ret = logger_set_version(reader, argp); - break; - } - - mutex_unlock(&log->mutex); - - return ret; -} - -static const struct file_operations logger_fops = { - .owner = THIS_MODULE, - .read = logger_read, - .write_iter = logger_write_iter, - .poll = logger_poll, - .unlocked_ioctl = logger_ioctl, - .compat_ioctl = logger_ioctl, - .open = logger_open, - .release = logger_release, -}; - -/* - * Log size must must be a power of two, and greater than - * (LOGGER_ENTRY_MAX_PAYLOAD + sizeof(struct logger_entry)). - */ -static int __init create_log(char *log_name, int size) -{ - int ret = 0; - struct logger_log *log; - unsigned char *buffer; - - buffer = vmalloc(size); - if (buffer == NULL) - return -ENOMEM; - - log = kzalloc(sizeof(struct logger_log), GFP_KERNEL); - if (log == NULL) { - ret = -ENOMEM; - goto out_free_buffer; - } - log->buffer = buffer; - - log->misc.minor = MISC_DYNAMIC_MINOR; - log->misc.name = kstrdup(log_name, GFP_KERNEL); - if (log->misc.name == NULL) { - ret = -ENOMEM; - goto out_free_log; - } - - log->misc.fops = &logger_fops; - log->misc.parent = NULL; - - init_waitqueue_head(&log->wq); - INIT_LIST_HEAD(&log->readers); - mutex_init(&log->mutex); - log->w_off = 0; - log->head = 0; - log->size = size; - - INIT_LIST_HEAD(&log->logs); - list_add_tail(&log->logs, &log_list); - - /* finally, initialize the misc device for this log */ - ret = misc_register(&log->misc); - if (unlikely(ret)) { - pr_err("failed to register misc device for log '%s'!\n", - log->misc.name); - goto out_free_misc_name; - } - - pr_info("created %luK log '%s'\n", - (unsigned long) log->size >> 10, log->misc.name); - - return 0; - -out_free_misc_name: - kfree(log->misc.name); - -out_free_log: - kfree(log); - -out_free_buffer: - vfree(buffer); - return ret; -} - -static int __init logger_init(void) -{ - int ret; - - ret = create_log(LOGGER_LOG_MAIN, 256*1024); - if (unlikely(ret)) - goto out; - - ret = create_log(LOGGER_LOG_EVENTS, 256*1024); - if (unlikely(ret)) - goto out; - - ret = create_log(LOGGER_LOG_RADIO, 256*1024); - if (unlikely(ret)) - goto out; - - ret = create_log(LOGGER_LOG_SYSTEM, 256*1024); - if (unlikely(ret)) - goto out; - -out: - return ret; -} - -static void __exit logger_exit(void) -{ - struct logger_log *current_log, *next_log; - - list_for_each_entry_safe(current_log, next_log, &log_list, logs) { - /* we have to delete all the entry inside log_list */ - misc_deregister(¤t_log->misc); - vfree(current_log->buffer); - kfree(current_log->misc.name); - list_del(¤t_log->logs); - kfree(current_log); - } -} - - -device_initcall(logger_init); -module_exit(logger_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Robert Love, <rlove@google.com>"); -MODULE_DESCRIPTION("Android Logger"); diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h deleted file mode 100644 index 70af7d805df..00000000000 --- a/drivers/staging/android/logger.h +++ /dev/null @@ -1,89 +0,0 @@ -/* include/linux/logger.h - * - * Copyright (C) 2007-2008 Google, Inc. - * Author: Robert Love <rlove@android.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _LINUX_LOGGER_H -#define _LINUX_LOGGER_H - -#include <linux/types.h> -#include <linux/ioctl.h> - -/** - * struct user_logger_entry_compat - defines a single entry that is given to a logger - * @len: The length of the payload - * @__pad: Two bytes of padding that appear to be required - * @pid: The generating process' process ID - * @tid: The generating process' thread ID - * @sec: The number of seconds that have elapsed since the Epoch - * @nsec: The number of nanoseconds that have elapsed since @sec - * @msg: The message that is to be logged - * - * The userspace structure for version 1 of the logger_entry ABI. - * This structure is returned to userspace unless the caller requests - * an upgrade to a newer ABI version. - */ -struct user_logger_entry_compat { - __u16 len; - __u16 __pad; - __s32 pid; - __s32 tid; - __s32 sec; - __s32 nsec; - char msg[0]; -}; - -/** - * struct logger_entry - defines a single entry that is given to a logger - * @len: The length of the payload - * @hdr_size: sizeof(struct logger_entry_v2) - * @pid: The generating process' process ID - * @tid: The generating process' thread ID - * @sec: The number of seconds that have elapsed since the Epoch - * @nsec: The number of nanoseconds that have elapsed since @sec - * @euid: Effective UID of logger - * @msg: The message that is to be logged - * - * The structure for version 2 of the logger_entry ABI. - * This structure is returned to userspace if ioctl(LOGGER_SET_VERSION) - * is called with version >= 2 - */ -struct logger_entry { - __u16 len; - __u16 hdr_size; - __s32 pid; - __s32 tid; - __s32 sec; - __s32 nsec; - kuid_t euid; - char msg[0]; -}; - -#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */ -#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */ -#define LOGGER_LOG_SYSTEM "log_system" /* system/framework messages */ -#define LOGGER_LOG_MAIN "log_main" /* everything else */ - -#define LOGGER_ENTRY_MAX_PAYLOAD 4076 - -#define __LOGGERIO 0xAE - -#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */ -#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */ -#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */ -#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */ -#define LOGGER_GET_VERSION _IO(__LOGGERIO, 5) /* abi version */ -#define LOGGER_SET_VERSION _IO(__LOGGERIO, 6) /* abi version */ - -#endif /* _LINUX_LOGGER_H */ diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 1532a86404b..91ed2c4cff4 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -96,7 +96,8 @@ static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence) sync_status_str(status)); if (status <= 0) { - struct timespec64 ts64 = ktime_to_timespec64(pt->base.timestamp); + struct timespec64 ts64 = + ktime_to_timespec64(pt->base.timestamp); seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); } diff --git a/drivers/staging/android/uapi/android_alarm.h b/drivers/staging/android/uapi/android_alarm.h deleted file mode 100644 index aa013f6f5f3..00000000000 --- a/drivers/staging/android/uapi/android_alarm.h +++ /dev/null @@ -1,62 +0,0 @@ -/* drivers/staging/android/uapi/android_alarm.h - * - * Copyright (C) 2006-2007 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _UAPI_LINUX_ANDROID_ALARM_H -#define _UAPI_LINUX_ANDROID_ALARM_H - -#include <linux/ioctl.h> -#include <linux/time.h> - -enum android_alarm_type { - /* return code bit numbers or set alarm arg */ - ANDROID_ALARM_RTC_WAKEUP, - ANDROID_ALARM_RTC, - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, - ANDROID_ALARM_ELAPSED_REALTIME, - ANDROID_ALARM_SYSTEMTIME, - - ANDROID_ALARM_TYPE_COUNT, - - /* return code bit numbers */ - /* ANDROID_ALARM_TIME_CHANGE = 16 */ -}; - -enum android_alarm_return_flags { - ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP, - ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC, - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK = - 1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, - ANDROID_ALARM_ELAPSED_REALTIME_MASK = - 1U << ANDROID_ALARM_ELAPSED_REALTIME, - ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME, - ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16 -}; - -/* Disable alarm */ -#define ANDROID_ALARM_CLEAR(type) _IO('a', 0 | ((type) << 4)) - -/* Ack last alarm and wait for next */ -#define ANDROID_ALARM_WAIT _IO('a', 1) - -#define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) -/* Set alarm */ -#define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) -#define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) -#define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) -#define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) -#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) - -#endif diff --git a/drivers/staging/board/board.c b/drivers/staging/board/board.c index 6050fbdfd31..d5a6abc8451 100644 --- a/drivers/staging/board/board.c +++ b/drivers/staging/board/board.c @@ -11,8 +11,7 @@ static bool find_by_address(u64 base_address) struct resource res; while (dn) { - if (of_can_translate_address(dn) - && !of_address_to_resource(dn, 0, &res)) { + if (!of_address_to_resource(dn, 0, &res)) { if (res.start == base_address) { of_node_put(dn); return true; diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c index 471d0877f38..5455bf3d5a9 100644 --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c +++ b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c @@ -91,8 +91,10 @@ static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event, if (ndata->clk == clk_wzrd->clk_in1) max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1]; - if (ndata->clk == clk_wzrd->axi_clk) + else if (ndata->clk == clk_wzrd->axi_clk) max = WZRD_ACLK_MAX_FREQ; + else + return NOTIFY_DONE; /* should never happen */ switch (event) { case PRE_RATE_CHANGE: @@ -239,6 +241,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) /* register div per output */ for (i = WZRD_NUM_OUTPUTS - 1; i >= 0 ; i--) { const char *clkout_name; + if (of_property_read_string_index(np, "clock-output-names", i, &clkout_name)) { dev_err(&pdev->dev, diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index a8201fe8751..593fcb1783b 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -168,7 +168,7 @@ config COMEDI_PCL730 config COMEDI_PCL812 tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216" - depends on VIRT_TO_BUS && ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA, @@ -179,7 +179,7 @@ config COMEDI_PCL812 config COMEDI_PCL816 tristate "Advantech PCL-814 and PCL-816 ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for Advantech PCL-814 and PCL-816 ISA cards @@ -188,7 +188,7 @@ config COMEDI_PCL816 config COMEDI_PCL818 tristate "Advantech PCL-718 and PCL-818 ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for Advantech PCL-818 ISA cards PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718 @@ -281,7 +281,7 @@ config COMEDI_DAS08_ISA config COMEDI_DAS16 tristate "DAS-16 compatible ISA and PC/104 card support" - depends on ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API select COMEDI_8255 ---help--- Enable support for Keithley Metrabyte/ComputerBoards DAS16 @@ -309,7 +309,7 @@ config COMEDI_DAS800 config COMEDI_DAS1800 tristate "DAS1800 and compatible ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for DAS1800 and compatible ISA cards Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO, @@ -372,7 +372,7 @@ config COMEDI_DT2817 config COMEDI_DT282X tristate "Data Translation DT2821 series and DT-EZ ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for Data Translation DT2821 series including DT-EZ DT2821, DT2821-F-16SE, DT2821-F-8DI, DT2821-G-16SE, DT2821-G-8DI, @@ -462,7 +462,7 @@ config COMEDI_ADQ12B config COMEDI_NI_AT_A2150 tristate "NI AT-A2150 ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for National Instruments AT-A2150 cards @@ -502,7 +502,7 @@ config COMEDI_NI_ATMIO16D config COMEDI_NI_LABPC_ISA tristate "NI Lab-PC and compatibles ISA support" select COMEDI_NI_LABPC - select COMEDI_NI_LABPC_ISADMA if ISA_DMA_API && VIRT_TO_BUS + select COMEDI_NI_LABPC_ISADMA if ISA_DMA_API ---help--- Enable support for National Instruments Lab-PC and compatibles Lab-PC-1200, Lab-PC-1200AI, Lab-PC+. @@ -724,7 +724,6 @@ config COMEDI_ADL_PCI9111 config COMEDI_ADL_PCI9118 tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support" depends on HAS_DMA - depends on VIRT_TO_BUS ---help--- Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards @@ -1263,12 +1262,16 @@ config COMEDI_DAS08 tristate select COMEDI_8255 +config COMEDI_ISADMA + tristate + config COMEDI_NI_LABPC tristate select COMEDI_8255 config COMEDI_NI_LABPC_ISADMA tristate + select COMEDI_ISADMA config COMEDI_NI_TIO tristate diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 5a4c74f703b..25848244c4b 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -1,23 +1,23 @@ /* - comedi/comedi_compat32.c - 32-bit ioctl compatibility for 64-bit comedi kernel module. - - Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk> - Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org> - - 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/comedi_compat32.c + * 32-bit ioctl compatibility for 64-bit comedi kernel module. + * + * Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk> + * Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include <linux/uaccess.h> #include <linux/compat.h> @@ -27,11 +27,15 @@ #define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct) #define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct) -/* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. - * It's too late to change it now, but it only affects the command number. */ +/* + * N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. + * It's too late to change it now, but it only affects the command number. + */ #define COMEDI32_CMD _IOR(CIO, 9, struct comedi32_cmd_struct) -/* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR. - * It's too late to change it now, but it only affects the command number. */ +/* + * N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR. + * It's too late to change it now, but it only affects the command number. + */ #define COMEDI32_CMDTEST _IOR(CIO, 10, struct comedi32_cmd_struct) #define COMEDI32_INSNLIST _IOR(CIO, 11, struct comedi32_insnlist_struct) #define COMEDI32_INSN _IOR(CIO, 12, struct comedi32_insn_struct) @@ -39,7 +43,7 @@ struct comedi32_chaninfo_struct { unsigned int subdev; compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */ - compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */ + compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */ compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */ unsigned int unused[4]; }; @@ -62,16 +66,16 @@ struct comedi32_cmd_struct { unsigned int scan_end_arg; unsigned int stop_src; unsigned int stop_arg; - compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */ + compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */ unsigned int chanlist_len; - compat_uptr_t data; /* 32-bit 'short *' */ + compat_uptr_t data; /* 32-bit 'short *' */ unsigned int data_len; }; struct comedi32_insn_struct { unsigned int insn; unsigned int n; - compat_uptr_t data; /* 32-bit 'unsigned int *' */ + compat_uptr_t data; /* 32-bit 'unsigned int *' */ unsigned int subdev; unsigned int chanspec; unsigned int unused[3]; @@ -79,7 +83,7 @@ struct comedi32_insn_struct { struct comedi32_insnlist_struct { unsigned int n_insns; - compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */ + compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */ }; /* Handle translated ioctl. */ @@ -215,10 +219,12 @@ static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, int err; unsigned int temp; - /* Copy back most of cmd structure. */ - /* Assume the pointer values are already valid. */ - /* (Could use ptr_to_compat() to set them, but that wasn't implemented - * until kernel version 2.6.11.) */ + /* + * Copy back most of cmd structure. + * + * Assume the pointer values are already valid. + * (Could use ptr_to_compat() to set them.) + */ if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd)) || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) return -EFAULT; @@ -262,7 +268,7 @@ static int compat_cmd(struct file *file, unsigned long arg) { struct comedi_cmd __user *cmd; struct comedi32_cmd_struct __user *cmd32; - int rc; + int rc, err; cmd32 = compat_ptr(arg); cmd = compat_alloc_user_space(sizeof(*cmd)); @@ -271,7 +277,15 @@ static int compat_cmd(struct file *file, unsigned long arg) if (rc) return rc; - return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); + rc = translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); + if (rc == -EAGAIN) { + /* Special case: copy cmd back to user. */ + err = put_compat_cmd(cmd32, cmd); + if (err) + rc = err; + } + + return rc; } /* Handle 32-bit COMEDI_CMDTEST ioctl. */ @@ -395,10 +409,12 @@ static int compat_insn(struct file *file, unsigned long arg) return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn); } -/* Process untranslated ioctl. */ -/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ -static inline int raw_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +/* + * compat_ioctl file operation. + * + * Returns -ENOIOCTLCMD for unrecognised ioctl codes. + */ +long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int rc; @@ -445,10 +461,3 @@ static inline int raw_ioctl(struct file *file, unsigned int cmd, } return rc; } - -/* compat_ioctl file operation. */ -/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ -long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return raw_ioctl(file, cmd, arg); -} diff --git a/drivers/staging/comedi/comedi_compat32.h b/drivers/staging/comedi/comedi_compat32.h index 2d0a6fcf60f..5ce77f3e8c2 100644 --- a/drivers/staging/comedi/comedi_compat32.h +++ b/drivers/staging/comedi/comedi_compat32.h @@ -1,23 +1,23 @@ /* - comedi/comedi_compat32.h - 32-bit ioctl compatibility for 64-bit comedi kernel module. - - Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk> - Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org> - - 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/comedi_compat32.h + * 32-bit ioctl compatibility for 64-bit comedi kernel module. + * + * Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk> + * Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _COMEDI_COMPAT32_H #define _COMEDI_COMPAT32_H diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index f143cb64d69..727640e89c7 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1,20 +1,20 @@ /* - comedi/comedi_fops.c - comedi kernel module - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> - - 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/comedi_fops.c + * comedi kernel module + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -113,6 +113,18 @@ static void comedi_dev_kref_release(struct kref *kref) kfree(dev); } +/** + * comedi_dev_put - release a use of a comedi device structure + * @dev: comedi_device struct + * + * Must be called when a user of a comedi device is finished with it. + * When the last user of the comedi device calls this function, the + * comedi device is destroyed. + * + * Return 1 if the comedi device is destroyed by this call or dev is + * NULL, otherwise return 0. Callers must not assume the comedi + * device is still valid if this function returns 0. + */ int comedi_dev_put(struct comedi_device *dev) { if (dev) @@ -220,6 +232,18 @@ static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) return dev; } +/** + * comedi_dev_get_from_minor - get comedi device by minor device number + * @minor: minor device number + * + * Finds the comedi device associated by the minor device number, if any, + * and increments its reference count. The comedi device is prevented from + * being freed until a matching call is made to comedi_dev_put(). + * + * Return a pointer to the comedi device if it exists, with its usage + * reference incremented. Return NULL if no comedi device exists with the + * specified minor device number. + */ struct comedi_device *comedi_dev_get_from_minor(unsigned minor) { if (minor < COMEDI_NUM_BOARD_MINORS) @@ -323,8 +347,7 @@ static int resize_async_buffer(struct comedi_device *dev, return -EBUSY; } - /* make sure buffer is an integral number of pages - * (we round up) */ + /* make sure buffer is an integral number of pages (we round up) */ new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; retval = comedi_buf_alloc(dev, s, new_size); @@ -600,11 +623,18 @@ static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s) return runflags; } +/** + * comedi_is_subdevice_running - check if async command running on subdevice + * @s: comedi_subdevice struct + * + * Return true if an asynchronous comedi command is active on the comedi + * subdevice, else return false. + */ bool comedi_is_subdevice_running(struct comedi_subdevice *s) { unsigned runflags = comedi_get_subdevice_runflags(s); - return (runflags & SRF_RUNNING) ? true : false; + return (runflags & COMEDI_SRF_RUNNING) ? true : false; } EXPORT_SYMBOL_GPL(comedi_is_subdevice_running); @@ -612,14 +642,14 @@ static bool comedi_is_subdevice_in_error(struct comedi_subdevice *s) { unsigned runflags = comedi_get_subdevice_runflags(s); - return (runflags & SRF_ERROR) ? true : false; + return (runflags & COMEDI_SRF_ERROR) ? true : false; } static bool comedi_is_subdevice_idle(struct comedi_subdevice *s) { unsigned runflags = comedi_get_subdevice_runflags(s); - return (runflags & (SRF_ERROR | SRF_RUNNING)) ? false : true; + return (runflags & COMEDI_SRF_BUSY_MASK) ? false : true; } /** @@ -634,20 +664,20 @@ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) { s->private = kzalloc(size, GFP_KERNEL); if (s->private) - s->runflags |= SRF_FREE_SPRIV; + s->runflags |= COMEDI_SRF_FREE_SPRIV; return s->private; } EXPORT_SYMBOL_GPL(comedi_alloc_spriv); /* - This function restores a subdevice to an idle state. + * This function restores a subdevice to an idle state. */ static void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_async *async = s->async; - comedi_set_subdevice_runflags(s, SRF_RUNNING, 0); + comedi_set_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0); if (async) { comedi_buf_reset(s); async->inttrig = NULL; @@ -709,18 +739,18 @@ static int is_device_busy(struct comedi_device *dev) } /* - COMEDI_DEVCONFIG - device config ioctl - - arg: - pointer to devconfig structure - - reads: - devconfig structure at arg - - writes: - none -*/ + * COMEDI_DEVCONFIG ioctl + * attaches (and configures) or detaches a legacy device + * + * arg: + * pointer to comedi_devconfig structure (NULL if detaching) + * + * reads: + * comedi_devconfig structure (if attaching) + * + * writes: + * nothing + */ static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig __user *arg) { @@ -761,19 +791,18 @@ static int do_devconfig_ioctl(struct comedi_device *dev, } /* - COMEDI_BUFCONFIG - buffer configuration ioctl - - arg: - pointer to bufconfig structure - - reads: - bufconfig at arg - - writes: - modified bufconfig at arg - -*/ + * COMEDI_BUFCONFIG ioctl + * buffer configuration + * + * arg: + * pointer to comedi_bufconfig structure + * + * reads: + * comedi_bufconfig structure + * + * writes: + * modified comedi_bufconfig structure + */ static int do_bufconfig_ioctl(struct comedi_device *dev, struct comedi_bufconfig __user *arg) { @@ -823,19 +852,18 @@ copyback: } /* - COMEDI_DEVINFO - device info ioctl - - arg: - pointer to devinfo structure - - reads: - none - - writes: - devinfo structure - -*/ + * COMEDI_DEVINFO ioctl + * device info + * + * arg: + * pointer to comedi_devinfo structure + * + * reads: + * nothing + * + * writes: + * comedi_devinfo structure + */ static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo __user *arg, struct file *file) @@ -870,19 +898,18 @@ static int do_devinfo_ioctl(struct comedi_device *dev, } /* - COMEDI_SUBDINFO - subdevice info ioctl - - arg: - pointer to array of subdevice info structures - - reads: - none - - writes: - array of subdevice info structures at arg - -*/ + * COMEDI_SUBDINFO ioctl + * subdevices info + * + * arg: + * pointer to array of comedi_subdinfo structures + * + * reads: + * nothing + * + * writes: + * array of comedi_subdinfo structures + */ static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo __user *arg, void *file) { @@ -944,19 +971,19 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, } /* - COMEDI_CHANINFO - subdevice info ioctl - - arg: - pointer to chaninfo structure - - reads: - chaninfo structure at arg - - writes: - arrays at elements of chaninfo structure - -*/ + * COMEDI_CHANINFO ioctl + * subdevice channel info + * + * arg: + * pointer to comedi_chaninfo structure + * + * reads: + * comedi_chaninfo structure + * + * writes: + * array of maxdata values to chaninfo->maxdata_list if requested + * array of range table lengths to chaninfo->range_table_list if requested + */ static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo __user *arg) { @@ -1004,20 +1031,19 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, return 0; } - /* - COMEDI_BUFINFO - buffer information ioctl - - arg: - pointer to bufinfo structure - - reads: - bufinfo at arg - - writes: - modified bufinfo at arg - - */ +/* + * COMEDI_BUFINFO ioctl + * buffer information + * + * arg: + * pointer to comedi_bufinfo structure + * + * reads: + * comedi_bufinfo structure + * + * writes: + * modified comedi_bufinfo structure + */ static int do_bufinfo_ioctl(struct comedi_device *dev, struct comedi_bufinfo __user *arg, void *file) { @@ -1135,8 +1161,10 @@ static int check_insn_config_length(struct comedi_insn *insn, if (insn->n == 6) return 0; break; - /* by default we allow the insn since we don't have checks for - * all possible cases yet */ + /* + * by default we allow the insn since we don't have checks for + * all possible cases yet + */ default: pr_warn("No check for data length of config insn id %i is implemented\n", data[0]); @@ -1287,9 +1315,11 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, if (insn->n != 2) { ret = -EINVAL; } else { - /* Most drivers ignore the base channel in + /* + * Most drivers ignore the base channel in * insn->chanspec. Fix this here if - * the subdevice has <= 32 channels. */ + * the subdevice has <= 32 channels. + */ unsigned int orig_mask = data[0]; unsigned int shift = 0; @@ -1326,19 +1356,19 @@ out: } /* - * COMEDI_INSNLIST - * synchronous instructions + * COMEDI_INSNLIST ioctl + * synchronous instruction list * - * arg: - * pointer to sync cmd structure + * arg: + * pointer to comedi_insnlist structure * - * reads: - * sync cmd struct at arg - * instruction list - * data (for writes) + * reads: + * comedi_insnlist structure + * array of comedi_insn structures from insnlist->insns pointer + * data (for writes) from insns[].data pointers * - * writes: - * data (for reads) + * writes: + * data (for reads) to insns[].data pointers */ /* arbitrary limits */ #define MAX_SAMPLES 256 @@ -1415,18 +1445,18 @@ error: } /* - * COMEDI_INSN - * synchronous instructions + * COMEDI_INSN ioctl + * synchronous instruction * - * arg: - * pointer to insn + * arg: + * pointer to comedi_insn structure * - * reads: - * struct comedi_insn struct at arg - * data (for writes) + * reads: + * comedi_insn structure + * data (for writes) from insn->data pointer * - * writes: - * data (for reads) + * writes: + * data (for reads) to insn->data pointer */ static int do_insn_ioctl(struct comedi_device *dev, struct comedi_insn __user *arg, void *file) @@ -1558,6 +1588,20 @@ static int __comedi_get_user_chanlist(struct comedi_device *dev, return 0; } +/* + * COMEDI_CMD ioctl + * asynchronous acquisition command set-up + * + * arg: + * pointer to comedi_cmd structure + * + * reads: + * comedi_cmd structure + * channel/range list from cmd->chanlist pointer + * + * writes: + * possibly modified comedi_cmd structure (when -EAGAIN returned) + */ static int do_cmd_ioctl(struct comedi_device *dev, struct comedi_cmd __user *arg, void *file) { @@ -1634,10 +1678,13 @@ static int do_cmd_ioctl(struct comedi_device *dev, if (async->cmd.flags & CMDF_WAKE_EOS) async->cb_mask |= COMEDI_CB_EOS; - comedi_set_subdevice_runflags(s, SRF_ERROR | SRF_RUNNING, SRF_RUNNING); + comedi_set_subdevice_runflags(s, COMEDI_SRF_BUSY_MASK, + COMEDI_SRF_RUNNING); - /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with - * comedi_read() or comedi_write() */ + /* + * Set s->busy _after_ setting COMEDI_SRF_RUNNING flag to avoid + * race with comedi_read() or comedi_write(). + */ s->busy = file; ret = s->do_cmd(dev, s); if (ret == 0) @@ -1650,20 +1697,19 @@ cleanup: } /* - COMEDI_CMDTEST - command testing ioctl - - arg: - pointer to cmd structure - - reads: - cmd structure at arg - channel/range list - - writes: - modified cmd structure at arg - -*/ + * COMEDI_CMDTEST ioctl + * asynchronous aquisition command testing + * + * arg: + * pointer to comedi_cmd structure + * + * reads: + * comedi_cmd structure + * channel/range list from cmd->chanlist pointer + * + * writes: + * possibly modified comedi_cmd structure + */ static int do_cmdtest_ioctl(struct comedi_device *dev, struct comedi_cmd __user *arg, void *file) { @@ -1706,20 +1752,18 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, } /* - COMEDI_LOCK - lock subdevice - - arg: - subdevice number - - reads: - none - - writes: - none - -*/ - + * COMEDI_LOCK ioctl + * lock subdevice + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1742,21 +1786,18 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg, } /* - COMEDI_UNLOCK - unlock subdevice - - arg: - subdevice number - - reads: - none - - writes: - none - - This function isn't protected by the semaphore, since - we already own the lock. -*/ + * COMEDI_UNLOCK ioctl + * unlock subdevice + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1779,19 +1820,18 @@ static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg, } /* - COMEDI_CANCEL - cancel acquisition ioctl - - arg: - subdevice number - - reads: - nothing - - writes: - nothing - -*/ + * COMEDI_CANCEL ioctl + * cancel asynchronous acquisition + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1813,19 +1853,18 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg, } /* - COMEDI_POLL ioctl - instructs driver to synchronize buffers - - arg: - subdevice number - - reads: - nothing - - writes: - nothing - -*/ + * COMEDI_POLL ioctl + * instructs driver to synchronize buffers + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_poll_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1941,8 +1980,10 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, mutex_lock(&dev->mutex); - /* Device config is special, because it must work on - * an unconfigured device. */ + /* + * Device config is special, because it must work on + * an unconfigured device. + */ if (cmd == COMEDI_DEVCONFIG) { if (minor >= COMEDI_NUM_BOARD_MINORS) { /* Device config not appropriate on non-board minors. */ @@ -1954,8 +1995,10 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, if (rc == 0) { if (arg == 0 && dev->minor >= comedi_num_legacy_minors) { - /* Successfully unconfigured a dynamically - * allocated device. Try and remove it. */ + /* + * Successfully unconfigured a dynamically + * allocated device. Try and remove it. + */ if (comedi_clear_board_dev(dev)) { mutex_unlock(&dev->mutex); comedi_free_board_dev(dev); @@ -2581,6 +2624,17 @@ static const struct file_operations comedi_fops = { .llseek = noop_llseek, }; +/** + * comedi_event - handle events for asynchronous comedi command + * @dev: comedi_device struct + * @s: comedi_subdevice struct associated with dev + * Context: interrupt (usually), s->spin_lock spin-lock not held + * + * If an asynchronous comedi command is active on the subdevice, process + * any COMEDI_CB_... event flags that have been set, usually by an + * interrupt handler. These may change the run state of the asynchronous + * command, wake a task, and/or send a SIGIO signal. + */ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_async *async = s->async; @@ -2591,18 +2645,21 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) return; if (s->async->events & COMEDI_CB_CANCEL_MASK) - runflags_mask |= SRF_RUNNING; + runflags_mask |= COMEDI_SRF_RUNNING; /* * Remember if an error event has occurred, so an error * can be returned the next time the user does a read(). */ if (s->async->events & COMEDI_CB_ERROR_MASK) { - runflags_mask |= SRF_ERROR; - runflags |= SRF_ERROR; + runflags_mask |= COMEDI_SRF_ERROR; + runflags |= COMEDI_SRF_ERROR; } if (runflags_mask) { - /*sets SRF_ERROR and SRF_RUNNING together atomically */ + /* + * Sets COMEDI_SRF_ERROR and COMEDI_SRF_RUNNING together + * atomically. + */ comedi_set_subdevice_runflags(s, runflags_mask, runflags); } diff --git a/drivers/staging/comedi/comedi_pcmcia.c b/drivers/staging/comedi/comedi_pcmcia.c index 0529bae8e5a..7e784399a16 100644 --- a/drivers/staging/comedi/comedi_pcmcia.c +++ b/drivers/staging/comedi/comedi_pcmcia.c @@ -19,10 +19,7 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> - -#include "comedidev.h" +#include "comedi_pcmcia.h" /** * comedi_to_pcmcia_dev() - comedi_device pointer to pcmcia_device pointer. diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h new file mode 100644 index 00000000000..5d3db2b9b4a --- /dev/null +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -0,0 +1,55 @@ +/* + * comedi_pcmcia.h + * header file for Comedi PCMCIA drivers + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _COMEDI_PCMCIA_H +#define _COMEDI_PCMCIA_H + +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h> + +#include "comedidev.h" + +struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *); + +int comedi_pcmcia_enable(struct comedi_device *, + int (*conf_check)(struct pcmcia_device *, void *)); +void comedi_pcmcia_disable(struct comedi_device *); + +int comedi_pcmcia_auto_config(struct pcmcia_device *, struct comedi_driver *); +void comedi_pcmcia_auto_unconfig(struct pcmcia_device *); + +int comedi_pcmcia_driver_register(struct comedi_driver *, + struct pcmcia_driver *); +void comedi_pcmcia_driver_unregister(struct comedi_driver *, + struct pcmcia_driver *); + +/** + * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver + * @__comedi_driver: comedi_driver struct + * @__pcmcia_driver: pcmcia_driver struct + * + * Helper macro for comedi PCMCIA drivers which do not do anything special + * in module init/exit. This eliminates a lot of boilerplate. Each + * module may only use this macro once, and calling it replaces + * module_init() and module_exit() + */ +#define module_comedi_pcmcia_driver(__comedi_driver, __pcmcia_driver) \ + module_driver(__comedi_driver, comedi_pcmcia_driver_register, \ + comedi_pcmcia_driver_unregister, &(__pcmcia_driver)) + +#endif /* _COMEDI_PCMCIA_H */ diff --git a/drivers/staging/comedi/comedi_usb.c b/drivers/staging/comedi/comedi_usb.c index 0b862a64c04..68b75e8feec 100644 --- a/drivers/staging/comedi/comedi_usb.c +++ b/drivers/staging/comedi/comedi_usb.c @@ -17,9 +17,8 @@ */ #include <linux/module.h> -#include <linux/usb.h> -#include "comedidev.h" +#include "comedi_usb.h" /** * comedi_to_usb_interface() - comedi_device pointer to usb_interface pointer. diff --git a/drivers/staging/comedi/comedi_usb.h b/drivers/staging/comedi/comedi_usb.h new file mode 100644 index 00000000000..721128bece3 --- /dev/null +++ b/drivers/staging/comedi/comedi_usb.h @@ -0,0 +1,50 @@ +/* + * comedi_usb.h + * header file for USB Comedi drivers + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _COMEDI_USB_H +#define _COMEDI_USB_H + +#include <linux/usb.h> + +#include "comedidev.h" + +struct usb_interface *comedi_to_usb_interface(struct comedi_device *); +struct usb_device *comedi_to_usb_dev(struct comedi_device *); + +int comedi_usb_auto_config(struct usb_interface *, struct comedi_driver *, + unsigned long context); +void comedi_usb_auto_unconfig(struct usb_interface *); + +int comedi_usb_driver_register(struct comedi_driver *, struct usb_driver *); +void comedi_usb_driver_unregister(struct comedi_driver *, struct usb_driver *); + +/** + * module_comedi_usb_driver() - Helper macro for registering a comedi USB driver + * @__comedi_driver: comedi_driver struct + * @__usb_driver: usb_driver struct + * + * Helper macro for comedi USB drivers which do not do anything special + * in module init/exit. This eliminates a lot of boilerplate. Each + * module may only use this macro once, and calling it replaces + * module_init() and module_exit() + */ +#define module_comedi_usb_driver(__comedi_driver, __usb_driver) \ + module_driver(__comedi_driver, comedi_usb_driver_register, \ + comedi_usb_driver_unregister, &(__usb_driver)) + +#endif /* _COMEDI_USB_H */ diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 77be191988c..e138eb0dc37 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -299,34 +299,25 @@ struct comedi_device { void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); -/* we can expand the number of bits used to encode devices/subdevices into - the minor number soon, after more distros support > 8 bit minor numbers - (like after Debian Etch gets released) */ -enum comedi_minor_bits { - COMEDI_DEVICE_MINOR_MASK = 0xf, - COMEDI_SUBDEVICE_MINOR_MASK = 0xf0 -}; - -static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4; -static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; - struct comedi_device *comedi_dev_get_from_minor(unsigned minor); int comedi_dev_put(struct comedi_device *dev); -void init_polling(void); -void cleanup_polling(void); -void start_polling(struct comedi_device *); -void stop_polling(struct comedi_device *); - -/* subdevice runflags */ -enum subdevice_runflags { - SRF_RT = 0x00000002, - /* indicates an COMEDI_CB_ERROR event has occurred since the last - * command was started */ - SRF_ERROR = 0x00000004, - SRF_RUNNING = 0x08000000, - SRF_FREE_SPRIV = 0x80000000, /* free s->private on detach */ -}; +/** + * comedi_subdevice "runflags" + * @COMEDI_SRF_RT: DEPRECATED: command is running real-time + * @COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred + * since the last command was started + * @COMEDI_SRF_RUNNING: command is running + * @COMEDI_SRF_FREE_SPRIV: free s->private on detach + * + * @COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy" + */ +#define COMEDI_SRF_RT BIT(1) +#define COMEDI_SRF_ERROR BIT(2) +#define COMEDI_SRF_RUNNING BIT(27) +#define COMEDI_SRF_FREE_SPRIV BIT(31) + +#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING) bool comedi_is_subdevice_running(struct comedi_subdevice *s); @@ -605,66 +596,4 @@ void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *); module_driver(__comedi_driver, comedi_pci_driver_register, \ comedi_pci_driver_unregister, &(__pci_driver)) -/* comedi_pcmcia.c - comedi PCMCIA driver specific functions */ - -struct pcmcia_driver; -struct pcmcia_device; - -struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *); - -int comedi_pcmcia_enable(struct comedi_device *, - int (*conf_check)(struct pcmcia_device *, void *)); -void comedi_pcmcia_disable(struct comedi_device *); - -int comedi_pcmcia_auto_config(struct pcmcia_device *, struct comedi_driver *); -void comedi_pcmcia_auto_unconfig(struct pcmcia_device *); - -int comedi_pcmcia_driver_register(struct comedi_driver *, - struct pcmcia_driver *); -void comedi_pcmcia_driver_unregister(struct comedi_driver *, - struct pcmcia_driver *); - -/** - * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver - * @__comedi_driver: comedi_driver struct - * @__pcmcia_driver: pcmcia_driver struct - * - * Helper macro for comedi PCMCIA drivers which do not do anything special - * in module init/exit. This eliminates a lot of boilerplate. Each - * module may only use this macro once, and calling it replaces - * module_init() and module_exit() - */ -#define module_comedi_pcmcia_driver(__comedi_driver, __pcmcia_driver) \ - module_driver(__comedi_driver, comedi_pcmcia_driver_register, \ - comedi_pcmcia_driver_unregister, &(__pcmcia_driver)) - -/* comedi_usb.c - comedi USB driver specific functions */ - -struct usb_driver; -struct usb_interface; - -struct usb_interface *comedi_to_usb_interface(struct comedi_device *); -struct usb_device *comedi_to_usb_dev(struct comedi_device *); - -int comedi_usb_auto_config(struct usb_interface *, struct comedi_driver *, - unsigned long context); -void comedi_usb_auto_unconfig(struct usb_interface *); - -int comedi_usb_driver_register(struct comedi_driver *, struct usb_driver *); -void comedi_usb_driver_unregister(struct comedi_driver *, struct usb_driver *); - -/** - * module_comedi_usb_driver() - Helper macro for registering a comedi USB driver - * @__comedi_driver: comedi_driver struct - * @__usb_driver: usb_driver struct - * - * Helper macro for comedi USB drivers which do not do anything special - * in module init/exit. This eliminates a lot of boilerplate. Each - * module may only use this macro once, and calling it replaces - * module_init() and module_exit() - */ -#define module_comedi_usb_driver(__comedi_driver, __usb_driver) \ - module_driver(__comedi_driver, comedi_usb_driver_register, \ - comedi_usb_driver_unregister, &(__usb_driver)) - #endif /* _COMEDIDEV_H */ diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 61802d7947a..f32e7143894 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -125,7 +125,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; - if (s->runflags & SRF_FREE_SPRIV) + if (s->runflags & COMEDI_SRF_FREE_SPRIV) kfree(s->private); comedi_free_subdevice_minor(s); if (s->async) { diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h index 9f4c1411719..51b9c8d279c 100644 --- a/drivers/staging/comedi/drivers/8253.h +++ b/drivers/staging/comedi/drivers/8253.h @@ -1,20 +1,20 @@ /* - comedi/drivers/8253.h - Header file for 8253 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/drivers/8253.h + * Header file for 8253 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _8253_H #define _8253_H @@ -44,9 +44,11 @@ static inline void i8253_cascade_ns_to_timer(int i8253_osc_base, unsigned int start; unsigned int ns_low, ns_high; static const unsigned int max_count = 0x10000; - /* exit early if everything is already correct (this can save time + /* + * exit early if everything is already correct (this can save time * since this function may be called repeatedly during command tests - * and execution) */ + * and execution) + */ div1 = *d1 ? *d1 : max_count; div2 = *d2 ? *d2 : max_count; divider = div1 * div2; @@ -114,13 +116,14 @@ static inline void i8253_cascade_ns_to_timer(int i8253_osc_base, } *nanosec = div1 * div2 * i8253_osc_base; - /* masking is done since counter maps zero to 0x10000 */ + /* masking is done since counter maps zero to 0x10000 */ *d1 = div1 & 0xffff; *d2 = div2 & 0xffff; } #ifndef CMDTEST -/* i8254_load programs 8254 counter chip. It should also work for the 8253. +/* + * i8254_load programs 8254 counter chip. It should also work for the 8253. * base_address is the lowest io address * for the chip (the address of counter 0). * counter_number is the counter you want to load (0,1 or 2) @@ -158,12 +161,12 @@ static inline int i8254_load(unsigned long base_address, unsigned int regshift, return -1; byte = counter_number << 6; - byte |= 0x30; /* load low then high byte */ - byte |= (mode << 1); /* set counter mode */ + byte |= 0x30; /* load low then high byte */ + byte |= (mode << 1); /* set counter mode */ outb(byte, base_address + (i8254_control_reg << regshift)); - byte = count & 0xff; /* lsb of counter value */ + byte = count & 0xff; /* lsb of counter value */ outb(byte, base_address + (counter_number << regshift)); - byte = (count >> 8) & 0xff; /* msb of counter value */ + byte = (count >> 8) & 0xff; /* msb of counter value */ outb(byte, base_address + (counter_number << regshift)); return 0; @@ -187,18 +190,18 @@ static inline int i8254_mm_load(void __iomem *base_address, return -1; byte = counter_number << 6; - byte |= 0x30; /* load low then high byte */ - byte |= (mode << 1); /* set counter mode */ + byte |= 0x30; /* load low then high byte */ + byte |= (mode << 1); /* set counter mode */ writeb(byte, base_address + (i8254_control_reg << regshift)); - byte = count & 0xff; /* lsb of counter value */ + byte = count & 0xff; /* lsb of counter value */ writeb(byte, base_address + (counter_number << regshift)); - byte = (count >> 8) & 0xff; /* msb of counter value */ + byte = (count >> 8) & 0xff; /* msb of counter value */ writeb(byte, base_address + (counter_number << regshift)); return 0; } -/* Returns 16 bit counter value, should work for 8253 also.*/ +/* Returns 16 bit counter value, should work for 8253 also. */ static inline int i8254_read(unsigned long base_address, unsigned int regshift, unsigned int counter_number) { @@ -208,13 +211,13 @@ static inline int i8254_read(unsigned long base_address, unsigned int regshift, if (counter_number > 2) return -1; - /* latch counter */ + /* latch counter */ byte = counter_number << 6; outb(byte, base_address + (i8254_control_reg << regshift)); - /* read lsb */ + /* read lsb */ ret = inb(base_address + (counter_number << regshift)); - /* read msb */ + /* read msb */ ret += inb(base_address + (counter_number << regshift)) << 8; return ret; @@ -230,13 +233,13 @@ static inline int i8254_mm_read(void __iomem *base_address, if (counter_number > 2) return -1; - /* latch counter */ + /* latch counter */ byte = counter_number << 6; writeb(byte, base_address + (i8254_control_reg << regshift)); - /* read lsb */ + /* read lsb */ ret = readb(base_address + (counter_number << regshift)); - /* read msb */ + /* read msb */ ret += readb(base_address + (counter_number << regshift)) << 8; return ret; @@ -252,9 +255,9 @@ static inline void i8254_write(unsigned long base_address, if (counter_number > 2) return; - byte = count & 0xff; /* lsb of counter value */ + byte = count & 0xff; /* lsb of counter value */ outb(byte, base_address + (counter_number << regshift)); - byte = (count >> 8) & 0xff; /* msb of counter value */ + byte = (count >> 8) & 0xff; /* msb of counter value */ outb(byte, base_address + (counter_number << regshift)); } @@ -268,13 +271,14 @@ static inline void i8254_mm_write(void __iomem *base_address, if (counter_number > 2) return; - byte = count & 0xff; /* lsb of counter value */ + byte = count & 0xff; /* lsb of counter value */ writeb(byte, base_address + (counter_number << regshift)); - byte = (count >> 8) & 0xff; /* msb of counter value */ + byte = (count >> 8) & 0xff; /* msb of counter value */ writeb(byte, base_address + (counter_number << regshift)); } -/* Set counter mode, should work for 8253 also. +/* + * Set counter mode, should work for 8253 also. * Note: the 'mode' value is different to that for i8254_load() and comes * from the INSN_CONFIG_8254_SET_MODE command: * I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 @@ -293,8 +297,8 @@ static inline int i8254_set_mode(unsigned long base_address, return -1; byte = counter_number << 6; - byte |= 0x30; /* load low then high byte */ - byte |= mode; /* set counter mode and BCD|binary */ + byte |= 0x30; /* load low then high byte */ + byte |= mode; /* set counter mode and BCD|binary */ outb(byte, base_address + (i8254_control_reg << regshift)); return 0; @@ -313,8 +317,8 @@ static inline int i8254_mm_set_mode(void __iomem *base_address, return -1; byte = counter_number << 6; - byte |= 0x30; /* load low then high byte */ - byte |= mode; /* set counter mode and BCD|binary */ + byte |= 0x30; /* load low then high byte */ + byte |= mode; /* set counter mode and BCD|binary */ writeb(byte, base_address + (i8254_control_reg << regshift)); return 0; diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 34d4d8b5f31..c2f15de6a54 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -1,76 +1,51 @@ /* - comedi/drivers/8255.c - Driver for 8255 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998 David A. Schleef <ds@schleef.org> - - 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: 8255 -Description: generic 8255 support -Devices: [standard] 8255 (8255) -Author: ds -Status: works -Updated: Fri, 7 Jun 2002 12:56:45 -0700 - -The classic in digital I/O. The 8255 appears in Comedi as a single -digital I/O subdevice with 24 channels. The channel 0 corresponds -to the 8255's port A, bit 0; channel 23 corresponds to port C, bit -7. Direction configuration is done in blocks, with channels 0-7, -8-15, 16-19, and 20-23 making up the 4 blocks. The only 8255 mode -supported is mode 0. - -You should enable compilation this driver if you plan to use a board -that has an 8255 chip. For multifunction boards, the main driver will -configure the 8255 subdevice automatically. - -This driver also works independently with ISA and PCI cards that -directly map the 8255 registers to I/O ports, including cards with -multiple 8255 chips. To configure the driver for such a card, the -option list should be a list of the I/O port bases for each of the -8255 chips. For example, - - comedi_config /dev/comedi0 8255 0x200,0x204,0x208,0x20c - -Note that most PCI 8255 boards do NOT work with this driver, and -need a separate driver as a wrapper. For those that do work, the -I/O port base address can be found in the output of 'lspci -v'. - -*/ + * comedi/drivers/8255.c + * Driver for 8255 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef <ds@schleef.org> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* - This file contains an exported subdevice for driving an 8255. - - To use this subdevice as part of another driver, you need to - set up the subdevice in the attach function of the driver by - calling: - - subdev_8255_init(device, subdevice, io_function, iobase) - - device and subdevice are pointers to the device and subdevice - structures. io_function will be called to provide the - low-level input/output to the device, i.e., actual register - access. io_function will be called with the value of iobase - as the last parameter. If the 8255 device is mapped as 4 - consecutive I/O ports, you can use NULL for io_function - and the I/O port base for iobase, and an internal function will - handle the register access. - - In addition, if the main driver handles interrupts, you can - enable commands on the subdevice by calling subdev_8255_init_irq() - instead. Then, when you get an interrupt that is likely to be - from the 8255, you should call subdev_8255_interrupt(), which - will copy the latched value to a Comedi buffer. + * Driver: 8255 + * Description: generic 8255 support + * Devices: [standard] 8255 (8255) + * Author: ds + * Status: works + * Updated: Fri, 7 Jun 2002 12:56:45 -0700 + * + * The classic in digital I/O. The 8255 appears in Comedi as a single + * digital I/O subdevice with 24 channels. The channel 0 corresponds + * to the 8255's port A, bit 0; channel 23 corresponds to port C, bit + * 7. Direction configuration is done in blocks, with channels 0-7, + * 8-15, 16-19, and 20-23 making up the 4 blocks. The only 8255 mode + * supported is mode 0. + * + * You should enable compilation this driver if you plan to use a board + * that has an 8255 chip. For multifunction boards, the main driver will + * configure the 8255 subdevice automatically. + * + * This driver also works independently with ISA and PCI cards that + * directly map the 8255 registers to I/O ports, including cards with + * multiple 8255 chips. To configure the driver for such a card, the + * option list should be a list of the I/O port bases for each of the + * 8255 chips. For example, + * + * comedi_config /dev/comedi0 8255 0x200,0x204,0x208,0x20c + * + * Note that most PCI 8255 boards do NOT work with this driver, and + * need a separate driver as a wrapper. For those that do work, the + * I/O port base address can be found in the output of 'lspci -v'. */ #include <linux/module.h> @@ -218,6 +193,33 @@ static int __subdev_8255_init(struct comedi_device *dev, return 0; } +/** + * subdev_8255_init - initialize DIO subdevice for driving I/O mapped 8255 + * @dev: comedi device owning subdevice + * @s: comedi subdevice to initialize + * @io: (optional) register I/O call-back function + * @regbase: offset of 8255 registers from dev->iobase, or call-back context + * + * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. + * + * If the optional I/O call-back function is provided, its prototype is of + * the following form: + * + * int my_8255_callback(struct comedi_device *dev, + * struct comedi_subdevice *s, int dir, int port, + * int data, unsigned long regbase); + * + * where 'dev', 's', and 'regbase' match the values passed to this function, + * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' + * is the direction (0 for read, 1 for write) and 'data' is the value to be + * written. It should return 0 if writing or the value read if reading. + * + * If the optional I/O call-back function is not provided, an internal + * call-back function is used which uses consecutive I/O port addresses + * starting at dev->iobase + regbase. + * + * Return: -ENOMEM if failed to allocate memory, zero on success. + */ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, int (*io)(struct comedi_device *, int, int, int, unsigned long), @@ -227,6 +229,33 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, } EXPORT_SYMBOL_GPL(subdev_8255_init); +/** + * subdev_8255_mm_init - initialize DIO subdevice for driving mmio-mapped 8255 + * @dev: comedi device owning subdevice + * @s: comedi subdevice to initialize + * @io: (optional) register I/O call-back function + * @regbase: offset of 8255 registers from dev->mmio, or call-back context + * + * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. + * + * If the optional I/O call-back function is provided, its prototype is of + * the following form: + * + * int my_8255_callback(struct comedi_device *dev, + * struct comedi_subdevice *s, int dir, int port, + * int data, unsigned long regbase); + * + * where 'dev', 's', and 'regbase' match the values passed to this function, + * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' + * is the direction (0 for read, 1 for write) and 'data' is the value to be + * written. It should return 0 if writing or the value read if reading. + * + * If the optional I/O call-back function is not provided, an internal + * call-back function is used which uses consecutive MMIO virtual addresses + * starting at dev->mmio + regbase. + * + * Return: -ENOMEM if failed to allocate memory, zero on success. + */ int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, int (*io)(struct comedi_device *, int, int, int, unsigned long), @@ -235,10 +264,9 @@ int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, return __subdev_8255_init(dev, s, io, regbase, true); } EXPORT_SYMBOL_GPL(subdev_8255_mm_init); -/* - - Start of the 8255 standalone device +/* + * Start of the 8255 standalone device */ static int dev_8255_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h index 5985c8e0330..934b940ebd3 100644 --- a/drivers/staging/comedi/drivers/8255.h +++ b/drivers/staging/comedi/drivers/8255.h @@ -1,20 +1,20 @@ /* - module/8255.h - Header file for 8255 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998 David A. Schleef <ds@schleef.org> - - 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * module/8255.h + * Header file for 8255 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef <ds@schleef.org> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _8255_H #define _8255_H diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 8b958982885..984764211a2 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -22,33 +22,44 @@ */ /* -Driver: 8255_pci -Description: Generic PCI based 8255 Digital I/O boards -Devices: (ADLink) PCI-7224 [adl_pci-7224] - 24 channels - (ADLink) PCI-7248 [adl_pci-7248] - 48 channels - (ADLink) PCI-7296 [adl_pci-7296] - 96 channels - (Measurement Computing) PCI-DIO24 [cb_pci-dio24] - 24 channels - (Measurement Computing) PCI-DIO24H [cb_pci-dio24h] - 24 channels - (Measurement Computing) PCI-DIO48H [cb_pci-dio48h] - 48 channels - (Measurement Computing) PCI-DIO96H [cb_pci-dio96h] - 96 channels - (National Instruments) PCI-DIO-96 [ni_pci-dio-96] - 96 channels - (National Instruments) PCI-DIO-96B [ni_pci-dio-96b] - 96 channels - (National Instruments) PXI-6508 [ni_pxi-6508] - 96 channels - (National Instruments) PCI-6503 [ni_pci-6503] - 24 channels - (National Instruments) PCI-6503B [ni_pci-6503b] - 24 channels - (National Instruments) PCI-6503X [ni_pci-6503x] - 24 channels - (National Instruments) PXI-6503 [ni_pxi-6503] - 24 channels -Author: H Hartley Sweeten <hsweeten@visionengravers.com> -Updated: Wed, 12 Sep 2012 11:52:01 -0700 -Status: untested - -Some of these boards also have an 8254 programmable timer/counter -chip. This chip is not currently supported by this driver. - -Interrupt support for these boards is also not currently supported. - -Configuration Options: not applicable, uses PCI auto config -*/ + * Driver: 8255_pci + * Description: Generic PCI based 8255 Digital I/O boards + * Devices: [ADLink] PCI-7224 (adl_pci-7224), PCI-7248 (adl_pci-7248), + * PCI-7296 (adl_pci-7296), + * [Measurement Computing] PCI-DIO24 (cb_pci-dio24), + * PCI-DIO24H (cb_pci-dio24h), PCI-DIO48H (cb_pci-dio48h), + * PCI-DIO96H (cb_pci-dio96h), + * [National Instruments] PCI-DIO-96 (ni_pci-dio-96), + * PCI-DIO-96B (ni_pci-dio-96b), PXI-6508 (ni_pxi-6508), + * PCI-6503 (ni_pci-6503), PCI-6503B (ni_pci-6503b), + * PCI-6503X (ni_pci-6503x), PXI-6503 (ni_pxi-6503) + * Author: H Hartley Sweeten <hsweeten@visionengravers.com> + * Updated: Wed, 12 Sep 2012 11:52:01 -0700 + * Status: untested + * + * These boards have one or more 8255 digital I/O chips, each of which + * is supported as a separate 24-channel DIO subdevice. + * + * Boards with 24 DIO channels (1 DIO subdevice): + * + * PCI-7224, PCI-DIO24, PCI-DIO24H, PCI-6503, PCI-6503B, PCI-6503X, + * PXI-6503 + * + * Boards with 48 DIO channels (2 DIO subdevices): + * + * PCI-7248, PCI-DIO48H + * + * Boards with 96 DIO channels (4 DIO subdevices): + * + * PCI-7296, PCI-DIO96H, PCI-DIO-96, PCI-DIO-96B, PXI-6508 + * + * Some of these boards also have an 8254 programmable timer/counter + * chip. This chip is not currently supported by this driver. + * + * Interrupt support for these boards is also not currently supported. + * + * Configuration Options: not applicable, uses PCI auto config. + */ #include <linux/module.h> #include <linux/pci.h> diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index 84fdf20ca98..7d1fbd53a8a 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -3,6 +3,7 @@ ccflags-$(CONFIG_COMEDI_DEBUG) := -DDEBUG # Comedi "helper" modules +obj-$(CONFIG_COMEDI_ISADMA) += comedi_isadma.o # Comedi misc drivers obj-$(CONFIG_COMEDI_BOND) += comedi_bond.o diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c deleted file mode 100644 index bfa9228c833..00000000000 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ /dev/null @@ -1,2365 +0,0 @@ -/* - * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - * - * ADDI-DATA GmbH - * Dieselstrasse 3 - * D-77833 Ottersweier - * Tel: +19(0)7223/9493-0 - * Fax: +49(0)7223/9493-92 - * http://www.addi-data.com - * info@addi-data.com - * - * 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 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - */ - -/* Card Specific information */ -#define APCI1500_ADDRESS_RANGE 4 - -/* DIGITAL INPUT-OUTPUT DEFINE */ - -#define APCI1500_DIGITAL_OP 2 -#define APCI1500_DIGITAL_IP 0 -#define APCI1500_AND 2 -#define APCI1500_OR 4 -#define APCI1500_OR_PRIORITY 6 -#define APCI1500_CLK_SELECT 0 -#define COUNTER1 0 -#define COUNTER2 1 -#define COUNTER3 2 -#define APCI1500_COUNTER 0x20 -#define APCI1500_TIMER 0 -#define APCI1500_WATCHDOG 0 -#define APCI1500_SINGLE 0 -#define APCI1500_CONTINUOUS 0x80 -#define APCI1500_DISABLE 0 -#define APCI1500_ENABLE 1 -#define APCI1500_SOFTWARE_TRIGGER 0x4 -#define APCI1500_HARDWARE_TRIGGER 0x10 -#define APCI1500_SOFTWARE_GATE 0 -#define APCI1500_HARDWARE_GATE 0x8 -#define START 0 -#define STOP 1 -#define TRIGGER 2 - -/* - * Zillog I/O enumeration - */ -enum { - APCI1500_Z8536_PORT_C, - APCI1500_Z8536_PORT_B, - APCI1500_Z8536_PORT_A, - APCI1500_Z8536_CONTROL_REGISTER -}; - -/* - * Z8536 CIO Internal Address - */ -enum { - APCI1500_RW_MASTER_INTERRUPT_CONTROL, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - APCI1500_RW_PORT_A_INTERRUPT_CONTROL, - APCI1500_RW_PORT_B_INTERRUPT_CONTROL, - APCI1500_RW_TIMER_COUNTER_INTERRUPT_VECTOR, - APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, - APCI1500_RW_PORT_C_DATA_DIRECTION, - APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, - - APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - APCI1500_RW_CPT_TMR1_CMD_STATUS, - APCI1500_RW_CPT_TMR2_CMD_STATUS, - APCI1500_RW_CPT_TMR3_CMD_STATUS, - APCI1500_RW_PORT_A_DATA, - APCI1500_RW_PORT_B_DATA, - APCI1500_RW_PORT_C_DATA, - - APCI1500_R_CPT_TMR1_VALUE_HIGH, - APCI1500_R_CPT_TMR1_VALUE_LOW, - APCI1500_R_CPT_TMR2_VALUE_HIGH, - APCI1500_R_CPT_TMR2_VALUE_LOW, - APCI1500_R_CPT_TMR3_VALUE_HIGH, - APCI1500_R_CPT_TMR3_VALUE_LOW, - APCI1500_RW_CPT_TMR1_TIME_CST_HIGH, - APCI1500_RW_CPT_TMR1_TIME_CST_LOW, - APCI1500_RW_CPT_TMR2_TIME_CST_HIGH, - APCI1500_RW_CPT_TMR2_TIME_CST_LOW, - APCI1500_RW_CPT_TMR3_TIME_CST_HIGH, - APCI1500_RW_CPT_TMR3_TIME_CST_LOW, - APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION, - APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION, - APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION, - APCI1500_R_CURRENT_VECTOR, - - APCI1500_RW_PORT_A_SPECIFICATION, - APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, - APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, - APCI1500_RW_PORT_A_DATA_DIRECTION, - APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL, - APCI1500_RW_PORT_A_PATTERN_POLARITY, - APCI1500_RW_PORT_A_PATTERN_TRANSITION, - APCI1500_RW_PORT_A_PATTERN_MASK, - - APCI1500_RW_PORT_B_SPECIFICATION, - APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, - APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, - APCI1500_RW_PORT_B_DATA_DIRECTION, - APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL, - APCI1500_RW_PORT_B_PATTERN_POLARITY, - APCI1500_RW_PORT_B_PATTERN_TRANSITION, - APCI1500_RW_PORT_B_PATTERN_MASK -}; - -static int i_TimerCounter1Init; -static int i_TimerCounter2Init; -static int i_WatchdogCounter3Init; -static int i_Event1Status, i_Event2Status; -static int i_TimerCounterWatchdogInterrupt; -static int i_Logic, i_CounterLogic; -static int i_InterruptMask; -static int i_InputChannel; -static int i_TimerCounter1Enabled, i_TimerCounter2Enabled, - i_WatchdogCounter3Enabled; - -/* - * An event can be generated for each port. The first event is related to the - * first 8 channels (port 1) and the second to the following 6 channels (port 2) - * An interrupt is generated when one or both events have occurred. - * - * data[0] Number of the input port on which the event will take place (1 or 2) - * data[1] The event logic for port 1 has three possibilities: - * APCI1500_AND This logic links the inputs with an AND logic. - * APCI1500_OR This logic links the inputs with a OR logic. - * APCI1500_OR_PRIORITY This logic links the inputs with a priority OR - * logic. Input 1 has the highest priority level - * and input 8 the smallest. - * For the second port the user has 1 possibility: - * APCI1500_OR This logic links the inputs with a polarity OR logic - * data[2] These 8-character word for port1 and 6-character word for port 2 - * give the mask of the event. Each place gives the state of the input - * channels and can have one of these six characters - * 0 This input must be on 0 - * 1 This input must be on 1 - * 2 This input reacts to a falling edge - * 3 This input reacts to a rising edge - * 4 This input reacts to both edges - * 5 This input is not used for event - */ -static int apci1500_di_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0; - int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0; - int i_PatternTransitionCount = 0, i_RegValue; - int i; - - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Disables the main interrupt on the board */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - if (data[0] == 1) { - i_MaxChannel = 8; - } else { - if (data[0] == 2) { - i_MaxChannel = 6; - } else { - dev_warn(dev->class_dev, - "The specified port event does not exist\n"); - return -EINVAL; - } - } - switch (data[1]) { - case 0: - data[1] = APCI1500_AND; - break; - case 1: - data[1] = APCI1500_OR; - break; - case 2: - data[1] = APCI1500_OR_PRIORITY; - break; - default: - dev_warn(dev->class_dev, - "The specified interrupt logic does not exist\n"); - return -EINVAL; - } - - i_Logic = data[1]; - for (i_Count = i_MaxChannel, i = 0; i_Count > 0; i_Count--, i++) { - i_EventMask = data[2 + i]; - switch (i_EventMask) { - case 0: - i_PatternMask = - i_PatternMask | (1 << (i_MaxChannel - i_Count)); - break; - case 1: - i_PatternMask = - i_PatternMask | (1 << (i_MaxChannel - i_Count)); - i_PatternPolarity = - i_PatternPolarity | (1 << (i_MaxChannel - - i_Count)); - break; - case 2: - i_PatternMask = - i_PatternMask | (1 << (i_MaxChannel - i_Count)); - i_PatternTransition = - i_PatternTransition | (1 << (i_MaxChannel - - i_Count)); - break; - case 3: - i_PatternMask = - i_PatternMask | (1 << (i_MaxChannel - i_Count)); - i_PatternPolarity = - i_PatternPolarity | (1 << (i_MaxChannel - - i_Count)); - i_PatternTransition = - i_PatternTransition | (1 << (i_MaxChannel - - i_Count)); - break; - case 4: - i_PatternTransition = - i_PatternTransition | (1 << (i_MaxChannel - - i_Count)); - break; - case 5: - break; - default: - dev_warn(dev->class_dev, - "The option indicated in the event mask does not exist\n"); - return -EINVAL; - } - } - - if (data[0] == 1) { - /* Test the interrupt logic */ - - if (data[1] == APCI1500_AND || - data[1] == APCI1500_OR || - data[1] == APCI1500_OR_PRIORITY) { - /* Tests if a transition was declared */ - /* for a OR PRIORITY logic */ - - if (data[1] == APCI1500_OR_PRIORITY - && i_PatternTransition != 0) { - dev_warn(dev->class_dev, - "Transition error on an OR PRIORITY logic\n"); - return -EINVAL; - } - - /* Tests if more than one transition */ - /* was declared for an AND logic */ - - if (data[1] == APCI1500_AND) { - for (i_Count = 0; i_Count < 8; i_Count++) { - i_PatternTransitionCount = - i_PatternTransitionCount + - ((i_PatternTransition >> - i_Count) & 0x1); - - } - - if (i_PatternTransitionCount > 1) { - dev_warn(dev->class_dev, - "Transition error on an AND logic\n"); - return -EINVAL; - } - } - - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Disable Port A */ - outb(0xF0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the polarity register of port 1 */ - outb(APCI1500_RW_PORT_A_PATTERN_POLARITY, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternPolarity, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the pattern mask register of */ - /* port 1 */ - outb(APCI1500_RW_PORT_A_PATTERN_MASK, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternMask, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern transition register */ - /* of port 1 */ - outb(APCI1500_RW_PORT_A_PATTERN_TRANSITION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternTransition, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the mode specification mask */ - /* register of port 1 */ - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the mode specification mask */ - /* register of port 1 */ - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Port A new mode */ - - i_RegValue = (i_RegValue & 0xF9) | data[1] | 0x9; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - i_Event1Status = 1; - - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Enable Port A */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - } else { - dev_warn(dev->class_dev, - "The choice for interrupt logic does not exist\n"); - return -EINVAL; - } - } - - /* Test if event setting for port 2 */ - - if (data[0] == 2) { - /* Test the event logic */ - - if (data[1] == APCI1500_OR) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Disable Port B */ - outb(0x74, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the mode specification mask */ - /* register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the mode specification mask */ - /* register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = i_RegValue & 0xF9; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects error channels 1 and 2 */ - - i_PatternMask = (i_PatternMask | 0xC0); - i_PatternPolarity = (i_PatternPolarity | 0xC0); - i_PatternTransition = (i_PatternTransition | 0xC0); - - /* Selects the polarity register of port 2 */ - outb(APCI1500_RW_PORT_B_PATTERN_POLARITY, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternPolarity, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern transition register */ - /* of port 2 */ - outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternTransition, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern Mask register */ - /* of port 2 */ - - outb(APCI1500_RW_PORT_B_PATTERN_MASK, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternMask, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the mode specification mask */ - /* register of port 2 */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the mode specification mask */ - /* register of port 2 */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = (i_RegValue & 0xF9) | 4; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - i_Event2Status = 1; - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Enable Port B */ - - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "The choice for interrupt logic does not exist\n"); - return -EINVAL; - } - } - - return insn->n; -} - -/* - * Allows or disallows a port event - * - * data[0] 0 = Start input event, 1 = Stop input event - * data[1] Number of port (1 or 2) - */ -static int apci1500_di_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - int i_Event1InterruptStatus = 0, i_Event2InterruptStatus = - 0, i_RegValue; - - switch (data[0]) { - case START: - /* Tests the port number */ - - if (data[1] == 1 || data[1] == 2) { - /* Test if port 1 selected */ - - if (data[1] == 1) { - /* Test if event initialised */ - if (i_Event1Status == 1) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Disable Port A */ - outb(0xF0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of */ - /* port 1 */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Allows the pattern interrupt */ - outb(0xC0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Enable Port A */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_Event1InterruptStatus = 1; - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Authorizes the main interrupt on the board */ - outb(0xD0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - } else { - dev_warn(dev->class_dev, - "Event 1 not initialised\n"); - return -EINVAL; - } - } - if (data[1] == 2) { - - if (i_Event2Status == 1) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Disable Port B */ - outb(0x74, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of */ - /* port 2 */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Allows the pattern interrupt */ - outb(0xC0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Enable Port B */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Authorizes the main interrupt on the board */ - outb(0xD0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_Event2InterruptStatus = 1; - } else { - dev_warn(dev->class_dev, - "Event 2 not initialised\n"); - return -EINVAL; - } - } - } else { - dev_warn(dev->class_dev, - "The port parameter is in error\n"); - return -EINVAL; - } - - break; - - case STOP: - /* Tests the port number */ - - if (data[1] == 1 || data[1] == 2) { - /* Test if port 1 selected */ - - if (data[1] == 1) { - /* Test if event initialised */ - if (i_Event1Status == 1) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Disable Port A */ - outb(0xF0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of */ - /* port 1 */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Inhibits the pattern interrupt */ - outb(0xE0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Enable Port A */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_Event1InterruptStatus = 0; - } else { - dev_warn(dev->class_dev, - "Event 1 not initialised\n"); - return -EINVAL; - } - } - if (data[1] == 2) { - /* Test if event initialised */ - if (i_Event2Status == 1) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Disable Port B */ - outb(0x74, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of */ - /* port 2 */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Inhibits the pattern interrupt */ - outb(0xE0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Enable Port B */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_Event2InterruptStatus = 0; - } else { - - dev_warn(dev->class_dev, - "Event 2 not initialised\n"); - return -EINVAL; - } - } - - } else { - dev_warn(dev->class_dev, - "The port parameter is in error\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The option of START/STOP logic does not exist\n"); - return -EINVAL; - } - - return insn->n; -} - -/* - * Return the status of the digital input - */ -static int apci1500_di_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - int i_DummyRead = 0; - - /* Software reset */ - i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the master configuration control register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the mode specification register of port A */ - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the data path polarity register of port A */ - outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* High level of port A means 1 */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the data direction register of port A */ - outb(APCI1500_RW_PORT_A_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* All bits used as inputs */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of port A: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the handshake specification register of port A */ - outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the register */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the mode specification register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data path polarity register of port B */ - outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* A high level of port B means 1 */ - outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data direction register of port B */ - outb(APCI1500_RW_PORT_B_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* All bits used as inputs */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of port B: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the handshake specification register of port B */ - outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the register */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the data path polarity register of port C */ - outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* High level of port C means 1 */ - outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data direction register of port C */ - outb(APCI1500_RW_PORT_C_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* All bits used as inputs except channel 1 */ - outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the special IO register of port C */ - outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes it */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of timer 1 */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates Timer 2 interrupt management: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of Timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates interrupt management of timer 3: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes all interrupts */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - return insn->n; -} - -static int apci1500_di_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - - data[1] = inw(devpriv->i_IobaseAddon + APCI1500_DIGITAL_IP); - - return insn->n; -} - -/* - * Configures the digital output memory and the digital output error interrupt - * - * data[1] 1 = Enable the voltage error interrupt - * 2 = Disable the voltage error interrupt - */ -static int apci1500_do_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - - devpriv->b_OutputMemoryStatus = data[0]; - return insn->n; -} - -/* - * Writes port value to the selected port - */ -static int apci1500_do_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - static unsigned int ui_Temp; - unsigned int ui_Temp1; - unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */ - - if (!devpriv->b_OutputMemoryStatus) - ui_Temp = 0; - - if (data[3] == 0) { - if (data[1] == 0) { - data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; - outw(data[0], - devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP); - } else { - if (data[1] == 1) { - switch (ui_NoOfChannel) { - - case 2: - data[0] = - (data[0] << (2 * - data[2])) | ui_Temp; - break; - - case 4: - data[0] = - (data[0] << (4 * - data[2])) | ui_Temp; - break; - - case 8: - data[0] = - (data[0] << (8 * - data[2])) | ui_Temp; - break; - - case 15: - data[0] = data[0] | ui_Temp; - break; - - default: - dev_err(dev->class_dev, - "chan spec wrong\n"); - return -EINVAL; /* "sorry channel spec wrong " */ - - } - - outw(data[0], - devpriv->i_IobaseAddon + - APCI1500_DIGITAL_OP); - } else { - dev_warn(dev->class_dev, - "Specified channel not supported\n"); - return -EINVAL; - } - } - } else { - if (data[3] == 1) { - if (data[1] == 0) { - data[0] = ~data[0] & 0x1; - ui_Temp1 = 1; - ui_Temp1 = ui_Temp1 << ui_NoOfChannel; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = - (data[0] << ui_NoOfChannel) ^ - 0xffffffff; - data[0] = data[0] & ui_Temp; - outw(data[0], - devpriv->i_IobaseAddon + - APCI1500_DIGITAL_OP); - } else { - if (data[1] == 1) { - switch (ui_NoOfChannel) { - - case 2: - data[0] = ~data[0] & 0x3; - ui_Temp1 = 3; - ui_Temp1 = - ui_Temp1 << 2 * data[2]; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = - ((data[0] << (2 * - data - [2])) ^ - 0xffffffff) & ui_Temp; - break; - - case 4: - data[0] = ~data[0] & 0xf; - ui_Temp1 = 15; - ui_Temp1 = - ui_Temp1 << 4 * data[2]; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = - ((data[0] << (4 * - data - [2])) ^ - 0xffffffff) & ui_Temp; - break; - - case 8: - data[0] = ~data[0] & 0xff; - ui_Temp1 = 255; - ui_Temp1 = - ui_Temp1 << 8 * data[2]; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = - ((data[0] << (8 * - data - [2])) ^ - 0xffffffff) & ui_Temp; - break; - - case 15: - break; - - default: - dev_err(dev->class_dev, - "chan spec wrong\n"); - return -EINVAL; /* "sorry channel spec wrong " */ - - } - - outw(data[0], - devpriv->i_IobaseAddon + - APCI1500_DIGITAL_OP); - } else { - dev_warn(dev->class_dev, - "Specified channel not supported\n"); - return -EINVAL; - } - } - } else { - dev_warn(dev->class_dev, - "Specified functionality does not exist\n"); - return -EINVAL; - } - } - ui_Temp = data[0]; - return insn->n; -} - -/* - * Configures The Watchdog - * - * data[0] 0 = APCI1500_115_KHZ, 1 = APCI1500_3_6_KHZ, 2 = APCI1500_1_8_KHZ - * data[1] 0 = Counter1/Timer1, 1 = Counter2/Timer2, 2 = Counter3/Watchdog - * data[2] 0 = Counter, 1 = Timer/Watchdog - * data[3] This parameter has two meanings. If the counter/timer is used as - * a counter the limit value of the counter is given. If the counter/timer - * is used as a timer, the divider factor for the output is given. - * data[4] 0 = APCI1500_CONTINUOUS, 1 = APCI1500_SINGLE - * data[5] 0 = Software Trigger, 1 = Hardware Trigger - * data[6] 0 = Software gate, 1 = Hardware gate - * data[7] 0 = Interrupt Disable, 1 = Interrupt Enable - */ -static int apci1500_timer_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - int i_TimerCounterMode, i_MasterConfiguration; - - devpriv->tsk_Current = current; - - /* Selection of the input clock */ - if (data[0] == 0 || data[0] == 1 || data[0] == 2) { - outw(data[0], devpriv->i_IobaseAddon + APCI1500_CLK_SELECT); - } else { - if (data[0] != 3) { - dev_warn(dev->class_dev, - "The option for input clock selection does not exist\n"); - return -EINVAL; - } - } - /* Select the counter/timer */ - switch (data[1]) { - case COUNTER1: - /* selecting counter or timer */ - switch (data[2]) { - case 0: - data[2] = APCI1500_COUNTER; - break; - case 1: - data[2] = APCI1500_TIMER; - break; - default: - dev_warn(dev->class_dev, - "This choice is not a timer nor a counter\n"); - return -EINVAL; - } - - /* Selecting single or continuous mode */ - switch (data[4]) { - case 0: - data[4] = APCI1500_CONTINUOUS; - break; - case 1: - data[4] = APCI1500_SINGLE; - break; - default: - dev_warn(dev->class_dev, - "This option for single/continuous mode does not exist\n"); - return -EINVAL; - } - - i_TimerCounterMode = data[2] | data[4] | 7; - /* Test the reload value */ - - if ((data[3] >= 0) && (data[3] <= 65535)) { - if (data[7] == APCI1500_ENABLE - || data[7] == APCI1500_DISABLE) { - - /* Selects the mode register of timer/counter 1 */ - outb(APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Writes the new mode */ - outb(i_TimerCounterMode, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of timer/counter 1 */ - - outb(APCI1500_RW_CPT_TMR1_TIME_CST_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the low value */ - - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of timer/counter 1 */ - - outb(APCI1500_RW_CPT_TMR1_TIME_CST_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the high value */ - - data[3] = data[3] >> 8; - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the master configuration register */ - - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Reads the register */ - - i_MasterConfiguration = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Enables timer/counter 1 and triggers timer/counter 1 */ - - i_MasterConfiguration = - i_MasterConfiguration | 0x40; - - /* Selects the master configuration register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the new configuration */ - outb(i_MasterConfiguration, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the commands register of */ - /* timer/counter 1 */ - - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Disable timer/counter 1 */ - - outb(0x0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the commands register of */ - /* timer/counter 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Trigger timer/counter 1 */ - outb(0x2, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Error in selection of interrupt enable or disable\n"); - return -EINVAL; - } - } else { - dev_warn(dev->class_dev, - "Error in selection of reload value\n"); - return -EINVAL; - } - i_TimerCounterWatchdogInterrupt = data[7]; - i_TimerCounter1Init = 1; - break; - - case COUNTER2: /* selecting counter or timer */ - switch (data[2]) { - case 0: - data[2] = APCI1500_COUNTER; - break; - case 1: - data[2] = APCI1500_TIMER; - break; - default: - dev_warn(dev->class_dev, - "This choice is not a timer nor a counter\n"); - return -EINVAL; - } - - /* Selecting single or continuous mode */ - switch (data[4]) { - case 0: - data[4] = APCI1500_CONTINUOUS; - break; - case 1: - data[4] = APCI1500_SINGLE; - break; - default: - dev_warn(dev->class_dev, - "This option for single/continuous mode does not exist\n"); - return -EINVAL; - } - - /* Selecting software or hardware trigger */ - switch (data[5]) { - case 0: - data[5] = APCI1500_SOFTWARE_TRIGGER; - break; - case 1: - data[5] = APCI1500_HARDWARE_TRIGGER; - break; - default: - dev_warn(dev->class_dev, - "This choice for software or hardware trigger does not exist\n"); - return -EINVAL; - } - - /* Selecting software or hardware gate */ - switch (data[6]) { - case 0: - data[6] = APCI1500_SOFTWARE_GATE; - break; - case 1: - data[6] = APCI1500_HARDWARE_GATE; - break; - default: - dev_warn(dev->class_dev, - "This choice for software or hardware gate does not exist\n"); - return -EINVAL; - } - - i_TimerCounterMode = data[2] | data[4] | data[5] | data[6] | 7; - - /* Test the reload value */ - - if ((data[3] >= 0) && (data[3] <= 65535)) { - if (data[7] == APCI1500_ENABLE - || data[7] == APCI1500_DISABLE) { - - /* Selects the mode register of timer/counter 2 */ - outb(APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Writes the new mode */ - outb(i_TimerCounterMode, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of timer/counter 2 */ - - outb(APCI1500_RW_CPT_TMR2_TIME_CST_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the low value */ - - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of timer/counter 2 */ - - outb(APCI1500_RW_CPT_TMR2_TIME_CST_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the high value */ - - data[3] = data[3] >> 8; - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the master configuration register */ - - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Reads the register */ - - i_MasterConfiguration = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Enables timer/counter 2 and triggers timer/counter 2 */ - - i_MasterConfiguration = - i_MasterConfiguration | 0x20; - - /* Selects the master configuration register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the new configuration */ - outb(i_MasterConfiguration, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the commands register of */ - /* timer/counter 2 */ - - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Disable timer/counter 2 */ - - outb(0x0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the commands register of */ - /* timer/counter 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Trigger timer/counter 1 */ - outb(0x2, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Error in selection of interrupt enable or disable\n"); - return -EINVAL; - } - } else { - dev_warn(dev->class_dev, - "Error in selection of reload value\n"); - return -EINVAL; - } - i_TimerCounterWatchdogInterrupt = data[7]; - i_TimerCounter2Init = 1; - break; - - case COUNTER3: /* selecting counter or watchdog */ - switch (data[2]) { - case 0: - data[2] = APCI1500_COUNTER; - break; - case 1: - data[2] = APCI1500_WATCHDOG; - break; - default: - dev_warn(dev->class_dev, - "This choice is not a watchdog nor a counter\n"); - return -EINVAL; - } - - /* Selecting single or continuous mode */ - switch (data[4]) { - case 0: - data[4] = APCI1500_CONTINUOUS; - break; - case 1: - data[4] = APCI1500_SINGLE; - break; - default: - dev_warn(dev->class_dev, - "This option for single/continuous mode does not exist\n"); - return -EINVAL; - } - - /* Selecting software or hardware gate */ - switch (data[6]) { - case 0: - data[6] = APCI1500_SOFTWARE_GATE; - break; - case 1: - data[6] = APCI1500_HARDWARE_GATE; - break; - default: - dev_warn(dev->class_dev, - "This choice for software or hardware gate does not exist\n"); - return -EINVAL; - } - - /* Test if used for watchdog */ - - if (data[2] == APCI1500_WATCHDOG) { - /* - Enables the output line */ - /* - Enables retrigger */ - /* - Pulses output */ - i_TimerCounterMode = data[2] | data[4] | 0x54; - } else { - i_TimerCounterMode = data[2] | data[4] | data[6] | 7; - } - /* Test the reload value */ - - if ((data[3] >= 0) && (data[3] <= 65535)) { - if (data[7] == APCI1500_ENABLE - || data[7] == APCI1500_DISABLE) { - - /* Selects the mode register of watchdog/counter 3 */ - outb(APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Writes the new mode */ - outb(i_TimerCounterMode, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of watchdog/counter 3 */ - - outb(APCI1500_RW_CPT_TMR3_TIME_CST_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the low value */ - - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of watchdog/counter 3 */ - - outb(APCI1500_RW_CPT_TMR3_TIME_CST_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the high value */ - - data[3] = data[3] >> 8; - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the master configuration register */ - - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Reads the register */ - - i_MasterConfiguration = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Enables watchdog/counter 3 and triggers watchdog/counter 3 */ - - i_MasterConfiguration = - i_MasterConfiguration | 0x10; - - /* Selects the master configuration register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the new configuration */ - outb(i_MasterConfiguration, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Test if COUNTER */ - if (data[2] == APCI1500_COUNTER) { - - /* Selects the command register of */ - /* watchdog/counter 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Disable the watchdog/counter 3 and starts it */ - outb(0x0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the command register of */ - /* watchdog/counter 3 */ - - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Trigger the watchdog/counter 3 and starts it */ - outb(0x2, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - } - - } else { - - dev_warn(dev->class_dev, - "Error in selection of interrupt enable or disable\n"); - return -EINVAL; - } - } else { - dev_warn(dev->class_dev, - "Error in selection of reload value\n"); - return -EINVAL; - } - i_TimerCounterWatchdogInterrupt = data[7]; - i_WatchdogCounter3Init = 1; - break; - - default: - dev_warn(dev->class_dev, - "The specified counter/timer option does not exist\n"); - return -EINVAL; - } - i_CounterLogic = data[2]; - return insn->n; -} - -/* - * Start / Stop or trigger the timer counter or Watchdog - * - * data[0] 0 = Counter1/Timer1, 1 = Counter2/Timer2, 2 = Counter3/Watchdog - * data[1] 0 = Start, 1 = Stop, 2 = Trigger - * data[2] 0 = Counter, 1 = Timer/Watchdog - */ -static int apci1500_timer_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - int i_CommandAndStatusValue; - - switch (data[0]) { - case COUNTER1: - switch (data[1]) { - case START: - if (i_TimerCounter1Init == 1) { - if (i_TimerCounterWatchdogInterrupt == 1) - i_CommandAndStatusValue = 0xC4; /* Enable the interrupt */ - else - i_CommandAndStatusValue = 0xE4; /* disable the interrupt */ - - /* Starts timer/counter 1 */ - i_TimerCounter1Enabled = 1; - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Counter/Timer1 not configured\n"); - return -EINVAL; - } - break; - - case STOP: - - /* Stop timer/counter 1 */ - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(0x00, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_TimerCounter1Enabled = 0; - break; - - case TRIGGER: - if (i_TimerCounter1Init == 1) { - if (i_TimerCounter1Enabled == 1) { - /* Set Trigger and gate */ - - i_CommandAndStatusValue = 0x6; - } else { - /* Set Trigger */ - - i_CommandAndStatusValue = 0x2; - } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Counter/Timer1 not configured\n"); - return -EINVAL; - } - break; - - default: - dev_warn(dev->class_dev, - "The specified option for start/stop/trigger does not exist\n"); - return -EINVAL; - } - break; - - case COUNTER2: - switch (data[1]) { - case START: - if (i_TimerCounter2Init == 1) { - if (i_TimerCounterWatchdogInterrupt == 1) - i_CommandAndStatusValue = 0xC4; /* Enable the interrupt */ - else - i_CommandAndStatusValue = 0xE4; /* disable the interrupt */ - - /* Starts timer/counter 2 */ - i_TimerCounter2Enabled = 1; - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Counter/Timer2 not configured\n"); - return -EINVAL; - } - break; - - case STOP: - - /* Stop timer/counter 2 */ - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(0x00, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_TimerCounter2Enabled = 0; - break; - case TRIGGER: - if (i_TimerCounter2Init == 1) { - if (i_TimerCounter2Enabled == 1) { - /* Set Trigger and gate */ - - i_CommandAndStatusValue = 0x6; - } else { - /* Set Trigger */ - - i_CommandAndStatusValue = 0x2; - } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Counter/Timer2 not configured\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The specified option for start/stop/trigger does not exist\n"); - return -EINVAL; - } - break; - case COUNTER3: - switch (data[1]) { - case START: - if (i_WatchdogCounter3Init == 1) { - - if (i_TimerCounterWatchdogInterrupt == 1) - i_CommandAndStatusValue = 0xC4; /* Enable the interrupt */ - else - i_CommandAndStatusValue = 0xE4; /* disable the interrupt */ - - /* Starts Watchdog/counter 3 */ - i_WatchdogCounter3Enabled = 1; - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - } else { - dev_warn(dev->class_dev, - "Watchdog/Counter3 not configured\n"); - return -EINVAL; - } - break; - - case STOP: - - /* Stop Watchdog/counter 3 */ - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(0x00, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_WatchdogCounter3Enabled = 0; - break; - - case TRIGGER: - switch (data[2]) { - case 0: /* triggering counter 3 */ - if (i_WatchdogCounter3Init == 1) { - if (i_WatchdogCounter3Enabled == 1) { - /* Set Trigger and gate */ - - i_CommandAndStatusValue = 0x6; - } else { - /* Set Trigger */ - - i_CommandAndStatusValue = 0x2; - } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Counter3 not configured\n"); - return -EINVAL; - } - break; - case 1: - /* triggering Watchdog 3 */ - if (i_WatchdogCounter3Init == 1) { - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(0x6, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Watchdog 3 not configured\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "Wrong choice of watchdog/counter3\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The specified option for start/stop/trigger does not exist\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The specified choice for counter/watchdog/timer does not exist\n"); - return -EINVAL; - } - return insn->n; -} - -/* - * Read The Watchdog - * - * data[0] 0 = Counter1/Timer1, 1 = Counter2/Timer2, 2 = Counter3/Watchdog - */ -static int apci1500_timer_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - int i_CommandAndStatusValue; - - switch (data[0]) { - case COUNTER1: - /* Read counter/timer1 */ - if (i_TimerCounter1Init == 1) { - if (i_TimerCounter1Enabled == 1) { - /* Set RCC and gate */ - - i_CommandAndStatusValue = 0xC; - } else { - /* Set RCC */ - - i_CommandAndStatusValue = 0x8; - } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the counter register (high) */ - outb(APCI1500_R_CPT_TMR1_VALUE_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = data[0] << 8; - data[0] = data[0] & 0xff00; - outb(APCI1500_R_CPT_TMR1_VALUE_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - data[0] | inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Timer/Counter1 not configured\n"); - return -EINVAL; - } - break; - case COUNTER2: - /* Read counter/timer2 */ - if (i_TimerCounter2Init == 1) { - if (i_TimerCounter2Enabled == 1) { - /* Set RCC and gate */ - - i_CommandAndStatusValue = 0xC; - } else { - /* Set RCC */ - - i_CommandAndStatusValue = 0x8; - } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the counter register (high) */ - outb(APCI1500_R_CPT_TMR2_VALUE_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = data[0] << 8; - data[0] = data[0] & 0xff00; - outb(APCI1500_R_CPT_TMR2_VALUE_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - data[0] | inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Timer/Counter2 not configured\n"); - return -EINVAL; - } - break; - case COUNTER3: - /* Read counter/watchdog2 */ - if (i_WatchdogCounter3Init == 1) { - if (i_WatchdogCounter3Enabled == 1) { - /* Set RCC and gate */ - - i_CommandAndStatusValue = 0xC; - } else { - /* Set RCC */ - - i_CommandAndStatusValue = 0x8; - } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the counter register (high) */ - outb(APCI1500_R_CPT_TMR3_VALUE_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = data[0] << 8; - data[0] = data[0] & 0xff00; - outb(APCI1500_R_CPT_TMR3_VALUE_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - data[0] | inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "WatchdogCounter3 not configured\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The choice of timer/counter/watchdog does not exist\n"); - return -EINVAL; - } - - return insn->n; -} - -/* - * Read the interrupt mask - * - * data[0] The interrupt mask value - * data[1] Channel Number - */ -static int apci1500_timer_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - data[0] = i_InterruptMask; - data[1] = i_InputChannel; - i_InterruptMask = 0; - return insn->n; -} - -/* - * Configures the interrupt registers - */ -static int apci1500_do_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - unsigned int ui_Status; - int i_RegValue; - int i_Constant; - - devpriv->tsk_Current = current; - outl(0x0, devpriv->i_IobaseAmcc + 0x38); - if (data[0] == 1) { - i_Constant = 0xC0; - } else { - if (data[0] == 0) { - i_Constant = 0x00; - } else { - dev_warn(dev->class_dev, - "The parameter passed to driver is in error for enabling the voltage interrupt\n"); - return -EINVAL; - } - } - - /* Selects the mode specification register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Writes the new configuration (APCI1500_OR) */ - i_RegValue = (i_RegValue & 0xF9) | APCI1500_OR; - - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Authorises the interrupt on the board */ - outb(0xC0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern polarity register of port B */ - outb(APCI1500_RW_PORT_B_PATTERN_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern transition register of port B */ - outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern mask register of port B */ - outb(APCI1500_RW_PORT_B_PATTERN_MASK, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of port A */ - - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of port B */ - - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of timer 1 */ - - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of timer 2 */ - - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of timer 3 */ - - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Authorizes the main interrupt on the board */ - outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Enables the PCI interrupt */ - outl(0x3000, devpriv->i_IobaseAmcc + 0x38); - ui_Status = inl(devpriv->i_IobaseAmcc + 0x10); - ui_Status = inl(devpriv->i_IobaseAmcc + 0x38); - outl(0x23000, devpriv->i_IobaseAmcc + 0x38); - - return insn->n; -} - -static irqreturn_t apci1500_interrupt(int irq, void *d) -{ - - struct comedi_device *dev = d; - struct apci1500_private *devpriv = dev->private; - unsigned int ui_InterruptStatus = 0; - int i_RegValue = 0; - - /* Clear the interrupt mask */ - i_InterruptMask = 0; - - /* Read the board interrupt status */ - ui_InterruptStatus = inl(devpriv->i_IobaseAmcc + 0x38); - - /* Test if board generated a interrupt */ - if ((ui_InterruptStatus & 0x800000) == 0x800000) { - /* Disable all Interrupt */ - /* Selects the master interrupt control register */ - /* Disables the main interrupt on the board */ - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of port A */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_InterruptMask = i_InterruptMask | 1; - if (i_Logic == APCI1500_OR_PRIORITY) { - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the interrupt vector register of port A */ - outb(APCI1500_RW_PORT_A_INTERRUPT_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - i_InputChannel = 1 + (i_RegValue >> 1); - - } else { - i_InputChannel = 0; - } - } - - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of port B */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Reads port B */ - i_RegValue = - inb((unsigned int) devpriv->iobase + - APCI1500_Z8536_PORT_B); - - i_RegValue = i_RegValue & 0xC0; - /* Tests if this is an external error */ - - if (i_RegValue) { - /* Disable the interrupt */ - /* Selects the command and status register of port B */ - outl(0x0, devpriv->i_IobaseAmcc + 0x38); - - if (i_RegValue & 0x80) { - i_InterruptMask = - i_InterruptMask | 0x40; - } - - if (i_RegValue & 0x40) { - i_InterruptMask = - i_InterruptMask | 0x80; - } - } else { - i_InterruptMask = i_InterruptMask | 2; - } - } - - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of timer 1 */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_InterruptMask = i_InterruptMask | 4; - } - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of timer 2 */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_InterruptMask = i_InterruptMask | 8; - } - - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of timer 3 */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - if (i_CounterLogic == APCI1500_COUNTER) - i_InterruptMask = i_InterruptMask | 0x10; - else - i_InterruptMask = i_InterruptMask | 0x20; - } - - send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ - /* Enable all Interrupts */ - - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Authorizes the main interrupt on the board */ - outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - } else { - dev_warn(dev->class_dev, - "Interrupt from unknown source\n"); - - } - - return IRQ_HANDLED; -} - -static int apci1500_reset(struct comedi_device *dev) -{ - struct apci1500_private *devpriv = dev->private; - int i_DummyRead = 0; - - i_TimerCounter1Init = 0; - i_TimerCounter2Init = 0; - i_WatchdogCounter3Init = 0; - i_Event1Status = 0; - i_Event2Status = 0; - i_TimerCounterWatchdogInterrupt = 0; - i_Logic = 0; - i_CounterLogic = 0; - i_InterruptMask = 0; - i_InputChannel = 0; - i_TimerCounter1Enabled = 0; - i_TimerCounter2Enabled = 0; - i_WatchdogCounter3Enabled = 0; - - /* Software reset */ - i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the master configuration control register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the mode specification register of port A */ - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the data path polarity register of port A */ - outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* High level of port A means 1 */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the data direction register of port A */ - outb(APCI1500_RW_PORT_A_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* All bits used as inputs */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of port A: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the handshake specification register of port A */ - outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the register */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the mode specification register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data path polarity register of port B */ - outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* A high level of port B means 1 */ - outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data direction register of port B */ - outb(APCI1500_RW_PORT_B_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* All bits used as inputs */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of port B: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the handshake specification register of port B */ - outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the register */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the data path polarity register of port C */ - outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* High level of port C means 1 */ - outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data direction register of port C */ - outb(APCI1500_RW_PORT_C_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* All bits used as inputs except channel 1 */ - outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the special IO register of port C */ - outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes it */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of timer 1 */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates Timer 2 interrupt management: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of Timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates interrupt management of timer 3: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes all interrupts */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* reset all the digital outputs */ - outw(0x0, devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP); - /* Disable the board interrupt */ - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 3*/ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - return 0; -} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c index 339519a3d6b..1f2f78186d5 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c @@ -93,7 +93,6 @@ static int apci3501_write_insn_timer(struct comedi_device *dev, { struct apci3501_private *devpriv = dev->private; unsigned int ul_Command1 = 0; - int i_Temp; if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { @@ -135,7 +134,7 @@ static int apci3501_write_insn_timer(struct comedi_device *dev, } } - i_Temp = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1; + inl(dev->iobase + APCI3501_TIMER_STATUS_REG); return insn->n; } diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index bf14165297b..4911b627203 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -22,6 +22,54 @@ * more details. */ +/* + * Driver: addi_apci_1032 + * Description: ADDI-DATA APCI-1032 Digital Input Board + * Author: ADDI-DATA GmbH <info@addi-data.com>, + * H Hartley Sweeten <hsweeten@visionengravers.com> + * Status: untested + * Devices: [ADDI-DATA] APCI-1032 (addi_apci_1032) + * + * Configuration options: + * None; devices are configured automatically. + * + * This driver models the APCI-1032 as a 32-channel, digital input subdevice + * plus an additional digital input subdevice to handle change-of-state (COS) + * interrupts (if an interrupt handler can be set up successfully). + * + * The COS subdevice supports comedi asynchronous read commands. + * + * Change-Of-State (COS) interrupt configuration: + * + * Channels 0 to 15 are interruptible. These channels can be configured + * to generate interrupts based on AND/OR logic for the desired channels. + * + * OR logic: + * - reacts to rising or falling edges + * - interrupt is generated when any enabled channel meets the desired + * interrupt condition + * + * AND logic: + * - reacts to changes in level of the selected inputs + * - interrupt is generated when all enabled channels meet the desired + * interrupt condition + * - after an interrupt, a change in level must occur on the selected + * inputs to release the IRQ logic + * + * The COS subdevice must be configured before setting up a comedi + * asynchronous command: + * + * data[0] : INSN_CONFIG_DIGITAL_TRIG + * data[1] : trigger number (= 0) + * data[2] : configuration operation: + * - COMEDI_DIGITAL_TRIG_DISABLE = no interrupts + * - COMEDI_DIGITAL_TRIG_ENABLE_EDGES = OR (edge) interrupts + * - COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = AND (level) interrupts + * data[3] : left-shift for data[4] and data[5] + * data[4] : rising-edge/high level channels + * data[5] : falling-edge/low level channels + */ + #include <linux/module.h> #include <linux/pci.h> #include <linux/interrupt.h> @@ -62,36 +110,6 @@ static int apci1032_reset(struct comedi_device *dev) return 0; } -/* - * Change-Of-State (COS) interrupt configuration - * - * Channels 0 to 15 are interruptible. These channels can be configured - * to generate interrupts based on AND/OR logic for the desired channels. - * - * OR logic - * - reacts to rising or falling edges - * - interrupt is generated when any enabled channel - * meet the desired interrupt condition - * - * AND logic - * - reacts to changes in level of the selected inputs - * - interrupt is generated when all enabled channels - * meet the desired interrupt condition - * - after an interrupt, a change in level must occur on - * the selected inputs to release the IRQ logic - * - * The COS interrupt must be configured before it can be enabled. - * - * data[0] : INSN_CONFIG_DIGITAL_TRIG - * data[1] : trigger number (= 0) - * data[2] : configuration operation: - * COMEDI_DIGITAL_TRIG_DISABLE = no interrupts - * COMEDI_DIGITAL_TRIG_ENABLE_EDGES = OR (edge) interrupts - * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = AND (level) interrupts - * data[3] : left-shift for data[4] and data[5] - * data[4] : rising-edge/high level channels - * data[5] : falling-edge/low level channels - */ static int apci1032_cos_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 30b132c3d09..f15aa1f6b47 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -1,22 +1,755 @@ +/* + * addi_apci_1500.c + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data.com + * info@addi-data.com + * + * 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 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + #include <linux/module.h> #include <linux/pci.h> -#include <linux/sched.h> #include <linux/interrupt.h> #include "../comedidev.h" #include "comedi_fc.h" #include "amcc_s5933.h" +#include "z8536.h" + +/* + * PCI Bar 0 Register map (devpriv->amcc) + * see amcc_s5933.h for register and bit defines + */ + +/* + * PCI Bar 1 Register map (dev->iobase) + * see z8536.h for Z8536 internal registers and bit defines + */ +#define APCI1500_Z8536_PORTC_REG 0x00 +#define APCI1500_Z8536_PORTB_REG 0x01 +#define APCI1500_Z8536_PORTA_REG 0x02 +#define APCI1500_Z8536_CTRL_REG 0x03 + +/* + * PCI Bar 2 Register map (devpriv->addon) + */ +#define APCI1500_CLK_SEL_REG 0x00 +#define APCI1500_DI_REG 0x00 +#define APCI1500_DO_REG 0x02 struct apci1500_private { - int iobase; - int i_IobaseAmcc; - int i_IobaseAddon; - int i_IobaseReserved; - unsigned char b_OutputMemoryStatus; - struct task_struct *tsk_Current; + unsigned long amcc; + unsigned long addon; + + unsigned int clk_src; + + /* Digital trigger configuration [0]=AND [1]=OR */ + unsigned int pm[2]; /* Pattern Mask */ + unsigned int pt[2]; /* Pattern Transition */ + unsigned int pp[2]; /* Pattern Polarity */ }; -#include "addi-data/hwdrv_apci1500.c" +static unsigned int z8536_read(struct comedi_device *dev, unsigned int reg) +{ + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&dev->spinlock, flags); + outb(reg, dev->iobase + APCI1500_Z8536_CTRL_REG); + val = inb(dev->iobase + APCI1500_Z8536_CTRL_REG); + spin_unlock_irqrestore(&dev->spinlock, flags); + + return val; +} + +static void z8536_write(struct comedi_device *dev, + unsigned int val, unsigned int reg) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->spinlock, flags); + outb(reg, dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(val, dev->iobase + APCI1500_Z8536_CTRL_REG); + spin_unlock_irqrestore(&dev->spinlock, flags); +} + +static void z8536_reset(struct comedi_device *dev) +{ + unsigned long flags; + + /* + * Even if the state of the Z8536 is not known, the following + * sequence will reset it and put it in State 0. + */ + spin_lock_irqsave(&dev->spinlock, flags); + inb(dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); + inb(dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(1, dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); + spin_unlock_irqrestore(&dev->spinlock, flags); + + /* Disable all Ports and Counter/Timers */ + z8536_write(dev, 0x00, Z8536_CFG_CTRL_REG); + + /* + * Port A is connected to Ditial Input channels 0-7. + * Configure the port to allow interrupt detection. + */ + z8536_write(dev, Z8536_PAB_MODE_PTS_BIT | + Z8536_PAB_MODE_SB | + Z8536_PAB_MODE_PMS_DISABLE, + Z8536_PA_MODE_REG); + z8536_write(dev, 0xff, Z8536_PB_DPP_REG); + z8536_write(dev, 0xff, Z8536_PA_DD_REG); + + /* + * Port B is connected to Ditial Input channels 8-13. + * Configure the port to allow interrupt detection. + * + * NOTE: Bits 7 and 6 of Port B are connected to internal + * diagnostic signals and bit 7 is inverted. + */ + z8536_write(dev, Z8536_PAB_MODE_PTS_BIT | + Z8536_PAB_MODE_SB | + Z8536_PAB_MODE_PMS_DISABLE, + Z8536_PB_MODE_REG); + z8536_write(dev, 0x7f, Z8536_PB_DPP_REG); + z8536_write(dev, 0xff, Z8536_PB_DD_REG); + + /* + * Not sure what Port C is connected to... + */ + z8536_write(dev, 0x09, Z8536_PC_DPP_REG); + z8536_write(dev, 0x0e, Z8536_PC_DD_REG); + + /* + * Clear and disable all interrupt sources. + * + * Just in case, the reset of the Z8536 should have already + * done this. + */ + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_PA_CMDSTAT_REG); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_PA_CMDSTAT_REG); + + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_PB_CMDSTAT_REG); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_PB_CMDSTAT_REG); + + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_CT_CMDSTAT_REG(0)); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_CT_CMDSTAT_REG(0)); + + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_CT_CMDSTAT_REG(1)); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_CT_CMDSTAT_REG(1)); + + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_CT_CMDSTAT_REG(2)); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_CT_CMDSTAT_REG(2)); + + /* Disable all interrupts */ + z8536_write(dev, 0x00, Z8536_INT_CTRL_REG); +} + +static void apci1500_port_enable(struct comedi_device *dev, bool enable) +{ + unsigned int cfg; + + cfg = z8536_read(dev, Z8536_CFG_CTRL_REG); + if (enable) + cfg |= (Z8536_CFG_CTRL_PAE | Z8536_CFG_CTRL_PBE); + else + cfg &= ~(Z8536_CFG_CTRL_PAE | Z8536_CFG_CTRL_PBE); + z8536_write(dev, cfg, Z8536_CFG_CTRL_REG); +} + +static void apci1500_timer_enable(struct comedi_device *dev, + unsigned int chan, bool enable) +{ + unsigned int bit; + unsigned int cfg; + + if (chan == 0) + bit = Z8536_CFG_CTRL_CT1E; + else if (chan == 1) + bit = Z8536_CFG_CTRL_CT2E; + else + bit = Z8536_CFG_CTRL_PCE_CT3E; + + cfg = z8536_read(dev, Z8536_CFG_CTRL_REG); + if (enable) { + cfg |= bit; + } else { + cfg &= ~bit; + z8536_write(dev, 0x00, Z8536_CT_CMDSTAT_REG(chan)); + } + z8536_write(dev, cfg, Z8536_CFG_CTRL_REG); +} + +static bool apci1500_ack_irq(struct comedi_device *dev, + unsigned int reg) +{ + unsigned int val; + + val = z8536_read(dev, reg); + if ((val & Z8536_STAT_IE_IP) == Z8536_STAT_IE_IP) { + val &= 0x0f; /* preserve any write bits */ + val |= Z8536_CMD_CLR_IP_IUS; + z8536_write(dev, val, reg); + + return true; + } + return false; +} + +static irqreturn_t apci1500_interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + struct apci1500_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; + unsigned int status = 0; + unsigned int val; + + val = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); + if (!(val & INTCSR_INTR_ASSERTED)) + return IRQ_NONE; + + if (apci1500_ack_irq(dev, Z8536_PA_CMDSTAT_REG)) + status |= 0x01; /* port a event (inputs 0-7) */ + + if (apci1500_ack_irq(dev, Z8536_PB_CMDSTAT_REG)) { + /* Tests if this is an external error */ + val = inb(dev->iobase + APCI1500_Z8536_PORTB_REG); + val &= 0xc0; + if (val) { + if (val & 0x80) /* voltage error */ + status |= 0x40; + if (val & 0x40) /* short circuit error */ + status |= 0x80; + } else { + status |= 0x02; /* port b event (inputs 8-13) */ + } + } + + /* + * NOTE: The 'status' returned by the sample matches the + * interrupt mask information from the APCI-1500 Users Manual. + * + * Mask Meaning + * ---------- ------------------------------------------ + * 0x00000001 Event 1 has occured + * 0x00000010 Event 2 has occured + * 0x00000100 Counter/timer 1 has run down (not implemented) + * 0x00001000 Counter/timer 2 has run down (not implemented) + * 0x00010000 Counter 3 has run down (not implemented) + * 0x00100000 Watchdog has run down (not implemented) + * 0x01000000 Voltage error + * 0x10000000 Short-circuit error + */ + comedi_buf_write_samples(s, &status, 1); + comedi_handle_events(dev, s); + + return IRQ_HANDLED; +} + +static int apci1500_di_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + /* Disables the main interrupt on the board */ + z8536_write(dev, 0x00, Z8536_INT_CTRL_REG); + + /* Disable Ports A & B */ + apci1500_port_enable(dev, false); + + /* Ack any pending interrupts */ + apci1500_ack_irq(dev, Z8536_PA_CMDSTAT_REG); + apci1500_ack_irq(dev, Z8536_PB_CMDSTAT_REG); + + /* Disable pattern interrupts */ + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_PA_CMDSTAT_REG); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_PB_CMDSTAT_REG); + + /* Enable Ports A & B */ + apci1500_port_enable(dev, true); + + return 0; +} + +static int apci1500_di_inttrig_start(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) +{ + struct apci1500_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int pa_mode = Z8536_PAB_MODE_PMS_DISABLE; + unsigned int pb_mode = Z8536_PAB_MODE_PMS_DISABLE; + unsigned int pa_trig = trig_num & 0x01; + unsigned int pb_trig = (trig_num >> 1) & 0x01; + bool valid_trig = false; + unsigned int val; + + if (trig_num != cmd->start_arg) + return -EINVAL; + + /* Disable Ports A & B */ + apci1500_port_enable(dev, false); + + /* Set Port A for selected trigger pattern */ + z8536_write(dev, devpriv->pm[pa_trig] & 0xff, Z8536_PA_PM_REG); + z8536_write(dev, devpriv->pt[pa_trig] & 0xff, Z8536_PA_PT_REG); + z8536_write(dev, devpriv->pp[pa_trig] & 0xff, Z8536_PA_PP_REG); + + /* Set Port B for selected trigger pattern */ + z8536_write(dev, (devpriv->pm[pb_trig] >> 8) & 0xff, Z8536_PB_PM_REG); + z8536_write(dev, (devpriv->pt[pb_trig] >> 8) & 0xff, Z8536_PB_PT_REG); + z8536_write(dev, (devpriv->pp[pb_trig] >> 8) & 0xff, Z8536_PB_PP_REG); + + /* Set Port A trigger mode (if enabled) and enable interrupt */ + if (devpriv->pm[pa_trig] & 0xff) { + pa_mode = pa_trig ? Z8536_PAB_MODE_PMS_AND + : Z8536_PAB_MODE_PMS_OR; + + val = z8536_read(dev, Z8536_PA_MODE_REG); + val &= ~Z8536_PAB_MODE_PMS_MASK; + val |= (pa_mode | Z8536_PAB_MODE_IMO); + z8536_write(dev, val, Z8536_PA_MODE_REG); + + z8536_write(dev, Z8536_CMD_SET_IE, Z8536_PA_CMDSTAT_REG); + + valid_trig = true; + + dev_dbg(dev->class_dev, + "Port A configured for %s mode pattern detection\n", + pa_trig ? "AND" : "OR"); + } + + /* Set Port B trigger mode (if enabled) and enable interrupt */ + if (devpriv->pm[pb_trig] & 0xff00) { + pb_mode = pb_trig ? Z8536_PAB_MODE_PMS_AND + : Z8536_PAB_MODE_PMS_OR; + + val = z8536_read(dev, Z8536_PB_MODE_REG); + val &= ~Z8536_PAB_MODE_PMS_MASK; + val |= (pb_mode | Z8536_PAB_MODE_IMO); + z8536_write(dev, val, Z8536_PB_MODE_REG); + + z8536_write(dev, Z8536_CMD_SET_IE, Z8536_PB_CMDSTAT_REG); + + valid_trig = true; + + dev_dbg(dev->class_dev, + "Port B configured for %s mode pattern detection\n", + pb_trig ? "AND" : "OR"); + } + + /* Enable Ports A & B */ + apci1500_port_enable(dev, true); + + if (!valid_trig) { + dev_dbg(dev->class_dev, + "digital trigger %d is not configured\n", trig_num); + return -EINVAL; + } + + /* Authorizes the main interrupt on the board */ + z8536_write(dev, Z8536_INT_CTRL_MIE | Z8536_INT_CTRL_DLC, + Z8536_INT_CTRL_REG); + + return 0; +} + +static int apci1500_di_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + s->async->inttrig = apci1500_di_inttrig_start; + + return 0; +} + +static int apci1500_di_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int err = 0; + + /* Step 1 : check if triggers are trivially valid */ + + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + + if (err) + return 1; + + /* Step 2a : make sure trigger sources are unique */ + /* Step 2b : and mutually compatible */ + + /* Step 3: check if arguments are trivially valid */ + + /* + * Internal start source triggers: + * + * 0 AND mode for Port A (digital inputs 0-7) + * AND mode for Port B (digital inputs 8-13 and internal signals) + * + * 1 OR mode for Port A (digital inputs 0-7) + * AND mode for Port B (digital inputs 8-13 and internal signals) + * + * 2 AND mode for Port A (digital inputs 0-7) + * OR mode for Port B (digital inputs 8-13 and internal signals) + * + * 3 OR mode for Port A (digital inputs 0-7) + * OR mode for Port B (digital inputs 8-13 and internal signals) + */ + err |= cfc_check_trigger_arg_max(&cmd->start_arg, 3); + + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + + if (err) + return 3; + + /* Step 4: fix up any arguments */ + + /* Step 5: check channel list if it exists */ + + return 0; +} + +/* + * The pattern-recognition logic must be configured before the digital + * input async command is started. + * + * Digital input channels 0 to 13 can generate interrupts. Channels 14 + * and 15 are connected to internal board status/diagnostic signals. + * + * Channel 14 - Voltage error (the external supply is < 5V) + * Channel 15 - Short-circuit/overtemperature error + * + * data[0] : INSN_CONFIG_DIGITAL_TRIG + * data[1] : trigger number + * 0 = AND mode + * 1 = OR mode + * data[2] : configuration operation: + * COMEDI_DIGITAL_TRIG_DISABLE = no interrupts + * COMEDI_DIGITAL_TRIG_ENABLE_EDGES = edge interrupts + * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = level interrupts + * data[3] : left-shift for data[4] and data[5] + * data[4] : rising-edge/high level channels + * data[5] : falling-edge/low level channels + */ +static int apci1500_di_cfg_trig(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct apci1500_private *devpriv = dev->private; + unsigned int trig = data[1]; + unsigned int shift = data[3]; + unsigned int hi_mask = data[4] << shift; + unsigned int lo_mask = data[5] << shift; + unsigned int chan_mask = hi_mask | lo_mask; + unsigned int old_mask = (1 << shift) - 1; + unsigned int pm = devpriv->pm[trig] & old_mask; + unsigned int pt = devpriv->pt[trig] & old_mask; + unsigned int pp = devpriv->pp[trig] & old_mask; + + if (trig > 1) { + dev_dbg(dev->class_dev, + "invalid digital trigger number (0=AND, 1=OR)\n"); + return -EINVAL; + } + + if (chan_mask > 0xffff) { + dev_dbg(dev->class_dev, "invalid digital trigger channel\n"); + return -EINVAL; + } + + switch (data[2]) { + case COMEDI_DIGITAL_TRIG_DISABLE: + /* clear trigger configuration */ + pm = 0; + pt = 0; + pp = 0; + break; + case COMEDI_DIGITAL_TRIG_ENABLE_EDGES: + pm |= chan_mask; /* enable channels */ + pt |= chan_mask; /* enable edge detection */ + pp |= hi_mask; /* rising-edge channels */ + pp &= ~lo_mask; /* falling-edge channels */ + break; + case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS: + pm |= chan_mask; /* enable channels */ + pt &= ~chan_mask; /* enable level detection */ + pp |= hi_mask; /* high level channels */ + pp &= ~lo_mask; /* low level channels */ + break; + default: + return -EINVAL; + } + + /* + * The AND mode trigger can only have one channel (max) enabled + * for edge detection. + */ + if (trig == 0) { + int ret = 0; + unsigned int src; + + src = pt & 0xff; + if (src) + ret |= cfc_check_trigger_is_unique(src); + + src = (pt >> 8) & 0xff; + if (src) + ret |= cfc_check_trigger_is_unique(src); + + if (ret) { + dev_dbg(dev->class_dev, + "invalid AND trigger configuration\n"); + return ret; + } + } + + /* save the trigger configuration */ + devpriv->pm[trig] = pm; + devpriv->pt[trig] = pt; + devpriv->pp[trig] = pp; + + return insn->n; +} + +static int apci1500_di_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + switch (data[0]) { + case INSN_CONFIG_DIGITAL_TRIG: + return apci1500_di_cfg_trig(dev, s, insn, data); + default: + return -EINVAL; + } +} + +static int apci1500_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct apci1500_private *devpriv = dev->private; + + data[1] = inw(devpriv->addon + APCI1500_DI_REG); + + return insn->n; +} + +static int apci1500_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct apci1500_private *devpriv = dev->private; + + if (comedi_dio_update_state(s, data)) + outw(s->state, devpriv->addon + APCI1500_DO_REG); + + data[1] = s->state; + + return insn->n; +} + +static int apci1500_timer_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct apci1500_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val; + + switch (data[0]) { + case INSN_CONFIG_ARM: + val = data[1] & s->maxdata; + z8536_write(dev, val & 0xff, Z8536_CT_RELOAD_LSB_REG(chan)); + z8536_write(dev, (val >> 8) & 0xff, + Z8536_CT_RELOAD_MSB_REG(chan)); + + apci1500_timer_enable(dev, chan, true); + z8536_write(dev, Z8536_CT_CMDSTAT_GCB, + Z8536_CT_CMDSTAT_REG(chan)); + break; + case INSN_CONFIG_DISARM: + apci1500_timer_enable(dev, chan, false); + break; + + case INSN_CONFIG_GET_COUNTER_STATUS: + data[1] = 0; + val = z8536_read(dev, Z8536_CT_CMDSTAT_REG(chan)); + if (val & Z8536_CT_STAT_CIP) + data[1] |= COMEDI_COUNTER_COUNTING; + if (val & Z8536_CT_CMDSTAT_GCB) + data[1] |= COMEDI_COUNTER_ARMED; + if (val & Z8536_STAT_IP) { + data[1] |= COMEDI_COUNTER_TERMINAL_COUNT; + apci1500_ack_irq(dev, Z8536_CT_CMDSTAT_REG(chan)); + } + data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING | + COMEDI_COUNTER_TERMINAL_COUNT; + break; + + case INSN_CONFIG_SET_COUNTER_MODE: + /* Simulate the 8254 timer modes */ + switch (data[1]) { + case I8254_MODE0: + /* Interrupt on Terminal Count */ + val = Z8536_CT_MODE_ECE | + Z8536_CT_MODE_DCS_ONESHOT; + break; + case I8254_MODE1: + /* Hardware Retriggerable One-Shot */ + val = Z8536_CT_MODE_ETE | + Z8536_CT_MODE_DCS_ONESHOT; + break; + case I8254_MODE2: + /* Rate Generator */ + val = Z8536_CT_MODE_CSC | + Z8536_CT_MODE_DCS_PULSE; + break; + case I8254_MODE3: + /* Square Wave Mode */ + val = Z8536_CT_MODE_CSC | + Z8536_CT_MODE_DCS_SQRWAVE; + break; + case I8254_MODE4: + /* Software Triggered Strobe */ + val = Z8536_CT_MODE_REB | + Z8536_CT_MODE_DCS_PULSE; + break; + case I8254_MODE5: + /* Hardware Triggered Strobe (watchdog) */ + val = Z8536_CT_MODE_EOE | + Z8536_CT_MODE_ETE | + Z8536_CT_MODE_REB | + Z8536_CT_MODE_DCS_PULSE; + break; + default: + return -EINVAL; + } + apci1500_timer_enable(dev, chan, false); + z8536_write(dev, val, Z8536_CT_MODE_REG(chan)); + break; + + case INSN_CONFIG_SET_CLOCK_SRC: + if (data[1] > 2) + return -EINVAL; + devpriv->clk_src = data[1]; + if (devpriv->clk_src == 2) + devpriv->clk_src = 3; + outw(devpriv->clk_src, devpriv->addon + APCI1500_CLK_SEL_REG); + break; + case INSN_CONFIG_GET_CLOCK_SRC: + switch (devpriv->clk_src) { + case 0: + data[1] = 0; /* 111.86 kHz / 2 */ + data[2] = 17879; /* 17879 ns (approx) */ + break; + case 1: + data[1] = 1; /* 3.49 kHz / 2 */ + data[2] = 573066; /* 573066 ns (approx) */ + break; + case 3: + data[1] = 2; /* 1.747 kHz / 2 */ + data[2] = 1164822; /* 1164822 ns (approx) */ + break; + default: + return -EINVAL; + } + break; + + case INSN_CONFIG_SET_GATE_SRC: + if (chan == 0) + return -EINVAL; + + val = z8536_read(dev, Z8536_CT_MODE_REG(chan)); + val &= Z8536_CT_MODE_EGE; + if (data[1] == 1) + val |= Z8536_CT_MODE_EGE; + else if (data[1] > 1) + return -EINVAL; + z8536_write(dev, val, Z8536_CT_MODE_REG(chan)); + break; + case INSN_CONFIG_GET_GATE_SRC: + if (chan == 0) + return -EINVAL; + break; + + default: + return -EINVAL; + } + return insn->n; +} + +static int apci1500_timer_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int cmd; + + cmd = z8536_read(dev, Z8536_CT_CMDSTAT_REG(chan)); + cmd &= Z8536_CT_CMDSTAT_GCB; /* preserve gate */ + cmd |= Z8536_CT_CMD_TCB; /* set trigger */ + + /* software trigger a timer, it only makes sense to do one write */ + if (insn->n) + z8536_write(dev, cmd, Z8536_CT_CMDSTAT_REG(chan)); + + return insn->n; +} + +static int apci1500_timer_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int cmd; + unsigned int val; + int i; + + cmd = z8536_read(dev, Z8536_CT_CMDSTAT_REG(chan)); + cmd &= Z8536_CT_CMDSTAT_GCB; /* preserve gate */ + cmd |= Z8536_CT_CMD_RCC; /* set RCC */ + + for (i = 0; i < insn->n; i++) { + z8536_write(dev, cmd, Z8536_CT_CMDSTAT_REG(chan)); + + val = z8536_read(dev, Z8536_CT_VAL_MSB_REG(chan)) << 8; + val |= z8536_read(dev, Z8536_CT_VAL_LSB_REG(chan)); + + data[i] = val; + } + + return insn->n; +} static int apci1500_auto_attach(struct comedi_device *dev, unsigned long context) @@ -35,10 +768,10 @@ static int apci1500_auto_attach(struct comedi_device *dev, return ret; dev->iobase = pci_resource_start(pcidev, 1); - devpriv->iobase = dev->iobase; - devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); - devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2); - devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3); + devpriv->amcc = pci_resource_start(pcidev, 0); + devpriv->addon = pci_resource_start(pcidev, 2); + + z8536_reset(dev); if (pcidev->irq > 0) { ret = request_irq(pcidev->irq, apci1500_interrupt, IRQF_SHARED, @@ -51,51 +784,66 @@ static int apci1500_auto_attach(struct comedi_device *dev, if (ret) return ret; - /* Allocate and Initialise DI Subdevice Structures */ + /* Digital Input subdevice */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_config = apci1500_di_config; - s->insn_read = apci1500_di_read; - s->insn_write = apci1500_di_write; - s->insn_bits = apci1500_di_insn_bits; - - /* Allocate and Initialise DO Subdevice Structures */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = apci1500_di_insn_bits; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 1; + s->insn_config = apci1500_di_insn_config; + s->do_cmdtest = apci1500_di_cmdtest; + s->do_cmd = apci1500_di_cmd; + s->cancel = apci1500_di_cancel; + } + + /* Digital Output subdevice */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_config = apci1500_do_config; - s->insn_write = apci1500_do_write; - s->insn_bits = apci1500_do_bits; - - /* Allocate and Initialise Timer Subdevice Structures */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = apci1500_do_insn_bits; + + /* reset all the digital outputs */ + outw(0x0, devpriv->addon + APCI1500_DO_REG); + + /* Counter/Timer(Watchdog) subdevice */ s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_TIMER; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 1; - s->maxdata = 0; - s->len_chanlist = 1; - s->range_table = &range_digital; - s->insn_write = apci1500_timer_write; - s->insn_read = apci1500_timer_read; - s->insn_config = apci1500_timer_config; - s->insn_bits = apci1500_timer_bits; - - apci1500_reset(dev); + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 3; + s->maxdata = 0xffff; + s->range_table = &range_unknown; + s->insn_config = apci1500_timer_insn_config; + s->insn_write = apci1500_timer_insn_write; + s->insn_read = apci1500_timer_insn_read; + + /* Enable the PCI interrupt */ + if (dev->irq) { + outl(0x2000 | INTCSR_INBOX_FULL_INT, + devpriv->amcc + AMCC_OP_REG_INTCSR); + inl(devpriv->amcc + AMCC_OP_REG_IMB1); + inl(devpriv->amcc + AMCC_OP_REG_INTCSR); + outl(INTCSR_INBOX_INTR_STATUS | 0x2000 | INTCSR_INBOX_FULL_INT, + devpriv->amcc + AMCC_OP_REG_INTCSR); + } return 0; } static void apci1500_detach(struct comedi_device *dev) { - if (dev->iobase) - apci1500_reset(dev); + struct apci1500_private *devpriv = dev->private; + + if (devpriv->amcc) + outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR); comedi_pci_detach(dev); } diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index a726efcea6a..5961f195ba0 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -267,7 +267,6 @@ static irqreturn_t apci3501_interrupt(int irq, void *d) struct apci3501_private *devpriv = dev->private; unsigned int ui_Timer_AOWatchdog; unsigned long ul_Command1; - int i_temp; /* Disable Interrupt */ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); @@ -285,7 +284,7 @@ static irqreturn_t apci3501_interrupt(int irq, void *d) ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1); outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); - i_temp = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1; + inl(dev->iobase + APCI3501_TIMER_STATUS_REG); return IRQ_HANDLED; } diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 528f15c25da..a3ea4b7c18d 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -19,8 +19,7 @@ /* * Driver: adl_pci6208 * Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards - * Devices: (ADLink) PCI-6208 [adl_pci6208] - * (ADLink) PCI-6216 [adl_pci6216] + * Devices: [ADLink] PCI-6208 (adl_pci6208), PCI-6216 (adl_pci6216) * Author: nsyeow <nsyeow@pd.jaring.my> * Updated: Fri, 30 Jan 2004 14:44:27 +0800 * Status: untested diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c index fb8e5f58249..618e641ffaa 100644 --- a/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c @@ -22,27 +22,35 @@ */ /* -Driver: adl_pci7x3x -Description: 32/64-Channel Isolated Digital I/O Boards -Devices: (ADLink) PCI-7230 [adl_pci7230] - 16 input / 16 output - (ADLink) PCI-7233 [adl_pci7233] - 32 input - (ADLink) PCI-7234 [adl_pci7234] - 32 output - (ADLink) PCI-7432 [adl_pci7432] - 32 input / 32 output - (ADLink) PCI-7433 [adl_pci7433] - 64 input - (ADLink) PCI-7434 [adl_pci7434] - 64 output -Author: H Hartley Sweeten <hsweeten@visionengravers.com> -Updated: Thu, 02 Aug 2012 14:27:46 -0700 -Status: untested - -The PCI-7230, PCI-7432 and PCI-7433 boards also support external -interrupt signals on digital input channels 0 and 1. The PCI-7233 -has dual-interrupt sources for change-of-state (COS) on any 16 -digital input channels of LSB and for COS on any 16 digital input -lines of MSB. Interrupts are not currently supported by this -driver. - -Configuration Options: not applicable, uses comedi PCI auto config -*/ + * Driver: adl_pci7x3x + * Description: 32/64-Channel Isolated Digital I/O Boards + * Devices: [ADLink] PCI-7230 (adl_pci7230), PCI-7233 (adl_pci7233), + * PCI-7234 (adl_pci7234), PCI-7432 (adl_pci7432), PCI-7433 (adl_pci7433), + * PCI-7434 (adl_pci7434) + * Author: H Hartley Sweeten <hsweeten@visionengravers.com> + * Updated: Thu, 02 Aug 2012 14:27:46 -0700 + * Status: untested + * + * One or two subdevices are setup by this driver depending on + * the number of digital inputs and/or outputs provided by the + * board. Each subdevice has a maximum of 32 channels. + * + * PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output + * PCI-7233 - 1 subdevice: 0 - 32 input + * PCI-7234 - 1 subdevice: 0 - 32 output + * PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output + * PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input + * PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output + * + * The PCI-7230, PCI-7432 and PCI-7433 boards also support external + * interrupt signals on digital input channels 0 and 1. The PCI-7233 + * has dual-interrupt sources for change-of-state (COS) on any 16 + * digital input channels of LSB and for COS on any 16 digital input + * lines of MSB. Interrupts are not currently supported by this + * driver. + * + * Configuration Options: not applicable, uses comedi PCI auto config + */ #include <linux/module.h> #include <linux/pci.h> @@ -155,18 +163,6 @@ static int adl_pci7x3x_auto_attach(struct comedi_device *dev, return ret; dev->iobase = pci_resource_start(pcidev, 2); - /* - * One or two subdevices are setup by this driver depending on - * the number of digital inputs and/or outputs provided by the - * board. Each subdevice has a maximum of 32 channels. - * - * PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output - * PCI-7233 - 1 subdevice: 0 - 32 input - * PCI-7234 - 1 subdevice: 0 - 32 output - * PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output - * PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input - * PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output - */ ret = comedi_alloc_subdevices(dev, board->nsubdevs); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 72bccb447a7..cc6c53b800a 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -18,7 +18,7 @@ /* * Driver: adl_pci8164 * Description: Driver for the Adlink PCI-8164 4 Axes Motion Control board - * Devices: (ADLink) PCI-8164 [adl_pci8164] + * Devices: [ADLink] PCI-8164 (adl_pci8164) * Author: Michel Lachaine <mike@mikelachaine.ca> * Status: experimental * Updated: Mon, 14 Apr 2008 15:10:32 +0100 diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 47f6c0e9f01..f68dc99f8e2 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -539,7 +539,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) spin_unlock_irqrestore(&dev->spinlock, irq_flags); dev_dbg(dev->class_dev, "fifo overflow\n"); outb(0, dev->iobase + PCI9111_INT_CLR_REG); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return IRQ_HANDLED; diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 26603582e71..f61e392c2d3 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -749,13 +749,13 @@ static irqreturn_t pci9118_interrupt(int irq, void *d) if (intcsr & MASTER_ABORT_INT) { dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n"); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; goto interrupt_exit; } if (intcsr & TARGET_ABORT_INT) { dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n"); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; goto interrupt_exit; } diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index d02df7d0c62..9800c01e6fb 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -51,11 +51,6 @@ Configuration options: #include "8253.h" #include "amcc_s5933.h" -/* hardware types of the cards */ -#define TYPE_PCI171X 0 -#define TYPE_PCI1713 2 -#define TYPE_PCI1720 3 - #define PCI171x_AD_DATA 0 /* R: A/D data */ #define PCI171x_SOFTTRG 0 /* W: soft trigger for A/D */ #define PCI171x_RANGE 2 /* W: A/D gain/range register */ @@ -164,7 +159,7 @@ static const struct comedi_lrange range_pci17x1 = { static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; -static const struct comedi_lrange range_pci1720 = { +static const struct comedi_lrange pci1720_ao_range = { 4, { UNI_RANGE(5), UNI_RANGE(10), @@ -173,7 +168,7 @@ static const struct comedi_lrange range_pci1720 = { } }; -static const struct comedi_lrange range_pci171x_da = { +static const struct comedi_lrange pci171x_ao_range = { 2, { UNI_RANGE(5), UNI_RANGE(10) @@ -191,112 +186,81 @@ enum pci1710_boardid { struct boardtype { const char *name; /* board name */ - char have_irq; /* 1=card support IRQ */ - char cardtype; /* 0=1710& co. 2=1713, ... */ int n_aichan; /* num of A/D chans */ - int n_aichand; /* num of A/D chans in diff mode */ - int n_aochan; /* num of D/A chans */ - int n_dichan; /* num of DI chans */ - int n_dochan; /* num of DO chans */ - int n_counter; /* num of counters */ - int ai_maxdata; /* resolution of A/D */ - int ao_maxdata; /* resolution of D/A */ const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ const char *rangecode_ai; /* range codes for programming */ - const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ - unsigned int ai_ns_min; /* max sample speed of card v ns */ - unsigned int fifo_half_size; /* size of FIFO/2 */ + unsigned int is_pci1713:1; + unsigned int is_pci1720:1; + unsigned int has_irq:1; + unsigned int has_large_fifo:1; /* 4K or 1K FIFO */ + unsigned int has_diff_ai:1; + unsigned int has_ao:1; + unsigned int has_di_do:1; + unsigned int has_counter:1; }; static const struct boardtype boardtypes[] = { [BOARD_PCI1710] = { .name = "pci1710", - .have_irq = 1, - .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_aichand = 8, - .n_aochan = 2, - .n_dichan = 16, - .n_dochan = 16, - .n_counter = 1, - .ai_maxdata = 0x0fff, - .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, - .rangelist_ao = &range_pci171x_da, - .ai_ns_min = 10000, - .fifo_half_size = 2048, + .has_irq = 1, + .has_large_fifo = 1, + .has_diff_ai = 1, + .has_ao = 1, + .has_di_do = 1, + .has_counter = 1, }, [BOARD_PCI1710HG] = { .name = "pci1710hg", - .have_irq = 1, - .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_aichand = 8, - .n_aochan = 2, - .n_dichan = 16, - .n_dochan = 16, - .n_counter = 1, - .ai_maxdata = 0x0fff, - .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710hg, .rangecode_ai = range_codes_pci1710hg, - .rangelist_ao = &range_pci171x_da, - .ai_ns_min = 10000, - .fifo_half_size = 2048, + .has_irq = 1, + .has_large_fifo = 1, + .has_diff_ai = 1, + .has_ao = 1, + .has_di_do = 1, + .has_counter = 1, }, [BOARD_PCI1711] = { .name = "pci1711", - .have_irq = 1, - .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_aochan = 2, - .n_dichan = 16, - .n_dochan = 16, - .n_counter = 1, - .ai_maxdata = 0x0fff, - .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, - .rangelist_ao = &range_pci171x_da, - .ai_ns_min = 10000, - .fifo_half_size = 512, + .has_irq = 1, + .has_ao = 1, + .has_di_do = 1, + .has_counter = 1, }, [BOARD_PCI1713] = { .name = "pci1713", - .have_irq = 1, - .cardtype = TYPE_PCI1713, .n_aichan = 32, - .n_aichand = 16, - .ai_maxdata = 0x0fff, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, - .ai_ns_min = 10000, - .fifo_half_size = 2048, + .is_pci1713 = 1, + .has_irq = 1, + .has_large_fifo = 1, + .has_diff_ai = 1, }, [BOARD_PCI1720] = { .name = "pci1720", - .cardtype = TYPE_PCI1720, - .n_aochan = 4, - .ao_maxdata = 0x0fff, - .rangelist_ao = &range_pci1720, + .is_pci1720 = 1, + .has_ao = 1, }, [BOARD_PCI1731] = { .name = "pci1731", - .have_irq = 1, - .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_dichan = 16, - .n_dochan = 16, - .ai_maxdata = 0x0fff, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, - .ai_ns_min = 10000, - .fifo_half_size = 512, + .has_irq = 1, + .has_di_do = 1, }, }; struct pci1710_private { + unsigned int max_samples; unsigned int CntrlReg; /* Control register */ unsigned char ai_et; unsigned int ai_et_CntrlReg; @@ -308,39 +272,10 @@ struct pci1710_private { unsigned int act_chanlist[32]; /* list of scanned channel */ unsigned char saved_seglen; /* len of the non-repeating chanlist */ unsigned char da_ranges; /* copy of D/A outpit range register */ - unsigned short ao_data[4]; /* data output buffer */ unsigned int cnt0_write_wait; /* after a write, wait for update of the * internal state */ }; -/* used for gain list programming */ -static const unsigned int muxonechan[] = { - 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, - 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, - 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717, - 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f -}; - -static int pci171x_ai_dropout(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int chan, - unsigned int val) -{ - const struct boardtype *board = dev->board_ptr; - struct pci1710_private *devpriv = dev->private; - - if (board->cardtype != TYPE_PCI1713) { - if ((val & 0xf000) != devpriv->act_chanlist[chan]) { - dev_err(dev->class_dev, - "A/D data droput: received from channel %d, expected %d\n", - (val >> 12) & 0xf, - (devpriv->act_chanlist[chan] >> 12) & 0xf); - return -ENODATA; - } - } - return 0; -} - static int pci171x_ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -407,33 +342,39 @@ static int pci171x_ai_check_chanlist(struct comedi_device *dev, return 0; } -static void setup_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int n_chan, - unsigned int seglen) +static void pci171x_ai_setup_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int *chanlist, + unsigned int n_chan, + unsigned int seglen) { - const struct boardtype *this_board = dev->board_ptr; + const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; - unsigned int i, range, chanprog; + unsigned int first_chan = CR_CHAN(chanlist[0]); + unsigned int last_chan = CR_CHAN(chanlist[seglen - 1]); + unsigned int i; for (i = 0; i < seglen; i++) { /* store range list to card */ - chanprog = muxonechan[CR_CHAN(chanlist[i])]; - outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ - range = this_board->rangecode_ai[CR_RANGE(chanlist[i])]; - if (CR_AREF(chanlist[i]) == AREF_DIFF) - range |= 0x0020; - outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ - devpriv->act_chanlist[i] = - (CR_CHAN(chanlist[i]) << 12) & 0xf000; - } - for ( ; i < n_chan; i++) { /* store remainder of channel list */ - devpriv->act_chanlist[i] = - (CR_CHAN(chanlist[i]) << 12) & 0xf000; + unsigned int chan = CR_CHAN(chanlist[i]); + unsigned int range = CR_RANGE(chanlist[i]); + unsigned int aref = CR_AREF(chanlist[i]); + unsigned int rangeval; + + rangeval = board->rangecode_ai[range]; + if (aref == AREF_DIFF) + rangeval |= 0x0020; + + /* select channel and set range */ + outw(chan | (chan << 8), dev->iobase + PCI171x_MUX); + outw(rangeval, dev->iobase + PCI171x_RANGE); + + devpriv->act_chanlist[i] = chan; } + for ( ; i < n_chan; i++) /* store remainder of channel list */ + devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); - devpriv->ai_et_MuxVal = - CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); /* select channel interval to scan */ + devpriv->ai_et_MuxVal = first_chan | (last_chan << 8); outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); } @@ -450,9 +391,39 @@ static int pci171x_ai_eoc(struct comedi_device *dev, return -EBUSY; } -static int pci171x_insn_read_ai(struct comedi_device *dev, +static int pci171x_ai_read_sample(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int cur_chan, + unsigned int *val) +{ + const struct boardtype *board = dev->board_ptr; + struct pci1710_private *devpriv = dev->private; + unsigned int sample; + unsigned int chan; + + sample = inw(dev->iobase + PCI171x_AD_DATA); + if (!board->is_pci1713) { + /* + * The upper 4 bits of the 16-bit sample are the channel number + * that the sample was acquired from. Verify that this channel + * number matches the expected channel number. + */ + chan = sample >> 12; + if (chan != devpriv->act_chanlist[cur_chan]) { + dev_err(dev->class_dev, + "A/D data droput: received from channel %d, expected %d\n", + chan, devpriv->act_chanlist[cur_chan]); + return -ENODATA; + } + } + *val = sample & s->maxdata; + return 0; +} + +static int pci171x_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct pci1710_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); @@ -465,7 +436,7 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); - setup_channel_list(dev, s, &insn->chanspec, 1, 1); + pci171x_ai_setup_chanlist(dev, s, &insn->chanspec, 1, 1); for (i = 0; i < insn->n; i++) { unsigned int val; @@ -476,12 +447,11 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, if (ret) break; - val = inw(dev->iobase + PCI171x_AD_DATA); - ret = pci171x_ai_dropout(dev, s, chan, val); + ret = pci171x_ai_read_sample(dev, s, chan, &val); if (ret) break; - data[i] = val & s->maxdata; + data[i] = val; } outb(0, dev->iobase + PCI171x_CLRFIFO); @@ -490,73 +460,43 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, return ret ? ret : insn->n; } -/* -============================================================================== -*/ -static int pci171x_insn_write_ao(struct comedi_device *dev, +static int pci171x_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct pci1710_private *devpriv = dev->private; - unsigned int val; - int n, chan, range, ofs; - - chan = CR_CHAN(insn->chanspec); - range = CR_RANGE(insn->chanspec); - if (chan) { - devpriv->da_ranges &= 0xfb; - devpriv->da_ranges |= (range << 2); - outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); - ofs = PCI171x_DA2; - } else { - devpriv->da_ranges &= 0xfe; - devpriv->da_ranges |= range; - outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); - ofs = PCI171x_DA1; - } - val = devpriv->ao_data[chan]; - - for (n = 0; n < insn->n; n++) { - val = data[n]; - outw(val, dev->iobase + ofs); - } - - devpriv->ao_data[chan] = val; - - return n; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int reg = chan ? PCI171x_DA2 : PCI171x_DA1; + unsigned int val = s->readback[chan]; + int i; -} + devpriv->da_ranges &= ~(1 << (chan << 1)); + devpriv->da_ranges |= (range << (chan << 1)); + outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); -/* -============================================================================== -*/ -static int pci171x_insn_read_ao(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct pci1710_private *devpriv = dev->private; - int n, chan; + for (i = 0; i < insn->n; i++) { + val = data[i]; + outw(val, dev->iobase + reg); + } - chan = CR_CHAN(insn->chanspec); - for (n = 0; n < insn->n; n++) - data[n] = devpriv->ao_data[chan]; + s->readback[chan] = val; - return n; + return insn->n; } -/* -============================================================================== -*/ -static int pci171x_insn_bits_di(struct comedi_device *dev, +static int pci171x_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { data[1] = inw(dev->iobase + PCI171x_DI); return insn->n; } -static int pci171x_insn_bits_do(struct comedi_device *dev, +static int pci171x_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -584,10 +524,7 @@ static void pci171x_start_pacer(struct comedi_device *dev, } } -/* -============================================================================== -*/ -static int pci171x_insn_counter_read(struct comedi_device *dev, +static int pci171x_counter_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -608,10 +545,7 @@ static int pci171x_insn_counter_read(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ -static int pci171x_insn_counter_write(struct comedi_device *dev, +static int pci171x_counter_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -638,10 +572,7 @@ static int pci171x_insn_counter_write(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ -static int pci171x_insn_counter_config(struct comedi_device *dev, +static int pci171x_counter_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -677,57 +608,48 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, return 1; } -/* -============================================================================== -*/ -static int pci1720_insn_write_ao(struct comedi_device *dev, +static int pci1720_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct pci1710_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); unsigned int val; - int n, rangereg, chan; - - chan = CR_CHAN(insn->chanspec); - rangereg = devpriv->da_ranges & (~(0x03 << (chan << 1))); - rangereg |= (CR_RANGE(insn->chanspec) << (chan << 1)); - if (rangereg != devpriv->da_ranges) { - outb(rangereg, dev->iobase + PCI1720_RANGE); - devpriv->da_ranges = rangereg; + int i; + + val = devpriv->da_ranges & (~(0x03 << (chan << 1))); + val |= (range << (chan << 1)); + if (val != devpriv->da_ranges) { + outb(val, dev->iobase + PCI1720_RANGE); + devpriv->da_ranges = val; } - val = devpriv->ao_data[chan]; - for (n = 0; n < insn->n; n++) { - val = data[n]; + val = s->readback[chan]; + for (i = 0; i < insn->n; i++) { + val = data[i]; outw(val, dev->iobase + PCI1720_DA0 + (chan << 1)); - outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ + outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ } - devpriv->ao_data[chan] = val; + s->readback[chan] = val; - return n; + return insn->n; } -/* -============================================================================== -*/ static int pci171x_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct boardtype *this_board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; - switch (this_board->cardtype) { - default: - devpriv->CntrlReg &= Control_CNT0; - devpriv->CntrlReg |= Control_SW; - /* reset any operations */ - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); - pci171x_start_pacer(dev, false); - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); - break; - } + devpriv->CntrlReg &= Control_CNT0; + devpriv->CntrlReg |= Control_SW; + /* reset any operations */ + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + pci171x_start_pacer(dev, false); + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); return 0; } @@ -743,29 +665,25 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, status = inw(dev->iobase + PCI171x_STATUS); if (status & Status_FE) { dev_dbg(dev->class_dev, "A/D FIFO empty (%4x)\n", status); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_handle_events(dev, s); + s->async->events |= COMEDI_CB_ERROR; return; } if (status & Status_FF) { dev_dbg(dev->class_dev, "A/D FIFO Full status (Fatal Error!) (%4x)\n", status); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_handle_events(dev, s); + s->async->events |= COMEDI_CB_ERROR; return; } outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) { - val = inw(dev->iobase + PCI171x_AD_DATA); - ret = pci171x_ai_dropout(dev, s, s->async->cur_chan, val); + ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); if (ret) { - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; break; } - val &= s->maxdata; comedi_buf_write_samples(s, &val, 1); if (cmd->stop_src == TRIG_COUNT && @@ -776,85 +694,53 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, } outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ - - comedi_handle_events(dev, s); -} - -/* -============================================================================== -*/ -static int move_block_from_fifo(struct comedi_device *dev, - struct comedi_subdevice *s, int n, int turn) -{ - unsigned int val; - int ret; - int i; - - for (i = 0; i < n; i++) { - val = inw(dev->iobase + PCI171x_AD_DATA); - - ret = pci171x_ai_dropout(dev, s, s->async->cur_chan, val); - if (ret) { - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - return ret; - } - - val &= s->maxdata; - comedi_buf_write_samples(s, &val, 1); - } - return 0; } static void pci1710_handle_fifo(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct boardtype *this_board = dev->board_ptr; - struct comedi_cmd *cmd = &s->async->cmd; - unsigned int nsamples; - unsigned int m; - - m = inw(dev->iobase + PCI171x_STATUS); - if (!(m & Status_FH)) { - dev_dbg(dev->class_dev, "A/D FIFO not half full! (%4x)\n", m); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_handle_events(dev, s); + struct pci1710_private *devpriv = dev->private; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int status; + int i; + + status = inw(dev->iobase + PCI171x_STATUS); + if (!(status & Status_FH)) { + dev_dbg(dev->class_dev, "A/D FIFO not half full!\n"); + async->events |= COMEDI_CB_ERROR; return; } - if (m & Status_FF) { + if (status & Status_FF) { dev_dbg(dev->class_dev, - "A/D FIFO Full status (Fatal Error!) (%4x)\n", m); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_handle_events(dev, s); + "A/D FIFO Full status (Fatal Error!)\n"); + async->events |= COMEDI_CB_ERROR; return; } - nsamples = this_board->fifo_half_size; - if (comedi_samples_to_bytes(s, nsamples) >= s->async->prealloc_bufsz) { - m = comedi_bytes_to_samples(s, s->async->prealloc_bufsz); - if (move_block_from_fifo(dev, s, m, 0)) - return; - nsamples -= m; - } + for (i = 0; i < devpriv->max_samples; i++) { + unsigned int val; + int ret; - if (nsamples) { - if (move_block_from_fifo(dev, s, nsamples, 1)) - return; - } + ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); + if (ret) { + s->async->events |= COMEDI_CB_ERROR; + break; + } - if (cmd->stop_src == TRIG_COUNT && - s->async->scans_done >= cmd->stop_arg) { - s->async->events |= COMEDI_CB_EOA; - comedi_handle_events(dev, s); - return; + if (!comedi_buf_write_samples(s, &val, 1)) + break; + + if (cmd->stop_src == TRIG_COUNT && + async->scans_done >= cmd->stop_arg) { + async->events |= COMEDI_CB_EOA; + break; + } } - outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ - comedi_handle_events(dev, s); + outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ } -/* -============================================================================== -*/ static irqreturn_t interrupt_service_pci1710(int irq, void *d) { struct comedi_device *dev = d; @@ -891,6 +777,8 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) else pci1710_handle_fifo(dev, s); + comedi_handle_events(dev, s); + return IRQ_HANDLED; } @@ -901,8 +789,8 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) pci171x_start_pacer(dev, false); - setup_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len, - devpriv->saved_seglen); + pci171x_ai_setup_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, + devpriv->saved_seglen); outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); @@ -937,14 +825,10 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -/* -============================================================================== -*/ static int pci171x_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct boardtype *this_board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; int err = 0; unsigned int arg; @@ -977,8 +861,7 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); if (cmd->convert_src == TRIG_TIMER) - err |= cfc_check_trigger_arg_min(&cmd->convert_arg, - this_board->ai_ns_min); + err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000); else /* TRIG_FOLLOW */ err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); @@ -1016,12 +899,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, return 0; } -/* -============================================================================== -*/ static int pci171x_reset(struct comedi_device *dev) { - const struct boardtype *this_board = dev->board_ptr; + const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; outw(0x30, dev->iobase + PCI171x_CNTCTRL); @@ -1033,15 +913,11 @@ static int pci171x_reset(struct comedi_device *dev) outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ pci171x_start_pacer(dev, false); devpriv->da_ranges = 0; - if (this_board->n_aochan) { + if (board->has_ao) { /* set DACs to 0..5V */ outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */ - devpriv->ao_data[0] = 0x0000; - if (this_board->n_aochan > 1) { - outw(0, dev->iobase + PCI171x_DA2); - devpriv->ao_data[1] = 0x0000; - } + outw(0, dev->iobase + PCI171x_DA2); } outw(0, dev->iobase + PCI171x_DO); /* digital outputs to 0 */ outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ @@ -1050,9 +926,6 @@ static int pci171x_reset(struct comedi_device *dev) return 0; } -/* -============================================================================== -*/ static int pci1720_reset(struct comedi_device *dev) { struct pci1710_private *devpriv = dev->private; @@ -1066,43 +939,35 @@ static int pci1720_reset(struct comedi_device *dev) outw(0x0800, dev->iobase + PCI1720_DA2); outw(0x0800, dev->iobase + PCI1720_DA3); outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ - devpriv->ao_data[0] = 0x0800; - devpriv->ao_data[1] = 0x0800; - devpriv->ao_data[2] = 0x0800; - devpriv->ao_data[3] = 0x0800; + return 0; } -/* -============================================================================== -*/ static int pci1710_reset(struct comedi_device *dev) { - const struct boardtype *this_board = dev->board_ptr; + const struct boardtype *board = dev->board_ptr; - switch (this_board->cardtype) { - case TYPE_PCI1720: + if (board->is_pci1720) return pci1720_reset(dev); - default: - return pci171x_reset(dev); - } + + return pci171x_reset(dev); } static int pci1710_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct boardtype *this_board = NULL; + const struct boardtype *board = NULL; struct pci1710_private *devpriv; struct comedi_subdevice *s; int ret, subdev, n_subdevices; if (context < ARRAY_SIZE(boardtypes)) - this_board = &boardtypes[context]; - if (!this_board) + board = &boardtypes[context]; + if (!board) return -ENODEV; - dev->board_ptr = this_board; - dev->board_name = this_board->name; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1114,15 +979,13 @@ static int pci1710_auto_attach(struct comedi_device *dev, dev->iobase = pci_resource_start(pcidev, 2); n_subdevices = 0; - if (this_board->n_aichan) - n_subdevices++; - if (this_board->n_aochan) - n_subdevices++; - if (this_board->n_dichan) + if (board->n_aichan) n_subdevices++; - if (this_board->n_dochan) + if (board->has_ao) n_subdevices++; - if (this_board->n_counter) + if (board->has_di_do) + n_subdevices += 2; + if (board->has_counter) n_subdevices++; ret = comedi_alloc_subdevices(dev, n_subdevices); @@ -1131,7 +994,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, pci1710_reset(dev); - if (this_board->have_irq && pcidev->irq) { + if (board->has_irq && pcidev->irq) { ret = request_irq(pcidev->irq, interrupt_service_pci1710, IRQF_SHARED, dev->board_name, dev); if (ret == 0) @@ -1140,85 +1003,93 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev = 0; - if (this_board->n_aichan) { + if (board->n_aichan) { s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; - if (this_board->n_aichand) - s->subdev_flags |= SDF_DIFF; - s->n_chan = this_board->n_aichan; - s->maxdata = this_board->ai_maxdata; - s->range_table = this_board->rangelist_ai; - s->insn_read = pci171x_insn_read_ai; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; + if (board->has_diff_ai) + s->subdev_flags |= SDF_DIFF; + s->n_chan = board->n_aichan; + s->maxdata = 0x0fff; + s->range_table = board->rangelist_ai; + s->insn_read = pci171x_ai_insn_read; if (dev->irq) { dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->len_chanlist = s->n_chan; - s->do_cmdtest = pci171x_ai_cmdtest; - s->do_cmd = pci171x_ai_cmd; - s->cancel = pci171x_ai_cancel; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; + s->do_cmdtest = pci171x_ai_cmdtest; + s->do_cmd = pci171x_ai_cmd; + s->cancel = pci171x_ai_cancel; } subdev++; } - if (this_board->n_aochan) { + if (board->has_ao) { s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = this_board->n_aochan; - s->maxdata = this_board->ao_maxdata; - s->len_chanlist = this_board->n_aochan; - s->range_table = this_board->rangelist_ao; - switch (this_board->cardtype) { - case TYPE_PCI1720: - s->insn_write = pci1720_insn_write_ao; - break; - default: - s->insn_write = pci171x_insn_write_ao; - break; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->maxdata = 0x0fff; + if (board->is_pci1720) { + s->n_chan = 4; + s->range_table = &pci1720_ao_range; + s->insn_write = pci1720_ao_insn_write; + } else { + s->n_chan = 2; + s->range_table = &pci171x_ao_range; + s->insn_write = pci171x_ao_insn_write; } - s->insn_read = pci171x_insn_read_ao; + + ret = comedi_alloc_subdev_readback(s); + if (ret) + return ret; + + /* initialize the readback values to match the board reset */ + if (board->is_pci1720) { + int i; + + for (i = 0; i < s->n_chan; i++) + s->readback[i] = 0x0800; + } + subdev++; } - if (this_board->n_dichan) { + if (board->has_di_do) { s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = this_board->n_dichan; - s->maxdata = 1; - s->len_chanlist = this_board->n_dichan; - s->range_table = &range_digital; - s->insn_bits = pci171x_insn_bits_di; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci171x_di_insn_bits; subdev++; - } - if (this_board->n_dochan) { s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = this_board->n_dochan; - s->maxdata = 1; - s->len_chanlist = this_board->n_dochan; - s->range_table = &range_digital; - s->insn_bits = pci171x_insn_bits_do; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci171x_do_insn_bits; subdev++; } - if (this_board->n_counter) { + if (board->has_counter) { s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = this_board->n_counter; - s->len_chanlist = this_board->n_counter; - s->maxdata = 0xffff; - s->range_table = &range_unknown; - s->insn_read = pci171x_insn_counter_read; - s->insn_write = pci171x_insn_counter_write; - s->insn_config = pci171x_insn_counter_config; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 1; + s->maxdata = 0xffff; + s->range_table = &range_unknown; + s->insn_read = pci171x_counter_insn_read; + s->insn_write = pci171x_counter_insn_write; + s->insn_config = pci171x_counter_insn_config; subdev++; } + /* max_samples is half the FIFO size (2 bytes/sample) */ + devpriv->max_samples = (board->has_large_fifo) ? 2048 : 512; + return 0; } @@ -1312,5 +1183,5 @@ static struct pci_driver adv_pci1710_pci_driver = { module_comedi_pci_driver(adv_pci1710_driver, adv_pci1710_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi: Advantech PCI-1710 Series Multifunction DAS Cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 65f854e1eb6..f1945be89ef 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -20,7 +20,7 @@ * Driver: adv_pci1723 * Description: Advantech PCI-1723 * Author: yonggang <rsmgnu@gmail.com>, Ian Abbott <abbotti@mev.co.uk> - * Devices: (Advantech) PCI-1723 [adv_pci1723] + * Devices: [Advantech] PCI-1723 (adv_pci1723) * Updated: Mon, 14 Apr 2008 15:12:56 +0100 * Status: works * diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index a8d28403262..a3573ea6f9c 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -22,7 +22,7 @@ /* * Driver: adv_pci1724 * Description: Advantech PCI-1724U - * Devices: (Advantech) PCI-1724U [adv_pci1724] + * Devices: [Advantech] PCI-1724U (adv_pci1724) * Author: Frank Mori Hess <fmh6jj@gmail.com> * Updated: 2013-02-09 * Status: works diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 7b5ed439c16..1c7b325a373 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -1,48 +1,155 @@ /* + * aio_iiro_16.c + * Comedi driver for Access I/O Products 104-IIRO-16 board + * Copyright (C) 2006 C&C Technologies, Inc. + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - comedi/drivers/aio_iiro_16.c +/* + * Driver: aio_iiro_16 + * Description: Access I/O Products PC/104 Isolated Input/Relay Output Board + * Author: Zachary Ware <zach.ware@cctechnol.com> + * Devices: [Access I/O] 104-IIRO-16 (aio_iiro_16) + * Status: experimental + * + * Configuration Options: + * [0] - I/O port base address + * [1] - IRQ (optional) + * + * The board supports interrupts on change of state of the digital inputs. + * The sample data returned by the async command indicates which inputs + * changed state and the current state of the inputs: + * + * Bit 23 - IRQ Enable (1) / Disable (0) + * Bit 17 - Input 8-15 Changed State (1 = Changed, 0 = No Change) + * Bit 16 - Input 0-7 Changed State (1 = Changed, 0 = No Change) + * Bit 15 - Digital input 15 + * ... + * Bit 0 - Digital input 0 + */ - Driver for Access I/O Products PC-104 AIO-IIRO-16 Digital I/O board - Copyright (C) 2006 C&C Technologies, Inc. +#include <linux/module.h> +#include <linux/interrupt.h> - 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 of the License, or - (at your option) any later version. +#include "../comedidev.h" - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ +#include "comedi_fc.h" -/* +#define AIO_IIRO_16_RELAY_0_7 0x00 +#define AIO_IIRO_16_INPUT_0_7 0x01 +#define AIO_IIRO_16_IRQ 0x02 +#define AIO_IIRO_16_RELAY_8_15 0x04 +#define AIO_IIRO_16_INPUT_8_15 0x05 +#define AIO_IIRO_16_STATUS 0x07 +#define AIO_IIRO_16_STATUS_IRQE BIT(7) +#define AIO_IIRO_16_STATUS_INPUT_8_15 BIT(1) +#define AIO_IIRO_16_STATUS_INPUT_0_7 BIT(0) -Driver: aio_iiro_16 -Description: Access I/O Products PC-104 IIRO16 Relay And Isolated Input Board -Author: Zachary Ware <zach.ware@cctechnol.com> -Devices: - [Access I/O] PC-104 AIO12-8 -Status: experimental +static unsigned int aio_iiro_16_read_inputs(struct comedi_device *dev) +{ + unsigned int val; -Configuration Options: - [0] - I/O port base address + val = inb(dev->iobase + AIO_IIRO_16_INPUT_0_7); + val |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8; -*/ + return val; +} -#include <linux/module.h> -#include "../comedidev.h" +static irqreturn_t aio_iiro_16_cos(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->read_subdev; + unsigned int status; + unsigned int val; + + status = inb(dev->iobase + AIO_IIRO_16_STATUS); + if (!(status & AIO_IIRO_16_STATUS_IRQE)) + return IRQ_NONE; + + val = aio_iiro_16_read_inputs(dev); + val |= (status << 16); + + comedi_buf_write_samples(s, &val, 1); + comedi_handle_events(dev, s); + + return IRQ_HANDLED; +} + +static void aio_iiro_enable_irq(struct comedi_device *dev, bool enable) +{ + if (enable) + inb(dev->iobase + AIO_IIRO_16_IRQ); + else + outb(0, dev->iobase + AIO_IIRO_16_IRQ); +} + +static int aio_iiro_16_cos_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + aio_iiro_enable_irq(dev, false); + + return 0; +} -#define AIO_IIRO_16_RELAY_0_7 0x00 -#define AIO_IIRO_16_INPUT_0_7 0x01 -#define AIO_IIRO_16_IRQ 0x02 -#define AIO_IIRO_16_RELAY_8_15 0x04 -#define AIO_IIRO_16_INPUT_8_15 0x05 +static int aio_iiro_16_cos_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + aio_iiro_enable_irq(dev, true); + + return 0; +} + +static int aio_iiro_16_cos_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int err = 0; + + /* Step 1 : check if triggers are trivially valid */ + + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + + if (err) + return 1; + + /* Step 2a : make sure trigger sources are unique */ + /* Step 2b : and mutually compatible */ + + /* Step 3: check if arguments are trivially valid */ -static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + + if (err) + return 3; + + /* Step 4: fix up any arguments */ + + /* Step 5: check channel list if it exists */ + + return 0; +} + +static int aio_iiro_16_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { if (comedi_dio_update_state(s, data)) { outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7); @@ -55,14 +162,12 @@ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev, return insn->n; } -static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int aio_iiro_16_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - data[1] = 0; - data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7); - data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8; + data[1] = aio_iiro_16_read_inputs(dev); return insn->n; } @@ -77,25 +182,52 @@ static int aio_iiro_16_attach(struct comedi_device *dev, if (ret) return ret; + aio_iiro_enable_irq(dev, false); + + /* + * Digital input change of state interrupts are optionally supported + * using IRQ 2-7, 10-12, 14, or 15. + */ + if ((1 << it->options[1]) & 0xdcfc) { + ret = request_irq(it->options[1], aio_iiro_16_cos, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; + } + ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; + /* Digital Output subdevice */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = aio_iiro_16_dio_insn_bits_write; - + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = aio_iiro_16_do_insn_bits; + + /* get the initial state of the relays */ + s->state = inb(dev->iobase + AIO_IIRO_16_RELAY_0_7) | + (inb(dev->iobase + AIO_IIRO_16_RELAY_8_15) << 8); + + /* Digital Input subdevice */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = aio_iiro_16_dio_insn_bits_read; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = aio_iiro_16_di_insn_bits; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ | SDF_LSAMPL; + s->len_chanlist = 1; + s->do_cmdtest = aio_iiro_16_cos_cmdtest; + s->do_cmd = aio_iiro_16_cos_cmd; + s->cancel = aio_iiro_16_cos_cancel; + } return 0; } @@ -109,5 +241,5 @@ static struct comedi_driver aio_iiro_16_driver = { module_comedi_driver(aio_iiro_16_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Access I/O Products 104-IIRO-16 board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index e7cb7032a91..1a109e30d8f 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -22,7 +22,7 @@ * Description: Mechatronic Systems Inc. C6x_DIGIO DSP daughter card * Author: Dan Block * Status: unknown - * Devices: (Mechatronic Systems Inc.) C6x_DIGIO DSP daughter card [c6xdigio] + * Devices: [Mechatronic Systems Inc.] C6x_DIGIO DSP daughter card (c6xdigio) * Updated: Sun Nov 20 20:18:34 EST 2005 * * Configuration Options: diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 0a48d2a961d..1079b6c72b1 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -38,10 +38,7 @@ Status: experimental #include <linux/interrupt.h> #include <linux/delay.h> -#include "../comedidev.h" - -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> +#include "../comedi_pcmcia.h" #include "comedi_fc.h" #include "8253.h" diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 669b1703eb9..dd0c65a5b5a 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1355,7 +1355,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) outw(devpriv->adc_fifo_bits | LADFUL, devpriv->control_status + INT_ADCFIFO); spin_unlock_irqrestore(&dev->spinlock, flags); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; } comedi_handle_events(dev, s); diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index eddb7ace43d..5b43e4e6d03 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -439,6 +439,29 @@ static const struct comedi_lrange ai_ranges_64xx = { } }; +static const uint8_t ai_range_code_64xx[8] = { + 0x0, 0x1, 0x2, 0x3, /* bipolar 10, 5, 2,5, 1.25 */ + 0x8, 0x9, 0xa, 0xb /* unipolar 10, 5, 2.5, 1.25 */ +}; + +/* analog input ranges for 64-Mx boards */ +static const struct comedi_lrange ai_ranges_64_mx = { + 7, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; + +static const uint8_t ai_range_code_64_mx[7] = { + 0x0, 0x1, 0x2, 0x3, /* bipolar 5, 2.5, 1.25, 0.625 */ + 0x9, 0xa, 0xb /* unipolar 5, 2.5, 1.25 */ +}; + /* analog input ranges for 60xx boards */ static const struct comedi_lrange ai_ranges_60xx = { 4, { @@ -449,6 +472,10 @@ static const struct comedi_lrange ai_ranges_60xx = { } }; +static const uint8_t ai_range_code_60xx[4] = { + 0x0, 0x1, 0x4, 0x7 /* bipolar 10, 5, 0.5, 0.05 */ +}; + /* analog input ranges for 6030, etc boards */ static const struct comedi_lrange ai_ranges_6030 = { 14, { @@ -469,6 +496,11 @@ static const struct comedi_lrange ai_ranges_6030 = { } }; +static const uint8_t ai_range_code_6030[14] = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, /* bip 10, 5, 2, 1, 0.5, 0.2, 0.1 */ + 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* uni 10, 5, 2, 1, 0.5, 0.2, 0.1 */ +}; + /* analog input ranges for 6052, etc boards */ static const struct comedi_lrange ai_ranges_6052 = { 15, { @@ -490,6 +522,11 @@ static const struct comedi_lrange ai_ranges_6052 = { } }; +static const uint8_t ai_range_code_6052[15] = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, /* bipolar 10 ... 0.05 */ + 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* unipolar 10 ... 0.1 */ +}; + /* analog input ranges for 4020 board */ static const struct comedi_lrange ai_ranges_4020 = { 2, { @@ -593,6 +630,7 @@ struct pcidas64_board { int ai_bits; /* analog input resolution */ int ai_speed; /* fastest conversion period in ns */ const struct comedi_lrange *ai_range_table; + const uint8_t *ai_range_code; int ao_nchan; /* number of analog out channels */ int ao_bits; /* analog output resolution */ int ao_scan_speed; /* analog output scan speed */ @@ -651,6 +689,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_64XX, .ai_range_table = &ai_ranges_64xx, + .ai_range_code = ai_range_code_64xx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -666,6 +705,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_64XX, .ai_range_table = &ai_ranges_64xx, + .ai_range_code = ai_range_code_64xx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -680,7 +720,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -695,7 +736,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -710,7 +752,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -725,6 +768,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -740,6 +784,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -754,6 +799,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -769,6 +815,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -784,6 +831,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -799,6 +847,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -812,6 +861,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ai_fifo = &ai_fifo_60xx, .has_8255 = 0, }, @@ -823,6 +873,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ai_fifo = &ai_fifo_60xx, .has_8255 = 0, }, @@ -835,6 +886,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 0, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ai_fifo = &ai_fifo_60xx, .has_8255 = 0, }, @@ -848,6 +900,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -863,6 +916,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -878,6 +932,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 1000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -893,6 +948,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 3333, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -908,6 +964,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 1000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -923,6 +980,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 1000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -957,6 +1015,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_64XX, .ai_range_table = &ai_ranges_64xx, + .ai_range_code = ai_range_code_64xx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -968,7 +1027,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -980,7 +1040,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -992,7 +1053,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1004,7 +1066,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 2, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1016,7 +1079,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 2, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1028,7 +1092,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 2, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1115,45 +1180,8 @@ static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, unsigned int range_index) { const struct pcidas64_board *thisboard = dev->board_ptr; - const struct comedi_krange *range = - &thisboard->ai_range_table->range[range_index]; - unsigned int bits = 0; - switch (range->max) { - case 10000000: - bits = 0x000; - break; - case 5000000: - bits = 0x100; - break; - case 2000000: - case 2500000: - bits = 0x200; - break; - case 1000000: - case 1250000: - bits = 0x300; - break; - case 500000: - bits = 0x400; - break; - case 200000: - case 250000: - bits = 0x500; - break; - case 100000: - bits = 0x600; - break; - case 50000: - bits = 0x700; - break; - default: - dev_err(dev->class_dev, "bug! in %s\n", __func__); - break; - } - if (range->min == 0) - bits += 0x900; - return bits; + return thisboard->ai_range_code[range_index] << 8; } static unsigned int hw_revision(const struct comedi_device *dev, @@ -2776,7 +2804,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, /* check for fifo overrun */ if (status & ADC_OVERRUN_BIT) { dev_err(dev->class_dev, "fifo overrun\n"); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; } /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 01875d7c376..2b2cfcdda5b 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -22,12 +22,10 @@ /* * Driver: cb_pcidda * Description: MeasurementComputing PCI-DDA series - * Devices: (Measurement Computing) PCI-DDA08/12 [pci-dda08/12] - * (Measurement Computing) PCI-DDA04/12 [pci-dda04/12] - * (Measurement Computing) PCI-DDA02/12 [pci-dda02/12] - * (Measurement Computing) PCI-DDA08/16 [pci-dda08/16] - * (Measurement Computing) PCI-DDA04/16 [pci-dda04/16] - * (Measurement Computing) PCI-DDA02/16 [pci-dda02/16] + * Devices: [Measurement Computing] PCI-DDA08/12 (pci-dda08/12), + * PCI-DDA04/12 (pci-dda04/12), PCI-DDA02/12 (pci-dda02/12), + * PCI-DDA08/16 (pci-dda08/16), PCI-DDA04/16 (pci-dda04/16), + * PCI-DDA02/16 (pci-dda02/16) * Author: Ivan Martinez <ivanmr@altavista.com> * Frank Mori Hess <fmhess@users.sourceforge.net> * Status: works diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 85b2f4ab1ba..221d3819c96 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -261,6 +261,7 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it) { /* Append dev:subdev to devpriv->name */ char buf[20]; + snprintf(buf, sizeof(buf), "%u:%u ", bdev->minor, bdev->subdev); strlcat(devpriv->name, buf, diff --git a/drivers/staging/comedi/drivers/comedi_isadma.c b/drivers/staging/comedi/drivers/comedi_isadma.c new file mode 100644 index 00000000000..dbdea71d6b9 --- /dev/null +++ b/drivers/staging/comedi/drivers/comedi_isadma.c @@ -0,0 +1,262 @@ +/* + * COMEDI ISA DMA support functions + * Copyright (c) 2014 H Hartley Sweeten <hsweeten@visionengravers.com> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <asm/dma.h> + +#include "../comedidev.h" + +#include "comedi_isadma.h" + +/** + * comedi_isadma_program - program and enable an ISA DMA transfer + * @desc: the ISA DMA cookie to program and enable + */ +void comedi_isadma_program(struct comedi_isadma_desc *desc) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(desc->chan); + set_dma_mode(desc->chan, desc->mode); + set_dma_addr(desc->chan, desc->hw_addr); + set_dma_count(desc->chan, desc->size); + enable_dma(desc->chan); + release_dma_lock(flags); +} +EXPORT_SYMBOL_GPL(comedi_isadma_program); + +/** + * comedi_isadma_disable - disable the ISA DMA channel + * @dma_chan: the DMA channel to disable + * + * Returns the residue (remaining bytes) left in the DMA transfer. + */ +unsigned int comedi_isadma_disable(unsigned int dma_chan) +{ + unsigned long flags; + unsigned int residue; + + flags = claim_dma_lock(); + disable_dma(dma_chan); + residue = get_dma_residue(dma_chan); + release_dma_lock(flags); + + return residue; +} +EXPORT_SYMBOL_GPL(comedi_isadma_disable); + +/** + * comedi_isadma_disable_on_sample - disable the ISA DMA channel + * @dma_chan: the DMA channel to disable + * @size: the sample size (in bytes) + * + * Returns the residue (remaining bytes) left in the DMA transfer. + */ +unsigned int comedi_isadma_disable_on_sample(unsigned int dma_chan, + unsigned int size) +{ + int stalled = 0; + unsigned long flags; + unsigned int residue; + unsigned int new_residue; + + residue = comedi_isadma_disable(dma_chan); + while (residue % size) { + /* residue is a partial sample, enable DMA to allow more data */ + flags = claim_dma_lock(); + enable_dma(dma_chan); + release_dma_lock(flags); + + udelay(2); + new_residue = comedi_isadma_disable(dma_chan); + + /* is DMA stalled? */ + if (new_residue == residue) { + stalled++; + if (stalled > 10) + break; + } + residue = new_residue; + stalled = 0; + } + return residue; +} +EXPORT_SYMBOL_GPL(comedi_isadma_disable_on_sample); + +/** + * comedi_isadma_poll - poll the current DMA transfer + * @dma: the ISA DMA to poll + * + * Returns the position (in bytes) of the current DMA transfer. + */ +unsigned int comedi_isadma_poll(struct comedi_isadma *dma) +{ + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned long flags; + unsigned int result; + unsigned int result1; + + flags = claim_dma_lock(); + clear_dma_ff(desc->chan); + if (!isa_dma_bridge_buggy) + disable_dma(desc->chan); + result = get_dma_residue(desc->chan); + /* + * Read the counter again and choose higher value in order to + * avoid reading during counter lower byte roll over if the + * isa_dma_bridge_buggy is set. + */ + result1 = get_dma_residue(desc->chan); + if (!isa_dma_bridge_buggy) + enable_dma(desc->chan); + release_dma_lock(flags); + + if (result < result1) + result = result1; + if (result >= desc->size || result == 0) + return 0; + else + return desc->size - result; +} +EXPORT_SYMBOL_GPL(comedi_isadma_poll); + +/** + * comedi_isadma_set_mode - set the ISA DMA transfer direction + * @desc: the ISA DMA cookie to set + * @dma_dir: the DMA direction + */ +void comedi_isadma_set_mode(struct comedi_isadma_desc *desc, char dma_dir) +{ + desc->mode = (dma_dir == COMEDI_ISADMA_READ) ? DMA_MODE_READ + : DMA_MODE_WRITE; +} +EXPORT_SYMBOL_GPL(comedi_isadma_set_mode); + +/** + * comedi_isadma_alloc - allocate and initialize the ISA DMA + * @dev: comedi_device struct + * @n_desc: the number of cookies to allocate + * @dma_chan: DMA channel for the first cookie + * @dma_chan2: DMA channel for the second cookie + * @maxsize: the size of the buffer to allocate for each cookie + * @dma_dir: the DMA direction + * + * Returns the allocated and initialized ISA DMA or NULL if anything fails. + */ +struct comedi_isadma *comedi_isadma_alloc(struct comedi_device *dev, + int n_desc, unsigned int dma_chan1, + unsigned int dma_chan2, + unsigned int maxsize, char dma_dir) +{ + struct comedi_isadma *dma = NULL; + struct comedi_isadma_desc *desc; + unsigned int dma_chans[2]; + int i; + + if (n_desc < 1 || n_desc > 2) + goto no_dma; + + dma = kzalloc(sizeof(*dma), GFP_KERNEL); + if (!dma) + goto no_dma; + + desc = kcalloc(n_desc, sizeof(*desc), GFP_KERNEL); + if (!desc) + goto no_dma; + dma->desc = desc; + dma->n_desc = n_desc; + + dma_chans[0] = dma_chan1; + if (dma_chan2 == 0 || dma_chan2 == dma_chan1) + dma_chans[1] = dma_chan1; + else + dma_chans[1] = dma_chan2; + + if (request_dma(dma_chans[0], dev->board_name)) + goto no_dma; + dma->chan = dma_chans[0]; + if (dma_chans[1] != dma_chans[0]) { + if (request_dma(dma_chans[1], dev->board_name)) + goto no_dma; + } + dma->chan2 = dma_chans[1]; + + for (i = 0; i < n_desc; i++) { + desc = &dma->desc[i]; + desc->chan = dma_chans[i]; + desc->maxsize = maxsize; + desc->virt_addr = dma_alloc_coherent(NULL, desc->maxsize, + &desc->hw_addr, + GFP_KERNEL); + if (!desc->virt_addr) + goto no_dma; + comedi_isadma_set_mode(desc, dma_dir); + } + + return dma; + +no_dma: + comedi_isadma_free(dma); + return NULL; +} +EXPORT_SYMBOL_GPL(comedi_isadma_alloc); + +/** + * comedi_isadma_free - free the ISA DMA + * @dma: the ISA DMA to free + */ +void comedi_isadma_free(struct comedi_isadma *dma) +{ + struct comedi_isadma_desc *desc; + int i; + + if (!dma) + return; + + if (dma->desc) { + for (i = 0; i < dma->n_desc; i++) { + desc = &dma->desc[i]; + if (desc->virt_addr) + dma_free_coherent(NULL, desc->maxsize, + desc->virt_addr, desc->hw_addr); + } + kfree(dma->desc); + } + if (dma->chan2 && dma->chan2 != dma->chan) + free_dma(dma->chan2); + if (dma->chan) + free_dma(dma->chan); + kfree(dma); +} +EXPORT_SYMBOL_GPL(comedi_isadma_free); + +static int __init comedi_isadma_init(void) +{ + return 0; +} +module_init(comedi_isadma_init); + +static void __exit comedi_isadma_exit(void) +{ +} +module_exit(comedi_isadma_exit); + +MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); +MODULE_DESCRIPTION("Comedi ISA DMA support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/comedi_isadma.h b/drivers/staging/comedi/drivers/comedi_isadma.h new file mode 100644 index 00000000000..c7c524faf59 --- /dev/null +++ b/drivers/staging/comedi/drivers/comedi_isadma.h @@ -0,0 +1,116 @@ +/* + * COMEDI ISA DMA support functions + * Copyright (c) 2014 H Hartley Sweeten <hsweeten@visionengravers.com> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _COMEDI_ISADMA_H +#define _COMEDI_ISADMA_H + +/* + * These are used to avoid issues when <asm/dma.h> and the DMA_MODE_ + * defines are not available. + */ +#define COMEDI_ISADMA_READ 0 +#define COMEDI_ISADMA_WRITE 1 + +/** + * struct comedi_isadma_desc - cookie for ISA DMA + * @virt_addr: virtual address of buffer + * @hw_addr: hardware (bus) address of buffer + * @chan: DMA channel + * @maxsize: allocated size of buffer (in bytes) + * @size: transfer size (in bytes) + * @mode: DMA_MODE_READ or DMA_MODE_WRITE + */ +struct comedi_isadma_desc { + void *virt_addr; + dma_addr_t hw_addr; + unsigned int chan; + unsigned int maxsize; + unsigned int size; + char mode; +}; + +/** + * struct comedi_isadma - ISA DMA data + * @desc: cookie for each DMA buffer + * @n_desc: the number of cookies + * @cur_dma: the current cookie in use + * @chan: the first DMA channel requested + * @chan2: the second DMA channel requested + */ +struct comedi_isadma { + struct comedi_isadma_desc *desc; + int n_desc; + int cur_dma; + unsigned int chan; + unsigned int chan2; +}; + +#if IS_ENABLED(CONFIG_ISA_DMA_API) + +void comedi_isadma_program(struct comedi_isadma_desc *); +unsigned int comedi_isadma_disable(unsigned int dma_chan); +unsigned int comedi_isadma_disable_on_sample(unsigned int dma_chan, + unsigned int size); +unsigned int comedi_isadma_poll(struct comedi_isadma *); +void comedi_isadma_set_mode(struct comedi_isadma_desc *, char dma_dir); + +struct comedi_isadma *comedi_isadma_alloc(struct comedi_device *, + int n_desc, unsigned int dma_chan1, + unsigned int dma_chan2, + unsigned int maxsize, char dma_dir); +void comedi_isadma_free(struct comedi_isadma *); + +#else /* !IS_ENABLED(CONFIG_ISA_DMA_API) */ + +static inline void comedi_isadma_program(struct comedi_isadma_desc *desc) +{ +} + +static inline unsigned int comedi_isadma_disable(unsigned int dma_chan) +{ + return 0; +} + +static inline unsigned int +comedi_isadma_disable_on_sample(unsigned int dma_chan, unsigned int size) +{ + return 0; +} + +static inline unsigned int comedi_isadma_poll(struct comedi_isadma *dma) +{ + return 0; +} + +static inline void comedi_isadma_set_mode(struct comedi_isadma_desc *desc, + char dma_dir) +{ +} + +static inline struct comedi_isadma * +comedi_isadma_alloc(struct comedi_device *dev, int n_desc, + unsigned int dma_chan1, unsigned int dma_chan2, + unsigned int maxsize, char dma_dir) +{ + return NULL; +} + +static inline void comedi_isadma_free(struct comedi_isadma *dma) +{ +} + +#endif /* !IS_ENABLED(CONFIG_ISA_DMA_API) */ + +#endif /* #ifndef _COMEDI_ISADMA_H */ diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 3bac903c862..ceef6931edb 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -24,7 +24,7 @@ * Description: Standard PC parallel port * Author: ds * Status: works in immediate mode - * Devices: (standard) parallel port [comedi_parport] + * Devices: [standard] parallel port (comedi_parport) * Updated: Tue, 30 Apr 2002 21:11:45 -0700 * * A cheap and easy way to get a few more digital I/O lines. Steal diff --git a/drivers/staging/comedi/drivers/dac02.c b/drivers/staging/comedi/drivers/dac02.c index beb36c8dd00..a6798ad8fa7 100644 --- a/drivers/staging/comedi/drivers/dac02.c +++ b/drivers/staging/comedi/drivers/dac02.c @@ -24,7 +24,7 @@ /* * Driver: dac02 * Description: Comedi driver for DAC02 compatible boards - * Devices: (Keithley Metrabyte) DAC-02 [dac02] + * Devices: [Keithley Metrabyte] DAC-02 (dac02) * Author: H Hartley Sweeten <hsweeten@visionengravers.com> * Updated: Tue, 11 Mar 2014 11:27:19 -0700 * Status: unknown diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 20a9f0eb72b..c78c0df9bbe 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -1,6 +1,6 @@ /* * comedi/drivers/das08.c - * comedi driver for common DAS08 support (used by ISA/PCI/PCMCIA drivers) + * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef <ds@schleef.org> @@ -18,21 +18,6 @@ * GNU General Public License for more details. */ -/* - * Driver: das08 - * Description: DAS-08 compatible boards - * Devices: various, see das08_isa, das08_cs, and das08_pci drivers - * Author: Warren Jasper, ds, Frank Hess - * Updated: Fri, 31 Aug 2012 19:19:06 +0100 - * Status: works - * - * This driver is used by the das08_isa, das08_cs, and das08_pci - * drivers to provide the common support for the DAS-08 hardware. - * - * The driver doesn't support asynchronous commands, since the - * cheap das08 hardware doesn't really support them. - */ - #include <linux/module.h> #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index f3ccc2ce6d4..93fab689016 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -41,10 +41,7 @@ Command support does not exist, but could be added for this board. #include <linux/module.h> -#include "../comedidev.h" - -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> +#include "../comedi_pcmcia.h" #include "das08.h" diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c index e4ba268e78a..2d9a31dab55 100644 --- a/drivers/staging/comedi/drivers/das08_isa.c +++ b/drivers/staging/comedi/drivers/das08_isa.c @@ -21,18 +21,12 @@ /* * Driver: das08_isa * Description: DAS-08 ISA/PC-104 compatible boards - * Devices: (Keithley Metrabyte) DAS08 [isa-das08], - * (ComputerBoards) DAS08 [isa-das08] - * (ComputerBoards) DAS08-PGM [das08-pgm] - * (ComputerBoards) DAS08-PGH [das08-pgh] - * (ComputerBoards) DAS08-PGL [das08-pgl] - * (ComputerBoards) DAS08-AOH [das08-aoh] - * (ComputerBoards) DAS08-AOL [das08-aol] - * (ComputerBoards) DAS08-AOM [das08-aom] - * (ComputerBoards) DAS08/JR-AO [das08/jr-ao] - * (ComputerBoards) DAS08/JR-16-AO [das08jr-16-ao] - * (ComputerBoards) PC104-DAS08 [pc104-das08] - * (ComputerBoards) DAS08/JR/16 [das08jr/16] + * Devices: [Keithley Metrabyte] DAS08 (isa-das08), + * [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm), + * DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh), + * DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao), + * DAS08/JR-16-AO (das08jr-16-ao), PC104-DAS08 (pc104-das08), + * DAS08/JR/16 (das08jr/16) * Author: Warren Jasper, ds, Frank Hess * Updated: Fri, 31 Aug 2012 19:19:06 +0100 * Status: works diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index 0987ce55494..b2ea10b848c 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -21,7 +21,7 @@ /* * Driver: das08_pci * Description: DAS-08 PCI compatible boards - * Devices: (ComputerBoards) PCI-DAS08 [pci-das08] + * Devices: [ComputerBoards] PCI-DAS08 (pci-das08) * Author: Warren Jasper, ds, Frank Hess * Updated: Fri, 31 Aug 2012 19:19:06 +0100 * Status: works diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 2436057304a..2c20311120f 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -22,28 +22,17 @@ * Driver: das16 * Description: DAS16 compatible boards * Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze - * Devices: (Keithley Metrabyte) DAS-16 [das-16] - * (Keithley Metrabyte) DAS-16G [das-16g] - * (Keithley Metrabyte) DAS-16F [das-16f] - * (Keithley Metrabyte) DAS-1201 [das-1201] - * (Keithley Metrabyte) DAS-1202 [das-1202] - * (Keithley Metrabyte) DAS-1401 [das-1401] - * (Keithley Metrabyte) DAS-1402 [das-1402] - * (Keithley Metrabyte) DAS-1601 [das-1601] - * (Keithley Metrabyte) DAS-1602 [das-1602] - * (ComputerBoards) PC104-DAS16/JR [pc104-das16jr] - * (ComputerBoards) PC104-DAS16JR/16 [pc104-das16jr/16] - * (ComputerBoards) CIO-DAS16 [cio-das16] - * (ComputerBoards) CIO-DAS16F [cio-das16/f] - * (ComputerBoards) CIO-DAS16/JR [cio-das16/jr] - * (ComputerBoards) CIO-DAS16JR/16 [cio-das16jr/16] - * (ComputerBoards) CIO-DAS1401/12 [cio-das1401/12] - * (ComputerBoards) CIO-DAS1402/12 [cio-das1402/12] - * (ComputerBoards) CIO-DAS1402/16 [cio-das1402/16] - * (ComputerBoards) CIO-DAS1601/12 [cio-das1601/12] - * (ComputerBoards) CIO-DAS1602/12 [cio-das1602/12] - * (ComputerBoards) CIO-DAS1602/16 [cio-das1602/16] - * (ComputerBoards) CIO-DAS16/330 [cio-das16/330] + * Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g), + * DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202), + * DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601), + * DAS-1602 (das-1602), + * [ComputerBoards] PC104-DAS16/JR (pc104-das16jr), + * PC104-DAS16JR/16 (pc104-das16jr/16), CIO-DAS16 (cio-das16), + * CIO-DAS16F (cio-das16/f), CIO-DAS16/JR (cio-das16/jr), + * CIO-DAS16JR/16 (cio-das16jr/16), CIO-DAS1401/12 (cio-das1401/12), + * CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16), + * CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12), + * CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330) * Status: works * Updated: 2003-10-12 * @@ -82,17 +71,14 @@ #include <linux/module.h> #include <linux/slab.h> -#include <linux/delay.h> -#include <linux/pci.h> #include <linux/interrupt.h> -#include <asm/dma.h> - #include "../comedidev.h" +#include "comedi_isadma.h" +#include "comedi_fc.h" #include "8253.h" #include "8255.h" -#include "comedi_fc.h" #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */ @@ -451,86 +437,37 @@ static inline int timer_period(void) } struct das16_private_struct { + struct comedi_isadma *dma; unsigned int clockbase; unsigned int ctrl_reg; - unsigned long adc_byte_count; unsigned int divisor1; unsigned int divisor2; - unsigned int dma_chan; - uint16_t *dma_buffer[2]; - dma_addr_t dma_buffer_addr[2]; - unsigned int current_buffer; - unsigned int dma_transfer_size; - struct comedi_lrange *user_ai_range_table; - struct comedi_lrange *user_ao_range_table; struct timer_list timer; - short timer_running; unsigned long extra_iobase; unsigned int can_burst:1; + unsigned int timer_running:1; }; -static void das16_ai_enable(struct comedi_device *dev, - unsigned int mode, unsigned int src) -{ - struct das16_private_struct *devpriv = dev->private; - - devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | - DAS16_CTRL_DMAE | - DAS16_CTRL_PACING_MASK); - devpriv->ctrl_reg |= mode; - - if (src == TRIG_EXT) - devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER; - else - devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER; - outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); -} - -static void das16_ai_disable(struct comedi_device *dev) +static void das16_ai_setup_dma(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int unread_samples) { struct das16_private_struct *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize); + unsigned int nsamples; - /* disable interrupts, dma and pacer clocked conversions */ - devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | - DAS16_CTRL_DMAE | - DAS16_CTRL_PACING_MASK); - outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); -} - -/* the pc104-das16jr (at least) has problems if the dma - transfer is interrupted in the middle of transferring - a 16 bit sample, so this function takes care to get - an even transfer count after disabling dma - channel. -*/ -static int disable_dma_on_even(struct comedi_device *dev) -{ - struct das16_private_struct *devpriv = dev->private; - static const int disable_limit = 100; - static const int enable_timeout = 100; - int residue; - int new_residue; - int i; - int j; - - disable_dma(devpriv->dma_chan); - residue = get_dma_residue(devpriv->dma_chan); - for (i = 0; i < disable_limit && (residue % 2); ++i) { - enable_dma(devpriv->dma_chan); - for (j = 0; j < enable_timeout; ++j) { - udelay(2); - new_residue = get_dma_residue(devpriv->dma_chan); - if (new_residue != residue) - break; - } - disable_dma(devpriv->dma_chan); - residue = get_dma_residue(devpriv->dma_chan); - } - if (i == disable_limit) { - dev_err(dev->class_dev, - "failed to get an even dma transfer, could be trouble\n"); + /* + * Determine dma size based on the buffer size plus the number of + * unread samples and the number of samples remaining in the command. + */ + nsamples = comedi_nsamples_left(s, max_samples + unread_samples); + if (nsamples > unread_samples) { + nsamples -= unread_samples; + desc->size = comedi_samples_to_bytes(s, nsamples); + comedi_isadma_program(desc); } - return residue; } static void das16_interrupt(struct comedi_device *dev) @@ -539,11 +476,12 @@ static void das16_interrupt(struct comedi_device *dev) struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; unsigned long spin_flags; - unsigned long dma_flags; + unsigned int residue; + unsigned int nbytes; unsigned int nsamples; - int num_bytes, residue; - int buffer_index; spin_lock_irqsave(&dev->spinlock, spin_flags); if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) { @@ -551,42 +489,36 @@ static void das16_interrupt(struct comedi_device *dev) return; } - dma_flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma_chan); - residue = disable_dma_on_even(dev); + /* + * The pc104-das16jr (at least) has problems if the dma + * transfer is interrupted in the middle of transferring + * a 16 bit sample. + */ + residue = comedi_isadma_disable_on_sample(desc->chan, + comedi_bytes_per_sample(s)); - /* figure out how many points to read */ - if (residue > devpriv->dma_transfer_size) { + /* figure out how many samples to read */ + if (residue > desc->size) { dev_err(dev->class_dev, "residue > transfer size!\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - num_bytes = 0; - } else - num_bytes = devpriv->dma_transfer_size - residue; - - if (cmd->stop_src == TRIG_COUNT && - num_bytes >= devpriv->adc_byte_count) { - num_bytes = devpriv->adc_byte_count; - async->events |= COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; + nbytes = 0; + } else { + nbytes = desc->size - residue; } + nsamples = comedi_bytes_to_samples(s, nbytes); - buffer_index = devpriv->current_buffer; - devpriv->current_buffer = (devpriv->current_buffer + 1) % 2; - devpriv->adc_byte_count -= num_bytes; - - /* re-enable dma */ - if ((async->events & COMEDI_CB_EOA) == 0) { - set_dma_addr(devpriv->dma_chan, - devpriv->dma_buffer_addr[devpriv->current_buffer]); - set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); - enable_dma(devpriv->dma_chan); + /* restart DMA if more samples are needed */ + if (nsamples) { + dma->cur_dma = 1 - dma->cur_dma; + das16_ai_setup_dma(dev, s, nsamples); } - release_dma_lock(dma_flags); spin_unlock_irqrestore(&dev->spinlock, spin_flags); - nsamples = comedi_bytes_to_samples(s, num_bytes); - comedi_buf_write_samples(s, devpriv->dma_buffer[buffer_index], - nsamples); + comedi_buf_write_samples(s, desc->virt_addr, nsamples); + + if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) + async->events |= COMEDI_CB_EOA; comedi_handle_events(dev, s); } @@ -605,6 +537,29 @@ static void das16_timer_interrupt(unsigned long arg) spin_unlock_irqrestore(&dev->spinlock, flags); } +static void das16_ai_set_mux_range(struct comedi_device *dev, + unsigned int first_chan, + unsigned int last_chan, + unsigned int range) +{ + const struct das16_board *board = dev->board_ptr; + + /* set multiplexer */ + outb(first_chan | (last_chan << 4), dev->iobase + DAS16_MUX_REG); + + /* some boards do not have programmable gain */ + if (board->ai_pg == das16_pg_none) + return; + + /* + * Set gain (this is also burst rate register but according to + * computer boards manual, burst rate does nothing, even on + * keithley cards). + */ + outb((das16_gainlists[board->ai_pg])[range], + dev->iobase + DAS16_GAIN_REG); +} + static int das16_ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -755,13 +710,15 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + unsigned int first_chan = CR_CHAN(cmd->chanlist[0]); + unsigned int last_chan = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); + unsigned int range = CR_RANGE(cmd->chanlist[0]); unsigned int byte; unsigned long flags; - int range; if (cmd->flags & CMDF_PRIORITY) { dev_err(dev->class_dev, @@ -769,24 +726,11 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) return -1; } - devpriv->adc_byte_count = cmd->stop_arg * comedi_bytes_per_scan(s); - if (devpriv->can_burst) outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG); - /* set scan limits */ - byte = CR_CHAN(cmd->chanlist[0]); - byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4; - outb(byte, dev->iobase + DAS16_MUX_REG); - - /* set gain (this is also burst rate register but according to - * computer boards manual, burst rate does nothing, even on - * keithley cards) */ - if (board->ai_pg != das16_pg_none) { - range = CR_RANGE(cmd->chanlist[0]); - outb((das16_gainlists[board->ai_pg])[range], - dev->iobase + DAS16_GAIN_REG); - } + /* set mux and range for chanlist scan */ + das16_ai_set_mux_range(dev, first_chan, last_chan, range); /* set counter mode and counts */ cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags); @@ -805,19 +749,9 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) } outb(byte, dev->iobase + DAS16_PACER_REG); - /* set up dma transfer */ - flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma_chan); - devpriv->current_buffer = 0; - set_dma_addr(devpriv->dma_chan, - devpriv->dma_buffer_addr[devpriv->current_buffer]); - devpriv->dma_transfer_size = DAS16_DMA_SIZE; - set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); - enable_dma(devpriv->dma_chan); - release_dma_lock(flags); + /* set up dma transfer */ + dma->cur_dma = 0; + das16_ai_setup_dma(dev, s, 0); /* set up timer */ spin_lock_irqsave(&dev->spinlock, flags); @@ -825,7 +759,14 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->timer.expires = jiffies + timer_period(); add_timer(&devpriv->timer); - das16_ai_enable(dev, DAS16_CTRL_DMAE, cmd->convert_src); + /* enable DMA interrupt with external or internal pacing */ + devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_PACING_MASK); + devpriv->ctrl_reg |= DAS16_CTRL_DMAE; + if (cmd->convert_src == TRIG_EXT) + devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER; + else + devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER; + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); if (devpriv->can_burst) outb(0, dev->iobase + DAS1600_CONV_REG); @@ -837,12 +778,17 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct das16_private_struct *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); - das16_ai_disable(dev); - disable_dma(devpriv->dma_chan); + /* disable interrupts, dma and pacer clocked conversions */ + devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_DMAE | + DAS16_CTRL_PACING_MASK); + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); + + comedi_isadma_disable(dma->chan); /* disable SW timer */ if (devpriv->timer_running) { @@ -893,23 +839,14 @@ static int das16_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - const struct das16_board *board = dev->board_ptr; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); unsigned int val; int ret; int i; - das16_ai_disable(dev); - - /* set multiplexer */ - outb(chan | (chan << 4), dev->iobase + DAS16_MUX_REG); - - /* set gain */ - if (board->ai_pg != das16_pg_none) { - outb((das16_gainlists[board->ai_pg])[range], - dev->iobase + DAS16_GAIN_REG); - } + /* set mux and range for single channel */ + das16_ai_set_mux_range(dev, chan, chan, range); for (i = 0; i < insn->n; i++) { /* trigger conversion */ @@ -1001,14 +938,107 @@ static void das16_reset(struct comedi_device *dev) outb(0, dev->iobase + DAS16_TIMER_BASE_REG + i8254_control_reg); } +static void das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) +{ + struct das16_private_struct *devpriv = dev->private; + + /* only DMA channels 3 and 1 are valid */ + if (!(dma_chan == 1 || dma_chan == 3)) + return; + + /* DMA uses two buffers */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, + DAS16_DMA_SIZE, COMEDI_ISADMA_READ); + if (devpriv->dma) { + init_timer(&devpriv->timer); + devpriv->timer.function = das16_timer_interrupt; + devpriv->timer.data = (unsigned long)dev; + } +} + +static void das16_free_dma(struct comedi_device *dev) +{ + struct das16_private_struct *devpriv = dev->private; + + if (devpriv) { + if (devpriv->timer.data) + del_timer_sync(&devpriv->timer); + comedi_isadma_free(devpriv->dma); + } +} + +static const struct comedi_lrange *das16_ai_range(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_devconfig *it, + unsigned int pg_type, + unsigned int status) +{ + unsigned int min = it->options[4]; + unsigned int max = it->options[5]; + + /* get any user-defined input range */ + if (pg_type == das16_pg_none && (min || max)) { + struct comedi_lrange *lrange; + struct comedi_krange *krange; + + /* allocate single-range range table */ + lrange = comedi_alloc_spriv(s, + sizeof(*lrange) + sizeof(*krange)); + if (!lrange) + return &range_unknown; + + /* initialize ai range */ + lrange->length = 1; + krange = lrange->range; + krange->min = min; + krange->max = max; + krange->flags = UNIT_volt; + + return lrange; + } + + /* use software programmable range */ + if (status & DAS16_STATUS_UNIPOLAR) + return das16_ai_uni_lranges[pg_type]; + return das16_ai_bip_lranges[pg_type]; +} + +static const struct comedi_lrange *das16_ao_range(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_devconfig *it) +{ + unsigned int min = it->options[6]; + unsigned int max = it->options[7]; + + /* get any user-defined output range */ + if (min || max) { + struct comedi_lrange *lrange; + struct comedi_krange *krange; + + /* allocate single-range range table */ + lrange = comedi_alloc_spriv(s, + sizeof(*lrange) + sizeof(*krange)); + if (!lrange) + return &range_unknown; + + /* initialize ao range */ + lrange->length = 1; + krange = lrange->range; + krange->min = min; + krange->max = max; + krange->flags = UNIT_volt; + + return lrange; + } + + return &range_unknown; +} + static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv; struct comedi_subdevice *s; - struct comedi_lrange *lrange; - struct comedi_krange *krange; - unsigned int dma_chan = it->options[2]; unsigned int status; int ret; @@ -1063,72 +1093,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->clockbase = I8254_OSC_BASE_1MHZ; } - /* initialize dma */ - if (dma_chan == 1 || dma_chan == 3) { - unsigned long flags; - int i; - - if (request_dma(dma_chan, dev->board_name)) { - dev_err(dev->class_dev, - "failed to request dma channel %i\n", - dma_chan); - return -EINVAL; - } - devpriv->dma_chan = dma_chan; - - /* allocate dma buffers */ - for (i = 0; i < 2; i++) { - void *p; - - p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE, - &devpriv->dma_buffer_addr[i]); - if (!p) - return -ENOMEM; - devpriv->dma_buffer[i] = p; - } - - flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); - release_dma_lock(flags); - - init_timer(&devpriv->timer); - devpriv->timer.function = das16_timer_interrupt; - devpriv->timer.data = (unsigned long)dev; - } - - /* get any user-defined input range */ - if (board->ai_pg == das16_pg_none && - (it->options[4] || it->options[5])) { - /* allocate single-range range table */ - lrange = kzalloc(sizeof(*lrange) + sizeof(*krange), GFP_KERNEL); - if (!lrange) - return -ENOMEM; - - /* initialize ai range */ - devpriv->user_ai_range_table = lrange; - lrange->length = 1; - krange = devpriv->user_ai_range_table->range; - krange->min = it->options[4]; - krange->max = it->options[5]; - krange->flags = UNIT_volt; - } - - /* get any user-defined output range */ - if (it->options[6] || it->options[7]) { - /* allocate single-range range table */ - lrange = kzalloc(sizeof(*lrange) + sizeof(*krange), GFP_KERNEL); - if (!lrange) - return -ENOMEM; - - /* initialize ao range */ - devpriv->user_ao_range_table = lrange; - lrange->length = 1; - krange = devpriv->user_ao_range_table->range; - krange->min = it->options[6]; - krange->max = it->options[7]; - krange->flags = UNIT_volt; - } + das16_alloc_dma(dev, it->options[2]); ret = comedi_alloc_subdevices(dev, 4 + board->has_8255); if (ret) @@ -1149,15 +1114,9 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) } s->len_chanlist = s->n_chan; s->maxdata = board->ai_maxdata; - if (devpriv->user_ai_range_table) { /* user defined ai range */ - s->range_table = devpriv->user_ai_range_table; - } else if (status & DAS16_STATUS_UNIPOLAR) { - s->range_table = das16_ai_uni_lranges[board->ai_pg]; - } else { - s->range_table = das16_ai_bip_lranges[board->ai_pg]; - } + s->range_table = das16_ai_range(dev, s, it, board->ai_pg, status); s->insn_read = das16_ai_insn_read; - if (devpriv->dma_chan) { + if (devpriv->dma) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->do_cmdtest = das16_cmd_test; @@ -1173,7 +1132,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; s->maxdata = 0x0fff; - s->range_table = devpriv->user_ao_range_table; + s->range_table = das16_ao_range(dev, s, it); s->insn_write = das16_ao_insn_write; ret = comedi_alloc_subdev_readback(s); @@ -1230,25 +1189,11 @@ static void das16_detach(struct comedi_device *dev) { const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv = dev->private; - int i; if (devpriv) { - if (devpriv->timer.data) - del_timer_sync(&devpriv->timer); if (dev->iobase) das16_reset(dev); - - for (i = 0; i < 2; i++) { - if (devpriv->dma_buffer[i]) - pci_free_consistent(NULL, DAS16_DMA_SIZE, - devpriv->dma_buffer[i], - devpriv-> - dma_buffer_addr[i]); - } - if (devpriv->dma_chan) - free_dma(devpriv->dma_chan); - kfree(devpriv->user_ai_range_table); - kfree(devpriv->user_ao_range_table); + das16_free_dma(dev); if (devpriv->extra_iobase) release_region(devpriv->extra_iobase, diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index 80f41b7e827..3666a68979f 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -455,7 +455,7 @@ static void das16m1_handler(struct comedi_device *dev, unsigned int status) /* this probably won't catch overruns since the card doesn't generate * overrun interrupts, but we might as well try */ if (status & OVRUN) { - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; dev_err(dev->class_dev, "fifo overflow\n"); } diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index be825d21a18..0790a28828d 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -98,12 +98,12 @@ TODO: #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/io.h> -#include "../comedidev.h" -#include <asm/dma.h> +#include "../comedidev.h" -#include "8253.h" +#include "comedi_isadma.h" #include "comedi_fc.h" +#include "8253.h" /* misc. defines */ #define DAS1800_SIZE 16 /* uses 16 io addresses */ @@ -421,19 +421,14 @@ static const struct das1800_board das1800_boards[] = { }; struct das1800_private { + struct comedi_isadma *dma; unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */ unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */ int irq_dma_bits; /* bits for control register b */ /* dma bits for control register b, stored so that dma can be * turned on and off */ int dma_bits; - unsigned int dma0; /* dma channels used */ - unsigned int dma1; - unsigned int dma_current; /* dma channel currently in use */ - uint16_t *ai_buf0; /* pointers to dma buffers */ - uint16_t *ai_buf1; - uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */ - unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */ + uint16_t *fifo_buf; /* bounce buffer for analog input FIFO */ unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */ unsigned short ao_update_bits; /* remembers the last write to the * 'update' dac */ @@ -480,9 +475,9 @@ static void das1800_handle_fifo_half_full(struct comedi_device *dev, struct das1800_private *devpriv = dev->private; unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2); - insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, nsamples); - munge_data(dev, devpriv->ai_buf0, nsamples); - comedi_buf_write_samples(s, devpriv->ai_buf0, nsamples); + insw(dev->iobase + DAS1800_FIFO, devpriv->fifo_buf, nsamples); + munge_data(dev, devpriv->fifo_buf, nsamples); + comedi_buf_write_samples(s, devpriv->fifo_buf, nsamples); } static void das1800_handle_fifo_not_empty(struct comedi_device *dev, @@ -508,29 +503,21 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev, } } -/* Utility function used by das1800_flush_dma() and das1800_handle_dma(). - * Assumes dma lock is held */ +/* Utility function used by das1800_flush_dma() and das1800_handle_dma() */ static void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int channel, uint16_t *buffer) + struct comedi_isadma_desc *desc) { - struct das1800_private *devpriv = dev->private; - unsigned int nbytes; + unsigned int residue = comedi_isadma_disable(desc->chan); + unsigned int nbytes = desc->size - residue; unsigned int nsamples; - disable_dma(channel); - - /* clear flip-flop to make sure 2-byte registers - * get set correctly */ - clear_dma_ff(channel); - /* figure out how many points to read */ - nbytes = devpriv->dma_transfer_size - get_dma_residue(channel); nsamples = comedi_bytes_to_samples(s, nbytes); nsamples = comedi_nsamples_left(s, nsamples); - munge_data(dev, buffer, nsamples); - comedi_buf_write_samples(s, buffer, nsamples); + munge_data(dev, desc->virt_addr, nsamples); + comedi_buf_write_samples(s, desc->virt_addr, nsamples); } /* flushes remaining data from board when external trigger has stopped acquisition @@ -539,28 +526,19 @@ static void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; - unsigned long flags; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - flags = claim_dma_lock(); - das1800_flush_dma_channel(dev, s, devpriv->dma_current, - devpriv->dma_current_buf); + das1800_flush_dma_channel(dev, s, desc); if (dual_dma) { /* switch to other channel and flush it */ - if (devpriv->dma_current == devpriv->dma0) { - devpriv->dma_current = devpriv->dma1; - devpriv->dma_current_buf = devpriv->ai_buf1; - } else { - devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->ai_buf0; - } - das1800_flush_dma_channel(dev, s, devpriv->dma_current, - devpriv->dma_current_buf); + dma->cur_dma = 1 - dma->cur_dma; + desc = &dma->desc[dma->cur_dma]; + das1800_flush_dma_channel(dev, s, desc); } - release_dma_lock(flags); - /* get any remaining samples in fifo */ das1800_handle_fifo_not_empty(dev, s); } @@ -569,47 +547,41 @@ static void das1800_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int status) { struct das1800_private *devpriv = dev->private; - unsigned long flags; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - flags = claim_dma_lock(); - das1800_flush_dma_channel(dev, s, devpriv->dma_current, - devpriv->dma_current_buf); - /* re-enable dma channel */ - set_dma_addr(devpriv->dma_current, - virt_to_bus(devpriv->dma_current_buf)); - set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size); - enable_dma(devpriv->dma_current); - release_dma_lock(flags); + das1800_flush_dma_channel(dev, s, desc); + + /* re-enable dma channel */ + comedi_isadma_program(desc); if (status & DMATC) { /* clear DMATC interrupt bit */ outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS); /* switch dma channels for next time, if appropriate */ - if (dual_dma) { - /* read data from the other channel next time */ - if (devpriv->dma_current == devpriv->dma0) { - devpriv->dma_current = devpriv->dma1; - devpriv->dma_current_buf = devpriv->ai_buf1; - } else { - devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->ai_buf0; - } - } + if (dual_dma) + dma->cur_dma = 1 - dma->cur_dma; } } static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; + int i; outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */ outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */ outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */ - if (devpriv->dma0) - disable_dma(devpriv->dma0); - if (devpriv->dma1) - disable_dma(devpriv->dma1); + + for (i = 0; i < 2; i++) { + desc = &dma->desc[i]; + if (desc->chan) + comedi_isadma_disable(desc->chan); + } + return 0; } @@ -639,7 +611,7 @@ static void das1800_ai_handler(struct comedi_device *dev) /* clear OVF interrupt bit */ outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS); dev_err(dev->class_dev, "FIFO overflow\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return; } @@ -963,79 +935,64 @@ static void das1800_setup_counters(struct comedi_device *dev, } } -/* utility function that suggests a dma transfer size based on the conversion period 'ns' */ -static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd) +static unsigned int das1800_ai_transfer_size(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int maxbytes, + unsigned int ns) { - unsigned int size = DMA_BUF_SIZE; - static const int sample_size = 2; /* size in bytes of one sample from board */ - unsigned int fill_time = 300000000; /* target time in nanoseconds for filling dma buffer */ - unsigned int max_size; /* maximum size we will allow for a transfer */ + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes); + unsigned int samples; + + samples = max_samples; - /* make dma buffer fill in 0.3 seconds for timed modes */ + /* for timed modes, make dma buffer fill in 'ns' time */ switch (cmd->scan_begin_src) { - case TRIG_FOLLOW: /* not in burst mode */ + case TRIG_FOLLOW: /* not in burst mode */ if (cmd->convert_src == TRIG_TIMER) - size = (fill_time / cmd->convert_arg) * sample_size; + samples = ns / cmd->convert_arg; break; case TRIG_TIMER: - size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) * - sample_size; - break; - default: - size = DMA_BUF_SIZE; + samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len); break; } - /* set a minimum and maximum size allowed */ - max_size = DMA_BUF_SIZE; - /* if we are taking limited number of conversions, limit transfer size to that */ - if (cmd->stop_src == TRIG_COUNT && - cmd->stop_arg * cmd->chanlist_len * sample_size < max_size) - max_size = cmd->stop_arg * cmd->chanlist_len * sample_size; + /* limit samples to what is remaining in the command */ + samples = comedi_nsamples_left(s, samples); - if (size > max_size) - size = max_size; - if (size < sample_size) - size = sample_size; + if (samples > max_samples) + samples = max_samples; + if (samples < 1) + samples = 1; - return size; + return comedi_samples_to_bytes(s, samples); } -/* sets up dma */ -static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) +static void das1800_ai_setup_dma(struct comedi_device *dev, + struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; - unsigned long lock_flags; - const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; + unsigned int bytes; if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0) return; - /* determine a reasonable dma transfer size */ - devpriv->dma_transfer_size = suggest_transfer_size(cmd); - lock_flags = claim_dma_lock(); - disable_dma(devpriv->dma0); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma0); - set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0)); - /* set appropriate size of transfer */ - set_dma_count(devpriv->dma0, devpriv->dma_transfer_size); - devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->ai_buf0; - enable_dma(devpriv->dma0); - /* set up dual dma if appropriate */ - if (dual_dma) { - disable_dma(devpriv->dma1); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma1); - set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1)); - /* set appropriate size of transfer */ - set_dma_count(devpriv->dma1, devpriv->dma_transfer_size); - enable_dma(devpriv->dma1); + dma->cur_dma = 0; + + /* determine a dma transfer size to fill buffer in 0.3 sec */ + bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000); + + desc->size = bytes; + comedi_isadma_program(desc); + + /* set up dual dma if appropriate */ + if (devpriv->irq_dma_bits & DMA_DUAL) { + desc = &dma->desc[1]; + desc->size = bytes; + comedi_isadma_program(desc); } - release_dma_lock(lock_flags); } /* programs channel/gain list into card */ @@ -1097,7 +1054,7 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, /* setup card and start */ program_chanlist(dev, cmd); das1800_setup_counters(dev, cmd); - setup_dma(dev, cmd); + das1800_ai_setup_dma(dev, s); outb(control_c, dev->iobase + DAS1800_CONTROL_C); /* set conversion rate and length for burst mode */ if (control_c & BMDE) { @@ -1234,79 +1191,57 @@ static int das1800_do_wbits(struct comedi_device *dev, return insn->n; } -static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, - unsigned int dma1) +static void das1800_init_dma(struct comedi_device *dev, + struct comedi_devconfig *it) { struct das1800_private *devpriv = dev->private; - unsigned long flags; + unsigned int *dma_chan; - /* need an irq to do dma */ - if (dev->irq && dma0) { - /* encode dma0 and dma1 into 2 digit hexadecimal for switch */ - switch ((dma0 & 0x7) | (dma1 << 4)) { - case 0x5: /* dma0 == 5 */ - devpriv->dma_bits |= DMA_CH5; - break; - case 0x6: /* dma0 == 6 */ - devpriv->dma_bits |= DMA_CH6; - break; - case 0x7: /* dma0 == 7 */ - devpriv->dma_bits |= DMA_CH7; - break; - case 0x65: /* dma0 == 5, dma1 == 6 */ - devpriv->dma_bits |= DMA_CH5_CH6; - break; - case 0x76: /* dma0 == 6, dma1 == 7 */ - devpriv->dma_bits |= DMA_CH6_CH7; - break; - case 0x57: /* dma0 == 7, dma1 == 5 */ - devpriv->dma_bits |= DMA_CH7_CH5; - break; - default: - dev_err(dev->class_dev, - "only supports dma channels 5 through 7\n"); - dev_err(dev->class_dev, - "Dual dma only allows the following combinations:\n"); - dev_err(dev->class_dev, - "dma 5,6 / 6,7 / or 7,5\n"); - return -EINVAL; - } - if (request_dma(dma0, dev->driver->driver_name)) { - dev_err(dev->class_dev, - "failed to allocate dma channel %i\n", dma0); - return -EINVAL; - } - devpriv->dma0 = dma0; - devpriv->dma_current = dma0; - if (dma1) { - if (request_dma(dma1, dev->driver->driver_name)) { - dev_err(dev->class_dev, - "failed to allocate dma channel %i\n", - dma1); - return -EINVAL; - } - devpriv->dma1 = dma1; - } - devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if (devpriv->ai_buf0 == NULL) - return -ENOMEM; - devpriv->dma_current_buf = devpriv->ai_buf0; - if (dma1) { - devpriv->ai_buf1 = - kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if (devpriv->ai_buf1 == NULL) - return -ENOMEM; - } - flags = claim_dma_lock(); - disable_dma(devpriv->dma0); - set_dma_mode(devpriv->dma0, DMA_MODE_READ); - if (dma1) { - disable_dma(devpriv->dma1); - set_dma_mode(devpriv->dma1, DMA_MODE_READ); - } - release_dma_lock(flags); + /* + * it->options[2] is DMA channel 0 + * it->options[3] is DMA channel 1 + * + * Encode the DMA channels into 2 digit hexadecimal for switch. + */ + dma_chan = &it->options[2]; + + switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) { + case 0x5: /* dma0 == 5 */ + devpriv->dma_bits = DMA_CH5; + break; + case 0x6: /* dma0 == 6 */ + devpriv->dma_bits = DMA_CH6; + break; + case 0x7: /* dma0 == 7 */ + devpriv->dma_bits = DMA_CH7; + break; + case 0x65: /* dma0 == 5, dma1 == 6 */ + devpriv->dma_bits = DMA_CH5_CH6; + break; + case 0x76: /* dma0 == 6, dma1 == 7 */ + devpriv->dma_bits = DMA_CH6_CH7; + break; + case 0x57: /* dma0 == 7, dma1 == 5 */ + devpriv->dma_bits = DMA_CH7_CH5; + break; + default: + return; } - return 0; + + /* DMA can use 1 or 2 buffers, each with a separate channel */ + devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1, + dma_chan[0], dma_chan[1], + DMA_BUF_SIZE, COMEDI_ISADMA_READ); + if (!devpriv->dma) + devpriv->dma_bits = 0; +} + +static void das1800_free_dma(struct comedi_device *dev) +{ + struct das1800_private *devpriv = dev->private; + + if (devpriv) + comedi_isadma_free(devpriv->dma); } static int das1800_probe(struct comedi_device *dev) @@ -1374,8 +1309,6 @@ static int das1800_attach(struct comedi_device *dev, struct das1800_private *devpriv; struct comedi_subdevice *s; unsigned int irq = it->options[1]; - unsigned int dma0 = it->options[2]; - unsigned int dma1 = it->options[3]; int board; int ret; @@ -1437,16 +1370,13 @@ static int das1800_attach(struct comedi_device *dev, } } - ret = das1800_init_dma(dev, dma0, dma1); - if (ret < 0) - return ret; + /* an irq and one dma channel is required to use dma */ + if (dev->irq & it->options[2]) + das1800_init_dma(dev, it); - if (devpriv->ai_buf0 == NULL) { - devpriv->ai_buf0 = - kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL); - if (devpriv->ai_buf0 == NULL) - return -ENOMEM; - } + devpriv->fifo_buf = kmalloc_array(FIFO_SIZE, sizeof(uint16_t), GFP_KERNEL); + if (!devpriv->fifo_buf) + return -ENOMEM; ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -1523,13 +1453,9 @@ static void das1800_detach(struct comedi_device *dev) { struct das1800_private *devpriv = dev->private; + das1800_free_dma(dev); if (devpriv) { - if (devpriv->dma0) - free_dma(devpriv->dma0); - if (devpriv->dma1) - free_dma(devpriv->dma1); - kfree(devpriv->ai_buf0); - kfree(devpriv->ai_buf1); + kfree(devpriv->fifo_buf); if (devpriv->iobase2) release_region(devpriv->iobase2, DAS1800_SIZE); } diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 780f4f646ea..b8755b50a11 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -20,8 +20,8 @@ /* * Driver: das6402 * Description: Keithley Metrabyte DAS6402 (& compatibles) - * Devices: (Keithley Metrabyte) DAS6402-12 (das6402-12) - * (Keithley Metrabyte) DAS6402-16 (das6402-16) + * Devices: [Keithley Metrabyte] DAS6402-12 (das6402-12), + * DAS6402-16 (das6402-16) * Author: H Hartley Sweeten <hsweeten@visionengravers.com> * Updated: Fri, 14 Mar 2014 10:18:43 -0700 * Status: unknown diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index e5bdc242344..ff7f4be3f31 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -511,7 +511,7 @@ static irqreturn_t das800_interrupt(int irq, void *d) if (fifo_overflow) { spin_unlock_irqrestore(&dev->spinlock, irq_flags); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return IRQ_HANDLED; } diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 6df298a99cc..1af006609fc 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -19,7 +19,7 @@ /* * Driver: dmm32at * Description: Diamond Systems Diamond-MM-32-AT - * Devices: (Diamond Systems) Diamond-MM-32-AT [dmm32at] + * Devices: [Diamond Systems] Diamond-MM-32-AT (dmm32at) * Author: Perry J. Piplani <perry.j.piplani@nasa.gov> * Updated: Fri Jun 4 09:13:24 CDT 2004 * Status: experimental @@ -365,7 +365,7 @@ static void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) /* enable the ai conversion interrupt and the clock to start scans */ outb(DMM32AT_INTCLK_ADINT | DMM32AT_INTCLK_CLKEN | DMM32AT_INTCLK_CLKSEL, - dev->iobase + DMM32AT_INTCLK_REG); + dev->iobase + DMM32AT_INTCLK_REG); } static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 2be98bb9a80..db21d213585 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -20,22 +20,12 @@ * Driver: dt282x * Description: Data Translation DT2821 series (including DT-EZ) * Author: ds - * Devices: (Data Translation) DT2821 [dt2821] - * (Data Translation) DT2821-F-16SE [dt2821-f] - * (Data Translation) DT2821-F-8DI [dt2821-f] - * (Data Translation) DT2821-G-16SE [dt2821-g] - * (Data Translation) DT2821-G-8DI [dt2821-g] - * (Data Translation) DT2823 [dt2823] - * (Data Translation) DT2824-PGH [dt2824-pgh] - * (Data Translation) DT2824-PGL [dt2824-pgl] - * (Data Translation) DT2825 [dt2825] - * (Data Translation) DT2827 [dt2827] - * (Data Translation) DT2828 [dt2828] - * (Data Translation) DT2928 [dt2829] - * (Data Translation) DT21-EZ [dt21-ez] - * (Data Translation) DT23-EZ [dt23-ez] - * (Data Translation) DT24-EZ [dt24-ez] - * (Data Translation) DT24-EZ-PGL [dt24-ez-pgl] + * Devices: [Data Translation] DT2821 (dt2821), DT2821-F-16SE (dt2821-f), + * DT2821-F-8DI (dt2821-f), DT2821-G-16SE (dt2821-g), + * DT2821-G-8DI (dt2821-g), DT2823 (dt2823), DT2824-PGH (dt2824-pgh), + * DT2824-PGL (dt2824-pgl), DT2825 (dt2825), DT2827 (dt2827), + * DT2828 (dt2828), DT2928 (dt2829), DT21-EZ (dt21-ez), DT23-EZ (dt23-ez), + * DT24-EZ (dt24-ez), DT24-EZ-PGL (dt24-ez-pgl) * Status: complete * Updated: Wed, 22 Aug 2001 17:11:34 -0700 * @@ -66,15 +56,14 @@ */ #include <linux/module.h> -#include "../comedidev.h" - #include <linux/delay.h> #include <linux/gfp.h> #include <linux/interrupt.h> #include <linux/io.h> -#include <asm/dma.h> +#include "../comedidev.h" +#include "comedi_isadma.h" #include "comedi_fc.h" /* @@ -311,55 +300,36 @@ static const struct dt282x_board boardtypes[] = { }; struct dt282x_private { + struct comedi_isadma *dma; unsigned int ad_2scomp:1; - unsigned int divisor; - int dacsr; /* software copies of registers */ int adcsr; int supcsr; - int ntrig; int nread; - - struct { - int chan; - unsigned short *buf; /* DMA buffer */ - int size; /* size of current transfer */ - } dma[2]; - int dma_maxsize; /* max size of DMA transfer (in bytes) */ - int current_dma_index; int dma_dir; }; static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) { struct dt282x_private *devpriv = dev->private; - int dma_chan; - unsigned long dma_ptr; - unsigned long flags; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma_index]; if (!devpriv->ntrig) return 0; if (n == 0) - n = devpriv->dma_maxsize; + n = desc->maxsize; if (n > devpriv->ntrig * 2) n = devpriv->ntrig * 2; devpriv->ntrig -= n / 2; - devpriv->dma[dma_index].size = n; - dma_chan = devpriv->dma[dma_index].chan; - dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); - - set_dma_mode(dma_chan, DMA_MODE_READ); - flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_addr(dma_chan, dma_ptr); - set_dma_count(dma_chan, n); - release_dma_lock(flags); + desc->size = n; + comedi_isadma_set_mode(desc, devpriv->dma_dir); - enable_dma(dma_chan); + comedi_isadma_program(desc); return n; } @@ -367,22 +337,13 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) { struct dt282x_private *devpriv = dev->private; - int dma_chan; - unsigned long dma_ptr; - unsigned long flags; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma_index]; - devpriv->dma[dma_index].size = n; - dma_chan = devpriv->dma[dma_index].chan; - dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); + desc->size = n; + comedi_isadma_set_mode(desc, devpriv->dma_dir); - set_dma_mode(dma_chan, DMA_MODE_WRITE); - flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_addr(dma_chan, dma_ptr); - set_dma_count(dma_chan, n); - release_dma_lock(flags); - - enable_dma(dma_chan); + comedi_isadma_program(desc); return n; } @@ -390,9 +351,14 @@ static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) static void dt282x_disable_dma(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; + int i; - disable_dma(devpriv->dma[0].chan); - disable_dma(devpriv->dma[1].chan); + for (i = 0; i < 2; i++) { + desc = &dma->desc[i]; + comedi_isadma_disable(desc->chan); + } } static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags) @@ -454,11 +420,12 @@ static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev, int cur_dma) { struct dt282x_private *devpriv = dev->private; - void *ptr = devpriv->dma[cur_dma].buf; - unsigned int nsamples = comedi_bytes_to_samples(s, devpriv->dma_maxsize); + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[cur_dma]; + unsigned int nsamples = comedi_bytes_to_samples(s, desc->maxsize); unsigned int nbytes; - nbytes = comedi_buf_read_samples(s, ptr, nsamples); + nbytes = comedi_buf_read_samples(s, desc->virt_addr, nsamples); if (nbytes) dt282x_prep_ao_dma(dev, cur_dma, nbytes); else @@ -471,39 +438,37 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; - int cur_dma = devpriv->current_dma_index; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, dev->iobase + DT2821_SUPCSR_REG); - disable_dma(devpriv->dma[cur_dma].chan); - - devpriv->current_dma_index = 1 - cur_dma; + comedi_isadma_disable(desc->chan); - if (!dt282x_ao_setup_dma(dev, s, cur_dma)) + if (!dt282x_ao_setup_dma(dev, s, dma->cur_dma)) s->async->events |= COMEDI_CB_OVERFLOW; + + dma->cur_dma = 1 - dma->cur_dma; } static void dt282x_ai_dma_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; - int cur_dma = devpriv->current_dma_index; - void *ptr = devpriv->dma[cur_dma].buf; - int size = devpriv->dma[cur_dma].size; - unsigned int nsamples = comedi_bytes_to_samples(s, size); + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int nsamples = comedi_bytes_to_samples(s, desc->size); int ret; outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, dev->iobase + DT2821_SUPCSR_REG); - disable_dma(devpriv->dma[cur_dma].chan); - - devpriv->current_dma_index = 1 - cur_dma; + comedi_isadma_disable(desc->chan); - dt282x_munge(dev, s, ptr, size); - ret = comedi_buf_write_samples(s, ptr, nsamples); - if (ret != size) + dt282x_munge(dev, s, desc->virt_addr, desc->size); + ret = comedi_buf_write_samples(s, desc->virt_addr, nsamples); + if (ret != desc->size) return; devpriv->nread -= nsamples; @@ -524,7 +489,9 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev, } #endif /* restart the channel */ - dt282x_prep_ai_dma(dev, cur_dma, 0); + dt282x_prep_ai_dma(dev, dma->cur_dma, 0); + + dma->cur_dma = 1 - dma->cur_dma; } static irqreturn_t dt282x_interrupt(int irq, void *d) @@ -545,7 +512,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) dacsr = inw(dev->iobase + DT2821_DACSR_REG); supcsr = inw(dev->iobase + DT2821_SUPCSR_REG); if (supcsr & DT2821_SUPCSR_DMAD) { - if (devpriv->dma_dir == DMA_MODE_READ) + if (devpriv->dma_dir == COMEDI_ISADMA_READ) dt282x_ai_dma_interrupt(dev, s); else dt282x_ao_dma_interrupt(dev, s_ao); @@ -718,14 +685,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); - if (cmd->scan_begin_src == TRIG_FOLLOW) { - /* internal trigger */ - err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - } else { - /* external trigger */ - /* should be level/edge, hi/lo specification here */ - err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - } + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 4000); @@ -757,6 +717,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; int ret; @@ -778,8 +739,8 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg; devpriv->nread = devpriv->ntrig; - devpriv->dma_dir = DMA_MODE_READ; - devpriv->current_dma_index = 0; + devpriv->dma_dir = COMEDI_ISADMA_READ; + dma->cur_dma = 0; dt282x_prep_ai_dma(dev, 0, 0); if (devpriv->ntrig) { dt282x_prep_ai_dma(dev, 1, 0); @@ -942,6 +903,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; dt282x_disable_dma(dev); @@ -958,8 +920,8 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len; devpriv->nread = devpriv->ntrig; - devpriv->dma_dir = DMA_MODE_WRITE; - devpriv->current_dma_index = 0; + devpriv->dma_dir = COMEDI_ISADMA_WRITE; + dma->cur_dma = 0; outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG); @@ -1063,46 +1025,42 @@ static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x) return ai_range_table[x]; } -static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2) +static void dt282x_alloc_dma(struct comedi_device *dev, + struct comedi_devconfig *it) { struct dt282x_private *devpriv = dev->private; - int ret; + unsigned int irq_num = it->options[1]; + unsigned int dma_chan[2]; - ret = request_dma(dma1, "dt282x A"); - if (ret) - return -EBUSY; - devpriv->dma[0].chan = dma1; + if (it->options[2] < it->options[3]) { + dma_chan[0] = it->options[2]; + dma_chan[1] = it->options[3]; + } else { + dma_chan[0] = it->options[3]; + dma_chan[1] = it->options[2]; + } - ret = request_dma(dma2, "dt282x B"); - if (ret) - return -EBUSY; - devpriv->dma[1].chan = dma2; + if (!irq_num || dma_chan[0] == dma_chan[1] || + dma_chan[0] < 5 || dma_chan[0] > 7 || + dma_chan[1] < 5 || dma_chan[1] > 7) + return; - devpriv->dma_maxsize = PAGE_SIZE; - devpriv->dma[0].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - devpriv->dma[1].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) - return -ENOMEM; + if (request_irq(irq_num, dt282x_interrupt, 0, dev->board_name, dev)) + return; - return 0; + /* DMA uses two 4K buffers with separate DMA channels */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan[0], dma_chan[1], + PAGE_SIZE, 0); + if (!devpriv->dma) + free_irq(irq_num, dev); } static void dt282x_free_dma(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; - int i; - - if (!devpriv) - return; - for (i = 0; i < 2; i++) { - if (devpriv->dma[i].chan) - free_dma(devpriv->dma[i].chan); - if (devpriv->dma[i].buf) - free_page((unsigned long)devpriv->dma[i].buf); - devpriv->dma[i].chan = 0; - devpriv->dma[i].buf = NULL; - } + if (devpriv) + comedi_isadma_free(devpriv->dma); } static int dt282x_initialize(struct comedi_device *dev) @@ -1160,36 +1118,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; /* an IRQ and 2 DMA channels are required for async command support */ - if (it->options[1] && it->options[2] && it->options[3]) { - unsigned int irq = it->options[1]; - unsigned int dma1 = it->options[2]; - unsigned int dma2 = it->options[3]; - - if (dma2 < dma1) { - unsigned int swap; - - swap = dma1; - dma1 = dma2; - dma2 = swap; - } - - if (dma1 != dma2 && - dma1 >= 5 && dma1 <= 7 && - dma2 >= 5 && dma2 <= 7) { - ret = request_irq(irq, dt282x_interrupt, 0, - dev->board_name, dev); - if (ret == 0) { - dev->irq = irq; - - ret = dt282x_grab_dma(dev, dma1, dma2); - if (ret < 0) { - dt282x_free_dma(dev); - free_irq(dev->irq, dev); - dev->irq = 0; - } - } - } - } + dt282x_alloc_dma(dev, it); ret = comedi_alloc_subdevices(dev, 3); if (ret) diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 1d9a7a63e06..0aa51980e32 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -355,7 +355,7 @@ static irqreturn_t dt3k_interrupt(int irq, void *d) dt3k_ai_empty_fifo(dev, s); if (status & (DT3000_ADSWERR | DT3000_ADHWERR)) - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; debug_n_ints++; if (debug_n_ints >= 10) diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 06c601d8fdf..e11c216a4c8 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -42,9 +42,8 @@ for my needs. #include <linux/module.h> #include <linux/errno.h> #include <linux/uaccess.h> -#include <linux/usb.h> -#include "../comedidev.h" +#include "../comedi_usb.h" #define DT9812_DIAGS_BOARD_INFO_ADDR 0xFBFF #define DT9812_MAX_WRITE_CMD_PIPE_SIZE 32 diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index 1b6324c6eb2..6c1e442f6c8 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -14,24 +14,23 @@ */ /* - Driver: dyna_pci10xx - Devices: Dynalog India PCI DAQ Cards, http://www.dynalogindia.com/ - Author: Prashant Shah <pshah.mumbai@gmail.com> - Developed at Automation Labs, Chemical Dept., IIT Bombay, India. - Prof. Kannan Moudgalya <kannan@iitb.ac.in> - http://www.iitb.ac.in - Status: Stable - Version: 1.0 - Device Supported : - - Dynalog PCI 1050 - - Notes : - - Dynalog India Pvt. Ltd. does not have a registered PCI Vendor ID and - they are using the PLX Technlogies Vendor ID since that is the PCI Chip used - in the card. - - Dynalog India Pvt. Ltd. has provided the internal register specification for - their cards in their manuals. -*/ + * Driver: dyna_pci10xx + * Description: Dynalog India PCI DAQ Cards, http://www.dynalogindia.com/ + * Devices: [Dynalog] PCI-1050 (dyna_pci1050) + * Author: Prashant Shah <pshah.mumbai@gmail.com> + * Status: Stable + * + * Developed at Automation Labs, Chemical Dept., IIT Bombay, India. + * Prof. Kannan Moudgalya <kannan@iitb.ac.in> + * http://www.iitb.ac.in + * + * Notes : + * - Dynalog India Pvt. Ltd. does not have a registered PCI Vendor ID and + * they are using the PLX Technlogies Vendor ID since that is the PCI Chip + * used in the card. + * - Dynalog India Pvt. Ltd. has provided the internal register specification + * for their cards in their manuals. + */ #include <linux/module.h> #include <linux/delay.h> diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 0979f536ed3..deada9784b6 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -261,12 +261,12 @@ static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) if (hpdi_board_status & RX_OVERRUN_BIT) { dev_err(dev->class_dev, "rx fifo overrun\n"); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; } if (hpdi_board_status & RX_UNDERRUN_BIT) { dev_err(dev->class_dev, "rx fifo underrun\n"); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; } if (devpriv->dio_count == 0) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 1085d66935f..0768bc42a5d 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -9,7 +9,7 @@ /* * Driver: ii_pci20kc * Description: Intelligent Instruments PCI-20001C carrier board - * Devices: (Intelligent Instrumentation) PCI-20001C [ii_pci20kc] + * Devices: [Intelligent Instrumentation] PCI-20001C (ii_pci20kc) * Author: Markus Kempf <kempf@matsci.uni-sb.de> * Status: works * diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h index 20478ae8fad..356811defaf 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.h +++ b/drivers/staging/comedi/drivers/jr3_pci.h @@ -261,8 +261,9 @@ struct intern_transform { } link[8]; }; -/* JR3 force/torque sensor data definition. For more information see sensor and */ -/* hardware manuals. */ +/* JR3 force/torque sensor data definition. For more information see sensor + * and hardware manuals. + */ struct jr3_channel { /* Raw_channels is the area used to store the raw data coming from */ diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 77e94a34b51..3c19e0f178c 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -19,7 +19,7 @@ /* * Driver: ke_counter * Description: Driver for Kolter Electronic Counter Card - * Devices: (Kolter Electronic) PCI Counter Card [ke_counter] + * Devices: [Kolter Electronic] PCI Counter Card (ke_counter) * Author: Michael Hillmann * Updated: Mon, 14 Apr 2008 15:42:42 +0100 * Status: tested diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 915685c1c85..d120aa244cf 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1068,7 +1068,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) ME4000_AI_CTRL_BIT_SC_IRQ); outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; dev_err(dev->class_dev, "FIFO overflow\n"); } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) @@ -1089,7 +1089,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) ME4000_AI_CTRL_BIT_SC_IRQ); outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; dev_err(dev->class_dev, "Undefined FIFO state\n"); } diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index b5278c11e62..92e23527f2c 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -19,8 +19,7 @@ /* * Driver: me_daq * Description: Meilhaus PCI data acquisition cards - * Devices: (Meilhaus) ME-2600i [me-2600i] - * (Meilhaus) ME-2000i [me-2000i] + * Devices: [Meilhaus] ME-2600i (me-2600i), ME-2000i (me-2000i) * Author: Michael Hillmann <hillmann@syscongroup.de> * Status: experimental * @@ -175,7 +174,7 @@ struct me_private_data { static inline void sleep(unsigned sec) { - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(sec * HZ); } diff --git a/drivers/staging/comedi/drivers/mf6x4.c b/drivers/staging/comedi/drivers/mf6x4.c index af21bc180c4..db972bce2b5 100644 --- a/drivers/staging/comedi/drivers/mf6x4.c +++ b/drivers/staging/comedi/drivers/mf6x4.c @@ -18,7 +18,7 @@ /* * Driver: mf6x4 * Description: Humusoft MF634 and MF624 Data acquisition card driver - * Devices: Humusoft MF634, Humusoft MF624 + * Devices: [Humusoft] MF634 (mf634), MF624 (mf624) * Author: Rostislav Lisovy <lisovy@gmail.com> * Status: works * Updated: diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index ffc9e61d6cd..1e537a5cf86 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -494,9 +494,7 @@ EXPORT_SYMBOL_GPL(mite_bytes_read_from_memory_ub); unsigned mite_dma_tcr(struct mite_channel *mite_chan) { struct mite_struct *mite = mite_chan->mite; - int lkar; - lkar = readl(mite->mite_io_addr + MITE_LKAR(mite_chan->channel)); return readl(mite->mite_io_addr + MITE_TCR(mite_chan->channel)); } EXPORT_SYMBOL_GPL(mite_dma_tcr); diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index f99847f3999..530f716f658 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -19,8 +19,7 @@ /* * Driver: ni_6527 * Description: National Instruments 6527 - * Devices: (National Instruments) PCI-6527 [pci-6527] - * (National Instruments) PXI-6527 [pxi-6527] + * Devices: [National Instruments] PCI-6527 (pci-6527), PXI-6527 (pxi-6527) * Author: David A. Schleef <ds@schleef.org> * Updated: Sat, 25 Jan 2003 13:24:40 -0800 * Status: works diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index bcb326e3156..67cb758eb0c 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -25,28 +25,14 @@ * Author: Jon Grierson <jd@renko.co.uk>, * Frank Mori Hess <fmhess@users.sourceforge.net> * Status: testing - * Devices: (National Instruments) PCI-6509 [ni_65xx] - * (National Instruments) PXI-6509 [ni_65xx] - * (National Instruments) PCI-6510 [ni_65xx] - * (National Instruments) PCI-6511 [ni_65xx] - * (National Instruments) PXI-6511 [ni_65xx] - * (National Instruments) PCI-6512 [ni_65xx] - * (National Instruments) PXI-6512 [ni_65xx] - * (National Instruments) PCI-6513 [ni_65xx] - * (National Instruments) PXI-6513 [ni_65xx] - * (National Instruments) PCI-6514 [ni_65xx] - * (National Instruments) PXI-6514 [ni_65xx] - * (National Instruments) PCI-6515 [ni_65xx] - * (National Instruments) PXI-6515 [ni_65xx] - * (National Instruments) PCI-6516 [ni_65xx] - * (National Instruments) PCI-6517 [ni_65xx] - * (National Instruments) PCI-6518 [ni_65xx] - * (National Instruments) PCI-6519 [ni_65xx] - * (National Instruments) PCI-6520 [ni_65xx] - * (National Instruments) PCI-6521 [ni_65xx] - * (National Instruments) PXI-6521 [ni_65xx] - * (National Instruments) PCI-6528 [ni_65xx] - * (National Instruments) PXI-6528 [ni_65xx] + * Devices: [National Instruments] PCI-6509 (pci-6509), PXI-6509 (pxi-6509), + * PCI-6510 (pci-6510), PCI-6511 (pci-6511), PXI-6511 (pxi-6511), + * PCI-6512 (pci-6512), PXI-6512 (pxi-6512), PCI-6513 (pci-6513), + * PXI-6513 (pxi-6513), PCI-6514 (pci-6514), PXI-6514 (pxi-6514), + * PCI-6515 (pxi-6515), PXI-6515 (pxi-6515), PCI-6516 (pci-6516), + * PCI-6517 (pci-6517), PCI-6518 (pci-6518), PCI-6519 (pci-6519), + * PCI-6520 (pci-6520), PCI-6521 (pci-6521), PXI-6521 (pxi-6521), + * PCI-6528 (pci-6528), PXI-6528 (pxi-6528) * Updated: Mon, 21 Jul 2014 12:49:58 +0000 * * Configuration Options: not applicable, uses PCI auto config diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 69e543a0bf2..a1ce0b0b8c4 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -62,14 +62,13 @@ TRIG_WAKE_EOS #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/slab.h> -#include "../comedidev.h" - #include <linux/io.h> -#include <asm/dma.h> +#include "../comedidev.h" -#include "8253.h" +#include "comedi_isadma.h" #include "comedi_fc.h" +#include "8253.h" #define A2150_DMA_BUFFER_SIZE 0xff00 /* size in bytes of dma buffer */ @@ -146,11 +145,8 @@ static const struct a2150_board a2150_boards[] = { }; struct a2150_private { - - volatile unsigned int count; /* number of data points left to be taken */ - unsigned int dma; /* dma channel */ - uint16_t *dma_buffer; /* dma buffer */ - unsigned int dma_transfer_size; /* size in bytes of dma transfers */ + struct comedi_isadma *dma; + unsigned int count; /* number of data points left to be taken */ int irq_dma_bits; /* irq/dma register bits */ int config_bits; /* config register bits */ }; @@ -158,68 +154,54 @@ struct a2150_private { /* interrupt service routine */ static irqreturn_t a2150_interrupt(int irq, void *d) { - int i; - int status; - unsigned long flags; struct comedi_device *dev = d; struct a2150_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; struct comedi_subdevice *s = dev->read_subdev; - struct comedi_async *async; - struct comedi_cmd *cmd; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned short *buf = desc->virt_addr; unsigned int max_points, num_points, residue, leftover; unsigned short dpnt; + int status; + int i; - if (!dev->attached) { - dev_err(dev->class_dev, "premature interrupt\n"); + if (!dev->attached) return IRQ_HANDLED; - } - /* initialize async here to make sure s is not NULL */ - async = s->async; - cmd = &async->cmd; status = inw(dev->iobase + STATUS_REG); - - if ((status & INTR_BIT) == 0) { - dev_err(dev->class_dev, "spurious interrupt\n"); + if ((status & INTR_BIT) == 0) return IRQ_NONE; - } if (status & OVFL_BIT) { - dev_err(dev->class_dev, "fifo overflow\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); } if ((status & DMA_TC_BIT) == 0) { - dev_err(dev->class_dev, - "caught non-dma interrupt? Aborting.\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return IRQ_HANDLED; } - flags = claim_dma_lock(); - disable_dma(devpriv->dma); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma); - - /* figure out how many points to read */ - max_points = comedi_bytes_to_samples(s, devpriv->dma_transfer_size); - /* residue is the number of points left to be done on the dma + /* + * residue is the number of bytes left to be done on the dma * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ - residue = comedi_bytes_to_samples(s, get_dma_residue(devpriv->dma)); - num_points = max_points - residue; + residue = comedi_isadma_disable(desc->chan); + + /* figure out how many points to read */ + max_points = comedi_bytes_to_samples(s, desc->size); + num_points = max_points - comedi_bytes_to_samples(s, residue); if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT) num_points = devpriv->count; /* figure out how many points will be stored next time */ leftover = 0; if (cmd->stop_src == TRIG_NONE) { - leftover = comedi_bytes_to_samples(s, - devpriv->dma_transfer_size); + leftover = comedi_bytes_to_samples(s, desc->size); } else if (devpriv->count > max_points) { leftover = devpriv->count - max_points; if (leftover > max_points) @@ -234,7 +216,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) for (i = 0; i < num_points; i++) { /* write data point to comedi buffer */ - dpnt = devpriv->dma_buffer[i]; + dpnt = buf[i]; /* convert from 2's complement to unsigned coding */ dpnt ^= 0x8000; comedi_buf_write_samples(s, &dpnt, 1); @@ -245,14 +227,11 @@ static irqreturn_t a2150_interrupt(int irq, void *d) } } } - /* re-enable dma */ + /* re-enable dma */ if (leftover) { - set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer)); - set_dma_count(devpriv->dma, - comedi_samples_to_bytes(s, leftover)); - enable_dma(devpriv->dma); + desc->size = comedi_samples_to_bytes(s, leftover); + comedi_isadma_program(desc); } - release_dma_lock(flags); comedi_handle_events(dev, s); @@ -265,13 +244,15 @@ static irqreturn_t a2150_interrupt(int irq, void *d) static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct a2150_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; /* disable dma on card */ devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT; outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); /* disable computer's dma */ - disable_dma(devpriv->dma); + comedi_isadma_disable(desc->chan); /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); @@ -503,10 +484,11 @@ static int a2150_ai_cmdtest(struct comedi_device *dev, static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct a2150_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned long timer_base = dev->iobase + I8253_BASE_REG; - unsigned long lock_flags; unsigned int old_config_bits = devpriv->config_bits; unsigned int trigger_bits; @@ -542,27 +524,19 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* initialize number of samples remaining */ devpriv->count = cmd->stop_arg * cmd->chanlist_len; - /* enable computer's dma */ - lock_flags = claim_dma_lock(); - disable_dma(devpriv->dma); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer)); + comedi_isadma_disable(desc->chan); + /* set size of transfer to fill in 1/3 second */ #define ONE_THIRD_SECOND 333333333 - devpriv->dma_transfer_size = - sizeof(devpriv->dma_buffer[0]) * cmd->chanlist_len * - ONE_THIRD_SECOND / cmd->scan_begin_arg; - if (devpriv->dma_transfer_size > A2150_DMA_BUFFER_SIZE) - devpriv->dma_transfer_size = A2150_DMA_BUFFER_SIZE; - if (devpriv->dma_transfer_size < sizeof(devpriv->dma_buffer[0])) - devpriv->dma_transfer_size = sizeof(devpriv->dma_buffer[0]); - devpriv->dma_transfer_size -= - devpriv->dma_transfer_size % sizeof(devpriv->dma_buffer[0]); - set_dma_count(devpriv->dma, devpriv->dma_transfer_size); - enable_dma(devpriv->dma); - release_dma_lock(lock_flags); + desc->size = comedi_bytes_per_sample(s) * cmd->chanlist_len * + ONE_THIRD_SECOND / cmd->scan_begin_arg; + if (desc->size > desc->maxsize) + desc->size = desc->maxsize; + if (desc->size < comedi_bytes_per_sample(s)) + desc->size = comedi_bytes_per_sample(s); + desc->size -= desc->size % comedi_bytes_per_sample(s); + + comedi_isadma_program(desc); /* clear dma interrupt before enabling it, to try and get rid of that * one spurious interrupt that has been happening */ @@ -677,6 +651,45 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return n; } +static void a2150_alloc_irq_and_dma(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct a2150_private *devpriv = dev->private; + unsigned int irq_num = it->options[1]; + unsigned int dma_chan = it->options[2]; + + /* + * Only IRQs 15, 14, 12-9, and 7-3 are valid. + * Only DMA channels 7-5 and 3-0 are valid. + */ + if (irq_num > 15 || dma_chan > 7 || + !((1 << irq_num) & 0xdef8) || !((1 << dma_chan) & 0xef)) + return; + + if (request_irq(irq_num, a2150_interrupt, 0, dev->board_name, dev)) + return; + + /* DMA uses 1 buffer */ + devpriv->dma = comedi_isadma_alloc(dev, 1, dma_chan, dma_chan, + A2150_DMA_BUFFER_SIZE, + COMEDI_ISADMA_READ); + if (!devpriv->dma) { + free_irq(irq_num, dev); + } else { + dev->irq = irq_num; + devpriv->irq_dma_bits = IRQ_LVL_BITS(irq_num) | + DMA_CHAN_BITS(dma_chan); + } +} + +static void a2150_free_dma(struct comedi_device *dev) +{ + struct a2150_private *devpriv = dev->private; + + if (devpriv) + comedi_isadma_free(devpriv->dma); +} + /* probes board type, returns offset */ static int a2150_probe(struct comedi_device *dev) { @@ -690,8 +703,6 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct a2150_board *thisboard; struct a2150_private *devpriv; struct comedi_subdevice *s; - unsigned int irq = it->options[1]; - unsigned int dma = it->options[2]; static const int timeout = 2000; int i; int ret; @@ -712,31 +723,8 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) thisboard = dev->board_ptr; dev->board_name = thisboard->name; - if ((irq >= 3 && irq <= 7) || (irq >= 9 && irq <= 12) || - irq == 14 || irq == 15) { - ret = request_irq(irq, a2150_interrupt, 0, - dev->board_name, dev); - if (ret == 0) { - devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq); - dev->irq = irq; - } - } - - if (dev->irq && dma <= 7 && dma != 4) { - ret = request_dma(dma, dev->board_name); - if (ret == 0) { - devpriv->dma = dma; - devpriv->dma_buffer = kmalloc(A2150_DMA_BUFFER_SIZE, - GFP_KERNEL | GFP_DMA); - if (!devpriv->dma_buffer) - return -ENOMEM; - - disable_dma(dma); - set_dma_mode(dma, DMA_MODE_READ); - - devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma); - } - } + /* an IRQ and DMA are required to support async commands */ + a2150_alloc_irq_and_dma(dev, it); ret = comedi_alloc_subdevices(dev, 1); if (ret) @@ -750,7 +738,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->maxdata = 0xffff; s->range_table = &range_a2150; s->insn_read = a2150_ai_rinsn; - if (dev->irq && devpriv->dma) { + if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->len_chanlist = s->n_chan; @@ -791,15 +779,9 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void a2150_detach(struct comedi_device *dev) { - struct a2150_private *devpriv = dev->private; - if (dev->iobase) outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG); - if (devpriv) { - if (devpriv->dma) - free_dma(devpriv->dma); - kfree(devpriv->dma_buffer); - } + a2150_free_dma(dev); comedi_legacy_detach(dev); }; diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 05370a4a74a..9eeaf3c5a85 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -19,8 +19,7 @@ /* * Driver: ni_at_ao * Description: National Instruments AT-AO-6/10 - * Devices: (National Instruments) AT-AO-6 [at-ao-6] - * (National Instruments) AT-AO-10 [at-ao-10] + * Devices: [National Instruments] AT-AO-6 (at-ao-6), AT-AO-10 (at-ao-10) * Status: should work * Author: David A. Schleef <ds@schleef.org> * Updated: Sun Dec 26 12:26:28 EST 2004 diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 0c5ff287dce..301f154be81 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -300,7 +300,6 @@ static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct ni_board_struct *boardtype; - struct ni_private *devpriv; struct pnp_dev *isapnp_dev; int ret; unsigned long iobase; @@ -310,7 +309,6 @@ static int ni_atmio_attach(struct comedi_device *dev, ret = ni_alloc_private(dev); if (ret) return ret; - devpriv = dev->private; iobase = it->options[0]; irq = it->options[1]; diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 5e472cb7fbd..8f6396edd21 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -51,10 +51,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> -#include "../comedidev.h" - -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> +#include "../comedi_pcmcia.h" /* daqcard700 registers */ #define DIO_W 0x04 /* WO 8bit */ diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 8cfabdbaa30..a208cb34843 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -32,11 +32,7 @@ the PCMCIA interface. */ #include <linux/module.h> -#include "../comedidev.h" - -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ds.h> +#include "../comedi_pcmcia.h" #include "8255.h" diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 1fbfdb4c80c..a916047791b 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -17,9 +17,8 @@ /* * Driver: ni_labpc * Description: National Instruments Lab-PC (& compatibles) - * Devices: (National Instruments) Lab-PC-1200 [lab-pc-1200] - * (National Instruments) Lab-PC-1200AI [lab-pc-1200ai] - * (National Instruments) Lab-PC+ [lab-pc+] + * Devices: [National Instruments] Lab-PC-1200 (lab-pc-1200), + * Lab-PC-1200AI (lab-pc-1200ai), Lab-PC+ (lab-pc+) * Author: Frank Mori Hess <fmhess@users.sourceforge.net> * Status: works * @@ -85,15 +84,10 @@ static const struct labpc_boardinfo labpc_boards[] = { static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct labpc_private *devpriv; unsigned int irq = it->options[1]; unsigned int dma_chan = it->options[2]; int ret; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - ret = comedi_request_region(dev, it->options[0], 0x20); if (ret) return ret; @@ -110,11 +104,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void labpc_detach(struct comedi_device *dev) { - struct labpc_private *devpriv = dev->private; - - if (devpriv) - labpc_free_dma_chan(dev); - + labpc_free_dma_chan(dev); comedi_legacy_detach(dev); } diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index ac2c01f9dfd..be89ae479af 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -35,6 +35,8 @@ struct labpc_boardinfo { }; struct labpc_private { + struct comedi_isadma *dma; + /* number of data points left to be taken */ unsigned long long count; /* software copys of bits written to command registers */ @@ -61,11 +63,7 @@ struct labpc_private { * conversions */ unsigned int divisor_b1; - unsigned int dma_chan; /* dma channel to use */ - u16 *dma_buffer; /* buffer ai will dma into */ - phys_addr_t dma_addr; - /* transfer size in bytes for current transfer */ - unsigned int dma_transfer_size; + /* we are using dma/fifo-half-full/etc. */ enum transfer_type current_transfer; /* diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index d89d5852aee..b88ee2614bf 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -368,10 +368,6 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, enum scan_mode mode) { struct labpc_private *devpriv = dev->private; - /* max value for 16 bit counter in mode 2 */ - const int max_counter_value = 0x10000; - /* min value for 16 bit counter in mode 2 */ - const int min_counter_value = 2; unsigned int base_period; unsigned int scan_period; unsigned int convert_period; @@ -388,11 +384,10 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, * clock speed on convert and scan counters) */ devpriv->divisor_b0 = (scan_period - 1) / - (I8254_OSC_BASE_2MHZ * max_counter_value) + 1; - if (devpriv->divisor_b0 < min_counter_value) - devpriv->divisor_b0 = min_counter_value; - if (devpriv->divisor_b0 > max_counter_value) - devpriv->divisor_b0 = max_counter_value; + (I8254_OSC_BASE_2MHZ * 0x10000) + 1; + + cfc_check_trigger_arg_min(&devpriv->divisor_b0, 2); + cfc_check_trigger_arg_max(&devpriv->divisor_b0, 0x10000); base_period = I8254_OSC_BASE_2MHZ * devpriv->divisor_b0; @@ -400,16 +395,16 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, switch (cmd->flags & CMDF_ROUND_MASK) { default: case CMDF_ROUND_NEAREST: - devpriv->divisor_a0 = - (convert_period + (base_period / 2)) / base_period; - devpriv->divisor_b1 = - (scan_period + (base_period / 2)) / base_period; + devpriv->divisor_a0 = DIV_ROUND_CLOSEST(convert_period, + base_period); + devpriv->divisor_b1 = DIV_ROUND_CLOSEST(scan_period, + base_period); break; case CMDF_ROUND_UP: - devpriv->divisor_a0 = - (convert_period + (base_period - 1)) / base_period; - devpriv->divisor_b1 = - (scan_period + (base_period - 1)) / base_period; + devpriv->divisor_a0 = DIV_ROUND_UP(convert_period, + base_period); + devpriv->divisor_b1 = DIV_ROUND_UP(scan_period, + base_period); break; case CMDF_ROUND_DOWN: devpriv->divisor_a0 = convert_period / base_period; @@ -417,14 +412,10 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, break; } /* make sure a0 and b1 values are acceptable */ - if (devpriv->divisor_a0 < min_counter_value) - devpriv->divisor_a0 = min_counter_value; - if (devpriv->divisor_a0 > max_counter_value) - devpriv->divisor_a0 = max_counter_value; - if (devpriv->divisor_b1 < min_counter_value) - devpriv->divisor_b1 = min_counter_value; - if (devpriv->divisor_b1 > max_counter_value) - devpriv->divisor_b1 = max_counter_value; + cfc_check_trigger_arg_min(&devpriv->divisor_a0, 2); + cfc_check_trigger_arg_max(&devpriv->divisor_a0, 0x10000); + cfc_check_trigger_arg_min(&devpriv->divisor_b1, 2); + cfc_check_trigger_arg_max(&devpriv->divisor_b1, 0x10000); /* write corrected timings to command */ labpc_set_ai_convert_period(cmd, mode, base_period * devpriv->divisor_a0); @@ -687,7 +678,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* figure out what method we will use to transfer data */ - if (labpc_have_dma_chan(dev) && + if (devpriv->dma && /* dma unsafe at RT priority, * and too much setup time for CMDF_WAKE_EOS */ (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY)) == 0) @@ -823,7 +814,7 @@ static int labpc_drain_fifo(struct comedi_device *dev) } if (i == timeout) { dev_err(dev->class_dev, "ai timeout, fifo never empties\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; return -1; } @@ -875,7 +866,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d) if (devpriv->stat1 & STAT1_OVERRUN) { /* clear error interrupt */ devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); dev_err(dev->class_dev, "overrun\n"); return IRQ_HANDLED; @@ -895,7 +886,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d) if (devpriv->stat1 & STAT1_OVERFLOW) { /* clear error interrupt */ devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); dev_err(dev->class_dev, "overflow\n"); return IRQ_HANDLED; @@ -1215,11 +1206,15 @@ int labpc_common_attach(struct comedi_device *dev, unsigned int irq, unsigned long isr_flags) { const struct labpc_boardinfo *board = dev->board_ptr; - struct labpc_private *devpriv = dev->private; + struct labpc_private *devpriv; struct comedi_subdevice *s; int ret; int i; + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) + return -ENOMEM; + if (dev->mmio) { devpriv->read_byte = labpc_readb; devpriv->write_byte = labpc_writeb; diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index 0a8b3223f74..746c4cd9978 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -54,19 +54,11 @@ NI manuals: */ #include <linux/module.h> -#include "../comedidev.h" -#include <linux/delay.h> +#include "../comedi_pcmcia.h" -#include "8253.h" -#include "8255.h" -#include "comedi_fc.h" #include "ni_labpc.h" -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ds.h> - static const struct labpc_boardinfo labpc_cs_boards[] = { { .name = "daqcard-1200", @@ -80,7 +72,6 @@ static int labpc_auto_attach(struct comedi_device *dev, unsigned long context) { struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); - struct labpc_private *devpriv; int ret; /* The ni_labpc driver needs the board_ptr */ @@ -96,10 +87,6 @@ static int labpc_auto_attach(struct comedi_device *dev, if (!link->irq) return -EINVAL; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - return labpc_common_attach(dev, link->irq, IRQF_SHARED); } diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 6d386050e59..6b4ccd86b3d 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -19,23 +19,25 @@ #include <linux/module.h> #include <linux/slab.h> -#include "../comedidev.h" -#include <asm/dma.h> +#include "../comedidev.h" +#include "comedi_isadma.h" #include "comedi_fc.h" #include "ni_labpc.h" #include "ni_labpc_regs.h" #include "ni_labpc_isadma.h" /* size in bytes of dma buffer */ -static const int dma_buffer_size = 0xff00; -/* 2 bytes per sample */ -static const int sample_size = 2; +#define LABPC_ISADMA_BUFFER_SIZE 0xff00 /* utility function that suggests a dma transfer size in bytes */ -static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) +static unsigned int labpc_suggest_transfer_size(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int maxbytes) { + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int sample_size = comedi_bytes_per_sample(s); unsigned int size; unsigned int freq; @@ -49,8 +51,8 @@ static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) size = (freq / 3) * sample_size; /* set a minimum and maximum size allowed */ - if (size > dma_buffer_size) - size = dma_buffer_size - dma_buffer_size % sample_size; + if (size > maxbytes) + size = maxbytes; else if (size < sample_size) size = sample_size; @@ -60,23 +62,18 @@ static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct labpc_private *devpriv = dev->private; + struct comedi_isadma_desc *desc = &devpriv->dma->desc[0]; struct comedi_cmd *cmd = &s->async->cmd; - unsigned long irq_flags; - - irq_flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma_chan); - set_dma_addr(devpriv->dma_chan, devpriv->dma_addr); + unsigned int sample_size = comedi_bytes_per_sample(s); + /* set appropriate size of transfer */ - devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd); + desc->size = labpc_suggest_transfer_size(dev, s, desc->maxsize); if (cmd->stop_src == TRIG_COUNT && - devpriv->count * sample_size < devpriv->dma_transfer_size) - devpriv->dma_transfer_size = devpriv->count * sample_size; - set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); - enable_dma(devpriv->dma_chan); - release_dma_lock(irq_flags); + devpriv->count * sample_size < desc->size) + desc->size = devpriv->count * sample_size; + + comedi_isadma_program(desc); + /* set CMD3 bits for caller to enable DMA and interrupt */ devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN); } @@ -85,61 +82,55 @@ EXPORT_SYMBOL_GPL(labpc_setup_dma); void labpc_drain_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; + struct comedi_isadma_desc *desc = &devpriv->dma->desc[0]; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - int status; - unsigned long flags; - unsigned int max_points, num_points, residue, leftover; + unsigned int max_samples = comedi_bytes_to_samples(s, desc->size); + unsigned int residue; + unsigned int nsamples; + unsigned int leftover; - status = devpriv->stat1; - - flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma_chan); - - /* figure out how many points to read */ - max_points = devpriv->dma_transfer_size / sample_size; - /* residue is the number of points left to be done on the dma + /* + * residue is the number of bytes left to be done on the dma * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ - residue = get_dma_residue(devpriv->dma_chan) / sample_size; - num_points = max_points - residue; - if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_points) - num_points = devpriv->count; - - /* figure out how many points will be stored next time */ - leftover = 0; - if (cmd->stop_src != TRIG_COUNT) { - leftover = devpriv->dma_transfer_size / sample_size; - } else if (devpriv->count > num_points) { - leftover = devpriv->count - num_points; - if (leftover > max_points) - leftover = max_points; - } - - comedi_buf_write_samples(s, devpriv->dma_buffer, num_points); + residue = comedi_isadma_disable(desc->chan); - if (cmd->stop_src == TRIG_COUNT) - devpriv->count -= num_points; + /* + * Figure out how many samples to read for this transfer and + * how many will be stored for next time. + */ + nsamples = max_samples - comedi_bytes_to_samples(s, residue); + if (cmd->stop_src == TRIG_COUNT) { + if (devpriv->count <= nsamples) { + nsamples = devpriv->count; + leftover = 0; + } else { + leftover = devpriv->count - nsamples; + if (leftover > max_samples) + leftover = max_samples; + } + devpriv->count -= nsamples; + } else { + leftover = max_samples; + } + desc->size = comedi_samples_to_bytes(s, leftover); - /* set address and count for next transfer */ - set_dma_addr(devpriv->dma_chan, devpriv->dma_addr); - set_dma_count(devpriv->dma_chan, leftover * sample_size); - release_dma_lock(flags); + comedi_buf_write_samples(s, desc->virt_addr, nsamples); } EXPORT_SYMBOL_GPL(labpc_drain_dma); static void handle_isa_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; + struct comedi_isadma_desc *desc = &devpriv->dma->desc[0]; labpc_drain_dma(dev); - enable_dma(devpriv->dma_chan); + if (desc->size) + comedi_isadma_program(desc); /* clear dma tc interrupt */ devpriv->write_byte(dev, 0x1, DMATC_CLEAR_REG); @@ -160,36 +151,18 @@ void labpc_handle_dma_status(struct comedi_device *dev) } EXPORT_SYMBOL_GPL(labpc_handle_dma_status); -int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) +void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { struct labpc_private *devpriv = dev->private; - void *dma_buffer; - unsigned long dma_flags; - int ret; + /* only DMA channels 3 and 1 are valid */ if (dma_chan != 1 && dma_chan != 3) - return -EINVAL; - - dma_buffer = kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA); - if (!dma_buffer) - return -ENOMEM; - - ret = request_dma(dma_chan, dev->board_name); - if (ret) { - kfree(dma_buffer); - return ret; - } - - devpriv->dma_buffer = dma_buffer; - devpriv->dma_chan = dma_chan; - devpriv->dma_addr = virt_to_bus(devpriv->dma_buffer); - - dma_flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); - release_dma_lock(dma_flags); + return; - return 0; + /* DMA uses 1 buffer */ + devpriv->dma = comedi_isadma_alloc(dev, 1, dma_chan, dma_chan, + LABPC_ISADMA_BUFFER_SIZE, + COMEDI_ISADMA_READ); } EXPORT_SYMBOL_GPL(labpc_init_dma_chan); @@ -197,12 +170,8 @@ void labpc_free_dma_chan(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - kfree(devpriv->dma_buffer); - devpriv->dma_buffer = NULL; - if (devpriv->dma_chan) { - free_dma(devpriv->dma_chan); - devpriv->dma_chan = 0; - } + if (devpriv) + comedi_isadma_free(devpriv->dma); } EXPORT_SYMBOL_GPL(labpc_free_dma_chan); diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h index 771af4bd5a7..b8a1b0ee629 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -5,18 +5,9 @@ #ifndef _NI_LABPC_ISADMA_H #define _NI_LABPC_ISADMA_H -#define NI_LABPC_HAVE_ISA_DMA IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISADMA) +#if IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISADMA) -#if NI_LABPC_HAVE_ISA_DMA - -static inline bool labpc_have_dma_chan(struct comedi_device *dev) -{ - struct labpc_private *devpriv = dev->private; - - return (bool)devpriv->dma_chan; -} - -int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); +void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); void labpc_free_dma_chan(struct comedi_device *dev); void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s); void labpc_drain_dma(struct comedi_device *dev); @@ -24,15 +15,9 @@ void labpc_handle_dma_status(struct comedi_device *dev); #else -static inline bool labpc_have_dma_chan(struct comedi_device *dev) -{ - return false; -} - -static inline int labpc_init_dma_chan(struct comedi_device *dev, - unsigned int dma_chan) +static inline void labpc_init_dma_chan(struct comedi_device *dev, + unsigned int dma_chan) { - return -ENOTSUPP; } static inline void labpc_free_dma_chan(struct comedi_device *dev) diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index 3fc42040656..0407ff681df 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -17,7 +17,7 @@ /* * Driver: ni_labpc_pci * Description: National Instruments Lab-PC PCI-1200 - * Devices: (National Instruments) PCI-1200 [ni_pci-1200] + * Devices: [National Instruments] PCI-1200 (ni_pci-1200) * Author: Frank Mori Hess <fmhess@users.sourceforge.net> * Status: works * @@ -79,7 +79,6 @@ static int labpc_pci_auto_attach(struct comedi_device *dev, { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct labpc_boardinfo *board = NULL; - struct labpc_private *devpriv; int ret; if (context < ARRAY_SIZE(labpc_pci_boards)) @@ -101,10 +100,6 @@ static int labpc_pci_auto_attach(struct comedi_device *dev, if (!dev->mmio) return -ENOMEM; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - return labpc_common_attach(dev, pcidev->irq, IRQF_SHARED); } diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 11e70173712..b6ddc015ded 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1478,7 +1478,7 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, dev_err(dev->class_dev, "unknown mite interrupt (ai_mite_status=%08x)\n", ai_mite_status); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; /* disable_irq(dev->irq); */ } #endif @@ -1491,8 +1491,7 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, /* we probably aren't even running a command now, * so it's a good idea to be careful. */ if (comedi_is_subdevice_running(s)) { - s->async->events |= - COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); } return; @@ -1579,7 +1578,7 @@ static void handle_b_interrupt(struct comedi_device *dev, dev_err(dev->class_dev, "unknown mite interrupt (ao_mite_status=%08x)\n", ao_mite_status); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; } #endif diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 9b201e48233..e3d821bf2d6 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -37,16 +37,12 @@ See the notes in the ni_atmio.o driver. */ #include <linux/module.h> -#include "../comedidev.h" - #include <linux/delay.h> +#include "../comedi_pcmcia.h" #include "ni_stc.h" #include "8255.h" -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> - /* * AT specific setup */ @@ -163,7 +159,6 @@ static int mio_cs_auto_attach(struct comedi_device *dev, { struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); static const struct ni_board_struct *board; - struct ni_private *devpriv; int ret; board = ni_getboardtype(dev, link); @@ -188,8 +183,6 @@ static int mio_cs_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = dev->private; - return ni_E_init(dev, 0, 1); } diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index db7e8aac67b..db399fe8c30 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -418,7 +418,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) CHSR_DRQ1 | CHSR_MRDY)) { dev_dbg(dev->class_dev, "unknown mite interrupt, disabling IRQ\n"); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; disable_irq(dev->irq); } } @@ -460,7 +460,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) break; } else if (flags & Waited) { writeb(ClearWaited, dev->mmio + Group_1_First_Clear); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; break; } else if (flags & PrimaryTC) { writeb(ClearPrimaryTC, diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 0525292c1d8..c20c51bef3e 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -16,29 +16,28 @@ */ /* -Driver: ni_tio -Description: National Instruments general purpose counters -Devices: -Author: J.P. Mellor <jpmellor@rose-hulman.edu>, - Herman.Bruyninckx@mech.kuleuven.ac.be, - Wim.Meeussen@mech.kuleuven.ac.be, - Klaas.Gadeyne@mech.kuleuven.ac.be, - Frank Mori Hess <fmhess@users.sourceforge.net> -Updated: Thu Nov 16 09:50:32 EST 2006 -Status: works - -This module is not used directly by end-users. Rather, it -is used by other drivers (for example ni_660x and ni_pcimio) -to provide support for NI's general purpose counters. It was -originally based on the counter code from ni_660x.c and -ni_mio_common.c. - -References: -DAQ 660x Register-Level Programmer Manual (NI 370505A-01) -DAQ 6601/6602 User Manual (NI 322137B-01) -340934b.pdf DAQ-STC reference manual + * Module: ni_tio + * Description: National Instruments general purpose counters + * Author: J.P. Mellor <jpmellor@rose-hulman.edu>, + * Herman.Bruyninckx@mech.kuleuven.ac.be, + * Wim.Meeussen@mech.kuleuven.ac.be, + * Klaas.Gadeyne@mech.kuleuven.ac.be, + * Frank Mori Hess <fmhess@users.sourceforge.net> + * Updated: Thu Nov 16 09:50:32 EST 2006 + * Status: works + * + * This module is not used directly by end-users. Rather, it + * is used by other drivers (for example ni_660x and ni_pcimio) + * to provide support for NI's general purpose counters. It was + * originally based on the counter code from ni_660x.c and + * ni_mio_common.c. + * + * References: + * DAQ 660x Register-Level Programmer Manual (NI 370505A-01) + * DAQ 6601/6602 User Manual (NI 322137B-01) + * 340934b.pdf DAQ-STC reference manual + */ -*/ /* TODO: Support use of both banks X and Y diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 6037bec77ef..d36c3abd312 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -16,29 +16,28 @@ */ /* -Driver: ni_tiocmd -Description: National Instruments general purpose counters command support -Devices: -Author: J.P. Mellor <jpmellor@rose-hulman.edu>, - Herman.Bruyninckx@mech.kuleuven.ac.be, - Wim.Meeussen@mech.kuleuven.ac.be, - Klaas.Gadeyne@mech.kuleuven.ac.be, - Frank Mori Hess <fmhess@users.sourceforge.net> -Updated: Fri, 11 Apr 2008 12:32:35 +0100 -Status: works - -This module is not used directly by end-users. Rather, it -is used by other drivers (for example ni_660x and ni_pcimio) -to provide command support for NI's general purpose counters. -It was originally split out of ni_tio.c to stop the 'ni_tio' -module depending on the 'mite' module. - -References: -DAQ 660x Register-Level Programmer Manual (NI 370505A-01) -DAQ 6601/6602 User Manual (NI 322137B-01) -340934b.pdf DAQ-STC reference manual + * Module: ni_tiocmd + * Description: National Instruments general purpose counters command support + * Author: J.P. Mellor <jpmellor@rose-hulman.edu>, + * Herman.Bruyninckx@mech.kuleuven.ac.be, + * Wim.Meeussen@mech.kuleuven.ac.be, + * Klaas.Gadeyne@mech.kuleuven.ac.be, + * Frank Mori Hess <fmhess@users.sourceforge.net> + * Updated: Fri, 11 Apr 2008 12:32:35 +0100 + * Status: works + * + * This module is not used directly by end-users. Rather, it + * is used by other drivers (for example ni_660x and ni_pcimio) + * to provide command support for NI's general purpose counters. + * It was originally split out of ni_tio.c to stop the 'ni_tio' + * module depending on the 'mite' module. + * + * References: + * DAQ 660x Register-Level Programmer Manual (NI 370505A-01) + * DAQ 6601/6602 User Manual (NI 322137B-01) + * 340934b.pdf DAQ-STC reference manual + */ -*/ /* TODO: Support use of both banks X and Y diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c index 3b5a1b90366..5f649f88d55 100644 --- a/drivers/staging/comedi/drivers/ni_usb6501.c +++ b/drivers/staging/comedi/drivers/ni_usb6501.c @@ -96,9 +96,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> -#include <linux/usb.h> -#include "../comedidev.h" +#include "../comedi_usb.h" #define NI6501_TIMEOUT 1000 diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 938aebc8e0e..cb7e4c37b8b 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -22,10 +22,8 @@ /* * Driver: pcl711 * Description: Advantech PCL-711 and 711b, ADLink ACL-8112 - * Devices: (Advantech) PCL-711 [pcl711] - * (Advantech) PCL-711B [pcl711b] - * (AdLink) ACL-8112HG [acl8112hg] - * (AdLink) ACL-8112DG [acl8112dg] + * Devices: [Advantech] PCL-711 (pcl711), PCL-711B (pcl711b), + * [ADLink] ACL-8112HG (acl8112hg), ACL-8112DG (acl8112dg) * Author: David A. Schleef <ds@schleef.org> * Janne Jalkanen <jalkanen@cs.hut.fi> * Eric Bunn <ebu@cs.hut.fi> diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index fcc440855e6..74b07e1744c 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -8,14 +8,10 @@ /* * Driver: pcl724 * Description: Comedi driver for 8255 based ISA DIO boards - * Devices: (Advantech) PCL-724 [pcl724] - * (Advantech) PCL-722 [pcl722] - * (Advantech) PCL-731 [pcl731] - * (ADLink) ACL-7122 [acl7122] - * (ADLink) ACL-7124 [acl7124] - * (ADLink) PET-48DIO [pet48dio] - * (WinSystems) PCM-IO48 [pcmio48] - * (Diamond Systems) ONYX-MM-DIO [onyx-mm-dio] + * Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731), + * [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio), + * [WinSystems] PCM-IO48 (pcmio48), + * [Diamond Systems] ONYX-MM-DIO (onyx-mm-dio) * Author: Michal Dobes <dobes@tesnet.cz> * Status: untested * diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 86f713fdf1d..40798150cfd 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -21,11 +21,8 @@ * Description: Advantech PCL-726 & compatibles * Author: David A. Schleef <ds@schleef.org> * Status: untested - * Devices: (Advantech) PCL-726 [pcl726] - * (Advantech) PCL-727 [pcl727] - * (Advantech) PCL-728 [pcl728] - * (ADLink) ACL-6126 [acl6126] - * (ADLink) ACL-6128 [acl6128] + * Devices: [Advantech] PCL-726 (pcl726), PCL-727 (pcl727), PCL-728 (pcl728), + * [ADLink] ACL-6126 (acl6126), ACL-6128 (acl6128) * * Configuration Options: * [0] - IO Base diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index a6c5770b280..ce958eef2a6 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -7,19 +7,12 @@ /* * Driver: pcl730 * Description: Advantech PCL-730 (& compatibles) - * Devices: (Advantech) PCL-730 [pcl730] - * (ICP) ISO-730 [iso730] - * (Adlink) ACL-7130 [acl7130] - * (Advantech) PCM-3730 [pcm3730] - * (Advantech) PCL-725 [pcl725] - * (ICP) P8R8-DIO [p16r16dio] - * (Adlink) ACL-7225b [acl7225b] - * (ICP) P16R16-DIO [p16r16dio] - * (Advantech) PCL-733 [pcl733] - * (Advantech) PCL-734 [pcl734] - * (Diamond Systems) OPMM-1616-XT [opmm-1616-xt] - * (Diamond Systems) PEARL-MM-P [prearl-mm-p] - * (Diamond Systems) IR104-PBF [ir104-pbf] + * Devices: [Advantech] PCL-730 (pcl730), PCM-3730 (pcm3730), PCL-725 (pcl725), + * PCL-733 (pcl733), PCL-734 (pcl734), + * [ADLink] ACL-7130 (acl7130), ACL-7225b (acl7225b), + * [ICP] ISO-730 (iso730), P8R8-DIO (p8r8dio), P16R16-DIO (p16r16dio), + * [Diamond Systems] OPMM-1616-XT (opmm-1616-xt), PEARL-MM-P (pearl-mm-p), + * IR104-PBF (ir104-pbf), * Author: José Luis Sánchez (jsanchezv@teleline.es) * Status: untested * diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index ac243ca5e0f..3ffb1ea2ecc 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -111,12 +111,12 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/gfp.h> -#include "../comedidev.h" - #include <linux/delay.h> #include <linux/io.h> -#include <asm/dma.h> +#include "../comedidev.h" + +#include "comedi_isadma.h" #include "comedi_fc.h" #include "8253.h" @@ -507,19 +507,11 @@ static const struct pcl812_board boardtypes[] = { }; struct pcl812_private { - unsigned char dma; /* >0 use dma ( usedDMA channel) */ + struct comedi_isadma *dma; unsigned char range_correction; /* =1 we must add 1 to range number */ unsigned int last_ai_chanspec; unsigned char mode_reg_int; /* there is stored INT number for some card */ unsigned int ai_poll_ptr; /* how many sampes transfer poll */ - unsigned int dmapages; - unsigned int hwdmasize; - unsigned long dmabuf[2]; /* PTR to DMA buf */ - unsigned int hwdmaptr[2]; /* HW PTR to DMA buf */ - unsigned int dmabytestomove[2]; /* how many bytes DMA transfer */ - int next_dma_buf; /* which buffer is next to use */ - unsigned int dma_runs_to_end; /* how many times we must switch DMA buffers */ - unsigned int last_dma_run; /* how many bytes to transfer on last DMA buffer */ unsigned int max_812_ai_mode0_rangewait; /* setling time for gain */ unsigned int divisor1; unsigned int divisor2; @@ -546,90 +538,32 @@ static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers) } static void pcl812_ai_setup_dma(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *s, + unsigned int unread_samples) { struct pcl812_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; - unsigned int dma_flags; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; unsigned int bytes; + unsigned int max_samples; + unsigned int nsamples; - /* we use EOS, so adapt DMA buffer to one scan */ - if (devpriv->ai_eos) { - devpriv->dmabytestomove[0] = comedi_bytes_per_scan(s); - devpriv->dmabytestomove[1] = comedi_bytes_per_scan(s); - devpriv->dma_runs_to_end = 1; - } else { - devpriv->dmabytestomove[0] = devpriv->hwdmasize; - devpriv->dmabytestomove[1] = devpriv->hwdmasize; - if (s->async->prealloc_bufsz < devpriv->hwdmasize) { - devpriv->dmabytestomove[0] = - s->async->prealloc_bufsz; - devpriv->dmabytestomove[1] = - s->async->prealloc_bufsz; - } - if (cmd->stop_src == TRIG_NONE) { - devpriv->dma_runs_to_end = 1; - } else { - /* how many samples we must transfer? */ - bytes = cmd->stop_arg * comedi_bytes_per_scan(s); - - /* how many DMA pages we must fill */ - devpriv->dma_runs_to_end = - bytes / devpriv->dmabytestomove[0]; - - /* on last dma transfer must be moved */ - devpriv->last_dma_run = - bytes % devpriv->dmabytestomove[0]; - if (devpriv->dma_runs_to_end == 0) - devpriv->dmabytestomove[0] = - devpriv->last_dma_run; - devpriv->dma_runs_to_end--; - } - } - if (devpriv->dmabytestomove[0] > devpriv->hwdmasize) { - devpriv->dmabytestomove[0] = devpriv->hwdmasize; - devpriv->ai_eos = 0; - } - if (devpriv->dmabytestomove[1] > devpriv->hwdmasize) { - devpriv->dmabytestomove[1] = devpriv->hwdmasize; - devpriv->ai_eos = 0; - } - devpriv->next_dma_buf = 0; - set_dma_mode(devpriv->dma, DMA_MODE_READ); - dma_flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); - set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]); - release_dma_lock(dma_flags); - enable_dma(devpriv->dma); -} + comedi_isadma_disable(dma->chan); -static void pcl812_ai_setup_next_dma(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pcl812_private *devpriv = dev->private; - unsigned long dma_flags; - - devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; - disable_dma(devpriv->dma); - set_dma_mode(devpriv->dma, DMA_MODE_READ); - dma_flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]); - if (devpriv->ai_eos) { - set_dma_count(devpriv->dma, - devpriv->dmabytestomove[devpriv->next_dma_buf]); - } else { - if (devpriv->dma_runs_to_end) { - set_dma_count(devpriv->dma, - devpriv->dmabytestomove[devpriv-> - next_dma_buf]); - } else { - set_dma_count(devpriv->dma, devpriv->last_dma_run); - } - devpriv->dma_runs_to_end--; + /* if using EOS, adapt DMA buffer to one scan */ + bytes = devpriv->ai_eos ? comedi_bytes_per_scan(s) : desc->maxsize; + max_samples = comedi_bytes_to_samples(s, bytes); + + /* + * Determine dma size based on the buffer size plus the number of + * unread samples and the number of samples remaining in the command. + */ + nsamples = comedi_nsamples_left(s, max_samples + unread_samples); + if (nsamples > unread_samples) { + nsamples -= unread_samples; + desc->size = comedi_samples_to_bytes(s, nsamples); + comedi_isadma_program(desc); } - release_dma_lock(dma_flags); - enable_dma(devpriv->dma); } static void pcl812_ai_set_chan_range(struct comedi_device *dev, @@ -786,6 +720,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; unsigned int ctrl = 0; unsigned int i; @@ -794,7 +729,7 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) pcl812_ai_set_chan_range(dev, cmd->chanlist[0], 1); - if (devpriv->dma) { /* check if we can use DMA transfer */ + if (dma) { /* check if we can use DMA transfer */ devpriv->ai_dma = 1; for (i = 1; i < cmd->chanlist_len; i++) if (cmd->chanlist[0] != cmd->chanlist[i]) { @@ -817,8 +752,11 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_dma = 0; } - if (devpriv->ai_dma) - pcl812_ai_setup_dma(dev, s); + if (devpriv->ai_dma) { + /* setup and enable dma for the first buffer */ + dma->cur_dma = 0; + pcl812_ai_setup_dma(dev, s, 0); + } switch (cmd->convert_src) { case TRIG_TIMER: @@ -859,7 +797,7 @@ static void pcl812_handle_eoc(struct comedi_device *dev, if (pcl812_ai_eoc(dev, s, NULL, 0)) { dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return; } @@ -895,19 +833,21 @@ static void pcl812_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; - int len, bufptr; - unsigned short *ptr; - - ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf]; - len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - - devpriv->ai_poll_ptr; - - pcl812_ai_setup_next_dma(dev, s); + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int nsamples; + int bufptr; + nsamples = comedi_bytes_to_samples(s, desc->size) - + devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - transfer_from_dma_buf(dev, s, ptr, bufptr, len); + /* restart dma with the next buffer */ + dma->cur_dma = 1 - dma->cur_dma; + pcl812_ai_setup_dma(dev, s, nsamples); + + transfer_from_dma_buf(dev, s, desc->virt_addr, bufptr, nsamples); } static irqreturn_t pcl812_interrupt(int irq, void *d) @@ -935,45 +875,37 @@ static irqreturn_t pcl812_interrupt(int irq, void *d) static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; unsigned long flags; - unsigned int top1, top2, i; + unsigned int poll; + int ret; + /* poll is valid only for DMA transfer */ if (!devpriv->ai_dma) - return 0; /* poll is valid only for DMA transfer */ + return 0; spin_lock_irqsave(&dev->spinlock, flags); - for (i = 0; i < 10; i++) { - /* where is now DMA */ - top1 = get_dma_residue(devpriv->ai_dma); - top2 = get_dma_residue(devpriv->ai_dma); - if (top1 == top2) - break; - } - - if (top1 != top2) { - spin_unlock_irqrestore(&dev->spinlock, flags); - return 0; - } - /* where is now DMA in buffer */ - top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1; - top1 >>= 1; /* sample position */ - top2 = top1 - devpriv->ai_poll_ptr; - if (top2 < 1) { /* no new samples */ - spin_unlock_irqrestore(&dev->spinlock, flags); - return 0; + poll = comedi_isadma_poll(dma); + poll = comedi_bytes_to_samples(s, poll); + if (poll > devpriv->ai_poll_ptr) { + desc = &dma->desc[dma->cur_dma]; + transfer_from_dma_buf(dev, s, desc->virt_addr, + devpriv->ai_poll_ptr, + poll - devpriv->ai_poll_ptr); + /* new buffer position */ + devpriv->ai_poll_ptr = poll; + + ret = comedi_buf_n_bytes_ready(s); + } else { + /* no new samples */ + ret = 0; } - transfer_from_dma_buf(dev, s, - (void *)devpriv->dmabuf[1 - - devpriv->next_dma_buf], - devpriv->ai_poll_ptr, top2); - - devpriv->ai_poll_ptr = top1; /* new buffer position */ - spin_unlock_irqrestore(&dev->spinlock, flags); - return comedi_buf_n_bytes_ready(s); + return ret; } static int pcl812_ai_cancel(struct comedi_device *dev, @@ -982,7 +914,7 @@ static int pcl812_ai_cancel(struct comedi_device *dev, struct pcl812_private *devpriv = dev->private; if (devpriv->ai_dma) - disable_dma(devpriv->dma); + comedi_isadma_disable(devpriv->dma->chan); outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG, dev->iobase + PCL812_CTRL_REG); @@ -1192,6 +1124,27 @@ static void pcl812_set_ai_range_table(struct comedi_device *dev, } } +static void pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) +{ + struct pcl812_private *devpriv = dev->private; + + /* only DMA channels 3 and 1 are valid */ + if (!(dma_chan == 3 || dma_chan == 1)) + return; + + /* DMA uses two 8K buffers */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, + PAGE_SIZE * 2, COMEDI_ISADMA_READ); +} + +static void pcl812_free_dma(struct comedi_device *dev) +{ + struct pcl812_private *devpriv = dev->private; + + if (devpriv) + comedi_isadma_free(devpriv->dma); +} + static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl812_board *board = dev->board_ptr; @@ -1200,7 +1153,6 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) int n_subdevices; int subdev; int ret; - int i; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1218,31 +1170,8 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* we need an IRQ to do DMA on channel 3 or 1 */ - if (dev->irq && board->has_dma && - (it->options[2] == 3 || it->options[2] == 1)) { - ret = request_dma(it->options[2], dev->board_name); - if (ret) { - dev_err(dev->class_dev, - "unable to request DMA channel %d\n", - it->options[2]); - return -EBUSY; - } - devpriv->dma = it->options[2]; - - devpriv->dmapages = 1; /* we want 8KB */ - devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; - - for (i = 0; i < 2; i++) { - unsigned long dmabuf; - - dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dmabuf) - return -ENOMEM; - - devpriv->dmabuf[i] = dmabuf; - devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); - } - } + if (dev->irq && board->has_dma) + pcl812_alloc_dma(dev, it->options[2]); /* differential analog inputs? */ switch (board->board_type) { @@ -1384,16 +1313,7 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcl812_detach(struct comedi_device *dev) { - struct pcl812_private *devpriv = dev->private; - - if (devpriv) { - if (devpriv->dmabuf[0]) - free_pages(devpriv->dmabuf[0], devpriv->dmapages); - if (devpriv->dmabuf[1]) - free_pages(devpriv->dmabuf[1], devpriv->dmapages); - if (devpriv->dma) - free_dma(devpriv->dma); - } + pcl812_free_dma(dev); comedi_legacy_detach(dev); } diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 73deb4bd5c9..da35edfccbc 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -33,14 +33,14 @@ Configuration Options: */ #include <linux/module.h> -#include "../comedidev.h" - #include <linux/gfp.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/interrupt.h> -#include <asm/dma.h> +#include "../comedidev.h" + +#include "comedi_isadma.h" #include "comedi_fc.h" #include "8253.h" @@ -114,14 +114,7 @@ static const struct pcl816_board boardtypes[] = { }; struct pcl816_private { - unsigned int dma; /* used DMA, 0=don't use DMA */ - unsigned int dmapages; - unsigned int hwdmasize; - unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */ - unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */ - int next_dma_buf; /* which DMA buffer will be used next round */ - long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ - unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ + struct comedi_isadma *dma; unsigned int ai_poll_ptr; /* how many sampes transfer poll */ unsigned int divisor1; unsigned int divisor2; @@ -149,63 +142,27 @@ static void pcl816_start_pacer(struct comedi_device *dev, bool load_counters) } static void pcl816_ai_setup_dma(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pcl816_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; - unsigned int dma_flags; - unsigned int bytes; - - bytes = devpriv->hwdmasize; - if (cmd->stop_src == TRIG_COUNT) { - /* how many */ - bytes = cmd->stop_arg * comedi_bytes_per_scan(s); - - /* how many DMA pages we must fill */ - devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize; - - /* on last dma transfer must be moved */ - devpriv->last_dma_run = bytes % devpriv->hwdmasize; - devpriv->dma_runs_to_end--; - if (devpriv->dma_runs_to_end >= 0) - bytes = devpriv->hwdmasize; - } else - devpriv->dma_runs_to_end = -1; - - devpriv->next_dma_buf = 0; - set_dma_mode(devpriv->dma, DMA_MODE_READ); - dma_flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); - set_dma_count(devpriv->dma, bytes); - release_dma_lock(dma_flags); - enable_dma(devpriv->dma); -} - -static void pcl816_ai_setup_next_dma(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *s, + unsigned int unread_samples) { struct pcl816_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; - unsigned long dma_flags; - - disable_dma(devpriv->dma); - if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { - /* switch dma bufs */ - devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; - set_dma_mode(devpriv->dma, DMA_MODE_READ); - dma_flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, - devpriv->hwdmaptr[devpriv->next_dma_buf]); - if (devpriv->dma_runs_to_end) - set_dma_count(devpriv->dma, devpriv->hwdmasize); - else - set_dma_count(devpriv->dma, devpriv->last_dma_run); - release_dma_lock(dma_flags); - enable_dma(devpriv->dma); + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize); + unsigned int nsamples; + + comedi_isadma_disable(dma->chan); + + /* + * Determine dma size based on the buffer maxsize plus the number of + * unread samples and the number of samples remaining in the command. + */ + nsamples = comedi_nsamples_left(s, max_samples + unread_samples); + if (nsamples > unread_samples) { + nsamples -= unread_samples; + desc->size = comedi_samples_to_bytes(s, nsamples); + comedi_isadma_program(desc); } - - devpriv->dma_runs_to_end--; } static void pcl816_ai_set_chan_range(struct comedi_device *dev, @@ -318,9 +275,10 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) struct comedi_device *dev = d; struct comedi_subdevice *s = dev->read_subdev; struct pcl816_private *devpriv = dev->private; - unsigned short *ptr; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int nsamples; unsigned int bufptr; - unsigned int len; if (!dev->attached || !devpriv->ai_cmd_running) { pcl816_ai_clear_eoc(dev); @@ -333,15 +291,16 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) return IRQ_HANDLED; } - ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf]; - - pcl816_ai_setup_next_dma(dev, s); - - len = (devpriv->hwdmasize >> 1) - devpriv->ai_poll_ptr; + nsamples = comedi_bytes_to_samples(s, desc->size) - + devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - transfer_from_dma_buf(dev, s, ptr, bufptr, len); + /* restart dma with the next buffer */ + dma->cur_dma = 1 - dma->cur_dma; + pcl816_ai_setup_dma(dev, s, nsamples); + + transfer_from_dma_buf(dev, s, desc->virt_addr, bufptr, nsamples); pcl816_ai_clear_eoc(dev); @@ -483,6 +442,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl816_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; unsigned int ctrl; unsigned int seglen; @@ -502,7 +462,9 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_poll_ptr = 0; devpriv->ai_cmd_canceled = 0; - pcl816_ai_setup_dma(dev, s); + /* setup and enable dma for the first buffer */ + dma->cur_dma = 0; + pcl816_ai_setup_dma(dev, s, 0); pcl816_start_pacer(dev, true); @@ -513,7 +475,8 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ctrl |= PCL816_CTRL_EXT_TRIG; outb(ctrl, dev->iobase + PCL816_CTRL_REG); - outb((devpriv->dma << 4) | dev->irq, dev->iobase + PCL816_STATUS_REG); + outb((dma->chan << 4) | dev->irq, + dev->iobase + PCL816_STATUS_REG); return 0; } @@ -521,42 +484,34 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl816_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; unsigned long flags; - unsigned int top1, top2, i; + unsigned int poll; + int ret; spin_lock_irqsave(&dev->spinlock, flags); - for (i = 0; i < 20; i++) { - top1 = get_dma_residue(devpriv->dma); /* where is now DMA */ - top2 = get_dma_residue(devpriv->dma); - if (top1 == top2) - break; - } - if (top1 != top2) { - spin_unlock_irqrestore(&dev->spinlock, flags); - return 0; - } - - /* where is now DMA in buffer */ - top1 = devpriv->hwdmasize - top1; - top1 >>= 1; /* sample position */ - top2 = top1 - devpriv->ai_poll_ptr; - if (top2 < 1) { /* no new samples */ - spin_unlock_irqrestore(&dev->spinlock, flags); - return 0; - } + poll = comedi_isadma_poll(dma); + poll = comedi_bytes_to_samples(s, poll); + if (poll > devpriv->ai_poll_ptr) { + desc = &dma->desc[dma->cur_dma]; + transfer_from_dma_buf(dev, s, desc->virt_addr, + devpriv->ai_poll_ptr, + poll - devpriv->ai_poll_ptr); + /* new buffer position */ + devpriv->ai_poll_ptr = poll; - transfer_from_dma_buf(dev, s, - (unsigned short *)devpriv->dmabuf[devpriv-> - next_dma_buf], - devpriv->ai_poll_ptr, top2); + comedi_handle_events(dev, s); - devpriv->ai_poll_ptr = top1; /* new buffer position */ + ret = comedi_buf_n_bytes_ready(s); + } else { + /* no new samples */ + ret = 0; + } spin_unlock_irqrestore(&dev->spinlock, flags); - comedi_handle_events(dev, s); - - return comedi_buf_n_bytes_ready(s); + return ret; } static int pcl816_ai_cancel(struct comedi_device *dev, @@ -657,13 +612,44 @@ static void pcl816_reset(struct comedi_device *dev) outb(0, dev->iobase + PCL816_DO_DI_MSB_REG); } +static void pcl816_alloc_irq_and_dma(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pcl816_private *devpriv = dev->private; + unsigned int irq_num = it->options[1]; + unsigned int dma_chan = it->options[2]; + + /* only IRQs 2-7 and DMA channels 3 and 1 are valid */ + if (!(irq_num >= 2 && irq_num <= 7) || + !(dma_chan == 3 || dma_chan == 1)) + return; + + if (request_irq(irq_num, pcl816_interrupt, 0, dev->board_name, dev)) + return; + + /* DMA uses two 16K buffers */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, + PAGE_SIZE * 4, COMEDI_ISADMA_READ); + if (!devpriv->dma) + free_irq(irq_num, dev); + else + dev->irq = irq_num; +} + +static void pcl816_free_dma(struct comedi_device *dev) +{ + struct pcl816_private *devpriv = dev->private; + + if (devpriv) + comedi_isadma_free(devpriv->dma); +} + static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl816_board *board = dev->board_ptr; struct pcl816_private *devpriv; struct comedi_subdevice *s; int ret; - int i; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -673,39 +659,8 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - /* we can use IRQ 2-7 for async command support */ - if (it->options[1] >= 2 && it->options[1] <= 7) { - ret = request_irq(it->options[1], pcl816_interrupt, 0, - dev->board_name, dev); - if (ret == 0) - dev->irq = it->options[1]; - } - - /* we need an IRQ to do DMA on channel 3 or 1 */ - if (dev->irq && (it->options[2] == 3 || it->options[2] == 1)) { - ret = request_dma(it->options[2], dev->board_name); - if (ret) { - dev_err(dev->class_dev, - "unable to request DMA channel %d\n", - it->options[2]); - return -EBUSY; - } - devpriv->dma = it->options[2]; - - devpriv->dmapages = 2; /* we need 16KB */ - devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; - - for (i = 0; i < 2; i++) { - unsigned long dmabuf; - - dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dmabuf) - return -ENOMEM; - - devpriv->dmabuf[i] = dmabuf; - devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); - } - } + /* an IRQ and DMA are required to support async commands */ + pcl816_alloc_irq_and_dma(dev, it); ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -718,7 +673,7 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->maxdata = board->ai_maxdata; s->range_table = &range_pcl816; s->insn_read = pcl816_ai_insn_read; - if (devpriv->dma) { + if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->len_chanlist = board->ai_chanlist; @@ -764,18 +719,11 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcl816_detach(struct comedi_device *dev) { - struct pcl816_private *devpriv = dev->private; - if (dev->private) { pcl816_ai_cancel(dev, dev->read_subdev); pcl816_reset(dev); - if (devpriv->dma) - free_dma(devpriv->dma); - if (devpriv->dmabuf[0]) - free_pages(devpriv->dmabuf[0], devpriv->dmapages); - if (devpriv->dmabuf[1]) - free_pages(devpriv->dmabuf[1], devpriv->dmapages); } + pcl816_free_dma(dev); comedi_legacy_detach(dev); } diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 8edea35532a..7e4cdea5fe5 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1,112 +1,105 @@ /* - comedi/drivers/pcl818.c - - Author: Michal Dobes <dobes@tesnet.cz> - - hardware driver for Advantech cards: - card: PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818, PCL-718 - driver: pcl818l, pcl818h, pcl818hd, pcl818hg, pcl818, pcl718 -*/ -/* -Driver: pcl818 -Description: Advantech PCL-818 cards, PCL-718 -Author: Michal Dobes <dobes@tesnet.cz> -Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h), - PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818), - PCL-718 (pcl718) -Status: works - -All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO. -Differences are only at maximal sample speed, range list and FIFO -support. -The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support -only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0. -PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO -but this code is untested. -A word or two about DMA. Driver support DMA operations at two ways: -1) DMA uses two buffers and after one is filled then is generated - INT and DMA restart with second buffer. With this mode I'm unable run - more that 80Ksamples/secs without data dropouts on K6/233. -2) DMA uses one buffer and run in autoinit mode and the data are - from DMA buffer moved on the fly with 2kHz interrupts from RTC. - This mode is used if the interrupt 8 is available for allocation. - If not, then first DMA mode is used. With this I can run at - full speed one card (100ksamples/secs) or two cards with - 60ksamples/secs each (more is problem on account of ISA limitations). - To use this mode you must have compiled kernel with disabled - "Enhanced Real Time Clock Support". - Maybe you can have problems if you use xntpd or similar. - If you've data dropouts with DMA mode 2 then: - a) disable IDE DMA - b) switch text mode console to fb. - - Options for PCL-818L: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0, 5=A/D input -5V.. +5V - 1, 10=A/D input -10V..+10V - [5] - 0, 5=D/A output 0-5V (internal reference -5V) - 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknown (external reference) - - Options for PCL-818, PCL-818H: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0, 5=D/A output 0-5V (internal reference -5V) - 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknown (external reference) - - Options for PCL-818HD, PCL-818HG: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA, - 1=use DMA ch 1, 3=use DMA ch 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0, 5=D/A output 0-5V (internal reference -5V) - 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknown (external reference) - - Options for PCL-718: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0=A/D Range is +/-10V - 1= +/-5V - 2= +/-2.5V - 3= +/-1V - 4= +/-0.5V - 5= user defined bipolar - 6= 0-10V - 7= 0-5V - 8= 0-2V - 9= 0-1V - 10= user defined unipolar - [5] - 0, 5=D/A outputs 0-5V (internal reference -5V) - 1, 10=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknown (external reference) - [6] - 0, 60=max 60kHz A/D sampling - 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed) - -*/ + * comedi/drivers/pcl818.c + * + * Driver: pcl818 + * Description: Advantech PCL-818 cards, PCL-718 + * Author: Michal Dobes <dobes@tesnet.cz> + * Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h), + * PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818), + * PCL-718 (pcl718) + * Status: works + * + * All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO. + * Differences are only at maximal sample speed, range list and FIFO + * support. + * The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support + * only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0. + * PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO + * but this code is untested. + * A word or two about DMA. Driver support DMA operations at two ways: + * 1) DMA uses two buffers and after one is filled then is generated + * INT and DMA restart with second buffer. With this mode I'm unable run + * more that 80Ksamples/secs without data dropouts on K6/233. + * 2) DMA uses one buffer and run in autoinit mode and the data are + * from DMA buffer moved on the fly with 2kHz interrupts from RTC. + * This mode is used if the interrupt 8 is available for allocation. + * If not, then first DMA mode is used. With this I can run at + * full speed one card (100ksamples/secs) or two cards with + * 60ksamples/secs each (more is problem on account of ISA limitations). + * To use this mode you must have compiled kernel with disabled + * "Enhanced Real Time Clock Support". + * Maybe you can have problems if you use xntpd or similar. + * If you've data dropouts with DMA mode 2 then: + * a) disable IDE DMA + * b) switch text mode console to fb. + * + * Options for PCL-818L: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0, 5=A/D input -5V.. +5V + * 1, 10=A/D input -10V..+10V + * [5] - 0, 5=D/A output 0-5V (internal reference -5V) + * 1, 10=D/A output 0-10V (internal reference -10V) + * 2 =D/A output unknown (external reference) + * + * Options for PCL-818, PCL-818H: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0, 5=D/A output 0-5V (internal reference -5V) + * 1, 10=D/A output 0-10V (internal reference -10V) + * 2 =D/A output unknown (external reference) + * + * Options for PCL-818HD, PCL-818HG: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA, + * 1=use DMA ch 1, 3=use DMA ch 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0, 5=D/A output 0-5V (internal reference -5V) + * 1, 10=D/A output 0-10V (internal reference -10V) + * 2 =D/A output unknown (external reference) + * + * Options for PCL-718: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0=A/D Range is +/-10V + * 1= +/-5V + * 2= +/-2.5V + * 3= +/-1V + * 4= +/-0.5V + * 5= user defined bipolar + * 6= 0-10V + * 7= 0-5V + * 8= 0-2V + * 9= 0-1V + * 10= user defined unipolar + * [5] - 0, 5=D/A outputs 0-5V (internal reference -5V) + * 1, 10=D/A outputs 0-10V (internal reference -10V) + * 2=D/A outputs unknown (external reference) + * [6] - 0, 60=max 60kHz A/D sampling + * 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed) + * + */ #include <linux/module.h> #include <linux/gfp.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/interrupt.h> -#include <asm/dma.h> #include "../comedidev.h" +#include "comedi_isadma.h" #include "comedi_fc.h" #include "8253.h" @@ -303,20 +296,14 @@ static const struct pcl818_board boardtypes[] = { }; struct pcl818_private { - unsigned int dma; /* used DMA, 0=don't use DMA */ - unsigned int dmapages; - unsigned int hwdmasize; - unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */ - unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */ - int next_dma_buf; /* which DMA buffer will be used next round */ - long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ - unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ - unsigned int ns_min; /* manimal allowed delay between samples (in us) for actual card */ + struct comedi_isadma *dma; + /* manimal allowed delay between samples (in us) for actual card */ + unsigned int ns_min; int i8253_osc_base; /* 1/frequency of on board oscilator in ns */ - unsigned int act_chanlist[16]; /* MUX setting for actual AI operations */ + /* MUX setting for actual AI operations */ + unsigned int act_chanlist[16]; unsigned int act_chanlist_len; /* how long is actual MUX list */ unsigned int act_chanlist_pos; /* actual position in MUX list */ - unsigned int ai_data_len; /* len of data buffer */ unsigned int divisor1; unsigned int divisor2; unsigned int usefifo:1; @@ -340,58 +327,27 @@ static void pcl818_start_pacer(struct comedi_device *dev, bool load_counters) } static void pcl818_ai_setup_dma(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pcl818_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; - unsigned int flags; - unsigned int bytes; - - disable_dma(devpriv->dma); /* disable dma */ - bytes = devpriv->hwdmasize; - if (cmd->stop_src == TRIG_COUNT) { - bytes = cmd->stop_arg * comedi_bytes_per_scan(s); - devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize; - devpriv->last_dma_run = bytes % devpriv->hwdmasize; - devpriv->dma_runs_to_end--; - if (devpriv->dma_runs_to_end >= 0) - bytes = devpriv->hwdmasize; - } - - devpriv->next_dma_buf = 0; - set_dma_mode(devpriv->dma, DMA_MODE_READ); - flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); - set_dma_count(devpriv->dma, bytes); - release_dma_lock(flags); - enable_dma(devpriv->dma); -} - -static void pcl818_ai_setup_next_dma(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *s, + unsigned int unread_samples) { struct pcl818_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; - unsigned long flags; - - disable_dma(devpriv->dma); - devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; - if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { - /* switch dma bufs */ - set_dma_mode(devpriv->dma, DMA_MODE_READ); - flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, - devpriv->hwdmaptr[devpriv->next_dma_buf]); - if (devpriv->dma_runs_to_end || cmd->stop_src == TRIG_NONE) - set_dma_count(devpriv->dma, devpriv->hwdmasize); - else - set_dma_count(devpriv->dma, devpriv->last_dma_run); - release_dma_lock(flags); - enable_dma(devpriv->dma); + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize); + unsigned int nsamples; + + comedi_isadma_disable(dma->chan); + + /* + * Determine dma size based on the buffer maxsize plus the number of + * unread samples and the number of samples remaining in the command. + */ + nsamples = comedi_nsamples_left(s, max_samples + unread_samples); + if (nsamples > unread_samples) { + nsamples -= unread_samples; + desc->size = comedi_samples_to_bytes(s, nsamples); + comedi_isadma_program(desc); } - - devpriv->dma_runs_to_end--; } static void pcl818_ai_set_chan_range(struct comedi_device *dev, @@ -493,11 +449,12 @@ static int pcl818_ai_eoc(struct comedi_device *dev, return -EBUSY; } -static bool pcl818_ai_dropout(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int chan) +static bool pcl818_ai_write_sample(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int chan, unsigned int val) { struct pcl818_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned int expected_chan; expected_chan = devpriv->act_chanlist[devpriv->act_chanlist_pos]; @@ -507,17 +464,11 @@ static bool pcl818_ai_dropout(struct comedi_device *dev, (devpriv->dma) ? "DMA" : (devpriv->usefifo) ? "FIFO" : "IRQ", chan, expected_chan); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - return true; + s->async->events |= COMEDI_CB_ERROR; + return false; } - return false; -} -static bool pcl818_ai_next_chan(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pcl818_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; + comedi_buf_write_samples(s, &val, 1); devpriv->act_chanlist_pos++; if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) @@ -540,47 +491,35 @@ static void pcl818_handle_eoc(struct comedi_device *dev, if (pcl818_ai_eoc(dev, s, NULL, 0)) { dev_err(dev->class_dev, "A/D mode1/3 IRQ without DRDY!\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return; } val = pcl818_ai_get_sample(dev, s, &chan); - - if (pcl818_ai_dropout(dev, s, chan)) - return; - - comedi_buf_write_samples(s, &val, 1); - - pcl818_ai_next_chan(dev, s); + pcl818_ai_write_sample(dev, s, chan, val); } static void pcl818_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl818_private *devpriv = dev->private; - unsigned short *ptr; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned short *ptr = desc->virt_addr; + unsigned int nsamples = comedi_bytes_to_samples(s, desc->size); unsigned int chan; unsigned int val; - int i, len, bufptr; - - pcl818_ai_setup_next_dma(dev, s); - - ptr = (unsigned short *)devpriv->dmabuf[1 - devpriv->next_dma_buf]; + int i; - len = devpriv->hwdmasize >> 1; - bufptr = 0; + /* restart dma with the next buffer */ + dma->cur_dma = 1 - dma->cur_dma; + pcl818_ai_setup_dma(dev, s, nsamples); - for (i = 0; i < len; i++) { - val = ptr[bufptr++]; + for (i = 0; i < nsamples; i++) { + val = ptr[i]; chan = val & 0xf; val = (val >> 4) & s->maxdata; - - if (pcl818_ai_dropout(dev, s, chan)) - break; - - comedi_buf_write_samples(s, &val, 1); - - if (!pcl818_ai_next_chan(dev, s)) + if (!pcl818_ai_write_sample(dev, s, chan, val)) break; } } @@ -597,14 +536,14 @@ static void pcl818_handle_fifo(struct comedi_device *dev, if (status & 4) { dev_err(dev->class_dev, "A/D mode1/3 FIFO overflow!\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return; } if (status & 1) { dev_err(dev->class_dev, "A/D mode1/3 FIFO interrupt without data!\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return; } @@ -615,13 +554,7 @@ static void pcl818_handle_fifo(struct comedi_device *dev, for (i = 0; i < len; i++) { val = pcl818_ai_get_fifo_sample(dev, s, &chan); - - if (pcl818_ai_dropout(dev, s, chan)) - break; - - comedi_buf_write_samples(s, &val, 1); - - if (!pcl818_ai_next_chan(dev, s)) + if (!pcl818_ai_write_sample(dev, s, chan, val)) break; } } @@ -687,7 +620,8 @@ static int check_channel_list(struct comedi_device *dev, break; nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; - if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */ + if (nowmustbechan != CR_CHAN(chanlist[i])) { + /* channel list isn't continuous :-( */ dev_dbg(dev->class_dev, "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", i, CR_CHAN(chanlist[i]), nowmustbechan, @@ -804,6 +738,7 @@ static int pcl818_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl818_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; unsigned int ctrl = 0; unsigned int seglen; @@ -818,11 +753,9 @@ static int pcl818_ai_cmd(struct comedi_device *dev, return -EINVAL; pcl818_ai_setup_chanlist(dev, cmd->chanlist, seglen); - devpriv->ai_data_len = s->async->prealloc_bufsz; devpriv->ai_cmd_running = 1; devpriv->ai_cmd_canceled = 0; devpriv->act_chanlist_pos = 0; - devpriv->dma_runs_to_end = 0; if (cmd->convert_src == TRIG_TIMER) ctrl |= PCL818_CTRL_PACER_TRIG; @@ -831,8 +764,10 @@ static int pcl818_ai_cmd(struct comedi_device *dev, outb(PCL818_CNTENABLE_PACER_ENA, dev->iobase + PCL818_CNTENABLE_REG); - if (devpriv->dma) { - pcl818_ai_setup_dma(dev, s); + if (dma) { + /* setup and enable dma for the first buffer */ + dma->cur_dma = 0; + pcl818_ai_setup_dma(dev, s, 0); ctrl |= PCL818_CTRL_INTE | PCL818_CTRL_IRQ(dev->irq) | PCL818_CTRL_DMAE; @@ -854,12 +789,13 @@ static int pcl818_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl818_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; if (!devpriv->ai_cmd_running) return 0; - if (devpriv->dma) { + if (dma) { if (cmd->stop_src == TRIG_NONE || (cmd->stop_src == TRIG_COUNT && s->async->scans_done < cmd->stop_arg)) { @@ -872,7 +808,7 @@ static int pcl818_ai_cancel(struct comedi_device *dev, return 0; } } - disable_dma(devpriv->dma); + comedi_isadma_disable(dma->chan); } outb(PCL818_CTRL_DISABLE_TRIG, dev->iobase + PCL818_CTRL_REG); @@ -1054,13 +990,33 @@ static void pcl818_set_ai_range_table(struct comedi_device *dev, } } +static void pcl818_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) +{ + struct pcl818_private *devpriv = dev->private; + + /* only DMA channels 3 and 1 are valid */ + if (!(dma_chan == 3 || dma_chan == 1)) + return; + + /* DMA uses two 16K buffers */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, + PAGE_SIZE * 4, COMEDI_ISADMA_READ); +} + +static void pcl818_free_dma(struct comedi_device *dev) +{ + struct pcl818_private *devpriv = dev->private; + + if (devpriv) + comedi_isadma_free(devpriv->dma); +} + static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl818_board *board = dev->board_ptr; struct pcl818_private *devpriv; struct comedi_subdevice *s; int ret; - int i; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1084,31 +1040,8 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->usefifo = 1; /* we need an IRQ to do DMA on channel 3 or 1 */ - if (dev->irq && board->has_dma && - (it->options[2] == 3 || it->options[2] == 1)) { - ret = request_dma(it->options[2], dev->board_name); - if (ret) { - dev_err(dev->class_dev, - "unable to request DMA channel %d\n", - it->options[2]); - return -EBUSY; - } - devpriv->dma = it->options[2]; - - devpriv->dmapages = 2; /* we need 16KB */ - devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; - - for (i = 0; i < 2; i++) { - unsigned long dmabuf; - - dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dmabuf) - return -ENOMEM; - - devpriv->dmabuf[i] = dmabuf; - devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); - } - } + if (dev->irq && board->has_dma) + pcl818_alloc_dma(dev, it->options[2]); ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -1194,8 +1127,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->ns_min = board->ns_min; if (!board->is_818) { - if ((it->options[6] == 1) || (it->options[6] == 100)) - devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */ + if ((it->options[6] == 1) || (it->options[6] == 100)) { + /* extended PCL718 to 100kHz DAC */ + devpriv->ns_min = 10000; + } } pcl818_reset(dev); @@ -1210,13 +1145,8 @@ static void pcl818_detach(struct comedi_device *dev) if (devpriv) { pcl818_ai_cancel(dev, dev->read_subdev); pcl818_reset(dev); - if (devpriv->dma) - free_dma(devpriv->dma); - if (devpriv->dmabuf[0]) - free_pages(devpriv->dmabuf[0], devpriv->dmapages); - if (devpriv->dmabuf[1]) - free_pages(devpriv->dmabuf[1], devpriv->dmapages); } + pcl818_free_dma(dev); comedi_legacy_detach(dev); } diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index e3ac8ac6190..12f94fe82f5 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -19,8 +19,7 @@ /* * Driver: pcmad * Description: Winsystems PCM-A/D12, PCM-A/D16 - * Devices: (Winsystems) PCM-A/D12 [pcmad12] - * (Winsystems) PCM-A/D16 [pcmad16] + * Devices: [Winsystems] PCM-A/D12 (pcmad12), PCM-A/D16 (pcmad16) * Author: ds * Status: untested * diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 59108c06ced..d86c5e2cd0c 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -19,7 +19,7 @@ /* * Driver: pcmda12 * Description: A driver for the Winsystems PCM-D/A-12 - * Devices: (Winsystems) PCM-D/A-12 [pcmda12] + * Devices: [Winsystems] PCM-D/A-12 (pcmda12) * Author: Calin Culianu <calin@ajvar.org> * Updated: Fri, 13 Jan 2006 12:01:01 -0500 * Status: works diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index f0059e935da..2c0e7ecbf49 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -19,7 +19,7 @@ /* * Driver: pcmmio * Description: A driver for the PCM-MIO multifunction board - * Devices: (Winsystems) PCM-MIO [pcmmio] + * Devices: [Winsystems] PCM-MIO (pcmmio) * Author: Calin Culianu <calin@ajvar.org> * Updated: Wed, May 16 2007 16:21:10 -0500 * Status: works diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 0f5483b6147..a1641d98181 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -19,8 +19,7 @@ /* * Driver: pcmuio * Description: Winsystems PC-104 based 48/96-channel DIO boards. - * Devices: (Winsystems) PCM-UIO48A [pcmuio48] - * (Winsystems) PCM-UIO96A [pcmuio96] + * Devices: [Winsystems] PCM-UIO48A (pcmuio48), PCM-UIO96A (pcmuio96) * Author: Calin Culianu <calin@ajvar.org> * Updated: Fri, 13 Jan 2006 12:01:01 -0500 * Status: works diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 96098110b0b..8387fd0e4b7 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -48,15 +48,10 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308 */ #include <linux/module.h> -#include "../comedidev.h" #include <linux/semaphore.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ds.h> - #include <linux/completion.h> +#include "../comedi_pcmcia.h" #include "comedi_fc.h" struct daqp_private { @@ -210,8 +205,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) unsigned short data; if (status & DAQP_STATUS_DATA_LOST) { - s->async->events |= - COMEDI_CB_EOA | COMEDI_CB_OVERFLOW; + s->async->events |= COMEDI_CB_OVERFLOW; dev_warn(dev->class_dev, "data lost\n"); break; } @@ -239,7 +233,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) if (loop_limit <= 0) { dev_warn(dev->class_dev, "loop_limit reached in daqp_interrupt()\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; } comedi_handle_events(dev, s); diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 581aa58d9c0..c94ad12ed44 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -19,10 +19,8 @@ /* * Driver: rtd520 * Description: Real Time Devices PCI4520/DM7520 - * Devices: (Real Time Devices) DM7520HR-1 [DM7520] - * (Real Time Devices) DM7520HR-8 [DM7520] - * (Real Time Devices) PCI4520 [PCI4520] - * (Real Time Devices) PCI4520-8 [PCI4520] + * Devices: [Real Time Devices] DM7520HR-1 (DM7520), DM7520HR-8, + * PCI4520 (PCI4520), PCI4520-8 * Author: Dan Christian * Status: Works. Only tested on DM7520-8. Not SMP safe. * @@ -1014,10 +1012,8 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) readw(dev->mmio + LAS0_CLEAR); /* TODO: allow multiple interrupt sources */ - if (devpriv->xfer_count > 0) /* transfer every N samples */ - writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT); - else /* 1/2 FIFO transfers */ - writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT); + /* transfer every N samples */ + writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT); /* BUG: start_src is ASSUMED to be TRIG_NOW */ /* BUG? it seems like things are running before the "start" */ @@ -1031,8 +1027,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct rtd_private *devpriv = dev->private; - u32 overrun; - u16 status; /* pacer stop source: SOFTWARE */ writel(0, dev->mmio + LAS0_PACER_STOP); @@ -1040,8 +1034,6 @@ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) writel(0, dev->mmio + LAS0_ADC_CONVERSION); writew(0, dev->mmio + LAS0_IT); devpriv->ai_count = 0; /* stop and don't transfer any more */ - status = readw(dev->mmio + LAS0_IT); - overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff; writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR); return 0; } diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index 67b4b378bd0..340ac776e95 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -19,8 +19,7 @@ /* * Driver: rti800 * Description: Analog Devices RTI-800/815 - * Devices: (Analog Devices) RTI-800 [rti800] - * (Analog Devices) RTI-815 [rti815] + * Devices: [Analog Devices] RTI-800 (rti800), RTI-815 (rti815) * Author: David A. Schleef <ds@schleef.org> * Status: unknown * Updated: Fri, 05 Sep 2008 14:50:44 +0100 diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 96c3974207a..6db58fcfd49 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -20,7 +20,7 @@ * Driver: rti802 * Description: Analog Devices RTI-802 * Author: Anders Blomdell <anders.blomdell@control.lth.se> - * Devices: (Analog Devices) RTI-802 [rti802] + * Devices: [Analog Devices] RTI-802 (rti802) * Status: works * * Configuration Options: diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 14932c5f379..fc497dd9202 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -118,7 +118,7 @@ static void s626_mc_enable(struct comedi_device *dev, static void s626_mc_disable(struct comedi_device *dev, unsigned int cmd, unsigned int reg) { - writel(cmd << 16 , dev->mmio + reg); + writel(cmd << 16, dev->mmio + reg); mmiowb(); } diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 4737dbf8e01..1cd7403a4e9 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -16,10 +16,11 @@ /* * Driver: usbdux * Description: University of Stirling USB DAQ & INCITE Technology Limited - * Devices: (ITL) USB-DUX [usbdux] + * Devices: [ITL] USB-DUX (usbdux) * Author: Bernd Porr <mail@berndporr.me.uk> * Updated: 10 Oct 2014 * Status: Stable + * * Connection scheme for the counter at the digital port: * 0=/CLK0, 1=UP/DOWN0, 2=RESET0, 4=/CLK1, 5=UP/DOWN1, 6=RESET1. * The sampling rate of the counter is approximately 500Hz. @@ -79,11 +80,10 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> -#include <linux/usb.h> #include <linux/fcntl.h> #include <linux/compiler.h> -#include "../comedidev.h" +#include "../comedi_usb.h" #include "comedi_fc.h" diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index ddc4cb9d5ed..7ce27c16c2f 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -15,7 +15,7 @@ /* * Driver: usbduxfast * Description: University of Stirling USB DAQ & INCITE Technology Limited - * Devices: (ITL) USB-DUX [usbduxfast] + * Devices: [ITL] USB-DUX-FAST (usbduxfast) * Author: Bernd Porr <mail@berndporr.me.uk> * Updated: 10 Oct 2014 * Status: stable @@ -46,11 +46,10 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> -#include <linux/usb.h> #include <linux/fcntl.h> #include <linux/compiler.h> #include "comedi_fc.h" -#include "../comedidev.h" +#include "../comedi_usb.h" /* * timeout for the USB-transfer diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index dc19435b652..394969b7458 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -16,7 +16,7 @@ /* * Driver: usbduxsigma * Description: University of Stirling USB DAQ & INCITE Technology Limited - * Devices: (ITL) USB-DUX [usbduxsigma] + * Devices: [ITL] USB-DUX-SIGMA (usbduxsigma) * Author: Bernd Porr <mail@berndporr.me.uk> * Updated: 10 Oct 2014 * Status: stable @@ -45,13 +45,12 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> -#include <linux/usb.h> #include <linux/fcntl.h> #include <linux/compiler.h> #include <asm/unaligned.h> #include "comedi_fc.h" -#include "../comedidev.h" +#include "../comedi_usb.h" /* timeout for the USB-transfer in ms*/ #define BULK_TIMEOUT 1000 @@ -215,7 +214,6 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - unsigned int dio_state; uint32_t val; int ret; int i; @@ -224,9 +222,6 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev, if (devpriv->ai_counter == 0) { devpriv->ai_counter = devpriv->ai_timer; - /* get the state of the dio pins to allow external trigger */ - dio_state = be32_to_cpu(devpriv->in_buf[0]); - /* get the data from the USB bus and hand it over to comedi */ for (i = 0; i < cmd->chanlist_len; i++) { /* transfer data, note first byte is the DIO state */ diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index a19a56ee0ee..e37118321a2 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -18,21 +18,22 @@ GNU General Public License for more details. */ /* -Driver: vmk80xx -Description: Velleman USB Board Low-Level Driver -Devices: K8055/K8061 aka VM110/VM140 -Author: Manuel Gebele <forensixs@gmx.de> -Updated: Sun, 10 May 2009 11:14:59 +0200 -Status: works - -Supports: - - analog input - - analog output - - digital input - - digital output - - counter - - pwm -*/ + * Driver: vmk80xx + * Description: Velleman USB Board Low-Level Driver + * Devices: [Velleman] K8055 (K8055/VM110), K8061 (K8061/VM140), + * VM110 (K8055/VM110), VM140 (K8061/VM140) + * Author: Manuel Gebele <forensixs@gmx.de> + * Updated: Sun, 10 May 2009 11:14:59 +0200 + * Status: works + * + * Supports: + * - analog input + * - analog output + * - digital input + * - digital output + * - counter + * - pwm + */ #include <linux/kernel.h> #include <linux/module.h> @@ -41,10 +42,9 @@ Supports: #include <linux/input.h> #include <linux/slab.h> #include <linux/poll.h> -#include <linux/usb.h> #include <linux/uaccess.h> -#include "../comedidev.h" +#include "../comedi_usb.h" enum { DEVICE_VMK8055, @@ -550,41 +550,35 @@ static int vmk80xx_cnt_insn_config(struct comedi_device *dev, unsigned int *data) { struct vmk80xx_private *devpriv = dev->private; - unsigned int insn_cmd; - int chan; + unsigned int chan = CR_CHAN(insn->chanspec); int cmd; int reg; - int n; - - insn_cmd = data[0]; - if (insn_cmd != INSN_CONFIG_RESET && insn_cmd != GPCT_RESET) - return -EINVAL; + int ret; down(&devpriv->limit_sem); - - chan = CR_CHAN(insn->chanspec); - - if (devpriv->model == VMK8055_MODEL) { - if (!chan) { - cmd = VMK8055_CMD_RST_CNT1; - reg = VMK8055_CNT1_REG; + switch (data[0]) { + case INSN_CONFIG_RESET: + if (devpriv->model == VMK8055_MODEL) { + if (!chan) { + cmd = VMK8055_CMD_RST_CNT1; + reg = VMK8055_CNT1_REG; + } else { + cmd = VMK8055_CMD_RST_CNT2; + reg = VMK8055_CNT2_REG; + } + devpriv->usb_tx_buf[reg] = 0x00; } else { - cmd = VMK8055_CMD_RST_CNT2; - reg = VMK8055_CNT2_REG; + cmd = VMK8061_CMD_RST_CNT; } - - devpriv->usb_tx_buf[reg] = 0x00; - } else { - cmd = VMK8061_CMD_RST_CNT; + ret = vmk80xx_write_packet(dev, cmd); + break; + default: + ret = -EINVAL; + break; } - - for (n = 0; n < insn->n; n++) - if (vmk80xx_write_packet(dev, cmd)) - break; - up(&devpriv->limit_sem); - return n; + return ret ? ret : insn->n; } static int vmk80xx_cnt_insn_write(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/z8536.h b/drivers/staging/comedi/drivers/z8536.h new file mode 100644 index 00000000000..7be53109cc8 --- /dev/null +++ b/drivers/staging/comedi/drivers/z8536.h @@ -0,0 +1,202 @@ +/* + * Z8536 CIO Internal registers + */ + +#ifndef _Z8536_H +#define _Z8536_H + +/* Master Interrupt Control register */ +#define Z8536_INT_CTRL_REG 0x00 +#define Z8536_INT_CTRL_MIE BIT(7) /* Master Interrupt Enable */ +#define Z8536_INT_CTRL_DLC BIT(6) /* Disable Lower Chain */ +#define Z8536_INT_CTRL_NV BIT(5) /* No Vector */ +#define Z8536_INT_CTRL_PA_VIS BIT(4) /* Port A Vect Inc Status */ +#define Z8536_INT_CTRL_PB_VIS BIT(3) /* Port B Vect Inc Status */ +#define Z8536_INT_CTRL_VT_VIS BIT(2) /* C/T Vect Inc Status */ +#define Z8536_INT_CTRL_RJA BIT(1) /* Right Justified Addresses */ +#define Z8536_INT_CTRL_RESET BIT(0) /* Reset */ + +/* Master Configuration Control register */ +#define Z8536_CFG_CTRL_REG 0x01 +#define Z8536_CFG_CTRL_PBE BIT(7) /* Port B Enable */ +#define Z8536_CFG_CTRL_CT1E BIT(6) /* C/T 1 Enable */ +#define Z8536_CFG_CTRL_CT2E BIT(5) /* C/T 2 Enable */ +#define Z8536_CFG_CTRL_PCE_CT3E BIT(4) /* Port C & C/T 3 Enable */ +#define Z8536_CFG_CTRL_PLC BIT(3) /* Port A/B Link Control */ +#define Z8536_CFG_CTRL_PAE BIT(2) /* Port A Enable */ +#define Z8536_CFG_CTRL_LC_INDEP (0 << 0)/* C/Ts Independent */ +#define Z8536_CFG_CTRL_LC_GATE (1 << 0)/* C/T 1 Out Gates C/T 2 */ +#define Z8536_CFG_CTRL_LC_TRIG (2 << 0)/* C/T 1 Out Triggers C/T 2 */ +#define Z8536_CFG_CTRL_LC_CLK (3 << 0)/* C/T 1 Out Clocks C/T 2 */ +#define Z8536_CFG_CTRL_LC_MASK (3 << 0)/* C/T Link Control mask */ + +/* Interrupt Vector registers */ +#define Z8536_PA_INT_VECT_REG 0x02 +#define Z8536_PB_INT_VECT_REG 0x03 +#define Z8536_CT_INT_VECT_REG 0x04 +#define Z8536_CURR_INT_VECT_REG 0x1f + +/* Port A/B & Counter/Timer 1/2/3 Command and Status registers */ +#define Z8536_PA_CMDSTAT_REG 0x08 +#define Z8536_PB_CMDSTAT_REG 0x09 +#define Z8536_CT1_CMDSTAT_REG 0x0a +#define Z8536_CT2_CMDSTAT_REG 0x0b +#define Z8536_CT3_CMDSTAT_REG 0x0c +#define Z8536_CT_CMDSTAT_REG(x) (0x0a + (x)) +#define Z8536_CMD_NULL (0 << 5)/* Null Code */ +#define Z8536_CMD_CLR_IP_IUS (1 << 5)/* Clear IP & IUS */ +#define Z8536_CMD_SET_IUS (2 << 5)/* Set IUS */ +#define Z8536_CMD_CLR_IUS (3 << 5)/* Clear IUS */ +#define Z8536_CMD_SET_IP (4 << 5)/* Set IP */ +#define Z8536_CMD_CLR_IP (5 << 5)/* Clear IP */ +#define Z8536_CMD_SET_IE (6 << 5)/* Set IE */ +#define Z8536_CMD_CLR_IE (7 << 5)/* Clear IE */ +#define Z8536_CMD_MASK (7 << 5) + +#define Z8536_STAT_IUS BIT(7) /* Interrupt Under Service */ +#define Z8536_STAT_IE BIT(6) /* Interrupt Enable */ +#define Z8536_STAT_IP BIT(5) /* Interrupt Pending */ +#define Z8536_STAT_ERR BIT(4) /* Interrupt Error */ +#define Z8536_STAT_IE_IP (Z8536_STAT_IE | Z8536_STAT_IP) + +#define Z8536_PAB_STAT_ORE BIT(3) /* Output Register Empty */ +#define Z8536_PAB_STAT_IRF BIT(2) /* Input Register Full */ +#define Z8536_PAB_STAT_PMF BIT(1) /* Pattern Match Flag */ +#define Z8536_PAB_CMDSTAT_IOE BIT(0) /* Interrupt On Error */ + +#define Z8536_CT_CMD_RCC BIT(3) /* Read Counter Control */ +#define Z8536_CT_CMDSTAT_GCB BIT(2) /* Gate Command Bit */ +#define Z8536_CT_CMD_TCB BIT(1) /* Trigger Command Bit */ +#define Z8536_CT_STAT_CIP BIT(0) /* Count In Progress */ + +/* Port Data registers */ +#define Z8536_PA_DATA_REG 0x0d +#define Z8536_PB_DATA_REG 0x0e +#define Z8536_PC_DATA_REG 0x0f + +/* Counter/Timer 1/2/3 Current Count registers */ +#define Z8536_CT1_VAL_MSB_REG 0x10 +#define Z8536_CT1_VAL_LSB_REG 0x11 +#define Z8536_CT2_VAL_MSB_REG 0x12 +#define Z8536_CT2_VAL_LSB_REG 0x13 +#define Z8536_CT3_VAL_MSB_REG 0x14 +#define Z8536_CT3_VAL_LSB_REG 0x15 +#define Z8536_CT_VAL_MSB_REG(x) (0x10 + ((x) * 2)) +#define Z8536_CT_VAL_LSB_REG(x) (0x11 + ((x) * 2)) + +/* Counter/Timer 1/2/3 Time Constant registers */ +#define Z8536_CT1_RELOAD_MSB_REG 0x16 +#define Z8536_CT1_RELOAD_LSB_REG 0x17 +#define Z8536_CT2_RELOAD_MSB_REG 0x18 +#define Z8536_CT2_RELOAD_LSB_REG 0x19 +#define Z8536_CT3_RELOAD_MSB_REG 0x1a +#define Z8536_CT3_RELOAD_LSB_REG 0x1b +#define Z8536_CT_RELOAD_MSB_REG(x) (0x16 + ((x) * 2)) +#define Z8536_CT_RELOAD_LSB_REG(x) (0x17 + ((x) * 2)) + +/* Counter/Timer 1/2/3 Mode Specification registers */ +#define Z8536_CT1_MODE_REG 0x1c +#define Z8536_CT2_MODE_REG 0x1d +#define Z8536_CT3_MODE_REG 0x1e +#define Z8536_CT_MODE_REG(x) (0x1c + (x)) +#define Z8536_CT_MODE_CSC BIT(7) /* Continuous/Single Cycle */ +#define Z8536_CT_MODE_EOE BIT(6) /* External Output Enable */ +#define Z8536_CT_MODE_ECE BIT(5) /* External Count Enable */ +#define Z8536_CT_MODE_ETE BIT(4) /* External Trigger Enable */ +#define Z8536_CT_MODE_EGE BIT(3) /* External Gate Enable */ +#define Z8536_CT_MODE_REB BIT(2) /* Retrigger Enable Bit */ +#define Z8536_CT_MODE_DCS_PULSE (0 << 0)/* Duty Cycle - Pulse */ +#define Z8536_CT_MODE_DCS_ONESHOT (1 << 0)/* Duty Cycle - One-Shot */ +#define Z8536_CT_MODE_DCS_SQRWAVE (2 << 0)/* Duty Cycle - Square Wave */ +#define Z8536_CT_MODE_DCS_DO_NOT_USE (3 << 0)/* Duty Cycle - Do Not Use */ +#define Z8536_CT_MODE_DCS_MASK (3 << 0)/* Duty Cycle mask */ + +/* Port A/B Mode Specification registers */ +#define Z8536_PA_MODE_REG 0x20 +#define Z8536_PB_MODE_REG 0x28 +#define Z8536_PAB_MODE_PTS_BIT (0 << 6)/* Bit Port */ +#define Z8536_PAB_MODE_PTS_INPUT (1 << 6)/* Input Port */ +#define Z8536_PAB_MODE_PTS_OUTPUT (2 << 6)/* Output Port */ +#define Z8536_PAB_MODE_PTS_BIDIR (3 << 6)/* Bidirectional Port */ +#define Z8536_PAB_MODE_PTS_MASK (3 << 6)/* Port Type Select mask */ +#define Z8536_PAB_MODE_ITB BIT(5) /* Interrupt on Two Bytes */ +#define Z8536_PAB_MODE_SB BIT(4) /* Single Buffered mode */ +#define Z8536_PAB_MODE_IMO BIT(3) /* Interrupt on Match Only */ +#define Z8536_PAB_MODE_PMS_DISABLE (0 << 1)/* Disable Pattern Match */ +#define Z8536_PAB_MODE_PMS_AND (1 << 1)/* "AND" mode */ +#define Z8536_PAB_MODE_PMS_OR (2 << 1)/* "OR" mode */ +#define Z8536_PAB_MODE_PMS_OR_PEV (3 << 1)/* "OR-Priority" mode */ +#define Z8536_PAB_MODE_PMS_MASK (3 << 1)/* Pattern Mode mask */ +#define Z8536_PAB_MODE_LPM BIT(0) /* Latch on Pattern Match */ +#define Z8536_PAB_MODE_DTE BIT(0) /* Deskew Timer Enabled */ + +/* Port A/B Handshake Specification registers */ +#define Z8536_PA_HANDSHAKE_REG 0x21 +#define Z8536_PB_HANDSHAKE_REG 0x29 +#define Z8536_PAB_HANDSHAKE_HST_INTER (0 << 6)/* Interlocked Handshake */ +#define Z8536_PAB_HANDSHAKE_HST_STROBED (1 << 6)/* Strobed Handshake */ +#define Z8536_PAB_HANDSHAKE_HST_PULSED (2 << 6)/* Pulsed Handshake */ +#define Z8536_PAB_HANDSHAKE_HST_3WIRE (3 << 6)/* Three-Wire Handshake */ +#define Z8536_PAB_HANDSHAKE_HST_MASK (3 << 6)/* Handshake Type mask */ +#define Z8536_PAB_HANDSHAKE_RWS_DISABLE (0 << 3)/* Req/Wait Disabled */ +#define Z8536_PAB_HANDSHAKE_RWS_OUTWAIT (1 << 3)/* Output Wait */ +#define Z8536_PAB_HANDSHAKE_RWS_INWAIT (3 << 3)/* Input Wait */ +#define Z8536_PAB_HANDSHAKE_RWS_SPREQ (4 << 3)/* Special Request */ +#define Z8536_PAB_HANDSHAKE_RWS_OUTREQ (5 << 4)/* Output Request */ +#define Z8536_PAB_HANDSHAKE_RWS_INREQ (7 << 3)/* Input Request */ +#define Z8536_PAB_HANDSHAKE_RWS_MASK (7 << 3)/* Req/Wait mask */ +#define Z8536_PAB_HANDSHAKE_DESKEW(x) ((x) << 0)/* Deskew Time */ +#define Z8536_PAB_HANDSHAKE_DESKEW_MASK (3 << 0)/* Deskew Time mask */ + +/* + * Port A/B/C Data Path Polarity registers + * + * 0 = Non-Inverting + * 1 = Inverting + */ +#define Z8536_PA_DPP_REG 0x22 +#define Z8536_PB_DPP_REG 0x2a +#define Z8536_PC_DPP_REG 0x05 + +/* + * Port A/B/C Data Direction registers + * + * 0 = Output bit + * 1 = Input bit + */ +#define Z8536_PA_DD_REG 0x23 +#define Z8536_PB_DD_REG 0x2b +#define Z8536_PC_DD_REG 0x06 + +/* + * Port A/B/C Special I/O Control registers + * + * 0 = Normal Input or Output + * 1 = Output with open drain or Input with 1's catcher + */ +#define Z8536_PA_SIO_REG 0x24 +#define Z8536_PB_SIO_REG 0x2c +#define Z8536_PC_SIO_REG 0x07 + +/* + * Port A/B Pattern Polarity/Transition/Mask registers + * + * PM PT PP Pattern Specification + * -- -- -- ------------------------------------- + * 0 0 x Bit masked off + * 0 1 x Any transition + * 1 0 0 Zero (low-level) + * 1 0 1 One (high-level) + * 1 1 0 One-to-zero transition (falling-edge) + * 1 1 1 Zero-to-one transition (rising-edge) + */ +#define Z8536_PA_PP_REG 0x25 +#define Z8536_PB_PP_REG 0x2d + +#define Z8536_PA_PT_REG 0x26 +#define Z8536_PB_PT_REG 0x2e + +#define Z8536_PA_PM_REG 0x27 +#define Z8536_PB_PM_REG 0x2f + +#endif /* _Z8536_H */ diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index 8777f958c04..973f544e85e 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -95,7 +95,7 @@ static int comedi_do_insn(struct comedi_device *dev, if (s->type == COMEDI_SUBD_UNUSED) { dev_err(dev->class_dev, - "%d not useable subdevice\n", insn->subdev); + "%d not usable subdevice\n", insn->subdev); ret = -EIO; goto error; } diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 9a1dc56f21d..6a393b24bdd 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -1,20 +1,20 @@ /* - module/range.c - comedi routines for voltage ranges - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> - - 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/range.c + * comedi routines for voltage ranges + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include <linux/uaccess.h> #include "comedidev.h" @@ -42,18 +42,18 @@ const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none} } }; EXPORT_SYMBOL_GPL(range_unknown); /* - COMEDI_RANGEINFO - range information ioctl - - arg: - pointer to rangeinfo structure - - reads: - range info structure - - writes: - n struct comedi_krange structures to rangeinfo->range_ptr -*/ + * COMEDI_RANGEINFO ioctl + * range information + * + * arg: + * pointer to comedi_rangeinfo structure + * + * reads: + * comedi_rangeinfo structure + * + * writes: + * array of comedi_krange structures to rangeinfo->range_ptr pointer + */ int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo __user *arg) { diff --git a/drivers/staging/cptm1217/Kconfig b/drivers/staging/cptm1217/Kconfig deleted file mode 100644 index 43b1cc0a50a..00000000000 --- a/drivers/staging/cptm1217/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config TOUCHSCREEN_CLEARPAD_TM1217 - tristate "Synaptics Clearpad TM1217" - depends on I2C - depends on GPIOLIB - depends on INPUT - help - Say Y here if you have a Synaptics Clearpad TM1217 Controller - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called clearpad_tm1217. diff --git a/drivers/staging/cptm1217/Makefile b/drivers/staging/cptm1217/Makefile deleted file mode 100644 index 8961fafa80e..00000000000 --- a/drivers/staging/cptm1217/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += clearpad_tm1217.o - diff --git a/drivers/staging/cptm1217/TODO b/drivers/staging/cptm1217/TODO deleted file mode 100644 index 303922465e4..00000000000 --- a/drivers/staging/cptm1217/TODO +++ /dev/null @@ -1,5 +0,0 @@ -- Wait for the official upstream general clearpad drivers as promised over - the past few months -- Merge any device support needed from this driver into it -- Delete this driver - diff --git a/drivers/staging/cptm1217/clearpad_tm1217.c b/drivers/staging/cptm1217/clearpad_tm1217.c deleted file mode 100644 index 7f265ce0dd1..00000000000 --- a/drivers/staging/cptm1217/clearpad_tm1217.c +++ /dev/null @@ -1,665 +0,0 @@ -/* - * clearpad_tm1217.c - Touch Screen driver for Synaptics Clearpad - * TM1217 controller - * - * Copyright (C) 2008 Intel Corp - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; ifnot, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * Questions/Comments/Bug fixes to Ramesh Agarwal (ramesh.agarwal@intel.com) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/input.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/i2c.h> -#include <linux/timer.h> -#include <linux/gpio.h> -#include <linux/hrtimer.h> -#include <linux/kthread.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include "cp_tm1217.h" - -#define CPTM1217_DEVICE_NAME "cptm1217" -#define CPTM1217_DRIVER_NAME CPTM1217_DEVICE_NAME - -#define MAX_TOUCH_SUPPORTED 2 -#define TOUCH_SUPPORTED 1 -#define SAMPLING_FREQ 80 /* Frequency in HZ */ -#define DELAY_BTWIN_SAMPLE (1000 / SAMPLING_FREQ) -#define WAIT_FOR_RESPONSE 5 /* 5msec just works */ -#define MAX_RETRIES 5 /* As above */ -#define INCREMENTAL_DELAY 5 /* As above */ - -/* Regster Definitions */ -#define TMA1217_DEV_STATUS 0x13 /* Device Status */ -#define TMA1217_INT_STATUS 0x14 /* Interrupt Status */ - -/* Controller can detect up to 2 possible finger touches. - * Each finger touch provides 12 bit X Y co-ordinates, the values are split - * across 2 registers, and an 8 bit Z value */ -#define TMA1217_FINGER_STATE 0x18 /* Finger State */ -#define TMA1217_FINGER1_X_HIGHER8 0x19 /* Higher 8 bit of X coordinate */ -#define TMA1217_FINGER1_Y_HIGHER8 0x1A /* Higher 8 bit of Y coordinate */ -#define TMA1217_FINGER1_XY_LOWER4 0x1B /* Lower 4 bits of X and Y */ -#define TMA1217_FINGER1_Z_VALUE 0x1D /* 8 bit Z value for finger 1 */ -#define TMA1217_FINGER2_X_HIGHER8 0x1E /* Higher 8 bit of X coordinate */ -#define TMA1217_FINGER2_Y_HIGHER8 0x1F /* Higher 8 bit of Y coordinate */ -#define TMA1217_FINGER2_XY_LOWER4 0x20 /* Lower 4 bits of X and Y */ -#define TMA1217_FINGER2_Z_VALUE 0x22 /* 8 bit Z value for finger 2 */ -#define TMA1217_DEVICE_CTRL 0x23 /* Device Control */ -#define TMA1217_INTERRUPT_ENABLE 0x24 /* Interrupt Enable */ -#define TMA1217_REPORT_MODE 0x2B /* Reporting Mode */ -#define TMA1217_MAX_X_LOWER8 0x31 /* Bit 0-7 for Max X */ -#define TMA1217_MAX_X_HIGHER4 0x32 /* Bit 8-11 for Max X */ -#define TMA1217_MAX_Y_LOWER8 0x33 /* Bit 0-7 for Max Y */ -#define TMA1217_MAX_Y_HIGHER4 0x34 /* Bit 8-11 for Max Y */ -#define TMA1217_DEVICE_CMD_RESET 0x67 /* Device CMD reg for reset */ -#define TMA1217_DEVICE_CMD_REZERO 0x69 /* Device CMD reg for rezero */ - -#define TMA1217_MANUFACTURER_ID 0x73 /* Manufacturer Id */ -#define TMA1217_PRODUCT_FAMILY 0x75 /* Product Family */ -#define TMA1217_FIRMWARE_REVISION 0x76 /* Firmware Revision */ -#define TMA1217_SERIAL_NO_HIGH 0x7C /* Bit 8-15 of device serial no. */ -#define TMA1217_SERIAL_NO_LOW 0x7D /* Bit 0-7 of device serial no. */ -#define TMA1217_PRODUCT_ID_START 0x7E /* Start address for 10 byte ID */ -#define TMA1217_DEVICE_CAPABILITY 0x8B /* Reporting capability */ - - -/* - * The touch position structure. - */ -struct touch_state { - int x; - int y; - bool button; -}; - -/* Device Specific info given by the controller */ -struct cp_dev_info { - u16 maxX; - u16 maxY; -}; - -/* Vendor related info given by the controller */ -struct cp_vendor_info { - u8 vendor_id; - u8 product_family; - u8 firmware_rev; - u16 serial_no; -}; - -/* - * Private structure to store the device details - */ -struct cp_tm1217_device { - struct i2c_client *client; - struct device *dev; - struct cp_vendor_info vinfo; - struct cp_dev_info dinfo; - struct input_dev_info { - char phys[32]; - char name[128]; - struct input_dev *input; - struct touch_state touch; - } cp_input_info[MAX_TOUCH_SUPPORTED]; - - int thread_running; - struct mutex thread_mutex; - - int gpio; -}; - - -/* The following functions are used to read/write registers on the device - * as per the RMI prorocol. Technically, a page select should be written - * before doing read/write but since the register offsets are below 0xFF - * we can use the default value of page which is 0x00 - */ -static int cp_tm1217_read(struct cp_tm1217_device *ts, - u8 *req, int size) -{ - int i, retval; - - /* Send the address */ - retval = i2c_master_send(ts->client, &req[0], 1); - if (retval != 1) { - dev_err(ts->dev, "cp_tm1217: I2C send failed\n"); - return retval; - } - msleep(WAIT_FOR_RESPONSE); - for (i = 0; i < MAX_RETRIES; i++) { - retval = i2c_master_recv(ts->client, &req[1], size); - if (retval == size) - break; - - msleep(INCREMENTAL_DELAY); - dev_dbg(ts->dev, "cp_tm1217: Retry count is %d\n", i); - } - if (retval != size) - dev_err(ts->dev, "cp_tm1217: Read from device failed\n"); - - return retval; -} - -static int cp_tm1217_write(struct cp_tm1217_device *ts, - u8 *req, int size) -{ - int retval; - - /* Send the address and the data to be written */ - retval = i2c_master_send(ts->client, &req[0], size + 1); - if (retval != size + 1) { - dev_err(ts->dev, "cp_tm1217: I2C write failed: %d\n", retval); - return retval; - } - /* Wait for the write to complete. TBD why this is required */ - msleep(WAIT_FOR_RESPONSE); - - return size; -} - -static int cp_tm1217_mask_interrupt(struct cp_tm1217_device *ts) -{ - u8 req[2]; - int retval; - - req[0] = TMA1217_INTERRUPT_ENABLE; - req[1] = 0x0; - retval = cp_tm1217_write(ts, req, 1); - if (retval != 1) - return -EIO; - - return 0; -} - -static int cp_tm1217_unmask_interrupt(struct cp_tm1217_device *ts) -{ - u8 req[2]; - int retval; - - req[0] = TMA1217_INTERRUPT_ENABLE; - req[1] = 0xa; - retval = cp_tm1217_write(ts, req, 1); - if (retval != 1) - return -EIO; - - return 0; -} - -static void process_touch(struct cp_tm1217_device *ts, int index) -{ - int retval; - struct input_dev_info *input_info = - (struct input_dev_info *)&ts->cp_input_info[index]; - u8 xy_data[6]; - - if (index == 0) - xy_data[0] = TMA1217_FINGER1_X_HIGHER8; - else - xy_data[0] = TMA1217_FINGER2_X_HIGHER8; - - retval = cp_tm1217_read(ts, xy_data, 5); - if (retval < 5) { - dev_err(ts->dev, "cp_tm1217: XY read from device failed\n"); - return; - } - - /* Note: Currently not using the Z values but may be requried in - the future. */ - input_info->touch.x = (xy_data[1] << 4) - | (xy_data[3] & 0x0F); - input_info->touch.y = (xy_data[2] << 4) - | ((xy_data[3] & 0xF0) >> 4); - input_report_abs(input_info->input, ABS_X, input_info->touch.x); - input_report_abs(input_info->input, ABS_Y, input_info->touch.y); - input_sync(input_info->input); -} - -static void cp_tm1217_get_data(struct cp_tm1217_device *ts) -{ - u8 req[2]; - int retval, i, finger_touched = 0; - - do { - req[0] = TMA1217_FINGER_STATE; - retval = cp_tm1217_read(ts, req, 1); - if (retval != 1) { - dev_err(ts->dev, - "cp_tm1217: Read from device failed\n"); - continue; - } - finger_touched = 0; - /* Start sampling until the pressure is below - threshold */ - for (i = 0; i < TOUCH_SUPPORTED; i++) { - if (req[1] & 0x3) { - finger_touched++; - if (ts->cp_input_info[i].touch.button == 0) { - /* send the button touch event */ - input_report_key( - ts->cp_input_info[i].input, - BTN_TOUCH, 1); - ts->cp_input_info[i].touch.button = 1; - } - process_touch(ts, i); - } else { - if (ts->cp_input_info[i].touch.button == 1) { - /* send the button release event */ - input_report_key( - ts->cp_input_info[i].input, - BTN_TOUCH, 0); - input_sync(ts->cp_input_info[i].input); - ts->cp_input_info[i].touch.button = 0; - } - } - req[1] = req[1] >> 2; - } - msleep(DELAY_BTWIN_SAMPLE); - } while (finger_touched > 0); -} - -static irqreturn_t cp_tm1217_sample_thread(int irq, void *handle) -{ - struct cp_tm1217_device *ts = handle; - u8 req[2]; - int retval; - - /* Chedk if another thread is already running */ - mutex_lock(&ts->thread_mutex); - if (ts->thread_running == 1) { - mutex_unlock(&ts->thread_mutex); - return IRQ_HANDLED; - } - - ts->thread_running = 1; - mutex_unlock(&ts->thread_mutex); - - /* Mask the interrupts */ - retval = cp_tm1217_mask_interrupt(ts); - - /* Read the Interrupt Status register to find the cause of the - Interrupt */ - req[0] = TMA1217_INT_STATUS; - retval = cp_tm1217_read(ts, req, 1); - if (retval != 1) - goto exit_thread; - - if (!(req[1] & 0x8)) - goto exit_thread; - - cp_tm1217_get_data(ts); - -exit_thread: - /* Unmask the interrupts before going to sleep */ - retval = cp_tm1217_unmask_interrupt(ts); - - mutex_lock(&ts->thread_mutex); - ts->thread_running = 0; - mutex_unlock(&ts->thread_mutex); - - return IRQ_HANDLED; -} - -static int cp_tm1217_init_data(struct cp_tm1217_device *ts) -{ - int retval; - u8 req[2]; - - /* Read the vendor id/ fw revision etc. Ignoring return check as this - is non critical info */ - req[0] = TMA1217_MANUFACTURER_ID; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.vendor_id = req[1]; - - req[0] = TMA1217_PRODUCT_FAMILY; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.product_family = req[1]; - - req[0] = TMA1217_FIRMWARE_REVISION; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.firmware_rev = req[1]; - - req[0] = TMA1217_SERIAL_NO_HIGH; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.serial_no = (req[1] << 8); - - req[0] = TMA1217_SERIAL_NO_LOW; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.serial_no = ts->vinfo.serial_no | req[1]; - - req[0] = TMA1217_MAX_X_HIGHER4; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxX = (req[1] & 0xF) << 8; - - req[0] = TMA1217_MAX_X_LOWER8; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxX = ts->dinfo.maxX | req[1]; - - req[0] = TMA1217_MAX_Y_HIGHER4; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxY = (req[1] & 0xF) << 8; - - req[0] = TMA1217_MAX_Y_LOWER8; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxY = ts->dinfo.maxY | req[1]; - - return 0; - -} - -/* - * Set up a GPIO for use as the interrupt. We can't simply do this at - * boot time because the GPIO drivers themselves may not be around at - * boot/firmware set up time to do the work. Instead defer it to driver - * detection. - */ - -static int cp_tm1217_setup_gpio_irq(struct cp_tm1217_device *ts) -{ - int retval; - - /* Hook up the irq handler */ - retval = gpio_request(ts->gpio, "cp_tm1217_touch"); - if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n", - retval); - return retval; - } - - retval = gpio_direction_input(ts->gpio); - if (retval < 0) { - dev_err(ts->dev, - "cp_tm1217: GPIO direction configuration failed, error %d\n", - retval); - gpio_free(ts->gpio); - return retval; - } - - retval = gpio_to_irq(ts->gpio); - if (retval < 0) { - dev_err(ts->dev, - "cp_tm1217: GPIO to IRQ failed, error %d\n", retval); - gpio_free(ts->gpio); - } - dev_dbg(ts->dev, - "cp_tm1217: Got IRQ number is %d for GPIO %d\n", - retval, ts->gpio); - return retval; -} - -static int cp_tm1217_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct cp_tm1217_device *ts; - struct input_dev *input_dev; - struct input_dev_info *input_info; - struct cp_tm1217_platform_data *pdata; - u8 req[2]; - int i, retval; - - /* No pdata is fine - we then use "normal" IRQ mode */ - - pdata = client->dev.platform_data; - - ts = kzalloc(sizeof(struct cp_tm1217_device), GFP_KERNEL); - if (!ts) - return -ENOMEM; - - ts->client = client; - ts->dev = &client->dev; - i2c_set_clientdata(client, ts); - - ts->thread_running = 0; - mutex_init(&ts->thread_mutex); - - /* Reset the Controller */ - req[0] = TMA1217_DEVICE_CMD_RESET; - req[1] = 0x1; - retval = cp_tm1217_write(ts, req, 1); - if (retval != 1) { - dev_err(ts->dev, "cp_tm1217: Controller reset failed\n"); - kfree(ts); - return -EIO; - } - - /* Clear up the interrupt status from reset. */ - req[0] = TMA1217_INT_STATUS; - retval = cp_tm1217_read(ts, req, 1); - - /* Mask all the interrupts */ - retval = cp_tm1217_mask_interrupt(ts); - - /* Read the controller information */ - cp_tm1217_init_data(ts); - - /* The following code will register multiple event devices when - multi-pointer is enabled, the code has not been tested - with MPX */ - for (i = 0; i < TOUCH_SUPPORTED; i++) { - input_dev = input_allocate_device(); - if (input_dev == NULL) { - retval = -ENOMEM; - goto fail; - } - input_info = &ts->cp_input_info[i]; - snprintf(input_info->name, sizeof(input_info->name), - "cp_tm1217_touchscreen_%d", i); - input_dev->name = input_info->name; - snprintf(input_info->phys, sizeof(input_info->phys), - "%s/input%d", dev_name(&client->dev), i); - - input_dev->phys = input_info->phys; - input_dev->id.bustype = BUS_I2C; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - - input_set_abs_params(input_dev, ABS_X, 0, ts->dinfo.maxX, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, ts->dinfo.maxY, 0, 0); - - retval = input_register_device(input_dev); - if (retval) { - dev_err(ts->dev, - "Input dev registration failed for %s\n", - input_dev->name); - input_free_device(input_dev); - goto fail; - } - input_info->input = input_dev; - } - - /* Setup the reporting mode to send an interrupt only when - finger arrives or departs. */ - req[0] = TMA1217_REPORT_MODE; - req[1] = 0x02; - retval = cp_tm1217_write(ts, req, 1); - - /* Setup the device to no sleep mode for now and make it configured */ - req[0] = TMA1217_DEVICE_CTRL; - req[1] = 0x84; - retval = cp_tm1217_write(ts, req, 1); - - /* Check for the status of the device */ - req[0] = TMA1217_DEV_STATUS; - retval = cp_tm1217_read(ts, req, 1); - if (req[1] != 0) { - dev_err(ts->dev, - "cp_tm1217: Device Status 0x%x != 0: config failed\n", - req[1]); - - retval = -EIO; - goto fail; - } - - if (pdata && pdata->gpio) { - ts->gpio = pdata->gpio; - retval = cp_tm1217_setup_gpio_irq(ts); - } else - retval = client->irq; - - if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n", - retval); - goto fail; - } - - client->irq = retval; - - - retval = request_threaded_irq(client->irq, - NULL, cp_tm1217_sample_thread, - IRQF_TRIGGER_FALLING, "cp_tm1217_touch", ts); - if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: Request IRQ error %d\n", retval); - goto fail_gpio; - } - - /* Unmask the interrupts */ - retval = cp_tm1217_unmask_interrupt(ts); - if (retval == 0) - return 0; - - free_irq(client->irq, ts); -fail_gpio: - if (ts->gpio) - gpio_free(ts->gpio); -fail: - /* Clean up before returning failure */ - for (i = 0; i < TOUCH_SUPPORTED; i++) { - if (ts->cp_input_info[i].input) - input_unregister_device(ts->cp_input_info[i].input); - } - kfree(ts); - return retval; - -} - -#ifdef CONFIG_PM_SLEEP - -/* - * cp_tm1217 suspend - * - */ -static int cp_tm1217_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct cp_tm1217_device *ts = i2c_get_clientdata(client); - u8 req[2]; - int retval; - - /* Put the controller to sleep */ - req[0] = TMA1217_DEVICE_CTRL; - retval = cp_tm1217_read(ts, req, 1); - req[1] = (req[1] & 0xF8) | 0x1; - retval = cp_tm1217_write(ts, req, 1); - - if (device_may_wakeup(&client->dev)) - enable_irq_wake(client->irq); - - return 0; -} - -/* - * cp_tm1217_resume - * - */ -static int cp_tm1217_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct cp_tm1217_device *ts = i2c_get_clientdata(client); - u8 req[2]; - int retval; - - /* Take the controller out of sleep */ - req[0] = TMA1217_DEVICE_CTRL; - retval = cp_tm1217_read(ts, req, 1); - req[1] = (req[1] & 0xF8) | 0x4; - retval = cp_tm1217_write(ts, req, 1); - - /* Restore the register settings sinc the power to the - could have been cut off */ - - /* Setup the reporting mode to send an interrupt only when - finger arrives or departs. */ - req[0] = TMA1217_REPORT_MODE; - req[1] = 0x02; - retval = cp_tm1217_write(ts, req, 1); - - /* Setup the device to no sleep mode for now and make it configured */ - req[0] = TMA1217_DEVICE_CTRL; - req[1] = 0x84; - retval = cp_tm1217_write(ts, req, 1); - - /* Setup the interrupt mask */ - retval = cp_tm1217_unmask_interrupt(ts); - - if (device_may_wakeup(&client->dev)) - disable_irq_wake(client->irq); - - return 0; -} - -#endif - -static SIMPLE_DEV_PM_OPS(cp_tm1217_pm_ops, cp_tm1217_suspend, - cp_tm1217_resume); - -/* - * cp_tm1217_remove - * - */ -static int cp_tm1217_remove(struct i2c_client *client) -{ - struct cp_tm1217_device *ts = i2c_get_clientdata(client); - int i; - - free_irq(client->irq, ts); - if (ts->gpio) - gpio_free(ts->gpio); - for (i = 0; i < TOUCH_SUPPORTED; i++) - input_unregister_device(ts->cp_input_info[i].input); - kfree(ts); - return 0; -} - -static struct i2c_device_id cp_tm1217_idtable[] = { - { CPTM1217_DEVICE_NAME, 0 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, cp_tm1217_idtable); - -static struct i2c_driver cp_tm1217_driver = { - .driver = { - .owner = THIS_MODULE, - .name = CPTM1217_DRIVER_NAME, - .pm = &cp_tm1217_pm_ops, - }, - .id_table = cp_tm1217_idtable, - .probe = cp_tm1217_probe, - .remove = cp_tm1217_remove, -}; - -module_i2c_driver(cp_tm1217_driver); - -MODULE_AUTHOR("Ramesh Agarwal <ramesh.agarwal@intel.com>"); -MODULE_DESCRIPTION("Synaptics TM1217 TouchScreen Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/cptm1217/cp_tm1217.h b/drivers/staging/cptm1217/cp_tm1217.h deleted file mode 100644 index 30bad357a05..00000000000 --- a/drivers/staging/cptm1217/cp_tm1217.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __LINUX_I2C_CP_TM1217_H -#define __LINUX_I2C_CP_TM1217_H - -struct cp_tm1217_platform_data { - int gpio; /* If not set uses the IRQ resource 0 */ -}; - -#endif diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index bdb5317e3d9..7184747e065 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -978,8 +978,8 @@ static int dgap_parsefile(char **in) brd->u.board.conc1++; conc_type = dgap_gettok(in); - if (conc_type == 0 || conc_type != CX || - conc_type != EPC) { + if (conc_type == 0 || (conc_type != CX && + conc_type != EPC)) { pr_err("failed to set a type of concentratros"); return -1; } @@ -1019,8 +1019,8 @@ static int dgap_parsefile(char **in) brd->u.board.module1++; module_type = dgap_gettok(in); - if (module_type == 0 || module_type != PORTS || - module_type != MODEM) { + if (module_type == 0 || (module_type != PORTS && + module_type != MODEM)) { pr_err("failed to set a type of module"); return -1; } @@ -1400,27 +1400,27 @@ static int dgap_remap(struct board_t *brd) return -ENOMEM; if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, - "dgap")) { - release_mem_region(brd->membase, 0x200000); - return -ENOMEM; - } + "dgap")) + goto err_req_mem; brd->re_map_membase = ioremap(brd->membase, 0x200000); - if (!brd->re_map_membase) { - release_mem_region(brd->membase, 0x200000); - release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); - return -ENOMEM; - } + if (!brd->re_map_membase) + goto err_remap_mem; brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000); - if (!brd->re_map_port) { - release_mem_region(brd->membase, 0x200000); - release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); - iounmap(brd->re_map_membase); - return -ENOMEM; - } + if (!brd->re_map_port) + goto err_remap_port; return 0; + +err_remap_port: + iounmap(brd->re_map_membase); +err_remap_mem: + release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); +err_req_mem: + release_mem_region(brd->membase, 0x200000); + + return -ENOMEM; } static void dgap_unmap(struct board_t *brd) diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index ba98ff34811..f177d3a258c 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -97,12 +97,12 @@ static uint dgnc_poll_stop; /* Used to tell poller to stop */ static struct timer_list dgnc_poll_timer; -static struct pci_device_id dgnc_pci_tbl[] = { - { DIGI_VID, PCI_DEVICE_CLASSIC_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { DIGI_VID, PCI_DEVICE_CLASSIC_4_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, - { DIGI_VID, PCI_DEVICE_CLASSIC_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, - { DIGI_VID, PCI_DEVICE_CLASSIC_8_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, - {0,} /* 0 terminated list. */ +static const struct pci_device_id dgnc_pci_tbl[] = { + {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_4_DID), .driver_data = 0}, + {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_4_422_DID), .driver_data = 1}, + {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_8_DID), .driver_data = 2}, + {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_8_422_DID), .driver_data = 3}, + {0,} }; MODULE_DEVICE_TABLE(pci, dgnc_pci_tbl); @@ -238,6 +238,7 @@ static int dgnc_start(void) { int rc = 0; unsigned long flags; + struct device *dev; /* make sure that the globals are init'd before we do anything else */ dgnc_init_globals(); @@ -257,9 +258,20 @@ static int dgnc_start(void) dgnc_Major = rc; dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt"); - device_create(dgnc_class, NULL, - MKDEV(dgnc_Major, 0), - NULL, "dgnc_mgmt"); + if (IS_ERR(dgnc_class)) { + rc = PTR_ERR(dgnc_class); + pr_err(DRVSTR ": Can't create dgnc_mgmt class (%d)\n", rc); + goto failed_class; + } + + dev = device_create(dgnc_class, NULL, + MKDEV(dgnc_Major, 0), + NULL, "dgnc_mgmt"); + if (IS_ERR(dev)) { + rc = PTR_ERR(dev); + pr_err(DRVSTR ": Can't create device (%d)\n", rc); + goto failed_device; + } /* * Init any global tty stuff. @@ -268,7 +280,7 @@ static int dgnc_start(void) if (rc < 0) { pr_err(DRVSTR ": tty preinit - not enough memory (%d)\n", rc); - return rc; + goto failed_tty; } /* Start the poller */ @@ -282,6 +294,14 @@ static int dgnc_start(void) add_timer(&dgnc_poll_timer); + return 0; + +failed_tty: + device_destroy(dgnc_class, MKDEV(dgnc_Major, 0)); +failed_device: + class_destroy(dgnc_class); +failed_class: + unregister_chrdev(dgnc_Major, "dgnc"); return rc; } diff --git a/drivers/staging/dgnc/dgnc_utils.c b/drivers/staging/dgnc/dgnc_utils.c index 61efc13ec16..80b51332292 100644 --- a/drivers/staging/dgnc/dgnc_utils.c +++ b/drivers/staging/dgnc/dgnc_utils.c @@ -12,7 +12,7 @@ */ int dgnc_ms_sleep(ulong ms) { - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((ms * HZ) / 1000); return signal_pending(current); } diff --git a/drivers/staging/dgnc/digi.h b/drivers/staging/dgnc/digi.h index 3181a359046..d6e0b9f6b24 100644 --- a/drivers/staging/dgnc/digi.h +++ b/drivers/staging/dgnc/digi.h @@ -38,8 +38,8 @@ #if !defined(TIOCMODG) -#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */ -#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */ +#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ +#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ #ifndef TIOCM_LE #define TIOCM_LE 0x01 /* line enable */ @@ -58,44 +58,44 @@ #endif #if !defined(TIOCMSET) -#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */ -#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */ +#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ +#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ #endif #if !defined(TIOCMBIC) -#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */ -#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */ +#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ +#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ #endif #if !defined(TIOCSDTR) -#define TIOCSDTR ('e'<<8) | 0 /* set DTR */ -#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */ +#define TIOCSDTR (('e'<<8) | 0) /* set DTR */ +#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ #endif /************************************************************************ * Ioctl command arguments for DIGI parameters. ************************************************************************/ -#define DIGI_GETA ('e'<<8) | 94 /* Read params */ +#define DIGI_GETA (('e'<<8) | 94) /* Read params */ -#define DIGI_SETA ('e'<<8) | 95 /* Set params */ -#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */ -#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */ +#define DIGI_SETA (('e'<<8) | 95) /* Set params */ +#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ +#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ -#define DIGI_KME ('e'<<8) | 98 /* Read/Write Host */ +#define DIGI_KME (('e'<<8) | 98) /* Read/Write Host */ /* Adapter Memory */ -#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */ +#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ /* control characters */ -#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */ +#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ /* control characters */ -#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */ +#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ /* flow control chars */ -#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */ +#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ /* flow control chars */ -#define DIGI_GEDELAY ('d'<<8) | 246 /* Get edelay */ -#define DIGI_SEDELAY ('d'<<8) | 247 /* Set edelay */ +#define DIGI_GEDELAY (('d'<<8) | 246) /* Get edelay */ +#define DIGI_SEDELAY (('d'<<8) | 247) /* Set edelay */ struct digiflow_t { unsigned char startc; /* flow cntl start char */ @@ -104,8 +104,8 @@ struct digiflow_t { #ifdef FLOW_2200 -#define F2200_GETA ('e'<<8) | 104 /* Get 2x36 flow cntl flags */ -#define F2200_SETAW ('e'<<8) | 105 /* Set 2x36 flow cntl flags */ +#define F2200_GETA (('e'<<8) | 104) /* Get 2x36 flow cntl flags */ +#define F2200_SETAW (('e'<<8) | 105) /* Set 2x36 flow cntl flags */ #define F2200_MASK 0x03 /* 2200 flow cntl bit mask */ #define FCNTL_2200 0x01 /* 2x36 terminal flow cntl */ #define PCNTL_2200 0x02 /* 2x36 printer flow cntl */ @@ -241,7 +241,7 @@ struct digi_dinfo { char dinfo_version[16]; /* driver version */ }; -#define DIGI_GETDD ('d'<<8) | 248 /* get driver info */ +#define DIGI_GETDD (('d'<<8) | 248) /* get driver info */ /************************************************************************ * Structure used with ioctl commands for per-board information @@ -261,7 +261,7 @@ struct digi_info { char info_reserved[7]; /* for future expansion */ }; -#define DIGI_GETBD ('d'<<8) | 249 /* get board info */ +#define DIGI_GETBD (('d'<<8) | 249) /* get board info */ struct digi_stat { unsigned int info_chan; /* Channel number (0 based) */ @@ -276,7 +276,7 @@ struct digi_stat { unsigned int info_reserved[8]; /* for future expansion */ }; -#define DIGI_GETSTAT ('d'<<8) | 244 /* get board info */ +#define DIGI_GETSTAT (('d'<<8) | 244) /* get board info */ /************************************************************************ * * Structure used with ioctl commands for per-channel information @@ -339,7 +339,7 @@ struct digi_getcounter { #define INFO_CH_WLOW 0x0020 #define INFO_XXBUF_BUSY 0x0040 -#define DIGI_GETCH ('d'<<8) | 245 /* get board info */ +#define DIGI_GETCH (('d'<<8) | 245) /* get board info */ /* Board type definitions */ @@ -384,15 +384,15 @@ struct digi_getcounter { #define BD_TRIBOOT 0x8 #define BD_BADKME 0x80 -#define DIGI_SPOLL ('d'<<8) | 254 /* change poller rate */ +#define DIGI_SPOLL (('d'<<8) | 254) /* change poller rate */ #define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) /* Set integer baud rate */ #define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) /* Get integer baud rate */ -#define DIGI_REALPORT_GETBUFFERS ('e'<<8) | 108 -#define DIGI_REALPORT_SENDIMMEDIATE ('e'<<8) | 109 -#define DIGI_REALPORT_GETCOUNTERS ('e'<<8) | 110 -#define DIGI_REALPORT_GETEVENTS ('e'<<8) | 111 +#define DIGI_REALPORT_GETBUFFERS (('e'<<8) | 108) +#define DIGI_REALPORT_SENDIMMEDIATE (('e'<<8) | 109) +#define DIGI_REALPORT_GETCOUNTERS (('e'<<8) | 110) +#define DIGI_REALPORT_GETEVENTS (('e'<<8) | 111) #define EV_OPU 0x0001 /* !<Output paused by client */ #define EV_OPS 0x0002 /* !<Output paused by reqular sw flowctrl */ diff --git a/drivers/staging/dgnc/dpacompat.h b/drivers/staging/dgnc/dpacompat.h index b2d2dc08f86..33cb394524b 100644 --- a/drivers/staging/dgnc/dpacompat.h +++ b/drivers/staging/dgnc/dpacompat.h @@ -51,7 +51,7 @@ struct ni_info { #define RW_READ 1 #define RW_WRITE 2 -#define DIGI_KME ('e'<<8) | 98 /* Read/Write Host */ +#define DIGI_KME (('e'<<8) | 98) /* Read/Write Host */ #define SUBTYPE 0007 #define T_PCXI 0000 @@ -106,10 +106,10 @@ struct ni_info { /* Ioctls needed for dpa operation */ -#define DIGI_GETDD ('d'<<8) | 248 /* get driver info */ -#define DIGI_GETBD ('d'<<8) | 249 /* get board info */ -#define DIGI_GET_NI_INFO ('d'<<8) | 250 /* nonintelligent state snfo */ +#define DIGI_GETDD (('d'<<8) | 248) /* get driver info */ +#define DIGI_GETBD (('d'<<8) | 249) /* get board info */ +#define DIGI_GET_NI_INFO (('d'<<8) | 250) /* nonintelligent state snfo */ /* Other special ioctls */ -#define DIGI_TIMERIRQ ('d'<<8) | 251 /* Enable/disable RS_TIMER use */ -#define DIGI_LOOPBACK ('d'<<8) | 252 /* Enable/disable UART internal loopback */ +#define DIGI_TIMERIRQ (('d'<<8) | 251) /* Enable/disable RS_TIMER use */ +#define DIGI_LOOPBACK (('d'<<8) | 252) /* Enable/disable UART internal loopback */ diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index bd70ea05708..4be646ce8a1 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -3249,42 +3249,6 @@ static const char *gp_ep_name[NUM_ENDPOINTS] = { }; /*-------------------------------------------------------------------------*/ -static void __init nbu2ss_drv_set_ep_info( - struct nbu2ss_udc *udc, - struct nbu2ss_ep *ep, - const char *name) -{ - ep->udc = udc; - ep->desc = NULL; - - ep->ep.driver_data = NULL; - ep->ep.name = name; - ep->ep.ops = &nbu2ss_ep_ops; - - if (isdigit(name[2])) { - - long num; - int res; - char tempbuf[2]; - - tempbuf[0] = name[2]; - tempbuf[1] = '\0'; - res = kstrtol(tempbuf, 16, &num); - - if (num == 0) - ep->ep.maxpacket = EP0_PACKETSIZE; - else - ep->ep.maxpacket = EP_PACKETSIZE; - - } else { - ep->ep.maxpacket = EP_PACKETSIZE; - } - - list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); - INIT_LIST_HEAD(&ep->queue); -} - -/*-------------------------------------------------------------------------*/ static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) { int i; @@ -3292,9 +3256,21 @@ static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) INIT_LIST_HEAD(&udc->gadget.ep_list); udc->gadget.ep0 = &udc->ep[0].ep; + for (i = 0; i < NUM_ENDPOINTS; i++) { + struct nbu2ss_ep *ep = &udc->ep[i]; - for (i = 0; i < NUM_ENDPOINTS; i++) - nbu2ss_drv_set_ep_info(udc, &udc->ep[i], gp_ep_name[i]); + ep->udc = udc; + ep->desc = NULL; + + ep->ep.driver_data = NULL; + ep->ep.name = gp_ep_name[i]; + ep->ep.ops = &nbu2ss_ep_ops; + + ep->ep.maxpacket = (i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE); + + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + INIT_LIST_HEAD(&ep->queue); + } list_del_init(&udc->ep[0].ep.ep_list); } diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig new file mode 100644 index 00000000000..995a9101a08 --- /dev/null +++ b/drivers/staging/fbtft/Kconfig @@ -0,0 +1,169 @@ +menuconfig FB_TFT + tristate "Support for small TFT LCD display modules" + depends on FB && SPI && GPIOLIB + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + select FB_BACKLIGHT + +config FB_TFT_AGM1264K_FL + tristate "FB driver for the AGM1264K-FL LCD display" + depends on FB_TFT + help + Framebuffer support for the AGM1264K-FL LCD display (two Samsung KS0108 compatable chips) + +config FB_TFT_BD663474 + tristate "FB driver for the BD663474 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for BD663474 + +config FB_TFT_HX8340BN + tristate "FB driver for the HX8340BN LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for HX8340BN + +config FB_TFT_HX8347D + tristate "FB driver for the HX8347D LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for HX8347D + +config FB_TFT_HX8353D + tristate "FB driver for the HX8353D LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for HX8353D + +config FB_TFT_ILI9320 + tristate "FB driver for the ILI9320 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9320 + +config FB_TFT_ILI9325 + tristate "FB driver for the ILI9325 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9325 + +config FB_TFT_ILI9340 + tristate "FB driver for the ILI9340 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9340 + +config FB_TFT_ILI9341 + tristate "FB driver for the ILI9341 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9341 + +config FB_TFT_ILI9481 + tristate "FB driver for the ILI9481 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9481 + +config FB_TFT_ILI9486 + tristate "FB driver for the ILI9486 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9486 + +config FB_TFT_PCD8544 + tristate "FB driver for the PCD8544 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for PCD8544 + +config FB_TFT_RA8875 + tristate "FB driver for the RA8875 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for RA8875 + +config FB_TFT_S6D02A1 + tristate "FB driver for the S6D02A1 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for S6D02A1 + +config FB_TFT_S6D1121 + tristate "FB driver for the S6D1211 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for S6D1121 + +config FB_TFT_SSD1289 + tristate "FB driver for the SSD1289 LCD Controller" + depends on FB_TFT + help + Framebuffer support for SSD1289 + +config FB_TFT_SSD1306 + tristate "FB driver for the SSD1306 OLED Controller" + depends on FB_TFT + help + Framebuffer support for SSD1306 + +config FB_TFT_SSD1331 + tristate "FB driver for the SSD1331 LCD Controller" + depends on FB_TFT + help + Framebuffer support for SSD1331 + +config FB_TFT_SSD1351 + tristate "FB driver for the SSD1351 LCD Controller" + depends on FB_TFT + help + Framebuffer support for SSD1351 + +config FB_TFT_ST7735R + tristate "FB driver for the ST7735R LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ST7735R + +config FB_TFT_TINYLCD + tristate "FB driver for tinylcd.com display" + depends on FB_TFT + help + Custom Framebuffer support for tinylcd.com display + +config FB_TFT_TLS8204 + tristate "FB driver for the TLS8204 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for TLS8204 + +config FB_TFT_UC1701 + tristate "FB driver for the UC1701 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for UC1701 + +config FB_TFT_UPD161704 + tristate "FB driver for the uPD161704 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for uPD161704 + +config FB_TFT_WATTEROTT + tristate "FB driver for the WATTEROTT LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for WATTEROTT + +config FB_FLEX + tristate "Generic FB driver for TFT LCD displays" + depends on FB_TFT + help + Generic Framebuffer support for TFT LCD displays. + +config FB_TFT_FBTFT_DEVICE + tristate "Module to for adding FBTFT devices" + depends on FB_TFT diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile new file mode 100644 index 00000000000..e773f0fdcfe --- /dev/null +++ b/drivers/staging/fbtft/Makefile @@ -0,0 +1,34 @@ +# Core module +obj-$(CONFIG_FB_TFT) += fbtft.o +fbtft-y += fbtft-core.o fbtft-sysfs.o fbtft-bus.o fbtft-io.o + +# drivers +obj-$(CONFIG_FB_TFT_AGM1264K_FL) += fb_agm1264k-fl.o +obj-$(CONFIG_FB_TFT_BD663474) += fb_bd663474.o +obj-$(CONFIG_FB_TFT_HX8340BN) += fb_hx8340bn.o +obj-$(CONFIG_FB_TFT_HX8347D) += fb_hx8347d.o +obj-$(CONFIG_FB_TFT_HX8353D) += fb_hx8353d.o +obj-$(CONFIG_FB_TFT_ILI9320) += fb_ili9320.o +obj-$(CONFIG_FB_TFT_ILI9325) += fb_ili9325.o +obj-$(CONFIG_FB_TFT_ILI9340) += fb_ili9340.o +obj-$(CONFIG_FB_TFT_ILI9341) += fb_ili9341.o +obj-$(CONFIG_FB_TFT_ILI9481) += fb_ili9481.o +obj-$(CONFIG_FB_TFT_ILI9486) += fb_ili9486.o +obj-$(CONFIG_FB_TFT_PCD8544) += fb_pcd8544.o +obj-$(CONFIG_FB_TFT_RA8875) += fb_ra8875.o +obj-$(CONFIG_FB_TFT_S6D02A1) += fb_s6d02a1.o +obj-$(CONFIG_FB_TFT_S6D1121) += fb_s6d1121.o +obj-$(CONFIG_FB_TFT_SSD1289) += fb_ssd1289.o +obj-$(CONFIG_FB_TFT_SSD1306) += fb_ssd1306.o +obj-$(CONFIG_FB_TFT_SSD1331) += fb_ssd1331.o +obj-$(CONFIG_FB_TFT_SSD1351) += fb_ssd1351.o +obj-$(CONFIG_FB_TFT_ST7735R) += fb_st7735r.o +obj-$(CONFIG_FB_TFT_TINYLCD) += fb_tinylcd.o +obj-$(CONFIG_FB_TFT_TLS8204) += fb_tls8204.o +obj-$(CONFIG_FB_TFT_UC1701) += fb_uc1701.o +obj-$(CONFIG_FB_TFT_UPD161704) += fb_upd161704.o +obj-$(CONFIG_FB_TFT_WATTEROTT) += fb_watterott.o +obj-$(CONFIG_FB_FLEX) += flexfb.o + +# Device modules +obj-$(CONFIG_FB_TFT_FBTFT_DEVICE) += fbtft_device.o diff --git a/drivers/staging/fbtft/README b/drivers/staging/fbtft/README new file mode 100644 index 00000000000..bc89b5805f7 --- /dev/null +++ b/drivers/staging/fbtft/README @@ -0,0 +1,32 @@ + FBTFT +========= + +Linux Framebuffer drivers for small TFT LCD display modules. +The module 'fbtft' makes writing drivers for some of these displays very easy. + +Development is done on a Raspberry Pi running the Raspbian "wheezy" distribution. + +INSTALLATION + Download kernel sources + + From Linux 3.15 + cd drivers/video/fbdev/fbtft + git clone https://github.com/notro/fbtft.git + + Add to drivers/video/fbdev/Kconfig: source "drivers/video/fbdev/fbtft/Kconfig" + Add to drivers/video/fbdev/Makefile: obj-y += fbtft/ + + Before Linux 3.15 + cd drivers/video + git clone https://github.com/notro/fbtft.git + + Add to drivers/video/Kconfig: source "drivers/video/fbtft/Kconfig" + Add to drivers/video/Makefile: obj-y += fbtft/ + + Enable driver(s) in menuconfig and build the kernel + + +See wiki for more information: https://github.com/notro/fbtft/wiki + + +Source: https://github.com/notro/fbtft/ diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c new file mode 100644 index 00000000000..9cc7d25cf0e --- /dev/null +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -0,0 +1,462 @@ +/* + * FB driver for Two KS0108 LCD controllers in AGM1264K-FL display + * + * Copyright (C) 2014 ololoshka2871 + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/slab.h> + +#include "fbtft.h" + +/* Uncomment text line to use negative image on display */ +/*#define NEGATIVE*/ + +#define WHITE 0xff +#define BLACK 0 + +#define DRVNAME "fb_agm1264k-fl" +#define WIDTH 64 +#define HEIGHT 64 +#define TOTALWIDTH (WIDTH * 2) /* because 2 x ks0108 in one display */ +#define FPS 20 + +#define EPIN gpio.wr +#define RS gpio.dc +#define RW gpio.aux[2] +#define CS0 gpio.aux[0] +#define CS1 gpio.aux[1] + + +/* diffusing error (“Floyd-Steinberg”) */ +#define DIFFUSING_MATRIX_WIDTH 2 +#define DIFFUSING_MATRIX_HEIGHT 2 + +static const signed char +diffusing_matrix[DIFFUSING_MATRIX_WIDTH][DIFFUSING_MATRIX_HEIGHT] = { + {-1, 3}, + {3, 2}, +}; + +static const unsigned char gamma_correction_table[] = { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, +6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, +13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, +22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, +33, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40, 41, 42, 43, 43, 44, 45, +46, 47, 48, 49, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, +62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 81, +82, 83, 84, 85, 87, 88, 89, 90, 91, 93, 94, 95, 97, 98, 99, 100, 102, +103, 105, 106, 107, 109, 110, 111, 113, 114, 116, 117, 119, 120, 121, +123, 124, 126, 127, 129, 130, 132, 133, 135, 137, 138, 140, 141, 143, +145, 146, 148, 149, 151, 153, 154, 156, 158, 159, 161, 163, 165, 166, +168, 170, 172, 173, 175, 177, 179, 181, 182, 184, 186, 188, 190, 192, +194, 196, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, +221, 223, 225, 227, 229, 231, 234, 236, 238, 240, 242, 244, 246, 248, +251, 253, 255 +}; + +static int init_display(struct fbtft_par *par) +{ + u8 i; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + for (i = 0; i < 2; ++i) { + write_reg(par, i, 0x3f); /* display on */ + write_reg(par, i, 0x40); /* set x to 0 */ + write_reg(par, i, 0xb0); /* set page to 0 */ + write_reg(par, i, 0xc0); /* set start line to 0 */ + } + + return 0; +} + +static void reset(struct fbtft_par *par) +{ + if (par->gpio.reset == -1) + return; + + fbtft_dev_dbg(DEBUG_RESET, par, par->info->device, "%s()\n", __func__); + + gpio_set_value(par->gpio.reset, 0); + udelay(20); + gpio_set_value(par->gpio.reset, 1); + mdelay(120); +} + +/* Check if all necessary GPIOS defined */ +static int verify_gpios(struct fbtft_par *par) +{ + int i; + + fbtft_dev_dbg(DEBUG_VERIFY_GPIOS, par, par->info->device, + "%s()\n", __func__); + + if (par->EPIN < 0) { + dev_err(par->info->device, + "Missing info about 'wr' (aka E) gpio. Aborting.\n"); + return -EINVAL; + } + for (i = 0; i < 8; ++i) { + if (par->gpio.db[i] < 0) { + dev_err(par->info->device, + "Missing info about 'db[%i]' gpio. Aborting.\n", + i); + return -EINVAL; + } + } + if (par->CS0 < 0) { + dev_err(par->info->device, + "Missing info about 'cs0' gpio. Aborting.\n"); + return -EINVAL; + } + if (par->CS1 < 0) { + dev_err(par->info->device, + "Missing info about 'cs1' gpio. Aborting.\n"); + return -EINVAL; + } + if (par->RW < 0) { + dev_err(par->info->device, + "Missing info about 'rw' gpio. Aborting.\n"); + return -EINVAL; + } + + return 0; +} + +static unsigned long +request_gpios_match(struct fbtft_par *par, const struct fbtft_gpio *gpio) +{ + fbtft_dev_dbg(DEBUG_REQUEST_GPIOS_MATCH, par, par->info->device, + "%s('%s')\n", __func__, gpio->name); + + if (strcasecmp(gpio->name, "wr") == 0) { + /* left ks0108 E pin */ + par->EPIN = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } else if (strcasecmp(gpio->name, "cs0") == 0) { + /* left ks0108 controller pin */ + par->CS0 = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "cs1") == 0) { + /* right ks0108 controller pin */ + par->CS1 = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } + + /* if write (rw = 0) e(1->0) perform write */ + /* if read (rw = 1) e(0->1) set data on D0-7*/ + else if (strcasecmp(gpio->name, "rw") == 0) { + par->RW = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } + + return FBTFT_GPIO_NO_MATCH; +} + +/* This function oses to enter commands + * first byte - destination controller 0 or 1 + * folowing - commands + */ +static void write_reg8_bus8(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + u8 *buf = (u8 *)par->buf; + + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { + va_start(args, len); + for (i = 0; i < len; i++) + buf[i] = (u8)va_arg(args, unsigned int); + + va_end(args); + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, + par->info->device, u8, buf, len, "%s: ", __func__); + } + + va_start(args, len); + + *buf = (u8)va_arg(args, unsigned int); + + if (*buf > 1) { + va_end(args); + dev_err(par->info->device, "%s: Incorrect chip sellect request (%d)\n", + __func__, *buf); + return; + } + + /* select chip */ + if (*buf) { + /* cs1 */ + gpio_set_value(par->CS0, 1); + gpio_set_value(par->CS1, 0); + } else { + /* cs0 */ + gpio_set_value(par->CS0, 0); + gpio_set_value(par->CS1, 1); + } + + gpio_set_value(par->RS, 0); /* RS->0 (command mode) */ + len--; + + if (len) { + i = len; + while (i--) + *buf++ = (u8)va_arg(args, unsigned int); + ret = par->fbtftops.write(par, par->buf, len * (sizeof(u8))); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %d\n", + __func__, ret); + return; + } + } + + va_end(args); +} + +static struct +{ + int xs, ys_page, xe, ye_page; +} addr_win; + +/* save display writing zone */ +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + addr_win.xs = xs; + addr_win.ys_page = ys / 8; + addr_win.xe = xe; + addr_win.ye_page = ye / 8; + + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys_page=%d, xe=%d, ye_page=%d)\n", __func__, + addr_win.xs, addr_win.ys_page, addr_win.xe, addr_win.ye_page); +} + +static void +construct_line_bitmap(struct fbtft_par *par, u8 *dest, signed short *src, + int xs, int xe, int y) +{ + int x, i; + + for (x = xs; x < xe; ++x) { + u8 res = 0; + + for (i = 0; i < 8; i++) + if (src[(y * 8 + i) * par->info->var.xres + x]) + res |= 1 << i; +#ifdef NEGATIVE + *dest++ = res; +#else + *dest++ = ~res; +#endif + } +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + u8 *buf = par->txbuf.buf; + int x, y; + int ret = 0; + + /* buffer to convert RGB565 -> grayscale16 -> Ditherd image 1bpp */ + signed short *convert_buf = kmalloc(par->info->var.xres * + par->info->var.yres * sizeof(signed short), GFP_NOIO); + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + /* converting to grayscale16 */ + for (x = 0; x < par->info->var.xres; ++x) + for (y = 0; y < par->info->var.yres; ++y) { + u16 pixel = vmem16[y * par->info->var.xres + x]; + u16 b = pixel & 0x1f; + u16 g = (pixel & (0x3f << 5)) >> 5; + u16 r = (pixel & (0x1f << (5 + 6))) >> (5 + 6); + + pixel = (299 * r + 587 * g + 114 * b) / 200; + if (pixel > 255) + pixel = 255; + + /* gamma-correction by table */ + convert_buf[y * par->info->var.xres + x] = + (signed short)gamma_correction_table[pixel]; + } + + /* Image Dithering */ + for (x = 0; x < par->info->var.xres; ++x) + for (y = 0; y < par->info->var.yres; ++y) { + signed short pixel = + convert_buf[y * par->info->var.xres + x]; + signed short error_b = pixel - BLACK; + signed short error_w = pixel - WHITE; + signed short error; + u16 i, j; + + /* what color close? */ + if (abs(error_b) >= abs(error_w)) { + /* white */ + error = error_w; + pixel = 0xff; + } else { + /* black */ + error = error_b; + pixel = 0; + } + + error /= 8; + + /* diffusion matrix row */ + for (i = 0; i < DIFFUSING_MATRIX_WIDTH; ++i) + /* diffusion matrix column */ + for (j = 0; j < DIFFUSING_MATRIX_HEIGHT; ++j) { + signed short *write_pos; + signed char coeff; + + /* skip pixels out of zone */ + if (x + i < 0 || + x + i >= par->info->var.xres + || y + j >= par->info->var.yres) + continue; + write_pos = &convert_buf[ + (y + j) * par->info->var.xres + + x + i]; + coeff = diffusing_matrix[i][j]; + if (coeff == -1) + /* pixel itself */ + *write_pos = pixel; + else { + signed short p = *write_pos + + error * coeff; + + if (p > WHITE) + p = WHITE; + if (p < BLACK) + p = BLACK; + *write_pos = p; + } + } + } + + /* 1 string = 2 pages */ + for (y = addr_win.ys_page; y <= addr_win.ye_page; ++y) { + /* left half of display */ + if (addr_win.xs < par->info->var.xres / 2) { + construct_line_bitmap(par, buf, convert_buf, + addr_win.xs, par->info->var.xres / 2, y); + + len = par->info->var.xres / 2 - addr_win.xs; + + /* select left side (sc0) + * set addr + */ + write_reg(par, 0x00, (1 << 6) | (u8)addr_win.xs); + write_reg(par, 0x00, (0x17 << 3) | (u8)y); + + /* write bitmap */ + gpio_set_value(par->RS, 1); /* RS->1 (data mode) */ + ret = par->fbtftops.write(par, buf, len); + if (ret < 0) + dev_err(par->info->device, + "%s: write failed and returned: %d\n", + __func__, ret); + } + /* right half of display */ + if (addr_win.xe >= par->info->var.xres / 2) { + construct_line_bitmap(par, buf, + convert_buf, par->info->var.xres / 2, + addr_win.xe + 1, y); + + len = addr_win.xe + 1 - par->info->var.xres / 2; + + /* select right side (sc1) + * set addr + */ + write_reg(par, 0x01, (1 << 6)); + write_reg(par, 0x01, (0x17 << 3) | (u8)y); + + /* write bitmap */ + gpio_set_value(par->RS, 1); /* RS->1 (data mode) */ + par->fbtftops.write(par, buf, len); + if (ret < 0) + dev_err(par->info->device, + "%s: write failed and returned: %d\n", + __func__, ret); + } + } + kfree(convert_buf); + + gpio_set_value(par->CS0, 1); + gpio_set_value(par->CS1, 1); + + return ret; +} + +static int write(struct fbtft_par *par, void *buf, size_t len) +{ + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + gpio_set_value(par->RW, 0); /* set write mode */ + + + while (len--) { + u8 i, data; + + data = *(u8 *) buf++; + + /* set data bus */ + for (i = 0; i < 8; ++i) + gpio_set_value(par->gpio.db[i], data & (1 << i)); + /* set E */ + gpio_set_value(par->EPIN, 1); + udelay(5); + /* unset E - write */ + gpio_set_value(par->EPIN, 0); + udelay(1); + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 8, + .width = TOTALWIDTH, + .height = HEIGHT, + .fps = FPS, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .verify_gpios = verify_gpios, + .request_gpios_match = request_gpios_match, + .reset = reset, + .write = write, + .write_register = write_reg8_bus8, + .write_vmem = write_vmem, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "displaytronic,fb_agm1264k-fl", &display); + +MODULE_ALIAS("platform:" DRVNAME); + +MODULE_DESCRIPTION("Two KS0108 LCD controllers in AGM1264K-FL display"); +MODULE_AUTHOR("ololoshka2871"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_bd663474.c b/drivers/staging/fbtft/fb_bd663474.c new file mode 100644 index 00000000000..7e00c609c7f --- /dev/null +++ b/drivers/staging/fbtft/fb_bd663474.c @@ -0,0 +1,193 @@ +/* + * FB driver for the uPD161704 LCD Controller + * + * Copyright (C) 2014 Seong-Woo Kim + * + * Based on fb_ili9325.c by Noralf Tronnes + * Based on ili9325.c by Jeroen Domburg + * Init code from UTFT library by Henning Karlsen + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_bd663474" +#define WIDTH 240 +#define HEIGHT 320 +#define BPP 16 + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + par->fbtftops.reset(par); + + /* Initialization sequence from Lib_UTFT */ + + /* oscillator start */ + write_reg(par, 0x000,0x0001); /*oscillator 0: stop, 1: operation */ + mdelay(10); + + /* Power settings */ + write_reg(par, 0x100, 0x0000 ); /* power supply setup */ + write_reg(par, 0x101, 0x0000 ); + write_reg(par, 0x102, 0x3110 ); + write_reg(par, 0x103, 0xe200 ); + write_reg(par, 0x110, 0x009d ); + write_reg(par, 0x111, 0x0022 ); + write_reg(par, 0x100, 0x0120 ); + mdelay( 20 ); + + write_reg(par, 0x100, 0x3120 ); + mdelay( 80 ); + /* Display control */ + write_reg(par, 0x001, 0x0100 ); + write_reg(par, 0x002, 0x0000 ); + write_reg(par, 0x003, 0x1230 ); + write_reg(par, 0x006, 0x0000 ); + write_reg(par, 0x007, 0x0101 ); + write_reg(par, 0x008, 0x0808 ); + write_reg(par, 0x009, 0x0000 ); + write_reg(par, 0x00b, 0x0000 ); + write_reg(par, 0x00c, 0x0000 ); + write_reg(par, 0x00d, 0x0018 ); + /* LTPS control settings */ + write_reg(par, 0x012, 0x0000 ); + write_reg(par, 0x013, 0x0000 ); + write_reg(par, 0x018, 0x0000 ); + write_reg(par, 0x019, 0x0000 ); + + write_reg(par, 0x203, 0x0000 ); + write_reg(par, 0x204, 0x0000 ); + + write_reg(par, 0x210, 0x0000 ); + write_reg(par, 0x211, 0x00ef ); + write_reg(par, 0x212, 0x0000 ); + write_reg(par, 0x213, 0x013f ); + write_reg(par, 0x214, 0x0000 ); + write_reg(par, 0x215, 0x0000 ); + write_reg(par, 0x216, 0x0000 ); + write_reg(par, 0x217, 0x0000 ); + + /* Gray scale settings */ + write_reg(par, 0x300, 0x5343); + write_reg(par, 0x301, 0x1021); + write_reg(par, 0x302, 0x0003); + write_reg(par, 0x303, 0x0011); + write_reg(par, 0x304, 0x050a); + write_reg(par, 0x305, 0x4342); + write_reg(par, 0x306, 0x1100); + write_reg(par, 0x307, 0x0003); + write_reg(par, 0x308, 0x1201); + write_reg(par, 0x309, 0x050a); + + /* RAM access settings */ + write_reg(par, 0x400, 0x4027 ); + write_reg(par, 0x401, 0x0000 ); + write_reg(par, 0x402, 0x0000 ); /* First screen drive position (1) */ + write_reg(par, 0x403, 0x013f ); /* First screen drive position (2) */ + write_reg(par, 0x404, 0x0000 ); + + write_reg(par, 0x200, 0x0000 ); + write_reg(par, 0x201, 0x0000 ); + write_reg(par, 0x100, 0x7120 ); + write_reg(par, 0x007, 0x0103 ); + mdelay( 10 ); + write_reg(par, 0x007, 0x0113 ); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R200h = Horizontal GRAM Start Address */ + /* R201h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0200, xs); + write_reg(par, 0x0201, ys); + break; + case 180: + write_reg(par, 0x0200, WIDTH - 1 - xs); + write_reg(par, 0x0201, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0200, WIDTH - 1 - ys); + write_reg(par, 0x0201, xs); + break; + case 90: + write_reg(par, 0x0200, ys); + write_reg(par, 0x0201, HEIGHT - 1 - xs); + break; + } + write_reg(par, 0x202); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + /* AM: GRAM update direction */ + case 0: + write_reg(par, 0x003, 0x1230); + break; + case 180: + write_reg(par, 0x003, 0x1200); + break; + case 270: + write_reg(par, 0x003, 0x1228); + break; + case 90: + write_reg(par, 0x003, 0x1218); + break; + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .bpp = BPP, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "hitachi,bd663474", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:bd663474"); +MODULE_ALIAS("platform:bd663474"); + +MODULE_DESCRIPTION("FB driver for the uPD161704 LCD Controller"); +MODULE_AUTHOR("Seong-Woo Kim"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_hx8340bn.c b/drivers/staging/fbtft/fb_hx8340bn.c new file mode 100644 index 00000000000..3939502f2c8 --- /dev/null +++ b/drivers/staging/fbtft/fb_hx8340bn.c @@ -0,0 +1,229 @@ +/* + * FB driver for the HX8340BN LCD Controller + * + * This display uses 9-bit SPI: Data/Command bit + 8 data bits + * For platforms that doesn't support 9-bit, the driver is capable + * of emulating this using 8-bit transfer. + * This is done by transfering eight 9-bit words in 9 bytes. + * + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/vmalloc.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_hx8340bn" +#define WIDTH 176 +#define HEIGHT 220 +#define TXBUFLEN (4 * PAGE_SIZE) +#define DEFAULT_GAMMA "1 3 0E 5 0 2 09 0 6 1 7 1 0 2 2\n" \ + "3 3 17 8 4 7 05 7 6 0 3 1 6 0 0 " + + +static bool emulate; +module_param(emulate, bool, 0); +MODULE_PARM_DESC(emulate, "Force emulation in 9-bit mode"); + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* BTL221722-276L startup sequence, from datasheet */ + + /* SETEXTCOM: Set extended command set (C1h) + This command is used to set extended command set access enable. + Enable: After command (C1h), must write: ffh,83h,40h */ + write_reg(par, 0xC1, 0xFF, 0x83, 0x40); + + /* Sleep out + This command turns off sleep mode. + In this mode the DC/DC converter is enabled, Internal oscillator + is started, and panel scanning is started. */ + write_reg(par, 0x11); + mdelay(150); + + /* Undoc'd register? */ + write_reg(par, 0xCA, 0x70, 0x00, 0xD9); + + /* SETOSC: Set Internal Oscillator (B0h) + This command is used to set internal oscillator related settings */ + /* OSC_EN: Enable internal oscillator */ + /* Internal oscillator frequency: 125% x 2.52MHz */ + write_reg(par, 0xB0, 0x01, 0x11); + + /* Drive ability setting */ + write_reg(par, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06); + mdelay(20); + + /* SETPWCTR5: Set Power Control 5(B5h) + This command is used to set VCOM Low and VCOM High Voltage */ + /* VCOMH 0110101 : 3.925 */ + /* VCOML 0100000 : -1.700 */ + /* 45h=69 VCOMH: "VMH" + 5d VCOML: "VMH" + 5d */ + write_reg(par, 0xB5, 0x35, 0x20, 0x45); + + /* SETPWCTR4: Set Power Control 4(B4h) + VRH[4:0]: Specify the VREG1 voltage adjusting. + VREG1 voltage is for gamma voltage setting. + BT[2:0]: Switch the output factor of step-up circuit 2 + for VGH and VGL voltage generation. */ + write_reg(par, 0xB4, 0x33, 0x25, 0x4C); + mdelay(10); + + /* Interface Pixel Format (3Ah) + This command is used to define the format of RGB picture data, + which is to be transfer via the system and RGB interface. */ + /* RGB interface: 16 Bit/Pixel */ + write_reg(par, 0x3A, 0x05); + + /* Display on (29h) + This command is used to recover from DISPLAY OFF mode. + Output from the Frame Memory is enabled. */ + write_reg(par, 0x29); + mdelay(10); + + return 0; +} + +void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, FBTFT_CASET, 0x00, xs, 0x00, xe); + write_reg(par, FBTFT_RASET, 0x00, ys, 0x00, ye); + write_reg(par, FBTFT_RAMWR); +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* MADCTL - Memory data access control */ + /* RGB/BGR can be set with H/W pin SRGB and MADCTL BGR bit */ +#define MY (1 << 7) +#define MX (1 << 6) +#define MV (1 << 5) + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, MX | MV | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, MX | MY | (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, MY | MV | (par->bgr << 3)); + break; + } + + return 0; +} + +/* + Gamma Curve selection, GC (only GC0 can be customized): + 0 = 2.2, 1 = 1.8, 2 = 2.5, 3 = 1.0 + Gamma string format: + OP0 OP1 CP0 CP1 CP2 CP3 CP4 MP0 MP1 MP2 MP3 MP4 MP5 CGM0 CGM1 + ON0 ON1 CN0 CN1 CN2 CN3 CN4 MN0 MN1 MN2 MN3 MN4 MN5 XXXX GC +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b1111, 0b1111, 0b11111, 0b1111, 0b1111, 0b1111, 0b11111, + 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b11, 0b11, + 0b1111, 0b1111, 0b11111, 0b1111, 0b1111, 0b1111, 0b11111, + 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b0, 0b0 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < par->gamma.num_curves; i++) + for (j = 0; j < par->gamma.num_values; j++) + CURVE(i, j) &= mask[i * par->gamma.num_values + j]; + + write_reg(par, 0x26, 1 << CURVE(1, 14)); /* Gamma Set (26h) */ + + if (CURVE(1, 14)) + return 0; /* only GC0 can be customized */ + + write_reg(par, 0xC2, + (CURVE(0, 8) << 4) | CURVE(0, 7), + (CURVE(0, 10) << 4) | CURVE(0, 9), + (CURVE(0, 12) << 4) | CURVE(0, 11), + CURVE(0, 2), + (CURVE(0, 4) << 4) | CURVE(0, 3), + CURVE(0, 5), + CURVE(0, 6), + (CURVE(0, 1) << 4) | CURVE(0, 0), + (CURVE(0, 14) << 2) | CURVE(0, 13)); + + write_reg(par, 0xC3, + (CURVE(1, 8) << 4) | CURVE(1, 7), + (CURVE(1, 10) << 4) | CURVE(1, 9), + (CURVE(1, 12) << 4) | CURVE(1, 11), + CURVE(1, 2), + (CURVE(1, 4) << 4) | CURVE(1, 3), + CURVE(1, 5), + CURVE(1, 6), + (CURVE(1, 1) << 4) | CURVE(1, 0)); + + mdelay(10); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .txbuflen = TXBUFLEN, + .gamma_num = 2, + .gamma_len = 15, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8340bn", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:hx8340bn"); +MODULE_ALIAS("platform:hx8340bn"); + +MODULE_DESCRIPTION("FB driver for the HX8340BN LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_hx8347d.c b/drivers/staging/fbtft/fb_hx8347d.c new file mode 100644 index 00000000000..8139a8f587b --- /dev/null +++ b/drivers/staging/fbtft/fb_hx8347d.c @@ -0,0 +1,181 @@ +/* + * FB driver for the HX8347D LCD Controller + * + * Copyright (C) 2013 Christian Vogelgsang + * + * Based on driver code found here: https://github.com/watterott/r61505u-Adapter + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_hx8347d" +#define WIDTH 320 +#define HEIGHT 240 +#define DEFAULT_GAMMA "0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" \ + "0 0 0 0 0 0 0 0 0 0 0 0 0 0" + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* driving ability */ + write_reg(par, 0xEA, 0x00); + write_reg(par, 0xEB, 0x20); + write_reg(par, 0xEC, 0x0C); + write_reg(par, 0xED, 0xC4); + write_reg(par, 0xE8, 0x40); + write_reg(par, 0xE9, 0x38); + write_reg(par, 0xF1, 0x01); + write_reg(par, 0xF2, 0x10); + write_reg(par, 0x27, 0xA3); + + /* power voltage */ + write_reg(par, 0x1B, 0x1B); + write_reg(par, 0x1A, 0x01); + write_reg(par, 0x24, 0x2F); + write_reg(par, 0x25, 0x57); + + /* VCOM offset */ + write_reg(par, 0x23, 0x8D); /* for flicker adjust */ + + /* power on */ + write_reg(par, 0x18, 0x36); + write_reg(par, 0x19, 0x01); /* start osc */ + write_reg(par, 0x01, 0x00); /* wakeup */ + write_reg(par, 0x1F, 0x88); + mdelay(5); + write_reg(par, 0x1F, 0x80); + mdelay(5); + write_reg(par, 0x1F, 0x90); + mdelay(5); + write_reg(par, 0x1F, 0xD0); + mdelay(5); + + /* color selection */ + write_reg(par, 0x17, 0x05); /* 65k */ + + /*panel characteristic */ + write_reg(par, 0x36, 0x00); + + /*display on */ + write_reg(par, 0x28, 0x38); + mdelay(40); + write_reg(par, 0x28, 0x3C); + + /* orientation */ + write_reg(par, 0x16, 0x60 | (par->bgr << 3)); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, 0x02, (xs >> 8) & 0xFF); + write_reg(par, 0x03, xs & 0xFF); + write_reg(par, 0x04, (xe >> 8) & 0xFF); + write_reg(par, 0x05, xe & 0xFF); + write_reg(par, 0x06, (ys >> 8) & 0xFF); + write_reg(par, 0x07, ys & 0xFF); + write_reg(par, 0x08, (ye >> 8) & 0xFF); + write_reg(par, 0x09, ye & 0xFF); + write_reg(par, 0x22); +} + +/* + Gamma string format: + VRP0 VRP1 VRP2 VRP3 VRP4 VRP5 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 CGM + VRN0 VRN1 VRN2 VRN3 VRN4 VRN5 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 CGM +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b1111111, 0b1111111, + 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, + 0b1111}; + int i, j; + int acc = 0; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < par->gamma.num_curves; i++) + for (j = 0; j < par->gamma.num_values; j++) { + acc += CURVE(i, j); + CURVE(i, j) &= mask[j]; + } + + if (acc == 0) /* skip if all values are zero */ + return 0; + + for (i = 0; i < par->gamma.num_curves; i++) { + write_reg(par, 0x40 + (i * 0x10), CURVE(i, 0)); + write_reg(par, 0x41 + (i * 0x10), CURVE(i, 1)); + write_reg(par, 0x42 + (i * 0x10), CURVE(i, 2)); + write_reg(par, 0x43 + (i * 0x10), CURVE(i, 3)); + write_reg(par, 0x44 + (i * 0x10), CURVE(i, 4)); + write_reg(par, 0x45 + (i * 0x10), CURVE(i, 5)); + write_reg(par, 0x46 + (i * 0x10), CURVE(i, 6)); + write_reg(par, 0x47 + (i * 0x10), CURVE(i, 7)); + write_reg(par, 0x48 + (i * 0x10), CURVE(i, 8)); + write_reg(par, 0x49 + (i * 0x10), CURVE(i, 9)); + write_reg(par, 0x4A + (i * 0x10), CURVE(i, 10)); + write_reg(par, 0x4B + (i * 0x10), CURVE(i, 11)); + write_reg(par, 0x4C + (i * 0x10), CURVE(i, 12)); + } + write_reg(par, 0x5D, (CURVE(1, 0) << 4) | CURVE(0, 0)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = 2, + .gamma_len = 14, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8347d", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:hx8347d"); +MODULE_ALIAS("platform:hx8347d"); + +MODULE_DESCRIPTION("FB driver for the HX8347D LCD Controller"); +MODULE_AUTHOR("Christian Vogelgsang"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_hx8353d.c b/drivers/staging/fbtft/fb_hx8353d.c new file mode 100644 index 00000000000..c9512dc5f4d --- /dev/null +++ b/drivers/staging/fbtft/fb_hx8353d.c @@ -0,0 +1,166 @@ +/* + * FB driver for the HX8353D LCD Controller + * + * Copyright (c) 2014 Petr Olivka + * Copyright (c) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_hx8353d" +#define DEFAULT_GAMMA "50 77 40 08 BF 00 03 0F 00 01 73 00 72 03 B0 0F 08 00 0F" + +static int init_display(struct fbtft_par *par) +{ + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + mdelay(150); + + /* SETEXTC */ + write_reg(par, 0xB9, 0xFF, 0x83, 0x53); + + /* RADJ */ + write_reg(par, 0xB0, 0x3C, 0x01); + + /* VCOM */ + write_reg(par, 0xB6, 0x94, 0x6C, 0x50); + + /* PWR */ + write_reg(par, 0xB1, 0x00, 0x01, 0x1B, 0x03, 0x01, 0x08, 0x77, 0x89); + + /* COLMOD */ + write_reg(par, 0x3A, 0x05); + + /* MEM ACCESS */ + write_reg(par, 0x36, 0xC0); + + /* SLPOUT - Sleep out & booster on */ + write_reg(par, 0x11); + mdelay(150); + + /* DISPON - Display On */ + write_reg(par, 0x29); + + /* RGBSET */ + write_reg(par, 0x2D, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62); + + return 0; +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* column address */ + write_reg(par, 0x2a, xs >> 8, xs & 0xff, xe >> 8, xe & 0xff); + + /* row adress */ + write_reg(par, 0x2b, ys >> 8, ys & 0xff, ye >> 8, ye & 0xff); + + /* memory write */ + write_reg(par, 0x2c); +} + +#define my (1 << 7) +#define mx (1 << 6) +#define mv (1 << 5) +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* madctl - memory data access control + rgb/bgr: + 1. mode selection pin srgb + rgb h/w pin for color filter setting: 0=rgb, 1=bgr + 2. madctl rgb bit + rgb-bgr order color filter panel: 0=rgb, 1=bgr */ + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, mx | my | (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, my | mv | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, mx | mv | (par->bgr << 3)); + break; + } + + return 0; +} + +/* + gamma string format: +*/ +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + write_reg(par, 0xE0, + curves[0], curves[1], curves[2], curves[3], + curves[4], curves[5], curves[6], curves[7], + curves[8], curves[9], curves[10], curves[11], + curves[12], curves[13], curves[14], curves[15], + curves[16], curves[17], curves[18]); + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = 128, + .height = 160, + .gamma_num = 1, + .gamma_len = 19, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8353d", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:hx8353d"); +MODULE_ALIAS("platform:hx8353d"); + +MODULE_DESCRIPTION("FB driver for the HX8353D LCD Controller"); +MODULE_AUTHOR("Petr Olivka"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c new file mode 100644 index 00000000000..b26d89368da --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -0,0 +1,234 @@ +/* + * FB driver for the ILI9320 LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ili9320" +#define WIDTH 240 +#define HEIGHT 320 +#define DEFAULT_GAMMA "07 07 6 0 0 0 5 5 4 0\n" \ + "07 08 4 7 5 1 2 0 7 7" + + +static unsigned read_devicecode(struct fbtft_par *par) +{ + int ret; + u8 rxbuf[8] = {0, }; + + write_reg(par, 0x0000); + ret = par->fbtftops.read(par, rxbuf, 4); + return (rxbuf[2] << 8) | rxbuf[3]; +} + +static int init_display(struct fbtft_par *par) +{ + unsigned devcode; + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + devcode = read_devicecode(par); + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "Device code: 0x%04X\n", + devcode); + if ((devcode != 0x0000) && (devcode != 0x9320)) + dev_warn(par->info->device, + "Unrecognized Device code: 0x%04X (expected 0x9320)\n", + devcode); + + /* Initialization sequence from ILI9320 Application Notes */ + + /* *********** Start Initial Sequence ********* */ + write_reg(par, 0x00E5, 0x8000); /* Set the Vcore voltage and this setting is must. */ + write_reg(par, 0x0000, 0x0001); /* Start internal OSC. */ + write_reg(par, 0x0001, 0x0100); /* set SS and SM bit */ + write_reg(par, 0x0002, 0x0700); /* set 1 line inversion */ + write_reg(par, 0x0004, 0x0000); /* Resize register */ + write_reg(par, 0x0008, 0x0202); /* set the back and front porch */ + write_reg(par, 0x0009, 0x0000); /* set non-display area refresh cycle */ + write_reg(par, 0x000A, 0x0000); /* FMARK function */ + write_reg(par, 0x000C, 0x0000); /* RGB interface setting */ + write_reg(par, 0x000D, 0x0000); /* Frame marker Position */ + write_reg(par, 0x000F, 0x0000); /* RGB interface polarity */ + + /* ***********Power On sequence *************** */ + write_reg(par, 0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + write_reg(par, 0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */ + write_reg(par, 0x0012, 0x0000); /* VREG1OUT voltage */ + write_reg(par, 0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */ + mdelay(200); /* Dis-charge capacitor power voltage */ + write_reg(par, 0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + write_reg(par, 0x0011, 0x0031); /* R11h=0x0031 at VCI=3.3V DC1[2:0], DC0[2:0], VC[2:0] */ + mdelay(50); + write_reg(par, 0x0012, 0x0138); /* R12h=0x0138 at VCI=3.3V VREG1OUT voltage */ + mdelay(50); + write_reg(par, 0x0013, 0x1800); /* R13h=0x1800 at VCI=3.3V VDV[4:0] for VCOM amplitude */ + write_reg(par, 0x0029, 0x0008); /* R29h=0x0008 at VCI=3.3V VCM[4:0] for VCOMH */ + mdelay(50); + write_reg(par, 0x0020, 0x0000); /* GRAM horizontal Address */ + write_reg(par, 0x0021, 0x0000); /* GRAM Vertical Address */ + + /* ------------------ Set GRAM area --------------- */ + write_reg(par, 0x0050, 0x0000); /* Horizontal GRAM Start Address */ + write_reg(par, 0x0051, 0x00EF); /* Horizontal GRAM End Address */ + write_reg(par, 0x0052, 0x0000); /* Vertical GRAM Start Address */ + write_reg(par, 0x0053, 0x013F); /* Vertical GRAM Start Address */ + write_reg(par, 0x0060, 0x2700); /* Gate Scan Line */ + write_reg(par, 0x0061, 0x0001); /* NDL,VLE, REV */ + write_reg(par, 0x006A, 0x0000); /* set scrolling line */ + + /* -------------- Partial Display Control --------- */ + write_reg(par, 0x0080, 0x0000); + write_reg(par, 0x0081, 0x0000); + write_reg(par, 0x0082, 0x0000); + write_reg(par, 0x0083, 0x0000); + write_reg(par, 0x0084, 0x0000); + write_reg(par, 0x0085, 0x0000); + + /* -------------- Panel Control ------------------- */ + write_reg(par, 0x0090, 0x0010); + write_reg(par, 0x0092, 0x0000); + write_reg(par, 0x0093, 0x0003); + write_reg(par, 0x0095, 0x0110); + write_reg(par, 0x0097, 0x0000); + write_reg(par, 0x0098, 0x0000); + write_reg(par, 0x0007, 0x0173); /* 262K color and display ON */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0020, xs); + write_reg(par, 0x0021, ys); + break; + case 180: + write_reg(par, 0x0020, WIDTH - 1 - xs); + write_reg(par, 0x0021, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0020, WIDTH - 1 - ys); + write_reg(par, 0x0021, xs); + break; + case 90: + write_reg(par, 0x0020, ys); + write_reg(par, 0x0021, HEIGHT - 1 - xs); + break; + } + write_reg(par, 0x0022); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x3, (par->bgr << 12) | 0x30); + break; + case 270: + write_reg(par, 0x3, (par->bgr << 12) | 0x28); + break; + case 180: + write_reg(par, 0x3, (par->bgr << 12) | 0x00); + break; + case 90: + write_reg(par, 0x3, (par->bgr << 12) | 0x18); + break; + } + return 0; +} + +/* + Gamma string format: + VRP0 VRP1 RP0 RP1 KP0 KP1 KP2 KP3 KP4 KP5 + VRN0 VRN1 RN0 RN1 KN0 KN1 KN2 KN3 KN4 KN5 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111, + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < 2; i++) + for (j = 0; j < 10; j++) + CURVE(i, j) &= mask[i*par->gamma.num_values + j]; + + write_reg(par, 0x0030, CURVE(0, 5) << 8 | CURVE(0, 4)); + write_reg(par, 0x0031, CURVE(0, 7) << 8 | CURVE(0, 6)); + write_reg(par, 0x0032, CURVE(0, 9) << 8 | CURVE(0, 8)); + write_reg(par, 0x0035, CURVE(0, 3) << 8 | CURVE(0, 2)); + write_reg(par, 0x0036, CURVE(0, 1) << 8 | CURVE(0, 0)); + + write_reg(par, 0x0037, CURVE(1, 5) << 8 | CURVE(1, 4)); + write_reg(par, 0x0038, CURVE(1, 7) << 8 | CURVE(1, 6)); + write_reg(par, 0x0039, CURVE(1, 9) << 8 | CURVE(1, 8)); + write_reg(par, 0x003C, CURVE(1, 3) << 8 | CURVE(1, 2)); + write_reg(par, 0x003D, CURVE(1, 1) << 8 | CURVE(1, 0)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = 2, + .gamma_len = 10, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9320", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9320"); +MODULE_ALIAS("platform:ili9320"); + +MODULE_DESCRIPTION("FB driver for the ILI9320 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c new file mode 100644 index 00000000000..5f88145fac9 --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -0,0 +1,291 @@ +/* + * FB driver for the ILI9325 LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * Based on ili9325.c by Jeroen Domburg + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ili9325" +#define WIDTH 240 +#define HEIGHT 320 +#define BPP 16 +#define FPS 20 +#define DEFAULT_GAMMA "0F 00 7 2 0 0 6 5 4 1\n" \ + "04 16 2 7 6 3 2 1 7 7" + + +static unsigned bt = 6; /* VGL=Vci*4 , VGH=Vci*4 */ +module_param(bt, uint, 0); +MODULE_PARM_DESC(bt, "Sets the factor used in the step-up circuits"); + +static unsigned vc = 0b011; /* Vci1=Vci*0.80 */ +module_param(vc, uint, 0); +MODULE_PARM_DESC(vc, +"Sets the ratio factor of Vci to generate the reference voltages Vci1"); + +static unsigned vrh = 0b1101; /* VREG1OUT=Vci*1.85 */ +module_param(vrh, uint, 0); +MODULE_PARM_DESC(vrh, +"Set the amplifying rate (1.6 ~ 1.9) of Vci applied to output the VREG1OUT"); + +static unsigned vdv = 0b10010; /* VCOMH amplitude=VREG1OUT*0.98 */ +module_param(vdv, uint, 0); +MODULE_PARM_DESC(vdv, +"Select the factor of VREG1OUT to set the amplitude of Vcom"); + +static unsigned vcm = 0b001010; /* VCOMH=VREG1OUT*0.735 */ +module_param(vcm, uint, 0); +MODULE_PARM_DESC(vcm, "Set the internal VcomH voltage"); + + +/* +Verify that this configuration is within the Voltage limits + +Display module configuration: Vcc = IOVcc = Vci = 3.3V + + Voltages +---------- +Vci = 3.3 +Vci1 = Vci * 0.80 = 2.64 +DDVDH = Vci1 * 2 = 5.28 +VCL = -Vci1 = -2.64 +VREG1OUT = Vci * 1.85 = 4.88 +VCOMH = VREG1OUT * 0.735 = 3.59 +VCOM amplitude = VREG1OUT * 0.98 = 4.79 +VGH = Vci * 4 = 13.2 +VGL = -Vci * 4 = -13.2 + + Limits +-------- +Power supplies +1.65 < IOVcc < 3.30 => 1.65 < 3.3 < 3.30 +2.40 < Vcc < 3.30 => 2.40 < 3.3 < 3.30 +2.50 < Vci < 3.30 => 2.50 < 3.3 < 3.30 + +Source/VCOM power supply voltage + 4.50 < DDVDH < 6.0 => 4.50 < 5.28 < 6.0 +-3.0 < VCL < -2.0 => -3.0 < -2.64 < -2.0 +VCI - VCL < 6.0 => 5.94 < 6.0 + +Gate driver output voltage + 10 < VGH < 20 => 10 < 13.2 < 20 +-15 < VGL < -5 => -15 < -13.2 < -5 +VGH - VGL < 32 => 26.4 < 32 + +VCOM driver output voltage +VCOMH - VCOML < 6.0 => 4.79 < 6.0 +*/ + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + bt &= 0b111; + vc &= 0b111; + vrh &= 0b1111; + vdv &= 0b11111; + vcm &= 0b111111; + + /* Initialization sequence from ILI9325 Application Notes */ + + /* ----------- Start Initial Sequence ----------- */ + write_reg(par, 0x00E3, 0x3008); /* Set internal timing */ + write_reg(par, 0x00E7, 0x0012); /* Set internal timing */ + write_reg(par, 0x00EF, 0x1231); /* Set internal timing */ + write_reg(par, 0x0001, 0x0100); /* set SS and SM bit */ + write_reg(par, 0x0002, 0x0700); /* set 1 line inversion */ + write_reg(par, 0x0004, 0x0000); /* Resize register */ + write_reg(par, 0x0008, 0x0207); /* set the back porch and front porch */ + write_reg(par, 0x0009, 0x0000); /* set non-display area refresh cycle */ + write_reg(par, 0x000A, 0x0000); /* FMARK function */ + write_reg(par, 0x000C, 0x0000); /* RGB interface setting */ + write_reg(par, 0x000D, 0x0000); /* Frame marker Position */ + write_reg(par, 0x000F, 0x0000); /* RGB interface polarity */ + + /* ----------- Power On sequence ----------- */ + write_reg(par, 0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + write_reg(par, 0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */ + write_reg(par, 0x0012, 0x0000); /* VREG1OUT voltage */ + write_reg(par, 0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */ + mdelay(200); /* Dis-charge capacitor power voltage */ + write_reg(par, 0x0010, /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + (1 << 12) | (bt << 8) | (1 << 7) | (0b001 << 4)); + write_reg(par, 0x0011, 0x220 | vc); /* DC1[2:0], DC0[2:0], VC[2:0] */ + mdelay(50); /* Delay 50ms */ + write_reg(par, 0x0012, vrh); /* Internal reference voltage= Vci; */ + mdelay(50); /* Delay 50ms */ + write_reg(par, 0x0013, vdv << 8); /* Set VDV[4:0] for VCOM amplitude */ + write_reg(par, 0x0029, vcm); /* Set VCM[5:0] for VCOMH */ + write_reg(par, 0x002B, 0x000C); /* Set Frame Rate */ + mdelay(50); /* Delay 50ms */ + write_reg(par, 0x0020, 0x0000); /* GRAM horizontal Address */ + write_reg(par, 0x0021, 0x0000); /* GRAM Vertical Address */ + + /*------------------ Set GRAM area --------------- */ + write_reg(par, 0x0050, 0x0000); /* Horizontal GRAM Start Address */ + write_reg(par, 0x0051, 0x00EF); /* Horizontal GRAM End Address */ + write_reg(par, 0x0052, 0x0000); /* Vertical GRAM Start Address */ + write_reg(par, 0x0053, 0x013F); /* Vertical GRAM Start Address */ + write_reg(par, 0x0060, 0xA700); /* Gate Scan Line */ + write_reg(par, 0x0061, 0x0001); /* NDL,VLE, REV */ + write_reg(par, 0x006A, 0x0000); /* set scrolling line */ + + /*-------------- Partial Display Control --------- */ + write_reg(par, 0x0080, 0x0000); + write_reg(par, 0x0081, 0x0000); + write_reg(par, 0x0082, 0x0000); + write_reg(par, 0x0083, 0x0000); + write_reg(par, 0x0084, 0x0000); + write_reg(par, 0x0085, 0x0000); + + /*-------------- Panel Control ------------------- */ + write_reg(par, 0x0090, 0x0010); + write_reg(par, 0x0092, 0x0600); + write_reg(par, 0x0007, 0x0133); /* 262K color and display ON */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0020, xs); + write_reg(par, 0x0021, ys); + break; + case 180: + write_reg(par, 0x0020, WIDTH - 1 - xs); + write_reg(par, 0x0021, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0020, WIDTH - 1 - ys); + write_reg(par, 0x0021, xs); + break; + case 90: + write_reg(par, 0x0020, ys); + write_reg(par, 0x0021, HEIGHT - 1 - xs); + break; + } + write_reg(par, 0x0022); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + /* AM: GRAM update direction */ + case 0: + write_reg(par, 0x03, 0x0030 | (par->bgr << 12)); + break; + case 180: + write_reg(par, 0x03, 0x0000 | (par->bgr << 12)); + break; + case 270: + write_reg(par, 0x03, 0x0028 | (par->bgr << 12)); + break; + case 90: + write_reg(par, 0x03, 0x0018 | (par->bgr << 12)); + break; + } + + return 0; +} + +/* + Gamma string format: + VRP0 VRP1 RP0 RP1 KP0 KP1 KP2 KP3 KP4 KP5 + VRN0 VRN1 RN0 RN1 KN0 KN1 KN2 KN3 KN4 KN5 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111, + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < 2; i++) + for (j = 0; j < 10; j++) + CURVE(i, j) &= mask[i*par->gamma.num_values + j]; + + write_reg(par, 0x0030, CURVE(0, 5) << 8 | CURVE(0, 4)); + write_reg(par, 0x0031, CURVE(0, 7) << 8 | CURVE(0, 6)); + write_reg(par, 0x0032, CURVE(0, 9) << 8 | CURVE(0, 8)); + write_reg(par, 0x0035, CURVE(0, 3) << 8 | CURVE(0, 2)); + write_reg(par, 0x0036, CURVE(0, 1) << 8 | CURVE(0, 0)); + + write_reg(par, 0x0037, CURVE(1, 5) << 8 | CURVE(1, 4)); + write_reg(par, 0x0038, CURVE(1, 7) << 8 | CURVE(1, 6)); + write_reg(par, 0x0039, CURVE(1, 9) << 8 | CURVE(1, 8)); + write_reg(par, 0x003C, CURVE(1, 3) << 8 | CURVE(1, 2)); + write_reg(par, 0x003D, CURVE(1, 1) << 8 | CURVE(1, 0)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .bpp = BPP, + .fps = FPS, + .gamma_num = 2, + .gamma_len = 10, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9325", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9325"); +MODULE_ALIAS("platform:ili9325"); + +MODULE_DESCRIPTION("FB driver for the ILI9325 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ili9340.c b/drivers/staging/fbtft/fb_ili9340.c new file mode 100644 index 00000000000..985687d94ec --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9340.c @@ -0,0 +1,163 @@ +/* + * FB driver for the ILI9340 LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ili9340" +#define WIDTH 240 +#define HEIGHT 320 + + +/* Init sequence taken from: Arduino Library for the Adafruit 2.2" display */ +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + write_reg(par, 0xEF, 0x03, 0x80, 0x02); + write_reg(par, 0xCF, 0x00 , 0XC1 , 0X30); + write_reg(par, 0xED, 0x64 , 0x03 , 0X12 , 0X81); + write_reg(par, 0xE8, 0x85 , 0x00 , 0x78); + write_reg(par, 0xCB, 0x39 , 0x2C , 0x00 , 0x34 , 0x02); + write_reg(par, 0xF7, 0x20); + write_reg(par, 0xEA, 0x00 , 0x00); + + /* Power Control 1 */ + write_reg(par, 0xC0, 0x23); + + /* Power Control 2 */ + write_reg(par, 0xC1, 0x10); + + /* VCOM Control 1 */ + write_reg(par, 0xC5, 0x3e, 0x28); + + /* VCOM Control 2 */ + write_reg(par, 0xC7, 0x86); + + /* COLMOD: Pixel Format Set */ + /* 16 bits/pixel */ + write_reg(par, 0x3A, 0x55); + + /* Frame Rate Control */ + /* Division ratio = fosc, Frame Rate = 79Hz */ + write_reg(par, 0xB1, 0x00, 0x18); + + /* Display Function Control */ + write_reg(par, 0xB6, 0x08, 0x82, 0x27); + + /* Gamma Function Disable */ + write_reg(par, 0xF2, 0x00); + + /* Gamma curve selected */ + write_reg(par, 0x26, 0x01); + + /* Positive Gamma Correction */ + write_reg(par, 0xE0, + 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, + 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00); + + /* Negative Gamma Correction */ + write_reg(par, 0xE1, + 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, + 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F); + + /* Sleep OUT */ + write_reg(par, 0x11); + + mdelay(120); + + /* Display ON */ + write_reg(par, 0x29); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +#define ILI9340_MADCTL_MV 0x20 +#define ILI9340_MADCTL_MX 0x40 +#define ILI9340_MADCTL_MY 0x80 +static int set_var(struct fbtft_par *par) +{ + u8 val; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 270: + val = ILI9340_MADCTL_MV; + break; + case 180: + val = ILI9340_MADCTL_MY; + break; + case 90: + val = ILI9340_MADCTL_MV | ILI9340_MADCTL_MY | ILI9340_MADCTL_MX; + break; + default: + val = ILI9340_MADCTL_MX; + break; + } + /* Memory Access Control */ + write_reg(par, 0x36, val | (par->bgr << 3)); + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9340", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9340"); +MODULE_ALIAS("platform:ili9340"); + +MODULE_DESCRIPTION("FB driver for the ILI9340 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ili9341.c b/drivers/staging/fbtft/fb_ili9341.c new file mode 100644 index 00000000000..225b2d84371 --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9341.c @@ -0,0 +1,179 @@ +/* + * FB driver for the ILI9341 LCD display controller + * + * This display uses 9-bit SPI: Data/Command bit + 8 data bits + * For platforms that doesn't support 9-bit, the driver is capable + * of emulating this using 8-bit transfer. + * This is done by transfering eight 9-bit words in 9 bytes. + * + * Copyright (C) 2013 Christian Vogelgsang + * Based on adafruit22fb.c by Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ili9341" +#define WIDTH 240 +#define HEIGHT 320 +#define TXBUFLEN (4 * PAGE_SIZE) +#define DEFAULT_GAMMA "1F 1A 18 0A 0F 06 45 87 32 0A 07 02 07 05 00\n" \ + "00 25 27 05 10 09 3A 78 4D 05 18 0D 38 3A 1F" + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* startup sequence for MI0283QT-9A */ + write_reg(par, 0x01); /* software reset */ + mdelay(5); + write_reg(par, 0x28); /* display off */ + /* --------------------------------------------------------- */ + write_reg(par, 0xCF, 0x00, 0x83, 0x30); + write_reg(par, 0xED, 0x64, 0x03, 0x12, 0x81); + write_reg(par, 0xE8, 0x85, 0x01, 0x79); + write_reg(par, 0xCB, 0x39, 0X2C, 0x00, 0x34, 0x02); + write_reg(par, 0xF7, 0x20); + write_reg(par, 0xEA, 0x00, 0x00); + /* ------------power control-------------------------------- */ + write_reg(par, 0xC0, 0x26); + write_reg(par, 0xC1, 0x11); + /* ------------VCOM --------- */ + write_reg(par, 0xC5, 0x35, 0x3E); + write_reg(par, 0xC7, 0xBE); + /* ------------memory access control------------------------ */ + write_reg(par, 0x3A, 0x55); /* 16bit pixel */ + /* ------------frame rate----------------------------------- */ + write_reg(par, 0xB1, 0x00, 0x1B); + /* ------------Gamma---------------------------------------- */ + /* write_reg(par, 0xF2, 0x08); */ /* Gamma Function Disable */ + write_reg(par, 0x26, 0x01); + /* ------------display-------------------------------------- */ + write_reg(par, 0xB7, 0x07); /* entry mode set */ + write_reg(par, 0xB6, 0x0A, 0x82, 0x27, 0x00); + write_reg(par, 0x11); /* sleep out */ + mdelay(100); + write_reg(par, 0x29); /* display on */ + mdelay(20); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address set */ + write_reg(par, 0x2A, + (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF); + + /* Row adress set */ + write_reg(par, 0x2B, + (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +#define MEM_Y (7) /* MY row address order */ +#define MEM_X (6) /* MX column address order */ +#define MEM_V (5) /* MV row / column exchange */ +#define MEM_L (4) /* ML vertical refresh order */ +#define MEM_H (2) /* MH horizontal refresh order */ +#define MEM_BGR (3) /* RGB-BGR Order */ +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, (1 << MEM_X) | (par->bgr << MEM_BGR)); + break; + case 270: + write_reg(par, 0x36, + (1<<MEM_V) | (1 << MEM_L) | (par->bgr << MEM_BGR)); + break; + case 180: + write_reg(par, 0x36, (1 << MEM_Y) | (par->bgr << MEM_BGR)); + break; + case 90: + write_reg(par, 0x36, (1 << MEM_Y) | (1 << MEM_X) | + (1 << MEM_V) | (par->bgr << MEM_BGR)); + break; + } + + return 0; +} + +/* + Gamma string format: + Positive: Par1 Par2 [...] Par15 + Negative: Par1 Par2 [...] Par15 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + int i; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + for (i = 0; i < par->gamma.num_curves; i++) + write_reg(par, 0xE0 + i, + CURVE(i, 0), CURVE(i, 1), CURVE(i, 2), + CURVE(i, 3), CURVE(i, 4), CURVE(i, 5), + CURVE(i, 6), CURVE(i, 7), CURVE(i, 8), + CURVE(i, 9), CURVE(i, 10), CURVE(i, 11), + CURVE(i, 12), CURVE(i, 13), CURVE(i, 14)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .txbuflen = TXBUFLEN, + .gamma_num = 2, + .gamma_len = 15, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9341", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9341"); +MODULE_ALIAS("platform:ili9341"); + +MODULE_DESCRIPTION("FB driver for the ILI9341 LCD display controller"); +MODULE_AUTHOR("Christian Vogelgsang"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ili9481.c b/drivers/staging/fbtft/fb_ili9481.c new file mode 100644 index 00000000000..725157a1ac4 --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9481.c @@ -0,0 +1,117 @@ +/* + * FB driver for the ILI9481 LCD Controller + * + * Copyright (c) 2014 Petr Olivka + * Copyright (c) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ili9481" +#define WIDTH 320 +#define HEIGHT 480 + +static int default_init_sequence[] = { + + /* SLP_OUT - Sleep out */ + -1, 0x11, + -2, 50, + /* Power setting */ + -1, 0xD0, 0x07, 0x42, 0x18, + /* VCOM */ + -1, 0xD1, 0x00, 0x07, 0x10, + /* Power setting for norm. mode */ + -1, 0xD2, 0x01, 0x02, + /* Panel driving setting */ + -1, 0xC0, 0x10, 0x3B, 0x00, 0x02, 0x11, + /* Frame rate & inv. */ + -1, 0xC5, 0x03, + /* Pixel format */ + -1, 0x3A, 0x55, + /* Gamma */ + -1, 0xC8, 0x00, 0x32, 0x36, 0x45, 0x06, 0x16, + 0x37, 0x75, 0x77, 0x54, 0x0C, 0x00, + /* DISP_ON */ + -1, 0x29, + -3 +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* column address */ + write_reg(par, 0x2a, xs >> 8, xs & 0xff, xe >> 8, xe & 0xff); + + /* row adress */ + write_reg(par, 0x2b, ys >> 8, ys & 0xff, ye >> 8, ye & 0xff); + + /* memory write */ + write_reg(par, 0x2c); +} + +#define HFLIP 0x01 +#define VFLIP 0x02 +#define ROWxCOL 0x20 +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 270: + write_reg(par, 0x36, ROWxCOL | HFLIP | VFLIP | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, VFLIP | (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, ROWxCOL | (par->bgr << 3)); + break; + default: + write_reg(par, 0x36, HFLIP | (par->bgr << 3)); + break; + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .init_sequence = default_init_sequence, + .fbtftops = { + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9481", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9481"); +MODULE_ALIAS("platform:ili9481"); + +MODULE_DESCRIPTION("FB driver for the ILI9481 LCD Controller"); +MODULE_AUTHOR("Petr Olivka"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ili9486.c b/drivers/staging/fbtft/fb_ili9486.c new file mode 100644 index 00000000000..95b89999d32 --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9486.c @@ -0,0 +1,121 @@ +/* + * FB driver for the ILI9486 LCD Controller + * + * Copyright (C) 2014 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ili9486" +#define WIDTH 320 +#define HEIGHT 480 + + +/* this init sequence matches PiScreen */ +static int default_init_sequence[] = { + /* Interface Mode Control */ + -1, 0xb0, 0x0, + /* Sleep OUT */ + -1, 0x11, + -2, 250, + /* Interface Pixel Format */ + -1, 0x3A, 0x55, + /* Power Control 3 */ + -1, 0xC2, 0x44, + /* VCOM Control 1 */ + -1, 0xC5, 0x00, 0x00, 0x00, 0x00, + /* PGAMCTRL(Positive Gamma Control) */ + -1, 0xE0, 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, + 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00, + /* NGAMCTRL(Negative Gamma Control) */ + -1, 0xE1, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, + 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00, + /* Digital Gamma Control 1 */ + -1, 0xE2, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, + 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00, + /* Sleep OUT */ + -1, 0x11, + /* Display ON */ + -1, 0x29, + /* end marker */ + -3 +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, 0x80 | (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, 0x20 | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, 0x40 | (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, 0xE0 | (par->bgr << 3)); + break; + default: + break; + } + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .init_sequence = default_init_sequence, + .fbtftops = { + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9486", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9486"); +MODULE_ALIAS("platform:ili9486"); + +MODULE_DESCRIPTION("FB driver for the ILI9486 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c new file mode 100644 index 00000000000..8b9ebfb49ef --- /dev/null +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -0,0 +1,177 @@ +/* + * FB driver for the PCD8544 LCD Controller + * + * The display is monochrome and the video memory is RGB565. + * Any pixel value except 0 turns the pixel on. + * + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_pcd8544" +#define WIDTH 84 +#define HEIGHT 48 +#define TXBUFLEN (84*6) +#define DEFAULT_GAMMA "40" /* gamma is used to control contrast in this driver */ + +static unsigned tc; +module_param(tc, uint, 0); +MODULE_PARM_DESC(tc, "TC[1:0] Temperature coefficient: 0-3 (default: 0)"); + +static unsigned bs = 4; +module_param(bs, uint, 0); +MODULE_PARM_DESC(bs, "BS[2:0] Bias voltage level: 0-7 (default: 4)"); + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* Function set */ + write_reg(par, 0x21); /* 5:1 1 + 2:0 PD - Powerdown control: chip is active + 1:0 V - Entry mode: horizontal addressing + 0:1 H - Extended instruction set control: extended + */ + + /* H=1 Temperature control */ + write_reg(par, 0x04 | (tc & 0x3)); /* + 2:1 1 + 1:x TC1 - Temperature Coefficient: 0x10 + 0:x TC0 + */ + + /* H=1 Bias system */ + write_reg(par, 0x10 | (bs & 0x7)); /* + 4:1 1 + 3:0 0 + 2:x BS2 - Bias System + 1:x BS1 + 0:x BS0 + */ + + /* Function set */ + write_reg(par, 0x22); /* 5:1 1 + 2:0 PD - Powerdown control: chip is active + 1:1 V - Entry mode: vertical addressing + 0:0 H - Extended instruction set control: basic + */ + + /* H=0 Display control */ + write_reg(par, 0x08 | 4); /* + 3:1 1 + 2:1 D - DE: 10=normal mode + 1:0 0 + 0:0 E + */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* H=0 Set X address of RAM */ + write_reg(par, 0x80); /* 7:1 1 + 6-0: X[6:0] - 0x00 + */ + + /* H=0 Set Y address of RAM */ + write_reg(par, 0x40); /* 7:0 0 + 6:1 1 + 2-0: Y[2:0] - 0x0 + */ +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + u8 *buf = par->txbuf.buf; + int x, y, i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + for (x = 0; x < 84; x++) { + for (y = 0; y < 6; y++) { + *buf = 0x00; + for (i = 0; i < 8; i++) { + *buf |= (vmem16[(y*8+i)*84+x] ? 1 : 0) << i; + } + buf++; + } + } + + /* Write data */ + gpio_set_value(par->gpio.dc, 1); + ret = par->fbtftops.write(par, par->txbuf.buf, 6*84); + if (ret < 0) + dev_err(par->info->device, "%s: write failed and returned: %d\n", __func__, ret); + + return ret; +} + +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + curves[0] &= 0x7F; + + write_reg(par, 0x23); /* turn on extended instruction set */ + write_reg(par, 0x80 | curves[0]); + write_reg(par, 0x22); /* turn off extended instruction set */ + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .txbuflen = TXBUFLEN, + .gamma_num = 1, + .gamma_len = 1, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .write_vmem = write_vmem, + .set_gamma = set_gamma, + }, + .backlight = 1, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "philips,pdc8544", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("spi:pdc8544"); + +MODULE_DESCRIPTION("FB driver for the PCD8544 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ra8875.c b/drivers/staging/fbtft/fb_ra8875.c new file mode 100644 index 00000000000..c323c06344f --- /dev/null +++ b/drivers/staging/fbtft/fb_ra8875.c @@ -0,0 +1,331 @@ +/****************************************************************************** + + ProjectName: FBTFT driver ***** ***** + for the RA8875 LCD Controller * * ************ + * ** ** * * + Copyright © by Pf@nne & NOTRO * * * * * **** * + * * * * * * * + Last modification by: * * * * **** * + - Pf@nne (pf@nne-mail.de) * * ***** * + * * * ******* + ***** * * + Date : 10.06.2014 * * + Version : V1.13 ***** + Revison : 5 + +******************************************************************************* + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include <linux/gpio.h> +#include "fbtft.h" + +#define DRVNAME "fb_ra8875" + +static int write_spi(struct fbtft_par *par, void *buf, size_t len) +{ + struct spi_transfer t = { + .tx_buf = buf, + .len = len, + .speed_hz = 1000000, + }; + struct spi_message m; + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + if (!par->spi) { + dev_err(par->info->device, + "%s: par->spi is unexpectedly NULL\n", __func__); + return -1; + } + + spi_message_init(&m); + if (par->txbuf.dma && buf == par->txbuf.buf) { + t.tx_dma = par->txbuf.dma; + m.is_dma_mapped = 1; + } + spi_message_add_tail(&t, &m); + return spi_sync(par->spi, &m); +} + +static int init_display(struct fbtft_par *par) +{ + gpio_set_value(par->gpio.dc, 1); + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "%s()\n", __func__); + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "display size %dx%d\n", par->info->var.xres, par->info->var.yres); + + par->fbtftops.reset(par); + + if ((par->info->var.xres == 320) && (par->info->var.yres == 240)) { + /* PLL clock frequency */ + write_reg(par, 0x88 , 0x0A); + write_reg(par, 0x89 , 0x02); + mdelay(10); + /* color deep / MCU Interface */ + write_reg(par, 0x10 , 0x0C); + /* pixel clock period */ + write_reg(par, 0x04 , 0x03); + mdelay(1); + /* horizontal settings */ + write_reg(par, 0x14 , 0x27); + write_reg(par, 0x15 , 0x00); + write_reg(par, 0x16 , 0x05); + write_reg(par, 0x17 , 0x04); + write_reg(par, 0x18 , 0x03); + /* vertical settings */ + write_reg(par, 0x19 , 0xEF); + write_reg(par, 0x1A , 0x00); + write_reg(par, 0x1B , 0x05); + write_reg(par, 0x1C , 0x00); + write_reg(par, 0x1D , 0x0E); + write_reg(par, 0x1E , 0x00); + write_reg(par, 0x1F , 0x02); + } else if ((par->info->var.xres == 480) && (par->info->var.yres == 272)) { + /* PLL clock frequency */ + write_reg(par, 0x88 , 0x0A); + write_reg(par, 0x89 , 0x02); + mdelay(10); + /* color deep / MCU Interface */ + write_reg(par, 0x10 , 0x0C); + /* pixel clock period */ + write_reg(par, 0x04 , 0x82); + mdelay(1); + /* horizontal settings */ + write_reg(par, 0x14 , 0x3B); + write_reg(par, 0x15 , 0x00); + write_reg(par, 0x16 , 0x01); + write_reg(par, 0x17 , 0x00); + write_reg(par, 0x18 , 0x05); + /* vertical settings */ + write_reg(par, 0x19 , 0x0F); + write_reg(par, 0x1A , 0x01); + write_reg(par, 0x1B , 0x02); + write_reg(par, 0x1C , 0x00); + write_reg(par, 0x1D , 0x07); + write_reg(par, 0x1E , 0x00); + write_reg(par, 0x1F , 0x09); + } else if ((par->info->var.xres == 640) && (par->info->var.yres == 480)) { + /* PLL clock frequency */ + write_reg(par, 0x88 , 0x0B); + write_reg(par, 0x89 , 0x02); + mdelay(10); + /* color deep / MCU Interface */ + write_reg(par, 0x10 , 0x0C); + /* pixel clock period */ + write_reg(par, 0x04 , 0x01); + mdelay(1); + /* horizontal settings */ + write_reg(par, 0x14 , 0x4F); + write_reg(par, 0x15 , 0x05); + write_reg(par, 0x16 , 0x0F); + write_reg(par, 0x17 , 0x01); + write_reg(par, 0x18 , 0x00); + /* vertical settings */ + write_reg(par, 0x19 , 0xDF); + write_reg(par, 0x1A , 0x01); + write_reg(par, 0x1B , 0x0A); + write_reg(par, 0x1C , 0x00); + write_reg(par, 0x1D , 0x0E); + write_reg(par, 0x1E , 0x00); + write_reg(par, 0x1F , 0x01); + } else if ((par->info->var.xres == 800) && (par->info->var.yres == 480)) { + /* PLL clock frequency */ + write_reg(par, 0x88 , 0x0B); + write_reg(par, 0x89 , 0x02); + mdelay(10); + /* color deep / MCU Interface */ + write_reg(par, 0x10 , 0x0C); + /* pixel clock period */ + write_reg(par, 0x04 , 0x81); + mdelay(1); + /* horizontal settings */ + write_reg(par, 0x14 , 0x63); + write_reg(par, 0x15 , 0x03); + write_reg(par, 0x16 , 0x03); + write_reg(par, 0x17 , 0x02); + write_reg(par, 0x18 , 0x00); + /* vertical settings */ + write_reg(par, 0x19 , 0xDF); + write_reg(par, 0x1A , 0x01); + write_reg(par, 0x1B , 0x14); + write_reg(par, 0x1C , 0x00); + write_reg(par, 0x1D , 0x06); + write_reg(par, 0x1E , 0x00); + write_reg(par, 0x1F , 0x01); + } else { + dev_err(par->info->device, "display size is not supported!!"); + return -1; + } + + /* PWM clock */ + write_reg(par, 0x8a , 0x81); + write_reg(par, 0x8b , 0xFF); + mdelay(10); + + /* Display ON */ + write_reg(par, 0x01 , 0x80); + mdelay(10); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Set_Active_Window */ + write_reg(par, 0x30 , xs & 0x00FF); + write_reg(par, 0x31 , (xs & 0xFF00) >> 8); + write_reg(par, 0x32 , ys & 0x00FF); + write_reg(par, 0x33 , (ys & 0xFF00) >> 8); + write_reg(par, 0x34 , (xs+xe) & 0x00FF); + write_reg(par, 0x35 , ((xs+xe) & 0xFF00) >> 8); + write_reg(par, 0x36 , (ys+ye) & 0x00FF); + write_reg(par, 0x37 , ((ys+ye) & 0xFF00) >> 8); + + /* Set_Memory_Write_Cursor */ + write_reg(par, 0x46, xs & 0xff); + write_reg(par, 0x47, (xs >> 8) & 0x03); + write_reg(par, 0x48, ys & 0xff); + write_reg(par, 0x49, (ys >> 8) & 0x01); + + write_reg(par, 0x02); +} + +static void write_reg8_bus8(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + u8 *buf = (u8 *)par->buf; + + /* slow down spi-speed for writing registers */ + par->fbtftops.write = write_spi; + + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { + va_start(args, len); + for (i = 0; i < len; i++) + buf[i] = (u8)va_arg(args, unsigned int); + va_end(args); + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device, + u8, buf, len, "%s: ", __func__); + } + + va_start(args, len); + *buf++ = 0x80; + *buf = (u8)va_arg(args, unsigned int); + ret = par->fbtftops.write(par, par->buf, 2); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %dn", + __func__, ret); + return; + } + len--; + + udelay(100); + + if (len) { + buf = (u8 *)par->buf; + *buf++ = 0x00; + i = len; + while (i--) + *buf++ = (u8)va_arg(args, unsigned int); + + ret = par->fbtftops.write(par, par->buf, len + 1); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %dn", + __func__, ret); + return; + } + } + va_end(args); + + /* restore user spi-speed */ + par->fbtftops.write = fbtft_write_spi; + udelay(100); +} + +static int write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16; + u16 *txbuf16 = (u16 *)par->txbuf.buf; + size_t remain; + size_t to_copy; + size_t tx_array_size; + int i; + int ret = 0; + size_t startbyte_size = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", + __func__, offset, len); + + remain = len / 2; + vmem16 = (u16 *)(par->info->screen_base + offset); + tx_array_size = par->txbuf.len / 2; + txbuf16 = (u16 *)(par->txbuf.buf + 1); + tx_array_size -= 2; + *(u8 *)(par->txbuf.buf) = 0x00; + startbyte_size = 1; + + while (remain) { + to_copy = remain > tx_array_size ? tx_array_size : remain; + dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", + to_copy, remain - to_copy); + + for (i = 0; i < to_copy; i++) + txbuf16[i] = cpu_to_be16(vmem16[i]); + + vmem16 = vmem16 + to_copy; + ret = par->fbtftops.write(par, par->txbuf.buf, + startbyte_size + to_copy * 2); + if (ret < 0) + return ret; + remain -= to_copy; + } + + return ret; +} + +static struct fbtft_display display = { + .regwidth = 8, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .write_register = write_reg8_bus8, + .write_vmem = write_vmem16_bus8, + .write = write_spi, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "raio,ra8875", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ra8875"); +MODULE_ALIAS("platform:ra8875"); + +MODULE_DESCRIPTION("FB driver for the RA8875 LCD Controller"); +MODULE_AUTHOR("Pf@nne"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_s6d02a1.c b/drivers/staging/fbtft/fb_s6d02a1.c new file mode 100644 index 00000000000..e412a42443e --- /dev/null +++ b/drivers/staging/fbtft/fb_s6d02a1.c @@ -0,0 +1,168 @@ +/* + * FB driver for the S6D02A1 LCD Controller + * + * Based on fb_st7735r.c by Noralf Tronnes + * Init code from UTFT library by Henning Karlsen + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> + +#include "fbtft.h" + +#define DRVNAME "fb_s6d02a1" + +static int default_init_sequence[] = { + + -1, 0xf0, 0x5a, 0x5a, + + -1, 0xfc, 0x5a, 0x5a, + + -1, 0xfa, 0x02, 0x1f, 0x00, 0x10, 0x22, 0x30, 0x38, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3d, 0x02, 0x01, + + -1, 0xfb, 0x21, 0x00, 0x02, 0x04, 0x07, 0x0a, 0x0b, 0x0c, 0x0c, 0x16, 0x1e, 0x30, 0x3f, 0x01, 0x02, + + /* power setting sequence */ + -1, 0xfd, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x01, 0x01, 0x00, 0x1f, 0x1f, + + -1, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x07, 0x00, 0x3C, 0x36, 0x00, 0x3C, 0x36, 0x00, + + -1, 0xf5, 0x00, 0x70, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x66, 0x06, + + -1, 0xf6, 0x02, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x01, 0x00, + + -1, 0xf2, 0x00, 0x01, 0x03, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x08, 0x08, + + -1, 0xf8, 0x11, + + -1, 0xf7, 0xc8, 0x20, 0x00, 0x00, + + -1, 0xf3, 0x00, 0x00, + + -1, 0x11, + -2, 50, + + -1, 0xf3, 0x00, 0x01, + -2, 50, + -1, 0xf3, 0x00, 0x03, + -2, 50, + -1, 0xf3, 0x00, 0x07, + -2, 50, + -1, 0xf3, 0x00, 0x0f, + -2, 50, + + -1, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x07, 0x00, 0x3C, 0x36, 0x00, 0x3C, 0x36, 0x00, + -2, 50, + + -1, 0xf3, 0x00, 0x1f, + -2, 50, + -1, 0xf3, 0x00, 0x7f, + -2, 50, + + -1, 0xf3, 0x00, 0xff, + -2, 50, + + -1, 0xfd, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x01, 0x00, 0x16, 0x16, + + -1, 0xf4, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x07, 0x00, 0x3C, 0x36, 0x00, 0x3C, 0x36, 0x00, + + /* initializing sequence */ + + -1, 0x36, 0x08, + + -1, 0x35, 0x00, + + -1, 0x3a, 0x05, + + /* gamma setting sequence */ + -1, 0x26, 0x01, /* preset gamma curves, possible values 0x01, 0x02, 0x04, 0x08 */ + + -2, 150, + -1, 0x29, + -1, 0x2c, + /* end marker */ + -3 + +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +#define MY (1 << 7) +#define MX (1 << 6) +#define MV (1 << 5) +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* MADCTL - Memory data access control + RGB/BGR: + 1. Mode selection pin SRGB + RGB H/W pin for color filter setting: 0=RGB, 1=BGR + 2. MADCTL RGB bit + RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, MX | MY | (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, MY | MV | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, MX | MV | (par->bgr << 3)); + break; + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 8, + .width = 128, + .height = 160, + .init_sequence = default_init_sequence, + .fbtftops = { + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "samsung,s6d02a1", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:s6d02a1"); +MODULE_ALIAS("platform:s6d02a1"); + +MODULE_DESCRIPTION("FB driver for the S6D02A1 LCD Controller"); +MODULE_AUTHOR("WOLFGANG BUENING"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c new file mode 100644 index 00000000000..1ef8c1ad827 --- /dev/null +++ b/drivers/staging/fbtft/fb_s6d1121.c @@ -0,0 +1,208 @@ +/* + * FB driver for the S6D1121 LCD Controller + * + * Copyright (C) 2013 Roman Rolinsky + * + * Based on fb_ili9325.c by Noralf Tronnes + * Based on ili9325.c by Jeroen Domburg + * Init code from UTFT library by Henning Karlsen + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_s6d1121" +#define WIDTH 240 +#define HEIGHT 320 +#define BPP 16 +#define FPS 20 +#define DEFAULT_GAMMA "26 09 24 2C 1F 23 24 25 22 26 25 23 0D 00\n" \ + "1C 1A 13 1D 0B 11 12 10 13 15 36 19 00 0D" + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + /* Initialization sequence from Lib_UTFT */ + + write_reg(par, 0x0011, 0x2004); + write_reg(par, 0x0013, 0xCC00); + write_reg(par, 0x0015, 0x2600); + write_reg(par, 0x0014, 0x252A); + write_reg(par, 0x0012, 0x0033); + write_reg(par, 0x0013, 0xCC04); + write_reg(par, 0x0013, 0xCC06); + write_reg(par, 0x0013, 0xCC4F); + write_reg(par, 0x0013, 0x674F); + write_reg(par, 0x0011, 0x2003); + write_reg(par, 0x0016, 0x0007); + write_reg(par, 0x0002, 0x0013); + write_reg(par, 0x0003, 0x0003); + write_reg(par, 0x0001, 0x0127); + write_reg(par, 0x0008, 0x0303); + write_reg(par, 0x000A, 0x000B); + write_reg(par, 0x000B, 0x0003); + write_reg(par, 0x000C, 0x0000); + write_reg(par, 0x0041, 0x0000); + write_reg(par, 0x0050, 0x0000); + write_reg(par, 0x0060, 0x0005); + write_reg(par, 0x0070, 0x000B); + write_reg(par, 0x0071, 0x0000); + write_reg(par, 0x0078, 0x0000); + write_reg(par, 0x007A, 0x0000); + write_reg(par, 0x0079, 0x0007); + write_reg(par, 0x0007, 0x0051); + write_reg(par, 0x0007, 0x0053); + write_reg(par, 0x0079, 0x0000); + + write_reg(par, 0x0022); /* Write Data to GRAM */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0020, xs); + write_reg(par, 0x0021, ys); + break; + case 180: + write_reg(par, 0x0020, WIDTH - 1 - xs); + write_reg(par, 0x0021, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0020, WIDTH - 1 - ys); + write_reg(par, 0x0021, xs); + break; + case 90: + write_reg(par, 0x0020, ys); + write_reg(par, 0x0021, HEIGHT - 1 - xs); + break; + } + write_reg(par, 0x0022); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + /* AM: GRAM update direction */ + case 0: + write_reg(par, 0x03, 0x0003 | (par->bgr << 12)); + break; + case 180: + write_reg(par, 0x03, 0x0000 | (par->bgr << 12)); + break; + case 270: + write_reg(par, 0x03, 0x000A | (par->bgr << 12)); + break; + case 90: + write_reg(par, 0x03, 0x0009 | (par->bgr << 12)); + break; + } + + return 0; +} + +/* + Gamma string format: + PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 PKP6 PKP7 PKP8 PKP9 PKP10 PKP11 VRP0 VRP1 + PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 PKN6 PKN7 PRN8 PRN9 PRN10 PRN11 VRN0 VRN1 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b11111, 0b11111, + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b11111, 0b11111 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < 2; i++) + for (j = 0; j < 14; j++) + CURVE(i, j) &= mask[i*par->gamma.num_values + j]; + + write_reg(par, 0x0030, CURVE(0, 1) << 8 | CURVE(0, 0)); + write_reg(par, 0x0031, CURVE(0, 3) << 8 | CURVE(0, 2)); + write_reg(par, 0x0032, CURVE(0, 5) << 8 | CURVE(0, 3)); + write_reg(par, 0x0033, CURVE(0, 7) << 8 | CURVE(0, 6)); + write_reg(par, 0x0034, CURVE(0, 9) << 8 | CURVE(0, 8)); + write_reg(par, 0x0035, CURVE(0, 11) << 8 | CURVE(0, 10)); + + write_reg(par, 0x0036, CURVE(1, 1) << 8 | CURVE(1, 0)); + write_reg(par, 0x0037, CURVE(1, 3) << 8 | CURVE(1, 2)); + write_reg(par, 0x0038, CURVE(1, 5) << 8 | CURVE(1, 4)); + write_reg(par, 0x0039, CURVE(1, 7) << 8 | CURVE(1, 6)); + write_reg(par, 0x003A, CURVE(1, 9) << 8 | CURVE(1, 8)); + write_reg(par, 0x003B, CURVE(1, 11) << 8 | CURVE(1, 10)); + + write_reg(par, 0x003C, CURVE(0, 13) << 8 | CURVE(0, 12)); + write_reg(par, 0x003D, CURVE(1, 13) << 8 | CURVE(1, 12)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .bpp = BPP, + .fps = FPS, + .gamma_num = 2, + .gamma_len = 14, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "samsung,s6d1121", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:s6d1121"); +MODULE_ALIAS("platform:s6d1121"); + +MODULE_DESCRIPTION("FB driver for the S6D1121 LCD Controller"); +MODULE_AUTHOR("Roman Rolinsky"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c new file mode 100644 index 00000000000..ef46fbca270 --- /dev/null +++ b/drivers/staging/fbtft/fb_ssd1289.c @@ -0,0 +1,206 @@ +/* + * FB driver for the SSD1289 LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * Init sequence taken from ITDB02_Graph16.cpp - (C)2010-2011 Henning Karlsen + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ssd1289" +#define WIDTH 240 +#define HEIGHT 320 +#define DEFAULT_GAMMA "02 03 2 5 7 7 4 2 4 2\n" \ + "02 03 2 5 7 5 4 2 4 2" + +static unsigned reg11 = 0x6040; +module_param(reg11, uint, 0); +MODULE_PARM_DESC(reg11, "Register 11h value"); + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + write_reg(par, 0x00, 0x0001); + write_reg(par, 0x03, 0xA8A4); + write_reg(par, 0x0C, 0x0000); + write_reg(par, 0x0D, 0x080C); + write_reg(par, 0x0E, 0x2B00); + write_reg(par, 0x1E, 0x00B7); + write_reg(par, 0x01, + (1 << 13) | (par->bgr << 11) | (1 << 9) | (HEIGHT - 1)); + write_reg(par, 0x02, 0x0600); + write_reg(par, 0x10, 0x0000); + write_reg(par, 0x05, 0x0000); + write_reg(par, 0x06, 0x0000); + write_reg(par, 0x16, 0xEF1C); + write_reg(par, 0x17, 0x0003); + write_reg(par, 0x07, 0x0233); + write_reg(par, 0x0B, 0x0000); + write_reg(par, 0x0F, 0x0000); + write_reg(par, 0x41, 0x0000); + write_reg(par, 0x42, 0x0000); + write_reg(par, 0x48, 0x0000); + write_reg(par, 0x49, 0x013F); + write_reg(par, 0x4A, 0x0000); + write_reg(par, 0x4B, 0x0000); + write_reg(par, 0x44, 0xEF00); + write_reg(par, 0x45, 0x0000); + write_reg(par, 0x46, 0x013F); + write_reg(par, 0x23, 0x0000); + write_reg(par, 0x24, 0x0000); + write_reg(par, 0x25, 0x8000); + write_reg(par, 0x4f, 0x0000); + write_reg(par, 0x4e, 0x0000); + write_reg(par, 0x22); + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + switch (par->info->var.rotate) { + /* R4Eh - Set GDDRAM X address counter */ + /* R4Fh - Set GDDRAM Y address counter */ + case 0: + write_reg(par, 0x4e, xs); + write_reg(par, 0x4f, ys); + break; + case 180: + write_reg(par, 0x4e, par->info->var.xres - 1 - xs); + write_reg(par, 0x4f, par->info->var.yres - 1 - ys); + break; + case 270: + write_reg(par, 0x4e, par->info->var.yres - 1 - ys); + write_reg(par, 0x4f, xs); + break; + case 90: + write_reg(par, 0x4e, ys); + write_reg(par, 0x4f, par->info->var.xres - 1 - xs); + break; + } + + /* R22h - RAM data write */ + write_reg(par, 0x22); +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (par->fbtftops.init_display != init_display) { + /* don't risk messing up register 11h */ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "%s: skipping since custom init_display() is used\n", + __func__); + return 0; + } + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x11, reg11 | 0b110000); + break; + case 270: + write_reg(par, 0x11, reg11 | 0b101000); + break; + case 180: + write_reg(par, 0x11, reg11 | 0b000000); + break; + case 90: + write_reg(par, 0x11, reg11 | 0b011000); + break; + } + + return 0; +} + +/* + Gamma string format: + VRP0 VRP1 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 + VRN0 VRN1 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111, + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < 2; i++) + for (j = 0; j < 10; j++) + CURVE(i, j) &= mask[i*par->gamma.num_values + j]; + + write_reg(par, 0x0030, CURVE(0, 5) << 8 | CURVE(0, 4)); + write_reg(par, 0x0031, CURVE(0, 7) << 8 | CURVE(0, 6)); + write_reg(par, 0x0032, CURVE(0, 9) << 8 | CURVE(0, 8)); + write_reg(par, 0x0033, CURVE(0, 3) << 8 | CURVE(0, 2)); + write_reg(par, 0x0034, CURVE(1, 5) << 8 | CURVE(1, 4)); + write_reg(par, 0x0035, CURVE(1, 7) << 8 | CURVE(1, 6)); + write_reg(par, 0x0036, CURVE(1, 9) << 8 | CURVE(1, 8)); + write_reg(par, 0x0037, CURVE(1, 3) << 8 | CURVE(1, 2)); + write_reg(par, 0x003A, CURVE(0, 1) << 8 | CURVE(0, 0)); + write_reg(par, 0x003B, CURVE(1, 1) << 8 | CURVE(1, 0)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = 2, + .gamma_len = 10, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1289", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ssd1289"); +MODULE_ALIAS("platform:ssd1289"); + +MODULE_DESCRIPTION("FB driver for the SSD1289 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ssd1306.c b/drivers/staging/fbtft/fb_ssd1306.c new file mode 100644 index 00000000000..5ea195b0de1 --- /dev/null +++ b/drivers/staging/fbtft/fb_ssd1306.c @@ -0,0 +1,229 @@ +/* + * FB driver for the SSD1306 OLED Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ssd1306" +#define WIDTH 128 +#define HEIGHT 64 + + +/* + write_reg() caveat: + + This doesn't work because D/C has to be LOW for both values: + write_reg(par, val1, val2); + + Do it like this: + write_reg(par, val1); + write_reg(par, val2); +*/ + +/* Init sequence taken from the Adafruit SSD1306 Arduino library */ +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gamma.curves[0] == 0) { + mutex_lock(&par->gamma.lock); + if (par->info->var.yres == 64) + par->gamma.curves[0] = 0xCF; + else + par->gamma.curves[0] = 0x8F; + mutex_unlock(&par->gamma.lock); + } + + /* Set Display OFF */ + write_reg(par, 0xAE); + + /* Set Display Clock Divide Ratio/ Oscillator Frequency */ + write_reg(par, 0xD5); + write_reg(par, 0x80); + + /* Set Multiplex Ratio */ + write_reg(par, 0xA8); + if (par->info->var.yres == 64) + write_reg(par, 0x3F); + else + write_reg(par, 0x1F); + + /* Set Display Offset */ + write_reg(par, 0xD3); + write_reg(par, 0x0); + + /* Set Display Start Line */ + write_reg(par, 0x40 | 0x0); + + /* Charge Pump Setting */ + write_reg(par, 0x8D); + /* A[2] = 1b, Enable charge pump during display on */ + write_reg(par, 0x14); + + /* Set Memory Addressing Mode */ + write_reg(par, 0x20); + /* Vertical addressing mode */ + write_reg(par, 0x01); + + /*Set Segment Re-map */ + /* column address 127 is mapped to SEG0 */ + write_reg(par, 0xA0 | 0x1); + + /* Set COM Output Scan Direction */ + /* remapped mode. Scan from COM[N-1] to COM0 */ + write_reg(par, 0xC8); + + /* Set COM Pins Hardware Configuration */ + write_reg(par, 0xDA); + if (par->info->var.yres == 64) + /* A[4]=1b, Alternative COM pin configuration */ + write_reg(par, 0x12); + else + /* A[4]=0b, Sequential COM pin configuration */ + write_reg(par, 0x02); + + /* Set Pre-charge Period */ + write_reg(par, 0xD9); + write_reg(par, 0xF1); + + /* Set VCOMH Deselect Level */ + write_reg(par, 0xDB); + /* according to the datasheet, this value is out of bounds */ + write_reg(par, 0x40); + + /* Entire Display ON */ + /* Resume to RAM content display. Output follows RAM content */ + write_reg(par, 0xA4); + + /* Set Normal Display + 0 in RAM: OFF in display panel + 1 in RAM: ON in display panel */ + write_reg(par, 0xA6); + + /* Set Display ON */ + write_reg(par, 0xAF); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Set Lower Column Start Address for Page Addressing Mode */ + write_reg(par, 0x00 | 0x0); + /* Set Higher Column Start Address for Page Addressing Mode */ + write_reg(par, 0x10 | 0x0); + /* Set Display Start Line */ + write_reg(par, 0x40 | 0x0); +} + +static int blank(struct fbtft_par *par, bool on) +{ + fbtft_par_dbg(DEBUG_BLANK, par, "%s(blank=%s)\n", + __func__, on ? "true" : "false"); + + if (on) + write_reg(par, 0xAE); + else + write_reg(par, 0xAF); + return 0; +} + +/* Gamma is used to control Contrast */ +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + curves[0] &= 0xFF; + + /* Set Contrast Control for BANK0 */ + write_reg(par, 0x81); + write_reg(par, curves[0]); + + return 0; +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + u8 *buf = par->txbuf.buf; + int x, y, i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + for (x = 0; x < par->info->var.xres; x++) { + for (y = 0; y < par->info->var.yres/8; y++) { + *buf = 0x00; + for (i = 0; i < 8; i++) + *buf |= (vmem16[(y*8+i)*par->info->var.xres+x] ? 1 : 0) << i; + buf++; + } + } + + /* Write data */ + gpio_set_value(par->gpio.dc, 1); + ret = par->fbtftops.write(par, par->txbuf.buf, + par->info->var.xres*par->info->var.yres/8); + if (ret < 0) + dev_err(par->info->device, + "%s: write failed and returned: %d\n", __func__, ret); + + return ret; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = 1, + .gamma_len = 1, + .gamma = "00", + .fbtftops = { + .write_vmem = write_vmem, + .init_display = init_display, + .set_addr_win = set_addr_win, + .blank = blank, + .set_gamma = set_gamma, + }, +}; + + +FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1306", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ssd1306"); +MODULE_ALIAS("platform:ssd1306"); + +MODULE_DESCRIPTION("SSD1306 OLED Driver"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ssd1331.c b/drivers/staging/fbtft/fb_ssd1331.c new file mode 100644 index 00000000000..da7464f90e3 --- /dev/null +++ b/drivers/staging/fbtft/fb_ssd1331.c @@ -0,0 +1,205 @@ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ssd1331" +#define WIDTH 96 +#define HEIGHT 64 +#define GAMMA_NUM 1 +#define GAMMA_LEN 63 +#define DEFAULT_GAMMA "0 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2" \ + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + write_reg(par, 0xae); /* Display Off */ + write_reg(par, 0xa0, 0x70 | (par->bgr << 2)); /* Set Colour Depth */ + write_reg(par, 0x72); // RGB colour + write_reg(par, 0xa1, 0x00); /* Set Display Start Line */ + write_reg(par, 0xa2, 0x00); /* Set Display Offset */ + write_reg(par, 0xa4); /* NORMALDISPLAY */ + write_reg(par, 0xa8, 0x3f); // Set multiplex + write_reg(par, 0xad, 0x8e); // Set master + // write_reg(par, 0xb0, 0x0b); // Set power mode + write_reg(par, 0xb1, 0x31); // Precharge + write_reg(par, 0xb3, 0xf0); // Clock div + write_reg(par, 0x8a, 0x64); // Precharge A + write_reg(par, 0x8b, 0x78); // Precharge B + write_reg(par, 0x8c, 0x64); // Precharge C + write_reg(par, 0xbb, 0x3a); // Precharge level + write_reg(par, 0xbe, 0x3e); // vcomh + write_reg(par, 0x87, 0x06); // Master current + write_reg(par, 0x81, 0x91); // Contrast A + write_reg(par, 0x82, 0x50); // Contrast B + write_reg(par, 0x83, 0x7d); // Contrast C + write_reg(par, 0xaf); /* Set Sleep Mode Display On */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, 0x15, xs, xe); + write_reg(par, 0x75, ys, ye); +} + +static void write_reg8_bus8(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + u8 *buf = (u8 *)par->buf; + + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { + va_start(args, len); + for (i = 0; i < len; i++) { + buf[i] = (u8)va_arg(args, unsigned int); + } + va_end(args); + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device, u8, buf, len, "%s: ", __func__); + } + + va_start(args, len); + + *buf = (u8)va_arg(args, unsigned int); + if (par->gpio.dc != -1) + gpio_set_value(par->gpio.dc, 0); + ret = par->fbtftops.write(par, par->buf, sizeof(u8)); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); + return; + } + len--; + + if (len) { + i = len; + while (i--) { + *buf++ = (u8)va_arg(args, unsigned int); + } + ret = par->fbtftops.write(par, par->buf, len * (sizeof(u8))); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); + return; + } + } + if (par->gpio.dc != -1) + gpio_set_value(par->gpio.dc, 1); + va_end(args); +} + +/* + Grayscale Lookup Table + GS1 - GS63 + The driver Gamma curve contains the relative values between the entries + in the Lookup table. + + From datasheet: + 8.8 Gray Scale Decoder + + there are total 180 Gamma Settings (Setting 0 to Setting 180) + available for the Gray Scale table. + + The gray scale is defined in incremental way, with reference + to the length of previous table entry: + Setting of GS1 has to be >= 0 + Setting of GS2 has to be > Setting of GS1 +1 + Setting of GS3 has to be > Setting of GS2 +1 + : + Setting of GS63 has to be > Setting of GS62 +1 + + +*/ +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long tmp[GAMMA_NUM * GAMMA_LEN]; + int i, acc = 0; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + for (i = 0; i < 63; i++) { + if (i > 0 && curves[i] < 2) { + dev_err(par->info->device, + "Illegal value in Grayscale Lookup Table at index %d. " \ + "Must be greater than 1\n", i); + return -EINVAL; + } + acc += curves[i]; + tmp[i] = acc; + if (acc > 180) { + dev_err(par->info->device, + "Illegal value(s) in Grayscale Lookup Table. " \ + "At index=%d, the accumulated value has exceeded 180\n", i); + return -EINVAL; + } + } + + write_reg(par, 0xB8, + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], + tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + tmp[16], tmp[17], tmp[18], tmp[19], tmp[20], tmp[21], tmp[22], tmp[23], + tmp[24], tmp[25], tmp[26], tmp[27], tmp[28], tmp[29], tmp[30], tmp[31], + tmp[32], tmp[33], tmp[34], tmp[35], tmp[36], tmp[37], tmp[38], tmp[39], + tmp[40], tmp[41], tmp[42], tmp[43], tmp[44], tmp[45], tmp[46], tmp[47], + tmp[48], tmp[49], tmp[50], tmp[51], tmp[52], tmp[53], tmp[54], tmp[55], + tmp[56], tmp[57], tmp[58], tmp[59], tmp[60], tmp[61], tmp[62]); + + return 0; +} + +static int blank(struct fbtft_par *par, bool on) +{ + fbtft_par_dbg(DEBUG_BLANK, par, "%s(blank=%s)\n", + __func__, on ? "true" : "false"); + if (on) + write_reg(par, 0xAE); + else + write_reg(par, 0xAF); + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = GAMMA_NUM, + .gamma_len = GAMMA_LEN, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .write_register = write_reg8_bus8, + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_gamma = set_gamma, + .blank = blank, + }, +}; + +FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1331", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ssd1331"); +MODULE_ALIAS("platform:ssd1331"); + +MODULE_DESCRIPTION("SSD1331 OLED Driver"); +MODULE_AUTHOR("Alec Smecher (adapted from SSD1351 by James Davies)"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c new file mode 100644 index 00000000000..062d98660f6 --- /dev/null +++ b/drivers/staging/fbtft/fb_ssd1351.c @@ -0,0 +1,258 @@ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_ssd1351" +#define WIDTH 128 +#define HEIGHT 128 +#define GAMMA_NUM 1 +#define GAMMA_LEN 63 +#define DEFAULT_GAMMA "0 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2" \ + +static void register_onboard_backlight(struct fbtft_par *par); + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (par->pdata + && par->pdata->display.backlight == FBTFT_ONBOARD_BACKLIGHT) { + /* module uses onboard GPIO for panel power */ + par->fbtftops.register_backlight = register_onboard_backlight; + } + + par->fbtftops.reset(par); + + write_reg(par, 0xfd, 0x12); /* Command Lock */ + write_reg(par, 0xfd, 0xb1); /* Command Lock */ + write_reg(par, 0xae); /* Display Off */ + write_reg(par, 0xb3, 0xf1); /* Front Clock Div */ + write_reg(par, 0xca, 0x7f); /* Set Mux Ratio */ + write_reg(par, 0x15, 0x00, 0x7f); /* Set Column Address */ + write_reg(par, 0x75, 0x00, 0x7f); /* Set Row Address */ + write_reg(par, 0xa1, 0x00); /* Set Display Start Line */ + write_reg(par, 0xa2, 0x00); /* Set Display Offset */ + write_reg(par, 0xb5, 0x00); /* Set GPIO */ + write_reg(par, 0xab, 0x01); /* Set Function Selection */ + write_reg(par, 0xb1, 0x32); /* Set Phase Length */ + write_reg(par, 0xb4, 0xa0, 0xb5, 0x55); /* Set Segment Low Voltage */ + write_reg(par, 0xbb, 0x17); /* Set Precharge Voltage */ + write_reg(par, 0xbe, 0x05); /* Set VComH Voltage */ + write_reg(par, 0xc1, 0xc8, 0x80, 0xc8); /* Set Contrast */ + write_reg(par, 0xc7, 0x0f); /* Set Master Contrast */ + write_reg(par, 0xb6, 0x01); /* Set Second Precharge Period */ + write_reg(par, 0xa6); /* Set Display Mode Reset */ + write_reg(par, 0xaf); /* Set Sleep Mode Display On */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, 0x15, xs, xe); + write_reg(par, 0x75, ys, ye); + write_reg(par, 0x5c); +} + +static int set_var(struct fbtft_par *par) +{ + unsigned remap; + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (par->fbtftops.init_display != init_display) { + /* don't risk messing up register A0h */ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "%s: skipping since custom init_display() is used\n", + __func__); + return 0; + } + + remap = 0x60 | (par->bgr << 2); /* Set Colour Depth */ + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0xA0, remap | 0b00 | 1<<4); + break; + case 270: + write_reg(par, 0xA0, remap | 0b11 | 1<<4); + break; + case 180: + write_reg(par, 0xA0, remap | 0b10); + break; + case 90: + write_reg(par, 0xA0, remap | 0b01); + break; + } + + return 0; +} + +/* + Grayscale Lookup Table + GS1 - GS63 + The driver Gamma curve contains the relative values between the entries + in the Lookup table. + + From datasheet: + 8.8 Gray Scale Decoder + + there are total 180 Gamma Settings (Setting 0 to Setting 180) + available for the Gray Scale table. + + The gray scale is defined in incremental way, with reference + to the length of previous table entry: + Setting of GS1 has to be >= 0 + Setting of GS2 has to be > Setting of GS1 +1 + Setting of GS3 has to be > Setting of GS2 +1 + : + Setting of GS63 has to be > Setting of GS62 +1 + + +*/ +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long tmp[GAMMA_NUM * GAMMA_LEN]; + int i, acc = 0; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + for (i = 0; i < 63; i++) { + if (i > 0 && curves[i] < 2) { + dev_err(par->info->device, + "Illegal value in Grayscale Lookup Table at index %d. " \ + "Must be greater than 1\n", i); + return -EINVAL; + } + acc += curves[i]; + tmp[i] = acc; + if (acc > 180) { + dev_err(par->info->device, + "Illegal value(s) in Grayscale Lookup Table. " \ + "At index=%d, the accumulated value has exceeded 180\n", i); + return -EINVAL; + } + } + + write_reg(par, 0xB8, + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], + tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + tmp[16], tmp[17], tmp[18], tmp[19], tmp[20], tmp[21], tmp[22], tmp[23], + tmp[24], tmp[25], tmp[26], tmp[27], tmp[28], tmp[29], tmp[30], tmp[31], + tmp[32], tmp[33], tmp[34], tmp[35], tmp[36], tmp[37], tmp[38], tmp[39], + tmp[40], tmp[41], tmp[42], tmp[43], tmp[44], tmp[45], tmp[46], tmp[47], + tmp[48], tmp[49], tmp[50], tmp[51], tmp[52], tmp[53], tmp[54], tmp[55], + tmp[56], tmp[57], tmp[58], tmp[59], tmp[60], tmp[61], tmp[62]); + + return 0; +} + +static int blank(struct fbtft_par *par, bool on) +{ + fbtft_par_dbg(DEBUG_BLANK, par, "%s(blank=%s)\n", + __func__, on ? "true" : "false"); + if (on) + write_reg(par, 0xAE); + else + write_reg(par, 0xAF); + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = GAMMA_NUM, + .gamma_len = GAMMA_LEN, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + .blank = blank, + }, +}; + +#ifdef CONFIG_FB_BACKLIGHT +static int update_onboard_backlight(struct backlight_device *bd) +{ + struct fbtft_par *par = bl_get_data(bd); + bool on; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, + "%s: power=%d, fb_blank=%d\n", + __func__, bd->props.power, bd->props.fb_blank); + + on = (bd->props.power == FB_BLANK_UNBLANK) + && (bd->props.fb_blank == FB_BLANK_UNBLANK); + /* Onboard backlight connected to GPIO0 on SSD1351, GPIO1 unused */ + write_reg(par, 0xB5, on ? 0x03 : 0x02); + + return 0; +} + +static void register_onboard_backlight(struct fbtft_par *par) +{ + struct backlight_device *bd; + struct backlight_properties bl_props = { 0, }; + struct backlight_ops *bl_ops; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__); + + bl_ops = devm_kzalloc(par->info->device, sizeof(struct backlight_ops), + GFP_KERNEL); + if (!bl_ops) { + dev_err(par->info->device, + "%s: could not allocate memory for backlight operations.\n", + __func__); + return; + } + + bl_ops->update_status = update_onboard_backlight; + bl_props.type = BACKLIGHT_RAW; + bl_props.power = FB_BLANK_POWERDOWN; + + bd = backlight_device_register(dev_driver_string(par->info->device), + par->info->device, par, bl_ops, &bl_props); + if (IS_ERR(bd)) { + dev_err(par->info->device, + "cannot register backlight device (%ld)\n", + PTR_ERR(bd)); + return; + } + par->info->bl_dev = bd; + + if (!par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight = fbtft_unregister_backlight; +} +#else +static void register_onboard_backlight(struct fbtft_par *par) { }; +#endif + + +FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1351", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ssd1351"); +MODULE_ALIAS("platform:ssd1351"); + +MODULE_DESCRIPTION("SSD1351 OLED Driver"); +MODULE_AUTHOR("James Davies"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_st7735r.c b/drivers/staging/fbtft/fb_st7735r.c new file mode 100644 index 00000000000..b63aa38e51c --- /dev/null +++ b/drivers/staging/fbtft/fb_st7735r.c @@ -0,0 +1,195 @@ +/* + * FB driver for the ST7735R LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> + +#include "fbtft.h" + +#define DRVNAME "fb_st7735r" +#define DEFAULT_GAMMA "0F 1A 0F 18 2F 28 20 22 1F 1B 23 37 00 07 02 10\n" \ + "0F 1B 0F 17 33 2C 29 2E 30 30 39 3F 00 07 03 10" + + +static int default_init_sequence[] = { + /* SWRESET - Software reset */ + -1, 0x01, + -2, 150, /* delay */ + + /* SLPOUT - Sleep out & booster on */ + -1, 0x11, + -2, 500, /* delay */ + + /* FRMCTR1 - frame rate control: normal mode + frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ + -1, 0xB1, 0x01, 0x2C, 0x2D, + + /* FRMCTR2 - frame rate control: idle mode + frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ + -1, 0xB2, 0x01, 0x2C, 0x2D, + + /* FRMCTR3 - frame rate control - partial mode + dot inversion mode, line inversion mode */ + -1, 0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, + + /* INVCTR - display inversion control + no inversion */ + -1, 0xB4, 0x07, + + /* PWCTR1 - Power Control + -4.6V, AUTO mode */ + -1, 0xC0, 0xA2, 0x02, 0x84, + + /* PWCTR2 - Power Control + VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD */ + -1, 0xC1, 0xC5, + + /* PWCTR3 - Power Control + Opamp current small, Boost frequency */ + -1, 0xC2, 0x0A, 0x00, + + /* PWCTR4 - Power Control + BCLK/2, Opamp current small & Medium low */ + -1, 0xC3,0x8A,0x2A, + + /* PWCTR5 - Power Control */ + -1, 0xC4, 0x8A, 0xEE, + + /* VMCTR1 - Power Control */ + -1, 0xC5, 0x0E, + + /* INVOFF - Display inversion off */ + -1, 0x20, + + /* COLMOD - Interface pixel format */ + -1, 0x3A, 0x05, + + /* DISPON - Display On */ + -1, 0x29, + -2, 100, /* delay */ + + /* NORON - Partial off (Normal) */ + -1, 0x13, + -2, 10, /* delay */ + + /* end marker */ + -3 +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +#define MY (1 << 7) +#define MX (1 << 6) +#define MV (1 << 5) +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* MADCTL - Memory data access control + RGB/BGR: + 1. Mode selection pin SRGB + RGB H/W pin for color filter setting: 0=RGB, 1=BGR + 2. MADCTL RGB bit + RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, MX | MY | (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, MY | MV | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, MX | MV | (par->bgr << 3)); + break; + } + + return 0; +} + +/* + Gamma string format: + VRF0P VOS0P PK0P PK1P PK2P PK3P PK4P PK5P PK6P PK7P PK8P PK9P SELV0P SELV1P SELV62P SELV63P + VRF0N VOS0N PK0N PK1N PK2N PK3N PK4N PK5N PK6N PK7N PK8N PK9N SELV0N SELV1N SELV62N SELV63N +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + int i,j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < par->gamma.num_curves; i++) + for (j = 0; j < par->gamma.num_values; j++) + CURVE(i,j) &= 0b111111; + + for (i = 0; i < par->gamma.num_curves; i++) + write_reg(par, 0xE0 + i, + CURVE(i, 0), CURVE(i, 1), CURVE(i, 2), CURVE(i, 3), + CURVE(i, 4), CURVE(i, 5), CURVE(i, 6), CURVE(i, 7), + CURVE(i, 8), CURVE(i, 9), CURVE(i, 10), CURVE(i, 11), + CURVE(i, 12), CURVE(i, 13), CURVE(i, 14), CURVE(i,15)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 8, + .width = 128, + .height = 160, + .init_sequence = default_init_sequence, + .gamma_num = 2, + .gamma_len = 16, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "sitronix,st7735r", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:st7735r"); +MODULE_ALIAS("platform:st7735r"); + +MODULE_DESCRIPTION("FB driver for the ST7735R LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_tinylcd.c b/drivers/staging/fbtft/fb_tinylcd.c new file mode 100644 index 00000000000..ca98bfb5c7d --- /dev/null +++ b/drivers/staging/fbtft/fb_tinylcd.c @@ -0,0 +1,124 @@ +/* + * Custom FB driver for tinylcd.com display + * + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_tinylcd" +#define WIDTH 320 +#define HEIGHT 480 + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + write_reg(par, 0xB0, 0x80); + write_reg(par, 0xC0, 0x0A, 0x0A); + write_reg(par, 0xC1, 0x45, 0x07); + write_reg(par, 0xC2, 0x33); + write_reg(par, 0xC5, 0x00, 0x42, 0x80); + write_reg(par, 0xB1, 0xD0, 0x11); + write_reg(par, 0xB4, 0x02); + write_reg(par, 0xB6, 0x00, 0x22, 0x3B); + write_reg(par, 0xB7, 0x07); + write_reg(par, 0x36, 0x58); + write_reg(par, 0xF0, 0x36, 0xA5, 0xD3); + write_reg(par, 0xE5, 0x80); + write_reg(par, 0xE5, 0x01); + write_reg(par, 0xB3, 0x00); + write_reg(par, 0xE5, 0x00); + write_reg(par, 0xF0, 0x36, 0xA5, 0x53); + write_reg(par, 0xE0, 0x00, 0x35, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x35, 0x33, 0x00, 0x00, 0x00); + write_reg(par, 0x3A, 0x55); + write_reg(par, 0x11); + udelay(250); + write_reg(par, 0x29); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 270: + write_reg(par, 0xB6, 0x00, 0x02, 0x3B); + write_reg(par, 0x36, 0x28); + break; + case 180: + write_reg(par, 0xB6, 0x00, 0x22, 0x3B); + write_reg(par, 0x36, 0x58); + break; + case 90: + write_reg(par, 0xB6, 0x00, 0x22, 0x3B); + write_reg(par, 0x36, 0x38); + break; + default: + write_reg(par, 0xB6, 0x00, 0x22, 0x3B); + write_reg(par, 0x36, 0x08); + break; + } + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "neosec,tinylcd", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("spi:tinylcd"); + +MODULE_DESCRIPTION("Custom FB driver for tinylcd.com display"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_tls8204.c b/drivers/staging/fbtft/fb_tls8204.c new file mode 100644 index 00000000000..8738c7a7bfd --- /dev/null +++ b/drivers/staging/fbtft/fb_tls8204.c @@ -0,0 +1,176 @@ +/* + * FB driver for the TLS8204 LCD Controller + * + * The display is monochrome and the video memory is RGB565. + * Any pixel value except 0 turns the pixel on. + * + * Copyright (C) 2013 Noralf Tronnes + * Copyright (C) 2014 Michael Hope (adapted for the TLS8204) + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_tls8204" +#define WIDTH 84 +#define HEIGHT 48 +#define TXBUFLEN WIDTH +#define DEFAULT_GAMMA "40" /* gamma is used to control contrast in this driver */ + +static unsigned bs = 4; +module_param(bs, uint, 0); +MODULE_PARM_DESC(bs, "BS[2:0] Bias voltage level: 0-7 (default: 4)"); + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* Enter extended command mode */ + write_reg(par, 0x21); /* 5:1 1 + 2:0 PD - Powerdown control: chip is active + 1:0 V - Entry mode: horizontal addressing + 0:1 H - Extended instruction set control: extended + */ + + /* H=1 Bias system */ + write_reg(par, 0x10 | (bs & 0x7)); /* + 4:1 1 + 3:0 0 + 2:x BS2 - Bias System + 1:x BS1 + 0:x BS0 + */ + + /* Set the address of the first display line. */ + write_reg(par, 0x04 | (64 >> 6)); + write_reg(par, 0x40 | (64 & 0x3F)); + + /* Enter H=0 standard command mode */ + write_reg(par, 0x20); + + /* H=0 Display control */ + write_reg(par, 0x08 | 4); /* + 3:1 1 + 2:1 D - DE: 10=normal mode + 1:0 0 + 0:0 E + */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* H=0 Set X address of RAM */ + write_reg(par, 0x80); /* 7:1 1 + 6-0: X[6:0] - 0x00 + */ + + /* H=0 Set Y address of RAM */ + write_reg(par, 0x40); /* 7:0 0 + 6:1 1 + 2-0: Y[2:0] - 0x0 + */ +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + int x, y, i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + for (y = 0; y < HEIGHT/8; y++) { + u8 *buf = par->txbuf.buf; + /* The display is 102x68 but the LCD is 84x48. Set + the write pointer at the start of each row. */ + gpio_set_value(par->gpio.dc, 0); + write_reg(par, 0x80 | 0); + write_reg(par, 0x40 | y); + + for (x = 0; x < WIDTH; x++) { + u8 ch = 0; + for (i = 0; i < 8*WIDTH; i += WIDTH) { + ch >>= 1; + if (vmem16[(y*8*WIDTH)+i+x]) + ch |= 0x80; + } + *buf++ = ch; + } + /* Write the row */ + gpio_set_value(par->gpio.dc, 1); + ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH); + if (ret < 0) { + dev_err(par->info->device, + "%s: write failed and returned: %d\n", __func__, ret); + break; + } + } + + return ret; +} + +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + curves[0] &= 0x7F; + + write_reg(par, 0x21); /* turn on extended instruction set */ + write_reg(par, 0x80 | curves[0]); + write_reg(par, 0x20); /* turn off extended instruction set */ + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .txbuflen = TXBUFLEN, + .gamma_num = 1, + .gamma_len = 1, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .write_vmem = write_vmem, + .set_gamma = set_gamma, + }, + .backlight = 1, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "teralane,tls8204", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("spi:tls8204"); + +MODULE_DESCRIPTION("FB driver for the TLS8204 LCD Controller"); +MODULE_AUTHOR("Michael Hope"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_uc1701.c b/drivers/staging/fbtft/fb_uc1701.c new file mode 100644 index 00000000000..d70ac524278 --- /dev/null +++ b/drivers/staging/fbtft/fb_uc1701.c @@ -0,0 +1,210 @@ +/* + * FB driver for the UC1701 LCD Controller + * + * The display is monochrome and the video memory is RGB565. + * Any pixel value except 0 turns the pixel on. + * + * Copyright (C) 2014 Juergen Holzmann + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_uc1701" +#define WIDTH 102 +#define HEIGHT 64 +#define PAGES (HEIGHT/8) + +/* 1: Display on/off */ +#define LCD_DISPLAY_ENABLE 0xAE +/* 2: display start line set */ +#define LCD_START_LINE 0x40 +/* 3: Page address set (lower 4 bits select one of the pages) */ +#define LCD_PAGE_ADDRESS 0xB0 +/* 4: column address */ +#define LCD_COL_ADDRESS 0x10 +/* 8: select orientation */ +#define LCD_BOTTOMVIEW 0xA0 +/* 9: inverted display */ +#define LCD_DISPLAY_INVERT 0xA6 +/* 10: show memory content or switch all pixels on */ +#define LCD_ALL_PIXEL 0xA4 +/* 11: lcd bias set */ +#define LCD_BIAS 0xA2 +/* 14: Reset Controller */ +#define LCD_RESET_CMD 0xE2 +/* 15: output mode select (turns display upside-down) */ +#define LCD_SCAN_DIR 0xC0 +/* 16: power control set */ +#define LCD_POWER_CONTROL 0x28 +/* 17: voltage regulator resistor ratio set */ +#define LCD_VOLTAGE 0x20 +/* 18: Volume mode set */ +#define LCD_VOLUME_MODE 0x81 +/* 22: NOP command */ +#define LCD_NO_OP 0xE3 +/* 25: advanced program control */ +#define LCD_ADV_PROG_CTRL 0xFA +/* 25: advanced program control2 */ +#define LCD_ADV_PROG_CTRL2 0x10 +#define LCD_TEMPCOMP_HIGH 0x80 +/* column offset for normal orientation */ +#define SHIFT_ADDR_NORMAL 0 +/* column offset for bottom view orientation */ +#define SHIFT_ADDR_TOPVIEW 30 + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* softreset of LCD */ + write_reg(par, LCD_RESET_CMD); + mdelay(10); + + /* set startpoint */ + /* LCD_START_LINE | (pos & 0x3F) */ + write_reg(par, LCD_START_LINE); + + /* select orientation BOTTOMVIEW */ + write_reg(par, LCD_BOTTOMVIEW | 1); + /* output mode select (turns display upside-down) */ + write_reg(par, LCD_SCAN_DIR | 0x00); + + /* Normal Pixel mode */ + write_reg(par, LCD_ALL_PIXEL | 0); + + /* positive display */ + write_reg(par, LCD_DISPLAY_INVERT | 0); + + /* bias 1/9 */ + write_reg(par, LCD_BIAS | 0); + + /* power control mode: all features on */ + /* LCD_POWER_CONTROL | (val&0x07) */ + write_reg(par, LCD_POWER_CONTROL | 0x07); + + /* set voltage regulator R/R */ + /* LCD_VOLTAGE | (val&0x07) */ + write_reg(par, LCD_VOLTAGE | 0x07); + + /* volume mode set */ + /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ + write_reg(par, LCD_VOLUME_MODE); + /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ + write_reg(par, 0x09); + /* ???? */ + /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ + write_reg(par, LCD_NO_OP); + + /* advanced program control */ + write_reg(par, LCD_ADV_PROG_CTRL); + write_reg(par, LCD_ADV_PROG_CTRL2|LCD_TEMPCOMP_HIGH); + + /* enable display */ + write_reg(par, LCD_DISPLAY_ENABLE | 1); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* goto address */ + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_PAGE_ADDRESS); + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, 0x00); + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_COL_ADDRESS); +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + u8 *buf = par->txbuf.buf; + int x, y, i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + for (y = 0; y < PAGES; y++) { + buf = par->txbuf.buf; + for (x = 0; x < WIDTH; x++) { + *buf = 0x00; + for (i = 0; i < 8; i++) + *buf |= (vmem16[((y*8*WIDTH)+(i*WIDTH))+x] ? 1 : 0) << i; + buf++; + } + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_PAGE_ADDRESS|(u8)y); + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, 0x00); + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_COL_ADDRESS); + gpio_set_value(par->gpio.dc, 1); + ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH); + gpio_set_value(par->gpio.dc, 0); + } + + if (ret < 0) + dev_err(par->info->device, "%s: write failed and returned: %d\n", __func__, ret); + + return ret; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .write_vmem = write_vmem, + }, + .backlight = 1, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "UltraChip,uc1701", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("spi:uc1701"); + +MODULE_DESCRIPTION("FB driver for the UC1701 LCD Controller"); +MODULE_AUTHOR("Juergen Holzmann"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_upd161704.c b/drivers/staging/fbtft/fb_upd161704.c new file mode 100644 index 00000000000..fff57b330ba --- /dev/null +++ b/drivers/staging/fbtft/fb_upd161704.c @@ -0,0 +1,206 @@ +/* + * FB driver for the uPD161704 LCD Controller + * + * Copyright (C) 2014 Seong-Woo Kim + * + * Based on fb_ili9325.c by Noralf Tronnes + * Based on ili9325.c by Jeroen Domburg + * Init code from UTFT library by Henning Karlsen + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_upd161704" +#define WIDTH 240 +#define HEIGHT 320 +#define BPP 16 + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + /* Initialization sequence from Lib_UTFT */ + + /* register reset */ + write_reg(par, 0x0003,0x0001); /* Soft reset */ + + /* oscillator start */ + write_reg(par, 0x003A,0x0001); /*Oscillator 0: stop, 1: operation */ + udelay(100); + + /* y-setting */ + write_reg(par, 0x0024,0x007B); /* amplitude setting */ + udelay(10); + write_reg(par, 0x0025,0x003B); /* amplitude setting */ + write_reg(par, 0x0026,0x0034); /* amplitude setting */ + udelay(10); + write_reg(par, 0x0027,0x0004); /* amplitude setting */ + write_reg(par, 0x0052,0x0025); /* circuit setting 1 */ + udelay(10); + write_reg(par, 0x0053,0x0033); /* circuit setting 2 */ + write_reg(par, 0x0061,0x001C); /* adjustment V10 positive polarity */ + udelay(10); + write_reg(par, 0x0062,0x002C); /* adjustment V9 negative polarity */ + write_reg(par, 0x0063,0x0022); /* adjustment V34 positive polarity */ + udelay(10); + write_reg(par, 0x0064,0x0027); /* adjustment V31 negative polarity */ + udelay(10); + write_reg(par, 0x0065,0x0014); /* adjustment V61 negative polarity */ + udelay(10); + write_reg(par, 0x0066,0x0010); /* adjustment V61 negative polarity */ + + /* Basical clock for 1 line (BASECOUNT[7:0]) number specified */ + write_reg(par, 0x002E,0x002D); + + /* Power supply setting */ + write_reg(par, 0x0019,0x0000); /* DC/DC output setting */ + udelay(200); + write_reg(par, 0x001A,0x1000); /* DC/DC frequency setting */ + write_reg(par, 0x001B,0x0023); /* DC/DC rising setting */ + write_reg(par, 0x001C,0x0C01); /* Regulator voltage setting */ + write_reg(par, 0x001D,0x0000); /* Regulator current setting */ + write_reg(par, 0x001E,0x0009); /* VCOM output setting */ + write_reg(par, 0x001F,0x0035); /* VCOM amplitude setting */ + write_reg(par, 0x0020,0x0015); /* VCOMM cencter setting */ + write_reg(par, 0x0018,0x1E7B); /* DC/DC operation setting */ + + /* windows setting */ + write_reg(par, 0x0008,0x0000); /* Minimum X address */ + write_reg(par, 0x0009,0x00EF); /* Maximum X address */ + write_reg(par, 0x000a,0x0000); /* Minimum Y address */ + write_reg(par, 0x000b,0x013F); /* Maximum Y address */ + + /* LCD display area setting */ + write_reg(par, 0x0029,0x0000); /* [LCDSIZE] X MIN. size set */ + write_reg(par, 0x002A,0x0000); /* [LCDSIZE] Y MIN. size set */ + write_reg(par, 0x002B,0x00EF); /* [LCDSIZE] X MAX. size set */ + write_reg(par, 0x002C,0x013F); /* [LCDSIZE] Y MAX. size set */ + + /* Gate scan setting */ + write_reg(par, 0x0032,0x0002); + + /* n line inversion line number */ + write_reg(par, 0x0033,0x0000); + + /* Line inversion/frame inversion/interlace setting */ + write_reg(par, 0x0037,0x0000); + + /* Gate scan operation setting register */ + write_reg(par, 0x003B,0x0001); + + /* Color mode */ + /*GS = 0: 260-k color (64 gray scale), GS = 1: 8 color (2 gray scale) */ + write_reg(par, 0x0004,0x0000); + + /* RAM control register */ + write_reg(par, 0x0005,0x0000); /*Window access 00:Normal, 10:Window */ + + /* Display setting register 2 */ + write_reg(par, 0x0001,0x0000); + + /* display setting */ + write_reg(par, 0x0000,0x0000); /* display on */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0006, xs); + write_reg(par, 0x0007, ys); + break; + case 180: + write_reg(par, 0x0006, WIDTH - 1 - xs); + write_reg(par, 0x0007, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0006, WIDTH - 1 - ys); + write_reg(par, 0x0007, xs); + break; + case 90: + write_reg(par, 0x0006, ys); + write_reg(par, 0x0007, HEIGHT - 1 - xs); + break; + } + + write_reg(par, 0x0e); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + /* AM: GRAM update direction */ + case 0: + write_reg(par, 0x01, 0x0000); + write_reg(par, 0x05, 0x0000); + break; + case 180: + write_reg(par, 0x01, 0x00C0); + write_reg(par, 0x05, 0x0000); + break; + case 270: + write_reg(par, 0x01, 0x0080); + write_reg(par, 0x05, 0x0001); + break; + case 90: + write_reg(par, 0x01, 0x0040); + write_reg(par, 0x05, 0x0001); + break; + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "nec,upd161704", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:upd161704"); +MODULE_ALIAS("platform:upd161704"); + +MODULE_DESCRIPTION("FB driver for the uPD161704 LCD Controller"); +MODULE_AUTHOR("Seong-Woo Kim"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fb_watterott.c b/drivers/staging/fbtft/fb_watterott.c new file mode 100644 index 00000000000..975b579359f --- /dev/null +++ b/drivers/staging/fbtft/fb_watterott.c @@ -0,0 +1,324 @@ +/* + * FB driver for the Watterott LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "fb_watterott" +#define WIDTH 320 +#define HEIGHT 240 +#define FPS 5 +#define TXBUFLEN 1024 +#define DEFAULT_BRIGHTNESS 50 + +#define CMD_VERSION 0x01 +#define CMD_LCD_LED 0x10 +#define CMD_LCD_RESET 0x11 +#define CMD_LCD_ORIENTATION 0x20 +#define CMD_LCD_DRAWIMAGE 0x27 +#define COLOR_RGB323 8 +#define COLOR_RGB332 9 +#define COLOR_RGB233 10 +#define COLOR_RGB565 16 + + +static short mode = 565; +module_param(mode, short, 0); +MODULE_PARM_DESC(mode, "RGB color transfer mode: 332, 565 (default)"); + +static void write_reg8_bus8(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + u8 *buf = par->buf; + + va_start(args, len); + for (i = 0; i < len; i++) + *buf++ = (u8)va_arg(args, unsigned int); + va_end(args); + + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, + par->info->device, u8, par->buf, len, "%s: ", __func__); + + ret = par->fbtftops.write(par, par->buf, len); + if (ret < 0) { + dev_err(par->info->device, + "%s: write() failed and returned %d\n", __func__, ret); + return; + } +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + unsigned start_line, end_line; + u16 *vmem16 = (u16 *)(par->info->screen_base + offset); + u16 *pos = par->txbuf.buf + 1; + u16 *buf16 = par->txbuf.buf + 10; + int i, j; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + start_line = offset / par->info->fix.line_length; + end_line = start_line + (len / par->info->fix.line_length) - 1; + + /* Set command header. pos: x, y, w, h */ + ((u8 *)par->txbuf.buf)[0] = CMD_LCD_DRAWIMAGE; + pos[0] = 0; + pos[2] = cpu_to_be16(par->info->var.xres); + pos[3] = cpu_to_be16(1); + ((u8 *)par->txbuf.buf)[9] = COLOR_RGB565; + + for (i = start_line; i <= end_line; i++) { + pos[1] = cpu_to_be16(i); + for (j = 0; j < par->info->var.xres; j++) + buf16[j] = cpu_to_be16(*vmem16++); + ret = par->fbtftops.write(par, + par->txbuf.buf, 10 + par->info->fix.line_length); + if (ret < 0) + return ret; + udelay(300); + } + + return 0; +} + +#define RGB565toRGB323(c) (((c&0xE000)>>8) | ((c&0600)>>6) | ((c&0x001C)>>2)) +#define RGB565toRGB332(c) (((c&0xE000)>>8) | ((c&0700)>>6) | ((c&0x0018)>>3)) +#define RGB565toRGB233(c) (((c&0xC000)>>8) | ((c&0700)>>5) | ((c&0x001C)>>2)) + +static int write_vmem_8bit(struct fbtft_par *par, size_t offset, size_t len) +{ + unsigned start_line, end_line; + u16 *vmem16 = (u16 *)(par->info->screen_base + offset); + u16 *pos = par->txbuf.buf + 1; + u8 *buf8 = par->txbuf.buf + 10; + int i, j; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + start_line = offset / par->info->fix.line_length; + end_line = start_line + (len / par->info->fix.line_length) - 1; + + /* Set command header. pos: x, y, w, h */ + ((u8 *)par->txbuf.buf)[0] = CMD_LCD_DRAWIMAGE; + pos[0] = 0; + pos[2] = cpu_to_be16(par->info->var.xres); + pos[3] = cpu_to_be16(1); + ((u8 *)par->txbuf.buf)[9] = COLOR_RGB332; + + for (i = start_line; i <= end_line; i++) { + pos[1] = cpu_to_be16(i); + for (j = 0; j < par->info->var.xres; j++) { + buf8[j] = RGB565toRGB332(*vmem16); + vmem16++; + } + ret = par->fbtftops.write(par, + par->txbuf.buf, 10 + par->info->var.xres); + if (ret < 0) + return ret; + udelay(700); + } + + return 0; +} + +static unsigned firmware_version(struct fbtft_par *par) +{ + u8 rxbuf[4] = {0, }; + + write_reg(par, CMD_VERSION); + par->fbtftops.read(par, rxbuf, 4); + if (rxbuf[1] != '.') + return 0; + + return (rxbuf[0] - '0') << 8 | (rxbuf[2] - '0') << 4 | (rxbuf[3] - '0'); +} + +static int init_display(struct fbtft_par *par) +{ + int ret; + unsigned version; + u8 save_mode; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* enable SPI interface by having CS and MOSI low during reset */ + save_mode = par->spi->mode; + par->spi->mode |= SPI_CS_HIGH; + ret = par->spi->master->setup(par->spi); /* set CS inactive low */ + if (ret) { + dev_err(par->info->device, "Could not set SPI_CS_HIGH\n"); + return ret; + } + write_reg(par, 0x00); /* make sure mode is set */ + + mdelay(50); + par->fbtftops.reset(par); + mdelay(1000); + par->spi->mode = save_mode; + ret = par->spi->master->setup(par->spi); + if (ret) { + dev_err(par->info->device, "Could not restore SPI mode\n"); + return ret; + } + write_reg(par, 0x00); + + version = firmware_version(par); + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "Firmware version: %x.%02x\n", + version >> 8, version & 0xFF); + + if (mode == 332) + par->fbtftops.write_vmem = write_vmem_8bit; + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + /* not used on this controller */ +} + +static int set_var(struct fbtft_par *par) +{ + u8 rotate; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* this controller rotates clock wise */ + switch (par->info->var.rotate) { + case 90: + rotate = 27; + break; + case 180: + rotate = 18; + break; + case 270: + rotate = 9; + break; + default: + rotate = 0; + } + write_reg(par, CMD_LCD_ORIENTATION, rotate); + + return 0; +} + +static int verify_gpios(struct fbtft_par *par) +{ + if (par->gpio.reset < 0) { + dev_err(par->info->device, "Missing 'reset' gpio. Aborting.\n"); + return -EINVAL; + } + return 0; +} + +#ifdef CONFIG_FB_BACKLIGHT +static int backlight_chip_update_status(struct backlight_device *bd) +{ + struct fbtft_par *par = bl_get_data(bd); + int brightness = bd->props.brightness; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, + "%s: brightness=%d, power=%d, fb_blank=%d\n", + __func__, bd->props.brightness, bd->props.power, + bd->props.fb_blank); + + if (bd->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bd->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + write_reg(par, CMD_LCD_LED, brightness); + + return 0; +} + +static void register_chip_backlight(struct fbtft_par *par) +{ + struct backlight_device *bd; + struct backlight_properties bl_props = { 0, }; + struct backlight_ops *bl_ops; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__); + + bl_ops = devm_kzalloc(par->info->device, sizeof(struct backlight_ops), + GFP_KERNEL); + if (!bl_ops) { + dev_err(par->info->device, + "%s: could not allocate memory for backlight operations.\n", + __func__); + return; + } + + bl_ops->update_status = backlight_chip_update_status; + bl_props.type = BACKLIGHT_RAW; + bl_props.power = FB_BLANK_POWERDOWN; + bl_props.max_brightness = 100; + bl_props.brightness = DEFAULT_BRIGHTNESS; + + bd = backlight_device_register(dev_driver_string(par->info->device), + par->info->device, par, bl_ops, &bl_props); + if (IS_ERR(bd)) { + dev_err(par->info->device, + "cannot register backlight device (%ld)\n", + PTR_ERR(bd)); + return; + } + par->info->bl_dev = bd; + + if (!par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight = fbtft_unregister_backlight; +} +#else +#define register_chip_backlight NULL +#endif + + +static struct fbtft_display display = { + .regwidth = 8, + .buswidth = 8, + .width = WIDTH, + .height = HEIGHT, + .fps = FPS, + .txbuflen = TXBUFLEN, + .fbtftops = { + .write_register = write_reg8_bus8, + .write_vmem = write_vmem, + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .verify_gpios = verify_gpios, + .register_backlight = register_chip_backlight, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "watterott,openlcd", &display); + +MODULE_ALIAS("spi:" DRVNAME); + +MODULE_DESCRIPTION("FB driver for the Watterott LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c new file mode 100644 index 00000000000..b3cddb0b3d6 --- /dev/null +++ b/drivers/staging/fbtft/fbtft-bus.c @@ -0,0 +1,256 @@ +#include <linux/export.h> +#include <linux/errno.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include "fbtft.h" + + + + +/***************************************************************************** + * + * void (*write_reg)(struct fbtft_par *par, int len, ...); + * + *****************************************************************************/ + +#define define_fbtft_write_reg(func, type, modifier) \ +void func(struct fbtft_par *par, int len, ...) \ +{ \ + va_list args; \ + int i, ret; \ + int offset = 0; \ + type *buf = (type *)par->buf; \ + \ + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { \ + va_start(args, len); \ + for (i = 0; i < len; i++) { \ + buf[i] = (type)va_arg(args, unsigned int); \ + } \ + va_end(args); \ + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device, type, buf, len, "%s: ", __func__); \ + } \ + \ + va_start(args, len); \ + \ + if (par->startbyte) { \ + *(u8 *)par->buf = par->startbyte; \ + buf = (type *)(par->buf + 1); \ + offset = 1; \ + } \ + \ + *buf = modifier((type)va_arg(args, unsigned int)); \ + if (par->gpio.dc != -1) \ + gpio_set_value(par->gpio.dc, 0); \ + ret = par->fbtftops.write(par, par->buf, sizeof(type)+offset); \ + if (ret < 0) { \ + va_end(args); \ + dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); \ + return; \ + } \ + len--; \ + \ + if (par->startbyte) \ + *(u8 *)par->buf = par->startbyte | 0x2; \ + \ + if (len) { \ + i = len; \ + while (i--) { \ + *buf++ = modifier((type)va_arg(args, unsigned int)); \ + } \ + if (par->gpio.dc != -1) \ + gpio_set_value(par->gpio.dc, 1); \ + ret = par->fbtftops.write(par, par->buf, len * (sizeof(type)+offset)); \ + if (ret < 0) { \ + va_end(args); \ + dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); \ + return; \ + } \ + } \ + va_end(args); \ +} \ +EXPORT_SYMBOL(func); + +define_fbtft_write_reg(fbtft_write_reg8_bus8, u8, ) +define_fbtft_write_reg(fbtft_write_reg16_bus8, u16, cpu_to_be16) +define_fbtft_write_reg(fbtft_write_reg16_bus16, u16, ) + +void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + int pad = 0; + u16 *buf = (u16 *)par->buf; + + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { + va_start(args, len); + for (i = 0; i < len; i++) + *(((u8 *)buf) + i) = (u8)va_arg(args, unsigned int); + va_end(args); + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, + par->info->device, u8, buf, len, "%s: ", __func__); + } + if (len <= 0) + return; + + if (par->spi && (par->spi->bits_per_word == 8)) { + /* we're emulating 9-bit, pad start of buffer with no-ops + (assuming here that zero is a no-op) */ + pad = (len % 4) ? 4 - (len % 4) : 0; + for (i = 0; i < pad; i++) + *buf++ = 0x000; + } + + va_start(args, len); + *buf++ = (u8)va_arg(args, unsigned int); + i = len - 1; + while (i--) { + *buf = (u8)va_arg(args, unsigned int); + *buf++ |= 0x100; /* dc=1 */ + } + va_end(args); + ret = par->fbtftops.write(par, par->buf, (len + pad) * sizeof(u16)); + if (ret < 0) { + dev_err(par->info->device, + "%s: write() failed and returned %d\n", __func__, ret); + return; + } +} +EXPORT_SYMBOL(fbtft_write_reg8_bus9); + + + + +/***************************************************************************** + * + * int (*write_vmem)(struct fbtft_par *par); + * + *****************************************************************************/ + +/* 16 bit pixel over 8-bit databus */ +int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16; + u16 *txbuf16 = (u16 *)par->txbuf.buf; + size_t remain; + size_t to_copy; + size_t tx_array_size; + int i; + int ret = 0; + size_t startbyte_size = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", + __func__, offset, len); + + remain = len / 2; + vmem16 = (u16 *)(par->info->screen_base + offset); + + if (par->gpio.dc != -1) + gpio_set_value(par->gpio.dc, 1); + + /* non buffered write */ + if (!par->txbuf.buf) + return par->fbtftops.write(par, vmem16, len); + + /* buffered write */ + tx_array_size = par->txbuf.len / 2; + + if (par->startbyte) { + txbuf16 = (u16 *)(par->txbuf.buf + 1); + tx_array_size -= 2; + *(u8 *)(par->txbuf.buf) = par->startbyte | 0x2; + startbyte_size = 1; + } + + while (remain) { + to_copy = remain > tx_array_size ? tx_array_size : remain; + dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", + to_copy, remain - to_copy); + + for (i = 0; i < to_copy; i++) + txbuf16[i] = cpu_to_be16(vmem16[i]); + + vmem16 = vmem16 + to_copy; + ret = par->fbtftops.write(par, par->txbuf.buf, + startbyte_size + to_copy * 2); + if (ret < 0) + return ret; + remain -= to_copy; + } + + return ret; +} +EXPORT_SYMBOL(fbtft_write_vmem16_bus8); + +/* 16 bit pixel over 9-bit SPI bus: dc + high byte, dc + low byte */ +int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len) +{ + u8 *vmem8; + u16 *txbuf16 = par->txbuf.buf; + size_t remain; + size_t to_copy; + size_t tx_array_size; + int i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", + __func__, offset, len); + + if (!par->txbuf.buf) { + dev_err(par->info->device, "%s: txbuf.buf is NULL\n", __func__); + return -1; + } + + remain = len; + vmem8 = par->info->screen_base + offset; + + tx_array_size = par->txbuf.len / 2; + + while (remain) { + to_copy = remain > tx_array_size ? tx_array_size : remain; + dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", + to_copy, remain - to_copy); + +#ifdef __LITTLE_ENDIAN + for (i = 0; i < to_copy; i += 2) { + txbuf16[i] = 0x0100 | vmem8[i+1]; + txbuf16[i+1] = 0x0100 | vmem8[i]; + } +#else + for (i = 0; i < to_copy; i++) + txbuf16[i] = 0x0100 | vmem8[i]; +#endif + vmem8 = vmem8 + to_copy; + ret = par->fbtftops.write(par, par->txbuf.buf, to_copy*2); + if (ret < 0) + return ret; + remain -= to_copy; + } + + return ret; +} +EXPORT_SYMBOL(fbtft_write_vmem16_bus9); + +int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len) +{ + dev_err(par->info->device, "%s: function not implemented\n", __func__); + return -1; +} +EXPORT_SYMBOL(fbtft_write_vmem8_bus8); + +/* 16 bit pixel over 16-bit databus */ +int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", + __func__, offset, len); + + vmem16 = (u16 *)(par->info->screen_base + offset); + + if (par->gpio.dc != -1) + gpio_set_value(par->gpio.dc, 1); + + /* no need for buffered write with 16-bit bus */ + return par->fbtftops.write(par, vmem16, len); +} +EXPORT_SYMBOL(fbtft_write_vmem16_bus16); diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c new file mode 100644 index 00000000000..37dcf7eb191 --- /dev/null +++ b/drivers/staging/fbtft/fbtft-core.c @@ -0,0 +1,1521 @@ +/* + * Copyright (C) 2013 Noralf Tronnes + * + * This driver is inspired by: + * st7735fb.c, Copyright (C) 2011, Matt Porter + * broadsheetfb.c, Copyright (C) 2008, Jaya Kumar + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> +#include <linux/uaccess.h> +#include <linux/backlight.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/dma-mapping.h> +#include <linux/of.h> +#include <linux/of_gpio.h> + +#include "fbtft.h" + +extern void fbtft_sysfs_init(struct fbtft_par *par); +extern void fbtft_sysfs_exit(struct fbtft_par *par); +extern void fbtft_expand_debug_value(unsigned long *debug); +extern int fbtft_gamma_parse_str(struct fbtft_par *par, unsigned long *curves, + const char *str, int size); + +static unsigned long debug; +module_param(debug, ulong , 0); +MODULE_PARM_DESC(debug, "override device debug level"); + +static bool dma = true; +module_param(dma, bool, 0); +MODULE_PARM_DESC(dma, "Use DMA buffer"); + + +void fbtft_dbg_hex(const struct device *dev, int groupsize, + void *buf, size_t len, const char *fmt, ...) +{ + va_list args; + static char textbuf[512]; + char *text = textbuf; + size_t text_len; + + va_start(args, fmt); + text_len = vscnprintf(text, sizeof(textbuf), fmt, args); + va_end(args); + + hex_dump_to_buffer(buf, len, 32, groupsize, text + text_len, + 512 - text_len, false); + + if (len > 32) + dev_info(dev, "%s ...\n", text); + else + dev_info(dev, "%s\n", text); +} +EXPORT_SYMBOL(fbtft_dbg_hex); + +static unsigned long fbtft_request_gpios_match(struct fbtft_par *par, + const struct fbtft_gpio *gpio) +{ + int ret; + long val; + + fbtft_par_dbg(DEBUG_REQUEST_GPIOS_MATCH, par, "%s('%s')\n", + __func__, gpio->name); + + if (strcasecmp(gpio->name, "reset") == 0) { + par->gpio.reset = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "dc") == 0) { + par->gpio.dc = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } else if (strcasecmp(gpio->name, "cs") == 0) { + par->gpio.cs = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "wr") == 0) { + par->gpio.wr = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "rd") == 0) { + par->gpio.rd = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "latch") == 0) { + par->gpio.latch = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } else if (gpio->name[0] == 'd' && gpio->name[1] == 'b') { + ret = kstrtol(&gpio->name[2], 10, &val); + if (ret == 0 && val < 16) { + par->gpio.db[val] = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } + } else if (strcasecmp(gpio->name, "led") == 0) { + par->gpio.led[0] = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } else if (strcasecmp(gpio->name, "led_") == 0) { + par->gpio.led[0] = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } + + return FBTFT_GPIO_NO_MATCH; +} + +static int fbtft_request_gpios(struct fbtft_par *par) +{ + struct fbtft_platform_data *pdata = par->pdata; + const struct fbtft_gpio *gpio; + unsigned long flags; + int ret; + + if (pdata && pdata->gpios) { + gpio = pdata->gpios; + while (gpio->name[0]) { + flags = FBTFT_GPIO_NO_MATCH; + /* if driver provides match function, try it first, + if no match use our own */ + if (par->fbtftops.request_gpios_match) + flags = par->fbtftops.request_gpios_match(par, gpio); + if (flags == FBTFT_GPIO_NO_MATCH) + flags = fbtft_request_gpios_match(par, gpio); + if (flags != FBTFT_GPIO_NO_MATCH) { + ret = devm_gpio_request_one(par->info->device, + gpio->gpio, flags, + par->info->device->driver->name); + if (ret < 0) { + dev_err(par->info->device, + "%s: gpio_request_one('%s'=%d) failed with %d\n", + __func__, gpio->name, + gpio->gpio, ret); + return ret; + } + fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, + "%s: '%s' = GPIO%d\n", + __func__, gpio->name, gpio->gpio); + } + gpio++; + } + } + + return 0; +} + +#ifdef CONFIG_OF +static int fbtft_request_one_gpio(struct fbtft_par *par, + const char *name, int index, int *gpiop) +{ + struct device *dev = par->info->device; + struct device_node *node = dev->of_node; + int gpio, flags, ret = 0; + enum of_gpio_flags of_flags; + + if (of_find_property(node, name, NULL)) { + gpio = of_get_named_gpio_flags(node, name, index, &of_flags); + if (gpio == -ENOENT) + return 0; + if (gpio == -EPROBE_DEFER) + return gpio; + if (gpio < 0) { + dev_err(dev, + "failed to get '%s' from DT\n", name); + return gpio; + } + + /* active low translates to initially low */ + flags = (of_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW : + GPIOF_OUT_INIT_HIGH; + ret = devm_gpio_request_one(dev, gpio, flags, + dev->driver->name); + if (ret) { + dev_err(dev, + "gpio_request_one('%s'=%d) failed with %d\n", + name, gpio, ret); + return ret; + } + if (gpiop) + *gpiop = gpio; + fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' = GPIO%d\n", + __func__, name, gpio); + } + + return ret; +} + +static int fbtft_request_gpios_dt(struct fbtft_par *par) +{ + int i; + int ret; + + if (!par->info->device->of_node) + return -EINVAL; + + ret = fbtft_request_one_gpio(par, "reset-gpios", 0, &par->gpio.reset); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "dc-gpios", 0, &par->gpio.dc); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "rd-gpios", 0, &par->gpio.rd); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "wr-gpios", 0, &par->gpio.wr); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "cs-gpios", 0, &par->gpio.cs); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "latch-gpios", 0, &par->gpio.latch); + if (ret) + return ret; + for (i = 0; i < 16; i++) { + ret = fbtft_request_one_gpio(par, "db-gpios", i, + &par->gpio.db[i]); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "led-gpios", i, + &par->gpio.led[i]); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "aux-gpios", i, + &par->gpio.aux[i]); + if (ret) + return ret; + } + + return 0; +} +#endif + +#ifdef CONFIG_FB_BACKLIGHT +static int fbtft_backlight_update_status(struct backlight_device *bd) +{ + struct fbtft_par *par = bl_get_data(bd); + bool polarity = !!(bd->props.state & BL_CORE_DRIVER1); + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, + "%s: polarity=%d, power=%d, fb_blank=%d\n", + __func__, polarity, bd->props.power, bd->props.fb_blank); + + if ((bd->props.power == FB_BLANK_UNBLANK) && (bd->props.fb_blank == FB_BLANK_UNBLANK)) + gpio_set_value(par->gpio.led[0], polarity); + else + gpio_set_value(par->gpio.led[0], !polarity); + + return 0; +} + +static int fbtft_backlight_get_brightness(struct backlight_device *bd) +{ + return bd->props.brightness; +} + +void fbtft_unregister_backlight(struct fbtft_par *par) +{ + const struct backlight_ops *bl_ops; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__); + + if (par->info->bl_dev) { + par->info->bl_dev->props.power = FB_BLANK_POWERDOWN; + backlight_update_status(par->info->bl_dev); + bl_ops = par->info->bl_dev->ops; + backlight_device_unregister(par->info->bl_dev); + par->info->bl_dev = NULL; + } +} + +void fbtft_register_backlight(struct fbtft_par *par) +{ + struct backlight_device *bd; + struct backlight_properties bl_props = { 0, }; + struct backlight_ops *bl_ops; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__); + + if (par->gpio.led[0] == -1) { + fbtft_par_dbg(DEBUG_BACKLIGHT, par, + "%s(): led pin not set, exiting.\n", __func__); + return; + } + + bl_ops = devm_kzalloc(par->info->device, sizeof(struct backlight_ops), + GFP_KERNEL); + if (!bl_ops) { + dev_err(par->info->device, + "%s: could not allocate memeory for backlight operations.\n", + __func__); + return; + } + + bl_ops->get_brightness = fbtft_backlight_get_brightness; + bl_ops->update_status = fbtft_backlight_update_status; + bl_props.type = BACKLIGHT_RAW; + /* Assume backlight is off, get polarity from current state of pin */ + bl_props.power = FB_BLANK_POWERDOWN; + if (!gpio_get_value(par->gpio.led[0])) + bl_props.state |= BL_CORE_DRIVER1; + + bd = backlight_device_register(dev_driver_string(par->info->device), + par->info->device, par, bl_ops, &bl_props); + if (IS_ERR(bd)) { + dev_err(par->info->device, + "cannot register backlight device (%ld)\n", + PTR_ERR(bd)); + return; + } + par->info->bl_dev = bd; + + if (!par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight = fbtft_unregister_backlight; +} +#else +void fbtft_register_backlight(struct fbtft_par *par) { }; +void fbtft_unregister_backlight(struct fbtft_par *par) { }; +#endif +EXPORT_SYMBOL(fbtft_register_backlight); +EXPORT_SYMBOL(fbtft_unregister_backlight); + +static void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, + int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address set */ + write_reg(par, 0x2A, + (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF); + + /* Row adress set */ + write_reg(par, 0x2B, + (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + + +static void fbtft_reset(struct fbtft_par *par) +{ + if (par->gpio.reset == -1) + return; + fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__); + gpio_set_value(par->gpio.reset, 0); + udelay(20); + gpio_set_value(par->gpio.reset, 1); + mdelay(120); +} + + +static void fbtft_update_display(struct fbtft_par *par, unsigned start_line, + unsigned end_line) +{ + size_t offset, len; + struct timespec ts_start, ts_end, ts_fps, ts_duration; + long fps_ms, fps_us, duration_ms, duration_us; + long fps, throughput; + bool timeit = false; + int ret = 0; + + if (unlikely(par->debug & (DEBUG_TIME_FIRST_UPDATE | DEBUG_TIME_EACH_UPDATE))) { + if ((par->debug & DEBUG_TIME_EACH_UPDATE) || \ + ((par->debug & DEBUG_TIME_FIRST_UPDATE) && !par->first_update_done)) { + getnstimeofday(&ts_start); + timeit = true; + } + } + + /* Sanity checks */ + if (start_line > end_line) { + dev_warn(par->info->device, + "%s: start_line=%u is larger than end_line=%u. Shouldn't happen, will do full display update\n", + __func__, start_line, end_line); + start_line = 0; + end_line = par->info->var.yres - 1; + } + if (start_line > par->info->var.yres - 1 || end_line > par->info->var.yres - 1) { + dev_warn(par->info->device, + "%s: start_line=%u or end_line=%u is larger than max=%d. Shouldn't happen, will do full display update\n", + __func__, start_line, end_line, par->info->var.yres - 1); + start_line = 0; + end_line = par->info->var.yres - 1; + } + + fbtft_par_dbg(DEBUG_UPDATE_DISPLAY, par, "%s(start_line=%u, end_line=%u)\n", + __func__, start_line, end_line); + + if (par->fbtftops.set_addr_win) + par->fbtftops.set_addr_win(par, 0, start_line, + par->info->var.xres-1, end_line); + + offset = start_line * par->info->fix.line_length; + len = (end_line - start_line + 1) * par->info->fix.line_length; + ret = par->fbtftops.write_vmem(par, offset, len); + if (ret < 0) + dev_err(par->info->device, + "%s: write_vmem failed to update display buffer\n", + __func__); + + if (unlikely(timeit)) { + getnstimeofday(&ts_end); + if (par->update_time.tv_nsec == 0 && par->update_time.tv_sec == 0) { + par->update_time.tv_sec = ts_start.tv_sec; + par->update_time.tv_nsec = ts_start.tv_nsec; + } + ts_fps = timespec_sub(ts_start, par->update_time); + par->update_time.tv_sec = ts_start.tv_sec; + par->update_time.tv_nsec = ts_start.tv_nsec; + fps_ms = (ts_fps.tv_sec * 1000) + ((ts_fps.tv_nsec / 1000000) % 1000); + fps_us = (ts_fps.tv_nsec / 1000) % 1000; + fps = fps_ms * 1000 + fps_us; + fps = fps ? 1000000 / fps : 0; + + ts_duration = timespec_sub(ts_end, ts_start); + duration_ms = (ts_duration.tv_sec * 1000) + ((ts_duration.tv_nsec / 1000000) % 1000); + duration_us = (ts_duration.tv_nsec / 1000) % 1000; + throughput = duration_ms * 1000 + duration_us; + throughput = throughput ? (len * 1000) / throughput : 0; + throughput = throughput * 1000 / 1024; + + dev_info(par->info->device, + "Display update: %ld kB/s (%ld.%.3ld ms), fps=%ld (%ld.%.3ld ms)\n", + throughput, duration_ms, duration_us, + fps, fps_ms, fps_us); + par->first_update_done = true; + } +} + + +static void fbtft_mkdirty(struct fb_info *info, int y, int height) +{ + struct fbtft_par *par = info->par; + struct fb_deferred_io *fbdefio = info->fbdefio; + + /* special case, needed ? */ + if (y == -1) { + y = 0; + height = info->var.yres - 1; + } + + /* Mark display lines/area as dirty */ + spin_lock(&par->dirty_lock); + if (y < par->dirty_lines_start) + par->dirty_lines_start = y; + if (y + height - 1 > par->dirty_lines_end) + par->dirty_lines_end = y + height - 1; + spin_unlock(&par->dirty_lock); + + /* Schedule deferred_io to update display (no-op if already on queue)*/ + schedule_delayed_work(&info->deferred_work, fbdefio->delay); +} + +static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist) +{ + struct fbtft_par *par = info->par; + unsigned dirty_lines_start, dirty_lines_end; + struct page *page; + unsigned long index; + unsigned y_low = 0, y_high = 0; + int count = 0; + + spin_lock(&par->dirty_lock); + dirty_lines_start = par->dirty_lines_start; + dirty_lines_end = par->dirty_lines_end; + /* set display line markers as clean */ + par->dirty_lines_start = par->info->var.yres - 1; + par->dirty_lines_end = 0; + spin_unlock(&par->dirty_lock); + + /* Mark display lines as dirty */ + list_for_each_entry(page, pagelist, lru) { + count++; + index = page->index << PAGE_SHIFT; + y_low = index / info->fix.line_length; + y_high = (index + PAGE_SIZE - 1) / info->fix.line_length; + fbtft_dev_dbg(DEBUG_DEFERRED_IO, par, info->device, + "page->index=%lu y_low=%d y_high=%d\n", + page->index, y_low, y_high); + if (y_high > info->var.yres - 1) + y_high = info->var.yres - 1; + if (y_low < dirty_lines_start) + dirty_lines_start = y_low; + if (y_high > dirty_lines_end) + dirty_lines_end = y_high; + } + + par->fbtftops.update_display(info->par, + dirty_lines_start, dirty_lines_end); +} + + +static void fbtft_fb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + struct fbtft_par *par = info->par; + + fbtft_dev_dbg(DEBUG_FB_FILLRECT, par, info->dev, + "%s: dx=%d, dy=%d, width=%d, height=%d\n", + __func__, rect->dx, rect->dy, rect->width, rect->height); + sys_fillrect(info, rect); + + par->fbtftops.mkdirty(info, rect->dy, rect->height); +} + +static void fbtft_fb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + struct fbtft_par *par = info->par; + + fbtft_dev_dbg(DEBUG_FB_COPYAREA, par, info->dev, + "%s: dx=%d, dy=%d, width=%d, height=%d\n", + __func__, area->dx, area->dy, area->width, area->height); + sys_copyarea(info, area); + + par->fbtftops.mkdirty(info, area->dy, area->height); +} + +static void fbtft_fb_imageblit(struct fb_info *info, + const struct fb_image *image) +{ + struct fbtft_par *par = info->par; + + fbtft_dev_dbg(DEBUG_FB_IMAGEBLIT, par, info->dev, + "%s: dx=%d, dy=%d, width=%d, height=%d\n", + __func__, image->dx, image->dy, image->width, image->height); + sys_imageblit(info, image); + + par->fbtftops.mkdirty(info, image->dy, image->height); +} + +static ssize_t fbtft_fb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct fbtft_par *par = info->par; + ssize_t res; + + fbtft_dev_dbg(DEBUG_FB_WRITE, par, info->dev, + "%s: count=%zd, ppos=%llu\n", __func__, count, *ppos); + res = fb_sys_write(info, buf, count, ppos); + + /* TODO: only mark changed area + update all for now */ + par->fbtftops.mkdirty(info, -1, 0); + + return res; +} + +/* from pxafb.c */ +static unsigned int chan_to_field(unsigned chan, struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int fbtft_fb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + struct fbtft_par *par = info->par; + unsigned val; + int ret = 1; + + fbtft_dev_dbg(DEBUG_FB_SETCOLREG, par, info->dev, + "%s(regno=%u, red=0x%X, green=0x%X, blue=0x%X, trans=0x%X)\n", + __func__, regno, red, green, blue, transp); + + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + if (regno < 16) { + u32 *pal = info->pseudo_palette; + + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue, &info->var.blue); + + pal[regno] = val; + ret = 0; + } + break; + + } + return ret; +} + +static int fbtft_fb_blank(int blank, struct fb_info *info) +{ + struct fbtft_par *par = info->par; + int ret = -EINVAL; + + fbtft_dev_dbg(DEBUG_FB_BLANK, par, info->dev, "%s(blank=%d)\n", + __func__, blank); + + if (!par->fbtftops.blank) + return ret; + + switch (blank) { + case FB_BLANK_POWERDOWN: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_NORMAL: + ret = par->fbtftops.blank(par, true); + break; + case FB_BLANK_UNBLANK: + ret = par->fbtftops.blank(par, false); + break; + } + return ret; +} + +static void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src) +{ + if (src->write) + dst->write = src->write; + if (src->read) + dst->read = src->read; + if (src->write_vmem) + dst->write_vmem = src->write_vmem; + if (src->write_register) + dst->write_register = src->write_register; + if (src->set_addr_win) + dst->set_addr_win = src->set_addr_win; + if (src->reset) + dst->reset = src->reset; + if (src->mkdirty) + dst->mkdirty = src->mkdirty; + if (src->update_display) + dst->update_display = src->update_display; + if (src->init_display) + dst->init_display = src->init_display; + if (src->blank) + dst->blank = src->blank; + if (src->request_gpios_match) + dst->request_gpios_match = src->request_gpios_match; + if (src->request_gpios) + dst->request_gpios = src->request_gpios; + if (src->verify_gpios) + dst->verify_gpios = src->verify_gpios; + if (src->register_backlight) + dst->register_backlight = src->register_backlight; + if (src->unregister_backlight) + dst->unregister_backlight = src->unregister_backlight; + if (src->set_var) + dst->set_var = src->set_var; + if (src->set_gamma) + dst->set_gamma = src->set_gamma; +} + +/** + * fbtft_framebuffer_alloc - creates a new frame buffer info structure + * + * @display: pointer to structure describing the display + * @dev: pointer to the device for this fb, this can be NULL + * + * Creates a new frame buffer info structure. + * + * Also creates and populates the following structures: + * info->fbops + * info->fbdefio + * info->pseudo_palette + * par->fbtftops + * par->txbuf + * + * Returns the new structure, or NULL if an error occurred. + * + */ +struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, + struct device *dev) +{ + struct fb_info *info; + struct fbtft_par *par; + struct fb_ops *fbops = NULL; + struct fb_deferred_io *fbdefio = NULL; + struct fbtft_platform_data *pdata = dev->platform_data; + u8 *vmem = NULL; + void *txbuf = NULL; + void *buf = NULL; + unsigned width; + unsigned height; + int txbuflen = display->txbuflen; + unsigned bpp = display->bpp; + unsigned fps = display->fps; + int vmem_size, i; + int *init_sequence = display->init_sequence; + char *gamma = display->gamma; + unsigned long *gamma_curves = NULL; + + /* sanity check */ + if (display->gamma_num * display->gamma_len > FBTFT_GAMMA_MAX_VALUES_TOTAL) { + dev_err(dev, + "%s: FBTFT_GAMMA_MAX_VALUES_TOTAL=%d is exceeded\n", + __func__, FBTFT_GAMMA_MAX_VALUES_TOTAL); + return NULL; + } + + /* defaults */ + if (!fps) + fps = 20; + if (!bpp) + bpp = 16; + + if (!pdata) { + dev_err(dev, "platform data is missing\n"); + return NULL; + } + + /* override driver values? */ + if (pdata->fps) + fps = pdata->fps; + if (pdata->txbuflen) + txbuflen = pdata->txbuflen; + if (pdata->display.init_sequence) + init_sequence = pdata->display.init_sequence; + if (pdata->gamma) + gamma = pdata->gamma; + if (pdata->display.debug) + display->debug = pdata->display.debug; + if (pdata->display.backlight) + display->backlight = pdata->display.backlight; + if (pdata->display.width) + display->width = pdata->display.width; + if (pdata->display.height) + display->height = pdata->display.height; + if (pdata->display.buswidth) + display->buswidth = pdata->display.buswidth; + if (pdata->display.regwidth) + display->regwidth = pdata->display.regwidth; + + display->debug |= debug; + fbtft_expand_debug_value(&display->debug); + + switch (pdata->rotate) { + case 90: + case 270: + width = display->height; + height = display->width; + break; + default: + width = display->width; + height = display->height; + } + + vmem_size = display->width * display->height * bpp / 8; + vmem = vzalloc(vmem_size); + if (!vmem) + goto alloc_fail; + + fbops = devm_kzalloc(dev, sizeof(struct fb_ops), GFP_KERNEL); + if (!fbops) + goto alloc_fail; + + fbdefio = devm_kzalloc(dev, sizeof(struct fb_deferred_io), GFP_KERNEL); + if (!fbdefio) + goto alloc_fail; + + buf = devm_kzalloc(dev, 128, GFP_KERNEL); + if (!buf) + goto alloc_fail; + + if (display->gamma_num && display->gamma_len) { + gamma_curves = devm_kzalloc(dev, display->gamma_num * display->gamma_len * sizeof(gamma_curves[0]), + GFP_KERNEL); + if (!gamma_curves) + goto alloc_fail; + } + + info = framebuffer_alloc(sizeof(struct fbtft_par), dev); + if (!info) + goto alloc_fail; + + info->screen_base = (u8 __force __iomem *)vmem; + info->fbops = fbops; + info->fbdefio = fbdefio; + + fbops->owner = dev->driver->owner; + fbops->fb_read = fb_sys_read; + fbops->fb_write = fbtft_fb_write; + fbops->fb_fillrect = fbtft_fb_fillrect; + fbops->fb_copyarea = fbtft_fb_copyarea; + fbops->fb_imageblit = fbtft_fb_imageblit; + fbops->fb_setcolreg = fbtft_fb_setcolreg; + fbops->fb_blank = fbtft_fb_blank; + + fbdefio->delay = HZ/fps; + fbdefio->deferred_io = fbtft_deferred_io; + fb_deferred_io_init(info); + + strncpy(info->fix.id, dev->driver->name, 16); + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.xpanstep = 0; + info->fix.ypanstep = 0; + info->fix.ywrapstep = 0; + info->fix.line_length = width*bpp/8; + info->fix.accel = FB_ACCEL_NONE; + info->fix.smem_len = vmem_size; + + info->var.rotate = pdata->rotate; + info->var.xres = width; + info->var.yres = height; + info->var.xres_virtual = info->var.xres; + info->var.yres_virtual = info->var.yres; + info->var.bits_per_pixel = bpp; + info->var.nonstd = 1; + + /* RGB565 */ + info->var.red.offset = 11; + info->var.red.length = 5; + info->var.green.offset = 5; + info->var.green.length = 6; + info->var.blue.offset = 0; + info->var.blue.length = 5; + info->var.transp.offset = 0; + info->var.transp.length = 0; + + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; + + par = info->par; + par->info = info; + par->pdata = dev->platform_data; + par->debug = display->debug; + par->buf = buf; + spin_lock_init(&par->dirty_lock); + par->bgr = pdata->bgr; + par->startbyte = pdata->startbyte; + par->init_sequence = init_sequence; + par->gamma.curves = gamma_curves; + par->gamma.num_curves = display->gamma_num; + par->gamma.num_values = display->gamma_len; + mutex_init(&par->gamma.lock); + info->pseudo_palette = par->pseudo_palette; + + if (par->gamma.curves && gamma) { + if (fbtft_gamma_parse_str(par, + par->gamma.curves, gamma, strlen(gamma))) + goto alloc_fail; + } + + /* Transmit buffer */ + if (txbuflen == -1) + txbuflen = vmem_size + 2; /* add in case startbyte is used */ + +#ifdef __LITTLE_ENDIAN + if ((!txbuflen) && (bpp > 8)) + txbuflen = PAGE_SIZE; /* need buffer for byteswapping */ +#endif + + if (txbuflen > 0) { + if (dma) { + dev->coherent_dma_mask = ~0; + txbuf = dmam_alloc_coherent(dev, txbuflen, &par->txbuf.dma, GFP_DMA); + } else { + txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL); + } + if (!txbuf) + goto alloc_fail; + par->txbuf.buf = txbuf; + par->txbuf.len = txbuflen; + } + + /* Initialize gpios to disabled */ + par->gpio.reset = -1; + par->gpio.dc = -1; + par->gpio.rd = -1; + par->gpio.wr = -1; + par->gpio.cs = -1; + par->gpio.latch = -1; + for (i = 0; i < 16; i++) { + par->gpio.db[i] = -1; + par->gpio.led[i] = -1; + par->gpio.aux[i] = -1; + } + + /* default fbtft operations */ + par->fbtftops.write = fbtft_write_spi; + par->fbtftops.read = fbtft_read_spi; + par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; + par->fbtftops.write_register = fbtft_write_reg8_bus8; + par->fbtftops.set_addr_win = fbtft_set_addr_win; + par->fbtftops.reset = fbtft_reset; + par->fbtftops.mkdirty = fbtft_mkdirty; + par->fbtftops.update_display = fbtft_update_display; + par->fbtftops.request_gpios = fbtft_request_gpios; + if (display->backlight) + par->fbtftops.register_backlight = fbtft_register_backlight; + + /* use driver provided functions */ + fbtft_merge_fbtftops(&par->fbtftops, &display->fbtftops); + + return info; + +alloc_fail: + vfree(vmem); + + return NULL; +} +EXPORT_SYMBOL(fbtft_framebuffer_alloc); + +/** + * fbtft_framebuffer_release - frees up all memory used by the framebuffer + * + * @info: frame buffer info structure + * + */ +void fbtft_framebuffer_release(struct fb_info *info) +{ + fb_deferred_io_cleanup(info); + vfree(info->screen_base); + framebuffer_release(info); +} +EXPORT_SYMBOL(fbtft_framebuffer_release); + +/** + * fbtft_register_framebuffer - registers a tft frame buffer device + * @fb_info: frame buffer info structure + * + * Sets SPI driverdata if needed + * Requests needed gpios. + * Initializes display + * Updates display. + * Registers a frame buffer device @fb_info. + * + * Returns negative errno on error, or zero for success. + * + */ +int fbtft_register_framebuffer(struct fb_info *fb_info) +{ + int ret; + char text1[50] = ""; + char text2[50] = ""; + struct fbtft_par *par = fb_info->par; + struct spi_device *spi = par->spi; + + /* sanity checks */ + if (!par->fbtftops.init_display) { + dev_err(fb_info->device, "missing fbtftops.init_display()\n"); + return -EINVAL; + } + + if (spi) + spi_set_drvdata(spi, fb_info); + if (par->pdev) + platform_set_drvdata(par->pdev, fb_info); + + ret = par->fbtftops.request_gpios(par); + if (ret < 0) + goto reg_fail; + + if (par->fbtftops.verify_gpios) { + ret = par->fbtftops.verify_gpios(par); + if (ret < 0) + goto reg_fail; + } + + ret = par->fbtftops.init_display(par); + if (ret < 0) + goto reg_fail; + if (par->fbtftops.set_var) { + ret = par->fbtftops.set_var(par); + if (ret < 0) + goto reg_fail; + } + + /* update the entire display */ + par->fbtftops.update_display(par, 0, par->info->var.yres - 1); + + if (par->fbtftops.set_gamma && par->gamma.curves) { + ret = par->fbtftops.set_gamma(par, par->gamma.curves); + if (ret) + goto reg_fail; + } + + if (par->fbtftops.register_backlight) + par->fbtftops.register_backlight(par); + + ret = register_framebuffer(fb_info); + if (ret < 0) + goto reg_fail; + + fbtft_sysfs_init(par); + + if (par->txbuf.buf) + sprintf(text1, ", %d KiB %sbuffer memory", + par->txbuf.len >> 10, par->txbuf.dma ? "DMA " : ""); + if (spi) + sprintf(text2, ", spi%d.%d at %d MHz", spi->master->bus_num, + spi->chip_select, spi->max_speed_hz/1000000); + dev_info(fb_info->dev, + "%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n", + fb_info->fix.id, fb_info->var.xres, fb_info->var.yres, + fb_info->fix.smem_len >> 10, text1, + HZ/fb_info->fbdefio->delay, text2); + +#ifdef CONFIG_FB_BACKLIGHT + /* Turn on backlight if available */ + if (fb_info->bl_dev) { + fb_info->bl_dev->props.power = FB_BLANK_UNBLANK; + fb_info->bl_dev->ops->update_status(fb_info->bl_dev); + } +#endif + + return 0; + +reg_fail: + if (par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight(par); + if (spi) + spi_set_drvdata(spi, NULL); + if (par->pdev) + platform_set_drvdata(par->pdev, NULL); + + return ret; +} +EXPORT_SYMBOL(fbtft_register_framebuffer); + +/** + * fbtft_unregister_framebuffer - releases a tft frame buffer device + * @fb_info: frame buffer info structure + * + * Frees SPI driverdata if needed + * Frees gpios. + * Unregisters frame buffer device. + * + */ +int fbtft_unregister_framebuffer(struct fb_info *fb_info) +{ + struct fbtft_par *par = fb_info->par; + struct spi_device *spi = par->spi; + int ret; + + if (spi) + spi_set_drvdata(spi, NULL); + if (par->pdev) + platform_set_drvdata(par->pdev, NULL); + if (par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight(par); + fbtft_sysfs_exit(par); + ret = unregister_framebuffer(fb_info); + return ret; +} +EXPORT_SYMBOL(fbtft_unregister_framebuffer); + +#ifdef CONFIG_OF +/** + * fbtft_init_display_dt() - Device Tree init_display() function + * @par: Driver data + * + * Return: 0 if successful, negative if error + */ +static int fbtft_init_display_dt(struct fbtft_par *par) +{ + struct device_node *node = par->info->device->of_node; + struct property *prop; + const __be32 *p; + u32 val; + int buf[64], i, j; + char msg[128]; + char str[16]; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (!node) + return -EINVAL; + + prop = of_find_property(node, "init", NULL); + p = of_prop_next_u32(prop, NULL, &val); + if (!p) + return -EINVAL; + while (p) { + if (val & FBTFT_OF_INIT_CMD) { + val &= 0xFFFF; + i = 0; + while (p && !(val & 0xFFFF0000)) { + if (i > 63) { + dev_err(par->info->device, + "%s: Maximum register values exceeded\n", + __func__); + return -EINVAL; + } + buf[i++] = val; + p = of_prop_next_u32(prop, p, &val); + } + /* make debug message */ + msg[0] = '\0'; + for (j = 0; j < i; j++) { + snprintf(str, 128, " %02X", buf[j]); + strcat(msg, str); + } + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "init: write_register:%s\n", msg); + + par->fbtftops.write_register(par, i, + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[10], buf[11], + buf[12], buf[13], buf[14], buf[15], + buf[16], buf[17], buf[18], buf[19], + buf[20], buf[21], buf[22], buf[23], + buf[24], buf[25], buf[26], buf[27], + buf[28], buf[29], buf[30], buf[31], + buf[32], buf[33], buf[34], buf[35], + buf[36], buf[37], buf[38], buf[39], + buf[40], buf[41], buf[42], buf[43], + buf[44], buf[45], buf[46], buf[47], + buf[48], buf[49], buf[50], buf[51], + buf[52], buf[53], buf[54], buf[55], + buf[56], buf[57], buf[58], buf[59], + buf[60], buf[61], buf[62], buf[63]); + } else if (val & FBTFT_OF_INIT_DELAY) { + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "init: msleep(%u)\n", val & 0xFFFF); + msleep(val & 0xFFFF); + p = of_prop_next_u32(prop, p, &val); + } else { + dev_err(par->info->device, "illegal init value 0x%X\n", + val); + return -EINVAL; + } + } + + return 0; +} +#endif + +/** + * fbtft_init_display() - Generic init_display() function + * @par: Driver data + * + * Uses par->init_sequence to do the initialization + * + * Return: 0 if successful, negative if error + */ +int fbtft_init_display(struct fbtft_par *par) +{ + int buf[64]; + char msg[128]; + char str[16]; + int i = 0; + int j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* sanity check */ + if (!par->init_sequence) { + dev_err(par->info->device, + "error: init_sequence is not set\n"); + return -EINVAL; + } + + /* make sure stop marker exists */ + for (i = 0; i < FBTFT_MAX_INIT_SEQUENCE; i++) + if (par->init_sequence[i] == -3) + break; + if (i == FBTFT_MAX_INIT_SEQUENCE) { + dev_err(par->info->device, + "missing stop marker at end of init sequence\n"); + return -EINVAL; + } + + par->fbtftops.reset(par); + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + i = 0; + while (i < FBTFT_MAX_INIT_SEQUENCE) { + if (par->init_sequence[i] == -3) { + /* done */ + return 0; + } + if (par->init_sequence[i] >= 0) { + dev_err(par->info->device, + "missing delimiter at position %d\n", i); + return -EINVAL; + } + if (par->init_sequence[i+1] < 0) { + dev_err(par->info->device, + "missing value after delimiter %d at position %d\n", + par->init_sequence[i], i); + return -EINVAL; + } + switch (par->init_sequence[i]) { + case -1: + i++; + /* make debug message */ + strcpy(msg, ""); + j = i + 1; + while (par->init_sequence[j] >= 0) { + sprintf(str, "0x%02X ", par->init_sequence[j]); + strcat(msg, str); + j++; + } + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "init: write(0x%02X) %s\n", + par->init_sequence[i], msg); + + /* Write */ + j = 0; + while (par->init_sequence[i] >= 0) { + if (j > 63) { + dev_err(par->info->device, + "%s: Maximum register values exceeded\n", + __func__); + return -EINVAL; + } + buf[j++] = par->init_sequence[i++]; + } + par->fbtftops.write_register(par, j, + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[10], buf[11], + buf[12], buf[13], buf[14], buf[15], + buf[16], buf[17], buf[18], buf[19], + buf[20], buf[21], buf[22], buf[23], + buf[24], buf[25], buf[26], buf[27], + buf[28], buf[29], buf[30], buf[31], + buf[32], buf[33], buf[34], buf[35], + buf[36], buf[37], buf[38], buf[39], + buf[40], buf[41], buf[42], buf[43], + buf[44], buf[45], buf[46], buf[47], + buf[48], buf[49], buf[50], buf[51], + buf[52], buf[53], buf[54], buf[55], + buf[56], buf[57], buf[58], buf[59], + buf[60], buf[61], buf[62], buf[63]); + break; + case -2: + i++; + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "init: mdelay(%d)\n", par->init_sequence[i]); + mdelay(par->init_sequence[i++]); + break; + default: + dev_err(par->info->device, + "unknown delimiter %d at position %d\n", + par->init_sequence[i], i); + return -EINVAL; + } + } + + dev_err(par->info->device, + "%s: something is wrong. Shouldn't get here.\n", __func__); + return -EINVAL; +} +EXPORT_SYMBOL(fbtft_init_display); + +/** + * fbtft_verify_gpios() - Generic verify_gpios() function + * @par: Driver data + * + * Uses @spi, @pdev and @buswidth to determine which GPIOs is needed + * + * Return: 0 if successful, negative if error + */ +static int fbtft_verify_gpios(struct fbtft_par *par) +{ + struct fbtft_platform_data *pdata; + int i; + + fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__); + + pdata = par->info->device->platform_data; + if (pdata->display.buswidth != 9 && par->startbyte == 0 && \ + par->gpio.dc < 0) { + dev_err(par->info->device, + "Missing info about 'dc' gpio. Aborting.\n"); + return -EINVAL; + } + + if (!par->pdev) + return 0; + + if (par->gpio.wr < 0) { + dev_err(par->info->device, "Missing 'wr' gpio. Aborting.\n"); + return -EINVAL; + } + for (i = 0; i < pdata->display.buswidth; i++) { + if (par->gpio.db[i] < 0) { + dev_err(par->info->device, + "Missing 'db%02d' gpio. Aborting.\n", i); + return -EINVAL; + } + } + + return 0; +} + +#ifdef CONFIG_OF +/* returns 0 if the property is not present */ +static u32 fbtft_of_value(struct device_node *node, const char *propname) +{ + int ret; + u32 val = 0; + + ret = of_property_read_u32(node, propname, &val); + if (ret == 0) + pr_info("%s: %s = %u\n", __func__, propname, val); + + return val; +} + +static struct fbtft_platform_data *fbtft_probe_dt(struct device *dev) +{ + struct device_node *node = dev->of_node; + struct fbtft_platform_data *pdata; + + if (!node) { + dev_err(dev, "Missing platform data or DT\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->display.width = fbtft_of_value(node, "width"); + pdata->display.height = fbtft_of_value(node, "height"); + pdata->display.regwidth = fbtft_of_value(node, "regwidth"); + pdata->display.buswidth = fbtft_of_value(node, "buswidth"); + pdata->display.backlight = fbtft_of_value(node, "backlight"); + pdata->display.bpp = fbtft_of_value(node, "bpp"); + pdata->display.debug = fbtft_of_value(node, "debug"); + pdata->rotate = fbtft_of_value(node, "rotate"); + pdata->bgr = of_property_read_bool(node, "bgr"); + pdata->fps = fbtft_of_value(node, "fps"); + pdata->txbuflen = fbtft_of_value(node, "txbuflen"); + pdata->startbyte = fbtft_of_value(node, "startbyte"); + of_property_read_string(node, "gamma", (const char **)&pdata->gamma); + + if (of_find_property(node, "led-gpios", NULL)) + pdata->display.backlight = 1; + if (of_find_property(node, "init", NULL)) + pdata->display.fbtftops.init_display = fbtft_init_display_dt; + pdata->display.fbtftops.request_gpios = fbtft_request_gpios_dt; + + return pdata; +} +#else +static struct fbtft_platform_data *fbtft_probe_dt(struct device *dev) +{ + dev_err(dev, "Missing platform data\n"); + return ERR_PTR(-EINVAL); +} +#endif + +/** + * fbtft_probe_common() - Generic device probe() helper function + * @display: Display properties + * @sdev: SPI device + * @pdev: Platform device + * + * Allocates, initializes and registers a framebuffer + * + * Either @sdev or @pdev should be NULL + * + * Return: 0 if successful, negative if error + */ +int fbtft_probe_common(struct fbtft_display *display, + struct spi_device *sdev, struct platform_device *pdev) +{ + struct device *dev; + struct fb_info *info; + struct fbtft_par *par; + struct fbtft_platform_data *pdata; + int ret; + + if (sdev) + dev = &sdev->dev; + else + dev = &pdev->dev; + + if (unlikely(display->debug & DEBUG_DRIVER_INIT_FUNCTIONS)) + dev_info(dev, "%s()\n", __func__); + + pdata = dev->platform_data; + if (!pdata) { + pdata = fbtft_probe_dt(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + dev->platform_data = pdata; + } + + info = fbtft_framebuffer_alloc(display, dev); + if (!info) + return -ENOMEM; + + par = info->par; + par->spi = sdev; + par->pdev = pdev; + + if (display->buswidth == 0) { + dev_err(dev, "buswidth is not set\n"); + return -EINVAL; + } + + /* write register functions */ + if (display->regwidth == 8 && display->buswidth == 8) { + par->fbtftops.write_register = fbtft_write_reg8_bus8; + } else + if (display->regwidth == 8 && display->buswidth == 9 && par->spi) { + par->fbtftops.write_register = fbtft_write_reg8_bus9; + } else if (display->regwidth == 16 && display->buswidth == 8) { + par->fbtftops.write_register = fbtft_write_reg16_bus8; + } else if (display->regwidth == 16 && display->buswidth == 16) { + par->fbtftops.write_register = fbtft_write_reg16_bus16; + } else { + dev_warn(dev, + "no default functions for regwidth=%d and buswidth=%d\n", + display->regwidth, display->buswidth); + } + + /* write_vmem() functions */ + if (display->buswidth == 8) + par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; + else if (display->buswidth == 9) + par->fbtftops.write_vmem = fbtft_write_vmem16_bus9; + else if (display->buswidth == 16) + par->fbtftops.write_vmem = fbtft_write_vmem16_bus16; + + /* GPIO write() functions */ + if (par->pdev) { + if (display->buswidth == 8) + par->fbtftops.write = fbtft_write_gpio8_wr; + else if (display->buswidth == 16) + par->fbtftops.write = fbtft_write_gpio16_wr; + } + + /* 9-bit SPI setup */ + if (par->spi && display->buswidth == 9) { + par->spi->bits_per_word = 9; + ret = par->spi->master->setup(par->spi); + if (ret) { + dev_warn(&par->spi->dev, + "9-bit SPI not available, emulating using 8-bit.\n"); + par->spi->bits_per_word = 8; + ret = par->spi->master->setup(par->spi); + if (ret) + goto out_release; + /* allocate buffer with room for dc bits */ + par->extra = devm_kzalloc(par->info->device, + par->txbuf.len + (par->txbuf.len / 8) + 8, + GFP_KERNEL); + if (!par->extra) { + ret = -ENOMEM; + goto out_release; + } + par->fbtftops.write = fbtft_write_spi_emulate_9; + } + } + + if (!par->fbtftops.verify_gpios) + par->fbtftops.verify_gpios = fbtft_verify_gpios; + + /* make sure we still use the driver provided functions */ + fbtft_merge_fbtftops(&par->fbtftops, &display->fbtftops); + + /* use init_sequence if provided */ + if (par->init_sequence) + par->fbtftops.init_display = fbtft_init_display; + + /* use platform_data provided functions above all */ + fbtft_merge_fbtftops(&par->fbtftops, &pdata->display.fbtftops); + + ret = fbtft_register_framebuffer(info); + if (ret < 0) + goto out_release; + + return 0; + +out_release: + fbtft_framebuffer_release(info); + + return ret; +} +EXPORT_SYMBOL(fbtft_probe_common); + +/** + * fbtft_remove_common() - Generic device remove() helper function + * @dev: Device + * @info: Framebuffer + * + * Unregisters and releases the framebuffer + * + * Return: 0 if successful, negative if error + */ +int fbtft_remove_common(struct device *dev, struct fb_info *info) +{ + struct fbtft_par *par; + + if (!info) + return -EINVAL; + par = info->par; + if (par) + fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par, + "%s()\n", __func__); + fbtft_unregister_framebuffer(info); + fbtft_framebuffer_release(info); + + return 0; +} +EXPORT_SYMBOL(fbtft_remove_common); + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fbtft-io.c b/drivers/staging/fbtft/fbtft-io.c new file mode 100644 index 00000000000..32155a7b2a6 --- /dev/null +++ b/drivers/staging/fbtft/fbtft-io.c @@ -0,0 +1,239 @@ +#include <linux/export.h> +#include <linux/errno.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include "fbtft.h" + +int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len) +{ + struct spi_transfer t = { + .tx_buf = buf, + .len = len, + }; + struct spi_message m; + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + if (!par->spi) { + dev_err(par->info->device, + "%s: par->spi is unexpectedly NULL\n", __func__); + return -1; + } + + spi_message_init(&m); + if (par->txbuf.dma && buf == par->txbuf.buf) { + t.tx_dma = par->txbuf.dma; + m.is_dma_mapped = 1; + } + spi_message_add_tail(&t, &m); + return spi_sync(par->spi, &m); +} +EXPORT_SYMBOL(fbtft_write_spi); + +/** + * fbtft_write_spi_emulate_9() - write SPI emulating 9-bit + * @par: Driver data + * @buf: Buffer to write + * @len: Length of buffer (must be divisible by 8) + * + * When 9-bit SPI is not available, this function can be used to emulate that. + * par->extra must hold a transformation buffer used for transfer. + */ +int fbtft_write_spi_emulate_9(struct fbtft_par *par, void *buf, size_t len) +{ + u16 *src = buf; + u8 *dst = par->extra; + size_t size = len / 2; + size_t added = 0; + int bits, i, j; + u64 val, dc, tmp; + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + if (!par->extra) { + dev_err(par->info->device, "%s: error: par->extra is NULL\n", + __func__); + return -EINVAL; + } + if ((len % 8) != 0) { + dev_err(par->info->device, + "%s: error: len=%d must be divisible by 8\n", + __func__, len); + return -EINVAL; + } + + for (i = 0; i < size; i += 8) { + tmp = 0; + bits = 63; + for (j = 0; j < 7; j++) { + dc = (*src & 0x0100) ? 1 : 0; + val = *src & 0x00FF; + tmp |= dc << bits; + bits -= 8; + tmp |= val << bits--; + src++; + } + tmp |= ((*src & 0x0100) ? 1 : 0); + *(u64 *)dst = cpu_to_be64(tmp); + dst += 8; + *dst++ = (u8)(*src++ & 0x00FF); + added++; + } + + return spi_write(par->spi, par->extra, size + added); +} +EXPORT_SYMBOL(fbtft_write_spi_emulate_9); + +int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len) +{ + int ret; + u8 txbuf[32] = { 0, }; + struct spi_transfer t = { + .speed_hz = 2000000, + .rx_buf = buf, + .len = len, + }; + struct spi_message m; + + if (!par->spi) { + dev_err(par->info->device, + "%s: par->spi is unexpectedly NULL\n", __func__); + return -ENODEV; + } + + if (par->startbyte) { + if (len > 32) { + dev_err(par->info->device, + "%s: len=%d can't be larger than 32 when using 'startbyte'\n", + __func__, len); + return -EINVAL; + } + txbuf[0] = par->startbyte | 0x3; + t.tx_buf = txbuf; + fbtft_par_dbg_hex(DEBUG_READ, par, par->info->device, u8, + txbuf, len, "%s(len=%d) txbuf => ", __func__, len); + } + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + ret = spi_sync(par->spi, &m); + fbtft_par_dbg_hex(DEBUG_READ, par, par->info->device, u8, buf, len, + "%s(len=%d) buf <= ", __func__, len); + + return ret; +} +EXPORT_SYMBOL(fbtft_read_spi); + +/* + * Optimized use of gpiolib is twice as fast as no optimization + * only one driver can use the optimized version at a time + */ +int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) +{ + u8 data; + int i; +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + static u8 prev_data; +#endif + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + while (len--) { + data = *(u8 *) buf; + + /* Start writing by pulling down /WR */ + gpio_set_value(par->gpio.wr, 0); + + /* Set data */ +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + if (data == prev_data) { + gpio_set_value(par->gpio.wr, 0); /* used as delay */ + } else { + for (i = 0; i < 8; i++) { + if ((data & 1) != (prev_data & 1)) + gpio_set_value(par->gpio.db[i], + (data & 1)); + data >>= 1; + prev_data >>= 1; + } + } +#else + for (i = 0; i < 8; i++) { + gpio_set_value(par->gpio.db[i], (data & 1)); + data >>= 1; + } +#endif + + /* Pullup /WR */ + gpio_set_value(par->gpio.wr, 1); + +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + prev_data = *(u8 *) buf; +#endif + buf++; + } + + return 0; +} +EXPORT_SYMBOL(fbtft_write_gpio8_wr); + +int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) +{ + u16 data; + int i; +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + static u16 prev_data; +#endif + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + while (len) { + data = *(u16 *) buf; + + /* Start writing by pulling down /WR */ + gpio_set_value(par->gpio.wr, 0); + + /* Set data */ +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + if (data == prev_data) { + gpio_set_value(par->gpio.wr, 0); /* used as delay */ + } else { + for (i = 0; i < 16; i++) { + if ((data & 1) != (prev_data & 1)) + gpio_set_value(par->gpio.db[i], + (data & 1)); + data >>= 1; + prev_data >>= 1; + } + } +#else + for (i = 0; i < 16; i++) { + gpio_set_value(par->gpio.db[i], (data & 1)); + data >>= 1; + } +#endif + + /* Pullup /WR */ + gpio_set_value(par->gpio.wr, 1); + +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + prev_data = *(u16 *) buf; +#endif + buf += 2; + len -= 2; + } + + return 0; +} +EXPORT_SYMBOL(fbtft_write_gpio16_wr); + +int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len) +{ + dev_err(par->info->device, "%s: function not implemented\n", __func__); + return -1; +} +EXPORT_SYMBOL(fbtft_write_gpio16_wr_latched); diff --git a/drivers/staging/fbtft/fbtft-sysfs.c b/drivers/staging/fbtft/fbtft-sysfs.c new file mode 100644 index 00000000000..45f8de3d11a --- /dev/null +++ b/drivers/staging/fbtft/fbtft-sysfs.c @@ -0,0 +1,222 @@ +#include "fbtft.h" + + +static int get_next_ulong(char **str_p, unsigned long *val, char *sep, int base) +{ + char *p_val; + int ret; + + if (!str_p || !(*str_p)) + return -EINVAL; + + p_val = strsep(str_p, sep); + + if (!p_val) + return -EINVAL; + + ret = kstrtoul(p_val, base, val); + if (ret) + return -EINVAL; + + return 0; +} + +int fbtft_gamma_parse_str(struct fbtft_par *par, unsigned long *curves, + const char *str, int size) +{ + char *str_p, *curve_p = NULL; + char *tmp; + unsigned long val = 0; + int ret = 0; + int curve_counter, value_counter; + + fbtft_par_dbg(DEBUG_SYSFS, par, "%s() str=\n", __func__); + + if (!str || !curves) + return -EINVAL; + + fbtft_par_dbg(DEBUG_SYSFS, par, "%s\n", str); + + tmp = kmalloc(size+1, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + memcpy(tmp, str, size+1); + + /* replace optional separators */ + str_p = tmp; + while (*str_p) { + if (*str_p == ',') + *str_p = ' '; + if (*str_p == ';') + *str_p = '\n'; + str_p++; + } + + str_p = strim(tmp); + + curve_counter = 0; + while (str_p) { + if (curve_counter == par->gamma.num_curves) { + dev_err(par->info->device, "Gamma: Too many curves\n"); + ret = -EINVAL; + goto out; + } + curve_p = strsep(&str_p, "\n"); + value_counter = 0; + while (curve_p) { + if (value_counter == par->gamma.num_values) { + dev_err(par->info->device, + "Gamma: Too many values\n"); + ret = -EINVAL; + goto out; + } + ret = get_next_ulong(&curve_p, &val, " ", 16); + if (ret) + goto out; + curves[curve_counter * par->gamma.num_values + value_counter] = val; + value_counter++; + } + if (value_counter != par->gamma.num_values) { + dev_err(par->info->device, "Gamma: Too few values\n"); + ret = -EINVAL; + goto out; + } + curve_counter++; + } + if (curve_counter != par->gamma.num_curves) { + dev_err(par->info->device, "Gamma: Too few curves\n"); + ret = -EINVAL; + goto out; + } + +out: + kfree(tmp); + return ret; +} + +static ssize_t +sprintf_gamma(struct fbtft_par *par, unsigned long *curves, char *buf) +{ + ssize_t len = 0; + unsigned int i, j; + + mutex_lock(&par->gamma.lock); + for (i = 0; i < par->gamma.num_curves; i++) { + for (j = 0; j < par->gamma.num_values; j++) + len += scnprintf(&buf[len], PAGE_SIZE, + "%04lx ", curves[i*par->gamma.num_values + j]); + buf[len-1] = '\n'; + } + mutex_unlock(&par->gamma.lock); + + return len; +} + +static ssize_t store_gamma_curve(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *fb_info = dev_get_drvdata(device); + struct fbtft_par *par = fb_info->par; + unsigned long tmp_curves[FBTFT_GAMMA_MAX_VALUES_TOTAL]; + int ret; + + ret = fbtft_gamma_parse_str(par, tmp_curves, buf, count); + if (ret) + return ret; + + ret = par->fbtftops.set_gamma(par, tmp_curves); + if (ret) + return ret; + + mutex_lock(&par->gamma.lock); + memcpy(par->gamma.curves, tmp_curves, + par->gamma.num_curves * par->gamma.num_values * sizeof(tmp_curves[0])); + mutex_unlock(&par->gamma.lock); + + return count; +} + +static ssize_t show_gamma_curve(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fb_info = dev_get_drvdata(device); + struct fbtft_par *par = fb_info->par; + + return sprintf_gamma(par, par->gamma.curves, buf); +} + +static struct device_attribute gamma_device_attrs[] = { + __ATTR(gamma, 0660, show_gamma_curve, store_gamma_curve), +}; + + +void fbtft_expand_debug_value(unsigned long *debug) +{ + switch (*debug & 0b111) { + case 1: + *debug |= DEBUG_LEVEL_1; + break; + case 2: + *debug |= DEBUG_LEVEL_2; + break; + case 3: + *debug |= DEBUG_LEVEL_3; + break; + case 4: + *debug |= DEBUG_LEVEL_4; + break; + case 5: + *debug |= DEBUG_LEVEL_5; + break; + case 6: + *debug |= DEBUG_LEVEL_6; + break; + case 7: + *debug = 0xFFFFFFFF; + break; + } +} + +static ssize_t store_debug(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *fb_info = dev_get_drvdata(device); + struct fbtft_par *par = fb_info->par; + int ret; + + ret = kstrtoul(buf, 10, &par->debug); + if (ret) + return ret; + fbtft_expand_debug_value(&par->debug); + + return count; +} + +static ssize_t show_debug(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fb_info = dev_get_drvdata(device); + struct fbtft_par *par = fb_info->par; + + return snprintf(buf, PAGE_SIZE, "%lu\n", par->debug); +} + +static struct device_attribute debug_device_attr = \ + __ATTR(debug, 0660, show_debug, store_debug); + + +void fbtft_sysfs_init(struct fbtft_par *par) +{ + device_create_file(par->info->dev, &debug_device_attr); + if (par->gamma.curves && par->fbtftops.set_gamma) + device_create_file(par->info->dev, &gamma_device_attrs[0]); +} + +void fbtft_sysfs_exit(struct fbtft_par *par) +{ + device_remove_file(par->info->dev, &debug_device_attr); + if (par->gamma.curves && par->fbtftops.set_gamma) + device_remove_file(par->info->dev, &gamma_device_attrs[0]); +} diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h new file mode 100644 index 00000000000..0dbf3f95fe7 --- /dev/null +++ b/drivers/staging/fbtft/fbtft.h @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LINUX_FBTFT_H +#define __LINUX_FBTFT_H + +#include <linux/fb.h> +#include <linux/spinlock.h> +#include <linux/spi/spi.h> +#include <linux/platform_device.h> + + +#define FBTFT_NOP 0x00 +#define FBTFT_SWRESET 0x01 +#define FBTFT_RDDID 0x04 +#define FBTFT_RDDST 0x09 +#define FBTFT_CASET 0x2A +#define FBTFT_RASET 0x2B +#define FBTFT_RAMWR 0x2C + +#define FBTFT_ONBOARD_BACKLIGHT 2 + +#define FBTFT_GPIO_NO_MATCH 0xFFFF +#define FBTFT_GPIO_NAME_SIZE 32 +#define FBTFT_MAX_INIT_SEQUENCE 512 +#define FBTFT_GAMMA_MAX_VALUES_TOTAL 128 + +#define FBTFT_OF_INIT_CMD BIT(24) +#define FBTFT_OF_INIT_DELAY BIT(25) + +/** + * struct fbtft_gpio - Structure that holds one pinname to gpio mapping + * @name: pinname (reset, dc, etc.) + * @gpio: GPIO number + * + */ +struct fbtft_gpio { + char name[FBTFT_GPIO_NAME_SIZE]; + unsigned gpio; +}; + +struct fbtft_par; + +/** + * struct fbtft_ops - FBTFT operations structure + * @write: Writes to interface bus + * @read: Reads from interface bus + * @write_vmem: Writes video memory to display + * @write_reg: Writes to controller register + * @set_addr_win: Set the GRAM update window + * @reset: Reset the LCD controller + * @mkdirty: Marks display lines for update + * @update_display: Updates the display + * @init_display: Initializes the display + * @blank: Blank the display (optional) + * @request_gpios_match: Do pinname to gpio matching + * @request_gpios: Request gpios from the kernel + * @free_gpios: Free previously requested gpios + * @verify_gpios: Verify that necessary gpios is present (optional) + * @register_backlight: Used to register backlight device (optional) + * @unregister_backlight: Unregister backlight device (optional) + * @set_var: Configure LCD with values from variables like @rotate and @bgr + * (optional) + * @set_gamma: Set Gamma curve (optional) + * + * Most of these operations have default functions assigned to them in + * fbtft_framebuffer_alloc() + */ +struct fbtft_ops { + int (*write)(struct fbtft_par *par, void *buf, size_t len); + int (*read)(struct fbtft_par *par, void *buf, size_t len); + int (*write_vmem)(struct fbtft_par *par, size_t offset, size_t len); + void (*write_register)(struct fbtft_par *par, int len, ...); + + void (*set_addr_win)(struct fbtft_par *par, + int xs, int ys, int xe, int ye); + void (*reset)(struct fbtft_par *par); + void (*mkdirty)(struct fb_info *info, int from, int to); + void (*update_display)(struct fbtft_par *par, + unsigned start_line, unsigned end_line); + int (*init_display)(struct fbtft_par *par); + int (*blank)(struct fbtft_par *par, bool on); + + unsigned long (*request_gpios_match)(struct fbtft_par *par, + const struct fbtft_gpio *gpio); + int (*request_gpios)(struct fbtft_par *par); + int (*verify_gpios)(struct fbtft_par *par); + + void (*register_backlight)(struct fbtft_par *par); + void (*unregister_backlight)(struct fbtft_par *par); + + int (*set_var)(struct fbtft_par *par); + int (*set_gamma)(struct fbtft_par *par, unsigned long *curves); +}; + +/** + * struct fbtft_display - Describes the display properties + * @width: Width of display in pixels + * @height: Height of display in pixels + * @regwidth: LCD Controller Register width in bits + * @buswidth: Display interface bus width in bits + * @backlight: Backlight type. + * @fbtftops: FBTFT operations provided by driver or device (platform_data) + * @bpp: Bits per pixel + * @fps: Frames per second + * @txbuflen: Size of transmit buffer + * @init_sequence: Pointer to LCD initialization array + * @gamma: String representation of Gamma curve(s) + * @gamma_num: Number of Gamma curves + * @gamma_len: Number of values per Gamma curve + * @debug: Initial debug value + * + * This structure is not stored by FBTFT except for init_sequence. + */ +struct fbtft_display { + unsigned width; + unsigned height; + unsigned regwidth; + unsigned buswidth; + unsigned backlight; + struct fbtft_ops fbtftops; + unsigned bpp; + unsigned fps; + int txbuflen; + int *init_sequence; + char *gamma; + int gamma_num; + int gamma_len; + unsigned long debug; +}; + +/** + * struct fbtft_platform_data - Passes display specific data to the driver + * @display: Display properties + * @gpios: Pointer to an array of piname to gpio mappings + * @rotate: Display rotation angle + * @bgr: LCD Controller BGR bit + * @fps: Frames per second (this will go away, use @fps in @fbtft_display) + * @txbuflen: Size of transmit buffer + * @startbyte: When set, enables use of Startbyte in transfers + * @gamma: String representation of Gamma curve(s) + * @extra: A way to pass extra info + */ +struct fbtft_platform_data { + struct fbtft_display display; + const struct fbtft_gpio *gpios; + unsigned rotate; + bool bgr; + unsigned fps; + int txbuflen; + u8 startbyte; + char *gamma; + void *extra; +}; + +/** + * struct fbtft_par - Main FBTFT data structure + * + * This structure holds all relevant data to operate the display + * + * See sourcefile for documentation since nested structs is not + * supported by kernel-doc. + * + */ +/* @spi: Set if it is a SPI device + * @pdev: Set if it is a platform device + * @info: Pointer to framebuffer fb_info structure + * @pdata: Pointer to platform data + * @ssbuf: Not used + * @pseudo_palette: Used by fb_set_colreg() + * @txbuf.buf: Transmit buffer + * @txbuf.len: Transmit buffer length + * @buf: Small buffer used when writing init data over SPI + * @startbyte: Used by some controllers when in SPI mode. + * Format: 6 bit Device id + RS bit + RW bit + * @fbtftops: FBTFT operations provided by driver or device (platform_data) + * @dirty_lock: Protects dirty_lines_start and dirty_lines_end + * @dirty_lines_start: Where to begin updating display + * @dirty_lines_end: Where to end updating display + * @gpio.reset: GPIO used to reset display + * @gpio.dc: Data/Command signal, also known as RS + * @gpio.rd: Read latching signal + * @gpio.wr: Write latching signal + * @gpio.latch: Bus latch signal, eg. 16->8 bit bus latch + * @gpio.cs: LCD Chip Select with parallel interface bus + * @gpio.db[16]: Parallel databus + * @gpio.led[16]: Led control signals + * @gpio.aux[16]: Auxillary signals, not used by core + * @init_sequence: Pointer to LCD initialization array + * @gamma.lock: Mutex for Gamma curve locking + * @gamma.curves: Pointer to Gamma curve array + * @gamma.num_values: Number of values per Gamma curve + * @gamma.num_curves: Number of Gamma curves + * @debug: Pointer to debug value + * @current_debug: + * @first_update_done: Used to only time the first display update + * @update_time: Used to calculate 'fps' in debug output + * @bgr: BGR mode/\n + * @extra: Extra info needed by driver + */ +struct fbtft_par { + struct spi_device *spi; + struct platform_device *pdev; + struct fb_info *info; + struct fbtft_platform_data *pdata; + u16 *ssbuf; + u32 pseudo_palette[16]; + struct { + void *buf; + dma_addr_t dma; + size_t len; + } txbuf; + u8 *buf; + u8 startbyte; + struct fbtft_ops fbtftops; + spinlock_t dirty_lock; + unsigned dirty_lines_start; + unsigned dirty_lines_end; + struct { + int reset; + int dc; + int rd; + int wr; + int latch; + int cs; + int db[16]; + int led[16]; + int aux[16]; + } gpio; + int *init_sequence; + struct { + struct mutex lock; + unsigned long *curves; + int num_values; + int num_curves; + } gamma; + unsigned long debug; + bool first_update_done; + struct timespec update_time; + bool bgr; + void *extra; +}; + +#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int)) + +#define write_reg(par, ...) \ +do { \ + par->fbtftops.write_register(par, NUMARGS(__VA_ARGS__), __VA_ARGS__); \ +} while (0) + +/* fbtft-core.c */ +extern void fbtft_dbg_hex(const struct device *dev, + int groupsize, void *buf, size_t len, const char *fmt, ...); +extern struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, + struct device *dev); +extern void fbtft_framebuffer_release(struct fb_info *info); +extern int fbtft_register_framebuffer(struct fb_info *fb_info); +extern int fbtft_unregister_framebuffer(struct fb_info *fb_info); +extern void fbtft_register_backlight(struct fbtft_par *par); +extern void fbtft_unregister_backlight(struct fbtft_par *par); +extern int fbtft_init_display(struct fbtft_par *par); +extern int fbtft_probe_common(struct fbtft_display *display, + struct spi_device *sdev, struct platform_device *pdev); +extern int fbtft_remove_common(struct device *dev, struct fb_info *info); + +/* fbtft-io.c */ +extern int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len); +extern int fbtft_write_spi_emulate_9(struct fbtft_par *par, + void *buf, size_t len); +extern int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len); +extern int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len); +extern int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len); +extern int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, + void *buf, size_t len); + +/* fbtft-bus.c */ +extern int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len); +extern int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len); +extern int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len); +extern int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len); +extern void fbtft_write_reg8_bus8(struct fbtft_par *par, int len, ...); +extern void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...); +extern void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...); +extern void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...); + + +#define FBTFT_REGISTER_DRIVER(_name, _compatible, _display) \ + \ +static int fbtft_driver_probe_spi(struct spi_device *spi) \ +{ \ + return fbtft_probe_common(_display, spi, NULL); \ +} \ + \ +static int fbtft_driver_remove_spi(struct spi_device *spi) \ +{ \ + struct fb_info *info = spi_get_drvdata(spi); \ + \ + return fbtft_remove_common(&spi->dev, info); \ +} \ + \ +static int fbtft_driver_probe_pdev(struct platform_device *pdev) \ +{ \ + return fbtft_probe_common(_display, NULL, pdev); \ +} \ + \ +static int fbtft_driver_remove_pdev(struct platform_device *pdev) \ +{ \ + struct fb_info *info = platform_get_drvdata(pdev); \ + \ + return fbtft_remove_common(&pdev->dev, info); \ +} \ + \ +static const struct of_device_id dt_ids[] = { \ + { .compatible = _compatible }, \ + {}, \ +}; \ + \ +MODULE_DEVICE_TABLE(of, dt_ids); \ + \ + \ +static struct spi_driver fbtft_driver_spi_driver = { \ + .driver = { \ + .name = _name, \ + .owner = THIS_MODULE, \ + .of_match_table = of_match_ptr(dt_ids), \ + }, \ + .probe = fbtft_driver_probe_spi, \ + .remove = fbtft_driver_remove_spi, \ +}; \ + \ +static struct platform_driver fbtft_driver_platform_driver = { \ + .driver = { \ + .name = _name, \ + .owner = THIS_MODULE, \ + .of_match_table = of_match_ptr(dt_ids), \ + }, \ + .probe = fbtft_driver_probe_pdev, \ + .remove = fbtft_driver_remove_pdev, \ +}; \ + \ +static int __init fbtft_driver_module_init(void) \ +{ \ + int ret; \ + \ + ret = spi_register_driver(&fbtft_driver_spi_driver); \ + if (ret < 0) \ + return ret; \ + return platform_driver_register(&fbtft_driver_platform_driver); \ +} \ + \ +static void __exit fbtft_driver_module_exit(void) \ +{ \ + spi_unregister_driver(&fbtft_driver_spi_driver); \ + platform_driver_unregister(&fbtft_driver_platform_driver); \ +} \ + \ +module_init(fbtft_driver_module_init); \ +module_exit(fbtft_driver_module_exit); + + +/* Debug macros */ + +/* shorthand debug levels */ +#define DEBUG_LEVEL_1 DEBUG_REQUEST_GPIOS +#define DEBUG_LEVEL_2 (DEBUG_LEVEL_1 | DEBUG_DRIVER_INIT_FUNCTIONS | DEBUG_TIME_FIRST_UPDATE) +#define DEBUG_LEVEL_3 (DEBUG_LEVEL_2 | DEBUG_RESET | DEBUG_INIT_DISPLAY | DEBUG_BLANK | DEBUG_REQUEST_GPIOS | DEBUG_FREE_GPIOS | DEBUG_VERIFY_GPIOS | DEBUG_BACKLIGHT | DEBUG_SYSFS) +#define DEBUG_LEVEL_4 (DEBUG_LEVEL_2 | DEBUG_FB_READ | DEBUG_FB_WRITE | DEBUG_FB_FILLRECT | DEBUG_FB_COPYAREA | DEBUG_FB_IMAGEBLIT | DEBUG_FB_BLANK) +#define DEBUG_LEVEL_5 (DEBUG_LEVEL_3 | DEBUG_UPDATE_DISPLAY) +#define DEBUG_LEVEL_6 (DEBUG_LEVEL_4 | DEBUG_LEVEL_5) +#define DEBUG_LEVEL_7 0xFFFFFFFF + +#define DEBUG_DRIVER_INIT_FUNCTIONS (1<<3) +#define DEBUG_TIME_FIRST_UPDATE (1<<4) +#define DEBUG_TIME_EACH_UPDATE (1<<5) +#define DEBUG_DEFERRED_IO (1<<6) +#define DEBUG_FBTFT_INIT_FUNCTIONS (1<<7) + +/* fbops */ +#define DEBUG_FB_READ (1<<8) +#define DEBUG_FB_WRITE (1<<9) +#define DEBUG_FB_FILLRECT (1<<10) +#define DEBUG_FB_COPYAREA (1<<11) +#define DEBUG_FB_IMAGEBLIT (1<<12) +#define DEBUG_FB_SETCOLREG (1<<13) +#define DEBUG_FB_BLANK (1<<14) + +#define DEBUG_SYSFS (1<<16) + +/* fbtftops */ +#define DEBUG_BACKLIGHT (1<<17) +#define DEBUG_READ (1<<18) +#define DEBUG_WRITE (1<<19) +#define DEBUG_WRITE_VMEM (1<<20) +#define DEBUG_WRITE_REGISTER (1<<21) +#define DEBUG_SET_ADDR_WIN (1<<22) +#define DEBUG_RESET (1<<23) +#define DEBUG_MKDIRTY (1<<24) +#define DEBUG_UPDATE_DISPLAY (1<<25) +#define DEBUG_INIT_DISPLAY (1<<26) +#define DEBUG_BLANK (1<<27) +#define DEBUG_REQUEST_GPIOS (1<<28) +#define DEBUG_FREE_GPIOS (1<<29) +#define DEBUG_REQUEST_GPIOS_MATCH (1<<30) +#define DEBUG_VERIFY_GPIOS (1<<31) + + +#define fbtft_init_dbg(dev, format, arg...) \ +do { \ + if (unlikely((dev)->platform_data && \ + (((struct fbtft_platform_data *)(dev)->platform_data)->display.debug & DEBUG_DRIVER_INIT_FUNCTIONS))) \ + dev_info(dev, format, ##arg); \ +} while (0) + +#define fbtft_par_dbg(level, par, format, arg...) \ +do { \ + if (unlikely(par->debug & level)) \ + dev_info(par->info->device, format, ##arg); \ +} while (0) + +#define fbtft_dev_dbg(level, par, dev, format, arg...) \ +do { \ + if (unlikely(par->debug & level)) \ + dev_info(dev, format, ##arg); \ +} while (0) + +#define fbtft_par_dbg_hex(level, par, dev, type, buf, num, format, arg...) \ +do { \ + if (unlikely(par->debug & level)) \ + fbtft_dbg_hex(dev, sizeof(type), buf, num * sizeof(type), format, ##arg); \ +} while (0) + +#endif /* __LINUX_FBTFT_H */ diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c new file mode 100644 index 00000000000..b9f4c30e39c --- /dev/null +++ b/drivers/staging/fbtft/fbtft_device.c @@ -0,0 +1,1444 @@ +/* + * + * Copyright (C) 2013, Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> + +#include "fbtft.h" + +#define DRVNAME "fbtft_device" + +#define MAX_GPIOS 32 + +struct spi_device *spi_device; +struct platform_device *p_device; + +static char *name; +module_param(name, charp, 0); +MODULE_PARM_DESC(name, "Devicename (required). " \ +"name=list => list all supported devices."); + +static unsigned rotate; +module_param(rotate, uint, 0); +MODULE_PARM_DESC(rotate, +"Angle to rotate display counter clockwise: 0, 90, 180, 270"); + +static unsigned busnum; +module_param(busnum, uint, 0); +MODULE_PARM_DESC(busnum, "SPI bus number (default=0)"); + +static unsigned cs; +module_param(cs, uint, 0); +MODULE_PARM_DESC(cs, "SPI chip select (default=0)"); + +static unsigned speed; +module_param(speed, uint, 0); +MODULE_PARM_DESC(speed, "SPI speed (override device default)"); + +static int mode = -1; +module_param(mode, int, 0); +MODULE_PARM_DESC(mode, "SPI mode (override device default)"); + +static char *gpios; +module_param(gpios, charp, 0); +MODULE_PARM_DESC(gpios, +"List of gpios. Comma separated with the form: reset:23,dc:24 " \ +"(when overriding the default, all gpios must be specified)"); + +static unsigned fps; +module_param(fps, uint, 0); +MODULE_PARM_DESC(fps, "Frames per second (override driver default)"); + +static char *gamma; +module_param(gamma, charp, 0); +MODULE_PARM_DESC(gamma, +"String representation of Gamma Curve(s). Driver specific."); + +static int txbuflen; +module_param(txbuflen, int, 0); +MODULE_PARM_DESC(txbuflen, "txbuflen (override driver default)"); + +static int bgr = -1; +module_param(bgr, int, 0); +MODULE_PARM_DESC(bgr, +"BGR bit (supported by some drivers)."); + +static unsigned startbyte; +module_param(startbyte, uint, 0); +MODULE_PARM_DESC(startbyte, "Sets the Start byte used by some SPI displays."); + +static bool custom; +module_param(custom, bool, 0); +MODULE_PARM_DESC(custom, "Add a custom display device. " \ +"Use speed= argument to make it a SPI device, else platform_device"); + +static unsigned width; +module_param(width, uint, 0); +MODULE_PARM_DESC(width, "Display width, used with the custom argument"); + +static unsigned height; +module_param(height, uint, 0); +MODULE_PARM_DESC(height, "Display height, used with the custom argument"); + +static unsigned buswidth = 8; +module_param(buswidth, uint, 0); +MODULE_PARM_DESC(buswidth, "Display bus width, used with the custom argument"); + +static int init[FBTFT_MAX_INIT_SEQUENCE]; +static int init_num; +module_param_array(init, int, &init_num, 0); +MODULE_PARM_DESC(init, "Init sequence, used with the custom argument"); + +static unsigned long debug; +module_param(debug, ulong , 0); +MODULE_PARM_DESC(debug, +"level: 0-7 (the remaining 29 bits is for advanced usage)"); + +static unsigned verbose = 3; +module_param(verbose, uint, 0); +MODULE_PARM_DESC(verbose, +"0 silent, >0 show gpios, >1 show devices, >2 show devices before (default=3)"); + + +struct fbtft_device_display { + char *name; + struct spi_board_info *spi; + struct platform_device *pdev; +}; + +static void fbtft_device_pdev_release(struct device *dev); + +static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len); +static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par, + int xs, int ys, int xe, int ye); + +#define ADAFRUIT18_GAMMA \ + "02 1c 07 12 37 32 29 2d 29 25 2B 39 00 01 03 10\n" \ + "03 1d 07 06 2E 2C 29 2D 2E 2E 37 3F 00 00 02 10" + +static int hy28b_init_sequence[] = { + -1,0x00e7,0x0010,-1,0x0000,0x0001,-1,0x0001,0x0100,-1,0x0002,0x0700, + -1,0x0003,0x1030,-1,0x0004,0x0000,-1,0x0008,0x0207,-1,0x0009,0x0000, + -1,0x000a,0x0000,-1,0x000c,0x0001,-1,0x000d,0x0000,-1,0x000f,0x0000, + -1,0x0010,0x0000,-1,0x0011,0x0007,-1,0x0012,0x0000,-1,0x0013,0x0000, + -2,50,-1,0x0010,0x1590,-1,0x0011,0x0227,-2,50,-1,0x0012,0x009c,-2,50, + -1,0x0013,0x1900,-1,0x0029,0x0023,-1,0x002b,0x000e,-2,50, + -1,0x0020,0x0000,-1,0x0021,0x0000,-2,50,-1,0x0050,0x0000, + -1,0x0051,0x00ef,-1,0x0052,0x0000,-1,0x0053,0x013f,-1,0x0060,0xa700, + -1,0x0061,0x0001,-1,0x006a,0x0000,-1,0x0080,0x0000,-1,0x0081,0x0000, + -1,0x0082,0x0000,-1,0x0083,0x0000,-1,0x0084,0x0000,-1,0x0085,0x0000, + -1,0x0090,0x0010,-1,0x0092,0x0000,-1,0x0093,0x0003,-1,0x0095,0x0110, + -1,0x0097,0x0000,-1,0x0098,0x0000,-1,0x0007,0x0133,-1,0x0020,0x0000, + -1,0x0021,0x0000,-2,100,-3 }; + +#define HY28B_GAMMA \ + "04 1F 4 7 7 0 7 7 6 0\n" \ + "0F 00 1 7 4 0 0 0 6 7" + +static int pitft_init_sequence[] = { + -1,0x01,-2,5,-1,0x28,-1,0xEF,0x03,0x80,0x02,-1,0xCF,0x00,0xC1,0x30, + -1,0xED,0x64,0x03,0x12,0x81,-1,0xE8,0x85,0x00,0x78, + -1,0xCB,0x39,0x2C,0x00,0x34,0x02,-1,0xF7,0x20,-1,0xEA,0x00,0x00, + -1,0xC0,0x23,-1,0xC1,0x10,-1,0xC5,0x3e,0x28,-1,0xC7,0x86,-1,0x3A,0x55, + -1,0xB1,0x00,0x18,-1,0xB6,0x08,0x82,0x27,-1,0xF2,0x00,-1,0x26,0x01, + -1,0xE0,0x0F,0x31,0x2B,0x0C,0x0E,0x08,0x4E,0xF1,0x37,0x07,0x10,0x03, + 0x0E,0x09,0x00,-1,0xE1,0x00,0x0E,0x14,0x03,0x11,0x07,0x31,0xC1,0x48, + 0x08,0x0F,0x0C,0x31,0x36,0x0F,-1,0x11,-2,100,-1,0x29,-2,20,-3 }; + +static int waveshare32b_init_sequence[] = { + -1,0xCB,0x39,0x2C,0x00,0x34,0x02,-1,0xCF,0x00,0xC1,0x30, + -1,0xE8,0x85,0x00,0x78,-1,0xEA,0x00,0x00,-1,0xED,0x64,0x03,0x12,0x81, + -1,0xF7,0x20,-1,0xC0,0x23,-1,0xC1,0x10,-1,0xC5,0x3e,0x28,-1,0xC7,0x86, + -1,0x36,0x28,-1,0x3A,0x55,-1,0xB1,0x00,0x18,-1,0xB6,0x08,0x82,0x27, + -1,0xF2,0x00,-1,0x26,0x01, + -1,0xE0,0x0F,0x31,0x2B,0x0C,0x0E,0x08,0x4E,0xF1,0x37,0x07,0x10,0x03,0x0E,0x09,0x00, + -1,0xE1,0x00,0x0E,0x14,0x03,0x11,0x07,0x31,0xC1,0x48,0x08,0x0F,0x0C,0x31,0x36,0x0F, + -1,0x11,-2,120,-1,0x29,-1,0x2c,-3 }; + +/* Supported displays in alphabetical order */ +static struct fbtft_device_display displays[] = { + { + .name = "adafruit18", + .spi = &(struct spi_board_info) { + .modalias = "fb_st7735r", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + .gamma = ADAFRUIT18_GAMMA, + } + } + }, { + .name = "adafruit18_green", + .spi = &(struct spi_board_info) { + .modalias = "fb_st7735r", + .max_speed_hz = 4000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .fbtftops.set_addr_win = \ + adafruit18_green_tab_set_addr_win, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + .gamma = ADAFRUIT18_GAMMA, + } + } + }, { + .name = "adafruit22", + .spi = &(struct spi_board_info) { + .modalias = "fb_hx8340bn", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 9, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "adafruit22a", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9340", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "adafruit28", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9341", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "adafruit13m", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1306", + .max_speed_hz = 16000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "agm1264k-fl", + .pdev = &(struct platform_device) { + .name = "fb_agm1264k-fl", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = FBTFT_ONBOARD_BACKLIGHT, + }, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + } + } + }, { + .name = "dogs102", + .spi = &(struct spi_board_info) { + .modalias = "fb_uc1701", + .max_speed_hz = 8000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 13 }, + { "dc", 6 }, + {}, + }, + } + } + }, { + .name = "er_tftm050_2", + .spi = &(struct spi_board_info) { + .modalias = "fb_ra8875", + .max_speed_hz = 5000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .width = 480, + .height = 272, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "er_tftm070_5", + .spi = &(struct spi_board_info) { + .modalias = "fb_ra8875", + .max_speed_hz = 5000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .width = 800, + .height = 480, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "flexfb", + .spi = &(struct spi_board_info) { + .modalias = "flexfb", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "flexpfb", + .pdev = &(struct platform_device) { + .name = "flexpfb", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + { "reset", 17 }, + { "dc", 1 }, + { "wr", 0 }, + { "cs", 21 }, + { "db00", 9 }, + { "db01", 11 }, + { "db02", 18 }, + { "db03", 23 }, + { "db04", 24 }, + { "db05", 25 }, + { "db06", 8 }, + { "db07", 7 }, + { "led", 4 }, + {}, + }, + }, + } + } + }, { + .name = "freetronicsoled128", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1351", + .max_speed_hz = 20000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = FBTFT_ONBOARD_BACKLIGHT, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + } + } + }, { + .name = "hx8353d", + .spi = &(struct spi_board_info) { + .modalias = "fb_hx8353d", + .max_speed_hz = 16000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "hy28a", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9320", + .max_speed_hz = 32000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .startbyte = 0b01110000, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "hy28b", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9325", + .max_speed_hz = 48000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .init_sequence = hy28b_init_sequence, + }, + .startbyte = 0b01110000, + .bgr = true, + .fps= 50, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "led", 18 }, + {}, + }, + .gamma = HY28B_GAMMA, + } + } + }, { + .name = "ili9481", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9481", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .regwidth = 16, + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 22 }, + {}, + }, + } + } + }, { + .name = "itdb24", + .pdev = &(struct platform_device) { + .name = "fb_s6d1121", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = false, + .gpios = (const struct fbtft_gpio []) { + /* Wiring for LCD adapter kit */ + { "reset", 7 }, + { "dc", 0 }, /* rev 2: 2 */ + { "wr", 1 }, /* rev 2: 3 */ + { "cs", 8 }, + { "db00", 17 }, + { "db01", 18 }, + { "db02", 21 }, /* rev 2: 27 */ + { "db03", 22 }, + { "db04", 23 }, + { "db05", 24 }, + { "db06", 25 }, + { "db07", 4 }, + {} + }, + }, + } + } + }, { + .name = "itdb28", + .pdev = &(struct platform_device) { + .name = "fb_ili9325", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + } + } + }, { + .name = "itdb28_spi", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9325", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "mi0283qt-2", + .spi = &(struct spi_board_info) { + .modalias = "fb_hx8347d", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .startbyte = 0b01110000, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "mi0283qt-9a", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9341", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 9, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "mi0283qt-v2", + .spi = &(struct spi_board_info) { + .modalias = "fb_watterott", + .max_speed_hz = 4000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + {}, + }, + } + } + }, { + .name = "nokia3310", + .spi = &(struct spi_board_info) { + .modalias = "fb_pcd8544", + .max_speed_hz = 400000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "nokia3310a", + .spi = &(struct spi_board_info) { + .modalias = "fb_tls8204", + .max_speed_hz = 1000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "piscreen", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9486", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .regwidth = 16, + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 22 }, + {}, + }, + } + } + }, { + .name = "pitft", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9340", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .chip_select = 0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .init_sequence = pitft_init_sequence, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "dc", 25 }, + {}, + }, + } + } + }, { + .name = "pioled", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1351", + .max_speed_hz = 20000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + .gamma = "0 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 3 " \ + "3 3 3 3 3 3 3 3 " \ + "3 3 3 3 3 3 3 3 " \ + "3 3 3 4 4 4 4 4 " \ + "4 4 4 4 4 4 4" + } + } + }, { + .name = "rpi-display", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9341", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 23 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "s6d02a1", + .spi = &(struct spi_board_info) { + .modalias = "fb_s6d02a1", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "sainsmart18", + .spi = &(struct spi_board_info) { + .modalias = "fb_st7735r", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "sainsmart32", + .pdev = &(struct platform_device) { + .name = "fb_ssd1289", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 16, + .txbuflen = -2, /* disable buffer */ + .backlight = 1, + .fbtftops.write = write_gpio16_wr_slow, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + }, + } + }, { + .name = "sainsmart32_fast", + .pdev = &(struct platform_device) { + .name = "fb_ssd1289", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 16, + .txbuflen = -2, /* disable buffer */ + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + }, + } + }, { + .name = "sainsmart32_latched", + .pdev = &(struct platform_device) { + .name = "fb_ssd1289", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 16, + .txbuflen = -2, /* disable buffer */ + .backlight = 1, + .fbtftops.write = \ + fbtft_write_gpio16_wr_latched, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + }, + } + }, { + .name = "sainsmart32_spi", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1289", + .max_speed_hz = 16000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "spidev", + .spi = &(struct spi_board_info) { + .modalias = "spidev", + .max_speed_hz = 500000, + .bus_num = 0, + .chip_select = 0, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + {}, + }, + } + } + }, { + .name = "ssd1331", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1331", + .max_speed_hz = 20000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + } + } + }, { + .name = "tinylcd35", + .spi = &(struct spi_board_info) { + .modalias = "fb_tinylcd", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "tm022hdh26", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9341", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "tontec35_9481", /* boards before 02 July 2014 */ + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9481", + .max_speed_hz = 128000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 15 }, + { "dc", 25 }, + { "led_", 18 }, + {}, + }, + } + } + }, { + .name = "tontec35_9486", /* boards after 02 July 2014 */ + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9486", + .max_speed_hz = 128000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 15 }, + { "dc", 25 }, + { "led_", 18 }, + {}, + }, + } + } + }, { + .name = "upd161704", + .spi = &(struct spi_board_info) { + .modalias = "fb_upd161704", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + } + } + }, { + .name = "waveshare32b", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9340", + .max_speed_hz = 48000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .init_sequence = waveshare32b_init_sequence, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 27 }, + { "dc", 22 }, + {}, + }, + } + } + }, { + .name = "waveshare22", + .spi = &(struct spi_board_info) { + .modalias = "fb_bd663474", + .max_speed_hz = 32000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + } + } + }, { + /* This should be the last item. + Used with the custom argument */ + .name = "", + .spi = &(struct spi_board_info) { + .modalias = "", + .max_speed_hz = 0, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + {}, + }, + } + }, + .pdev = &(struct platform_device) { + .name = "", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + }, + }, + } +}; + +static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len) +{ + u16 data; + int i; +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + static u16 prev_data; +#endif + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + while (len) { + data = *(u16 *) buf; + + /* Start writing by pulling down /WR */ + gpio_set_value(par->gpio.wr, 0); + + /* Set data */ +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + if (data == prev_data) { + gpio_set_value(par->gpio.wr, 0); /* used as delay */ + } else { + for (i = 0; i < 16; i++) { + if ((data & 1) != (prev_data & 1)) + gpio_set_value(par->gpio.db[i], + (data & 1)); + data >>= 1; + prev_data >>= 1; + } + } +#else + for (i = 0; i < 16; i++) { + gpio_set_value(par->gpio.db[i], (data & 1)); + data >>= 1; + } +#endif + + /* Pullup /WR */ + gpio_set_value(par->gpio.wr, 1); + +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + prev_data = *(u16 *) buf; +#endif + buf += 2; + len -= 2; + } + + return 0; +} + +static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par, + int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + write_reg(par, 0x2A, 0, xs + 2, 0, xe + 2); + write_reg(par, 0x2B, 0, ys + 1, 0, ye + 1); + write_reg(par, 0x2C); +} + +/* used if gpios parameter is present */ +static struct fbtft_gpio fbtft_device_param_gpios[MAX_GPIOS+1] = { }; + +static void fbtft_device_pdev_release(struct device *dev) +{ +/* Needed to silence this message: +Device 'xxx' does not have a release() function, it is broken and must be fixed +*/ +} + +static int spi_device_found(struct device *dev, void *data) +{ + struct spi_device *spi = container_of(dev, struct spi_device, dev); + + pr_info(DRVNAME": %s %s %dkHz %d bits mode=0x%02X\n", + spi->modalias, dev_name(dev), spi->max_speed_hz/1000, + spi->bits_per_word, spi->mode); + + return 0; +} + +static void pr_spi_devices(void) +{ + pr_info(DRVNAME": SPI devices registered:\n"); + bus_for_each_dev(&spi_bus_type, NULL, NULL, spi_device_found); +} + +static int p_device_found(struct device *dev, void *data) +{ + struct platform_device + *pdev = container_of(dev, struct platform_device, dev); + + if (strstr(pdev->name, "fb")) + pr_info(DRVNAME": %s id=%d pdata? %s\n", + pdev->name, pdev->id, + pdev->dev.platform_data ? "yes" : "no"); + + return 0; +} + +static void pr_p_devices(void) +{ + pr_info(DRVNAME": 'fb' Platform devices registered:\n"); + bus_for_each_dev(&platform_bus_type, NULL, NULL, p_device_found); +} + +#ifdef MODULE +static void fbtft_device_spi_delete(struct spi_master *master, unsigned cs) +{ + struct device *dev; + char str[32]; + + snprintf(str, sizeof(str), "%s.%u", dev_name(&master->dev), cs); + + dev = bus_find_device_by_name(&spi_bus_type, NULL, str); + if (dev) { + if (verbose) + pr_info(DRVNAME": Deleting %s\n", str); + device_del(dev); + } +} + +static int fbtft_device_spi_device_register(struct spi_board_info *spi) +{ + struct spi_master *master; + + master = spi_busnum_to_master(spi->bus_num); + if (!master) { + pr_err(DRVNAME ": spi_busnum_to_master(%d) returned NULL\n", + spi->bus_num); + return -EINVAL; + } + /* make sure it's available */ + fbtft_device_spi_delete(master, spi->chip_select); + spi_device = spi_new_device(master, spi); + put_device(&master->dev); + if (!spi_device) { + pr_err(DRVNAME ": spi_new_device() returned NULL\n"); + return -EPERM; + } + return 0; +} +#else +static int fbtft_device_spi_device_register(struct spi_board_info *spi) +{ + return spi_register_board_info(spi, 1); +} +#endif + +static int __init fbtft_device_init(void) +{ + struct spi_board_info *spi = NULL; + struct fbtft_platform_data *pdata; + const struct fbtft_gpio *gpio = NULL; + char *p_gpio, *p_name, *p_num; + bool found = false; + int i = 0; + long val; + int ret = 0; + + pr_debug("\n\n"DRVNAME": init\n"); + + if (name == NULL) { +#ifdef MODULE + pr_err(DRVNAME": missing module parameter: 'name'\n"); + return -EINVAL; +#else + return 0; +#endif + } + + if (init_num > FBTFT_MAX_INIT_SEQUENCE) { + pr_err(DRVNAME \ + ": init parameter: exceeded max array size: %d\n", + FBTFT_MAX_INIT_SEQUENCE); + return -EINVAL; + } + + /* parse module parameter: gpios */ + while ((p_gpio = strsep(&gpios, ","))) { + if (strchr(p_gpio, ':') == NULL) { + pr_err(DRVNAME \ + ": error: missing ':' in gpios parameter: %s\n", + p_gpio); + return -EINVAL; + } + p_num = p_gpio; + p_name = strsep(&p_num, ":"); + if (p_name == NULL || p_num == NULL) { + pr_err(DRVNAME \ + ": something bad happened parsing gpios parameter: %s\n", + p_gpio); + return -EINVAL; + } + ret = kstrtol(p_num, 10, &val); + if (ret) { + pr_err(DRVNAME \ + ": could not parse number in gpios parameter: %s:%s\n", + p_name, p_num); + return -EINVAL; + } + strcpy(fbtft_device_param_gpios[i].name, p_name); + fbtft_device_param_gpios[i++].gpio = (int) val; + if (i == MAX_GPIOS) { + pr_err(DRVNAME \ + ": gpios parameter: exceeded max array size: %d\n", + MAX_GPIOS); + return -EINVAL; + } + } + if (fbtft_device_param_gpios[0].name[0]) + gpio = fbtft_device_param_gpios; + + if (verbose > 2) + pr_spi_devices(); /* print list of registered SPI devices */ + + if (verbose > 2) + pr_p_devices(); /* print list of 'fb' platform devices */ + + pr_debug(DRVNAME": name='%s', busnum=%d, cs=%d\n", name, busnum, cs); + + if (rotate > 0 && rotate < 4) { + rotate = (4 - rotate) * 90; + pr_warn("argument 'rotate' should be an angle. Values 1-3 is deprecated. Setting it to %d.\n", + rotate); + } + if (rotate != 0 && rotate != 90 && rotate != 180 && rotate != 270) { + pr_warn("argument 'rotate' illegal value: %d. Setting it to 0.\n", + rotate); + rotate = 0; + } + + /* name=list lists all supported displays */ + if (strncmp(name, "list", 32) == 0) { + pr_info(DRVNAME": Supported displays:\n"); + + for (i = 0; i < ARRAY_SIZE(displays); i++) + pr_info(DRVNAME": %s\n", displays[i].name); + return -ECANCELED; + } + + if (custom) { + i = ARRAY_SIZE(displays) - 1; + displays[i].name = name; + if (speed == 0) { + displays[i].pdev->name = name; + displays[i].spi = NULL; + } else { + strncpy(displays[i].spi->modalias, name, SPI_NAME_SIZE); + displays[i].pdev = NULL; + } + } + + for (i = 0; i < ARRAY_SIZE(displays); i++) { + if (strncmp(name, displays[i].name, 32) == 0) { + if (displays[i].spi) { + spi = displays[i].spi; + spi->chip_select = cs; + spi->bus_num = busnum; + if (speed) + spi->max_speed_hz = speed; + if (mode != -1) + spi->mode = mode; + pdata = (void *)spi->platform_data; + } else if (displays[i].pdev) { + p_device = displays[i].pdev; + pdata = p_device->dev.platform_data; + } else { + pr_err(DRVNAME": broken displays array\n"); + return -EINVAL; + } + + pdata->rotate = rotate; + if (bgr == 0) + pdata->bgr = false; + else if (bgr == 1) + pdata->bgr = true; + if (startbyte) + pdata->startbyte = startbyte; + if (gamma) + pdata->gamma = gamma; + pdata->display.debug = debug; + if (fps) + pdata->fps = fps; + if (txbuflen) + pdata->txbuflen = txbuflen; + if (init_num) + pdata->display.init_sequence = init; + if (gpio) + pdata->gpios = gpio; + if (custom) { + pdata->display.width = width; + pdata->display.height = height; + pdata->display.buswidth = buswidth; + pdata->display.backlight = 1; + } + + if (displays[i].spi) { + ret = fbtft_device_spi_device_register(spi); + if (ret) { + pr_err(DRVNAME \ + ": failed to register SPI device\n"); + return ret; + } + found = true; + break; + } else { + ret = platform_device_register(p_device); + if (ret < 0) { + pr_err(DRVNAME \ + ": platform_device_register() returned %d\n", + ret); + return ret; + } + found = true; + break; + } + } + } + + if (!found) { + pr_err(DRVNAME": display not supported: '%s'\n", name); + return -EINVAL; + } + + if (verbose && pdata && pdata->gpios) { + gpio = pdata->gpios; + pr_info(DRVNAME": GPIOS used by '%s':\n", name); + found = false; + while (verbose && gpio->name[0]) { + pr_info(DRVNAME": '%s' = GPIO%d\n", + gpio->name, gpio->gpio); + gpio++; + found = true; + } + if (!found) + pr_info(DRVNAME": (none)\n"); + } + + if (spi_device && (verbose > 1)) + pr_spi_devices(); + if (p_device && (verbose > 1)) + pr_p_devices(); + + return 0; +} + +static void __exit fbtft_device_exit(void) +{ + pr_debug(DRVNAME" - exit\n"); + + if (spi_device) { + device_del(&spi_device->dev); + kfree(spi_device); + } + + if (p_device) + platform_device_unregister(p_device); + +} + +arch_initcall(fbtft_device_init); +module_exit(fbtft_device_exit); + +MODULE_DESCRIPTION("Add a FBTFT device."); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c new file mode 100644 index 00000000000..90832c36e55 --- /dev/null +++ b/drivers/staging/fbtft/flexfb.c @@ -0,0 +1,592 @@ +/* + * Generic FB driver for TFT LCD displays + * + * Copyright (C) 2013 Noralf Tronnes + * + * 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 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/vmalloc.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include "fbtft.h" + +#define DRVNAME "flexfb" + + +static char *chip; +module_param(chip, charp, 0); +MODULE_PARM_DESC(chip, "LCD controller"); + +static unsigned int width; +module_param(width, uint, 0); +MODULE_PARM_DESC(width, "Display width"); + +static unsigned int height; +module_param(height, uint, 0); +MODULE_PARM_DESC(height, "Display height"); + +static int init[512]; +static int init_num; +module_param_array(init, int, &init_num, 0); +MODULE_PARM_DESC(init, "Init sequence"); + +static unsigned int setaddrwin; +module_param(setaddrwin, uint, 0); +MODULE_PARM_DESC(setaddrwin, "Which set_addr_win() implementation to use"); + +static unsigned int buswidth = 8; +module_param(buswidth, uint, 0); +MODULE_PARM_DESC(buswidth, "Width of databus (default: 8)"); + +static unsigned int regwidth = 8; +module_param(regwidth, uint, 0); +MODULE_PARM_DESC(regwidth, "Width of controller register (default: 8)"); + +static bool nobacklight; +module_param(nobacklight, bool, 0); +MODULE_PARM_DESC(nobacklight, "Turn off backlight functionality."); + +static bool latched; +module_param(latched, bool, 0); +MODULE_PARM_DESC(latched, "Use with latched 16-bit databus"); + + +static int *initp; +static int initp_num; + +/* default init sequences */ +static int st7735r_init[] = { \ +-1,0x01,-2,150,-1,0x11,-2,500,-1,0xB1,0x01,0x2C,0x2D,-1,0xB2,0x01,0x2C,0x2D,-1,0xB3,0x01,0x2C,0x2D,0x01,0x2C,0x2D, \ +-1,0xB4,0x07,-1,0xC0,0xA2,0x02,0x84,-1,0xC1,0xC5,-1,0xC2,0x0A,0x00,-1,0xC3,0x8A,0x2A,-1,0xC4,0x8A,0xEE,-1,0xC5,0x0E, \ +-1,0x20,-1,0x36,0xC0,-1,0x3A,0x05,-1,0xE0,0x0f,0x1a,0x0f,0x18,0x2f,0x28,0x20,0x22,0x1f,0x1b,0x23,0x37,0x00,0x07,0x02,0x10, \ +-1,0xE1,0x0f,0x1b,0x0f,0x17,0x33,0x2c,0x29,0x2e,0x30,0x30,0x39,0x3f,0x00,0x07,0x03,0x10,-1,0x29,-2,100,-1,0x13,-2,10,-3 }; + +static int ssd1289_init[] = { \ +-1,0x00,0x0001,-1,0x03,0xA8A4,-1,0x0C,0x0000,-1,0x0D,0x080C,-1,0x0E,0x2B00,-1,0x1E,0x00B7,-1,0x01,0x2B3F,-1,0x02,0x0600, \ +-1,0x10,0x0000,-1,0x11,0x6070,-1,0x05,0x0000,-1,0x06,0x0000,-1,0x16,0xEF1C,-1,0x17,0x0003,-1,0x07,0x0233,-1,0x0B,0x0000, \ +-1,0x0F,0x0000,-1,0x41,0x0000,-1,0x42,0x0000,-1,0x48,0x0000,-1,0x49,0x013F,-1,0x4A,0x0000,-1,0x4B,0x0000,-1,0x44,0xEF00, \ +-1,0x45,0x0000,-1,0x46,0x013F,-1,0x30,0x0707,-1,0x31,0x0204,-1,0x32,0x0204,-1,0x33,0x0502,-1,0x34,0x0507,-1,0x35,0x0204, \ +-1,0x36,0x0204,-1,0x37,0x0502,-1,0x3A,0x0302,-1,0x3B,0x0302,-1,0x23,0x0000,-1,0x24,0x0000,-1,0x25,0x8000,-1,0x4f,0x0000, \ +-1,0x4e,0x0000,-1,0x22,-3 }; + +static int hx8340bn_init[] = { \ +-1,0xC1,0xFF,0x83,0x40,-1,0x11,-2,150,-1,0xCA,0x70,0x00,0xD9,-1,0xB0,0x01,0x11, \ +-1,0xC9,0x90,0x49,0x10,0x28,0x28,0x10,0x00,0x06,-2,20,-1,0xC2,0x60,0x71,0x01,0x0E,0x05,0x02,0x09,0x31,0x0A, \ +-1,0xC3,0x67,0x30,0x61,0x17,0x48,0x07,0x05,0x33,-2,10,-1,0xB5,0x35,0x20,0x45,-1,0xB4,0x33,0x25,0x4C,-2,10, \ +-1,0x3A,0x05,-1,0x29,-2,10,-3 }; + +static int ili9225_init[] = { \ +-1,0x0001,0x011C,-1,0x0002,0x0100,-1,0x0003,0x1030,-1,0x0008,0x0808,-1,0x000C,0x0000,-1,0x000F,0x0A01,-1,0x0020,0x0000, \ +-1,0x0021,0x0000,-2,50,-1,0x0010,0x0A00,-1,0x0011,0x1038,-2,50,-1,0x0012,0x1121,-1,0x0013,0x004E,-1,0x0014,0x676F, \ +-1,0x0030,0x0000,-1,0x0031,0x00DB,-1,0x0032,0x0000,-1,0x0033,0x0000,-1,0x0034,0x00DB,-1,0x0035,0x0000,-1,0x0036,0x00AF, \ +-1,0x0037,0x0000,-1,0x0038,0x00DB,-1,0x0039,0x0000,-1,0x0050,0x0000,-1,0x0051,0x060A,-1,0x0052,0x0D0A,-1,0x0053,0x0303, \ +-1,0x0054,0x0A0D,-1,0x0055,0x0A06,-1,0x0056,0x0000,-1,0x0057,0x0303,-1,0x0058,0x0000,-1,0x0059,0x0000,-2,50, \ +-1,0x0007,0x1017,-2,50,-3 }; + +static int ili9320_init[] = { \ +-1,0x00E5,0x8000,-1,0x0000,0x0001,-1,0x0001,0x0100,-1,0x0002,0x0700,-1,0x0003,0x1030,-1,0x0004,0x0000,-1,0x0008,0x0202, \ +-1,0x0009,0x0000,-1,0x000A,0x0000,-1,0x000C,0x0000,-1,0x000D,0x0000,-1,0x000F,0x0000,-1,0x0010,0x0000,-1,0x0011,0x0007, \ +-1,0x0012,0x0000,-1,0x0013,0x0000,-2,200,-1,0x0010,0x17B0,-1,0x0011,0x0031,-2,50,-1,0x0012,0x0138,-2,50,-1,0x0013,0x1800, \ +-1,0x0029,0x0008,-2,50,-1,0x0020,0x0000,-1,0x0021,0x0000,-1,0x0030,0x0000,-1,0x0031,0x0505,-1,0x0032,0x0004, \ +-1,0x0035,0x0006,-1,0x0036,0x0707,-1,0x0037,0x0105,-1,0x0038,0x0002,-1,0x0039,0x0707,-1,0x003C,0x0704,-1,0x003D,0x0807, \ +-1,0x0050,0x0000,-1,0x0051,0x00EF,-1,0x0052,0x0000,-1,0x0053,0x013F,-1,0x0060,0x2700,-1,0x0061,0x0001,-1,0x006A,0x0000, \ +-1,0x0080,0x0000,-1,0x0081,0x0000,-1,0x0082,0x0000,-1,0x0083,0x0000,-1,0x0084,0x0000,-1,0x0085,0x0000,-1,0x0090,0x0010, \ +-1,0x0092,0x0000,-1,0x0093,0x0003,-1,0x0095,0x0110,-1,0x0097,0x0000,-1,0x0098,0x0000,-1,0x0007,0x0173,-3 }; + +static int ili9325_init[] = { \ +-1,0x00E3,0x3008,-1,0x00E7,0x0012,-1,0x00EF,0x1231,-1,0x0001,0x0100,-1,0x0002,0x0700,-1,0x0003,0x1030,-1,0x0004,0x0000, \ +-1,0x0008,0x0207,-1,0x0009,0x0000,-1,0x000A,0x0000,-1,0x000C,0x0000,-1,0x000D,0x0000,-1,0x000F,0x0000,-1,0x0010,0x0000, \ +-1,0x0011,0x0007,-1,0x0012,0x0000,-1,0x0013,0x0000,-2,200,-1,0x0010,0x1690,-1,0x0011,0x0223,-2,50,-1,0x0012,0x000D,-2,50, \ +-1,0x0013,0x1200,-1,0x0029,0x000A,-1,0x002B,0x000C,-2,50,-1,0x0020,0x0000,-1,0x0021,0x0000,-1,0x0030,0x0000, \ +-1,0x0031,0x0506,-1,0x0032,0x0104,-1,0x0035,0x0207,-1,0x0036,0x000F,-1,0x0037,0x0306,-1,0x0038,0x0102,-1,0x0039,0x0707, \ +-1,0x003C,0x0702,-1,0x003D,0x1604,-1,0x0050,0x0000,-1,0x0051,0x00EF,-1,0x0052,0x0000,-1,0x0053,0x013F,-1,0x0060,0xA700, \ +-1,0x0061,0x0001,-1,0x006A,0x0000,-1,0x0080,0x0000,-1,0x0081,0x0000,-1,0x0082,0x0000,-1,0x0083,0x0000,-1,0x0084,0x0000, \ +-1,0x0085,0x0000,-1,0x0090,0x0010,-1,0x0092,0x0600,-1,0x0007,0x0133,-3 }; + +static int ili9341_init[] = { \ +-1,0x28,-2,20,-1,0xCF,0x00,0x83,0x30,-1,0xED,0x64,0x03,0x12,0x81,-1,0xE8,0x85,0x01,0x79, \ +-1,0xCB,0x39,0x2c,0x00,0x34,0x02,-1,0xF7,0x20,-1,0xEA,0x00,0x00,-1,0xC0,0x26,-1,0xC1,0x11, \ +-1,0xC5,0x35,0x3E,-1,0xC7,0xBE,-1,0xB1,0x00,0x1B,-1,0xB6,0x0a,0x82,0x27,0x00,-1,0xB7,0x07, \ +-1,0x3A,0x55,-1,0x36,0x48,-1,0x11,-2,120,-1,0x29,-2,20,-3 }; + +static int ssd1351_init[] = { -1,0xfd,0x12,-1,0xfd,0xb1,-1,0xae,-1,0xb3,0xf1,-1,0xca,0x7f,-1,0xa0,0x74, \ + -1,0x15,0x00,0x7f,-1,0x75,0x00,0x7f,-1,0xa1,0x00,-1,0xa2,0x00,-1,0xb5,0x00, \ + -1,0xab,0x01,-1,0xb1,0x32,-1,0xb4,0xa0,0xb5,0x55,-1,0xbb,0x17,-1,0xbe,0x05, \ + -1,0xc1,0xc8,0x80,0xc8,-1,0xc7,0x0f,-1,0xb6,0x01,-1,0xa6,-1,0xaf,-3 }; + + +/* ili9320, ili9325 */ +static void flexfb_set_addr_win_1(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0020, xs); + write_reg(par, 0x0021, ys); + break; + case 180: + write_reg(par, 0x0020, width - 1 - xs); + write_reg(par, 0x0021, height - 1 - ys); + break; + case 270: + write_reg(par, 0x0020, width - 1 - ys); + write_reg(par, 0x0021, xs); + break; + case 90: + write_reg(par, 0x0020, ys); + write_reg(par, 0x0021, height - 1 - xs); + break; + } + write_reg(par, 0x0022); /* Write Data to GRAM */ +} + +/* ssd1289 */ +static void flexfb_set_addr_win_2(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + switch (par->info->var.rotate) { + /* R4Eh - Set GDDRAM X address counter */ + /* R4Fh - Set GDDRAM Y address counter */ + case 0: + write_reg(par, 0x4e, xs); + write_reg(par, 0x4f, ys); + break; + case 180: + write_reg(par, 0x4e, par->info->var.xres - 1 - xs); + write_reg(par, 0x4f, par->info->var.yres - 1 - ys); + break; + case 270: + write_reg(par, 0x4e, par->info->var.yres - 1 - ys); + write_reg(par, 0x4f, xs); + break; + case 90: + write_reg(par, 0x4e, ys); + write_reg(par, 0x4f, par->info->var.xres - 1 - xs); + break; + } + + /* R22h - RAM data write */ + write_reg(par, 0x22, 0); +} + +/* ssd1351 */ +static void set_addr_win_3(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, 0x15, xs, xe); + write_reg(par, 0x75, ys, ye); + write_reg(par, 0x5C); +} + +static int flexfb_verify_gpios_dc(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__); + + if (par->gpio.dc < 0) { + dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n"); + return -EINVAL; + } + + return 0; +} + +static int flexfb_verify_gpios_db(struct fbtft_par *par) +{ + int i; + int num_db = buswidth; + + fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__); + + if (par->gpio.dc < 0) { + dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n"); + return -EINVAL; + } + if (par->gpio.wr < 0) { + dev_err(par->info->device, "Missing info about 'wr' gpio. Aborting.\n"); + return -EINVAL; + } + if (latched && (par->gpio.latch < 0)) { + dev_err(par->info->device, "Missing info about 'latch' gpio. Aborting.\n"); + return -EINVAL; + } + if (latched) + num_db=buswidth/2; + for (i=0;i < num_db;i++) { + if (par->gpio.db[i] < 0) { + dev_err(par->info->device, "Missing info about 'db%02d' gpio. Aborting.\n", i); + return -EINVAL; + } + } + + return 0; +} + +static struct fbtft_display flex_display = { }; + +static int flexfb_probe_common(struct spi_device *sdev, struct platform_device *pdev) +{ + struct device *dev; + struct fb_info *info; + struct fbtft_par *par; + int ret; + + initp = init; + initp_num = init_num; + + if (sdev) + dev = &sdev->dev; + else + dev = &pdev->dev; + + fbtft_init_dbg(dev, "%s(%s)\n", __func__, sdev ? "'SPI device'" : "'Platform device'"); + + if (chip) { + + if (!strcmp(chip, "st7735r")) { + if (!width) + width = 128; + if (!height) + height = 160; + if (init_num == 0) { + initp = st7735r_init; + initp_num = ARRAY_SIZE(st7735r_init); + } + + + } else if (!strcmp(chip, "hx8340bn")) { + if (!width) + width = 176; + if (!height) + height = 220; + setaddrwin = 0; + if (init_num == 0) { + initp = hx8340bn_init; + initp_num = ARRAY_SIZE(hx8340bn_init); + } + + + } else if (!strcmp(chip, "ili9225")) { + if (!width) + width = 176; + if (!height) + height = 220; + setaddrwin = 0; + regwidth = 16; + if (init_num == 0) { + initp = ili9225_init; + initp_num = ARRAY_SIZE(ili9225_init); + } + + + + } else if (!strcmp(chip, "ili9320")) { + if (!width) + width = 240; + if (!height) + height = 320; + setaddrwin = 1; + regwidth = 16; + if (init_num == 0) { + initp = ili9320_init; + initp_num = ARRAY_SIZE(ili9320_init); + } + + + } else if (!strcmp(chip, "ili9325")) { + if (!width) + width = 240; + if (!height) + height = 320; + setaddrwin = 1; + regwidth = 16; + if (init_num == 0) { + initp = ili9325_init; + initp_num = ARRAY_SIZE(ili9325_init); + } + + } else if (!strcmp(chip, "ili9341")) { + if (!width) + width = 240; + if (!height) + height = 320; + setaddrwin = 0; + regwidth = 8; + if (init_num == 0) { + initp = ili9341_init; + initp_num = ARRAY_SIZE(ili9341_init); + } + + + } else if (!strcmp(chip, "ssd1289")) { + if (!width) + width = 240; + if (!height) + height = 320; + setaddrwin = 2; + regwidth = 16; + if (init_num == 0) { + initp = ssd1289_init; + initp_num = ARRAY_SIZE(ssd1289_init); + } + + + + } else if (!strcmp(chip, "ssd1351")) { + if (!width) + width = 128; + if (!height) + height = 128; + setaddrwin = 3; + if (init_num == 0) { + initp = ssd1351_init; + initp_num = ARRAY_SIZE(ssd1351_init); + } + } else { + dev_err(dev, "chip=%s is not supported\n", chip); + return -EINVAL; + } + } + + if (width == 0 || height == 0) { + dev_err(dev, "argument(s) missing: width and height has to be set.\n"); + return -EINVAL; + } + flex_display.width = width; + flex_display.height = height; + fbtft_init_dbg(dev, "Display resolution: %dx%d\n", width, height); + fbtft_init_dbg(dev, "chip = %s\n", chip ? chip : "not set"); + fbtft_init_dbg(dev, "setaddrwin = %d\n", setaddrwin); + fbtft_init_dbg(dev, "regwidth = %d\n", regwidth); + fbtft_init_dbg(dev, "buswidth = %d\n", buswidth); + + info = fbtft_framebuffer_alloc(&flex_display, dev); + if (!info) + return -ENOMEM; + + par = info->par; + if (sdev) + par->spi = sdev; + else + par->pdev = pdev; + if (!par->init_sequence) + par->init_sequence = initp; + par->fbtftops.init_display = fbtft_init_display; + + /* registerwrite functions */ + switch (regwidth) { + case 8: + par->fbtftops.write_register = fbtft_write_reg8_bus8; + break; + case 16: + par->fbtftops.write_register = fbtft_write_reg16_bus8; + break; + default: + dev_err(dev, "argument 'regwidth': %d is not supported.\n", regwidth); + return -EINVAL; + } + + /* bus functions */ + if (sdev) { + par->fbtftops.write = fbtft_write_spi; + switch (buswidth) { + case 8: + par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; + if (!par->startbyte) + par->fbtftops.verify_gpios = flexfb_verify_gpios_dc; + break; + case 9: + if (regwidth == 16) { + dev_err(dev, "argument 'regwidth': %d is not supported with buswidth=%d and SPI.\n", regwidth, buswidth); + return -EINVAL; + } + par->fbtftops.write_register = fbtft_write_reg8_bus9; + par->fbtftops.write_vmem = fbtft_write_vmem16_bus9; + sdev->bits_per_word=9; + ret = sdev->master->setup(sdev); + if (ret) { + dev_warn(dev, + "9-bit SPI not available, emulating using 8-bit.\n"); + sdev->bits_per_word = 8; + ret = sdev->master->setup(sdev); + if (ret) + goto out_release; + /* allocate buffer with room for dc bits */ + par->extra = devm_kzalloc(par->info->device, + par->txbuf.len + (par->txbuf.len / 8) + 8, + GFP_KERNEL); + if (!par->extra) { + ret = -ENOMEM; + goto out_release; + } + par->fbtftops.write = fbtft_write_spi_emulate_9; + } + break; + default: + dev_err(dev, "argument 'buswidth': %d is not supported with SPI.\n", buswidth); + return -EINVAL; + } + } else { + par->fbtftops.verify_gpios = flexfb_verify_gpios_db; + switch (buswidth) { + case 8: + par->fbtftops.write = fbtft_write_gpio8_wr; + par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; + break; + case 16: + par->fbtftops.write_register = fbtft_write_reg16_bus16; + if (latched) + par->fbtftops.write = fbtft_write_gpio16_wr_latched; + else + par->fbtftops.write = fbtft_write_gpio16_wr; + par->fbtftops.write_vmem = fbtft_write_vmem16_bus16; + break; + default: + dev_err(dev, "argument 'buswidth': %d is not supported with parallel.\n", buswidth); + return -EINVAL; + } + } + + /* set_addr_win function */ + switch (setaddrwin) { + case 0: + /* use default */ + break; + case 1: + par->fbtftops.set_addr_win = flexfb_set_addr_win_1; + break; + case 2: + par->fbtftops.set_addr_win = flexfb_set_addr_win_2; + break; + case 3: + par->fbtftops.set_addr_win = set_addr_win_3; + break; + default: + dev_err(dev, "argument 'setaddrwin': unknown value %d.\n", setaddrwin); + return -EINVAL; + } + + if (!nobacklight) + par->fbtftops.register_backlight = fbtft_register_backlight; + + ret = fbtft_register_framebuffer(info); + if (ret < 0) + goto out_release; + + return 0; + +out_release: + fbtft_framebuffer_release(info); + + return ret; +} + +static int flexfb_remove_common(struct device *dev, struct fb_info *info) +{ + struct fbtft_par *par; + + if (!info) + return -EINVAL; + par = info->par; + if (par) + fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par, + "%s()\n", __func__); + fbtft_unregister_framebuffer(info); + fbtft_framebuffer_release(info); + + return 0; +} + +static int flexfb_probe_spi(struct spi_device *spi) +{ + return flexfb_probe_common(spi, NULL); +} + +static int flexfb_remove_spi(struct spi_device *spi) +{ + struct fb_info *info = spi_get_drvdata(spi); + + return flexfb_remove_common(&spi->dev, info); +} + +static int flexfb_probe_pdev(struct platform_device *pdev) +{ + return flexfb_probe_common(NULL, pdev); +} + +static int flexfb_remove_pdev(struct platform_device *pdev) +{ + struct fb_info *info = platform_get_drvdata(pdev); + + return flexfb_remove_common(&pdev->dev, info); +} + +static struct spi_driver flexfb_spi_driver = { + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, + .probe = flexfb_probe_spi, + .remove = flexfb_remove_spi, +}; + +static const struct platform_device_id flexfb_platform_ids[] = { + { "flexpfb", 0 }, + { }, +}; + +static struct platform_driver flexfb_platform_driver = { + .driver = { + .name = DRVNAME, + }, + .id_table = flexfb_platform_ids, + .probe = flexfb_probe_pdev, + .remove = flexfb_remove_pdev, +}; + +static int __init flexfb_init(void) +{ + int ret, ret2; + + ret = spi_register_driver(&flexfb_spi_driver); + ret2 = platform_driver_register(&flexfb_platform_driver); + if (ret < 0) + return ret; + return ret2; +} + +static void __exit flexfb_exit(void) +{ + spi_unregister_driver(&flexfb_spi_driver); + platform_driver_unregister(&flexfb_platform_driver); +} + +/* ------------------------------------------------------------------------- */ + +module_init(flexfb_init); +module_exit(flexfb_exit); + +MODULE_DESCRIPTION("Generic FB driver for TFT LCD displays"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index d5475b7270a..017c3b92f51 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -172,11 +172,11 @@ u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index) spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); /* check if we want to read upper or lower 32-bit word */ - if (Index) { + if (Index) data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAL); - } else { + else data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAH); - } + spin_unlock_irqrestore(&info->dpram_lock, flags); return data; @@ -204,11 +204,11 @@ static inline void ft1000_write_dpram_mag_16(struct net_device *dev, /* Provide mutual exclusive access while reading ASIC registers. */ spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); - if (Index) { + if (Index) ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAL, value); - } else { + else ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, value); - } + spin_unlock_irqrestore(&info->dpram_lock, flags); } @@ -440,9 +440,8 @@ static int ft1000_reset_card(struct net_device *dev) tempword = ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE, FT1000_MAG_DPRAM_FEFE_INDX); - if (tempword == 0xfefe) { + if (tempword == 0xfefe) break; - } mdelay(20); } @@ -570,12 +569,12 @@ static void ft1000_hbchk(u_long data) pr_debug("hi_ho value = 0x%x\n", tempword); /* Let's perform another check if ho is not detected */ if (tempword != ho) { - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) tempword = ft1000_read_dpram(dev, FT1000_HI_HO); - } - else { - tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX)); - } + else + tempword = ntohs(ft1000_read_dpram_mag_16(dev, + FT1000_MAG_HI_HO, + FT1000_MAG_HI_HO_INDX)); } if (tempword != ho) { pr_info("heartbeat failed - no ho detected\n"); @@ -621,9 +620,9 @@ static void ft1000_hbchk(u_long data) tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); /* Let's check doorbell again if fail */ - if (tempword & FT1000_DB_HB) { + if (tempword & FT1000_DB_HB) tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - } + if (tempword & FT1000_DB_HB) { pr_info("heartbeat doorbell not clear by firmware\n"); if (info->AsicID == ELECTRABUZZ_ID) { @@ -686,19 +685,15 @@ static void ft1000_hbchk(u_long data) } /* Let's write hi again if fail */ if (tempword != hi) { - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) ft1000_write_dpram(dev, FT1000_HI_HO, hi); - } - else { + else ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag, FT1000_MAG_HI_HO_INDX); - } - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) tempword = ft1000_read_dpram(dev, FT1000_HI_HO); - } - else { + else tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX)); - } } @@ -770,9 +765,8 @@ static void ft1000_send_cmd(struct net_device *dev, u16 *ptempbuffer, int size, size += sizeof(struct pseudo_hdr); /* check for odd byte and increment to 16-bit word align value */ - if ((size & 0x0001)) { + if ((size & 0x0001)) size++; - } pr_debug("total length = %d\n", size); pr_debug("length = %d\n", ntohs(*ptempbuffer)); /* @@ -915,9 +909,8 @@ static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer, * Calculate pseudo header checksum */ tempword = *ppseudohdr++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) tempword ^= *ppseudohdr++; - } if ((tempword != *ppseudohdr)) { pr_debug("Pseudo header checksum mismatch\n"); /* Drop this message */ @@ -957,12 +950,11 @@ static void ft1000_proc_drvmsg(struct net_device *dev) u16 wrd; } convert; - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) tempword = FT1000_DPRAM_RX_BASE+2; - } - else { + else tempword = FT1000_DPRAM_MAG_RX_BASE; - } + if (ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword)) { /* Get the message type which is total_len + PSEUDO header + msgtype + message body */ @@ -982,9 +974,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev) while (tempword & FT1000_DB_DPRAM_TX) { mdelay(5); i++; - if (i == 10) { + if (i == 10) break; - } } ptr = list_entry(info->prov_list.next, @@ -1039,8 +1030,7 @@ static void ft1000_proc_drvmsg(struct net_device *dev) info->ConTm = 0; } } - } - else { + } else { pr_debug("Media is down\n"); if (info->mediastate == 1) { info->mediastate = 0; @@ -1105,9 +1095,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev) mdelay(10); tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) { + if (tempword & FT1000_DB_DPRAM_TX) mdelay(10); - } } if ((tempword & FT1000_DB_DPRAM_TX) == 0) { @@ -1134,9 +1123,9 @@ static void ft1000_proc_drvmsg(struct net_device *dev) ppseudo_hdr->portsrc = 0; /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) ppseudo_hdr->checksum ^= *pmsg++; - } + info->DSPInfoBlk[8] = 0x7200; info->DSPInfoBlk[9] = htons(info->DSPInfoBlklen); @@ -1156,9 +1145,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev) mdelay(10); tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) { + if (tempword & FT1000_DB_DPRAM_TX) mdelay(10); - } } if ((tempword & FT1000_DB_DPRAM_TX) == 0) { @@ -1184,9 +1172,9 @@ static void ft1000_proc_drvmsg(struct net_device *dev) ppseudo_hdr->portsrc = 0; /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) ppseudo_hdr->checksum ^= *pmsg++; - } + pmsg = (u16 *)&tempbuffer[16]; *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG); *pmsg++ = htons(0x000e); @@ -1508,9 +1496,8 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR); pr_debug("FT1000_REG_MAG_DFSR = 0x%x\n", tempword); } - if (DrvErrNum) { + if (DrvErrNum) pcmcia->PktIntfErr++; - } } } @@ -1567,9 +1554,9 @@ static int ft1000_copy_up_pkt(struct net_device *dev) if (skb == NULL) { pr_debug("No Network buffers available\n"); /* Read High word to complete 32 bit access */ - if (info->AsicID == MAGNEMITE_ID) { + if (info->AsicID == MAGNEMITE_ID) tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); - } + ft1000_flush_fifo(dev, 0); info->stats.rx_errors++; return FAILURE; @@ -1673,9 +1660,8 @@ static int ft1000_copy_up_pkt(struct net_device *dev) } pr_debug("Data passed to Protocol layer:\n"); - for (i = 0; i < len + 12; i++) { + for (i = 0; i < len + 12; i++) pr_debug("Protocol Data: 0x%x\n", *ptemp++); - } skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); @@ -1729,21 +1715,16 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) /* Check if there is room on the FIFO */ if (len > ft1000_read_fifo_len(dev)) { udelay(10); - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } if (len > ft1000_read_fifo_len(dev)) { pr_debug("Transmit FIFO is full - pkt drop\n"); info->stats.tx_errors++; @@ -1751,11 +1732,11 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) } } /* Create pseudo header and send pseudo/ip to hardware */ - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) pseudo.blk.length = len; - } else { + else pseudo.blk.length = ntohs(len); - } + pseudo.blk.source = DSPID; /* Need to swap to get in correct order */ pseudo.blk.destination = HOSTID; pseudo.blk.portdest = NETWORKID; /* Need to swap to get in correct order */ @@ -1768,9 +1749,8 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) pseudo.blk.qos_class = 0; /* Calculate pseudo header checksum */ pseudo.blk.checksum = pseudo.buff[0]; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) pseudo.blk.checksum ^= pseudo.buff[i]; - } /* Production Mode */ if (info->AsicID == ELECTRABUZZ_ID) { @@ -1835,9 +1815,8 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) plong = (u32 *)packet; /* Write PPP type + IP Packet into Downlink FIFO */ - for (i = 0; i < (len >> 2); i++) { + for (i = 0; i < (len >> 2); i++) outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR); - } /* Check for odd alignment */ if (len & 0x0003) { diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index d12cfc9aa32..f0ac4383846 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -332,15 +332,15 @@ int card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer, pr_debug("enter card_send_command... size=%d\n", size); + ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL); + if (ret) + return ret; + commandbuf = kmalloc(size + 2, GFP_KERNEL); if (!commandbuf) return -ENOMEM; memcpy((void *)commandbuf + 2, (void *)ptempbuffer, size); - ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL); - if (ret) - return ret; - if (temp & 0x0100) usleep_range(900, 1100); diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 73eede16382..7c4a77bb94a 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -281,7 +281,8 @@ static int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type) icmp6_out.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; icmp6_out.icmp6_code = 0; icmp6_out.icmp6_cksum = 0; - icmp6_out.icmp6_dataun.un_data32[0] = htonl(0x60000000); /* R=0, S=1, O=1 */ + /* R=0, S=1, O=1 */ + icmp6_out.icmp6_dataun.un_data32[0] = htonl(0x60000000); ns = (struct neighbour_solicitation *) (skb_in->data + mac_header_len + diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index b5b063a738f..d1ab996b330 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -220,7 +220,7 @@ static int up_to_host(struct mux_rx *r) static void do_rx(struct work_struct *work) { struct mux_dev *mux_dev = - container_of(work, struct mux_dev , work_rx.work); + container_of(work, struct mux_dev, work_rx.work); struct mux_rx *r; struct rx_cxt *rx = (struct rx_cxt *)&mux_dev->rx; unsigned long flags; diff --git a/drivers/staging/gs_fpgaboot/io.c b/drivers/staging/gs_fpgaboot/io.c index b260e45c669..819db53da64 100644 --- a/drivers/staging/gs_fpgaboot/io.c +++ b/drivers/staging/gs_fpgaboot/io.c @@ -79,15 +79,6 @@ void xl_shift_bytes_out(enum wbus bus_byte, unsigned char *pdata) /* * generic bit swap for xilinx SYSTEMMAP FPGA programming */ -static inline unsigned char bitswap(unsigned char s) -{ - unsigned char d; - - d = (((s&0x80)>>7) | ((s&0x40)>>5) | ((s&0x20)>>3) | ((s&0x10)>>1) | - ((s&0x08)<<1) | ((s&0x04)<<3) | ((s&0x02)<<5) | ((s&0x01)<<7)); - return d; -} - void xl_program_b(int32_t i) { } diff --git a/drivers/staging/i2o/Kconfig b/drivers/staging/i2o/Kconfig new file mode 100644 index 00000000000..286c53f4b13 --- /dev/null +++ b/drivers/staging/i2o/Kconfig @@ -0,0 +1,120 @@ +menuconfig I2O + tristate "I2O device support" + depends on PCI + ---help--- + The Intelligent Input/Output (I2O) architecture allows hardware + drivers to be split into two parts: an operating system specific + module called the OSM and an hardware specific module called the + HDM. The OSM can talk to a whole range of HDM's, and ideally the + HDM's are not OS dependent. This allows for the same HDM driver to + be used under different operating systems if the relevant OSM is in + place. In order for this to work, you need to have an I2O interface + adapter card in your computer. This card contains a special I/O + processor (IOP), thus allowing high speeds since the CPU does not + have to deal with I/O. + + If you say Y here, you will get a choice of interface adapter + drivers and OSM's with the following questions. + + To compile this support as a module, choose M here: the + modules will be called i2o_core. + + If unsure, say N. + +if I2O + +config I2O_LCT_NOTIFY_ON_CHANGES + bool "Enable LCT notification" + default y + ---help--- + Only say N here if you have a I2O controller from SUN. The SUN + firmware doesn't support LCT notification on changes. If this option + is enabled on such a controller the driver will hang up in a endless + loop. On all other controllers say Y. + + If unsure, say Y. + +config I2O_EXT_ADAPTEC + bool "Enable Adaptec extensions" + default y + ---help--- + Say Y for support of raidutils for Adaptec I2O controllers. You also + have to say Y to "I2O Configuration support", "I2O SCSI OSM" below + and to "SCSI generic support" under "SCSI device configuration". + +config I2O_EXT_ADAPTEC_DMA64 + bool "Enable 64-bit DMA" + depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G ) + default y + ---help--- + Say Y for support of 64-bit DMA transfer mode on Adaptec I2O + controllers. + Note: You need at least firmware version 3709. + +config I2O_CONFIG + tristate "I2O Configuration support" + depends on VIRT_TO_BUS + ---help--- + Say Y for support of the configuration interface for the I2O adapters. + If you have a RAID controller from Adaptec and you want to use the + raidutils to manage your RAID array, you have to say Y here. + + To compile this support as a module, choose M here: the + module will be called i2o_config. + + Note: If you want to use the new API you have to download the + i2o_config patch from http://i2o.shadowconnect.com/ + +config I2O_CONFIG_OLD_IOCTL + bool "Enable ioctls (OBSOLETE)" + depends on I2O_CONFIG + default y + ---help--- + Enables old ioctls. + +config I2O_BUS + tristate "I2O Bus Adapter OSM" + ---help--- + Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM + provides access to the busses on the I2O controller. The main purpose + is to rescan the bus to find new devices. + + To compile this support as a module, choose M here: the + module will be called i2o_bus. + +config I2O_BLOCK + tristate "I2O Block OSM" + depends on BLOCK + ---help--- + Include support for the I2O Block OSM. The Block OSM presents disk + and other structured block devices to the operating system. If you + are using an RAID controller, you could access the array only by + the Block OSM driver. But it is possible to access the single disks + by the SCSI OSM driver, for example to monitor the disks. + + To compile this support as a module, choose M here: the + module will be called i2o_block. + +config I2O_SCSI + tristate "I2O SCSI OSM" + depends on SCSI + ---help--- + Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel + I2O controller. You can use both the SCSI and Block OSM together if + you wish. To access a RAID array, you must use the Block OSM driver. + But you could use the SCSI OSM driver to monitor the single disks. + + To compile this support as a module, choose M here: the + module will be called i2o_scsi. + +config I2O_PROC + tristate "I2O /proc support" + ---help--- + If you say Y here and to "/proc file system support", you will be + able to read I2O related information from the virtual directory + /proc/i2o. + + To compile this support as a module, choose M here: the + module will be called i2o_proc. + +endif # I2O diff --git a/drivers/staging/i2o/Makefile b/drivers/staging/i2o/Makefile new file mode 100644 index 00000000000..b0982dacfd0 --- /dev/null +++ b/drivers/staging/i2o/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for the kernel I2O OSM. +# +# Note : at this point, these files are compiled on all systems. +# In the future, some of these should be built conditionally. +# + +i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o memory.o +i2o_bus-y += bus-osm.o +i2o_config-y += config-osm.o +obj-$(CONFIG_I2O) += i2o_core.o +obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o +obj-$(CONFIG_I2O_BUS) += i2o_bus.o +obj-$(CONFIG_I2O_BLOCK) += i2o_block.o +obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o +obj-$(CONFIG_I2O_PROC) += i2o_proc.o diff --git a/drivers/staging/i2o/README b/drivers/staging/i2o/README new file mode 100644 index 00000000000..f072a8eb304 --- /dev/null +++ b/drivers/staging/i2o/README @@ -0,0 +1,98 @@ + + Linux I2O Support (c) Copyright 1999 Red Hat Software + and others. + + 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 of the License, or (at your option) any later version. + +AUTHORS (so far) + +Alan Cox, Building Number Three Ltd. + Core code, SCSI and Block OSMs + +Steve Ralston, LSI Logic Corp. + Debugging SCSI and Block OSM + +Deepak Saxena, Intel Corp. + Various core/block extensions + /proc interface, bug fixes + Ioctl interfaces for control + Debugging LAN OSM + +Philip Rumpf + Fixed assorted dumb SMP locking bugs + +Juha Sievanen, University of Helsinki Finland + LAN OSM code + /proc interface to LAN class + Bug fixes + Core code extensions + +Auvo Häkkinen, University of Helsinki Finland + LAN OSM code + /Proc interface to LAN class + Bug fixes + Core code extensions + +Taneli Vähäkangas, University of Helsinki Finland + Fixes to i2o_config + +CREDITS + + This work was made possible by + +Red Hat Software + Funding for the Building #3 part of the project + +Symbios Logic (Now LSI) + Host adapters, hints, known to work platforms when I hit + compatibility problems + +BoxHill Corporation + Loan of initial FibreChannel disk array used for development work. + +European Commission + Funding the work done by the University of Helsinki + +SysKonnect + Loan of FDDI and Gigabit Ethernet cards + +ASUSTeK + Loan of I2O motherboard + +STATUS: + +o The core setup works within limits. +o The scsi layer seems to almost work. + I'm still chasing down the hang bug. +o The block OSM is mostly functional +o LAN OSM works with FDDI and Ethernet cards. + +TO DO: + +General: +o Provide hidden address space if asked +o Long term message flow control +o PCI IOP's without interrupts are not supported yet +o Push FAIL handling into the core +o DDM control interfaces for module load etc +o Add I2O 2.0 support (Deffered to 2.5 kernel) + +Block: +o Multiple major numbers +o Read ahead and cache handling stuff. Talk to Ingo and people +o Power management +o Finish Media changers + +SCSI: +o Find the right way to associate drives/luns/busses + +Lan: +o Performance tuning +o Test Fibre Channel code + +Tape: +o Anyone seen anything implementing this ? + (D.S: Will attempt to do so if spare cycles permit) diff --git a/drivers/staging/i2o/README.ioctl b/drivers/staging/i2o/README.ioctl new file mode 100644 index 00000000000..4a7d2ebdfc9 --- /dev/null +++ b/drivers/staging/i2o/README.ioctl @@ -0,0 +1,394 @@ + +Linux I2O User Space Interface +rev 0.3 - 04/20/99 + +============================================================================= +Originally written by Deepak Saxena(deepak@plexity.net) +Currently maintained by Deepak Saxena(deepak@plexity.net) +============================================================================= + +I. Introduction + +The Linux I2O subsystem provides a set of ioctl() commands that can be +utilized by user space applications to communicate with IOPs and devices +on individual IOPs. This document defines the specific ioctl() commands +that are available to the user and provides examples of their uses. + +This document assumes the reader is familiar with or has access to the +I2O specification as no I2O message parameters are outlined. For information +on the specification, see http://www.i2osig.org + +This document and the I2O user space interface are currently maintained +by Deepak Saxena. Please send all comments, errata, and bug fixes to +deepak@csociety.purdue.edu + +II. IOP Access + +Access to the I2O subsystem is provided through the device file named +/dev/i2o/ctl. This file is a character file with major number 10 and minor +number 166. It can be created through the following command: + + mknod /dev/i2o/ctl c 10 166 + +III. Determining the IOP Count + + SYNOPSIS + + ioctl(fd, I2OGETIOPS, int *count); + + u8 count[MAX_I2O_CONTROLLERS]; + + DESCRIPTION + + This function returns the system's active IOP table. count should + point to a buffer containing MAX_I2O_CONTROLLERS entries. Upon + returning, each entry will contain a non-zero value if the given + IOP unit is active, and NULL if it is inactive or non-existent. + + RETURN VALUE. + + Returns 0 if no errors occur, and -1 otherwise. If an error occurs, + errno is set appropriately: + + EFAULT Invalid user space pointer was passed + +IV. Getting Hardware Resource Table + + SYNOPSIS + + ioctl(fd, I2OHRTGET, struct i2o_cmd_hrt *hrt); + + struct i2o_cmd_hrtlct + { + u32 iop; /* IOP unit number */ + void *resbuf; /* Buffer for result */ + u32 *reslen; /* Buffer length in bytes */ + }; + + DESCRIPTION + + This function returns the Hardware Resource Table of the IOP specified + by hrt->iop in the buffer pointed to by hrt->resbuf. The actual size of + the data is written into *(hrt->reslen). + + RETURNS + + This function returns 0 if no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(hrt->reslen) + +V. Getting Logical Configuration Table + + SYNOPSIS + + ioctl(fd, I2OLCTGET, struct i2o_cmd_lct *lct); + + struct i2o_cmd_hrtlct + { + u32 iop; /* IOP unit number */ + void *resbuf; /* Buffer for result */ + u32 *reslen; /* Buffer length in bytes */ + }; + + DESCRIPTION + + This function returns the Logical Configuration Table of the IOP specified + by lct->iop in the buffer pointed to by lct->resbuf. The actual size of + the data is written into *(lct->reslen). + + RETURNS + + This function returns 0 if no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(lct->reslen) + +VI. Setting Parameters + + SYNOPSIS + + ioctl(fd, I2OPARMSET, struct i2o_parm_setget *ops); + + struct i2o_cmd_psetget + { + u32 iop; /* IOP unit number */ + u32 tid; /* Target device TID */ + void *opbuf; /* Operation List buffer */ + u32 oplen; /* Operation List buffer length in bytes */ + void *resbuf; /* Result List buffer */ + u32 *reslen; /* Result List buffer length in bytes */ + }; + + DESCRIPTION + + This function posts a UtilParamsSet message to the device identified + by ops->iop and ops->tid. The operation list for the message is + sent through the ops->opbuf buffer, and the result list is written + into the buffer pointed to by ops->resbuf. The number of bytes + written is placed into *(ops->reslen). + + RETURNS + + The return value is the size in bytes of the data written into + ops->resbuf if no errors occur. If an error occurs, -1 is returned + and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(ops->reslen) + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + + A return value of 0 does not mean that the value was actually + changed properly on the IOP. The user should check the result + list to determine the specific status of the transaction. + +VII. Getting Parameters + + SYNOPSIS + + ioctl(fd, I2OPARMGET, struct i2o_parm_setget *ops); + + struct i2o_parm_setget + { + u32 iop; /* IOP unit number */ + u32 tid; /* Target device TID */ + void *opbuf; /* Operation List buffer */ + u32 oplen; /* Operation List buffer length in bytes */ + void *resbuf; /* Result List buffer */ + u32 *reslen; /* Result List buffer length in bytes */ + }; + + DESCRIPTION + + This function posts a UtilParamsGet message to the device identified + by ops->iop and ops->tid. The operation list for the message is + sent through the ops->opbuf buffer, and the result list is written + into the buffer pointed to by ops->resbuf. The actual size of data + written is placed into *(ops->reslen). + + RETURNS + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(ops->reslen) + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + + A return value of 0 does not mean that the value was actually + properly retrieved. The user should check the result list + to determine the specific status of the transaction. + +VIII. Downloading Software + + SYNOPSIS + + ioctl(fd, I2OSWDL, struct i2o_sw_xfer *sw); + + struct i2o_sw_xfer + { + u32 iop; /* IOP unit number */ + u8 flags; /* DownloadFlags field */ + u8 sw_type; /* Software type */ + u32 sw_id; /* Software ID */ + void *buf; /* Pointer to software buffer */ + u32 *swlen; /* Length of software buffer */ + u32 *maxfrag; /* Number of fragments */ + u32 *curfrag; /* Current fragment number */ + }; + + DESCRIPTION + + This function downloads a software fragment pointed by sw->buf + to the iop identified by sw->iop. The DownloadFlags, SwID, SwType + and SwSize fields of the ExecSwDownload message are filled in with + the values of sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen). + + The fragments _must_ be sent in order and be 8K in size. The last + fragment _may_ be shorter, however. The kernel will compute its + size based on information in the sw->swlen field. + + Please note that SW transfers can take a long time. + + RETURNS + + This function returns 0 no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + +IX. Uploading Software + + SYNOPSIS + + ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw); + + struct i2o_sw_xfer + { + u32 iop; /* IOP unit number */ + u8 flags; /* UploadFlags */ + u8 sw_type; /* Software type */ + u32 sw_id; /* Software ID */ + void *buf; /* Pointer to software buffer */ + u32 *swlen; /* Length of software buffer */ + u32 *maxfrag; /* Number of fragments */ + u32 *curfrag; /* Current fragment number */ + }; + + DESCRIPTION + + This function uploads a software fragment from the IOP identified + by sw->iop, sw->sw_type, sw->sw_id and optionally sw->swlen fields. + The UploadFlags, SwID, SwType and SwSize fields of the ExecSwUpload + message are filled in with the values of sw->flags, sw->sw_id, + sw->sw_type and *(sw->swlen). + + The fragments _must_ be requested in order and be 8K in size. The + user is responsible for allocating memory pointed by sw->buf. The + last fragment _may_ be shorter. + + Please note that SW transfers can take a long time. + + RETURNS + + This function returns 0 if no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + +X. Removing Software + + SYNOPSIS + + ioctl(fd, I2OSWDEL, struct i2o_sw_xfer *sw); + + struct i2o_sw_xfer + { + u32 iop; /* IOP unit number */ + u8 flags; /* RemoveFlags */ + u8 sw_type; /* Software type */ + u32 sw_id; /* Software ID */ + void *buf; /* Unused */ + u32 *swlen; /* Length of the software data */ + u32 *maxfrag; /* Unused */ + u32 *curfrag; /* Unused */ + }; + + DESCRIPTION + + This function removes software from the IOP identified by sw->iop. + The RemoveFlags, SwID, SwType and SwSize fields of the ExecSwRemove message + are filled in with the values of sw->flags, sw->sw_id, sw->sw_type and + *(sw->swlen). Give zero in *(sw->len) if the value is unknown. IOP uses + *(sw->swlen) value to verify correct identication of the module to remove. + The actual size of the module is written into *(sw->swlen). + + RETURNS + + This function returns 0 if no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + +X. Validating Configuration + + SYNOPSIS + + ioctl(fd, I2OVALIDATE, int *iop); + u32 iop; + + DESCRIPTION + + This function posts an ExecConfigValidate message to the controller + identified by iop. This message indicates that the current + configuration is accepted. The iop changes the status of suspect drivers + to valid and may delete old drivers from its store. + + RETURNS + + This function returns 0 if no erro occur. If an error occurs, -1 is + returned and errno is set appropriately: + + ETIMEDOUT Timeout waiting for reply message + ENXIO Invalid IOP number + +XI. Configuration Dialog + + SYNOPSIS + + ioctl(fd, I2OHTML, struct i2o_html *htquery); + struct i2o_html + { + u32 iop; /* IOP unit number */ + u32 tid; /* Target device ID */ + u32 page; /* HTML page */ + void *resbuf; /* Buffer for reply HTML page */ + u32 *reslen; /* Length in bytes of reply buffer */ + void *qbuf; /* Pointer to HTTP query string */ + u32 qlen; /* Length in bytes of query string buffer */ + }; + + DESCRIPTION + + This function posts an UtilConfigDialog message to the device identified + by htquery->iop and htquery->tid. The requested HTML page number is + provided by the htquery->page field, and the resultant data is stored + in the buffer pointed to by htquery->resbuf. If there is an HTTP query + string that is to be sent to the device, it should be sent in the buffer + pointed to by htquery->qbuf. If there is no query string, this field + should be set to NULL. The actual size of the reply received is written + into *(htquery->reslen). + + RETURNS + + This function returns 0 if no error occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(ops->reslen) + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + +XII. Events + + In the process of determining this. Current idea is to have use + the select() interface to allow user apps to periodically poll + the /dev/i2o/ctl device for events. When select() notifies the user + that an event is available, the user would call read() to retrieve + a list of all the events that are pending for the specific device. + +============================================================================= +Revision History +============================================================================= + +Rev 0.1 - 04/01/99 +- Initial revision + +Rev 0.2 - 04/06/99 +- Changed return values to match UNIX ioctl() standard. Only return values + are 0 and -1. All errors are reported through errno. +- Added summary of proposed possible event interfaces + +Rev 0.3 - 04/20/99 +- Changed all ioctls() to use pointers to user data instead of actual data +- Updated error values to match the code diff --git a/drivers/staging/i2o/bus-osm.c b/drivers/staging/i2o/bus-osm.c new file mode 100644 index 00000000000..7aa0339aea0 --- /dev/null +++ b/drivers/staging/i2o/bus-osm.c @@ -0,0 +1,176 @@ +/* + * Bus Adapter OSM + * + * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> + * + * 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 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * initial version. + */ + +#include <linux/module.h> +#include "i2o.h" + +#define OSM_NAME "bus-osm" +#define OSM_VERSION "1.317" +#define OSM_DESCRIPTION "I2O Bus Adapter OSM" + +static struct i2o_driver i2o_bus_driver; + +/* Bus OSM class handling definition */ +static struct i2o_class_id i2o_bus_class_id[] = { + {I2O_CLASS_BUS_ADAPTER}, + {I2O_CLASS_END} +}; + +/** + * i2o_bus_scan - Scan the bus for new devices + * @dev: I2O device of the bus, which should be scanned + * + * Scans the bus dev for new / removed devices. After the scan a new LCT + * will be fetched automatically. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_bus_scan(struct i2o_device *dev) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return -ETIMEDOUT; + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data. + tid); + + return i2o_msg_post_wait(dev->iop, msg, 60); +}; + +/** + * i2o_bus_store_scan - Scan the I2O Bus Adapter + * @d: device which should be scanned + * @attr: device_attribute + * @buf: output buffer + * @count: buffer size + * + * Returns count. + */ +static ssize_t i2o_bus_store_scan(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2o_device *i2o_dev = to_i2o_device(d); + int rc; + + if ((rc = i2o_bus_scan(i2o_dev))) + osm_warn("bus scan failed %d\n", rc); + + return count; +} + +/* Bus Adapter OSM device attributes */ +static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan); + +/** + * i2o_bus_probe - verify if dev is a I2O Bus Adapter device and install it + * @dev: device to verify if it is a I2O Bus Adapter device + * + * Because we want all Bus Adapters always return 0. + * Except when we fail. Then we are sad. + * + * Returns 0, except when we fail to excel. + */ +static int i2o_bus_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(get_device(dev)); + int rc; + + rc = device_create_file(dev, &dev_attr_scan); + if (rc) + goto err_out; + + osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid); + + return 0; + +err_out: + put_device(dev); + return rc; +}; + +/** + * i2o_bus_remove - remove the I2O Bus Adapter device from the system again + * @dev: I2O Bus Adapter device which should be removed + * + * Always returns 0. + */ +static int i2o_bus_remove(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + + device_remove_file(dev, &dev_attr_scan); + + put_device(dev); + + osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); + + return 0; +}; + +/* Bus Adapter OSM driver struct */ +static struct i2o_driver i2o_bus_driver = { + .name = OSM_NAME, + .classes = i2o_bus_class_id, + .driver = { + .probe = i2o_bus_probe, + .remove = i2o_bus_remove, + }, +}; + +/** + * i2o_bus_init - Bus Adapter OSM initialization function + * + * Only register the Bus Adapter OSM in the I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_bus_init(void) +{ + int rc; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + /* Register Bus Adapter OSM into I2O core */ + rc = i2o_driver_register(&i2o_bus_driver); + if (rc) { + osm_err("Could not register Bus Adapter OSM\n"); + return rc; + } + + return 0; +}; + +/** + * i2o_bus_exit - Bus Adapter OSM exit function + * + * Unregisters Bus Adapter OSM from I2O core. + */ +static void __exit i2o_bus_exit(void) +{ + i2o_driver_unregister(&i2o_bus_driver); +}; + +MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_bus_init); +module_exit(i2o_bus_exit); diff --git a/drivers/staging/i2o/config-osm.c b/drivers/staging/i2o/config-osm.c new file mode 100644 index 00000000000..519f52f9f68 --- /dev/null +++ b/drivers/staging/i2o/config-osm.c @@ -0,0 +1,90 @@ +/* + * Configuration OSM + * + * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> + * + * 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 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * initial version. + */ + +#include <linux/module.h> +#include "i2o.h" +#include <linux/dcache.h> +#include <linux/namei.h> +#include <linux/fs.h> + +#include <asm/uaccess.h> + +#define OSM_NAME "config-osm" +#define OSM_VERSION "1.323" +#define OSM_DESCRIPTION "I2O Configuration OSM" + +/* access mode user rw */ +#define S_IWRSR (S_IRUSR | S_IWUSR) + +static struct i2o_driver i2o_config_driver; + +/* Config OSM driver struct */ +static struct i2o_driver i2o_config_driver = { + .name = OSM_NAME, +}; + +#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL +#include "i2o_config.c" +#endif + +/** + * i2o_config_init - Configuration OSM initialization function + * + * Registers Configuration OSM in the I2O core and if old ioctl's are + * compiled in initialize them. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_config_init(void) +{ + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + if (i2o_driver_register(&i2o_config_driver)) { + osm_err("handler register failed.\n"); + return -EBUSY; + } +#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL + if (i2o_config_old_init()) { + osm_err("old config handler initialization failed\n"); + i2o_driver_unregister(&i2o_config_driver); + return -EBUSY; + } +#endif + + return 0; +} + +/** + * i2o_config_exit - Configuration OSM exit function + * + * If old ioctl's are compiled in exit remove them and unregisters + * Configuration OSM from I2O core. + */ +static void i2o_config_exit(void) +{ +#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL + i2o_config_old_exit(); +#endif + + i2o_driver_unregister(&i2o_config_driver); +} + +MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_config_init); +module_exit(i2o_config_exit); diff --git a/drivers/staging/i2o/core.h b/drivers/staging/i2o/core.h new file mode 100644 index 00000000000..91614f11f89 --- /dev/null +++ b/drivers/staging/i2o/core.h @@ -0,0 +1,69 @@ +/* + * I2O core internal declarations + * + * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> + * + * 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 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * initial version. + */ + +/* Exec-OSM */ +extern struct i2o_driver i2o_exec_driver; +extern int i2o_exec_lct_get(struct i2o_controller *); + +extern int __init i2o_exec_init(void); +extern void i2o_exec_exit(void); + +/* driver */ +extern struct bus_type i2o_bus_type; + +extern int i2o_driver_dispatch(struct i2o_controller *, u32); + +extern int __init i2o_driver_init(void); +extern void i2o_driver_exit(void); + +/* PCI */ +extern int __init i2o_pci_init(void); +extern void __exit i2o_pci_exit(void); + +/* device */ +extern const struct attribute_group *i2o_device_groups[]; + +extern void i2o_device_remove(struct i2o_device *); +extern int i2o_device_parse_lct(struct i2o_controller *); + +int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, + int oplen, void *reslist, int reslen); + +/* IOP */ +extern struct i2o_controller *i2o_iop_alloc(void); + +/** + * i2o_iop_free - Free the i2o_controller struct + * @c: I2O controller to free + */ +static inline void i2o_iop_free(struct i2o_controller *c) +{ + i2o_pool_free(&c->in_msg); + kfree(c); +} + +extern int i2o_iop_add(struct i2o_controller *); +extern void i2o_iop_remove(struct i2o_controller *); + +/* control registers relative to c->base */ +#define I2O_IRQ_STATUS 0x30 +#define I2O_IRQ_MASK 0x34 +#define I2O_IN_PORT 0x40 +#define I2O_OUT_PORT 0x44 + +/* Motorola/Freescale specific register offset */ +#define I2O_MOTOROLA_PORT_OFFSET 0x10400 + +#define I2O_IRQ_OUTBOUND_POST 0x00000008 diff --git a/drivers/staging/i2o/debug.c b/drivers/staging/i2o/debug.c new file mode 100644 index 00000000000..7a16114ed8e --- /dev/null +++ b/drivers/staging/i2o/debug.c @@ -0,0 +1,472 @@ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include "i2o.h" + +static void i2o_report_util_cmd(u8 cmd); +static void i2o_report_exec_cmd(u8 cmd); +static void i2o_report_fail_status(u8 req_status, u32 * msg); +static void i2o_report_common_status(u8 req_status); +static void i2o_report_common_dsc(u16 detailed_status); + +/* + * Used for error reporting/debugging purposes. + * Report Cmd name, Request status, Detailed Status. + */ +void i2o_report_status(const char *severity, const char *str, + struct i2o_message *m) +{ + u32 *msg = (u32 *) m; + u8 cmd = (msg[1] >> 24) & 0xFF; + u8 req_status = (msg[4] >> 24) & 0xFF; + u16 detailed_status = msg[4] & 0xFFFF; + + if (cmd == I2O_CMD_UTIL_EVT_REGISTER) + return; // No status in this reply + + printk("%s%s: ", severity, str); + + if (cmd < 0x1F) // Utility cmd + i2o_report_util_cmd(cmd); + + else if (cmd >= 0xA0 && cmd <= 0xEF) // Executive cmd + i2o_report_exec_cmd(cmd); + else + printk("Cmd = %0#2x, ", cmd); // Other cmds + + if (msg[0] & MSG_FAIL) { + i2o_report_fail_status(req_status, msg); + return; + } + + i2o_report_common_status(req_status); + + if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF)) + i2o_report_common_dsc(detailed_status); + else + printk(" / DetailedStatus = %0#4x.\n", + detailed_status); +} + +/* Used to dump a message to syslog during debugging */ +void i2o_dump_message(struct i2o_message *m) +{ +#ifdef DEBUG + u32 *msg = (u32 *) m; + int i; + printk(KERN_INFO "Dumping I2O message size %d @ %p\n", + msg[0] >> 16 & 0xffff, msg); + for (i = 0; i < ((msg[0] >> 16) & 0xffff); i++) + printk(KERN_INFO " msg[%d] = %0#10x\n", i, msg[i]); +#endif +} + +/* + * Used for error reporting/debugging purposes. + * Following fail status are common to all classes. + * The preserved message must be handled in the reply handler. + */ +static void i2o_report_fail_status(u8 req_status, u32 * msg) +{ + static char *FAIL_STATUS[] = { + "0x80", /* not used */ + "SERVICE_SUSPENDED", /* 0x81 */ + "SERVICE_TERMINATED", /* 0x82 */ + "CONGESTION", + "FAILURE", + "STATE_ERROR", + "TIME_OUT", + "ROUTING_FAILURE", + "INVALID_VERSION", + "INVALID_OFFSET", + "INVALID_MSG_FLAGS", + "FRAME_TOO_SMALL", + "FRAME_TOO_LARGE", + "INVALID_TARGET_ID", + "INVALID_INITIATOR_ID", + "INVALID_INITIATOR_CONTEX", /* 0x8F */ + "UNKNOWN_FAILURE" /* 0xFF */ + }; + + if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE) + printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n", + req_status); + else + printk("TRANSPORT_%s.\n", + FAIL_STATUS[req_status & 0x0F]); + + /* Dump some details */ + + printk(KERN_ERR " InitiatorId = %d, TargetId = %d\n", + (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF); + printk(KERN_ERR " LowestVersion = 0x%02X, HighestVersion = 0x%02X\n", + (msg[4] >> 8) & 0xFF, msg[4] & 0xFF); + printk(KERN_ERR " FailingHostUnit = 0x%04X, FailingIOP = 0x%03X\n", + msg[5] >> 16, msg[5] & 0xFFF); + + printk(KERN_ERR " Severity: 0x%02X\n", (msg[4] >> 16) & 0xFF); + if (msg[4] & (1 << 16)) + printk(KERN_DEBUG "(FormatError), " + "this msg can never be delivered/processed.\n"); + if (msg[4] & (1 << 17)) + printk(KERN_DEBUG "(PathError), " + "this msg can no longer be delivered/processed.\n"); + if (msg[4] & (1 << 18)) + printk(KERN_DEBUG "(PathState), " + "the system state does not allow delivery.\n"); + if (msg[4] & (1 << 19)) + printk(KERN_DEBUG + "(Congestion), resources temporarily not available;" + "do not retry immediately.\n"); +} + +/* + * Used for error reporting/debugging purposes. + * Following reply status are common to all classes. + */ +static void i2o_report_common_status(u8 req_status) +{ + static char *REPLY_STATUS[] = { + "SUCCESS", + "ABORT_DIRTY", + "ABORT_NO_DATA_TRANSFER", + "ABORT_PARTIAL_TRANSFER", + "ERROR_DIRTY", + "ERROR_NO_DATA_TRANSFER", + "ERROR_PARTIAL_TRANSFER", + "PROCESS_ABORT_DIRTY", + "PROCESS_ABORT_NO_DATA_TRANSFER", + "PROCESS_ABORT_PARTIAL_TRANSFER", + "TRANSACTION_ERROR", + "PROGRESS_REPORT" + }; + + if (req_status >= ARRAY_SIZE(REPLY_STATUS)) + printk("RequestStatus = %0#2x", req_status); + else + printk("%s", REPLY_STATUS[req_status]); +} + +/* + * Used for error reporting/debugging purposes. + * Following detailed status are valid for executive class, + * utility class, DDM class and for transaction error replies. + */ +static void i2o_report_common_dsc(u16 detailed_status) +{ + static char *COMMON_DSC[] = { + "SUCCESS", + "0x01", // not used + "BAD_KEY", + "TCL_ERROR", + "REPLY_BUFFER_FULL", + "NO_SUCH_PAGE", + "INSUFFICIENT_RESOURCE_SOFT", + "INSUFFICIENT_RESOURCE_HARD", + "0x08", // not used + "CHAIN_BUFFER_TOO_LARGE", + "UNSUPPORTED_FUNCTION", + "DEVICE_LOCKED", + "DEVICE_RESET", + "INAPPROPRIATE_FUNCTION", + "INVALID_INITIATOR_ADDRESS", + "INVALID_MESSAGE_FLAGS", + "INVALID_OFFSET", + "INVALID_PARAMETER", + "INVALID_REQUEST", + "INVALID_TARGET_ADDRESS", + "MESSAGE_TOO_LARGE", + "MESSAGE_TOO_SMALL", + "MISSING_PARAMETER", + "TIMEOUT", + "UNKNOWN_ERROR", + "UNKNOWN_FUNCTION", + "UNSUPPORTED_VERSION", + "DEVICE_BUSY", + "DEVICE_NOT_AVAILABLE" + }; + + if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE) + printk(" / DetailedStatus = %0#4x.\n", + detailed_status); + else + printk(" / %s.\n", COMMON_DSC[detailed_status]); +} + +/* + * Used for error reporting/debugging purposes + */ +static void i2o_report_util_cmd(u8 cmd) +{ + switch (cmd) { + case I2O_CMD_UTIL_NOP: + printk("UTIL_NOP, "); + break; + case I2O_CMD_UTIL_ABORT: + printk("UTIL_ABORT, "); + break; + case I2O_CMD_UTIL_CLAIM: + printk("UTIL_CLAIM, "); + break; + case I2O_CMD_UTIL_RELEASE: + printk("UTIL_CLAIM_RELEASE, "); + break; + case I2O_CMD_UTIL_CONFIG_DIALOG: + printk("UTIL_CONFIG_DIALOG, "); + break; + case I2O_CMD_UTIL_DEVICE_RESERVE: + printk("UTIL_DEVICE_RESERVE, "); + break; + case I2O_CMD_UTIL_DEVICE_RELEASE: + printk("UTIL_DEVICE_RELEASE, "); + break; + case I2O_CMD_UTIL_EVT_ACK: + printk("UTIL_EVENT_ACKNOWLEDGE, "); + break; + case I2O_CMD_UTIL_EVT_REGISTER: + printk("UTIL_EVENT_REGISTER, "); + break; + case I2O_CMD_UTIL_LOCK: + printk("UTIL_LOCK, "); + break; + case I2O_CMD_UTIL_LOCK_RELEASE: + printk("UTIL_LOCK_RELEASE, "); + break; + case I2O_CMD_UTIL_PARAMS_GET: + printk("UTIL_PARAMS_GET, "); + break; + case I2O_CMD_UTIL_PARAMS_SET: + printk("UTIL_PARAMS_SET, "); + break; + case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY: + printk("UTIL_REPLY_FAULT_NOTIFY, "); + break; + default: + printk("Cmd = %0#2x, ", cmd); + } +} + +/* + * Used for error reporting/debugging purposes + */ +static void i2o_report_exec_cmd(u8 cmd) +{ + switch (cmd) { + case I2O_CMD_ADAPTER_ASSIGN: + printk("EXEC_ADAPTER_ASSIGN, "); + break; + case I2O_CMD_ADAPTER_READ: + printk("EXEC_ADAPTER_READ, "); + break; + case I2O_CMD_ADAPTER_RELEASE: + printk("EXEC_ADAPTER_RELEASE, "); + break; + case I2O_CMD_BIOS_INFO_SET: + printk("EXEC_BIOS_INFO_SET, "); + break; + case I2O_CMD_BOOT_DEVICE_SET: + printk("EXEC_BOOT_DEVICE_SET, "); + break; + case I2O_CMD_CONFIG_VALIDATE: + printk("EXEC_CONFIG_VALIDATE, "); + break; + case I2O_CMD_CONN_SETUP: + printk("EXEC_CONN_SETUP, "); + break; + case I2O_CMD_DDM_DESTROY: + printk("EXEC_DDM_DESTROY, "); + break; + case I2O_CMD_DDM_ENABLE: + printk("EXEC_DDM_ENABLE, "); + break; + case I2O_CMD_DDM_QUIESCE: + printk("EXEC_DDM_QUIESCE, "); + break; + case I2O_CMD_DDM_RESET: + printk("EXEC_DDM_RESET, "); + break; + case I2O_CMD_DDM_SUSPEND: + printk("EXEC_DDM_SUSPEND, "); + break; + case I2O_CMD_DEVICE_ASSIGN: + printk("EXEC_DEVICE_ASSIGN, "); + break; + case I2O_CMD_DEVICE_RELEASE: + printk("EXEC_DEVICE_RELEASE, "); + break; + case I2O_CMD_HRT_GET: + printk("EXEC_HRT_GET, "); + break; + case I2O_CMD_ADAPTER_CLEAR: + printk("EXEC_IOP_CLEAR, "); + break; + case I2O_CMD_ADAPTER_CONNECT: + printk("EXEC_IOP_CONNECT, "); + break; + case I2O_CMD_ADAPTER_RESET: + printk("EXEC_IOP_RESET, "); + break; + case I2O_CMD_LCT_NOTIFY: + printk("EXEC_LCT_NOTIFY, "); + break; + case I2O_CMD_OUTBOUND_INIT: + printk("EXEC_OUTBOUND_INIT, "); + break; + case I2O_CMD_PATH_ENABLE: + printk("EXEC_PATH_ENABLE, "); + break; + case I2O_CMD_PATH_QUIESCE: + printk("EXEC_PATH_QUIESCE, "); + break; + case I2O_CMD_PATH_RESET: + printk("EXEC_PATH_RESET, "); + break; + case I2O_CMD_STATIC_MF_CREATE: + printk("EXEC_STATIC_MF_CREATE, "); + break; + case I2O_CMD_STATIC_MF_RELEASE: + printk("EXEC_STATIC_MF_RELEASE, "); + break; + case I2O_CMD_STATUS_GET: + printk("EXEC_STATUS_GET, "); + break; + case I2O_CMD_SW_DOWNLOAD: + printk("EXEC_SW_DOWNLOAD, "); + break; + case I2O_CMD_SW_UPLOAD: + printk("EXEC_SW_UPLOAD, "); + break; + case I2O_CMD_SW_REMOVE: + printk("EXEC_SW_REMOVE, "); + break; + case I2O_CMD_SYS_ENABLE: + printk("EXEC_SYS_ENABLE, "); + break; + case I2O_CMD_SYS_MODIFY: + printk("EXEC_SYS_MODIFY, "); + break; + case I2O_CMD_SYS_QUIESCE: + printk("EXEC_SYS_QUIESCE, "); + break; + case I2O_CMD_SYS_TAB_SET: + printk("EXEC_SYS_TAB_SET, "); + break; + default: + printk("Cmd = %#02x, ", cmd); + } +} + +void i2o_debug_state(struct i2o_controller *c) +{ + printk(KERN_INFO "%s: State = ", c->name); + switch (((i2o_status_block *) c->status_block.virt)->iop_state) { + case 0x01: + printk("INIT\n"); + break; + case 0x02: + printk("RESET\n"); + break; + case 0x04: + printk("HOLD\n"); + break; + case 0x05: + printk("READY\n"); + break; + case 0x08: + printk("OPERATIONAL\n"); + break; + case 0x10: + printk("FAILED\n"); + break; + case 0x11: + printk("FAULTED\n"); + break; + default: + printk("%x (unknown !!)\n", + ((i2o_status_block *) c->status_block.virt)->iop_state); + } +}; + +void i2o_dump_hrt(struct i2o_controller *c) +{ + u32 *rows = (u32 *) c->hrt.virt; + u8 *p = (u8 *) c->hrt.virt; + u8 *d; + int count; + int length; + int i; + int state; + + if (p[3] != 0) { + printk(KERN_ERR + "%s: HRT table for controller is too new a version.\n", + c->name); + return; + } + + count = p[0] | (p[1] << 8); + length = p[2]; + + printk(KERN_INFO "%s: HRT has %d entries of %d bytes each.\n", + c->name, count, length << 2); + + rows += 2; + + for (i = 0; i < count; i++) { + printk(KERN_INFO "Adapter %08X: ", rows[0]); + p = (u8 *) (rows + 1); + d = (u8 *) (rows + 2); + state = p[1] << 8 | p[0]; + + printk("TID %04X:[", state & 0xFFF); + state >>= 12; + if (state & (1 << 0)) + printk("H"); /* Hidden */ + if (state & (1 << 2)) { + printk("P"); /* Present */ + if (state & (1 << 1)) + printk("C"); /* Controlled */ + } + if (state > 9) + printk("*"); /* Hard */ + + printk("]:"); + + switch (p[3] & 0xFFFF) { + case 0: + /* Adapter private bus - easy */ + printk("Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2], + d[1] << 8 | d[0], *(u32 *) (d + 4)); + break; + case 1: + /* ISA bus */ + printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2], + d[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); + break; + + case 2: /* EISA bus */ + printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X", + p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); + break; + + case 3: /* MCA bus */ + printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], + d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); + break; + + case 4: /* PCI bus */ + printk("PCI %d: Bus %d Device %d Function %d", p[2], + d[2], d[1], d[0]); + break; + + case 0x80: /* Other */ + default: + printk("Unsupported bus type."); + break; + } + printk("\n"); + rows += length; + } +} + +EXPORT_SYMBOL(i2o_dump_message); diff --git a/drivers/staging/i2o/device.c b/drivers/staging/i2o/device.c new file mode 100644 index 00000000000..2af22553dd4 --- /dev/null +++ b/drivers/staging/i2o/device.c @@ -0,0 +1,594 @@ +/* + * Functions to handle I2O devices + * + * Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.com> + * + * 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 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * initial version. + */ + +#include <linux/module.h> +#include "i2o.h" +#include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> +#include "core.h" + +/** + * i2o_device_issue_claim - claim or release a device + * @dev: I2O device to claim or release + * @cmd: claim or release command + * @type: type of claim + * + * Issue I2O UTIL_CLAIM or UTIL_RELEASE messages. The message to be sent + * is set by cmd. dev is the I2O device which should be claim or + * released and the type is the claim type (see the I2O spec). + * + * Returs 0 on success or negative error code on failure. + */ +static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, + u32 type) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid); + msg->body[0] = cpu_to_le32(type); + + return i2o_msg_post_wait(dev->iop, msg, 60); +} + +/** + * i2o_device_claim - claim a device for use by an OSM + * @dev: I2O device to claim + * + * Do the leg work to assign a device to a given OSM. If the claim succeeds, + * the owner is the primary. If the attempt fails a negative errno code + * is returned. On success zero is returned. + */ +int i2o_device_claim(struct i2o_device *dev) +{ + int rc = 0; + + mutex_lock(&dev->lock); + + rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY); + if (!rc) + pr_debug("i2o: claim of device %d succeeded\n", + dev->lct_data.tid); + else + pr_debug("i2o: claim of device %d failed %d\n", + dev->lct_data.tid, rc); + + mutex_unlock(&dev->lock); + + return rc; +} + +/** + * i2o_device_claim_release - release a device that the OSM is using + * @dev: device to release + * + * Drop a claim by an OSM on a given I2O device. + * + * AC - some devices seem to want to refuse an unclaim until they have + * finished internal processing. It makes sense since you don't want a + * new device to go reconfiguring the entire system until you are done. + * Thus we are prepared to wait briefly. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_device_claim_release(struct i2o_device *dev) +{ + int tries; + int rc = 0; + + mutex_lock(&dev->lock); + + /* + * If the controller takes a nonblocking approach to + * releases we have to sleep/poll for a few times. + */ + for (tries = 0; tries < 10; tries++) { + rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_RELEASE, + I2O_CLAIM_PRIMARY); + if (!rc) + break; + + ssleep(1); + } + + if (!rc) + pr_debug("i2o: claim release of device %d succeeded\n", + dev->lct_data.tid); + else + pr_debug("i2o: claim release of device %d failed %d\n", + dev->lct_data.tid, rc); + + mutex_unlock(&dev->lock); + + return rc; +} + +/** + * i2o_device_release - release the memory for a I2O device + * @dev: I2O device which should be released + * + * Release the allocated memory. This function is called if refcount of + * device reaches 0 automatically. + */ +static void i2o_device_release(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + + pr_debug("i2o: device %s released\n", dev_name(dev)); + + kfree(i2o_dev); +} + +/** + * class_id_show - Displays class id of I2O device + * @dev: device of which the class id should be displayed + * @attr: pointer to device attribute + * @buf: buffer into which the class id should be printed + * + * Returns the number of bytes which are printed into the buffer. + */ +static ssize_t class_id_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + + sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id); + return strlen(buf) + 1; +} +static DEVICE_ATTR_RO(class_id); + +/** + * tid_show - Displays TID of I2O device + * @dev: device of which the TID should be displayed + * @attr: pointer to device attribute + * @buf: buffer into which the TID should be printed + * + * Returns the number of bytes which are printed into the buffer. + */ +static ssize_t tid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + + sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid); + return strlen(buf) + 1; +} +static DEVICE_ATTR_RO(tid); + +/* I2O device attributes */ +static struct attribute *i2o_device_attrs[] = { + &dev_attr_class_id.attr, + &dev_attr_tid.attr, + NULL, +}; + +static const struct attribute_group i2o_device_group = { + .attrs = i2o_device_attrs, +}; + +const struct attribute_group *i2o_device_groups[] = { + &i2o_device_group, + NULL, +}; + +/** + * i2o_device_alloc - Allocate a I2O device and initialize it + * + * Allocate the memory for a I2O device and initialize locks and lists + * + * Returns the allocated I2O device or a negative error code if the device + * could not be allocated. + */ +static struct i2o_device *i2o_device_alloc(void) +{ + struct i2o_device *dev; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&dev->list); + mutex_init(&dev->lock); + + dev->device.bus = &i2o_bus_type; + dev->device.release = &i2o_device_release; + + return dev; +} + +/** + * i2o_device_add - allocate a new I2O device and add it to the IOP + * @c: I2O controller that the device is on + * @entry: LCT entry of the I2O device + * + * Allocate a new I2O device and initialize it with the LCT entry. The + * device is appended to the device list of the controller. + * + * Returns zero on success, or a -ve errno. + */ +static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry) +{ + struct i2o_device *i2o_dev, *tmp; + int rc; + + i2o_dev = i2o_device_alloc(); + if (IS_ERR(i2o_dev)) { + printk(KERN_ERR "i2o: unable to allocate i2o device\n"); + return PTR_ERR(i2o_dev); + } + + i2o_dev->lct_data = *entry; + + dev_set_name(&i2o_dev->device, "%d:%03x", c->unit, + i2o_dev->lct_data.tid); + + i2o_dev->iop = c; + i2o_dev->device.parent = &c->device; + + rc = device_register(&i2o_dev->device); + if (rc) + goto err; + + list_add_tail(&i2o_dev->list, &c->devices); + + /* create user entries for this device */ + tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); + if (tmp && (tmp != i2o_dev)) { + rc = sysfs_create_link(&i2o_dev->device.kobj, + &tmp->device.kobj, "user"); + if (rc) + goto unreg_dev; + } + + /* create user entries referring to this device */ + list_for_each_entry(tmp, &c->devices, list) + if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + && (tmp != i2o_dev)) { + rc = sysfs_create_link(&tmp->device.kobj, + &i2o_dev->device.kobj, "user"); + if (rc) + goto rmlink1; + } + + /* create parent entries for this device */ + tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); + if (tmp && (tmp != i2o_dev)) { + rc = sysfs_create_link(&i2o_dev->device.kobj, + &tmp->device.kobj, "parent"); + if (rc) + goto rmlink1; + } + + /* create parent entries referring to this device */ + list_for_each_entry(tmp, &c->devices, list) + if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + && (tmp != i2o_dev)) { + rc = sysfs_create_link(&tmp->device.kobj, + &i2o_dev->device.kobj, "parent"); + if (rc) + goto rmlink2; + } + + i2o_driver_notify_device_add_all(i2o_dev); + + pr_debug("i2o: device %s added\n", dev_name(&i2o_dev->device)); + + return 0; + +rmlink2: + /* If link creating failed halfway, we loop whole list to cleanup. + * And we don't care wrong removing of link, because sysfs_remove_link + * will take care of it. + */ + list_for_each_entry(tmp, &c->devices, list) { + if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "parent"); + } + sysfs_remove_link(&i2o_dev->device.kobj, "parent"); +rmlink1: + list_for_each_entry(tmp, &c->devices, list) + if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "user"); + sysfs_remove_link(&i2o_dev->device.kobj, "user"); +unreg_dev: + list_del(&i2o_dev->list); + device_unregister(&i2o_dev->device); +err: + kfree(i2o_dev); + return rc; +} + +/** + * i2o_device_remove - remove an I2O device from the I2O core + * @i2o_dev: I2O device which should be released + * + * Is used on I2O controller removal or LCT modification, when the device + * is removed from the system. Note that the device could still hang + * around until the refcount reaches 0. + */ +void i2o_device_remove(struct i2o_device *i2o_dev) +{ + struct i2o_device *tmp; + struct i2o_controller *c = i2o_dev->iop; + + i2o_driver_notify_device_remove_all(i2o_dev); + + sysfs_remove_link(&i2o_dev->device.kobj, "parent"); + sysfs_remove_link(&i2o_dev->device.kobj, "user"); + + list_for_each_entry(tmp, &c->devices, list) { + if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "parent"); + if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "user"); + } + list_del(&i2o_dev->list); + + device_unregister(&i2o_dev->device); +} + +/** + * i2o_device_parse_lct - Parse a previously fetched LCT and create devices + * @c: I2O controller from which the LCT should be parsed. + * + * The Logical Configuration Table tells us what we can talk to on the + * board. For every entry we create an I2O device, which is registered in + * the I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_device_parse_lct(struct i2o_controller *c) +{ + struct i2o_device *dev, *tmp; + i2o_lct *lct; + u32 *dlct = c->dlct.virt; + int max = 0, i = 0; + u16 table_size; + u32 buf; + + mutex_lock(&c->lct_lock); + + kfree(c->lct); + + buf = le32_to_cpu(*dlct++); + table_size = buf & 0xffff; + + lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); + if (!lct) { + mutex_unlock(&c->lct_lock); + return -ENOMEM; + } + + lct->lct_ver = buf >> 28; + lct->boot_tid = buf >> 16 & 0xfff; + lct->table_size = table_size; + lct->change_ind = le32_to_cpu(*dlct++); + lct->iop_flags = le32_to_cpu(*dlct++); + + table_size -= 3; + + pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max, + lct->table_size); + + while (table_size > 0) { + i2o_lct_entry *entry = &lct->lct_entry[max]; + int found = 0; + + buf = le32_to_cpu(*dlct++); + entry->entry_size = buf & 0xffff; + entry->tid = buf >> 16 & 0xfff; + + entry->change_ind = le32_to_cpu(*dlct++); + entry->device_flags = le32_to_cpu(*dlct++); + + buf = le32_to_cpu(*dlct++); + entry->class_id = buf & 0xfff; + entry->version = buf >> 12 & 0xf; + entry->vendor_id = buf >> 16; + + entry->sub_class = le32_to_cpu(*dlct++); + + buf = le32_to_cpu(*dlct++); + entry->user_tid = buf & 0xfff; + entry->parent_tid = buf >> 12 & 0xfff; + entry->bios_info = buf >> 24; + + memcpy(&entry->identity_tag, dlct, 8); + dlct += 2; + + entry->event_capabilities = le32_to_cpu(*dlct++); + + /* add new devices, which are new in the LCT */ + list_for_each_entry_safe(dev, tmp, &c->devices, list) { + if (entry->tid == dev->lct_data.tid) { + found = 1; + break; + } + } + + if (!found) + i2o_device_add(c, entry); + + table_size -= 9; + max++; + } + + /* remove devices, which are not in the LCT anymore */ + list_for_each_entry_safe(dev, tmp, &c->devices, list) { + int found = 0; + + for (i = 0; i < max; i++) { + if (lct->lct_entry[i].tid == dev->lct_data.tid) { + found = 1; + break; + } + } + + if (!found) + i2o_device_remove(dev); + } + + mutex_unlock(&c->lct_lock); + + return 0; +} + +/* + * Run time support routines + */ + +/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET + * + * This function can be used for all UtilParamsGet/Set operations. + * The OperationList is given in oplist-buffer, + * and results are returned in reslist-buffer. + * Note that the minimum sized reslist is 8 bytes and contains + * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. + */ +int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, + int oplen, void *reslist, int reslen) +{ + struct i2o_message *msg; + int i = 0; + int rc; + struct i2o_dma res; + struct i2o_controller *c = i2o_dev->iop; + struct device *dev = &c->pdev->dev; + + res.virt = NULL; + + if (i2o_dma_alloc(dev, &res, reslen)) + return -ENOMEM; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) { + i2o_dma_free(dev, &res); + return PTR_ERR(msg); + } + + i = 0; + msg->u.head[1] = + cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid); + msg->body[i++] = cpu_to_le32(0x00000000); + msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */ + memcpy(&msg->body[i], oplist, oplen); + i += (oplen / 4 + (oplen % 4 ? 1 : 0)); + msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */ + msg->body[i++] = cpu_to_le32(res.phys); + + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | + SGL_OFFSET_5); + + rc = i2o_msg_post_wait_mem(c, msg, 10, &res); + + /* This only looks like a memory leak - don't "fix" it. */ + if (rc == -ETIMEDOUT) + return rc; + + memcpy(reslist, res.virt, res.len); + i2o_dma_free(dev, &res); + + return rc; +} + +/* + * Query one field group value or a whole scalar group. + */ +int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, + void *buf, int buflen) +{ + u32 opblk[] = { cpu_to_le32(0x00000001), + cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET), + cpu_to_le32((s16) field << 16 | 0x00000001) + }; + u8 *resblk; /* 8 bytes for header */ + int rc; + + resblk = kmalloc(buflen + 8, GFP_KERNEL); + if (!resblk) + return -ENOMEM; + + rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, + sizeof(opblk), resblk, buflen + 8); + + memcpy(buf, resblk + 8, buflen); /* cut off header */ + + kfree(resblk); + + return rc; +} + +/* + * if oper == I2O_PARAMS_TABLE_GET, get from all rows + * if fieldcount == -1 return all fields + * ibuf and ibuflen are unused (use NULL, 0) + * else return specific fields + * ibuf contains fieldindexes + * + * if oper == I2O_PARAMS_LIST_GET, get from specific rows + * if fieldcount == -1 return all fields + * ibuf contains rowcount, keyvalues + * else return specific fields + * fieldcount is # of fieldindexes + * ibuf contains fieldindexes, rowcount, keyvalues + * + * You could also use directly function i2o_issue_params(). + */ +int i2o_parm_table_get(struct i2o_device *dev, int oper, int group, + int fieldcount, void *ibuf, int ibuflen, void *resblk, + int reslen) +{ + u16 *opblk; + int size; + + size = 10 + ibuflen; + if (size % 4) + size += 4 - size % 4; + + opblk = kmalloc(size, GFP_KERNEL); + if (opblk == NULL) { + printk(KERN_ERR "i2o: no memory for query buffer.\n"); + return -ENOMEM; + } + + opblk[0] = 1; /* operation count */ + opblk[1] = 0; /* pad */ + opblk[2] = oper; + opblk[3] = group; + opblk[4] = fieldcount; + memcpy(opblk + 5, ibuf, ibuflen); /* other params */ + + size = i2o_parm_issue(dev, I2O_CMD_UTIL_PARAMS_GET, opblk, + size, resblk, reslen); + + kfree(opblk); + if (size > reslen) + return reslen; + + return size; +} + +EXPORT_SYMBOL(i2o_device_claim); +EXPORT_SYMBOL(i2o_device_claim_release); +EXPORT_SYMBOL(i2o_parm_field_get); +EXPORT_SYMBOL(i2o_parm_table_get); +EXPORT_SYMBOL(i2o_parm_issue); diff --git a/drivers/staging/i2o/driver.c b/drivers/staging/i2o/driver.c new file mode 100644 index 00000000000..111c3edde03 --- /dev/null +++ b/drivers/staging/i2o/driver.c @@ -0,0 +1,382 @@ +/* + * Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs + * + * Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.com> + * + * 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 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * initial version. + */ + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/rwsem.h> +#include "i2o.h" +#include <linux/workqueue.h> +#include <linux/string.h> +#include <linux/slab.h> +#include "core.h" + +#define OSM_NAME "i2o" + +/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ +static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; +module_param_named(max_drivers, i2o_max_drivers, uint, 0); +MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); + +/* I2O drivers lock and array */ +static spinlock_t i2o_drivers_lock; +static struct i2o_driver **i2o_drivers; + +/** + * i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM) + * @dev: device which should be verified + * @drv: the driver to match against + * + * Used by the bus to check if the driver wants to handle the device. + * + * Returns 1 if the class ids of the driver match the class id of the + * device, otherwise 0. + */ +static int i2o_bus_match(struct device *dev, struct device_driver *drv) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_driver *i2o_drv = to_i2o_driver(drv); + struct i2o_class_id *ids = i2o_drv->classes; + + if (ids) + while (ids->class_id != I2O_CLASS_END) { + if (ids->class_id == i2o_dev->lct_data.class_id) + return 1; + ids++; + } + return 0; +}; + +/* I2O bus type */ +struct bus_type i2o_bus_type = { + .name = "i2o", + .match = i2o_bus_match, + .dev_groups = i2o_device_groups, +}; + +/** + * i2o_driver_register - Register a I2O driver (OSM) in the I2O core + * @drv: I2O driver which should be registered + * + * Registers the OSM drv in the I2O core and creates an event queues if + * necessary. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_driver_register(struct i2o_driver *drv) +{ + struct i2o_controller *c; + int i; + int rc = 0; + unsigned long flags; + + osm_debug("Register driver %s\n", drv->name); + + if (drv->event) { + drv->event_queue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, + drv->name); + if (!drv->event_queue) { + osm_err("Could not initialize event queue for driver " + "%s\n", drv->name); + return -EFAULT; + } + osm_debug("Event queue initialized for driver %s\n", drv->name); + } else + drv->event_queue = NULL; + + drv->driver.name = drv->name; + drv->driver.bus = &i2o_bus_type; + + spin_lock_irqsave(&i2o_drivers_lock, flags); + + for (i = 0; i2o_drivers[i]; i++) + if (i >= i2o_max_drivers) { + osm_err("too many drivers registered, increase " + "max_drivers\n"); + spin_unlock_irqrestore(&i2o_drivers_lock, flags); + rc = -EFAULT; + goto out; + } + + drv->context = i; + i2o_drivers[i] = drv; + + spin_unlock_irqrestore(&i2o_drivers_lock, flags); + + osm_debug("driver %s gets context id %d\n", drv->name, drv->context); + + list_for_each_entry(c, &i2o_controllers, list) { + struct i2o_device *i2o_dev; + + i2o_driver_notify_controller_add(drv, c); + list_for_each_entry(i2o_dev, &c->devices, list) + i2o_driver_notify_device_add(drv, i2o_dev); + } + + rc = driver_register(&drv->driver); + if (rc) + goto out; + + return 0; +out: + if (drv->event_queue) { + destroy_workqueue(drv->event_queue); + drv->event_queue = NULL; + } + + return rc; +}; + +/** + * i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core + * @drv: I2O driver which should be unregistered + * + * Unregisters the OSM drv from the I2O core and cleanup event queues if + * necessary. + */ +void i2o_driver_unregister(struct i2o_driver *drv) +{ + struct i2o_controller *c; + unsigned long flags; + + osm_debug("unregister driver %s\n", drv->name); + + driver_unregister(&drv->driver); + + list_for_each_entry(c, &i2o_controllers, list) { + struct i2o_device *i2o_dev; + + list_for_each_entry(i2o_dev, &c->devices, list) + i2o_driver_notify_device_remove(drv, i2o_dev); + + i2o_driver_notify_controller_remove(drv, c); + } + + spin_lock_irqsave(&i2o_drivers_lock, flags); + i2o_drivers[drv->context] = NULL; + spin_unlock_irqrestore(&i2o_drivers_lock, flags); + + if (drv->event_queue) { + destroy_workqueue(drv->event_queue); + drv->event_queue = NULL; + osm_debug("event queue removed for %s\n", drv->name); + } +}; + +/** + * i2o_driver_dispatch - dispatch an I2O reply message + * @c: I2O controller of the message + * @m: I2O message number + * + * The reply is delivered to the driver from which the original message + * was. This function is only called from interrupt context. + * + * Returns 0 on success and the message should not be flushed. Returns > 0 + * on success and if the message should be flushed afterwords. Returns + * negative error code on failure (the message will be flushed too). + */ +int i2o_driver_dispatch(struct i2o_controller *c, u32 m) +{ + struct i2o_driver *drv; + struct i2o_message *msg = i2o_msg_out_to_virt(c, m); + u32 context = le32_to_cpu(msg->u.s.icntxt); + unsigned long flags; + + if (unlikely(context >= i2o_max_drivers)) { + osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, + context); + return -EIO; + } + + spin_lock_irqsave(&i2o_drivers_lock, flags); + drv = i2o_drivers[context]; + spin_unlock_irqrestore(&i2o_drivers_lock, flags); + + if (unlikely(!drv)) { + osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, + context); + return -EIO; + } + + if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { + struct i2o_device *dev, *tmp; + struct i2o_event *evt; + u16 size; + u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff; + + osm_debug("event received from device %d\n", tid); + + if (!drv->event) + return -EIO; + + /* cut of header from message size (in 32-bit words) */ + size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; + + evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); + if (!evt) + return -ENOMEM; + + evt->size = size; + evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); + evt->event_indicator = le32_to_cpu(msg->body[0]); + memcpy(&evt->data, &msg->body[1], size * 4); + + list_for_each_entry_safe(dev, tmp, &c->devices, list) + if (dev->lct_data.tid == tid) { + evt->i2o_dev = dev; + break; + } + + INIT_WORK(&evt->work, drv->event); + queue_work(drv->event_queue, &evt->work); + return 1; + } + + if (unlikely(!drv->reply)) { + osm_debug("%s: Reply to driver %s, but no reply function" + " defined!\n", c->name, drv->name); + return -EIO; + } + + return drv->reply(c, m, msg); +} + +/** + * i2o_driver_notify_controller_add_all - Send notify of added controller + * @c: newly added controller + * + * Send notifications to all registered drivers that a new controller was + * added. + */ +void i2o_driver_notify_controller_add_all(struct i2o_controller *c) +{ + int i; + struct i2o_driver *drv; + + for (i = 0; i < i2o_max_drivers; i++) { + drv = i2o_drivers[i]; + + if (drv) + i2o_driver_notify_controller_add(drv, c); + } +} + +/** + * i2o_driver_notify_controller_remove_all - Send notify of removed controller + * @c: controller that is being removed + * + * Send notifications to all registered drivers that a controller was + * removed. + */ +void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) +{ + int i; + struct i2o_driver *drv; + + for (i = 0; i < i2o_max_drivers; i++) { + drv = i2o_drivers[i]; + + if (drv) + i2o_driver_notify_controller_remove(drv, c); + } +} + +/** + * i2o_driver_notify_device_add_all - Send notify of added device + * @i2o_dev: newly added I2O device + * + * Send notifications to all registered drivers that a device was added. + */ +void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) +{ + int i; + struct i2o_driver *drv; + + for (i = 0; i < i2o_max_drivers; i++) { + drv = i2o_drivers[i]; + + if (drv) + i2o_driver_notify_device_add(drv, i2o_dev); + } +} + +/** + * i2o_driver_notify_device_remove_all - Send notify of removed device + * @i2o_dev: device that is being removed + * + * Send notifications to all registered drivers that a device was removed. + */ +void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) +{ + int i; + struct i2o_driver *drv; + + for (i = 0; i < i2o_max_drivers; i++) { + drv = i2o_drivers[i]; + + if (drv) + i2o_driver_notify_device_remove(drv, i2o_dev); + } +} + +/** + * i2o_driver_init - initialize I2O drivers (OSMs) + * + * Registers the I2O bus and allocate memory for the array of OSMs. + * + * Returns 0 on success or negative error code on failure. + */ +int __init i2o_driver_init(void) +{ + int rc = 0; + + spin_lock_init(&i2o_drivers_lock); + + if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) { + osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n", + i2o_max_drivers); + i2o_max_drivers = I2O_MAX_DRIVERS; + } + osm_info("max drivers = %d\n", i2o_max_drivers); + + i2o_drivers = + kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL); + if (!i2o_drivers) + return -ENOMEM; + + rc = bus_register(&i2o_bus_type); + + if (rc < 0) + kfree(i2o_drivers); + + return rc; +}; + +/** + * i2o_driver_exit - clean up I2O drivers (OSMs) + * + * Unregisters the I2O bus and frees driver array. + */ +void i2o_driver_exit(void) +{ + bus_unregister(&i2o_bus_type); + kfree(i2o_drivers); +}; + +EXPORT_SYMBOL(i2o_driver_register); +EXPORT_SYMBOL(i2o_driver_unregister); +EXPORT_SYMBOL(i2o_driver_notify_controller_add_all); +EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all); +EXPORT_SYMBOL(i2o_driver_notify_device_add_all); +EXPORT_SYMBOL(i2o_driver_notify_device_remove_all); diff --git a/drivers/staging/i2o/exec-osm.c b/drivers/staging/i2o/exec-osm.c new file mode 100644 index 00000000000..16d857d5e65 --- /dev/null +++ b/drivers/staging/i2o/exec-osm.c @@ -0,0 +1,612 @@ +/* + * Executive OSM + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * 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 of the License, or (at your + * option) any later version. + * + * A lot of the I2O message side code from this is taken from the Red + * Creek RCPCI45 adapter driver by Red Creek Communications + * + * Fixes/additions: + * Philipp Rumpf + * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> + * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> + * Deepak Saxena <deepak@plexity.net> + * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> + * Alan Cox <alan@lxorguk.ukuu.org.uk>: + * Ported to Linux 2.5. + * Markus Lidel <Markus.Lidel@shadowconnect.com>: + * Minor fixes for 2.6. + * Markus Lidel <Markus.Lidel@shadowconnect.com>: + * Support for sysfs included. + */ + +#include <linux/module.h> +#include "i2o.h" +#include <linux/delay.h> +#include <linux/workqueue.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/sched.h> /* wait_event_interruptible_timeout() needs this */ +#include <asm/param.h> /* HZ */ +#include "core.h" + +#define OSM_NAME "exec-osm" + +struct i2o_driver i2o_exec_driver; + +/* global wait list for POST WAIT */ +static LIST_HEAD(i2o_exec_wait_list); + +/* Wait struct needed for POST WAIT */ +struct i2o_exec_wait { + wait_queue_head_t *wq; /* Pointer to Wait queue */ + struct i2o_dma dma; /* DMA buffers to free on failure */ + u32 tcntxt; /* transaction context from reply */ + int complete; /* 1 if reply received otherwise 0 */ + u32 m; /* message id */ + struct i2o_message *msg; /* pointer to the reply message */ + struct list_head list; /* node in global wait list */ + spinlock_t lock; /* lock before modifying */ +}; + +/* Work struct needed to handle LCT NOTIFY replies */ +struct i2o_exec_lct_notify_work { + struct work_struct work; /* work struct */ + struct i2o_controller *c; /* controller on which the LCT NOTIFY + was received */ +}; + +/* Exec OSM class handling definition */ +static struct i2o_class_id i2o_exec_class_id[] = { + {I2O_CLASS_EXECUTIVE}, + {I2O_CLASS_END} +}; + +/** + * i2o_exec_wait_alloc - Allocate a i2o_exec_wait struct an initialize it + * + * Allocate the i2o_exec_wait struct and initialize the wait. + * + * Returns i2o_exec_wait pointer on success or negative error code on + * failure. + */ +static struct i2o_exec_wait *i2o_exec_wait_alloc(void) +{ + struct i2o_exec_wait *wait; + + wait = kzalloc(sizeof(*wait), GFP_KERNEL); + if (!wait) + return NULL; + + INIT_LIST_HEAD(&wait->list); + spin_lock_init(&wait->lock); + + return wait; +}; + +/** + * i2o_exec_wait_free - Free an i2o_exec_wait struct + * @wait: I2O wait data which should be cleaned up + */ +static void i2o_exec_wait_free(struct i2o_exec_wait *wait) +{ + kfree(wait); +}; + +/** + * i2o_msg_post_wait_mem - Post and wait a message with DMA buffers + * @c: controller + * @msg: message to post + * @timeout: time in seconds to wait + * @dma: i2o_dma struct of the DMA buffer to free on failure + * + * This API allows an OSM to post a message and then be told whether or + * not the system received a successful reply. If the message times out + * then the value '-ETIMEDOUT' is returned. This is a special case. In + * this situation the message may (should) complete at an indefinite time + * in the future. When it completes it will use the memory buffer + * attached to the request. If -ETIMEDOUT is returned then the memory + * buffer must not be freed. Instead the event completion will free them + * for you. In all other cases the buffer are your problem. + * + * Returns 0 on success, negative error code on timeout or positive error + * code from reply. + */ +int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, + unsigned long timeout, struct i2o_dma *dma) +{ + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); + struct i2o_exec_wait *wait; + static u32 tcntxt = 0x80000000; + unsigned long flags; + int rc = 0; + + wait = i2o_exec_wait_alloc(); + if (!wait) { + i2o_msg_nop(c, msg); + return -ENOMEM; + } + + if (tcntxt == 0xffffffff) + tcntxt = 0x80000000; + + if (dma) + wait->dma = *dma; + + /* + * Fill in the message initiator context and transaction context. + * We will only use transaction contexts >= 0x80000000 for POST WAIT, + * so we could find a POST WAIT reply easier in the reply handler. + */ + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + wait->tcntxt = tcntxt++; + msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt); + + wait->wq = &wq; + /* + * we add elements to the head, because if a entry in the list will + * never be removed, we have to iterate over it every time + */ + list_add(&wait->list, &i2o_exec_wait_list); + + /* + * Post the message to the controller. At some point later it will + * return. If we time out before it returns then complete will be zero. + */ + i2o_msg_post(c, msg); + + wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ); + + spin_lock_irqsave(&wait->lock, flags); + + wait->wq = NULL; + + if (wait->complete) + rc = le32_to_cpu(wait->msg->body[0]) >> 24; + else { + /* + * We cannot remove it now. This is important. When it does + * terminate (which it must do if the controller has not + * died...) then it will otherwise scribble on stuff. + * + * FIXME: try abort message + */ + if (dma) + dma->virt = NULL; + + rc = -ETIMEDOUT; + } + + spin_unlock_irqrestore(&wait->lock, flags); + + if (rc != -ETIMEDOUT) { + i2o_flush_reply(c, wait->m); + i2o_exec_wait_free(wait); + } + + return rc; +}; + +/** + * i2o_msg_post_wait_complete - Reply to a i2o_msg_post request from IOP + * @c: I2O controller which answers + * @m: message id + * @msg: pointer to the I2O reply message + * @context: transaction context of request + * + * This function is called in interrupt context only. If the reply reached + * before the timeout, the i2o_exec_wait struct is filled with the message + * and the task will be waked up. The task is now responsible for returning + * the message m back to the controller! If the message reaches us after + * the timeout clean up the i2o_exec_wait struct (including allocated + * DMA buffer). + * + * Return 0 on success and if the message m should not be given back to the + * I2O controller, or >0 on success and if the message should be given back + * afterwords. Returns negative error code on failure. In this case the + * message must also be given back to the controller. + */ +static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, + struct i2o_message *msg, u32 context) +{ + struct i2o_exec_wait *wait, *tmp; + unsigned long flags; + int rc = 1; + + /* + * We need to search through the i2o_exec_wait_list to see if the given + * message is still outstanding. If not, it means that the IOP took + * longer to respond to the message than we had allowed and timer has + * already expired. Not much we can do about that except log it for + * debug purposes, increase timeout, and recompile. + */ + list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { + if (wait->tcntxt == context) { + spin_lock_irqsave(&wait->lock, flags); + + list_del(&wait->list); + + wait->m = m; + wait->msg = msg; + wait->complete = 1; + + if (wait->wq) + rc = 0; + else + rc = -1; + + spin_unlock_irqrestore(&wait->lock, flags); + + if (rc) { + struct device *dev; + + dev = &c->pdev->dev; + + pr_debug("%s: timedout reply received!\n", + c->name); + i2o_dma_free(dev, &wait->dma); + i2o_exec_wait_free(wait); + } else + wake_up_interruptible(wait->wq); + + return rc; + } + } + + osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, + context); + + return -1; +}; + +/** + * i2o_exec_show_vendor_id - Displays Vendor ID of controller + * @d: device of which the Vendor ID should be displayed + * @attr: device_attribute to display + * @buf: buffer into which the Vendor ID should be printed + * + * Returns number of bytes printed into buffer. + */ +static ssize_t i2o_exec_show_vendor_id(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct i2o_device *dev = to_i2o_device(d); + u16 id; + + if (!i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { + sprintf(buf, "0x%04x", le16_to_cpu(id)); + return strlen(buf) + 1; + } + + return 0; +}; + +/** + * i2o_exec_show_product_id - Displays Product ID of controller + * @d: device of which the Product ID should be displayed + * @attr: device_attribute to display + * @buf: buffer into which the Product ID should be printed + * + * Returns number of bytes printed into buffer. + */ +static ssize_t i2o_exec_show_product_id(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct i2o_device *dev = to_i2o_device(d); + u16 id; + + if (!i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { + sprintf(buf, "0x%04x", le16_to_cpu(id)); + return strlen(buf) + 1; + } + + return 0; +}; + +/* Exec-OSM device attributes */ +static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL); +static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); + +/** + * i2o_exec_probe - Called if a new I2O device (executive class) appears + * @dev: I2O device which should be probed + * + * Registers event notification for every event from Executive device. The + * return is always 0, because we want all devices of class Executive. + * + * Returns 0 on success. + */ +static int i2o_exec_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + int rc; + + rc = i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); + if (rc) goto err_out; + + rc = device_create_file(dev, &dev_attr_vendor_id); + if (rc) goto err_evtreg; + rc = device_create_file(dev, &dev_attr_product_id); + if (rc) goto err_vid; + + i2o_dev->iop->exec = i2o_dev; + + return 0; + +err_vid: + device_remove_file(dev, &dev_attr_vendor_id); +err_evtreg: + i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); +err_out: + return rc; +}; + +/** + * i2o_exec_remove - Called on I2O device removal + * @dev: I2O device which was removed + * + * Unregisters event notification from Executive I2O device. + * + * Returns 0 on success. + */ +static int i2o_exec_remove(struct device *dev) +{ + device_remove_file(dev, &dev_attr_product_id); + device_remove_file(dev, &dev_attr_vendor_id); + + i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); + + return 0; +}; + +#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES +/** + * i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request + * @c: I2O controller to which the request should be send + * @change_ind: change indicator + * + * This function sends a LCT NOTIFY request to the I2O controller with + * the change indicator change_ind. If the change_ind == 0 the controller + * replies immediately after the request. If change_ind > 0 the reply is + * send after change indicator of the LCT is > change_ind. + */ +static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) +{ + i2o_status_block *sb = c->status_block.virt; + struct device *dev; + struct i2o_message *msg; + + mutex_lock(&c->lct_lock); + + dev = &c->pdev->dev; + + if (i2o_dma_realloc(dev, &c->dlct, + le32_to_cpu(sb->expected_lct_size))) { + mutex_unlock(&c->lct_lock); + return -ENOMEM; + } + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) { + mutex_unlock(&c->lct_lock); + return PTR_ERR(msg); + } + + msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); + msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(0xffffffff); + msg->body[1] = cpu_to_le32(change_ind); + msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); + msg->body[3] = cpu_to_le32(c->dlct.phys); + + i2o_msg_post(c, msg); + + mutex_unlock(&c->lct_lock); + + return 0; +} +#endif + +/** + * i2o_exec_lct_modified - Called on LCT NOTIFY reply + * @_work: work struct for a specific controller + * + * This function handles asynchronus LCT NOTIFY replies. It parses the + * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY + * again, otherwise send LCT NOTIFY to get informed on next LCT change. + */ +static void i2o_exec_lct_modified(struct work_struct *_work) +{ + struct i2o_exec_lct_notify_work *work = + container_of(_work, struct i2o_exec_lct_notify_work, work); + u32 change_ind = 0; + struct i2o_controller *c = work->c; + + kfree(work); + + if (i2o_device_parse_lct(c) != -EAGAIN) + change_ind = c->lct->change_ind + 1; + +#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES + i2o_exec_lct_notify(c, change_ind); +#endif +}; + +/** + * i2o_exec_reply - I2O Executive reply handler + * @c: I2O controller from which the reply comes + * @m: message id + * @msg: pointer to the I2O reply message + * + * This function is always called from interrupt context. If a POST WAIT + * reply was received, pass it to the complete function. If a LCT NOTIFY + * reply was received, a new event is created to handle the update. + * + * Returns 0 on success and if the reply should not be flushed or > 0 + * on success and if the reply should be flushed. Returns negative error + * code on failure and if the reply should be flushed. + */ +static int i2o_exec_reply(struct i2o_controller *c, u32 m, + struct i2o_message *msg) +{ + u32 context; + + if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { + struct i2o_message __iomem *pmsg; + u32 pm; + + /* + * If Fail bit is set we must take the transaction context of + * the preserved message to find the right request again. + */ + + pm = le32_to_cpu(msg->body[3]); + pmsg = i2o_msg_in_to_virt(c, pm); + context = readl(&pmsg->u.s.tcntxt); + + i2o_report_status(KERN_INFO, "i2o_core", msg); + + /* Release the preserved msg */ + i2o_msg_nop_mfa(c, pm); + } else + context = le32_to_cpu(msg->u.s.tcntxt); + + if (context & 0x80000000) + return i2o_msg_post_wait_complete(c, m, msg, context); + + if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { + struct i2o_exec_lct_notify_work *work; + + pr_debug("%s: LCT notify received\n", c->name); + + work = kmalloc(sizeof(*work), GFP_ATOMIC); + if (!work) + return -ENOMEM; + + work->c = c; + + INIT_WORK(&work->work, i2o_exec_lct_modified); + queue_work(i2o_exec_driver.event_queue, &work->work); + return 1; + } + + /* + * If this happens, we want to dump the message to the syslog so + * it can be sent back to the card manufacturer by the end user + * to aid in debugging. + * + */ + printk(KERN_WARNING "%s: Unsolicited message reply sent to core!" + "Message dumped to syslog\n", c->name); + i2o_dump_message(msg); + + return -EFAULT; +} + +/** + * i2o_exec_event - Event handling function + * @work: Work item in occurring event + * + * Handles events send by the Executive device. At the moment does not do + * anything useful. + */ +static void i2o_exec_event(struct work_struct *work) +{ + struct i2o_event *evt = container_of(work, struct i2o_event, work); + + if (likely(evt->i2o_dev)) + osm_debug("Event received from device: %d\n", + evt->i2o_dev->lct_data.tid); + kfree(evt); +}; + +/** + * i2o_exec_lct_get - Get the IOP's Logical Configuration Table + * @c: I2O controller from which the LCT should be fetched + * + * Send a LCT NOTIFY request to the controller, and wait + * I2O_TIMEOUT_LCT_GET seconds until arrival of response. If the LCT is + * to large, retry it. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_exec_lct_get(struct i2o_controller *c) +{ + struct i2o_message *msg; + int i = 0; + int rc = -EAGAIN; + + for (i = 1; i <= I2O_LCT_GET_TRIES; i++) { + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = + cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->body[0] = cpu_to_le32(0xffffffff); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); + msg->body[3] = cpu_to_le32(c->dlct.phys); + + rc = i2o_msg_post_wait(c, msg, I2O_TIMEOUT_LCT_GET); + if (rc < 0) + break; + + rc = i2o_device_parse_lct(c); + if (rc != -EAGAIN) + break; + } + + return rc; +} + +/* Exec OSM driver struct */ +struct i2o_driver i2o_exec_driver = { + .name = OSM_NAME, + .reply = i2o_exec_reply, + .event = i2o_exec_event, + .classes = i2o_exec_class_id, + .driver = { + .probe = i2o_exec_probe, + .remove = i2o_exec_remove, + }, +}; + +/** + * i2o_exec_init - Registers the Exec OSM + * + * Registers the Exec OSM in the I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +int __init i2o_exec_init(void) +{ + return i2o_driver_register(&i2o_exec_driver); +}; + +/** + * i2o_exec_exit - Removes the Exec OSM + * + * Unregisters the Exec OSM from the I2O core. + */ +void i2o_exec_exit(void) +{ + i2o_driver_unregister(&i2o_exec_driver); +}; + +EXPORT_SYMBOL(i2o_msg_post_wait_mem); +EXPORT_SYMBOL(i2o_exec_lct_get); diff --git a/drivers/staging/i2o/i2o.h b/drivers/staging/i2o/i2o.h new file mode 100644 index 00000000000..d23c3c20b20 --- /dev/null +++ b/drivers/staging/i2o/i2o.h @@ -0,0 +1,988 @@ +/* + * I2O kernel space accessible structures/APIs + * + * (c) Copyright 1999, 2000 Red Hat Software + * + * 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 of the License, or (at your option) any later version. + * + ************************************************************************* + * + * This header file defined the I2O APIs/structures for use by + * the I2O kernel modules. + * + */ + +#ifndef _I2O_H +#define _I2O_H + +#include <linux/i2o-dev.h> + +/* How many different OSM's are we allowing */ +#define I2O_MAX_DRIVERS 8 + +#include <linux/pci.h> +#include <linux/bug.h> +#include <linux/dma-mapping.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/workqueue.h> /* work_struct */ +#include <linux/mempool.h> +#include <linux/mutex.h> +#include <linux/scatterlist.h> +#include <linux/semaphore.h> /* Needed for MUTEX init macros */ + +#include <asm/io.h> + +/* message queue empty */ +#define I2O_QUEUE_EMPTY 0xffffffff + +/* + * Cache strategies + */ + +/* The NULL strategy leaves everything up to the controller. This tends to be a + * pessimal but functional choice. + */ +#define CACHE_NULL 0 +/* Prefetch data when reading. We continually attempt to load the next 32 sectors + * into the controller cache. + */ +#define CACHE_PREFETCH 1 +/* Prefetch data when reading. We sometimes attempt to load the next 32 sectors + * into the controller cache. When an I/O is less <= 8K we assume its probably + * not sequential and don't prefetch (default) + */ +#define CACHE_SMARTFETCH 2 +/* Data is written to the cache and then out on to the disk. The I/O must be + * physically on the medium before the write is acknowledged (default without + * NVRAM) + */ +#define CACHE_WRITETHROUGH 17 +/* Data is written to the cache and then out on to the disk. The controller + * is permitted to write back the cache any way it wants. (default if battery + * backed NVRAM is present). It can be useful to set this for swap regardless of + * battery state. + */ +#define CACHE_WRITEBACK 18 +/* Optimise for under powered controllers, especially on RAID1 and RAID0. We + * write large I/O's directly to disk bypassing the cache to avoid the extra + * memory copy hits. Small writes are writeback cached + */ +#define CACHE_SMARTBACK 19 +/* Optimise for under powered controllers, especially on RAID1 and RAID0. We + * write large I/O's directly to disk bypassing the cache to avoid the extra + * memory copy hits. Small writes are writethrough cached. Suitable for devices + * lacking battery backup + */ +#define CACHE_SMARTTHROUGH 20 + +/* + * Ioctl structures + */ + +#define BLKI2OGRSTRAT _IOR('2', 1, int) +#define BLKI2OGWSTRAT _IOR('2', 2, int) +#define BLKI2OSRSTRAT _IOW('2', 3, int) +#define BLKI2OSWSTRAT _IOW('2', 4, int) + +/* + * I2O Function codes + */ + +/* + * Executive Class + */ +#define I2O_CMD_ADAPTER_ASSIGN 0xB3 +#define I2O_CMD_ADAPTER_READ 0xB2 +#define I2O_CMD_ADAPTER_RELEASE 0xB5 +#define I2O_CMD_BIOS_INFO_SET 0xA5 +#define I2O_CMD_BOOT_DEVICE_SET 0xA7 +#define I2O_CMD_CONFIG_VALIDATE 0xBB +#define I2O_CMD_CONN_SETUP 0xCA +#define I2O_CMD_DDM_DESTROY 0xB1 +#define I2O_CMD_DDM_ENABLE 0xD5 +#define I2O_CMD_DDM_QUIESCE 0xC7 +#define I2O_CMD_DDM_RESET 0xD9 +#define I2O_CMD_DDM_SUSPEND 0xAF +#define I2O_CMD_DEVICE_ASSIGN 0xB7 +#define I2O_CMD_DEVICE_RELEASE 0xB9 +#define I2O_CMD_HRT_GET 0xA8 +#define I2O_CMD_ADAPTER_CLEAR 0xBE +#define I2O_CMD_ADAPTER_CONNECT 0xC9 +#define I2O_CMD_ADAPTER_RESET 0xBD +#define I2O_CMD_LCT_NOTIFY 0xA2 +#define I2O_CMD_OUTBOUND_INIT 0xA1 +#define I2O_CMD_PATH_ENABLE 0xD3 +#define I2O_CMD_PATH_QUIESCE 0xC5 +#define I2O_CMD_PATH_RESET 0xD7 +#define I2O_CMD_STATIC_MF_CREATE 0xDD +#define I2O_CMD_STATIC_MF_RELEASE 0xDF +#define I2O_CMD_STATUS_GET 0xA0 +#define I2O_CMD_SW_DOWNLOAD 0xA9 +#define I2O_CMD_SW_UPLOAD 0xAB +#define I2O_CMD_SW_REMOVE 0xAD +#define I2O_CMD_SYS_ENABLE 0xD1 +#define I2O_CMD_SYS_MODIFY 0xC1 +#define I2O_CMD_SYS_QUIESCE 0xC3 +#define I2O_CMD_SYS_TAB_SET 0xA3 + +/* + * Utility Class + */ +#define I2O_CMD_UTIL_NOP 0x00 +#define I2O_CMD_UTIL_ABORT 0x01 +#define I2O_CMD_UTIL_CLAIM 0x09 +#define I2O_CMD_UTIL_RELEASE 0x0B +#define I2O_CMD_UTIL_PARAMS_GET 0x06 +#define I2O_CMD_UTIL_PARAMS_SET 0x05 +#define I2O_CMD_UTIL_EVT_REGISTER 0x13 +#define I2O_CMD_UTIL_EVT_ACK 0x14 +#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10 +#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D +#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F +#define I2O_CMD_UTIL_LOCK 0x17 +#define I2O_CMD_UTIL_LOCK_RELEASE 0x19 +#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15 + +/* + * SCSI Host Bus Adapter Class + */ +#define I2O_CMD_SCSI_EXEC 0x81 +#define I2O_CMD_SCSI_ABORT 0x83 +#define I2O_CMD_SCSI_BUSRESET 0x27 + +/* + * Bus Adapter Class + */ +#define I2O_CMD_BUS_ADAPTER_RESET 0x85 +#define I2O_CMD_BUS_RESET 0x87 +#define I2O_CMD_BUS_SCAN 0x89 +#define I2O_CMD_BUS_QUIESCE 0x8b + +/* + * Random Block Storage Class + */ +#define I2O_CMD_BLOCK_READ 0x30 +#define I2O_CMD_BLOCK_WRITE 0x31 +#define I2O_CMD_BLOCK_CFLUSH 0x37 +#define I2O_CMD_BLOCK_MLOCK 0x49 +#define I2O_CMD_BLOCK_MUNLOCK 0x4B +#define I2O_CMD_BLOCK_MMOUNT 0x41 +#define I2O_CMD_BLOCK_MEJECT 0x43 +#define I2O_CMD_BLOCK_POWER 0x70 + +#define I2O_CMD_PRIVATE 0xFF + +/* Command status values */ + +#define I2O_CMD_IN_PROGRESS 0x01 +#define I2O_CMD_REJECTED 0x02 +#define I2O_CMD_FAILED 0x03 +#define I2O_CMD_COMPLETED 0x04 + +/* I2O API function return values */ + +#define I2O_RTN_NO_ERROR 0 +#define I2O_RTN_NOT_INIT 1 +#define I2O_RTN_FREE_Q_EMPTY 2 +#define I2O_RTN_TCB_ERROR 3 +#define I2O_RTN_TRANSACTION_ERROR 4 +#define I2O_RTN_ADAPTER_ALREADY_INIT 5 +#define I2O_RTN_MALLOC_ERROR 6 +#define I2O_RTN_ADPTR_NOT_REGISTERED 7 +#define I2O_RTN_MSG_REPLY_TIMEOUT 8 +#define I2O_RTN_NO_STATUS 9 +#define I2O_RTN_NO_FIRM_VER 10 +#define I2O_RTN_NO_LINK_SPEED 11 + +/* Reply message status defines for all messages */ + +#define I2O_REPLY_STATUS_SUCCESS 0x00 +#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 +#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 +#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 +#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 +#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 +#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 +#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 +#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 +#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A +#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B +#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 + +/* Status codes and Error Information for Parameter functions */ + +#define I2O_PARAMS_STATUS_SUCCESS 0x00 +#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 +#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 +#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 +#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 +#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 +#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06 +#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07 +#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08 +#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09 +#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A +#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B +#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C +#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D +#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E +#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F +#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10 + +/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error + * messages: Table 3-2 Detailed Status Codes.*/ + +#define I2O_DSC_SUCCESS 0x0000 +#define I2O_DSC_BAD_KEY 0x0002 +#define I2O_DSC_TCL_ERROR 0x0003 +#define I2O_DSC_REPLY_BUFFER_FULL 0x0004 +#define I2O_DSC_NO_SUCH_PAGE 0x0005 +#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006 +#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007 +#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009 +#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A +#define I2O_DSC_DEVICE_LOCKED 0x000B +#define I2O_DSC_DEVICE_RESET 0x000C +#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D +#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E +#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F +#define I2O_DSC_INVALID_OFFSET 0x0010 +#define I2O_DSC_INVALID_PARAMETER 0x0011 +#define I2O_DSC_INVALID_REQUEST 0x0012 +#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013 +#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014 +#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015 +#define I2O_DSC_MISSING_PARAMETER 0x0016 +#define I2O_DSC_TIMEOUT 0x0017 +#define I2O_DSC_UNKNOWN_ERROR 0x0018 +#define I2O_DSC_UNKNOWN_FUNCTION 0x0019 +#define I2O_DSC_UNSUPPORTED_VERSION 0x001A +#define I2O_DSC_DEVICE_BUSY 0x001B +#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C + +/* DetailedStatusCode defines for Block Storage Operation: Table 6-7 Detailed + Status Codes.*/ + +#define I2O_BSA_DSC_SUCCESS 0x0000 +#define I2O_BSA_DSC_MEDIA_ERROR 0x0001 +#define I2O_BSA_DSC_ACCESS_ERROR 0x0002 +#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003 +#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004 +#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005 +#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006 +#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007 +#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008 +#define I2O_BSA_DSC_BUS_FAILURE 0x0009 +#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A +#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B +#define I2O_BSA_DSC_DEVICE_RESET 0x000C +#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D +#define I2O_BSA_DSC_TIMEOUT 0x000E + +/* FailureStatusCodes, Table 3-3 Message Failure Codes */ + +#define I2O_FSC_TRANSPORT_SERVICE_SUSPENDED 0x81 +#define I2O_FSC_TRANSPORT_SERVICE_TERMINATED 0x82 +#define I2O_FSC_TRANSPORT_CONGESTION 0x83 +#define I2O_FSC_TRANSPORT_FAILURE 0x84 +#define I2O_FSC_TRANSPORT_STATE_ERROR 0x85 +#define I2O_FSC_TRANSPORT_TIME_OUT 0x86 +#define I2O_FSC_TRANSPORT_ROUTING_FAILURE 0x87 +#define I2O_FSC_TRANSPORT_INVALID_VERSION 0x88 +#define I2O_FSC_TRANSPORT_INVALID_OFFSET 0x89 +#define I2O_FSC_TRANSPORT_INVALID_MSG_FLAGS 0x8A +#define I2O_FSC_TRANSPORT_FRAME_TOO_SMALL 0x8B +#define I2O_FSC_TRANSPORT_FRAME_TOO_LARGE 0x8C +#define I2O_FSC_TRANSPORT_INVALID_TARGET_ID 0x8D +#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_ID 0x8E +#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F +#define I2O_FSC_TRANSPORT_UNKNOWN_FAILURE 0xFF + +/* Device Claim Types */ +#define I2O_CLAIM_PRIMARY 0x01000000 +#define I2O_CLAIM_MANAGEMENT 0x02000000 +#define I2O_CLAIM_AUTHORIZED 0x03000000 +#define I2O_CLAIM_SECONDARY 0x04000000 + +/* Message header defines for VersionOffset */ +#define I2OVER15 0x0001 +#define I2OVER20 0x0002 + +/* Default is 1.5 */ +#define I2OVERSION I2OVER15 + +#define SGL_OFFSET_0 I2OVERSION +#define SGL_OFFSET_4 (0x0040 | I2OVERSION) +#define SGL_OFFSET_5 (0x0050 | I2OVERSION) +#define SGL_OFFSET_6 (0x0060 | I2OVERSION) +#define SGL_OFFSET_7 (0x0070 | I2OVERSION) +#define SGL_OFFSET_8 (0x0080 | I2OVERSION) +#define SGL_OFFSET_9 (0x0090 | I2OVERSION) +#define SGL_OFFSET_10 (0x00A0 | I2OVERSION) +#define SGL_OFFSET_11 (0x00B0 | I2OVERSION) +#define SGL_OFFSET_12 (0x00C0 | I2OVERSION) +#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION) + +/* Transaction Reply Lists (TRL) Control Word structure */ +#define TRL_SINGLE_FIXED_LENGTH 0x00 +#define TRL_SINGLE_VARIABLE_LENGTH 0x40 +#define TRL_MULTIPLE_FIXED_LENGTH 0x80 + + /* msg header defines for MsgFlags */ +#define MSG_STATIC 0x0100 +#define MSG_64BIT_CNTXT 0x0200 +#define MSG_MULTI_TRANS 0x1000 +#define MSG_FAIL 0x2000 +#define MSG_FINAL 0x4000 +#define MSG_REPLY 0x8000 + + /* minimum size msg */ +#define THREE_WORD_MSG_SIZE 0x00030000 +#define FOUR_WORD_MSG_SIZE 0x00040000 +#define FIVE_WORD_MSG_SIZE 0x00050000 +#define SIX_WORD_MSG_SIZE 0x00060000 +#define SEVEN_WORD_MSG_SIZE 0x00070000 +#define EIGHT_WORD_MSG_SIZE 0x00080000 +#define NINE_WORD_MSG_SIZE 0x00090000 +#define TEN_WORD_MSG_SIZE 0x000A0000 +#define ELEVEN_WORD_MSG_SIZE 0x000B0000 +#define I2O_MESSAGE_SIZE(x) ((x)<<16) + +/* special TID assignments */ +#define ADAPTER_TID 0 +#define HOST_TID 1 + +/* outbound queue defines */ +#define I2O_MAX_OUTBOUND_MSG_FRAMES 128 +#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ + +/* inbound queue definitions */ +#define I2O_MSG_INPOOL_MIN 32 +#define I2O_INBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ + +#define I2O_POST_WAIT_OK 0 +#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT + +#define I2O_CONTEXT_LIST_MIN_LENGTH 15 +#define I2O_CONTEXT_LIST_USED 0x01 +#define I2O_CONTEXT_LIST_DELETED 0x02 + +/* timeouts */ +#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE 15 +#define I2O_TIMEOUT_MESSAGE_GET 5 +#define I2O_TIMEOUT_RESET 30 +#define I2O_TIMEOUT_STATUS_GET 5 +#define I2O_TIMEOUT_LCT_GET 360 +#define I2O_TIMEOUT_SCSI_SCB_ABORT 240 + +/* retries */ +#define I2O_HRT_GET_TRIES 3 +#define I2O_LCT_GET_TRIES 3 + +/* defines for max_sectors and max_phys_segments */ +#define I2O_MAX_SECTORS 1024 +#define I2O_MAX_SECTORS_LIMITED 128 +#define I2O_MAX_PHYS_SEGMENTS BLK_MAX_SEGMENTS + +/* + * Message structures + */ +struct i2o_message { + union { + struct { + u8 version_offset; + u8 flags; + u16 size; + u32 target_tid:12; + u32 init_tid:12; + u32 function:8; + u32 icntxt; /* initiator context */ + u32 tcntxt; /* transaction context */ + } s; + u32 head[4]; + } u; + /* List follows */ + u32 body[0]; +}; + +/* MFA and I2O message used by mempool */ +struct i2o_msg_mfa { + u32 mfa; /* MFA returned by the controller */ + struct i2o_message msg; /* I2O message */ +}; + +/* + * Each I2O device entity has one of these. There is one per device. + */ +struct i2o_device { + i2o_lct_entry lct_data; /* Device LCT information */ + + struct i2o_controller *iop; /* Controlling IOP */ + struct list_head list; /* node in IOP devices list */ + + struct device device; + + struct mutex lock; /* device lock */ +}; + +/* + * Event structure provided to the event handling function + */ +struct i2o_event { + struct work_struct work; + struct i2o_device *i2o_dev; /* I2O device pointer from which the + event reply was initiated */ + u16 size; /* Size of data in 32-bit words */ + u32 tcntxt; /* Transaction context used at + registration */ + u32 event_indicator; /* Event indicator from reply */ + u32 data[0]; /* Event data from reply */ +}; + +/* + * I2O classes which could be handled by the OSM + */ +struct i2o_class_id { + u16 class_id:12; +}; + +/* + * I2O driver structure for OSMs + */ +struct i2o_driver { + char *name; /* OSM name */ + int context; /* Low 8 bits of the transaction info */ + struct i2o_class_id *classes; /* I2O classes that this OSM handles */ + + /* Message reply handler */ + int (*reply) (struct i2o_controller *, u32, struct i2o_message *); + + /* Event handler */ + work_func_t event; + + struct workqueue_struct *event_queue; /* Event queue */ + + struct device_driver driver; + + /* notification of changes */ + void (*notify_controller_add) (struct i2o_controller *); + void (*notify_controller_remove) (struct i2o_controller *); + void (*notify_device_add) (struct i2o_device *); + void (*notify_device_remove) (struct i2o_device *); + + struct semaphore lock; +}; + +/* + * Contains DMA mapped address information + */ +struct i2o_dma { + void *virt; + dma_addr_t phys; + size_t len; +}; + +/* + * Contains slab cache and mempool information + */ +struct i2o_pool { + char *name; + struct kmem_cache *slab; + mempool_t *mempool; +}; + +/* + * Contains IO mapped address information + */ +struct i2o_io { + void __iomem *virt; + unsigned long phys; + unsigned long len; +}; + +/* + * Context queue entry, used for 32-bit context on 64-bit systems + */ +struct i2o_context_list_element { + struct list_head list; + u32 context; + void *ptr; + unsigned long timestamp; +}; + +/* + * Each I2O controller has one of these objects + */ +struct i2o_controller { + char name[16]; + int unit; + int type; + + struct pci_dev *pdev; /* PCI device */ + + unsigned int promise:1; /* Promise controller */ + unsigned int adaptec:1; /* DPT / Adaptec controller */ + unsigned int raptor:1; /* split bar */ + unsigned int no_quiesce:1; /* dont quiesce before reset */ + unsigned int short_req:1; /* use small block sizes */ + unsigned int limit_sectors:1; /* limit number of sectors / request */ + unsigned int pae_support:1; /* controller has 64-bit SGL support */ + + struct list_head devices; /* list of I2O devices */ + struct list_head list; /* Controller list */ + + void __iomem *in_port; /* Inbout port address */ + void __iomem *out_port; /* Outbound port address */ + void __iomem *irq_status; /* Interrupt status register address */ + void __iomem *irq_mask; /* Interrupt mask register address */ + + struct i2o_dma status; /* IOP status block */ + + struct i2o_dma hrt; /* HW Resource Table */ + i2o_lct *lct; /* Logical Config Table */ + struct i2o_dma dlct; /* Temp LCT */ + struct mutex lct_lock; /* Lock for LCT updates */ + struct i2o_dma status_block; /* IOP status block */ + + struct i2o_io base; /* controller messaging unit */ + struct i2o_io in_queue; /* inbound message queue Host->IOP */ + struct i2o_dma out_queue; /* outbound message queue IOP->Host */ + + struct i2o_pool in_msg; /* mempool for inbound messages */ + + unsigned int battery:1; /* Has a battery backup */ + unsigned int io_alloc:1; /* An I/O resource was allocated */ + unsigned int mem_alloc:1; /* A memory resource was allocated */ + + struct resource io_resource; /* I/O resource allocated to the IOP */ + struct resource mem_resource; /* Mem resource allocated to the IOP */ + + struct device device; + struct i2o_device *exec; /* Executive */ +#if BITS_PER_LONG == 64 + spinlock_t context_list_lock; /* lock for context_list */ + atomic_t context_list_counter; /* needed for unique contexts */ + struct list_head context_list; /* list of context id's + and pointers */ +#endif + spinlock_t lock; /* lock for controller + configuration */ + void *driver_data[I2O_MAX_DRIVERS]; /* storage for drivers */ +}; + +/* + * I2O System table entry + * + * The system table contains information about all the IOPs in the + * system. It is sent to all IOPs so that they can create peer2peer + * connections between them. + */ +struct i2o_sys_tbl_entry { + u16 org_id; + u16 reserved1; + u32 iop_id:12; + u32 reserved2:20; + u16 seg_num:12; + u16 i2o_version:4; + u8 iop_state; + u8 msg_type; + u16 frame_size; + u16 reserved3; + u32 last_changed; + u32 iop_capabilities; + u32 inbound_low; + u32 inbound_high; +}; + +struct i2o_sys_tbl { + u8 num_entries; + u8 version; + u16 reserved1; + u32 change_ind; + u32 reserved2; + u32 reserved3; + struct i2o_sys_tbl_entry iops[0]; +}; + +extern struct list_head i2o_controllers; + +/* Message functions */ +extern struct i2o_message *i2o_msg_get_wait(struct i2o_controller *, int); +extern int i2o_msg_post_wait_mem(struct i2o_controller *, struct i2o_message *, + unsigned long, struct i2o_dma *); + +/* IOP functions */ +extern int i2o_status_get(struct i2o_controller *); + +extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int, + u32); +extern struct i2o_device *i2o_iop_find_device(struct i2o_controller *, u16); +extern struct i2o_controller *i2o_find_iop(int); + +/* Functions needed for handling 64-bit pointers in 32-bit context */ +#if BITS_PER_LONG == 64 +extern u32 i2o_cntxt_list_add(struct i2o_controller *, void *); +extern void *i2o_cntxt_list_get(struct i2o_controller *, u32); +extern u32 i2o_cntxt_list_remove(struct i2o_controller *, void *); +extern u32 i2o_cntxt_list_get_ptr(struct i2o_controller *, void *); + +static inline u32 i2o_ptr_low(void *ptr) +{ + return (u32) (u64) ptr; +}; + +static inline u32 i2o_ptr_high(void *ptr) +{ + return (u32) ((u64) ptr >> 32); +}; + +static inline u32 i2o_dma_low(dma_addr_t dma_addr) +{ + return (u32) (u64) dma_addr; +}; + +static inline u32 i2o_dma_high(dma_addr_t dma_addr) +{ + return (u32) ((u64) dma_addr >> 32); +}; +#else +static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; + +static inline void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) +{ + return (void *)context; +}; + +static inline u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; + +static inline u32 i2o_cntxt_list_get_ptr(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; + +static inline u32 i2o_ptr_low(void *ptr) +{ + return (u32) ptr; +}; + +static inline u32 i2o_ptr_high(void *ptr) +{ + return 0; +}; + +static inline u32 i2o_dma_low(dma_addr_t dma_addr) +{ + return (u32) dma_addr; +}; + +static inline u32 i2o_dma_high(dma_addr_t dma_addr) +{ + return 0; +}; +#endif + +extern u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size); +extern dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, + size_t size, + enum dma_data_direction direction, + u32 ** sg_ptr); +extern int i2o_dma_map_sg(struct i2o_controller *c, + struct scatterlist *sg, int sg_count, + enum dma_data_direction direction, + u32 ** sg_ptr); +extern int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len); +extern void i2o_dma_free(struct device *dev, struct i2o_dma *addr); +extern int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, + size_t len); +extern int i2o_pool_alloc(struct i2o_pool *pool, const char *name, + size_t size, int min_nr); +extern void i2o_pool_free(struct i2o_pool *pool); +/* I2O driver (OSM) functions */ +extern int i2o_driver_register(struct i2o_driver *); +extern void i2o_driver_unregister(struct i2o_driver *); + +/** + * i2o_driver_notify_controller_add - Send notification of added controller + * @drv: I2O driver + * @c: I2O controller + * + * Send notification of added controller to a single registered driver. + */ +static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv, + struct i2o_controller *c) +{ + if (drv->notify_controller_add) + drv->notify_controller_add(c); +}; + +/** + * i2o_driver_notify_controller_remove - Send notification of removed controller + * @drv: I2O driver + * @c: I2O controller + * + * Send notification of removed controller to a single registered driver. + */ +static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv, + struct i2o_controller *c) +{ + if (drv->notify_controller_remove) + drv->notify_controller_remove(c); +}; + +/** + * i2o_driver_notify_device_add - Send notification of added device + * @drv: I2O driver + * @i2o_dev: the added i2o_device + * + * Send notification of added device to a single registered driver. + */ +static inline void i2o_driver_notify_device_add(struct i2o_driver *drv, + struct i2o_device *i2o_dev) +{ + if (drv->notify_device_add) + drv->notify_device_add(i2o_dev); +}; + +/** + * i2o_driver_notify_device_remove - Send notification of removed device + * @drv: I2O driver + * @i2o_dev: the added i2o_device + * + * Send notification of removed device to a single registered driver. + */ +static inline void i2o_driver_notify_device_remove(struct i2o_driver *drv, + struct i2o_device *i2o_dev) +{ + if (drv->notify_device_remove) + drv->notify_device_remove(i2o_dev); +}; + +extern void i2o_driver_notify_controller_add_all(struct i2o_controller *); +extern void i2o_driver_notify_controller_remove_all(struct i2o_controller *); +extern void i2o_driver_notify_device_add_all(struct i2o_device *); +extern void i2o_driver_notify_device_remove_all(struct i2o_device *); + +/* I2O device functions */ +extern int i2o_device_claim(struct i2o_device *); +extern int i2o_device_claim_release(struct i2o_device *); + +/* Exec OSM functions */ +extern int i2o_exec_lct_get(struct i2o_controller *); + +/* device / driver / kobject conversion functions */ +#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver) +#define to_i2o_device(dev) container_of(dev, struct i2o_device, device) +#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device) + +/** + * i2o_out_to_virt - Turn an I2O message to a virtual address + * @c: controller + * @m: message engine value + * + * Turn a receive message from an I2O controller bus address into + * a Linux virtual address. The shared page frame is a linear block + * so we simply have to shift the offset. This function does not + * work for sender side messages as they are ioremap objects + * provided by the I2O controller. + */ +static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c, + u32 m) +{ + BUG_ON(m < c->out_queue.phys + || m >= c->out_queue.phys + c->out_queue.len); + + return c->out_queue.virt + (m - c->out_queue.phys); +}; + +/** + * i2o_msg_in_to_virt - Turn an I2O message to a virtual address + * @c: controller + * @m: message engine value + * + * Turn a send message from an I2O controller bus address into + * a Linux virtual address. The shared page frame is a linear block + * so we simply have to shift the offset. This function does not + * work for receive side messages as they are kmalloc objects + * in a different pool. + */ +static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct + i2o_controller *c, + u32 m) +{ + return c->in_queue.virt + m; +}; + +/** + * i2o_msg_get - obtain an I2O message from the IOP + * @c: I2O controller + * + * This function tries to get a message frame. If no message frame is + * available do not wait until one is available (see also i2o_msg_get_wait). + * The returned pointer to the message frame is not in I/O memory, it is + * allocated from a mempool. But because a MFA is allocated from the + * controller too it is guaranteed that i2o_msg_post() will never fail. + * + * On a success a pointer to the message frame is returned. If the message + * queue is empty -EBUSY is returned and if no memory is available -ENOMEM + * is returned. + */ +static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c) +{ + struct i2o_msg_mfa *mmsg = mempool_alloc(c->in_msg.mempool, GFP_ATOMIC); + if (!mmsg) + return ERR_PTR(-ENOMEM); + + mmsg->mfa = readl(c->in_port); + if (unlikely(mmsg->mfa >= c->in_queue.len)) { + u32 mfa = mmsg->mfa; + + mempool_free(mmsg, c->in_msg.mempool); + + if (mfa == I2O_QUEUE_EMPTY) + return ERR_PTR(-EBUSY); + return ERR_PTR(-EFAULT); + } + + return &mmsg->msg; +}; + +/** + * i2o_msg_post - Post I2O message to I2O controller + * @c: I2O controller to which the message should be send + * @msg: message returned by i2o_msg_get() + * + * Post the message to the I2O controller and return immediately. + */ +static inline void i2o_msg_post(struct i2o_controller *c, + struct i2o_message *msg) +{ + struct i2o_msg_mfa *mmsg; + + mmsg = container_of(msg, struct i2o_msg_mfa, msg); + memcpy_toio(i2o_msg_in_to_virt(c, mmsg->mfa), msg, + (le32_to_cpu(msg->u.head[0]) >> 16) << 2); + writel(mmsg->mfa, c->in_port); + mempool_free(mmsg, c->in_msg.mempool); +}; + +/** + * i2o_msg_post_wait - Post and wait a message and wait until return + * @c: controller + * @msg: message to post + * @timeout: time in seconds to wait + * + * This API allows an OSM to post a message and then be told whether or + * not the system received a successful reply. If the message times out + * then the value '-ETIMEDOUT' is returned. + * + * Returns 0 on success or negative error code on failure. + */ +static inline int i2o_msg_post_wait(struct i2o_controller *c, + struct i2o_message *msg, + unsigned long timeout) +{ + return i2o_msg_post_wait_mem(c, msg, timeout, NULL); +}; + +/** + * i2o_msg_nop_mfa - Returns a fetched MFA back to the controller + * @c: I2O controller from which the MFA was fetched + * @mfa: MFA which should be returned + * + * This function must be used for preserved messages, because i2o_msg_nop() + * also returns the allocated memory back to the msg_pool mempool. + */ +static inline void i2o_msg_nop_mfa(struct i2o_controller *c, u32 mfa) +{ + struct i2o_message __iomem *msg; + u32 nop[3] = { + THREE_WORD_MSG_SIZE | SGL_OFFSET_0, + I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, + 0x00000000 + }; + + msg = i2o_msg_in_to_virt(c, mfa); + memcpy_toio(msg, nop, sizeof(nop)); + writel(mfa, c->in_port); +}; + +/** + * i2o_msg_nop - Returns a message which is not used + * @c: I2O controller from which the message was created + * @msg: message which should be returned + * + * If you fetch a message via i2o_msg_get, and can't use it, you must + * return the message with this function. Otherwise the MFA is lost as well + * as the allocated memory from the mempool. + */ +static inline void i2o_msg_nop(struct i2o_controller *c, + struct i2o_message *msg) +{ + struct i2o_msg_mfa *mmsg; + mmsg = container_of(msg, struct i2o_msg_mfa, msg); + + i2o_msg_nop_mfa(c, mmsg->mfa); + mempool_free(mmsg, c->in_msg.mempool); +}; + +/** + * i2o_flush_reply - Flush reply from I2O controller + * @c: I2O controller + * @m: the message identifier + * + * The I2O controller must be informed that the reply message is not needed + * anymore. If you forget to flush the reply, the message frame can't be + * used by the controller anymore and is therefore lost. + */ +static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) +{ + writel(m, c->out_port); +}; + +/* + * Endian handling wrapped into the macro - keeps the core code + * cleaner. + */ + +#define i2o_raw_writel(val, mem) __raw_writel(cpu_to_le32(val), mem) + +extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int); +extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int, + void *, int); + +/* debugging and troubleshooting/diagnostic helpers. */ +#define osm_printk(level, format, arg...) \ + printk(level "%s: " format, OSM_NAME , ## arg) + +#ifdef DEBUG +#define osm_debug(format, arg...) \ + osm_printk(KERN_DEBUG, format , ## arg) +#else +#define osm_debug(format, arg...) \ + do { } while (0) +#endif + +#define osm_err(format, arg...) \ + osm_printk(KERN_ERR, format , ## arg) +#define osm_info(format, arg...) \ + osm_printk(KERN_INFO, format , ## arg) +#define osm_warn(format, arg...) \ + osm_printk(KERN_WARNING, format , ## arg) + +/* debugging functions */ +extern void i2o_report_status(const char *, const char *, struct i2o_message *); +extern void i2o_dump_message(struct i2o_message *); +extern void i2o_dump_hrt(struct i2o_controller *c); +extern void i2o_debug_state(struct i2o_controller *c); + +#endif /* _I2O_H */ diff --git a/drivers/staging/i2o/i2o_block.c b/drivers/staging/i2o/i2o_block.c new file mode 100644 index 00000000000..0a13c64ce00 --- /dev/null +++ b/drivers/staging/i2o/i2o_block.c @@ -0,0 +1,1228 @@ +/* + * Block OSM + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * 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 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * For the purpose of avoiding doubt the preferred form of the work + * for making modifications shall be a standards compliant form such + * gzipped tar and not one requiring a proprietary or patent encumbered + * tool to unpack. + * + * Fixes/additions: + * Steve Ralston: + * Multiple device handling error fixes, + * Added a queue depth. + * Alan Cox: + * FC920 has an rmw bug. Dont or in the end marker. + * Removed queue walk, fixed for 64bitness. + * Rewrote much of the code over time + * Added indirect block lists + * Handle 64K limits on many controllers + * Don't use indirects on the Promise (breaks) + * Heavily chop down the queue depths + * Deepak Saxena: + * Independent queues per IOP + * Support for dynamic device creation/deletion + * Code cleanup + * Support for larger I/Os through merge* functions + * (taken from DAC960 driver) + * Boji T Kannanthanam: + * Set the I2O Block devices to be detected in increasing + * order of TIDs during boot. + * Search and set the I2O block device that we boot off + * from as the first device to be claimed (as /dev/i2o/hda) + * Properly attach/detach I2O gendisk structure from the + * system gendisk list. The I2O block devices now appear in + * /proc/partitions. + * Markus Lidel <Markus.Lidel@shadowconnect.com>: + * Minor bugfixes for 2.6. + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include "i2o.h" +#include <linux/mutex.h> + +#include <linux/mempool.h> + +#include <linux/genhd.h> +#include <linux/blkdev.h> +#include <linux/hdreg.h> + +#include <scsi/scsi.h> + +#include "i2o_block.h" + +#define OSM_NAME "block-osm" +#define OSM_VERSION "1.325" +#define OSM_DESCRIPTION "I2O Block Device OSM" + +static DEFINE_MUTEX(i2o_block_mutex); +static struct i2o_driver i2o_block_driver; + +/* global Block OSM request mempool */ +static struct i2o_block_mempool i2o_blk_req_pool; + +/* Block OSM class handling definition */ +static struct i2o_class_id i2o_block_class_id[] = { + {I2O_CLASS_RANDOM_BLOCK_STORAGE}, + {I2O_CLASS_END} +}; + +/** + * i2o_block_device_free - free the memory of the I2O Block device + * @dev: I2O Block device, which should be cleaned up + * + * Frees the request queue, gendisk and the i2o_block_device structure. + */ +static void i2o_block_device_free(struct i2o_block_device *dev) +{ + blk_cleanup_queue(dev->gd->queue); + + put_disk(dev->gd); + + kfree(dev); +}; + +/** + * i2o_block_remove - remove the I2O Block device from the system again + * @dev: I2O Block device which should be removed + * + * Remove gendisk from system and free all allocated memory. + * + * Always returns 0. + */ +static int i2o_block_remove(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev); + + osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid, + i2o_blk_dev->gd->disk_name); + + i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0); + + del_gendisk(i2o_blk_dev->gd); + + dev_set_drvdata(dev, NULL); + + i2o_device_claim_release(i2o_dev); + + i2o_block_device_free(i2o_blk_dev); + + return 0; +}; + +/** + * i2o_block_device flush - Flush all dirty data of I2O device dev + * @dev: I2O device which should be flushed + * + * Flushes all dirty data on device dev. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_flush(struct i2o_device *dev) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(60 << 16); + osm_debug("Flushing...\n"); + + return i2o_msg_post_wait(dev->iop, msg, 60); +}; + +/** + * i2o_block_device_mount - Mount (load) the media of device dev + * @dev: I2O device which should receive the mount request + * @media_id: Media Identifier + * + * Load a media into drive. Identifier should be set to -1, because the + * spec does not support any other value. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(-1); + msg->body[1] = cpu_to_le32(0x00000000); + osm_debug("Mounting...\n"); + + return i2o_msg_post_wait(dev->iop, msg, 2); +}; + +/** + * i2o_block_device_lock - Locks the media of device dev + * @dev: I2O device which should receive the lock request + * @media_id: Media Identifier + * + * Lock media of device dev to prevent removal. The media identifier + * should be set to -1, because the spec does not support any other value. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(-1); + osm_debug("Locking...\n"); + + return i2o_msg_post_wait(dev->iop, msg, 2); +}; + +/** + * i2o_block_device_unlock - Unlocks the media of device dev + * @dev: I2O device which should receive the unlocked request + * @media_id: Media Identifier + * + * Unlocks the media in device dev. The media identifier should be set to + * -1, because the spec does not support any other value. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(media_id); + osm_debug("Unlocking...\n"); + + return i2o_msg_post_wait(dev->iop, msg, 2); +}; + +/** + * i2o_block_device_power - Power management for device dev + * @dev: I2O device which should receive the power management request + * @op: Operation to send + * + * Send a power management request to the device dev. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_power(struct i2o_block_device *dev, u8 op) +{ + struct i2o_device *i2o_dev = dev->i2o_dev; + struct i2o_controller *c = i2o_dev->iop; + struct i2o_message *msg; + int rc; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(op << 24); + osm_debug("Power...\n"); + + rc = i2o_msg_post_wait(c, msg, 60); + if (!rc) + dev->power = op; + + return rc; +}; + +/** + * i2o_block_request_alloc - Allocate an I2O block request struct + * + * Allocates an I2O block request struct and initialize the list. + * + * Returns a i2o_block_request pointer on success or negative error code + * on failure. + */ +static inline struct i2o_block_request *i2o_block_request_alloc(void) +{ + struct i2o_block_request *ireq; + + ireq = mempool_alloc(i2o_blk_req_pool.pool, GFP_ATOMIC); + if (!ireq) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&ireq->queue); + sg_init_table(ireq->sg_table, I2O_MAX_PHYS_SEGMENTS); + + return ireq; +}; + +/** + * i2o_block_request_free - Frees a I2O block request + * @ireq: I2O block request which should be freed + * + * Frees the allocated memory (give it back to the request mempool). + */ +static inline void i2o_block_request_free(struct i2o_block_request *ireq) +{ + mempool_free(ireq, i2o_blk_req_pool.pool); +}; + +/** + * i2o_block_sglist_alloc - Allocate the SG list and map it + * @c: I2O controller to which the request belongs + * @ireq: I2O block request + * @mptr: message body pointer + * + * Builds the SG list and map it to be accessible by the controller. + * + * Returns 0 on failure or 1 on success. + */ +static inline int i2o_block_sglist_alloc(struct i2o_controller *c, + struct i2o_block_request *ireq, + u32 ** mptr) +{ + int nents; + enum dma_data_direction direction; + + ireq->dev = &c->pdev->dev; + nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table); + + if (rq_data_dir(ireq->req) == READ) + direction = PCI_DMA_FROMDEVICE; + else + direction = PCI_DMA_TODEVICE; + + ireq->sg_nents = nents; + + return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr); +}; + +/** + * i2o_block_sglist_free - Frees the SG list + * @ireq: I2O block request from which the SG should be freed + * + * Frees the SG list from the I2O block request. + */ +static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) +{ + enum dma_data_direction direction; + + if (rq_data_dir(ireq->req) == READ) + direction = PCI_DMA_FROMDEVICE; + else + direction = PCI_DMA_TODEVICE; + + dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction); +}; + +/** + * i2o_block_prep_req_fn - Allocates I2O block device specific struct + * @q: request queue for the request + * @req: the request to prepare + * + * Allocate the necessary i2o_block_request struct and connect it to + * the request. This is needed that we not lose the SG list later on. + * + * Returns BLKPREP_OK on success or BLKPREP_DEFER on failure. + */ +static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) +{ + struct i2o_block_device *i2o_blk_dev = q->queuedata; + struct i2o_block_request *ireq; + + if (unlikely(!i2o_blk_dev)) { + osm_err("block device already removed\n"); + return BLKPREP_KILL; + } + + /* connect the i2o_block_request to the request */ + if (!req->special) { + ireq = i2o_block_request_alloc(); + if (IS_ERR(ireq)) { + osm_debug("unable to allocate i2o_block_request!\n"); + return BLKPREP_DEFER; + } + + ireq->i2o_blk_dev = i2o_blk_dev; + req->special = ireq; + ireq->req = req; + } + /* do not come back here */ + req->cmd_flags |= REQ_DONTPREP; + + return BLKPREP_OK; +}; + +/** + * i2o_block_delayed_request_fn - delayed request queue function + * @work: the delayed request with the queue to start + * + * If the request queue is stopped for a disk, and there is no open + * request, a new event is created, which calls this function to start + * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never + * be started again. + */ +static void i2o_block_delayed_request_fn(struct work_struct *work) +{ + struct i2o_block_delayed_request *dreq = + container_of(work, struct i2o_block_delayed_request, + work.work); + struct request_queue *q = dreq->queue; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + kfree(dreq); +}; + +/** + * i2o_block_end_request - Post-processing of completed commands + * @req: request which should be completed + * @error: 0 for success, < 0 for error + * @nr_bytes: number of bytes to complete + * + * Mark the request as complete. The lock must not be held when entering. + * + */ +static void i2o_block_end_request(struct request *req, int error, + int nr_bytes) +{ + struct i2o_block_request *ireq = req->special; + struct i2o_block_device *dev = ireq->i2o_blk_dev; + struct request_queue *q = req->q; + unsigned long flags; + + if (blk_end_request(req, error, nr_bytes)) + if (error) + blk_end_request_all(req, -EIO); + + spin_lock_irqsave(q->queue_lock, flags); + + if (likely(dev)) { + dev->open_queue_depth--; + list_del(&ireq->queue); + } + + blk_start_queue(q); + + spin_unlock_irqrestore(q->queue_lock, flags); + + i2o_block_sglist_free(ireq); + i2o_block_request_free(ireq); +}; + +/** + * i2o_block_reply - Block OSM reply handler. + * @c: I2O controller from which the message arrives + * @m: message id of reply + * @msg: the actual I2O message reply + * + * This function gets all the message replies. + * + */ +static int i2o_block_reply(struct i2o_controller *c, u32 m, + struct i2o_message *msg) +{ + struct request *req; + int error = 0; + + req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); + if (unlikely(!req)) { + osm_err("NULL reply received!\n"); + return -1; + } + + /* + * Lets see what is cooking. We stuffed the + * request in the context. + */ + + if ((le32_to_cpu(msg->body[0]) >> 24) != 0) { + u32 status = le32_to_cpu(msg->body[0]); + /* + * Device not ready means two things. One is that the + * the thing went offline (but not a removal media) + * + * The second is that you have a SuperTrak 100 and the + * firmware got constipated. Unlike standard i2o card + * setups the supertrak returns an error rather than + * blocking for the timeout in these cases. + * + * Don't stick a supertrak100 into cache aggressive modes + */ + + osm_err("TID %03x error status: 0x%02x, detailed status: " + "0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff), + status >> 24, status & 0xffff); + + req->errors++; + + error = -EIO; + } + + i2o_block_end_request(req, error, le32_to_cpu(msg->body[1])); + + return 1; +}; + +static void i2o_block_event(struct work_struct *work) +{ + struct i2o_event *evt = container_of(work, struct i2o_event, work); + osm_debug("event received\n"); + kfree(evt); +}; + +/* + * SCSI-CAM for ioctl geometry mapping + * Duplicated with SCSI - this should be moved into somewhere common + * perhaps genhd ? + * + * LBA -> CHS mapping table taken from: + * + * "Incorporating the I2O Architecture into BIOS for Intel Architecture + * Platforms" + * + * This is an I2O document that is only available to I2O members, + * not developers. + * + * From my understanding, this is how all the I2O cards do this + * + * Disk Size | Sectors | Heads | Cylinders + * ---------------+---------+-------+------------------- + * 1 < X <= 528M | 63 | 16 | X/(63 * 16 * 512) + * 528M < X <= 1G | 63 | 32 | X/(63 * 32 * 512) + * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) + * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) + * + */ +#define BLOCK_SIZE_528M 1081344 +#define BLOCK_SIZE_1G 2097152 +#define BLOCK_SIZE_21G 4403200 +#define BLOCK_SIZE_42G 8806400 +#define BLOCK_SIZE_84G 17612800 + +static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, + unsigned char *hds, unsigned char *secs) +{ + unsigned long heads, sectors, cylinders; + + sectors = 63L; /* Maximize sectors per track */ + if (capacity <= BLOCK_SIZE_528M) + heads = 16; + else if (capacity <= BLOCK_SIZE_1G) + heads = 32; + else if (capacity <= BLOCK_SIZE_21G) + heads = 64; + else if (capacity <= BLOCK_SIZE_42G) + heads = 128; + else + heads = 255; + + cylinders = (unsigned long)capacity / (heads * sectors); + + *cyls = (unsigned short)cylinders; /* Stuff return values */ + *secs = (unsigned char)sectors; + *hds = (unsigned char)heads; +} + +/** + * i2o_block_open - Open the block device + * @bdev: block device being opened + * @mode: file open mode + * + * Power up the device, mount and lock the media. This function is called, + * if the block device is opened for access. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_open(struct block_device *bdev, fmode_t mode) +{ + struct i2o_block_device *dev = bdev->bd_disk->private_data; + + if (!dev->i2o_dev) + return -ENODEV; + + mutex_lock(&i2o_block_mutex); + if (dev->power > 0x1f) + i2o_block_device_power(dev, 0x02); + + i2o_block_device_mount(dev->i2o_dev, -1); + + i2o_block_device_lock(dev->i2o_dev, -1); + + osm_debug("Ready.\n"); + mutex_unlock(&i2o_block_mutex); + + return 0; +}; + +/** + * i2o_block_release - Release the I2O block device + * @disk: gendisk device being released + * @mode: file open mode + * + * Unlock and unmount the media, and power down the device. Gets called if + * the block device is closed. + */ +static void i2o_block_release(struct gendisk *disk, fmode_t mode) +{ + struct i2o_block_device *dev = disk->private_data; + u8 operation; + + /* + * This is to deal with the case of an application + * opening a device and then the device disappears while + * it's in use, and then the application tries to release + * it. ex: Unmounting a deleted RAID volume at reboot. + * If we send messages, it will just cause FAILs since + * the TID no longer exists. + */ + if (!dev->i2o_dev) + return; + + mutex_lock(&i2o_block_mutex); + i2o_block_device_flush(dev->i2o_dev); + + i2o_block_device_unlock(dev->i2o_dev, -1); + + if (dev->flags & (1 << 3 | 1 << 4)) /* Removable */ + operation = 0x21; + else + operation = 0x24; + + i2o_block_device_power(dev, operation); + mutex_unlock(&i2o_block_mutex); +} + +static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + i2o_block_biosparam(get_capacity(bdev->bd_disk), + &geo->cylinders, &geo->heads, &geo->sectors); + return 0; +} + +/** + * i2o_block_ioctl - Issue device specific ioctl calls. + * @bdev: block device being opened + * @mode: file open mode + * @cmd: ioctl command + * @arg: arg + * + * Handles ioctl request for the block device. + * + * Return 0 on success or negative error on failure. + */ +static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + struct gendisk *disk = bdev->bd_disk; + struct i2o_block_device *dev = disk->private_data; + int ret = -ENOTTY; + + /* Anyone capable of this syscall can do *real bad* things */ + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + mutex_lock(&i2o_block_mutex); + switch (cmd) { + case BLKI2OGRSTRAT: + ret = put_user(dev->rcache, (int __user *)arg); + break; + case BLKI2OGWSTRAT: + ret = put_user(dev->wcache, (int __user *)arg); + break; + case BLKI2OSRSTRAT: + ret = -EINVAL; + if (arg < 0 || arg > CACHE_SMARTFETCH) + break; + dev->rcache = arg; + ret = 0; + break; + case BLKI2OSWSTRAT: + ret = -EINVAL; + if (arg != 0 + && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) + break; + dev->wcache = arg; + ret = 0; + break; + } + mutex_unlock(&i2o_block_mutex); + + return ret; +}; + +/** + * i2o_block_check_events - Have we seen a media change? + * @disk: gendisk which should be verified + * @clearing: events being cleared + * + * Verifies if the media has changed. + * + * Returns 1 if the media was changed or 0 otherwise. + */ +static unsigned int i2o_block_check_events(struct gendisk *disk, + unsigned int clearing) +{ + struct i2o_block_device *p = disk->private_data; + + if (p->media_change_flag) { + p->media_change_flag = 0; + return DISK_EVENT_MEDIA_CHANGE; + } + return 0; +} + +/** + * i2o_block_transfer - Transfer a request to/from the I2O controller + * @req: the request which should be transferred + * + * This function converts the request into a I2O message. The necessary + * DMA buffers are allocated and after everything is setup post the message + * to the I2O controller. No cleanup is done by this function. It is done + * on the interrupt side when the reply arrives. + * + * Return 0 on success or negative error code on failure. + */ +static int i2o_block_transfer(struct request *req) +{ + struct i2o_block_device *dev = req->rq_disk->private_data; + struct i2o_controller *c; + u32 tid; + struct i2o_message *msg; + u32 *mptr; + struct i2o_block_request *ireq = req->special; + u32 tcntxt; + u32 sgl_offset = SGL_OFFSET_8; + u32 ctl_flags = 0x00000000; + int rc; + u32 cmd; + + if (unlikely(!dev->i2o_dev)) { + osm_err("transfer to removed drive\n"); + rc = -ENODEV; + goto exit; + } + + tid = dev->i2o_dev->lct_data.tid; + c = dev->i2o_dev->iop; + + msg = i2o_msg_get(c); + if (IS_ERR(msg)) { + rc = PTR_ERR(msg); + goto exit; + } + + tcntxt = i2o_cntxt_list_add(c, req); + if (!tcntxt) { + rc = -ENOMEM; + goto nop_msg; + } + + msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context); + msg->u.s.tcntxt = cpu_to_le32(tcntxt); + + mptr = &msg->body[0]; + + if (rq_data_dir(req) == READ) { + cmd = I2O_CMD_BLOCK_READ << 24; + + switch (dev->rcache) { + case CACHE_PREFETCH: + ctl_flags = 0x201F0008; + break; + + case CACHE_SMARTFETCH: + if (blk_rq_sectors(req) > 16) + ctl_flags = 0x201F0008; + else + ctl_flags = 0x001F0000; + break; + + default: + break; + } + } else { + cmd = I2O_CMD_BLOCK_WRITE << 24; + + switch (dev->wcache) { + case CACHE_WRITETHROUGH: + ctl_flags = 0x001F0008; + break; + case CACHE_WRITEBACK: + ctl_flags = 0x001F0010; + break; + case CACHE_SMARTBACK: + if (blk_rq_sectors(req) > 16) + ctl_flags = 0x001F0004; + else + ctl_flags = 0x001F0010; + break; + case CACHE_SMARTTHROUGH: + if (blk_rq_sectors(req) > 16) + ctl_flags = 0x001F0004; + else + ctl_flags = 0x001F0010; + default: + break; + } + } + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u8 cmd[10]; + u32 scsi_flags; + u16 hwsec; + + hwsec = queue_logical_block_size(req->q) >> KERNEL_SECTOR_SHIFT; + memset(cmd, 0, 10); + + sgl_offset = SGL_OFFSET_12; + + msg->u.head[1] = + cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid); + + *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); + *mptr++ = cpu_to_le32(tid); + + /* + * ENABLE_DISCONNECT + * SIMPLE_TAG + * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME + */ + if (rq_data_dir(req) == READ) { + cmd[0] = READ_10; + scsi_flags = 0x60a0000a; + } else { + cmd[0] = WRITE_10; + scsi_flags = 0xa0a0000a; + } + + *mptr++ = cpu_to_le32(scsi_flags); + + *((u32 *) & cmd[2]) = cpu_to_be32(blk_rq_pos(req) * hwsec); + *((u16 *) & cmd[7]) = cpu_to_be16(blk_rq_sectors(req) * hwsec); + + memcpy(mptr, cmd, 10); + mptr += 4; + *mptr++ = cpu_to_le32(blk_rq_bytes(req)); + } else +#endif + { + msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); + *mptr++ = cpu_to_le32(ctl_flags); + *mptr++ = cpu_to_le32(blk_rq_bytes(req)); + *mptr++ = + cpu_to_le32((u32) (blk_rq_pos(req) << KERNEL_SECTOR_SHIFT)); + *mptr++ = + cpu_to_le32(blk_rq_pos(req) >> (32 - KERNEL_SECTOR_SHIFT)); + } + + if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { + rc = -ENOMEM; + goto context_remove; + } + + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); + + list_add_tail(&ireq->queue, &dev->open_queue); + dev->open_queue_depth++; + + i2o_msg_post(c, msg); + + return 0; + + context_remove: + i2o_cntxt_list_remove(c, req); + + nop_msg: + i2o_msg_nop(c, msg); + + exit: + return rc; +}; + +/** + * i2o_block_request_fn - request queue handling function + * @q: request queue from which the request could be fetched + * + * Takes the next request from the queue, transfers it and if no error + * occurs dequeue it from the queue. On arrival of the reply the message + * will be processed further. If an error occurs requeue the request. + */ +static void i2o_block_request_fn(struct request_queue *q) +{ + struct request *req; + + while ((req = blk_peek_request(q)) != NULL) { + if (req->cmd_type == REQ_TYPE_FS) { + struct i2o_block_delayed_request *dreq; + struct i2o_block_request *ireq = req->special; + unsigned int queue_depth; + + queue_depth = ireq->i2o_blk_dev->open_queue_depth; + + if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { + if (!i2o_block_transfer(req)) { + blk_start_request(req); + continue; + } else + osm_info("transfer error\n"); + } + + if (queue_depth) + break; + + /* stop the queue and retry later */ + dreq = kmalloc(sizeof(*dreq), GFP_ATOMIC); + if (!dreq) + continue; + + dreq->queue = q; + INIT_DELAYED_WORK(&dreq->work, + i2o_block_delayed_request_fn); + + if (!queue_delayed_work(i2o_block_driver.event_queue, + &dreq->work, + I2O_BLOCK_RETRY_TIME)) + kfree(dreq); + else { + blk_stop_queue(q); + break; + } + } else { + blk_start_request(req); + __blk_end_request_all(req, -EIO); + } + } +}; + +/* I2O Block device operations definition */ +static const struct block_device_operations i2o_block_fops = { + .owner = THIS_MODULE, + .open = i2o_block_open, + .release = i2o_block_release, + .ioctl = i2o_block_ioctl, + .compat_ioctl = i2o_block_ioctl, + .getgeo = i2o_block_getgeo, + .check_events = i2o_block_check_events, +}; + +/** + * i2o_block_device_alloc - Allocate memory for a I2O Block device + * + * Allocate memory for the i2o_block_device struct, gendisk and request + * queue and initialize them as far as no additional information is needed. + * + * Returns a pointer to the allocated I2O Block device on success or a + * negative error code on failure. + */ +static struct i2o_block_device *i2o_block_device_alloc(void) +{ + struct i2o_block_device *dev; + struct gendisk *gd; + struct request_queue *queue; + int rc; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + osm_err("Insufficient memory to allocate I2O Block disk.\n"); + rc = -ENOMEM; + goto exit; + } + + INIT_LIST_HEAD(&dev->open_queue); + spin_lock_init(&dev->lock); + dev->rcache = CACHE_PREFETCH; + dev->wcache = CACHE_WRITEBACK; + + /* allocate a gendisk with 16 partitions */ + gd = alloc_disk(16); + if (!gd) { + osm_err("Insufficient memory to allocate gendisk.\n"); + rc = -ENOMEM; + goto cleanup_dev; + } + + /* initialize the request queue */ + queue = blk_init_queue(i2o_block_request_fn, &dev->lock); + if (!queue) { + osm_err("Insufficient memory to allocate request queue.\n"); + rc = -ENOMEM; + goto cleanup_queue; + } + + blk_queue_prep_rq(queue, i2o_block_prep_req_fn); + + gd->major = I2O_MAJOR; + gd->queue = queue; + gd->fops = &i2o_block_fops; + gd->private_data = dev; + + dev->gd = gd; + + return dev; + + cleanup_queue: + put_disk(gd); + + cleanup_dev: + kfree(dev); + + exit: + return ERR_PTR(rc); +}; + +/** + * i2o_block_probe - verify if dev is a I2O Block device and install it + * @dev: device to verify if it is a I2O Block device + * + * We only verify if the user_tid of the device is 0xfff and then install + * the device. Otherwise it is used by some other device (e. g. RAID). + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_controller *c = i2o_dev->iop; + struct i2o_block_device *i2o_blk_dev; + struct gendisk *gd; + struct request_queue *queue; + static int unit = 0; + int rc; + u64 size; + u32 blocksize; + u16 body_size = 4; + u16 power; + unsigned short max_sectors; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) + body_size = 8; +#endif + + if (c->limit_sectors) + max_sectors = I2O_MAX_SECTORS_LIMITED; + else + max_sectors = I2O_MAX_SECTORS; + + /* skip devices which are used by IOP */ + if (i2o_dev->lct_data.user_tid != 0xfff) { + osm_debug("skipping used device %03x\n", i2o_dev->lct_data.tid); + return -ENODEV; + } + + if (i2o_device_claim(i2o_dev)) { + osm_warn("Unable to claim device. Installation aborted\n"); + rc = -EFAULT; + goto exit; + } + + i2o_blk_dev = i2o_block_device_alloc(); + if (IS_ERR(i2o_blk_dev)) { + osm_err("could not alloc a new I2O block device"); + rc = PTR_ERR(i2o_blk_dev); + goto claim_release; + } + + i2o_blk_dev->i2o_dev = i2o_dev; + dev_set_drvdata(dev, i2o_blk_dev); + + /* setup gendisk */ + gd = i2o_blk_dev->gd; + gd->first_minor = unit << 4; + sprintf(gd->disk_name, "i2o/hd%c", 'a' + unit); + gd->driverfs_dev = &i2o_dev->device; + + /* setup request queue */ + queue = gd->queue; + queue->queuedata = i2o_blk_dev; + + blk_queue_max_hw_sectors(queue, max_sectors); + blk_queue_max_segments(queue, i2o_sg_tablesize(c, body_size)); + + osm_debug("max sectors = %d\n", queue->max_sectors); + osm_debug("phys segments = %d\n", queue->max_phys_segments); + osm_debug("max hw segments = %d\n", queue->max_hw_segments); + + /* + * Ask for the current media data. If that isn't supported + * then we ask for the device capacity data + */ + if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || + !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { + blk_queue_logical_block_size(queue, le32_to_cpu(blocksize)); + } else + osm_warn("unable to get blocksize of %s\n", gd->disk_name); + + if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || + !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { + set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT); + } else + osm_warn("could not get size of %s\n", gd->disk_name); + + if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) + i2o_blk_dev->power = power; + + i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); + + add_disk(gd); + + unit++; + + osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid, + i2o_blk_dev->gd->disk_name); + + return 0; + + claim_release: + i2o_device_claim_release(i2o_dev); + + exit: + return rc; +}; + +/* Block OSM driver struct */ +static struct i2o_driver i2o_block_driver = { + .name = OSM_NAME, + .event = i2o_block_event, + .reply = i2o_block_reply, + .classes = i2o_block_class_id, + .driver = { + .probe = i2o_block_probe, + .remove = i2o_block_remove, + }, +}; + +/** + * i2o_block_init - Block OSM initialization function + * + * Allocate the slab and mempool for request structs, registers i2o_block + * block device and finally register the Block OSM in the I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_block_init(void) +{ + int rc; + int size; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + /* Allocate request mempool and slab */ + size = sizeof(struct i2o_block_request); + i2o_blk_req_pool.slab = kmem_cache_create("i2o_block_req", size, 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!i2o_blk_req_pool.slab) { + osm_err("can't init request slab\n"); + rc = -ENOMEM; + goto exit; + } + + i2o_blk_req_pool.pool = + mempool_create_slab_pool(I2O_BLOCK_REQ_MEMPOOL_SIZE, + i2o_blk_req_pool.slab); + if (!i2o_blk_req_pool.pool) { + osm_err("can't init request mempool\n"); + rc = -ENOMEM; + goto free_slab; + } + + /* Register the block device interfaces */ + rc = register_blkdev(I2O_MAJOR, "i2o_block"); + if (rc) { + osm_err("unable to register block device\n"); + goto free_mempool; + } +#ifdef MODULE + osm_info("registered device at major %d\n", I2O_MAJOR); +#endif + + /* Register Block OSM into I2O core */ + rc = i2o_driver_register(&i2o_block_driver); + if (rc) { + osm_err("Could not register Block driver\n"); + goto unregister_blkdev; + } + + return 0; + + unregister_blkdev: + unregister_blkdev(I2O_MAJOR, "i2o_block"); + + free_mempool: + mempool_destroy(i2o_blk_req_pool.pool); + + free_slab: + kmem_cache_destroy(i2o_blk_req_pool.slab); + + exit: + return rc; +}; + +/** + * i2o_block_exit - Block OSM exit function + * + * Unregisters Block OSM from I2O core, unregisters i2o_block block device + * and frees the mempool and slab. + */ +static void __exit i2o_block_exit(void) +{ + /* Unregister I2O Block OSM from I2O core */ + i2o_driver_unregister(&i2o_block_driver); + + /* Unregister block device */ + unregister_blkdev(I2O_MAJOR, "i2o_block"); + + /* Free request mempool and slab */ + mempool_destroy(i2o_blk_req_pool.pool); + kmem_cache_destroy(i2o_blk_req_pool.slab); +}; + +MODULE_AUTHOR("Red Hat"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_block_init); +module_exit(i2o_block_exit); diff --git a/drivers/staging/i2o/i2o_block.h b/drivers/staging/i2o/i2o_block.h new file mode 100644 index 00000000000..cf8873cbca3 --- /dev/null +++ b/drivers/staging/i2o/i2o_block.h @@ -0,0 +1,103 @@ +/* + * Block OSM structures/API + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * 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 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * For the purpose of avoiding doubt the preferred form of the work + * for making modifications shall be a standards compliant form such + * gzipped tar and not one requiring a proprietary or patent encumbered + * tool to unpack. + * + * Fixes/additions: + * Steve Ralston: + * Multiple device handling error fixes, + * Added a queue depth. + * Alan Cox: + * FC920 has an rmw bug. Dont or in the end marker. + * Removed queue walk, fixed for 64bitness. + * Rewrote much of the code over time + * Added indirect block lists + * Handle 64K limits on many controllers + * Don't use indirects on the Promise (breaks) + * Heavily chop down the queue depths + * Deepak Saxena: + * Independent queues per IOP + * Support for dynamic device creation/deletion + * Code cleanup + * Support for larger I/Os through merge* functions + * (taken from DAC960 driver) + * Boji T Kannanthanam: + * Set the I2O Block devices to be detected in increasing + * order of TIDs during boot. + * Search and set the I2O block device that we boot off + * from as the first device to be claimed (as /dev/i2o/hda) + * Properly attach/detach I2O gendisk structure from the + * system gendisk list. The I2O block devices now appear in + * /proc/partitions. + * Markus Lidel <Markus.Lidel@shadowconnect.com>: + * Minor bugfixes for 2.6. + */ + +#ifndef I2O_BLOCK_OSM_H +#define I2O_BLOCK_OSM_H + +#define I2O_BLOCK_RETRY_TIME HZ/4 +#define I2O_BLOCK_MAX_OPEN_REQUESTS 50 + +/* request queue sizes */ +#define I2O_BLOCK_REQ_MEMPOOL_SIZE 32 + +#define KERNEL_SECTOR_SHIFT 9 +#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT) + +/* I2O Block OSM mempool struct */ +struct i2o_block_mempool { + struct kmem_cache *slab; + mempool_t *pool; +}; + +/* I2O Block device descriptor */ +struct i2o_block_device { + struct i2o_device *i2o_dev; /* pointer to I2O device */ + struct gendisk *gd; + spinlock_t lock; /* queue lock */ + struct list_head open_queue; /* list of transferred, but unfinished + requests */ + unsigned int open_queue_depth; /* number of requests in the queue */ + + int rcache; /* read cache flags */ + int wcache; /* write cache flags */ + int flags; + u16 power; /* power state */ + int media_change_flag; /* media changed flag */ +}; + +/* I2O Block device request */ +struct i2o_block_request { + struct list_head queue; + struct request *req; /* corresponding request */ + struct i2o_block_device *i2o_blk_dev; /* I2O block device */ + struct device *dev; /* device used for DMA */ + int sg_nents; /* number of SG elements */ + struct scatterlist sg_table[I2O_MAX_PHYS_SEGMENTS]; /* SG table */ +}; + +/* I2O Block device delayed request */ +struct i2o_block_delayed_request { + struct delayed_work work; + struct request_queue *queue; +}; + +#endif diff --git a/drivers/staging/i2o/i2o_config.c b/drivers/staging/i2o/i2o_config.c new file mode 100644 index 00000000000..04bd3b6de40 --- /dev/null +++ b/drivers/staging/i2o/i2o_config.c @@ -0,0 +1,1163 @@ +/* + * I2O Configuration Interface Driver + * + * (C) Copyright 1999-2002 Red Hat + * + * Written by Alan Cox, Building Number Three Ltd + * + * Fixes/additions: + * Deepak Saxena (04/20/1999): + * Added basic ioctl() support + * Deepak Saxena (06/07/1999): + * Added software download ioctl (still testing) + * Auvo Häkkinen (09/10/1999): + * Changes to i2o_cfg_reply(), ioctl_parms() + * Added ioct_validate() + * Taneli Vähäkangas (09/30/1999): + * Fixed ioctl_swdl() + * Taneli Vähäkangas (10/04/1999): + * Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() + * Deepak Saxena (11/18/1999): + * Added event managmenet support + * Alan Cox <alan@lxorguk.ukuu.org.uk>: + * 2.4 rewrite ported to 2.5 + * Markus Lidel <Markus.Lidel@shadowconnect.com>: + * Added pass-thru support for Adaptec's raidutils + * + * 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 of the License, or (at your option) any later version. + */ + +#include <linux/miscdevice.h> +#include <linux/mutex.h> +#include <linux/compat.h> +#include <linux/slab.h> + +#include <asm/uaccess.h> + +#include "core.h" + +#define SG_TABLESIZE 30 + +static DEFINE_MUTEX(i2o_cfg_mutex); +static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long); + +static spinlock_t i2o_config_lock; + +#define MODINC(x,y) ((x) = ((x) + 1) % (y)) + +struct sg_simple_element { + u32 flag_count; + u32 addr_bus; +}; + +struct i2o_cfg_info { + struct file *fp; + struct fasync_struct *fasync; + struct i2o_evt_info event_q[I2O_EVT_Q_LEN]; + u16 q_in; // Queue head index + u16 q_out; // Queue tail index + u16 q_len; // Queue length + u16 q_lost; // Number of lost events + ulong q_id; // Event queue ID...used as tx_context + struct i2o_cfg_info *next; +}; +static struct i2o_cfg_info *open_files = NULL; +static ulong i2o_cfg_info_id = 0; + +static int i2o_cfg_getiops(unsigned long arg) +{ + struct i2o_controller *c; + u8 __user *user_iop_table = (void __user *)arg; + u8 tmp[MAX_I2O_CONTROLLERS]; + int ret = 0; + + memset(tmp, 0, MAX_I2O_CONTROLLERS); + + list_for_each_entry(c, &i2o_controllers, list) + tmp[c->unit] = 1; + + if (copy_to_user(user_iop_table, tmp, MAX_I2O_CONTROLLERS)) + ret = -EFAULT; + + return ret; +}; + +static int i2o_cfg_gethrt(unsigned long arg) +{ + struct i2o_controller *c; + struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg; + struct i2o_cmd_hrtlct kcmd; + i2o_hrt *hrt; + int len; + u32 reslen; + int ret = 0; + + if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) + return -EFAULT; + + if (get_user(reslen, kcmd.reslen) < 0) + return -EFAULT; + + if (kcmd.resbuf == NULL) + return -EFAULT; + + c = i2o_find_iop(kcmd.iop); + if (!c) + return -ENXIO; + + hrt = (i2o_hrt *) c->hrt.virt; + + len = 8 + ((hrt->entry_len * hrt->num_entries) << 2); + + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) + ret = -ENOBUFS; + else if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) + ret = -EFAULT; + + return ret; +}; + +static int i2o_cfg_getlct(unsigned long arg) +{ + struct i2o_controller *c; + struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg; + struct i2o_cmd_hrtlct kcmd; + i2o_lct *lct; + int len; + int ret = 0; + u32 reslen; + + if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) + return -EFAULT; + + if (get_user(reslen, kcmd.reslen) < 0) + return -EFAULT; + + if (kcmd.resbuf == NULL) + return -EFAULT; + + c = i2o_find_iop(kcmd.iop); + if (!c) + return -ENXIO; + + lct = (i2o_lct *) c->lct; + + len = (unsigned int)lct->table_size << 2; + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) + ret = -ENOBUFS; + else if (copy_to_user(kcmd.resbuf, lct, len)) + ret = -EFAULT; + + return ret; +}; + +static int i2o_cfg_parms(unsigned long arg, unsigned int type) +{ + int ret = 0; + struct i2o_controller *c; + struct i2o_device *dev; + struct i2o_cmd_psetget __user *cmd = + (struct i2o_cmd_psetget __user *)arg; + struct i2o_cmd_psetget kcmd; + u32 reslen; + u8 *ops; + u8 *res; + int len = 0; + + u32 i2o_cmd = (type == I2OPARMGET ? + I2O_CMD_UTIL_PARAMS_GET : I2O_CMD_UTIL_PARAMS_SET); + + if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget))) + return -EFAULT; + + if (get_user(reslen, kcmd.reslen)) + return -EFAULT; + + c = i2o_find_iop(kcmd.iop); + if (!c) + return -ENXIO; + + dev = i2o_iop_find_device(c, kcmd.tid); + if (!dev) + return -ENXIO; + + /* + * Stop users being able to try and allocate arbitrary amounts + * of DMA space. 64K is way more than sufficient for this. + */ + if (kcmd.oplen > 65536) + return -EMSGSIZE; + + ops = memdup_user(kcmd.opbuf, kcmd.oplen); + if (IS_ERR(ops)) + return PTR_ERR(ops); + + /* + * It's possible to have a _very_ large table + * and that the user asks for all of it at once... + */ + res = kmalloc(65536, GFP_KERNEL); + if (!res) { + kfree(ops); + return -ENOMEM; + } + + len = i2o_parm_issue(dev, i2o_cmd, ops, kcmd.oplen, res, 65536); + kfree(ops); + + if (len < 0) { + kfree(res); + return -EAGAIN; + } + + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) + ret = -ENOBUFS; + else if (copy_to_user(kcmd.resbuf, res, len)) + ret = -EFAULT; + + kfree(res); + + return ret; +}; + +static int i2o_cfg_swdl(unsigned long arg) +{ + struct i2o_sw_xfer kxfer; + struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; + unsigned char maxfrag = 0, curfrag = 1; + struct i2o_dma buffer; + struct i2o_message *msg; + unsigned int status = 0, swlen = 0, fragsize = 8192; + struct i2o_controller *c; + + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + return -EFAULT; + + if (get_user(swlen, kxfer.swlen) < 0) + return -EFAULT; + + if (get_user(maxfrag, kxfer.maxfrag) < 0) + return -EFAULT; + + if (get_user(curfrag, kxfer.curfrag) < 0) + return -EFAULT; + + if (curfrag == maxfrag) + fragsize = swlen - (maxfrag - 1) * 8192; + + if (!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize)) + return -EFAULT; + + c = i2o_find_iop(kxfer.iop); + if (!c) + return -ENXIO; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { + i2o_msg_nop(c, msg); + return -ENOMEM; + } + + if (__copy_from_user(buffer.virt, kxfer.buf, fragsize)) { + i2o_msg_nop(c, msg); + i2o_dma_free(&c->pdev->dev, &buffer); + return -EFAULT; + } + + msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + msg->body[0] = + cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer. + sw_type) << 16) | + (((u32) maxfrag) << 8) | (((u32) curfrag))); + msg->body[1] = cpu_to_le32(swlen); + msg->body[2] = cpu_to_le32(kxfer.sw_id); + msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); + msg->body[4] = cpu_to_le32(buffer.phys); + + osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); + status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); + + if (status != -ETIMEDOUT) + i2o_dma_free(&c->pdev->dev, &buffer); + + if (status != I2O_POST_WAIT_OK) { + // it fails if you try and send frags out of order + // and for some yet unknown reasons too + osm_info("swdl failed, DetailedStatus = %d\n", status); + return status; + } + + return 0; +}; + +static int i2o_cfg_swul(unsigned long arg) +{ + struct i2o_sw_xfer kxfer; + struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; + unsigned char maxfrag = 0, curfrag = 1; + struct i2o_dma buffer; + struct i2o_message *msg; + unsigned int status = 0, swlen = 0, fragsize = 8192; + struct i2o_controller *c; + int ret = 0; + + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + return -EFAULT; + + if (get_user(swlen, kxfer.swlen) < 0) + return -EFAULT; + + if (get_user(maxfrag, kxfer.maxfrag) < 0) + return -EFAULT; + + if (get_user(curfrag, kxfer.curfrag) < 0) + return -EFAULT; + + if (curfrag == maxfrag) + fragsize = swlen - (maxfrag - 1) * 8192; + + if (!kxfer.buf) + return -EFAULT; + + c = i2o_find_iop(kxfer.iop); + if (!c) + return -ENXIO; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { + i2o_msg_nop(c, msg); + return -ENOMEM; + } + + msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + msg->body[0] = + cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer. + sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag); + msg->body[1] = cpu_to_le32(swlen); + msg->body[2] = cpu_to_le32(kxfer.sw_id); + msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); + msg->body[4] = cpu_to_le32(buffer.phys); + + osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); + status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); + + if (status != I2O_POST_WAIT_OK) { + if (status != -ETIMEDOUT) + i2o_dma_free(&c->pdev->dev, &buffer); + + osm_info("swul failed, DetailedStatus = %d\n", status); + return status; + } + + if (copy_to_user(kxfer.buf, buffer.virt, fragsize)) + ret = -EFAULT; + + i2o_dma_free(&c->pdev->dev, &buffer); + + return ret; +} + +static int i2o_cfg_swdel(unsigned long arg) +{ + struct i2o_controller *c; + struct i2o_sw_xfer kxfer; + struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; + struct i2o_message *msg; + unsigned int swlen; + int token; + + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + return -EFAULT; + + if (get_user(swlen, kxfer.swlen) < 0) + return -EFAULT; + + c = i2o_find_iop(kxfer.iop); + if (!c) + return -ENXIO; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + msg->body[0] = + cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16); + msg->body[1] = cpu_to_le32(swlen); + msg->body[2] = cpu_to_le32(kxfer.sw_id); + + token = i2o_msg_post_wait(c, msg, 10); + + if (token != I2O_POST_WAIT_OK) { + osm_info("swdel failed, DetailedStatus = %d\n", token); + return -ETIMEDOUT; + } + + return 0; +}; + +static int i2o_cfg_validate(unsigned long arg) +{ + int token; + int iop = (int)arg; + struct i2o_message *msg; + struct i2o_controller *c; + + c = i2o_find_iop(iop); + if (!c) + return -ENXIO; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + + token = i2o_msg_post_wait(c, msg, 10); + + if (token != I2O_POST_WAIT_OK) { + osm_info("Can't validate configuration, ErrorStatus = %d\n", + token); + return -ETIMEDOUT; + } + + return 0; +}; + +static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp) +{ + struct i2o_message *msg; + struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg; + struct i2o_evt_id kdesc; + struct i2o_controller *c; + struct i2o_device *d; + + if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id))) + return -EFAULT; + + /* IOP exists? */ + c = i2o_find_iop(kdesc.iop); + if (!c) + return -ENXIO; + + /* Device exists? */ + d = i2o_iop_find_device(c, kdesc.tid); + if (!d) + return -ENODEV; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | + kdesc.tid); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data)); + msg->body[0] = cpu_to_le32(kdesc.evt_mask); + + i2o_msg_post(c, msg); + + return 0; +} + +static int i2o_cfg_evt_get(unsigned long arg, struct file *fp) +{ + struct i2o_cfg_info *p = NULL; + struct i2o_evt_get __user *uget = (struct i2o_evt_get __user *)arg; + struct i2o_evt_get kget; + unsigned long flags; + + for (p = open_files; p; p = p->next) + if (p->q_id == (ulong) fp->private_data) + break; + + if (!p->q_len) + return -ENOENT; + + memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info)); + MODINC(p->q_out, I2O_EVT_Q_LEN); + spin_lock_irqsave(&i2o_config_lock, flags); + p->q_len--; + kget.pending = p->q_len; + kget.lost = p->q_lost; + spin_unlock_irqrestore(&i2o_config_lock, flags); + + if (copy_to_user(uget, &kget, sizeof(struct i2o_evt_get))) + return -EFAULT; + return 0; +} + +#ifdef CONFIG_COMPAT +static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, + unsigned long arg) +{ + struct i2o_cmd_passthru32 __user *cmd; + struct i2o_controller *c; + u32 __user *user_msg; + u32 *reply = NULL; + u32 __user *user_reply = NULL; + u32 size = 0; + u32 reply_size = 0; + u32 rcode = 0; + struct i2o_dma sg_list[SG_TABLESIZE]; + u32 sg_offset = 0; + u32 sg_count = 0; + u32 i = 0; + u32 sg_index = 0; + i2o_status_block *sb; + struct i2o_message *msg; + unsigned int iop; + + cmd = (struct i2o_cmd_passthru32 __user *)arg; + + if (get_user(iop, &cmd->iop) || get_user(i, &cmd->msg)) + return -EFAULT; + + user_msg = compat_ptr(i); + + c = i2o_find_iop(iop); + if (!c) { + osm_debug("controller %d not found\n", iop); + return -ENXIO; + } + + sb = c->status_block.virt; + + if (get_user(size, &user_msg[0])) { + osm_warn("unable to get size!\n"); + return -EFAULT; + } + size = size >> 16; + + if (size > sb->inbound_frame_size) { + osm_warn("size of message > inbound_frame_size"); + return -EFAULT; + } + + user_reply = &user_msg[size]; + + size <<= 2; // Convert to bytes + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + rcode = -EFAULT; + /* Copy in the user's I2O command */ + if (copy_from_user(msg, user_msg, size)) { + osm_warn("unable to copy user message\n"); + goto out; + } + i2o_dump_message(msg); + + if (get_user(reply_size, &user_reply[0]) < 0) + goto out; + + reply_size >>= 16; + reply_size <<= 2; + + rcode = -ENOMEM; + reply = kzalloc(reply_size, GFP_KERNEL); + if (!reply) { + printk(KERN_WARNING "%s: Could not allocate reply buffer\n", + c->name); + goto out; + } + + sg_offset = (msg->u.head[0] >> 4) & 0x0f; + + memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); + if (sg_offset) { + struct sg_simple_element *sg; + + if (sg_offset * 4 >= size) { + rcode = -EFAULT; + goto cleanup; + } + // TODO 64bit fix + sg = (struct sg_simple_element *)((&msg->u.head[0]) + + sg_offset); + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + if (sg_count > SG_TABLESIZE) { + printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", + c->name, sg_count); + rcode = -EINVAL; + goto cleanup; + } + + for (i = 0; i < sg_count; i++) { + int sg_size; + struct i2o_dma *p; + + if (!(sg[i].flag_count & 0x10000000 + /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) { + printk(KERN_DEBUG + "%s:Bad SG element %d - not simple (%x)\n", + c->name, i, sg[i].flag_count); + rcode = -EINVAL; + goto cleanup; + } + sg_size = sg[i].flag_count & 0xffffff; + p = &(sg_list[sg_index]); + /* Allocate memory for the transfer */ + if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { + printk(KERN_DEBUG + "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + c->name, sg_size, i, sg_count); + rcode = -ENOMEM; + goto sg_list_cleanup; + } + sg_index++; + /* Copy in the user's SG buffer if necessary */ + if (sg[i]. + flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { + // TODO 64bit fix + if (copy_from_user + (p->virt, + (void __user *)(unsigned long)sg[i]. + addr_bus, sg_size)) { + printk(KERN_DEBUG + "%s: Could not copy SG buf %d FROM user\n", + c->name, i); + rcode = -EFAULT; + goto sg_list_cleanup; + } + } + //TODO 64bit fix + sg[i].addr_bus = (u32) p->phys; + } + } + + rcode = i2o_msg_post_wait(c, msg, 60); + msg = NULL; + if (rcode) { + reply[4] = ((u32) rcode) << 24; + goto sg_list_cleanup; + } + + if (sg_offset) { + u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; + /* Copy back the Scatter Gather buffers back to user space */ + u32 j; + // TODO 64bit fix + struct sg_simple_element *sg; + int sg_size; + + // re-acquire the original message to handle correctly the sg copy operation + memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); + // get user msg size in u32s + if (get_user(size, &user_msg[0])) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + size = size >> 16; + size *= 4; + if (size > sizeof(rmsg)) { + rcode = -EINVAL; + goto sg_list_cleanup; + } + + /* Copy in the user's I2O command */ + if (copy_from_user(rmsg, user_msg, size)) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + + // TODO 64bit fix + sg = (struct sg_simple_element *)(rmsg + sg_offset); + for (j = 0; j < sg_count; j++) { + /* Copy out the SG list to user's buffer if necessary */ + if (! + (sg[j]. + flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) { + sg_size = sg[j].flag_count & 0xffffff; + // TODO 64bit fix + if (copy_to_user + ((void __user *)(u64) sg[j].addr_bus, + sg_list[j].virt, sg_size)) { + printk(KERN_WARNING + "%s: Could not copy %p TO user %x\n", + c->name, sg_list[j].virt, + sg[j].addr_bus); + rcode = -EFAULT; + goto sg_list_cleanup; + } + } + } + } + +sg_list_cleanup: + /* Copy back the reply to user space */ + if (reply_size) { + // we wrote our own values for context - now restore the user supplied ones + if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) { + printk(KERN_WARNING + "%s: Could not copy message context FROM user\n", + c->name); + rcode = -EFAULT; + } + if (copy_to_user(user_reply, reply, reply_size)) { + printk(KERN_WARNING + "%s: Could not copy reply TO user\n", c->name); + rcode = -EFAULT; + } + } + for (i = 0; i < sg_index; i++) + i2o_dma_free(&c->pdev->dev, &sg_list[i]); + +cleanup: + kfree(reply); +out: + if (msg) + i2o_msg_nop(c, msg); + return rcode; +} + +static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, + unsigned long arg) +{ + int ret; + switch (cmd) { + case I2OGETIOPS: + ret = i2o_cfg_ioctl(file, cmd, arg); + break; + case I2OPASSTHRU32: + mutex_lock(&i2o_cfg_mutex); + ret = i2o_cfg_passthru32(file, cmd, arg); + mutex_unlock(&i2o_cfg_mutex); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + return ret; +} + +#endif + +#ifdef CONFIG_I2O_EXT_ADAPTEC +static int i2o_cfg_passthru(unsigned long arg) +{ + struct i2o_cmd_passthru __user *cmd = + (struct i2o_cmd_passthru __user *)arg; + struct i2o_controller *c; + u32 __user *user_msg; + u32 *reply = NULL; + u32 __user *user_reply = NULL; + u32 size = 0; + u32 reply_size = 0; + u32 rcode = 0; + struct i2o_dma sg_list[SG_TABLESIZE]; + u32 sg_offset = 0; + u32 sg_count = 0; + int sg_index = 0; + u32 i = 0; + i2o_status_block *sb; + struct i2o_message *msg; + unsigned int iop; + + if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg)) + return -EFAULT; + + c = i2o_find_iop(iop); + if (!c) { + osm_warn("controller %d not found\n", iop); + return -ENXIO; + } + + sb = c->status_block.virt; + + if (get_user(size, &user_msg[0])) + return -EFAULT; + size = size >> 16; + + if (size > sb->inbound_frame_size) { + osm_warn("size of message > inbound_frame_size"); + return -EFAULT; + } + + user_reply = &user_msg[size]; + + size <<= 2; // Convert to bytes + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + rcode = -EFAULT; + /* Copy in the user's I2O command */ + if (copy_from_user(msg, user_msg, size)) + goto out; + + if (get_user(reply_size, &user_reply[0]) < 0) + goto out; + + reply_size >>= 16; + reply_size <<= 2; + + reply = kzalloc(reply_size, GFP_KERNEL); + if (!reply) { + printk(KERN_WARNING "%s: Could not allocate reply buffer\n", + c->name); + rcode = -ENOMEM; + goto out; + } + + sg_offset = (msg->u.head[0] >> 4) & 0x0f; + + memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); + if (sg_offset) { + struct sg_simple_element *sg; + struct i2o_dma *p; + + if (sg_offset * 4 >= size) { + rcode = -EFAULT; + goto cleanup; + } + // TODO 64bit fix + sg = (struct sg_simple_element *)((&msg->u.head[0]) + + sg_offset); + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + if (sg_count > SG_TABLESIZE) { + printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", + c->name, sg_count); + rcode = -EINVAL; + goto cleanup; + } + + for (i = 0; i < sg_count; i++) { + int sg_size; + + if (!(sg[i].flag_count & 0x10000000 + /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) { + printk(KERN_DEBUG + "%s:Bad SG element %d - not simple (%x)\n", + c->name, i, sg[i].flag_count); + rcode = -EINVAL; + goto sg_list_cleanup; + } + sg_size = sg[i].flag_count & 0xffffff; + p = &(sg_list[sg_index]); + if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { + /* Allocate memory for the transfer */ + printk(KERN_DEBUG + "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + c->name, sg_size, i, sg_count); + rcode = -ENOMEM; + goto sg_list_cleanup; + } + sg_index++; + /* Copy in the user's SG buffer if necessary */ + if (sg[i]. + flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { + // TODO 64bit fix + if (copy_from_user + (p->virt, (void __user *)sg[i].addr_bus, + sg_size)) { + printk(KERN_DEBUG + "%s: Could not copy SG buf %d FROM user\n", + c->name, i); + rcode = -EFAULT; + goto sg_list_cleanup; + } + } + sg[i].addr_bus = p->phys; + } + } + + rcode = i2o_msg_post_wait(c, msg, 60); + msg = NULL; + if (rcode) { + reply[4] = ((u32) rcode) << 24; + goto sg_list_cleanup; + } + + if (sg_offset) { + u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; + /* Copy back the Scatter Gather buffers back to user space */ + u32 j; + // TODO 64bit fix + struct sg_simple_element *sg; + int sg_size; + + // re-acquire the original message to handle correctly the sg copy operation + memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); + // get user msg size in u32s + if (get_user(size, &user_msg[0])) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + size = size >> 16; + size *= 4; + if (size > sizeof(rmsg)) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + + /* Copy in the user's I2O command */ + if (copy_from_user(rmsg, user_msg, size)) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + + // TODO 64bit fix + sg = (struct sg_simple_element *)(rmsg + sg_offset); + for (j = 0; j < sg_count; j++) { + /* Copy out the SG list to user's buffer if necessary */ + if (! + (sg[j]. + flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) { + sg_size = sg[j].flag_count & 0xffffff; + // TODO 64bit fix + if (copy_to_user + ((void __user *)sg[j].addr_bus, sg_list[j].virt, + sg_size)) { + printk(KERN_WARNING + "%s: Could not copy %p TO user %x\n", + c->name, sg_list[j].virt, + sg[j].addr_bus); + rcode = -EFAULT; + goto sg_list_cleanup; + } + } + } + } + +sg_list_cleanup: + /* Copy back the reply to user space */ + if (reply_size) { + // we wrote our own values for context - now restore the user supplied ones + if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) { + printk(KERN_WARNING + "%s: Could not copy message context FROM user\n", + c->name); + rcode = -EFAULT; + } + if (copy_to_user(user_reply, reply, reply_size)) { + printk(KERN_WARNING + "%s: Could not copy reply TO user\n", c->name); + rcode = -EFAULT; + } + } + + for (i = 0; i < sg_index; i++) + i2o_dma_free(&c->pdev->dev, &sg_list[i]); + +cleanup: + kfree(reply); +out: + if (msg) + i2o_msg_nop(c, msg); + return rcode; +} +#endif + +/* + * IOCTL Handler + */ +static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) +{ + int ret; + + mutex_lock(&i2o_cfg_mutex); + switch (cmd) { + case I2OGETIOPS: + ret = i2o_cfg_getiops(arg); + break; + + case I2OHRTGET: + ret = i2o_cfg_gethrt(arg); + break; + + case I2OLCTGET: + ret = i2o_cfg_getlct(arg); + break; + + case I2OPARMSET: + ret = i2o_cfg_parms(arg, I2OPARMSET); + break; + + case I2OPARMGET: + ret = i2o_cfg_parms(arg, I2OPARMGET); + break; + + case I2OSWDL: + ret = i2o_cfg_swdl(arg); + break; + + case I2OSWUL: + ret = i2o_cfg_swul(arg); + break; + + case I2OSWDEL: + ret = i2o_cfg_swdel(arg); + break; + + case I2OVALIDATE: + ret = i2o_cfg_validate(arg); + break; + + case I2OEVTREG: + ret = i2o_cfg_evt_reg(arg, fp); + break; + + case I2OEVTGET: + ret = i2o_cfg_evt_get(arg, fp); + break; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + case I2OPASSTHRU: + ret = i2o_cfg_passthru(arg); + break; +#endif + + default: + osm_debug("unknown ioctl called!\n"); + ret = -EINVAL; + } + mutex_unlock(&i2o_cfg_mutex); + return ret; +} + +static int cfg_open(struct inode *inode, struct file *file) +{ + struct i2o_cfg_info *tmp = kmalloc(sizeof(struct i2o_cfg_info), + GFP_KERNEL); + unsigned long flags; + + if (!tmp) + return -ENOMEM; + + mutex_lock(&i2o_cfg_mutex); + file->private_data = (void *)(i2o_cfg_info_id++); + tmp->fp = file; + tmp->fasync = NULL; + tmp->q_id = (ulong) file->private_data; + tmp->q_len = 0; + tmp->q_in = 0; + tmp->q_out = 0; + tmp->q_lost = 0; + tmp->next = open_files; + + spin_lock_irqsave(&i2o_config_lock, flags); + open_files = tmp; + spin_unlock_irqrestore(&i2o_config_lock, flags); + mutex_unlock(&i2o_cfg_mutex); + + return 0; +} + +static int cfg_fasync(int fd, struct file *fp, int on) +{ + ulong id = (ulong) fp->private_data; + struct i2o_cfg_info *p; + int ret = -EBADF; + + mutex_lock(&i2o_cfg_mutex); + for (p = open_files; p; p = p->next) + if (p->q_id == id) + break; + + if (p) + ret = fasync_helper(fd, fp, on, &p->fasync); + mutex_unlock(&i2o_cfg_mutex); + return ret; +} + +static int cfg_release(struct inode *inode, struct file *file) +{ + ulong id = (ulong) file->private_data; + struct i2o_cfg_info *p, **q; + unsigned long flags; + + mutex_lock(&i2o_cfg_mutex); + spin_lock_irqsave(&i2o_config_lock, flags); + for (q = &open_files; (p = *q) != NULL; q = &p->next) { + if (p->q_id == id) { + *q = p->next; + kfree(p); + break; + } + } + spin_unlock_irqrestore(&i2o_config_lock, flags); + mutex_unlock(&i2o_cfg_mutex); + + return 0; +} + +static const struct file_operations config_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .unlocked_ioctl = i2o_cfg_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = i2o_cfg_compat_ioctl, +#endif + .open = cfg_open, + .release = cfg_release, + .fasync = cfg_fasync, +}; + +static struct miscdevice i2o_miscdev = { + I2O_MINOR, + "i2octl", + &config_fops +}; + +static int __init i2o_config_old_init(void) +{ + spin_lock_init(&i2o_config_lock); + + if (misc_register(&i2o_miscdev) < 0) { + osm_err("can't register device.\n"); + return -EBUSY; + } + + return 0; +} + +static void i2o_config_old_exit(void) +{ + misc_deregister(&i2o_miscdev); +} + +MODULE_AUTHOR("Red Hat Software"); diff --git a/drivers/staging/i2o/i2o_proc.c b/drivers/staging/i2o/i2o_proc.c new file mode 100644 index 00000000000..ad84f3304f3 --- /dev/null +++ b/drivers/staging/i2o/i2o_proc.c @@ -0,0 +1,2045 @@ +/* + * procfs handler for Linux I2O subsystem + * + * (c) Copyright 1999 Deepak Saxena + * + * Originally written by Deepak Saxena(deepak@plexity.net) + * + * 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 of the License, or (at your + * option) any later version. + * + * This is an initial test release. The code is based on the design of the + * ide procfs system (drivers/block/ide-proc.c). Some code taken from + * i2o-core module by Alan Cox. + * + * DISCLAIMER: This code is still under development/test and may cause + * your system to behave unpredictably. Use at your own discretion. + * + * + * Fixes/additions: + * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI), + * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI) + * University of Helsinki, Department of Computer Science + * LAN entries + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * Changes for new I2O API + */ + +#define OSM_NAME "proc-osm" +#define OSM_VERSION "1.316" +#define OSM_DESCRIPTION "I2O ProcFS OSM" + +#define I2O_MAX_MODULES 4 +// FIXME! +#define FMT_U64_HEX "0x%08x%08x" +#define U64_VAL(pu64) *((u32*)(pu64)+1), *((u32*)(pu64)) + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include "i2o.h" +#include <linux/slab.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> + +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/byteorder.h> + +/* Structure used to define /proc entries */ +typedef struct _i2o_proc_entry_t { + char *name; /* entry name */ + umode_t mode; /* mode */ + const struct file_operations *fops; /* open function */ +} i2o_proc_entry; + +/* global I2O /proc/i2o entry */ +static struct proc_dir_entry *i2o_proc_dir_root; + +/* proc OSM driver struct */ +static struct i2o_driver i2o_proc_driver = { + .name = OSM_NAME, +}; + +static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) +{ + int i; + + /* 19990419 -sralston + * The I2O v1.5 (and v2.0 so far) "official specification" + * got serial numbers WRONG! + * Apparently, and despite what Section 3.4.4 says and + * Figure 3-35 shows (pg 3-39 in the pdf doc), + * the convention / consensus seems to be: + * + First byte is SNFormat + * + Second byte is SNLen (but only if SNFormat==7 (?)) + * + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format + */ + switch (serialno[0]) { + case I2O_SNFORMAT_BINARY: /* Binary */ + seq_printf(seq, "0x"); + for (i = 0; i < serialno[1]; i++) { + seq_printf(seq, "%02X", serialno[2 + i]); + } + break; + + case I2O_SNFORMAT_ASCII: /* ASCII */ + if (serialno[1] < ' ') { /* printable or SNLen? */ + /* sanity */ + max_len = + (max_len < serialno[1]) ? max_len : serialno[1]; + serialno[1 + max_len] = '\0'; + + /* just print it */ + seq_printf(seq, "%s", &serialno[2]); + } else { + /* print chars for specified length */ + for (i = 0; i < serialno[1]; i++) { + seq_printf(seq, "%c", serialno[2 + i]); + } + } + break; + + case I2O_SNFORMAT_UNICODE: /* UNICODE */ + seq_printf(seq, "UNICODE Format. Can't Display\n"); + break; + + case I2O_SNFORMAT_LAN48_MAC: /* LAN-48 MAC Address */ + seq_printf(seq, "LAN-48 MAC address @ %pM", &serialno[2]); + break; + + case I2O_SNFORMAT_WAN: /* WAN MAC Address */ + /* FIXME: Figure out what a WAN access address looks like?? */ + seq_printf(seq, "WAN Access Address"); + break; + +/* plus new in v2.0 */ + case I2O_SNFORMAT_LAN64_MAC: /* LAN-64 MAC Address */ + /* FIXME: Figure out what a LAN-64 address really looks like?? */ + seq_printf(seq, + "LAN-64 MAC address @ [?:%02X:%02X:?] %pM", + serialno[8], serialno[9], &serialno[2]); + break; + + case I2O_SNFORMAT_DDM: /* I2O DDM */ + seq_printf(seq, + "DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh", + *(u16 *) & serialno[2], + *(u16 *) & serialno[4], *(u16 *) & serialno[6]); + break; + + case I2O_SNFORMAT_IEEE_REG64: /* IEEE Registered (64-bit) */ + case I2O_SNFORMAT_IEEE_REG128: /* IEEE Registered (128-bit) */ + /* FIXME: Figure if this is even close?? */ + seq_printf(seq, + "IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n", + *(u32 *) & serialno[2], + *(u32 *) & serialno[6], + *(u32 *) & serialno[10], *(u32 *) & serialno[14]); + break; + + case I2O_SNFORMAT_UNKNOWN: /* Unknown 0 */ + case I2O_SNFORMAT_UNKNOWN2: /* Unknown 0xff */ + default: + seq_printf(seq, "Unknown data format (0x%02x)", serialno[0]); + break; + } + + return 0; +} + +/** + * i2o_get_class_name - do i2o class name lookup + * @class: class number + * + * Return a descriptive string for an i2o class. + */ +static const char *i2o_get_class_name(int class) +{ + int idx = 16; + static char *i2o_class_name[] = { + "Executive", + "Device Driver Module", + "Block Device", + "Tape Device", + "LAN Interface", + "WAN Interface", + "Fibre Channel Port", + "Fibre Channel Device", + "SCSI Device", + "ATE Port", + "ATE Device", + "Floppy Controller", + "Floppy Device", + "Secondary Bus Port", + "Peer Transport Agent", + "Peer Transport", + "Unknown" + }; + + switch (class & 0xfff) { + case I2O_CLASS_EXECUTIVE: + idx = 0; + break; + case I2O_CLASS_DDM: + idx = 1; + break; + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + idx = 2; + break; + case I2O_CLASS_SEQUENTIAL_STORAGE: + idx = 3; + break; + case I2O_CLASS_LAN: + idx = 4; + break; + case I2O_CLASS_WAN: + idx = 5; + break; + case I2O_CLASS_FIBRE_CHANNEL_PORT: + idx = 6; + break; + case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: + idx = 7; + break; + case I2O_CLASS_SCSI_PERIPHERAL: + idx = 8; + break; + case I2O_CLASS_ATE_PORT: + idx = 9; + break; + case I2O_CLASS_ATE_PERIPHERAL: + idx = 10; + break; + case I2O_CLASS_FLOPPY_CONTROLLER: + idx = 11; + break; + case I2O_CLASS_FLOPPY_DEVICE: + idx = 12; + break; + case I2O_CLASS_BUS_ADAPTER: + idx = 13; + break; + case I2O_CLASS_PEER_TRANSPORT_AGENT: + idx = 14; + break; + case I2O_CLASS_PEER_TRANSPORT: + idx = 15; + break; + } + + return i2o_class_name[idx]; +} + +#define SCSI_TABLE_SIZE 13 +static char *scsi_devices[] = { + "Direct-Access Read/Write", + "Sequential-Access Storage", + "Printer", + "Processor", + "WORM Device", + "CD-ROM Device", + "Scanner Device", + "Optical Memory Device", + "Medium Changer Device", + "Communications Device", + "Graphics Art Pre-Press Device", + "Graphics Art Pre-Press Device", + "Array Controller Device" +}; + +static char *chtostr(char *tmp, u8 *chars, int n) +{ + tmp[0] = 0; + return strncat(tmp, (char *)chars, n); +} + +static int i2o_report_query_status(struct seq_file *seq, int block_status, + char *group) +{ + switch (block_status) { + case -ETIMEDOUT: + return seq_printf(seq, "Timeout reading group %s.\n", group); + case -ENOMEM: + return seq_printf(seq, "No free memory to read the table.\n"); + case -I2O_PARAMS_STATUS_INVALID_GROUP_ID: + return seq_printf(seq, "Group %s not supported.\n", group); + default: + return seq_printf(seq, + "Error reading group %s. BlockStatus 0x%02X\n", + group, -block_status); + } +} + +static char *bus_strings[] = { + "Local Bus", + "ISA", + "EISA", + "PCI", + "PCMCIA", + "NUBUS", + "CARDBUS" +}; + +static int i2o_seq_show_hrt(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + i2o_hrt *hrt = (i2o_hrt *) c->hrt.virt; + u32 bus; + int i; + + if (hrt->hrt_version) { + seq_printf(seq, + "HRT table for controller is too new a version.\n"); + return 0; + } + + seq_printf(seq, "HRT has %d entries of %d bytes each.\n", + hrt->num_entries, hrt->entry_len << 2); + + for (i = 0; i < hrt->num_entries; i++) { + seq_printf(seq, "Entry %d:\n", i); + seq_printf(seq, " Adapter ID: %0#10x\n", + hrt->hrt_entry[i].adapter_id); + seq_printf(seq, " Controlling tid: %0#6x\n", + hrt->hrt_entry[i].parent_tid); + + if (hrt->hrt_entry[i].bus_type != 0x80) { + bus = hrt->hrt_entry[i].bus_type; + seq_printf(seq, " %s Information\n", + bus_strings[bus]); + + switch (bus) { + case I2O_BUS_LOCAL: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.local_bus. + LbBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x\n", + hrt->hrt_entry[i].bus.local_bus. + LbBaseMemoryAddress); + break; + + case I2O_BUS_ISA: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.isa_bus. + IsaBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x,", + hrt->hrt_entry[i].bus.isa_bus. + IsaBaseMemoryAddress); + seq_printf(seq, " CSN: %0#4x,", + hrt->hrt_entry[i].bus.isa_bus.CSN); + break; + + case I2O_BUS_EISA: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.eisa_bus. + EisaBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x,", + hrt->hrt_entry[i].bus.eisa_bus. + EisaBaseMemoryAddress); + seq_printf(seq, " Slot: %0#4x,", + hrt->hrt_entry[i].bus.eisa_bus. + EisaSlotNumber); + break; + + case I2O_BUS_PCI: + seq_printf(seq, " Bus: %0#4x", + hrt->hrt_entry[i].bus.pci_bus. + PciBusNumber); + seq_printf(seq, " Dev: %0#4x", + hrt->hrt_entry[i].bus.pci_bus. + PciDeviceNumber); + seq_printf(seq, " Func: %0#4x", + hrt->hrt_entry[i].bus.pci_bus. + PciFunctionNumber); + seq_printf(seq, " Vendor: %0#6x", + hrt->hrt_entry[i].bus.pci_bus. + PciVendorID); + seq_printf(seq, " Device: %0#6x\n", + hrt->hrt_entry[i].bus.pci_bus. + PciDeviceID); + break; + + default: + seq_printf(seq, " Unsupported Bus Type\n"); + } + } else + seq_printf(seq, " Unknown Bus Type\n"); + } + + return 0; +} + +static int i2o_seq_show_lct(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + i2o_lct *lct = (i2o_lct *) c->lct; + int entries; + int i; + +#define BUS_TABLE_SIZE 3 + static char *bus_ports[] = { + "Generic Bus", + "SCSI Bus", + "Fibre Channel Bus" + }; + + entries = (lct->table_size - 3) / 9; + + seq_printf(seq, "LCT contains %d %s\n", entries, + entries == 1 ? "entry" : "entries"); + if (lct->boot_tid) + seq_printf(seq, "Boot Device @ ID %d\n", lct->boot_tid); + + seq_printf(seq, "Current Change Indicator: %#10x\n", lct->change_ind); + + for (i = 0; i < entries; i++) { + seq_printf(seq, "Entry %d\n", i); + seq_printf(seq, " Class, SubClass : %s", + i2o_get_class_name(lct->lct_entry[i].class_id)); + + /* + * Classes which we'll print subclass info for + */ + switch (lct->lct_entry[i].class_id & 0xFFF) { + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + switch (lct->lct_entry[i].sub_class) { + case 0x00: + seq_printf(seq, ", Direct-Access Read/Write"); + break; + + case 0x04: + seq_printf(seq, ", WORM Drive"); + break; + + case 0x05: + seq_printf(seq, ", CD-ROM Drive"); + break; + + case 0x07: + seq_printf(seq, ", Optical Memory Device"); + break; + + default: + seq_printf(seq, ", Unknown (0x%02x)", + lct->lct_entry[i].sub_class); + break; + } + break; + + case I2O_CLASS_LAN: + switch (lct->lct_entry[i].sub_class & 0xFF) { + case 0x30: + seq_printf(seq, ", Ethernet"); + break; + + case 0x40: + seq_printf(seq, ", 100base VG"); + break; + + case 0x50: + seq_printf(seq, ", IEEE 802.5/Token-Ring"); + break; + + case 0x60: + seq_printf(seq, ", ANSI X3T9.5 FDDI"); + break; + + case 0x70: + seq_printf(seq, ", Fibre Channel"); + break; + + default: + seq_printf(seq, ", Unknown Sub-Class (0x%02x)", + lct->lct_entry[i].sub_class & 0xFF); + break; + } + break; + + case I2O_CLASS_SCSI_PERIPHERAL: + if (lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE) + seq_printf(seq, ", %s", + scsi_devices[lct->lct_entry[i]. + sub_class]); + else + seq_printf(seq, ", Unknown Device Type"); + break; + + case I2O_CLASS_BUS_ADAPTER: + if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) + seq_printf(seq, ", %s", + bus_ports[lct->lct_entry[i]. + sub_class]); + else + seq_printf(seq, ", Unknown Bus Type"); + break; + } + seq_printf(seq, "\n"); + + seq_printf(seq, " Local TID : 0x%03x\n", + lct->lct_entry[i].tid); + seq_printf(seq, " User TID : 0x%03x\n", + lct->lct_entry[i].user_tid); + seq_printf(seq, " Parent TID : 0x%03x\n", + lct->lct_entry[i].parent_tid); + seq_printf(seq, " Identity Tag : 0x%x%x%x%x%x%x%x%x\n", + lct->lct_entry[i].identity_tag[0], + lct->lct_entry[i].identity_tag[1], + lct->lct_entry[i].identity_tag[2], + lct->lct_entry[i].identity_tag[3], + lct->lct_entry[i].identity_tag[4], + lct->lct_entry[i].identity_tag[5], + lct->lct_entry[i].identity_tag[6], + lct->lct_entry[i].identity_tag[7]); + seq_printf(seq, " Change Indicator : %0#10x\n", + lct->lct_entry[i].change_ind); + seq_printf(seq, " Event Capab Mask : %0#10x\n", + lct->lct_entry[i].device_flags); + } + + return 0; +} + +static int i2o_seq_show_status(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + char prodstr[25]; + int version; + i2o_status_block *sb = c->status_block.virt; + + i2o_status_get(c); // reread the status block + + seq_printf(seq, "Organization ID : %0#6x\n", sb->org_id); + + version = sb->i2o_version; + +/* FIXME for Spec 2.0 + if (version == 0x02) { + seq_printf(seq, "Lowest I2O version supported: "); + switch(workspace[2]) { + case 0x00: + seq_printf(seq, "1.0\n"); + break; + case 0x01: + seq_printf(seq, "1.5\n"); + break; + case 0x02: + seq_printf(seq, "2.0\n"); + break; + } + + seq_printf(seq, "Highest I2O version supported: "); + switch(workspace[3]) { + case 0x00: + seq_printf(seq, "1.0\n"); + break; + case 0x01: + seq_printf(seq, "1.5\n"); + break; + case 0x02: + seq_printf(seq, "2.0\n"); + break; + } + } +*/ + seq_printf(seq, "IOP ID : %0#5x\n", sb->iop_id); + seq_printf(seq, "Host Unit ID : %0#6x\n", sb->host_unit_id); + seq_printf(seq, "Segment Number : %0#5x\n", sb->segment_number); + + seq_printf(seq, "I2O version : "); + switch (version) { + case 0x00: + seq_printf(seq, "1.0\n"); + break; + case 0x01: + seq_printf(seq, "1.5\n"); + break; + case 0x02: + seq_printf(seq, "2.0\n"); + break; + default: + seq_printf(seq, "Unknown version\n"); + } + + seq_printf(seq, "IOP State : "); + switch (sb->iop_state) { + case 0x01: + seq_printf(seq, "INIT\n"); + break; + + case 0x02: + seq_printf(seq, "RESET\n"); + break; + + case 0x04: + seq_printf(seq, "HOLD\n"); + break; + + case 0x05: + seq_printf(seq, "READY\n"); + break; + + case 0x08: + seq_printf(seq, "OPERATIONAL\n"); + break; + + case 0x10: + seq_printf(seq, "FAILED\n"); + break; + + case 0x11: + seq_printf(seq, "FAULTED\n"); + break; + + default: + seq_printf(seq, "Unknown\n"); + break; + } + + seq_printf(seq, "Messenger Type : "); + switch (sb->msg_type) { + case 0x00: + seq_printf(seq, "Memory mapped\n"); + break; + case 0x01: + seq_printf(seq, "Memory mapped only\n"); + break; + case 0x02: + seq_printf(seq, "Remote only\n"); + break; + case 0x03: + seq_printf(seq, "Memory mapped and remote\n"); + break; + default: + seq_printf(seq, "Unknown\n"); + } + + seq_printf(seq, "Inbound Frame Size : %d bytes\n", + sb->inbound_frame_size << 2); + seq_printf(seq, "Max Inbound Frames : %d\n", + sb->max_inbound_frames); + seq_printf(seq, "Current Inbound Frames : %d\n", + sb->cur_inbound_frames); + seq_printf(seq, "Max Outbound Frames : %d\n", + sb->max_outbound_frames); + + /* Spec doesn't say if NULL terminated or not... */ + memcpy(prodstr, sb->product_id, 24); + prodstr[24] = '\0'; + seq_printf(seq, "Product ID : %s\n", prodstr); + seq_printf(seq, "Expected LCT Size : %d bytes\n", + sb->expected_lct_size); + + seq_printf(seq, "IOP Capabilities\n"); + seq_printf(seq, " Context Field Size Support : "); + switch (sb->iop_capabilities & 0x0000003) { + case 0: + seq_printf(seq, "Supports only 32-bit context fields\n"); + break; + case 1: + seq_printf(seq, "Supports only 64-bit context fields\n"); + break; + case 2: + seq_printf(seq, "Supports 32-bit and 64-bit context fields, " + "but not concurrently\n"); + break; + case 3: + seq_printf(seq, "Supports 32-bit and 64-bit context fields " + "concurrently\n"); + break; + default: + seq_printf(seq, "0x%08x\n", sb->iop_capabilities); + } + seq_printf(seq, " Current Context Field Size : "); + switch (sb->iop_capabilities & 0x0000000C) { + case 0: + seq_printf(seq, "not configured\n"); + break; + case 4: + seq_printf(seq, "Supports only 32-bit context fields\n"); + break; + case 8: + seq_printf(seq, "Supports only 64-bit context fields\n"); + break; + case 12: + seq_printf(seq, "Supports both 32-bit or 64-bit context fields " + "concurrently\n"); + break; + default: + seq_printf(seq, "\n"); + } + seq_printf(seq, " Inbound Peer Support : %s\n", + (sb-> + iop_capabilities & 0x00000010) ? "Supported" : + "Not supported"); + seq_printf(seq, " Outbound Peer Support : %s\n", + (sb-> + iop_capabilities & 0x00000020) ? "Supported" : + "Not supported"); + seq_printf(seq, " Peer to Peer Support : %s\n", + (sb-> + iop_capabilities & 0x00000040) ? "Supported" : + "Not supported"); + + seq_printf(seq, "Desired private memory size : %d kB\n", + sb->desired_mem_size >> 10); + seq_printf(seq, "Allocated private memory size : %d kB\n", + sb->current_mem_size >> 10); + seq_printf(seq, "Private memory base address : %0#10x\n", + sb->current_mem_base); + seq_printf(seq, "Desired private I/O size : %d kB\n", + sb->desired_io_size >> 10); + seq_printf(seq, "Allocated private I/O size : %d kB\n", + sb->current_io_size >> 10); + seq_printf(seq, "Private I/O base address : %0#10x\n", + sb->current_io_base); + + return 0; +} + +static int i2o_seq_show_hw(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + static u32 work32[5]; + static u8 *work8 = (u8 *) work32; + static u16 *work16 = (u16 *) work32; + int token; + u32 hwcap; + + static char *cpu_table[] = { + "Intel 80960 series", + "AMD2900 series", + "Motorola 68000 series", + "ARM series", + "MIPS series", + "Sparc series", + "PowerPC series", + "Intel x86 series" + }; + + token = + i2o_parm_field_get(c->exec, 0x0000, -1, &work32, sizeof(work32)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0x0000 IOP Hardware"); + return 0; + } + + seq_printf(seq, "I2O Vendor ID : %0#6x\n", work16[0]); + seq_printf(seq, "Product ID : %0#6x\n", work16[1]); + seq_printf(seq, "CPU : "); + if (work8[16] > 8) + seq_printf(seq, "Unknown\n"); + else + seq_printf(seq, "%s\n", cpu_table[work8[16]]); + /* Anyone using ProcessorVersion? */ + + seq_printf(seq, "RAM : %dkB\n", work32[1] >> 10); + seq_printf(seq, "Non-Volatile Mem : %dkB\n", work32[2] >> 10); + + hwcap = work32[3]; + seq_printf(seq, "Capabilities : 0x%08x\n", hwcap); + seq_printf(seq, " [%s] Self booting\n", + (hwcap & 0x00000001) ? "+" : "-"); + seq_printf(seq, " [%s] Upgradable IRTOS\n", + (hwcap & 0x00000002) ? "+" : "-"); + seq_printf(seq, " [%s] Supports downloading DDMs\n", + (hwcap & 0x00000004) ? "+" : "-"); + seq_printf(seq, " [%s] Supports installing DDMs\n", + (hwcap & 0x00000008) ? "+" : "-"); + seq_printf(seq, " [%s] Battery-backed RAM\n", + (hwcap & 0x00000010) ? "+" : "-"); + + return 0; +} + +/* Executive group 0003h - Executing DDM List (table) */ +static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + int token; + int i; + + typedef struct _i2o_exec_execute_ddm_table { + u16 ddm_tid; + u8 module_type; + u8 reserved; + u16 i2o_vendor_id; + u16 module_id; + u8 module_name_version[28]; + u32 data_size; + u32 code_size; + } i2o_exec_execute_ddm_table; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_exec_execute_ddm_table ddm_table[I2O_MAX_MODULES]; + } *result; + + i2o_exec_execute_ddm_table ddm_table; + char tmp[28 + 1]; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if (!result) + return -ENOMEM; + + token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0003, -1, + NULL, 0, result, sizeof(*result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0x0003 Executing DDM List"); + goto out; + } + + seq_printf(seq, + "Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size\n"); + ddm_table = result->ddm_table[0]; + + for (i = 0; i < result->row_count; ddm_table = result->ddm_table[++i]) { + seq_printf(seq, "0x%03x ", ddm_table.ddm_tid & 0xFFF); + + switch (ddm_table.module_type) { + case 0x01: + seq_printf(seq, "Downloaded DDM "); + break; + case 0x22: + seq_printf(seq, "Embedded DDM "); + break; + default: + seq_printf(seq, " "); + } + + seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id); + seq_printf(seq, "%-#8x", ddm_table.module_id); + seq_printf(seq, "%-29s", + chtostr(tmp, ddm_table.module_name_version, 28)); + seq_printf(seq, "%9d ", ddm_table.data_size); + seq_printf(seq, "%8d", ddm_table.code_size); + + seq_printf(seq, "\n"); + } + out: + kfree(result); + return 0; +} + +/* Executive group 0004h - Driver Store (scalar) */ +static int i2o_seq_show_driver_store(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + u32 work32[8]; + int token; + + token = + i2o_parm_field_get(c->exec, 0x0004, -1, &work32, sizeof(work32)); + if (token < 0) { + i2o_report_query_status(seq, token, "0x0004 Driver Store"); + return 0; + } + + seq_printf(seq, "Module limit : %d\n" + "Module count : %d\n" + "Current space : %d kB\n" + "Free space : %d kB\n", + work32[0], work32[1], work32[2] >> 10, work32[3] >> 10); + + return 0; +} + +/* Executive group 0005h - Driver Store Table (table) */ +static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) +{ + typedef struct _i2o_driver_store { + u16 stored_ddm_index; + u8 module_type; + u8 reserved; + u16 i2o_vendor_id; + u16 module_id; + u8 module_name_version[28]; + u8 date[8]; + u32 module_size; + u32 mpb_size; + u32 module_flags; + } i2o_driver_store_table; + + struct i2o_controller *c = (struct i2o_controller *)seq->private; + int token; + int i; + + typedef struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_driver_store_table dst[I2O_MAX_MODULES]; + } i2o_driver_result_table; + + i2o_driver_result_table *result; + i2o_driver_store_table *dst; + char tmp[28 + 1]; + + result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL); + if (result == NULL) + return -ENOMEM; + + token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0005, -1, + NULL, 0, result, sizeof(*result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0x0005 DRIVER STORE TABLE"); + kfree(result); + return 0; + } + + seq_printf(seq, + "# Module_type Vendor Mod_id Module_name Vrs" + "Date Mod_size Par_size Flags\n"); + for (i = 0, dst = &result->dst[0]; i < result->row_count; + dst = &result->dst[++i]) { + seq_printf(seq, "%-3d", dst->stored_ddm_index); + switch (dst->module_type) { + case 0x01: + seq_printf(seq, "Downloaded DDM "); + break; + case 0x22: + seq_printf(seq, "Embedded DDM "); + break; + default: + seq_printf(seq, " "); + } + + seq_printf(seq, "%-#7x", dst->i2o_vendor_id); + seq_printf(seq, "%-#8x", dst->module_id); + seq_printf(seq, "%-29s", + chtostr(tmp, dst->module_name_version, 28)); + seq_printf(seq, "%-9s", chtostr(tmp, dst->date, 8)); + seq_printf(seq, "%8d ", dst->module_size); + seq_printf(seq, "%8d ", dst->mpb_size); + seq_printf(seq, "0x%04x", dst->module_flags); + seq_printf(seq, "\n"); + } + + kfree(result); + return 0; +} + +/* Generic group F000h - Params Descriptor (table) */ +static int i2o_seq_show_groups(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + u8 properties; + + typedef struct _i2o_group_info { + u16 group_number; + u16 field_count; + u16 row_count; + u8 properties; + u8 reserved; + } i2o_group_info; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_group_info group[256]; + } *result; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if (!result) + return -ENOMEM; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, + result, sizeof(*result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF000 Params Descriptor"); + goto out; + } + + seq_printf(seq, + "# Group FieldCount RowCount Type Add Del Clear\n"); + + for (i = 0; i < result->row_count; i++) { + seq_printf(seq, "%-3d", i); + seq_printf(seq, "0x%04X ", result->group[i].group_number); + seq_printf(seq, "%10d ", result->group[i].field_count); + seq_printf(seq, "%8d ", result->group[i].row_count); + + properties = result->group[i].properties; + if (properties & 0x1) + seq_printf(seq, "Table "); + else + seq_printf(seq, "Scalar "); + if (properties & 0x2) + seq_printf(seq, " + "); + else + seq_printf(seq, " - "); + if (properties & 0x4) + seq_printf(seq, " + "); + else + seq_printf(seq, " - "); + if (properties & 0x8) + seq_printf(seq, " + "); + else + seq_printf(seq, " - "); + + seq_printf(seq, "\n"); + } + + if (result->more_flag) + seq_printf(seq, "There is more...\n"); + out: + kfree(result); + return 0; +} + +/* Generic group F001h - Physical Device Table (table) */ +static int i2o_seq_show_phys_device(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u32 adapter_id[64]; + } result; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF001, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF001 Physical Device Table"); + return 0; + } + + if (result.row_count) + seq_printf(seq, "# AdapterId\n"); + + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%-2d", i); + seq_printf(seq, "%#7x\n", result.adapter_id[i]); + } + + if (result.more_flag) + seq_printf(seq, "There is more...\n"); + + return 0; +} + +/* Generic group F002h - Claimed Table (table) */ +static int i2o_seq_show_claimed(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u16 claimed_tid[64]; + } result; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF002, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF002 Claimed Table"); + return 0; + } + + if (result.row_count) + seq_printf(seq, "# ClaimedTid\n"); + + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%-2d", i); + seq_printf(seq, "%#7x\n", result.claimed_tid[i]); + } + + if (result.more_flag) + seq_printf(seq, "There is more...\n"); + + return 0; +} + +/* Generic group F003h - User Table (table) */ +static int i2o_seq_show_users(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + typedef struct _i2o_user_table { + u16 instance; + u16 user_tid; + u8 claim_type; + u8 reserved1; + u16 reserved2; + } i2o_user_table; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_user_table user[64]; + } *result; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if (!result) + return -ENOMEM; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF003, -1, NULL, 0, + result, sizeof(*result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF003 User Table"); + goto out; + } + + seq_printf(seq, "# Instance UserTid ClaimType\n"); + + for (i = 0; i < result->row_count; i++) { + seq_printf(seq, "%-3d", i); + seq_printf(seq, "%#8x ", result->user[i].instance); + seq_printf(seq, "%#7x ", result->user[i].user_tid); + seq_printf(seq, "%#9x\n", result->user[i].claim_type); + } + + if (result->more_flag) + seq_printf(seq, "There is more...\n"); + out: + kfree(result); + return 0; +} + +/* Generic group F005h - Private message extensions (table) (optional) */ +static int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + typedef struct _i2o_private { + u16 ext_instance; + u16 organization_id; + u16 x_function_code; + } i2o_private; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_private extension[64]; + } result; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF005 Private Message Extensions (optional)"); + return 0; + } + + seq_printf(seq, "Instance# OrgId FunctionCode\n"); + + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%0#9x ", result.extension[i].ext_instance); + seq_printf(seq, "%0#6x ", result.extension[i].organization_id); + seq_printf(seq, "%0#6x", result.extension[i].x_function_code); + + seq_printf(seq, "\n"); + } + + if (result.more_flag) + seq_printf(seq, "There is more...\n"); + + return 0; +} + +/* Generic group F006h - Authorized User Table (table) */ +static int i2o_seq_show_authorized_users(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u32 alternate_tid[64]; + } result; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF006, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF006 Autohorized User Table"); + return 0; + } + + if (result.row_count) + seq_printf(seq, "# AlternateTid\n"); + + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%-2d", i); + seq_printf(seq, "%#7x ", result.alternate_tid[i]); + } + + if (result.more_flag) + seq_printf(seq, "There is more...\n"); + + return 0; +} + +/* Generic group F100h - Device Identity (scalar) */ +static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + static u32 work32[128]; // allow for "stuff" + up to 256 byte (max) serial number + // == (allow) 512d bytes (max) + static u16 *work16 = (u16 *) work32; + int token; + char tmp[16 + 1]; + + token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF100 Device Identity"); + return 0; + } + + seq_printf(seq, "Device Class : %s\n", i2o_get_class_name(work16[0])); + seq_printf(seq, "Owner TID : %0#5x\n", work16[2]); + seq_printf(seq, "Parent TID : %0#5x\n", work16[3]); + seq_printf(seq, "Vendor info : %s\n", + chtostr(tmp, (u8 *) (work32 + 2), 16)); + seq_printf(seq, "Product info : %s\n", + chtostr(tmp, (u8 *) (work32 + 6), 16)); + seq_printf(seq, "Description : %s\n", + chtostr(tmp, (u8 *) (work32 + 10), 16)); + seq_printf(seq, "Product rev. : %s\n", + chtostr(tmp, (u8 *) (work32 + 14), 8)); + + seq_printf(seq, "Serial number : "); + print_serial_number(seq, (u8 *) (work32 + 16), + /* allow for SNLen plus + * possible trailing '\0' + */ + sizeof(work32) - (16 * sizeof(u32)) - 2); + seq_printf(seq, "\n"); + + return 0; +} + +static int i2o_seq_show_dev_name(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + + seq_printf(seq, "%s\n", dev_name(&d->device)); + + return 0; +} + +/* Generic group F101h - DDM Identity (scalar) */ +static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + + struct { + u16 ddm_tid; + u8 module_name[24]; + u8 module_rev[8]; + u8 sn_format; + u8 serial_number[12]; + u8 pad[256]; // allow up to 256 byte (max) serial number + } result; + + char tmp[24 + 1]; + + token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF101 DDM Identity"); + return 0; + } + + seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid); + seq_printf(seq, "Module name : %s\n", + chtostr(tmp, result.module_name, 24)); + seq_printf(seq, "Module revision : %s\n", + chtostr(tmp, result.module_rev, 8)); + + seq_printf(seq, "Serial number : "); + print_serial_number(seq, result.serial_number, sizeof(result) - 36); + /* allow for SNLen plus possible trailing '\0' */ + + seq_printf(seq, "\n"); + + return 0; +} + +/* Generic group F102h - User Information (scalar) */ +static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + + struct { + u8 device_name[64]; + u8 service_name[64]; + u8 physical_location[64]; + u8 instance_number[4]; + } result; + + char tmp[64 + 1]; + + token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF102 User Information"); + return 0; + } + + seq_printf(seq, "Device name : %s\n", + chtostr(tmp, result.device_name, 64)); + seq_printf(seq, "Service name : %s\n", + chtostr(tmp, result.service_name, 64)); + seq_printf(seq, "Physical name : %s\n", + chtostr(tmp, result.physical_location, 64)); + seq_printf(seq, "Instance number : %s\n", + chtostr(tmp, result.instance_number, 4)); + + return 0; +} + +/* Generic group F103h - SGL Operating Limits (scalar) */ +static int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + static u32 work32[12]; + static u16 *work16 = (u16 *) work32; + static u8 *work8 = (u8 *) work32; + int token; + + token = i2o_parm_field_get(d, 0xF103, -1, &work32, sizeof(work32)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF103 SGL Operating Limits"); + return 0; + } + + seq_printf(seq, "SGL chain size : %d\n", work32[0]); + seq_printf(seq, "Max SGL chain size : %d\n", work32[1]); + seq_printf(seq, "SGL chain size target : %d\n", work32[2]); + seq_printf(seq, "SGL frag count : %d\n", work16[6]); + seq_printf(seq, "Max SGL frag count : %d\n", work16[7]); + seq_printf(seq, "SGL frag count target : %d\n", work16[8]); + +/* FIXME + if (d->i2oversion == 0x02) + { +*/ + seq_printf(seq, "SGL data alignment : %d\n", work16[8]); + seq_printf(seq, "SGL addr limit : %d\n", work8[20]); + seq_printf(seq, "SGL addr sizes supported : "); + if (work8[21] & 0x01) + seq_printf(seq, "32 bit "); + if (work8[21] & 0x02) + seq_printf(seq, "64 bit "); + if (work8[21] & 0x04) + seq_printf(seq, "96 bit "); + if (work8[21] & 0x08) + seq_printf(seq, "128 bit "); + seq_printf(seq, "\n"); +/* + } +*/ + + return 0; +} + +/* Generic group F200h - Sensors (scalar) */ +static int i2o_seq_show_sensors(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + + struct { + u16 sensor_instance; + u8 component; + u16 component_instance; + u8 sensor_class; + u8 sensor_type; + u8 scaling_exponent; + u32 actual_reading; + u32 minimum_reading; + u32 low2lowcat_treshold; + u32 lowcat2low_treshold; + u32 lowwarn2low_treshold; + u32 low2lowwarn_treshold; + u32 norm2lowwarn_treshold; + u32 lowwarn2norm_treshold; + u32 nominal_reading; + u32 hiwarn2norm_treshold; + u32 norm2hiwarn_treshold; + u32 high2hiwarn_treshold; + u32 hiwarn2high_treshold; + u32 hicat2high_treshold; + u32 hi2hicat_treshold; + u32 maximum_reading; + u8 sensor_state; + u16 event_enable; + } result; + + token = i2o_parm_field_get(d, 0xF200, -1, &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF200 Sensors (optional)"); + return 0; + } + + seq_printf(seq, "Sensor instance : %d\n", result.sensor_instance); + + seq_printf(seq, "Component : %d = ", result.component); + switch (result.component) { + case 0: + seq_printf(seq, "Other"); + break; + case 1: + seq_printf(seq, "Planar logic Board"); + break; + case 2: + seq_printf(seq, "CPU"); + break; + case 3: + seq_printf(seq, "Chassis"); + break; + case 4: + seq_printf(seq, "Power Supply"); + break; + case 5: + seq_printf(seq, "Storage"); + break; + case 6: + seq_printf(seq, "External"); + break; + } + seq_printf(seq, "\n"); + + seq_printf(seq, "Component instance : %d\n", + result.component_instance); + seq_printf(seq, "Sensor class : %s\n", + result.sensor_class ? "Analog" : "Digital"); + + seq_printf(seq, "Sensor type : %d = ", result.sensor_type); + switch (result.sensor_type) { + case 0: + seq_printf(seq, "Other\n"); + break; + case 1: + seq_printf(seq, "Thermal\n"); + break; + case 2: + seq_printf(seq, "DC voltage (DC volts)\n"); + break; + case 3: + seq_printf(seq, "AC voltage (AC volts)\n"); + break; + case 4: + seq_printf(seq, "DC current (DC amps)\n"); + break; + case 5: + seq_printf(seq, "AC current (AC volts)\n"); + break; + case 6: + seq_printf(seq, "Door open\n"); + break; + case 7: + seq_printf(seq, "Fan operational\n"); + break; + } + + seq_printf(seq, "Scaling exponent : %d\n", + result.scaling_exponent); + seq_printf(seq, "Actual reading : %d\n", result.actual_reading); + seq_printf(seq, "Minimum reading : %d\n", result.minimum_reading); + seq_printf(seq, "Low2LowCat treshold : %d\n", + result.low2lowcat_treshold); + seq_printf(seq, "LowCat2Low treshold : %d\n", + result.lowcat2low_treshold); + seq_printf(seq, "LowWarn2Low treshold : %d\n", + result.lowwarn2low_treshold); + seq_printf(seq, "Low2LowWarn treshold : %d\n", + result.low2lowwarn_treshold); + seq_printf(seq, "Norm2LowWarn treshold : %d\n", + result.norm2lowwarn_treshold); + seq_printf(seq, "LowWarn2Norm treshold : %d\n", + result.lowwarn2norm_treshold); + seq_printf(seq, "Nominal reading : %d\n", result.nominal_reading); + seq_printf(seq, "HiWarn2Norm treshold : %d\n", + result.hiwarn2norm_treshold); + seq_printf(seq, "Norm2HiWarn treshold : %d\n", + result.norm2hiwarn_treshold); + seq_printf(seq, "High2HiWarn treshold : %d\n", + result.high2hiwarn_treshold); + seq_printf(seq, "HiWarn2High treshold : %d\n", + result.hiwarn2high_treshold); + seq_printf(seq, "HiCat2High treshold : %d\n", + result.hicat2high_treshold); + seq_printf(seq, "High2HiCat treshold : %d\n", + result.hi2hicat_treshold); + seq_printf(seq, "Maximum reading : %d\n", result.maximum_reading); + + seq_printf(seq, "Sensor state : %d = ", result.sensor_state); + switch (result.sensor_state) { + case 0: + seq_printf(seq, "Normal\n"); + break; + case 1: + seq_printf(seq, "Abnormal\n"); + break; + case 2: + seq_printf(seq, "Unknown\n"); + break; + case 3: + seq_printf(seq, "Low Catastrophic (LoCat)\n"); + break; + case 4: + seq_printf(seq, "Low (Low)\n"); + break; + case 5: + seq_printf(seq, "Low Warning (LoWarn)\n"); + break; + case 6: + seq_printf(seq, "High Warning (HiWarn)\n"); + break; + case 7: + seq_printf(seq, "High (High)\n"); + break; + case 8: + seq_printf(seq, "High Catastrophic (HiCat)\n"); + break; + } + + seq_printf(seq, "Event_enable : 0x%02X\n", result.event_enable); + seq_printf(seq, " [%s] Operational state change. \n", + (result.event_enable & 0x01) ? "+" : "-"); + seq_printf(seq, " [%s] Low catastrophic. \n", + (result.event_enable & 0x02) ? "+" : "-"); + seq_printf(seq, " [%s] Low reading. \n", + (result.event_enable & 0x04) ? "+" : "-"); + seq_printf(seq, " [%s] Low warning. \n", + (result.event_enable & 0x08) ? "+" : "-"); + seq_printf(seq, + " [%s] Change back to normal from out of range state. \n", + (result.event_enable & 0x10) ? "+" : "-"); + seq_printf(seq, " [%s] High warning. \n", + (result.event_enable & 0x20) ? "+" : "-"); + seq_printf(seq, " [%s] High reading. \n", + (result.event_enable & 0x40) ? "+" : "-"); + seq_printf(seq, " [%s] High catastrophic. \n", + (result.event_enable & 0x80) ? "+" : "-"); + + return 0; +} + +static int i2o_seq_open_hrt(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_hrt, PDE_DATA(inode)); +}; + +static int i2o_seq_open_lct(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_lct, PDE_DATA(inode)); +}; + +static int i2o_seq_open_status(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_status, PDE_DATA(inode)); +}; + +static int i2o_seq_open_hw(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_hw, PDE_DATA(inode)); +}; + +static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_ddm_table, PDE_DATA(inode)); +}; + +static int i2o_seq_open_driver_store(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_driver_store, PDE_DATA(inode)); +}; + +static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_drivers_stored, PDE_DATA(inode)); +}; + +static int i2o_seq_open_groups(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_groups, PDE_DATA(inode)); +}; + +static int i2o_seq_open_phys_device(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_phys_device, PDE_DATA(inode)); +}; + +static int i2o_seq_open_claimed(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_claimed, PDE_DATA(inode)); +}; + +static int i2o_seq_open_users(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_users, PDE_DATA(inode)); +}; + +static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_priv_msgs, PDE_DATA(inode)); +}; + +static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_authorized_users, + PDE_DATA(inode)); +}; + +static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_dev_identity, PDE_DATA(inode)); +}; + +static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_ddm_identity, PDE_DATA(inode)); +}; + +static int i2o_seq_open_uinfo(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_uinfo, PDE_DATA(inode)); +}; + +static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_sgl_limits, PDE_DATA(inode)); +}; + +static int i2o_seq_open_sensors(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_sensors, PDE_DATA(inode)); +}; + +static int i2o_seq_open_dev_name(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_dev_name, PDE_DATA(inode)); +}; + +static const struct file_operations i2o_seq_fops_lct = { + .open = i2o_seq_open_lct, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_hrt = { + .open = i2o_seq_open_hrt, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_status = { + .open = i2o_seq_open_status, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_hw = { + .open = i2o_seq_open_hw, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_ddm_table = { + .open = i2o_seq_open_ddm_table, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_driver_store = { + .open = i2o_seq_open_driver_store, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_drivers_stored = { + .open = i2o_seq_open_drivers_stored, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_groups = { + .open = i2o_seq_open_groups, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_phys_device = { + .open = i2o_seq_open_phys_device, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_claimed = { + .open = i2o_seq_open_claimed, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_users = { + .open = i2o_seq_open_users, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_priv_msgs = { + .open = i2o_seq_open_priv_msgs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_authorized_users = { + .open = i2o_seq_open_authorized_users, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_dev_name = { + .open = i2o_seq_open_dev_name, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_dev_identity = { + .open = i2o_seq_open_dev_identity, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_ddm_identity = { + .open = i2o_seq_open_ddm_identity, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_uinfo = { + .open = i2o_seq_open_uinfo, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_sgl_limits = { + .open = i2o_seq_open_sgl_limits, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_sensors = { + .open = i2o_seq_open_sensors, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * IOP specific entries...write field just in case someone + * ever wants one. + */ +static i2o_proc_entry i2o_proc_generic_iop_entries[] = { + {"hrt", S_IFREG | S_IRUGO, &i2o_seq_fops_hrt}, + {"lct", S_IFREG | S_IRUGO, &i2o_seq_fops_lct}, + {"status", S_IFREG | S_IRUGO, &i2o_seq_fops_status}, + {"hw", S_IFREG | S_IRUGO, &i2o_seq_fops_hw}, + {"ddm_table", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_table}, + {"driver_store", S_IFREG | S_IRUGO, &i2o_seq_fops_driver_store}, + {"drivers_stored", S_IFREG | S_IRUGO, &i2o_seq_fops_drivers_stored}, + {NULL, 0, NULL} +}; + +/* + * Device specific entries + */ +static i2o_proc_entry generic_dev_entries[] = { + {"groups", S_IFREG | S_IRUGO, &i2o_seq_fops_groups}, + {"phys_dev", S_IFREG | S_IRUGO, &i2o_seq_fops_phys_device}, + {"claimed", S_IFREG | S_IRUGO, &i2o_seq_fops_claimed}, + {"users", S_IFREG | S_IRUGO, &i2o_seq_fops_users}, + {"priv_msgs", S_IFREG | S_IRUGO, &i2o_seq_fops_priv_msgs}, + {"authorized_users", S_IFREG | S_IRUGO, &i2o_seq_fops_authorized_users}, + {"dev_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_identity}, + {"ddm_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_identity}, + {"user_info", S_IFREG | S_IRUGO, &i2o_seq_fops_uinfo}, + {"sgl_limits", S_IFREG | S_IRUGO, &i2o_seq_fops_sgl_limits}, + {"sensors", S_IFREG | S_IRUGO, &i2o_seq_fops_sensors}, + {NULL, 0, NULL} +}; + +/* + * Storage unit specific entries (SCSI Periph, BS) with device names + */ +static i2o_proc_entry rbs_dev_entries[] = { + {"dev_name", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_name}, + {NULL, 0, NULL} +}; + +/** + * i2o_proc_create_entries - Creates proc dir entries + * @dir: proc dir entry under which the entries should be placed + * @i2o_pe: pointer to the entries which should be added + * @data: pointer to I2O controller or device + * + * Create proc dir entries for a I2O controller or I2O device. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_proc_create_entries(struct proc_dir_entry *dir, + i2o_proc_entry * i2o_pe, void *data) +{ + struct proc_dir_entry *tmp; + + while (i2o_pe->name) { + tmp = proc_create_data(i2o_pe->name, i2o_pe->mode, dir, + i2o_pe->fops, data); + if (!tmp) + return -1; + + i2o_pe++; + } + + return 0; +} + +/** + * i2o_proc_device_add - Add an I2O device to the proc dir + * @dir: proc dir entry to which the device should be added + * @dev: I2O device which should be added + * + * Add an I2O device to the proc dir entry dir and create the entries for + * the device depending on the class of the I2O device. + */ +static void i2o_proc_device_add(struct proc_dir_entry *dir, + struct i2o_device *dev) +{ + char buff[10]; + struct proc_dir_entry *devdir; + i2o_proc_entry *i2o_pe = NULL; + + sprintf(buff, "%03x", dev->lct_data.tid); + + osm_debug("adding device /proc/i2o/%s/%s\n", dev->iop->name, buff); + + devdir = proc_mkdir_data(buff, 0, dir, dev); + if (!devdir) { + osm_warn("Could not allocate procdir!\n"); + return; + } + + i2o_proc_create_entries(devdir, generic_dev_entries, dev); + + /* Inform core that we want updates about this device's status */ + switch (dev->lct_data.class_id) { + case I2O_CLASS_SCSI_PERIPHERAL: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_pe = rbs_dev_entries; + break; + default: + break; + } + if (i2o_pe) + i2o_proc_create_entries(devdir, i2o_pe, dev); +} + +/** + * i2o_proc_iop_add - Add an I2O controller to the i2o proc tree + * @dir: parent proc dir entry + * @c: I2O controller which should be added + * + * Add the entries to the parent proc dir entry. Also each device is added + * to the controllers proc dir entry. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_proc_iop_add(struct proc_dir_entry *dir, + struct i2o_controller *c) +{ + struct proc_dir_entry *iopdir; + struct i2o_device *dev; + + osm_debug("adding IOP /proc/i2o/%s\n", c->name); + + iopdir = proc_mkdir_data(c->name, 0, dir, c); + if (!iopdir) + return -1; + + i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c); + + list_for_each_entry(dev, &c->devices, list) + i2o_proc_device_add(iopdir, dev); + + return 0; +} + +/** + * i2o_proc_fs_create - Create the i2o proc fs. + * + * Iterate over each I2O controller and create the entries for it. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_proc_fs_create(void) +{ + struct i2o_controller *c; + + i2o_proc_dir_root = proc_mkdir("i2o", NULL); + if (!i2o_proc_dir_root) + return -1; + + list_for_each_entry(c, &i2o_controllers, list) + i2o_proc_iop_add(i2o_proc_dir_root, c); + + return 0; +}; + +/** + * i2o_proc_fs_destroy - Cleanup the all i2o proc entries + * + * Iterate over each I2O controller and remove the entries for it. + * + * Returns 0 on success or negative error code on failure. + */ +static int __exit i2o_proc_fs_destroy(void) +{ + remove_proc_subtree("i2o", NULL); + + return 0; +}; + +/** + * i2o_proc_init - Init function for procfs + * + * Registers Proc OSM and creates procfs entries. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_proc_init(void) +{ + int rc; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + rc = i2o_driver_register(&i2o_proc_driver); + if (rc) + return rc; + + rc = i2o_proc_fs_create(); + if (rc) { + i2o_driver_unregister(&i2o_proc_driver); + return rc; + } + + return 0; +}; + +/** + * i2o_proc_exit - Exit function for procfs + * + * Unregisters Proc OSM and removes procfs entries. + */ +static void __exit i2o_proc_exit(void) +{ + i2o_driver_unregister(&i2o_proc_driver); + i2o_proc_fs_destroy(); +}; + +MODULE_AUTHOR("Deepak Saxena"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_proc_init); +module_exit(i2o_proc_exit); diff --git a/drivers/staging/i2o/i2o_scsi.c b/drivers/staging/i2o/i2o_scsi.c new file mode 100644 index 00000000000..1b11dcb3fae --- /dev/null +++ b/drivers/staging/i2o/i2o_scsi.c @@ -0,0 +1,814 @@ +/* + * 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 + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open non patent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. + * + * Complications for I2O scsi + * + * o Each (bus,lun) is a logical device in I2O. We keep a map + * table. We spoof failed selection for unmapped units + * o Request sense buffers can come back for free. + * o Scatter gather is a bit dynamic. We have to investigate at + * setup time. + * o Some of our resources are dynamically shared. The i2o core + * needs a message reservation protocol to avoid swap v net + * deadlocking. We need to back off queue requests. + * + * In general the firmware wants to help. Where its help isn't performance + * useful we just ignore the aid. Its not worth the code in truth. + * + * Fixes/additions: + * Steve Ralston: + * Scatter gather now works + * Markus Lidel <Markus.Lidel@shadowconnect.com>: + * Minor fixes for 2.6. + * + * To Do: + * 64bit cleanups + * Fix the resource management problems. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/string.h> +#include <linux/ioport.h> +#include <linux/jiffies.h> +#include <linux/interrupt.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/proc_fs.h> +#include <linux/prefetch.h> +#include <linux/pci.h> +#include <linux/blkdev.h> +#include "i2o.h" +#include <linux/scatterlist.h> + +#include <asm/dma.h> +#include <asm/io.h> +#include <linux/atomic.h> + +#include <scsi/scsi.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/sg.h> + +#define OSM_NAME "scsi-osm" +#define OSM_VERSION "1.316" +#define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" + +static struct i2o_driver i2o_scsi_driver; + +static unsigned int i2o_scsi_max_id = 16; +static unsigned int i2o_scsi_max_lun = 255; + +struct i2o_scsi_host { + struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ + struct i2o_controller *iop; /* pointer to the I2O controller */ + u64 lun; /* lun's used for block devices */ + struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ +}; + +static struct scsi_host_template i2o_scsi_host_template; + +#define I2O_SCSI_CAN_QUEUE 4 + +/* SCSI OSM class handling definition */ +static struct i2o_class_id i2o_scsi_class_id[] = { + {I2O_CLASS_SCSI_PERIPHERAL}, + {I2O_CLASS_END} +}; + +static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) +{ + struct i2o_scsi_host *i2o_shost; + struct i2o_device *i2o_dev; + struct Scsi_Host *scsi_host; + int max_channel = 0; + u8 type; + int i; + size_t size; + u16 body_size = 6; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) + body_size = 8; +#endif + + list_for_each_entry(i2o_dev, &c->devices, list) + if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { + if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + && (type == 0x01)) /* SCSI bus */ + max_channel++; + } + + if (!max_channel) { + osm_warn("no channels found on %s\n", c->name); + return ERR_PTR(-EFAULT); + } + + size = max_channel * sizeof(struct i2o_device *) + + sizeof(struct i2o_scsi_host); + + scsi_host = scsi_host_alloc(&i2o_scsi_host_template, size); + if (!scsi_host) { + osm_warn("Could not allocate SCSI host\n"); + return ERR_PTR(-ENOMEM); + } + + scsi_host->max_channel = max_channel - 1; + scsi_host->max_id = i2o_scsi_max_id; + scsi_host->max_lun = i2o_scsi_max_lun; + scsi_host->this_id = c->unit; + scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size); + + i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; + i2o_shost->scsi_host = scsi_host; + i2o_shost->iop = c; + i2o_shost->lun = 1; + + i = 0; + list_for_each_entry(i2o_dev, &c->devices, list) + if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { + if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + && (type == 0x01)) /* only SCSI bus */ + i2o_shost->channel[i++] = i2o_dev; + + if (i >= max_channel) + break; + } + + return i2o_shost; +}; + +/** + * i2o_scsi_get_host - Get an I2O SCSI host + * @c: I2O controller to for which to get the SCSI host + * + * If the I2O controller already exists as SCSI host, the SCSI host + * is returned, otherwise the I2O controller is added to the SCSI + * core. + * + * Returns pointer to the I2O SCSI host on success or NULL on failure. + */ +static struct i2o_scsi_host *i2o_scsi_get_host(struct i2o_controller *c) +{ + return c->driver_data[i2o_scsi_driver.context]; +}; + +/** + * i2o_scsi_remove - Remove I2O device from SCSI core + * @dev: device which should be removed + * + * Removes the I2O device from the SCSI core again. + * + * Returns 0 on success. + */ +static int i2o_scsi_remove(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_controller *c = i2o_dev->iop; + struct i2o_scsi_host *i2o_shost; + struct scsi_device *scsi_dev; + + osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); + + i2o_shost = i2o_scsi_get_host(c); + + shost_for_each_device(scsi_dev, i2o_shost->scsi_host) + if (scsi_dev->hostdata == i2o_dev) { + sysfs_remove_link(&i2o_dev->device.kobj, "scsi"); + scsi_remove_device(scsi_dev); + scsi_device_put(scsi_dev); + break; + } + + return 0; +}; + +/** + * i2o_scsi_probe - verify if dev is a I2O SCSI device and install it + * @dev: device to verify if it is a I2O SCSI device + * + * Retrieve channel, id and lun for I2O device. If everything goes well + * register the I2O device as SCSI device on the I2O SCSI controller. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_scsi_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_controller *c = i2o_dev->iop; + struct i2o_scsi_host *i2o_shost; + struct Scsi_Host *scsi_host; + struct i2o_device *parent; + struct scsi_device *scsi_dev; + u32 id = -1; + u64 lun = -1; + int channel = -1; + int i, rc; + + i2o_shost = i2o_scsi_get_host(c); + if (!i2o_shost) + return -EFAULT; + + scsi_host = i2o_shost->scsi_host; + + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + case I2O_CLASS_EXECUTIVE: +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u8 type; + struct i2o_device *d = i2o_shost->channel[0]; + + if (!i2o_parm_field_get(d, 0x0000, 0, &type, 1) + && (type == 0x01)) /* SCSI bus */ + if (!i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { + channel = 0; + if (i2o_dev->lct_data.class_id == + I2O_CLASS_RANDOM_BLOCK_STORAGE) + lun = + cpu_to_le64(i2o_shost-> + lun++); + else + lun = 0; + } + } +#endif + break; + + case I2O_CLASS_SCSI_PERIPHERAL: + if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4)) + return -EFAULT; + + if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8)) + return -EFAULT; + + parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); + if (!parent) { + osm_warn("can not find parent of device %03x\n", + i2o_dev->lct_data.tid); + return -EFAULT; + } + + for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) + if (i2o_shost->channel[i] == parent) + channel = i; + break; + + default: + return -EFAULT; + } + + if (channel == -1) { + osm_warn("can not find channel of device %03x\n", + i2o_dev->lct_data.tid); + return -EFAULT; + } + + if (le32_to_cpu(id) >= scsi_host->max_id) { + osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", + le32_to_cpu(id), scsi_host->max_id); + return -EFAULT; + } + + if (le64_to_cpu(lun) >= scsi_host->max_lun) { + osm_warn("SCSI device lun (%llu) >= max_lun of I2O host (%llu)", + le64_to_cpu(lun), scsi_host->max_lun); + return -EFAULT; + } + + scsi_dev = + __scsi_add_device(i2o_shost->scsi_host, channel, le32_to_cpu(id), + le64_to_cpu(lun), i2o_dev); + + if (IS_ERR(scsi_dev)) { + osm_warn("can not add SCSI device %03x\n", + i2o_dev->lct_data.tid); + return PTR_ERR(scsi_dev); + } + + rc = sysfs_create_link(&i2o_dev->device.kobj, + &scsi_dev->sdev_gendev.kobj, "scsi"); + if (rc) + goto err; + + osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %llu\n", + i2o_dev->lct_data.tid, channel, le32_to_cpu(id), + le64_to_cpu(lun)); + + return 0; + +err: + scsi_remove_device(scsi_dev); + return rc; +}; + +static const char *i2o_scsi_info(struct Scsi_Host *SChost) +{ + struct i2o_scsi_host *hostdata; + hostdata = (struct i2o_scsi_host *)SChost->hostdata; + return hostdata->iop->name; +} + +/** + * i2o_scsi_reply - SCSI OSM message reply handler + * @c: controller issuing the reply + * @m: message id for flushing + * @msg: the message from the controller + * + * Process reply messages (interrupts in normal scsi controller think). + * We can get a variety of messages to process. The normal path is + * scsi command completions. We must also deal with IOP failures, + * the reply to a bus reset and the reply to a LUN query. + * + * Returns 0 on success and if the reply should not be flushed or > 0 + * on success and if the reply should be flushed. Returns negative error + * code on failure and if the reply should be flushed. + */ +static int i2o_scsi_reply(struct i2o_controller *c, u32 m, + struct i2o_message *msg) +{ + struct scsi_cmnd *cmd; + u32 error; + struct device *dev; + + cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); + if (unlikely(!cmd)) { + osm_err("NULL reply received!\n"); + return -1; + } + + /* + * Low byte is device status, next is adapter status, + * (then one byte reserved), then request status. + */ + error = le32_to_cpu(msg->body[0]); + + osm_debug("Completed %0x%p\n", cmd); + + cmd->result = error & 0xff; + /* + * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let + * the SCSI layer handle the error + */ + if (cmd->result) + memcpy(cmd->sense_buffer, &msg->body[3], + min(SCSI_SENSE_BUFFERSIZE, 40)); + + /* only output error code if AdapterStatus is not HBA_SUCCESS */ + if ((error >> 8) & 0xff) + osm_err("SCSI error %08x\n", error); + + dev = &c->pdev->dev; + + scsi_dma_unmap(cmd); + + cmd->scsi_done(cmd); + + return 1; +}; + +/** + * i2o_scsi_notify_device_add - Retrieve notifications of added devices + * @i2o_dev: the I2O device which was added + * + * If a I2O device is added we catch the notification, because I2O classes + * other than SCSI peripheral will not be received through + * i2o_scsi_probe(). + */ +static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) +{ + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_scsi_probe(&i2o_dev->device); + break; + + default: + break; + } +}; + +/** + * i2o_scsi_notify_device_remove - Retrieve notifications of removed devices + * @i2o_dev: the I2O device which was removed + * + * If a I2O device is removed, we catch the notification to remove the + * corresponding SCSI device. + */ +static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev) +{ + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_scsi_remove(&i2o_dev->device); + break; + + default: + break; + } +}; + +/** + * i2o_scsi_notify_controller_add - Retrieve notifications of added controllers + * @c: the controller which was added + * + * If a I2O controller is added, we catch the notification to add a + * corresponding Scsi_Host. + */ +static void i2o_scsi_notify_controller_add(struct i2o_controller *c) +{ + struct i2o_scsi_host *i2o_shost; + int rc; + + i2o_shost = i2o_scsi_host_alloc(c); + if (IS_ERR(i2o_shost)) { + osm_err("Could not initialize SCSI host\n"); + return; + } + + rc = scsi_add_host(i2o_shost->scsi_host, &c->device); + if (rc) { + osm_err("Could not add SCSI host\n"); + scsi_host_put(i2o_shost->scsi_host); + return; + } + + c->driver_data[i2o_scsi_driver.context] = i2o_shost; + + osm_debug("new I2O SCSI host added\n"); +}; + +/** + * i2o_scsi_notify_controller_remove - Retrieve notifications of removed controllers + * @c: the controller which was removed + * + * If a I2O controller is removed, we catch the notification to remove the + * corresponding Scsi_Host. + */ +static void i2o_scsi_notify_controller_remove(struct i2o_controller *c) +{ + struct i2o_scsi_host *i2o_shost; + i2o_shost = i2o_scsi_get_host(c); + if (!i2o_shost) + return; + + c->driver_data[i2o_scsi_driver.context] = NULL; + + scsi_remove_host(i2o_shost->scsi_host); + scsi_host_put(i2o_shost->scsi_host); + osm_debug("I2O SCSI host removed\n"); +}; + +/* SCSI OSM driver struct */ +static struct i2o_driver i2o_scsi_driver = { + .name = OSM_NAME, + .reply = i2o_scsi_reply, + .classes = i2o_scsi_class_id, + .notify_device_add = i2o_scsi_notify_device_add, + .notify_device_remove = i2o_scsi_notify_device_remove, + .notify_controller_add = i2o_scsi_notify_controller_add, + .notify_controller_remove = i2o_scsi_notify_controller_remove, + .driver = { + .probe = i2o_scsi_probe, + .remove = i2o_scsi_remove, + }, +}; + +/** + * i2o_scsi_queuecommand - queue a SCSI command + * @SCpnt: scsi command pointer + * @done: callback for completion + * + * Issue a scsi command asynchronously. Return 0 on success or 1 if + * we hit an error (normally message queue congestion). The only + * minor complication here is that I2O deals with the device addressing + * so we have to map the bus/dev/lun back to an I2O handle as well + * as faking absent devices ourself. + * + * Locks: takes the controller lock on error path only + */ + +static int i2o_scsi_queuecommand_lck(struct scsi_cmnd *SCpnt, + void (*done) (struct scsi_cmnd *)) +{ + struct i2o_controller *c; + struct i2o_device *i2o_dev; + int tid; + struct i2o_message *msg; + /* + * ENABLE_DISCONNECT + * SIMPLE_TAG + * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME + */ + u32 scsi_flags = 0x20a00000; + u32 sgl_offset; + u32 *mptr; + u32 cmd = I2O_CMD_SCSI_EXEC << 24; + int rc = 0; + + /* + * Do the incoming paperwork + */ + i2o_dev = SCpnt->device->hostdata; + + SCpnt->scsi_done = done; + + if (unlikely(!i2o_dev)) { + osm_warn("no I2O device in request\n"); + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + goto exit; + } + c = i2o_dev->iop; + tid = i2o_dev->lct_data.tid; + + osm_debug("qcmd: Tid = %03x\n", tid); + osm_debug("Real scsi messages.\n"); + + /* + * Put together a scsi execscb message + */ + switch (SCpnt->sc_data_direction) { + case PCI_DMA_NONE: + /* DATA NO XFER */ + sgl_offset = SGL_OFFSET_0; + break; + + case PCI_DMA_TODEVICE: + /* DATA OUT (iop-->dev) */ + scsi_flags |= 0x80000000; + sgl_offset = SGL_OFFSET_10; + break; + + case PCI_DMA_FROMDEVICE: + /* DATA IN (iop<--dev) */ + scsi_flags |= 0x40000000; + sgl_offset = SGL_OFFSET_10; + break; + + default: + /* Unknown - kill the command */ + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + goto exit; + } + + /* + * Obtain an I2O message. If there are none free then + * throw it back to the scsi layer + */ + + msg = i2o_msg_get(c); + if (IS_ERR(msg)) { + rc = SCSI_MLQUEUE_HOST_BUSY; + goto exit; + } + + mptr = &msg->body[0]; + +#if 0 /* this code can't work */ +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u32 adpt_flags = 0; + + if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) { + i2o_sg_io_hdr_t __user *usr_ptr = + ((Sg_request *) (SCpnt->sc_request-> + upper_private_data))->header. + usr_ptr; + + if (usr_ptr) + get_user(adpt_flags, &usr_ptr->flags); + } + + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + /* interpret flag has to be set for executive */ + adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET; + break; + + default: + break; + } + + /* + * for Adaptec controllers we use the PRIVATE command, because + * the normal SCSI EXEC doesn't support all SCSI commands on + * all controllers (for example READ CAPACITY). + */ + if (sgl_offset == SGL_OFFSET_10) + sgl_offset = SGL_OFFSET_12; + cmd = I2O_CMD_PRIVATE << 24; + *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); + *mptr++ = cpu_to_le32(adpt_flags | tid); + } +#endif +#endif + + msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); + msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context); + + /* We want the SCSI control block back */ + msg->u.s.tcntxt = cpu_to_le32(i2o_cntxt_list_add(c, SCpnt)); + + /* LSI_920_PCI_QUIRK + * + * Intermittant observations of msg frame word data corruption + * observed on msg[4] after: + * WRITE, READ-MODIFY-WRITE + * operations. 19990606 -sralston + * + * (Hence we build this word via tag. Its good practice anyway + * we don't want fetches over PCI needlessly) + */ + + /* Attach tags to the devices */ + /* FIXME: implement + if(SCpnt->device->tagged_supported) { + if(SCpnt->tag == HEAD_OF_QUEUE_TAG) + scsi_flags |= 0x01000000; + else if(SCpnt->tag == ORDERED_QUEUE_TAG) + scsi_flags |= 0x01800000; + } + */ + + *mptr++ = cpu_to_le32(scsi_flags | SCpnt->cmd_len); + + /* Write SCSI command into the message - always 16 byte block */ + memcpy(mptr, SCpnt->cmnd, 16); + mptr += 4; + + if (sgl_offset != SGL_OFFSET_0) { + /* write size of data addressed by SGL */ + *mptr++ = cpu_to_le32(scsi_bufflen(SCpnt)); + + /* Now fill in the SGList and command */ + + if (scsi_sg_count(SCpnt)) { + if (!i2o_dma_map_sg(c, scsi_sglist(SCpnt), + scsi_sg_count(SCpnt), + SCpnt->sc_data_direction, &mptr)) + goto nomem; + } + } + + /* Stick the headers on */ + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); + + /* Queue the message */ + i2o_msg_post(c, msg); + + osm_debug("Issued %0x%p\n", SCpnt); + + return 0; + + nomem: + rc = -ENOMEM; + i2o_msg_nop(c, msg); + + exit: + return rc; +} + +static DEF_SCSI_QCMD(i2o_scsi_queuecommand) + +/** + * i2o_scsi_abort - abort a running command + * @SCpnt: command to abort + * + * Ask the I2O controller to abort a command. This is an asynchrnous + * process and our callback handler will see the command complete with an + * aborted message if it succeeds. + * + * Returns 0 if the command is successfully aborted or negative error code + * on failure. + */ +static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) +{ + struct i2o_device *i2o_dev; + struct i2o_controller *c; + struct i2o_message *msg; + int tid; + int status = FAILED; + + osm_warn("Aborting command block.\n"); + + i2o_dev = SCpnt->device->hostdata; + c = i2o_dev->iop; + tid = i2o_dev->lct_data.tid; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return SCSI_MLQUEUE_HOST_BUSY; + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); + msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); + + if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) + status = SUCCESS; + + return status; +} + +/** + * i2o_scsi_bios_param - Invent disk geometry + * @sdev: scsi device + * @dev: block layer device + * @capacity: size in sectors + * @ip: geometry array + * + * This is anyone's guess quite frankly. We use the same rules everyone + * else appears to and hope. It seems to work. + */ + +static int i2o_scsi_bios_param(struct scsi_device *sdev, + struct block_device *dev, sector_t capacity, + int *ip) +{ + int size; + + size = capacity; + ip[0] = 64; /* heads */ + ip[1] = 32; /* sectors */ + if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */ + ip[0] = 255; /* heads */ + ip[1] = 63; /* sectors */ + ip[2] = size / (255 * 63); /* cylinders */ + } + return 0; +} + +static struct scsi_host_template i2o_scsi_host_template = { + .proc_name = OSM_NAME, + .name = OSM_DESCRIPTION, + .info = i2o_scsi_info, + .queuecommand = i2o_scsi_queuecommand, + .eh_abort_handler = i2o_scsi_abort, + .bios_param = i2o_scsi_bios_param, + .can_queue = I2O_SCSI_CAN_QUEUE, + .sg_tablesize = 8, + .cmd_per_lun = 6, + .use_clustering = ENABLE_CLUSTERING, +}; + +/** + * i2o_scsi_init - SCSI OSM initialization function + * + * Register SCSI OSM into I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_scsi_init(void) +{ + int rc; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + /* Register SCSI OSM into I2O core */ + rc = i2o_driver_register(&i2o_scsi_driver); + if (rc) { + osm_err("Could not register SCSI driver\n"); + return rc; + } + + return 0; +}; + +/** + * i2o_scsi_exit - SCSI OSM exit function + * + * Unregisters SCSI OSM from I2O core. + */ +static void __exit i2o_scsi_exit(void) +{ + /* Unregister I2O SCSI OSM from I2O core */ + i2o_driver_unregister(&i2o_scsi_driver); +}; + +MODULE_AUTHOR("Red Hat Software"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_scsi_init); +module_exit(i2o_scsi_exit); diff --git a/drivers/staging/i2o/iop.c b/drivers/staging/i2o/iop.c new file mode 100644 index 00000000000..52334fc8b54 --- /dev/null +++ b/drivers/staging/i2o/iop.c @@ -0,0 +1,1247 @@ +/* + * Functions to handle I2O controllers and I2O message handling + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * 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 of the License, or (at your + * option) any later version. + * + * A lot of the I2O message side code from this is taken from the + * Red Creek RCPCI45 adapter driver by Red Creek Communications + * + * Fixes/additions: + * Philipp Rumpf + * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> + * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> + * Deepak Saxena <deepak@plexity.net> + * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> + * Alan Cox <alan@lxorguk.ukuu.org.uk>: + * Ported to Linux 2.5. + * Markus Lidel <Markus.Lidel@shadowconnect.com>: + * Minor fixes for 2.6. + */ + +#include <linux/module.h> +#include "i2o.h" +#include <linux/delay.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include "core.h" + +#define OSM_NAME "i2o" +#define OSM_VERSION "1.325" +#define OSM_DESCRIPTION "I2O subsystem" + +/* global I2O controller list */ +LIST_HEAD(i2o_controllers); + +/* + * global I2O System Table. Contains information about all the IOPs in the + * system. Used to inform IOPs about each others existence. + */ +static struct i2o_dma i2o_systab; + +static int i2o_hrt_get(struct i2o_controller *c); + +/** + * i2o_msg_get_wait - obtain an I2O message from the IOP + * @c: I2O controller + * @wait: how long to wait until timeout + * + * This function waits up to wait seconds for a message slot to be + * available. + * + * On a success the message is returned and the pointer to the message is + * set in msg. The returned message is the physical page frame offset + * address from the read port (see the i2o spec). If no message is + * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. + */ +struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait) +{ + unsigned long timeout = jiffies + wait * HZ; + struct i2o_message *msg; + + while (IS_ERR(msg = i2o_msg_get(c))) { + if (time_after(jiffies, timeout)) { + osm_debug("%s: Timeout waiting for message frame.\n", + c->name); + return ERR_PTR(-ETIMEDOUT); + } + schedule_timeout_uninterruptible(1); + } + + return msg; +}; + +#if BITS_PER_LONG == 64 +/** + * i2o_cntxt_list_add - Append a pointer to context list and return a id + * @c: controller to which the context list belong + * @ptr: pointer to add to the context list + * + * Because the context field in I2O is only 32-bit large, on 64-bit the + * pointer is to large to fit in the context field. The i2o_cntxt_list + * functions therefore map pointers to context fields. + * + * Returns context id > 0 on success or 0 on failure. + */ +u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) +{ + struct i2o_context_list_element *entry; + unsigned long flags; + + if (!ptr) + osm_err("%s: couldn't add NULL pointer to context list!\n", + c->name); + + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) { + osm_err("%s: Could not allocate memory for context list element" + "\n", c->name); + return 0; + } + + entry->ptr = ptr; + entry->timestamp = jiffies; + INIT_LIST_HEAD(&entry->list); + + spin_lock_irqsave(&c->context_list_lock, flags); + + if (unlikely(atomic_inc_and_test(&c->context_list_counter))) + atomic_inc(&c->context_list_counter); + + entry->context = atomic_read(&c->context_list_counter); + + list_add(&entry->list, &c->context_list); + + spin_unlock_irqrestore(&c->context_list_lock, flags); + + osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); + + return entry->context; +}; + +/** + * i2o_cntxt_list_remove - Remove a pointer from the context list + * @c: controller to which the context list belong + * @ptr: pointer which should be removed from the context list + * + * Removes a previously added pointer from the context list and returns + * the matching context id. + * + * Returns context id on success or 0 on failure. + */ +u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) +{ + struct i2o_context_list_element *entry; + u32 context = 0; + unsigned long flags; + + spin_lock_irqsave(&c->context_list_lock, flags); + list_for_each_entry(entry, &c->context_list, list) + if (entry->ptr == ptr) { + list_del(&entry->list); + context = entry->context; + kfree(entry); + break; + } + spin_unlock_irqrestore(&c->context_list_lock, flags); + + if (!context) + osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name, + ptr); + + osm_debug("%s: remove ptr from context list %d -> %p\n", c->name, + context, ptr); + + return context; +}; + +/** + * i2o_cntxt_list_get - Get a pointer from the context list and remove it + * @c: controller to which the context list belong + * @context: context id to which the pointer belong + * + * Returns pointer to the matching context id on success or NULL on + * failure. + */ +void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) +{ + struct i2o_context_list_element *entry; + unsigned long flags; + void *ptr = NULL; + + spin_lock_irqsave(&c->context_list_lock, flags); + list_for_each_entry(entry, &c->context_list, list) + if (entry->context == context) { + list_del(&entry->list); + ptr = entry->ptr; + kfree(entry); + break; + } + spin_unlock_irqrestore(&c->context_list_lock, flags); + + if (!ptr) + osm_warn("%s: context id %d not found\n", c->name, context); + + osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context, + ptr); + + return ptr; +}; + +/** + * i2o_cntxt_list_get_ptr - Get a context id from the context list + * @c: controller to which the context list belong + * @ptr: pointer to which the context id should be fetched + * + * Returns context id which matches to the pointer on success or 0 on + * failure. + */ +u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr) +{ + struct i2o_context_list_element *entry; + u32 context = 0; + unsigned long flags; + + spin_lock_irqsave(&c->context_list_lock, flags); + list_for_each_entry(entry, &c->context_list, list) + if (entry->ptr == ptr) { + context = entry->context; + break; + } + spin_unlock_irqrestore(&c->context_list_lock, flags); + + if (!context) + osm_warn("%s: Could not find nonexistent ptr %p\n", c->name, + ptr); + + osm_debug("%s: get context id from context list %p -> %d\n", c->name, + ptr, context); + + return context; +}; +#endif + +/** + * i2o_iop_find - Find an I2O controller by id + * @unit: unit number of the I2O controller to search for + * + * Lookup the I2O controller on the controller list. + * + * Returns pointer to the I2O controller on success or NULL if not found. + */ +struct i2o_controller *i2o_find_iop(int unit) +{ + struct i2o_controller *c; + + list_for_each_entry(c, &i2o_controllers, list) { + if (c->unit == unit) + return c; + } + + return NULL; +}; + +/** + * i2o_iop_find_device - Find a I2O device on an I2O controller + * @c: I2O controller where the I2O device hangs on + * @tid: TID of the I2O device to search for + * + * Searches the devices of the I2O controller for a device with TID tid and + * returns it. + * + * Returns a pointer to the I2O device if found, otherwise NULL. + */ +struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid) +{ + struct i2o_device *dev; + + list_for_each_entry(dev, &c->devices, list) + if (dev->lct_data.tid == tid) + return dev; + + return NULL; +}; + +/** + * i2o_quiesce_controller - quiesce controller + * @c: controller + * + * Quiesce an IOP. Causes IOP to make external operation quiescent + * (i2o 'READY' state). Internal operation of the IOP continues normally. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_quiesce(struct i2o_controller *c) +{ + struct i2o_message *msg; + i2o_status_block *sb = c->status_block.virt; + int rc; + + i2o_status_get(c); + + /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */ + if ((sb->iop_state != ADAPTER_STATE_READY) && + (sb->iop_state != ADAPTER_STATE_OPERATIONAL)) + return 0; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | + ADAPTER_TID); + + /* Long timeout needed for quiesce if lots of devices */ + if ((rc = i2o_msg_post_wait(c, msg, 240))) + osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc); + else + osm_debug("%s: Quiesced.\n", c->name); + + i2o_status_get(c); // Entered READY state + + return rc; +}; + +/** + * i2o_iop_enable - move controller from ready to OPERATIONAL + * @c: I2O controller + * + * Enable IOP. This allows the IOP to resume external operations and + * reverses the effect of a quiesce. Returns zero or an error code if + * an error occurs. + */ +static int i2o_iop_enable(struct i2o_controller *c) +{ + struct i2o_message *msg; + i2o_status_block *sb = c->status_block.virt; + int rc; + + i2o_status_get(c); + + /* Enable only allowed on READY state */ + if (sb->iop_state != ADAPTER_STATE_READY) + return -EINVAL; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | + ADAPTER_TID); + + /* How long of a timeout do we need? */ + if ((rc = i2o_msg_post_wait(c, msg, 240))) + osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc); + else + osm_debug("%s: Enabled.\n", c->name); + + i2o_status_get(c); // entered OPERATIONAL state + + return rc; +}; + +/** + * i2o_iop_quiesce_all - Quiesce all I2O controllers on the system + * + * Quiesce all I2O controllers which are connected to the system. + */ +static inline void i2o_iop_quiesce_all(void) +{ + struct i2o_controller *c, *tmp; + + list_for_each_entry_safe(c, tmp, &i2o_controllers, list) { + if (!c->no_quiesce) + i2o_iop_quiesce(c); + } +}; + +/** + * i2o_iop_enable_all - Enables all controllers on the system + * + * Enables all I2O controllers which are connected to the system. + */ +static inline void i2o_iop_enable_all(void) +{ + struct i2o_controller *c, *tmp; + + list_for_each_entry_safe(c, tmp, &i2o_controllers, list) + i2o_iop_enable(c); +}; + +/** + * i2o_clear_controller - Bring I2O controller into HOLD state + * @c: controller + * + * Clear an IOP to HOLD state, ie. terminate external operations, clear all + * input queues and prepare for a system restart. IOP's internal operation + * continues normally and the outbound queue is alive. The IOP is not + * expected to rebuild its LCT. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_clear(struct i2o_controller *c) +{ + struct i2o_message *msg; + int rc; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + /* Quiesce all IOPs first */ + i2o_iop_quiesce_all(); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | + ADAPTER_TID); + + if ((rc = i2o_msg_post_wait(c, msg, 30))) + osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc); + else + osm_debug("%s: Cleared.\n", c->name); + + /* Enable all IOPs */ + i2o_iop_enable_all(); + + return rc; +} + +/** + * i2o_iop_init_outbound_queue - setup the outbound message queue + * @c: I2O controller + * + * Clear and (re)initialize IOP's outbound queue and post the message + * frames to the IOP. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_init_outbound_queue(struct i2o_controller *c) +{ + u32 m; + volatile u8 *status = c->status.virt; + struct i2o_message *msg; + ulong timeout; + int i; + + osm_debug("%s: Initializing Outbound Queue...\n", c->name); + + memset(c->status.virt, 0, 4); + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(PAGE_SIZE); + /* Outbound msg frame size in words and Initcode */ + msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80); + msg->body[2] = cpu_to_le32(0xd0000004); + msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys)); + msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys)); + + i2o_msg_post(c, msg); + + timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; + while (*status <= I2O_CMD_IN_PROGRESS) { + if (time_after(jiffies, timeout)) { + osm_warn("%s: Timeout Initializing\n", c->name); + return -ETIMEDOUT; + } + schedule_timeout_uninterruptible(1); + } + + m = c->out_queue.phys; + + /* Post frames */ + for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) { + i2o_flush_reply(c, m); + udelay(1); /* Promise */ + m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32); + } + + return 0; +} + +/** + * i2o_iop_reset - reset an I2O controller + * @c: controller to reset + * + * Reset the IOP into INIT state and wait until IOP gets into RESET state. + * Terminate all external operations, clear IOP's inbound and outbound + * queues, terminate all DDMs, and reload the IOP's operating environment + * and all local DDMs. The IOP rebuilds its LCT. + */ +static int i2o_iop_reset(struct i2o_controller *c) +{ + volatile u8 *status = c->status.virt; + struct i2o_message *msg; + unsigned long timeout; + i2o_status_block *sb = c->status_block.virt; + int rc = 0; + + osm_debug("%s: Resetting controller\n", c->name); + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + memset(c->status_block.virt, 0, 8); + + /* Quiesce all IOPs first */ + i2o_iop_quiesce_all(); + + msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(0x00000000); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys)); + msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys)); + + i2o_msg_post(c, msg); + + /* Wait for a reply */ + timeout = jiffies + I2O_TIMEOUT_RESET * HZ; + while (!*status) { + if (time_after(jiffies, timeout)) + break; + + schedule_timeout_uninterruptible(1); + } + + switch (*status) { + case I2O_CMD_REJECTED: + osm_warn("%s: IOP reset rejected\n", c->name); + rc = -EPERM; + break; + + case I2O_CMD_IN_PROGRESS: + /* + * Once the reset is sent, the IOP goes into the INIT state + * which is indeterminate. We need to wait until the IOP has + * rebooted before we can let the system talk to it. We read + * the inbound Free_List until a message is available. If we + * can't read one in the given amount of time, we assume the + * IOP could not reboot properly. + */ + osm_debug("%s: Reset in progress, waiting for reboot...\n", + c->name); + + while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) { + if (time_after(jiffies, timeout)) { + osm_err("%s: IOP reset timeout.\n", c->name); + rc = PTR_ERR(msg); + goto exit; + } + schedule_timeout_uninterruptible(1); + } + i2o_msg_nop(c, msg); + + /* from here all quiesce commands are safe */ + c->no_quiesce = 0; + + /* verify if controller is in state RESET */ + i2o_status_get(c); + + if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET)) + osm_warn("%s: reset completed, but adapter not in RESET" + " state.\n", c->name); + else + osm_debug("%s: reset completed.\n", c->name); + + break; + + default: + osm_err("%s: IOP reset timeout.\n", c->name); + rc = -ETIMEDOUT; + break; + } + + exit: + /* Enable all IOPs */ + i2o_iop_enable_all(); + + return rc; +}; + +/** + * i2o_iop_activate - Bring controller up to HOLD + * @c: controller + * + * This function brings an I2O controller into HOLD state. The adapter + * is reset if necessary and then the queues and resource table are read. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_activate(struct i2o_controller *c) +{ + i2o_status_block *sb = c->status_block.virt; + int rc; + int state; + + /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ + /* In READY state, Get status */ + + rc = i2o_status_get(c); + if (rc) { + osm_info("%s: Unable to obtain status, attempting a reset.\n", + c->name); + rc = i2o_iop_reset(c); + if (rc) + return rc; + } + + if (sb->i2o_version > I2OVER15) { + osm_err("%s: Not running version 1.5 of the I2O Specification." + "\n", c->name); + return -ENODEV; + } + + switch (sb->iop_state) { + case ADAPTER_STATE_FAULTED: + osm_err("%s: hardware fault\n", c->name); + return -EFAULT; + + case ADAPTER_STATE_READY: + case ADAPTER_STATE_OPERATIONAL: + case ADAPTER_STATE_HOLD: + case ADAPTER_STATE_FAILED: + osm_debug("%s: already running, trying to reset...\n", c->name); + rc = i2o_iop_reset(c); + if (rc) + return rc; + } + + /* preserve state */ + state = sb->iop_state; + + rc = i2o_iop_init_outbound_queue(c); + if (rc) + return rc; + + /* if adapter was not in RESET state clear now */ + if (state != ADAPTER_STATE_RESET) + i2o_iop_clear(c); + + i2o_status_get(c); + + if (sb->iop_state != ADAPTER_STATE_HOLD) { + osm_err("%s: failed to bring IOP into HOLD state\n", c->name); + return -EIO; + } + + return i2o_hrt_get(c); +}; + +static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags) +{ + i2o_status_block *sb = c->status_block.virt; + struct resource *res = &c->mem_resource; + resource_size_t size, align; + int err; + + res->name = c->pdev->bus->name; + res->flags = flags; + res->start = 0; + res->end = 0; + osm_info("%s: requires private memory resources.\n", c->name); + + if (flags & IORESOURCE_MEM) { + size = sb->desired_mem_size; + align = 1 << 20; /* unspecified, use 1Mb and play safe */ + } else { + size = sb->desired_io_size; + align = 1 << 12; /* unspecified, use 4Kb and play safe */ + } + + err = pci_bus_alloc_resource(c->pdev->bus, res, size, align, 0, 0, + NULL, NULL); + if (err < 0) + return; + + if (flags & IORESOURCE_MEM) { + c->mem_alloc = 1; + sb->current_mem_size = resource_size(res); + sb->current_mem_base = res->start; + } else if (flags & IORESOURCE_IO) { + c->io_alloc = 1; + sb->current_io_size = resource_size(res); + sb->current_io_base = res->start; + } + osm_info("%s: allocated PCI space %pR\n", c->name, res); +} + +/** + * i2o_iop_systab_set - Set the I2O System Table of the specified IOP + * @c: I2O controller to which the system table should be send + * + * Before the systab could be set i2o_systab_build() must be called. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_systab_set(struct i2o_controller *c) +{ + struct i2o_message *msg; + i2o_status_block *sb = c->status_block.virt; + struct device *dev = &c->pdev->dev; + int rc; + + if (sb->current_mem_size < sb->desired_mem_size) + i2o_res_alloc(c, IORESOURCE_MEM); + + if (sb->current_io_size < sb->desired_io_size) + i2o_res_alloc(c, IORESOURCE_IO); + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len, + PCI_DMA_TODEVICE); + if (!i2o_systab.phys) { + i2o_msg_nop(c, msg); + return -ENOMEM; + } + + msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | + ADAPTER_TID); + + /* + * Provide three SGL-elements: + * System table (SysTab), Private memory space declaration and + * Private i/o space declaration + */ + + msg->body[0] = cpu_to_le32(c->unit + 2); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len); + msg->body[3] = cpu_to_le32(i2o_systab.phys); + msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size); + msg->body[5] = cpu_to_le32(sb->current_mem_base); + msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size); + msg->body[6] = cpu_to_le32(sb->current_io_base); + + rc = i2o_msg_post_wait(c, msg, 120); + + dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len, + PCI_DMA_TODEVICE); + + if (rc < 0) + osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name, + -rc); + else + osm_debug("%s: SysTab set.\n", c->name); + + return rc; +} + +/** + * i2o_iop_online - Bring a controller online into OPERATIONAL state. + * @c: I2O controller + * + * Send the system table and enable the I2O controller. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_online(struct i2o_controller *c) +{ + int rc; + + rc = i2o_iop_systab_set(c); + if (rc) + return rc; + + /* In READY state */ + osm_debug("%s: Attempting to enable...\n", c->name); + rc = i2o_iop_enable(c); + if (rc) + return rc; + + return 0; +}; + +/** + * i2o_iop_remove - Remove the I2O controller from the I2O core + * @c: I2O controller + * + * Remove the I2O controller from the I2O core. If devices are attached to + * the controller remove these also and finally reset the controller. + */ +void i2o_iop_remove(struct i2o_controller *c) +{ + struct i2o_device *dev, *tmp; + + osm_debug("%s: deleting controller\n", c->name); + + i2o_driver_notify_controller_remove_all(c); + + list_del(&c->list); + + list_for_each_entry_safe(dev, tmp, &c->devices, list) + i2o_device_remove(dev); + + device_del(&c->device); + + /* Ask the IOP to switch to RESET state */ + i2o_iop_reset(c); +} + +/** + * i2o_systab_build - Build system table + * + * The system table contains information about all the IOPs in the system + * (duh) and is used by the Executives on the IOPs to establish peer2peer + * connections. We're not supporting peer2peer at the moment, but this + * will be needed down the road for things like lan2lan forwarding. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_systab_build(void) +{ + struct i2o_controller *c, *tmp; + int num_controllers = 0; + u32 change_ind = 0; + int count = 0; + struct i2o_sys_tbl *systab = i2o_systab.virt; + + list_for_each_entry_safe(c, tmp, &i2o_controllers, list) + num_controllers++; + + if (systab) { + change_ind = systab->change_ind; + kfree(i2o_systab.virt); + } + + /* Header + IOPs */ + i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers * + sizeof(struct i2o_sys_tbl_entry); + + systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL); + if (!systab) { + osm_err("unable to allocate memory for System Table\n"); + return -ENOMEM; + } + + systab->version = I2OVERSION; + systab->change_ind = change_ind + 1; + + list_for_each_entry_safe(c, tmp, &i2o_controllers, list) { + i2o_status_block *sb; + + if (count >= num_controllers) { + osm_err("controller added while building system table" + "\n"); + break; + } + + sb = c->status_block.virt; + + /* + * Get updated IOP state so we have the latest information + * + * We should delete the controller at this point if it + * doesn't respond since if it's not on the system table + * it is techninically not part of the I2O subsystem... + */ + if (unlikely(i2o_status_get(c))) { + osm_err("%s: Deleting b/c could not get status while " + "attempting to build system table\n", c->name); + i2o_iop_remove(c); + continue; // try the next one + } + + systab->iops[count].org_id = sb->org_id; + systab->iops[count].iop_id = c->unit + 2; + systab->iops[count].seg_num = 0; + systab->iops[count].i2o_version = sb->i2o_version; + systab->iops[count].iop_state = sb->iop_state; + systab->iops[count].msg_type = sb->msg_type; + systab->iops[count].frame_size = sb->inbound_frame_size; + systab->iops[count].last_changed = change_ind; + systab->iops[count].iop_capabilities = sb->iop_capabilities; + systab->iops[count].inbound_low = + i2o_dma_low(c->base.phys + I2O_IN_PORT); + systab->iops[count].inbound_high = + i2o_dma_high(c->base.phys + I2O_IN_PORT); + + count++; + } + + systab->num_entries = count; + + return 0; +}; + +/** + * i2o_parse_hrt - Parse the hardware resource table. + * @c: I2O controller + * + * We don't do anything with it except dumping it (in debug mode). + * + * Returns 0. + */ +static int i2o_parse_hrt(struct i2o_controller *c) +{ + i2o_dump_hrt(c); + return 0; +}; + +/** + * i2o_status_get - Get the status block from the I2O controller + * @c: I2O controller + * + * Issue a status query on the controller. This updates the attached + * status block. The status block could then be accessed through + * c->status_block. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_status_get(struct i2o_controller *c) +{ + struct i2o_message *msg; + volatile u8 *status_block; + unsigned long timeout; + + status_block = (u8 *) c->status_block.virt; + memset(c->status_block.virt, 0, sizeof(i2o_status_block)); + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(0x00000000); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys)); + msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys)); + msg->body[4] = cpu_to_le32(sizeof(i2o_status_block)); /* always 88 bytes */ + + i2o_msg_post(c, msg); + + /* Wait for a reply */ + timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; + while (status_block[87] != 0xFF) { + if (time_after(jiffies, timeout)) { + osm_err("%s: Get status timeout.\n", c->name); + return -ETIMEDOUT; + } + + schedule_timeout_uninterruptible(1); + } + +#ifdef DEBUG + i2o_debug_state(c); +#endif + + return 0; +} + +/* + * i2o_hrt_get - Get the Hardware Resource Table from the I2O controller + * @c: I2O controller from which the HRT should be fetched + * + * The HRT contains information about possible hidden devices but is + * mostly useless to us. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_hrt_get(struct i2o_controller *c) +{ + int rc; + int i; + i2o_hrt *hrt = c->hrt.virt; + u32 size = sizeof(i2o_hrt); + struct device *dev = &c->pdev->dev; + + for (i = 0; i < I2O_HRT_GET_TRIES; i++) { + struct i2o_message *msg; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len); + msg->body[1] = cpu_to_le32(c->hrt.phys); + + rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt); + + if (rc < 0) { + osm_err("%s: Unable to get HRT (status=%#x)\n", c->name, + -rc); + return rc; + } + + size = hrt->num_entries * hrt->entry_len << 2; + if (size > c->hrt.len) { + if (i2o_dma_realloc(dev, &c->hrt, size)) + return -ENOMEM; + else + hrt = c->hrt.virt; + } else + return i2o_parse_hrt(c); + } + + osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name, + I2O_HRT_GET_TRIES); + + return -EBUSY; +} + +/** + * i2o_iop_release - release the memory for a I2O controller + * @dev: I2O controller which should be released + * + * Release the allocated memory. This function is called if refcount of + * device reaches 0 automatically. + */ +static void i2o_iop_release(struct device *dev) +{ + struct i2o_controller *c = to_i2o_controller(dev); + + i2o_iop_free(c); +}; + +/** + * i2o_iop_alloc - Allocate and initialize a i2o_controller struct + * + * Allocate the necessary memory for a i2o_controller struct and + * initialize the lists and message mempool. + * + * Returns a pointer to the I2O controller or a negative error code on + * failure. + */ +struct i2o_controller *i2o_iop_alloc(void) +{ + static int unit = 0; /* 0 and 1 are NULL IOP and Local Host */ + struct i2o_controller *c; + char poolname[32]; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) { + osm_err("i2o: Insufficient memory to allocate a I2O controller." + "\n"); + return ERR_PTR(-ENOMEM); + } + + c->unit = unit++; + sprintf(c->name, "iop%d", c->unit); + + snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name); + if (i2o_pool_alloc + (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32), + I2O_MSG_INPOOL_MIN)) { + kfree(c); + return ERR_PTR(-ENOMEM); + }; + + INIT_LIST_HEAD(&c->devices); + spin_lock_init(&c->lock); + mutex_init(&c->lct_lock); + + device_initialize(&c->device); + + c->device.release = &i2o_iop_release; + + dev_set_name(&c->device, "iop%d", c->unit); + +#if BITS_PER_LONG == 64 + spin_lock_init(&c->context_list_lock); + atomic_set(&c->context_list_counter, 0); + INIT_LIST_HEAD(&c->context_list); +#endif + + return c; +}; + +/** + * i2o_iop_add - Initialize the I2O controller and add him to the I2O core + * @c: controller + * + * Initialize the I2O controller and if no error occurs add him to the I2O + * core. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_iop_add(struct i2o_controller *c) +{ + int rc; + + if ((rc = device_add(&c->device))) { + osm_err("%s: could not add controller\n", c->name); + goto iop_reset; + } + + osm_info("%s: Activating I2O controller...\n", c->name); + osm_info("%s: This may take a few minutes if there are many devices\n", + c->name); + + if ((rc = i2o_iop_activate(c))) { + osm_err("%s: could not activate controller\n", c->name); + goto device_del; + } + + osm_debug("%s: building sys table...\n", c->name); + + if ((rc = i2o_systab_build())) + goto device_del; + + osm_debug("%s: online controller...\n", c->name); + + if ((rc = i2o_iop_online(c))) + goto device_del; + + osm_debug("%s: getting LCT...\n", c->name); + + if ((rc = i2o_exec_lct_get(c))) + goto device_del; + + list_add(&c->list, &i2o_controllers); + + i2o_driver_notify_controller_add_all(c); + + osm_info("%s: Controller added\n", c->name); + + return 0; + + device_del: + device_del(&c->device); + + iop_reset: + i2o_iop_reset(c); + + return rc; +}; + +/** + * i2o_event_register - Turn on/off event notification for a I2O device + * @dev: I2O device which should receive the event registration request + * @drv: driver which want to get notified + * @tcntxt: transaction context to use with this notifier + * @evt_mask: mask of events + * + * Create and posts an event registration message to the task. No reply + * is waited for, or expected. If you do not want further notifications, + * call the i2o_event_register again with a evt_mask of 0. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv, + int tcntxt, u32 evt_mask) +{ + struct i2o_controller *c = dev->iop; + struct i2o_message *msg; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->u.s.icntxt = cpu_to_le32(drv->context); + msg->u.s.tcntxt = cpu_to_le32(tcntxt); + msg->body[0] = cpu_to_le32(evt_mask); + + i2o_msg_post(c, msg); + + return 0; +}; + +/** + * i2o_iop_init - I2O main initialization function + * + * Initialize the I2O drivers (OSM) functions, register the Executive OSM, + * initialize the I2O PCI part and finally initialize I2O device stuff. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_iop_init(void) +{ + int rc = 0; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + if ((rc = i2o_driver_init())) + goto exit; + + if ((rc = i2o_exec_init())) + goto driver_exit; + + if ((rc = i2o_pci_init())) + goto exec_exit; + + return 0; + + exec_exit: + i2o_exec_exit(); + + driver_exit: + i2o_driver_exit(); + + exit: + return rc; +} + +/** + * i2o_iop_exit - I2O main exit function + * + * Removes I2O controllers from PCI subsystem and shut down OSMs. + */ +static void __exit i2o_iop_exit(void) +{ + i2o_pci_exit(); + i2o_exec_exit(); + i2o_driver_exit(); +}; + +module_init(i2o_iop_init); +module_exit(i2o_iop_exit); + +MODULE_AUTHOR("Red Hat Software"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +#if BITS_PER_LONG == 64 +EXPORT_SYMBOL(i2o_cntxt_list_add); +EXPORT_SYMBOL(i2o_cntxt_list_get); +EXPORT_SYMBOL(i2o_cntxt_list_remove); +EXPORT_SYMBOL(i2o_cntxt_list_get_ptr); +#endif +EXPORT_SYMBOL(i2o_msg_get_wait); +EXPORT_SYMBOL(i2o_find_iop); +EXPORT_SYMBOL(i2o_iop_find_device); +EXPORT_SYMBOL(i2o_event_register); +EXPORT_SYMBOL(i2o_status_get); +EXPORT_SYMBOL(i2o_controllers); diff --git a/drivers/staging/i2o/memory.c b/drivers/staging/i2o/memory.c new file mode 100644 index 00000000000..8f9509d275a --- /dev/null +++ b/drivers/staging/i2o/memory.c @@ -0,0 +1,313 @@ +/* + * Functions to handle I2O memory + * + * Pulled from the inlines in i2o headers and uninlined + * + * + * 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 of the License, or (at your + * option) any later version. + */ + +#include <linux/module.h> +#include "i2o.h" +#include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> +#include "core.h" + +/* Protects our 32/64bit mask switching */ +static DEFINE_MUTEX(mem_lock); + +/** + * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL + * @c: I2O controller for which the calculation should be done + * @body_size: maximum body size used for message in 32-bit words. + * + * Return the maximum number of SG elements in a SG list. + */ +u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size) +{ + i2o_status_block *sb = c->status_block.virt; + u16 sg_count = + (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) - + body_size; + + if (c->pae_support) { + /* + * for 64-bit a SG attribute element must be added and each + * SG element needs 12 bytes instead of 8. + */ + sg_count -= 2; + sg_count /= 3; + } else + sg_count /= 2; + + if (c->short_req && (sg_count > 8)) + sg_count = 8; + + return sg_count; +} +EXPORT_SYMBOL_GPL(i2o_sg_tablesize); + + +/** + * i2o_dma_map_single - Map pointer to controller and fill in I2O message. + * @c: I2O controller + * @ptr: pointer to the data which should be mapped + * @size: size of data in bytes + * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE + * @sg_ptr: pointer to the SG list inside the I2O message + * + * This function does all necessary DMA handling and also writes the I2O + * SGL elements into the I2O message. For details on DMA handling see also + * dma_map_single(). The pointer sg_ptr will only be set to the end of the + * SG list if the allocation was successful. + * + * Returns DMA address which must be checked for failures using + * dma_mapping_error(). + */ +dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, + size_t size, + enum dma_data_direction direction, + u32 ** sg_ptr) +{ + u32 sg_flags; + u32 *mptr = *sg_ptr; + dma_addr_t dma_addr; + + switch (direction) { + case DMA_TO_DEVICE: + sg_flags = 0xd4000000; + break; + case DMA_FROM_DEVICE: + sg_flags = 0xd0000000; + break; + default: + return 0; + } + + dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction); + if (!dma_mapping_error(&c->pdev->dev, dma_addr)) { +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) { + *mptr++ = cpu_to_le32(0x7C020002); + *mptr++ = cpu_to_le32(PAGE_SIZE); + } +#endif + + *mptr++ = cpu_to_le32(sg_flags | size); + *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr)); +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) + *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr)); +#endif + *sg_ptr = mptr; + } + return dma_addr; +} +EXPORT_SYMBOL_GPL(i2o_dma_map_single); + +/** + * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message. + * @c: I2O controller + * @sg: SG list to be mapped + * @sg_count: number of elements in the SG list + * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE + * @sg_ptr: pointer to the SG list inside the I2O message + * + * This function does all necessary DMA handling and also writes the I2O + * SGL elements into the I2O message. For details on DMA handling see also + * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG + * list if the allocation was successful. + * + * Returns 0 on failure or 1 on success. + */ +int i2o_dma_map_sg(struct i2o_controller *c, struct scatterlist *sg, + int sg_count, enum dma_data_direction direction, u32 ** sg_ptr) +{ + u32 sg_flags; + u32 *mptr = *sg_ptr; + + switch (direction) { + case DMA_TO_DEVICE: + sg_flags = 0x14000000; + break; + case DMA_FROM_DEVICE: + sg_flags = 0x10000000; + break; + default: + return 0; + } + + sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction); + if (!sg_count) + return 0; + +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) { + *mptr++ = cpu_to_le32(0x7C020002); + *mptr++ = cpu_to_le32(PAGE_SIZE); + } +#endif + + while (sg_count-- > 0) { + if (!sg_count) + sg_flags |= 0xC0000000; + *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg)); + *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg))); +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) + *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg))); +#endif + sg = sg_next(sg); + } + *sg_ptr = mptr; + + return 1; +} +EXPORT_SYMBOL_GPL(i2o_dma_map_sg); + +/** + * i2o_dma_alloc - Allocate DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: i2o_dma struct which should get the DMA buffer + * @len: length of the new DMA memory + * + * Allocate a coherent DMA memory and write the pointers into addr. + * + * Returns 0 on success or -ENOMEM on failure. + */ +int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len) +{ + struct pci_dev *pdev = to_pci_dev(dev); + int dma_64 = 0; + + mutex_lock(&mem_lock); + if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_BIT_MASK(64))) { + dma_64 = 1; + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + mutex_unlock(&mem_lock); + return -ENOMEM; + } + } + + addr->virt = dma_alloc_coherent(dev, len, &addr->phys, GFP_KERNEL); + + if ((sizeof(dma_addr_t) > 4) && dma_64) + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) + printk(KERN_WARNING "i2o: unable to set 64-bit DMA"); + mutex_unlock(&mem_lock); + + if (!addr->virt) + return -ENOMEM; + + memset(addr->virt, 0, len); + addr->len = len; + + return 0; +} +EXPORT_SYMBOL_GPL(i2o_dma_alloc); + + +/** + * i2o_dma_free - Free DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: i2o_dma struct which contains the DMA buffer + * + * Free a coherent DMA memory and set virtual address of addr to NULL. + */ +void i2o_dma_free(struct device *dev, struct i2o_dma *addr) +{ + if (addr->virt) { + if (addr->phys) + dma_free_coherent(dev, addr->len, addr->virt, + addr->phys); + else + kfree(addr->virt); + addr->virt = NULL; + } +} +EXPORT_SYMBOL_GPL(i2o_dma_free); + + +/** + * i2o_dma_realloc - Realloc DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: pointer to a i2o_dma struct DMA buffer + * @len: new length of memory + * + * If there was something allocated in the addr, free it first. If len > 0 + * than try to allocate it and write the addresses back to the addr + * structure. If len == 0 set the virtual address to NULL. + * + * Returns the 0 on success or negative error code on failure. + */ +int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len) +{ + i2o_dma_free(dev, addr); + + if (len) + return i2o_dma_alloc(dev, addr, len); + + return 0; +} +EXPORT_SYMBOL_GPL(i2o_dma_realloc); + +/* + * i2o_pool_alloc - Allocate an slab cache and mempool + * @mempool: pointer to struct i2o_pool to write data into. + * @name: name which is used to identify cache + * @size: size of each object + * @min_nr: minimum number of objects + * + * First allocates a slab cache with name and size. Then allocates a + * mempool which uses the slab cache for allocation and freeing. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_pool_alloc(struct i2o_pool *pool, const char *name, + size_t size, int min_nr) +{ + pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL); + if (!pool->name) + goto exit; + strcpy(pool->name, name); + + pool->slab = + kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL); + if (!pool->slab) + goto free_name; + + pool->mempool = mempool_create_slab_pool(min_nr, pool->slab); + if (!pool->mempool) + goto free_slab; + + return 0; + +free_slab: + kmem_cache_destroy(pool->slab); + +free_name: + kfree(pool->name); + +exit: + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(i2o_pool_alloc); + +/* + * i2o_pool_free - Free slab cache and mempool again + * @mempool: pointer to struct i2o_pool which should be freed + * + * Note that you have to return all objects to the mempool again before + * calling i2o_pool_free(). + */ +void i2o_pool_free(struct i2o_pool *pool) +{ + mempool_destroy(pool->mempool); + kmem_cache_destroy(pool->slab); + kfree(pool->name); +}; +EXPORT_SYMBOL_GPL(i2o_pool_free); diff --git a/drivers/staging/i2o/pci.c b/drivers/staging/i2o/pci.c new file mode 100644 index 00000000000..b3b8a61dd4a --- /dev/null +++ b/drivers/staging/i2o/pci.c @@ -0,0 +1,497 @@ +/* + * PCI handling of I2O controller + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * 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 of the License, or (at your + * option) any later version. + * + * A lot of the I2O message side code from this is taken from the Red + * Creek RCPCI45 adapter driver by Red Creek Communications + * + * Fixes/additions: + * Philipp Rumpf + * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> + * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> + * Deepak Saxena <deepak@plexity.net> + * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> + * Alan Cox <alan@lxorguk.ukuu.org.uk>: + * Ported to Linux 2.5. + * Markus Lidel <Markus.Lidel@shadowconnect.com>: + * Minor fixes for 2.6. + * Markus Lidel <Markus.Lidel@shadowconnect.com>: + * Support for sysfs included. + */ + +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include "i2o.h" +#include <linux/module.h> +#include "core.h" + +#define OSM_DESCRIPTION "I2O-subsystem" + +/* PCI device id table for all I2O controllers */ +static struct pci_device_id i2o_pci_ids[] = { + {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, + {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, + {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962, + .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID}, + {0} +}; + +/** + * i2o_pci_free - Frees the DMA memory for the I2O controller + * @c: I2O controller to free + * + * Remove all allocated DMA memory and unmap memory IO regions. If MTRR + * is enabled, also remove it again. + */ +static void i2o_pci_free(struct i2o_controller *c) +{ + struct device *dev; + + dev = &c->pdev->dev; + + i2o_dma_free(dev, &c->out_queue); + i2o_dma_free(dev, &c->status_block); + kfree(c->lct); + i2o_dma_free(dev, &c->dlct); + i2o_dma_free(dev, &c->hrt); + i2o_dma_free(dev, &c->status); + + if (c->raptor && c->in_queue.virt) + iounmap(c->in_queue.virt); + + if (c->base.virt) + iounmap(c->base.virt); + + pci_release_regions(c->pdev); +} + +/** + * i2o_pci_alloc - Allocate DMA memory, map IO memory for I2O controller + * @c: I2O controller + * + * Allocate DMA memory for a PCI (or in theory AGP) I2O controller. All + * IO mappings are also done here. If MTRR is enabled, also do add memory + * regions here. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_pci_alloc(struct i2o_controller *c) +{ + struct pci_dev *pdev = c->pdev; + struct device *dev = &pdev->dev; + int i; + + if (pci_request_regions(pdev, OSM_DESCRIPTION)) { + printk(KERN_ERR "%s: device already claimed\n", c->name); + return -ENODEV; + } + + for (i = 0; i < 6; i++) { + /* Skip I/O spaces */ + if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { + if (!c->base.phys) { + c->base.phys = pci_resource_start(pdev, i); + c->base.len = pci_resource_len(pdev, i); + + /* + * If we know what card it is, set the size + * correctly. Code is taken from dpt_i2o.c + */ + if (pdev->device == 0xa501) { + if (pdev->subsystem_device >= 0xc032 && + pdev->subsystem_device <= 0xc03b) { + if (c->base.len > 0x400000) + c->base.len = 0x400000; + } else { + if (c->base.len > 0x100000) + c->base.len = 0x100000; + } + } + if (!c->raptor) + break; + } else { + c->in_queue.phys = pci_resource_start(pdev, i); + c->in_queue.len = pci_resource_len(pdev, i); + break; + } + } + } + + if (i == 6) { + printk(KERN_ERR "%s: I2O controller has no memory regions" + " defined.\n", c->name); + i2o_pci_free(c); + return -EINVAL; + } + + /* Map the I2O controller */ + if (c->raptor) { + printk(KERN_INFO "%s: PCI I2O controller\n", c->name); + printk(KERN_INFO " BAR0 at 0x%08lX size=%ld\n", + (unsigned long)c->base.phys, (unsigned long)c->base.len); + printk(KERN_INFO " BAR1 at 0x%08lX size=%ld\n", + (unsigned long)c->in_queue.phys, + (unsigned long)c->in_queue.len); + } else + printk(KERN_INFO "%s: PCI I2O controller at %08lX size=%ld\n", + c->name, (unsigned long)c->base.phys, + (unsigned long)c->base.len); + + c->base.virt = ioremap_nocache(c->base.phys, c->base.len); + if (!c->base.virt) { + printk(KERN_ERR "%s: Unable to map controller.\n", c->name); + i2o_pci_free(c); + return -ENOMEM; + } + + if (c->raptor) { + c->in_queue.virt = + ioremap_nocache(c->in_queue.phys, c->in_queue.len); + if (!c->in_queue.virt) { + printk(KERN_ERR "%s: Unable to map controller.\n", + c->name); + i2o_pci_free(c); + return -ENOMEM; + } + } else + c->in_queue = c->base; + + c->irq_status = c->base.virt + I2O_IRQ_STATUS; + c->irq_mask = c->base.virt + I2O_IRQ_MASK; + c->in_port = c->base.virt + I2O_IN_PORT; + c->out_port = c->base.virt + I2O_OUT_PORT; + + /* Motorola/Freescale chip does not follow spec */ + if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) { + /* Check if CPU is enabled */ + if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) { + printk(KERN_INFO "%s: MPC82XX needs CPU running to " + "service I2O.\n", c->name); + i2o_pci_free(c); + return -ENODEV; + } else { + c->irq_status += I2O_MOTOROLA_PORT_OFFSET; + c->irq_mask += I2O_MOTOROLA_PORT_OFFSET; + c->in_port += I2O_MOTOROLA_PORT_OFFSET; + c->out_port += I2O_MOTOROLA_PORT_OFFSET; + printk(KERN_INFO "%s: MPC82XX workarounds activated.\n", + c->name); + } + } + + if (i2o_dma_alloc(dev, &c->status, 8)) { + i2o_pci_free(c); + return -ENOMEM; + } + + if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt))) { + i2o_pci_free(c); + return -ENOMEM; + } + + if (i2o_dma_alloc(dev, &c->dlct, 8192)) { + i2o_pci_free(c); + return -ENOMEM; + } + + if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block))) { + i2o_pci_free(c); + return -ENOMEM; + } + + if (i2o_dma_alloc(dev, &c->out_queue, + I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE * + sizeof(u32))) { + i2o_pci_free(c); + return -ENOMEM; + } + + pci_set_drvdata(pdev, c); + + return 0; +} + +/** + * i2o_pci_interrupt - Interrupt handler for I2O controller + * @irq: interrupt line + * @dev_id: pointer to the I2O controller + * + * Handle an interrupt from a PCI based I2O controller. This turns out + * to be rather simple. We keep the controller pointer in the cookie. + */ +static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id) +{ + struct i2o_controller *c = dev_id; + u32 m; + irqreturn_t rc = IRQ_NONE; + + while (readl(c->irq_status) & I2O_IRQ_OUTBOUND_POST) { + m = readl(c->out_port); + if (m == I2O_QUEUE_EMPTY) { + /* + * Old 960 steppings had a bug in the I2O unit that + * caused the queue to appear empty when it wasn't. + */ + m = readl(c->out_port); + if (unlikely(m == I2O_QUEUE_EMPTY)) + break; + } + + /* dispatch it */ + if (i2o_driver_dispatch(c, m)) + /* flush it if result != 0 */ + i2o_flush_reply(c, m); + + rc = IRQ_HANDLED; + } + + return rc; +} + +/** + * i2o_pci_irq_enable - Allocate interrupt for I2O controller + * @c: i2o_controller that the request is for + * + * Allocate an interrupt for the I2O controller, and activate interrupts + * on the I2O controller. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_pci_irq_enable(struct i2o_controller *c) +{ + struct pci_dev *pdev = c->pdev; + int rc; + + writel(0xffffffff, c->irq_mask); + + if (pdev->irq) { + rc = request_irq(pdev->irq, i2o_pci_interrupt, IRQF_SHARED, + c->name, c); + if (rc < 0) { + printk(KERN_ERR "%s: unable to allocate interrupt %d." + "\n", c->name, pdev->irq); + return rc; + } + } + + writel(0x00000000, c->irq_mask); + + printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq); + + return 0; +} + +/** + * i2o_pci_irq_disable - Free interrupt for I2O controller + * @c: I2O controller + * + * Disable interrupts in I2O controller and then free interrupt. + */ +static void i2o_pci_irq_disable(struct i2o_controller *c) +{ + writel(0xffffffff, c->irq_mask); + + if (c->pdev->irq > 0) + free_irq(c->pdev->irq, c); +} + +/** + * i2o_pci_probe - Probe the PCI device for an I2O controller + * @pdev: PCI device to test + * @id: id which matched with the PCI device id table + * + * Probe the PCI device for any device which is a memory of the + * Intelligent, I2O class or an Adaptec Zero Channel Controller. We + * attempt to set up each such device and register it with the core. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct i2o_controller *c; + int rc; + struct pci_dev *i960 = NULL; + + printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); + + if ((pdev->class & 0xff) > 1) { + printk(KERN_WARNING "i2o: %s does not support I2O 1.5 " + "(skipping).\n", pci_name(pdev)); + return -ENODEV; + } + + if ((rc = pci_enable_device(pdev))) { + printk(KERN_WARNING "i2o: couldn't enable device %s\n", + pci_name(pdev)); + return rc; + } + + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", + pci_name(pdev)); + rc = -ENODEV; + goto disable; + } + + pci_set_master(pdev); + + c = i2o_iop_alloc(); + if (IS_ERR(c)) { + printk(KERN_ERR "i2o: couldn't allocate memory for %s\n", + pci_name(pdev)); + rc = PTR_ERR(c); + goto disable; + } else + printk(KERN_INFO "%s: controller found (%s)\n", c->name, + pci_name(pdev)); + + c->pdev = pdev; + c->device.parent = &pdev->dev; + + /* Cards that fall apart if you hit them with large I/O loads... */ + if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) { + c->short_req = 1; + printk(KERN_INFO "%s: Symbios FC920 workarounds activated.\n", + c->name); + } + + if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { + /* + * Expose the ship behind i960 for initialization, or it will + * failed + */ + i960 = pci_get_slot(c->pdev->bus, + PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); + + if (i960) { + pci_write_config_word(i960, 0x42, 0); + pci_dev_put(i960); + } + + c->promise = 1; + c->limit_sectors = 1; + } + + if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT) + c->adaptec = 1; + + /* Cards that go bananas if you quiesce them before you reset them. */ + if (pdev->vendor == PCI_VENDOR_ID_DPT) { + c->no_quiesce = 1; + if (pdev->device == 0xa511) + c->raptor = 1; + + if (pdev->subsystem_device == 0xc05a) { + c->limit_sectors = 1; + printk(KERN_INFO + "%s: limit sectors per request to %d\n", c->name, + I2O_MAX_SECTORS_LIMITED); + } +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if (sizeof(dma_addr_t) > 4) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) + printk(KERN_INFO "%s: 64-bit DMA unavailable\n", + c->name); + else { + c->pae_support = 1; + printk(KERN_INFO "%s: using 64-bit DMA\n", + c->name); + } + } +#endif + } + + if ((rc = i2o_pci_alloc(c))) { + printk(KERN_ERR "%s: DMA / IO allocation for I2O controller " + "failed\n", c->name); + goto free_controller; + } + + if (i2o_pci_irq_enable(c)) { + printk(KERN_ERR "%s: unable to enable interrupts for I2O " + "controller\n", c->name); + goto free_pci; + } + + if ((rc = i2o_iop_add(c))) + goto uninstall; + + if (i960) + pci_write_config_word(i960, 0x42, 0x03ff); + + return 0; + + uninstall: + i2o_pci_irq_disable(c); + + free_pci: + i2o_pci_free(c); + + free_controller: + i2o_iop_free(c); + + disable: + pci_disable_device(pdev); + + return rc; +} + +/** + * i2o_pci_remove - Removes a I2O controller from the system + * @pdev: I2O controller which should be removed + * + * Reset the I2O controller, disable interrupts and remove all allocated + * resources. + */ +static void i2o_pci_remove(struct pci_dev *pdev) +{ + struct i2o_controller *c; + c = pci_get_drvdata(pdev); + + i2o_iop_remove(c); + i2o_pci_irq_disable(c); + i2o_pci_free(c); + + pci_disable_device(pdev); + + printk(KERN_INFO "%s: Controller removed.\n", c->name); + + put_device(&c->device); +}; + +/* PCI driver for I2O controller */ +static struct pci_driver i2o_pci_driver = { + .name = "PCI_I2O", + .id_table = i2o_pci_ids, + .probe = i2o_pci_probe, + .remove = i2o_pci_remove, +}; + +/** + * i2o_pci_init - registers I2O PCI driver in PCI subsystem + * + * Returns > 0 on success or negative error code on failure. + */ +int __init i2o_pci_init(void) +{ + return pci_register_driver(&i2o_pci_driver); +}; + +/** + * i2o_pci_exit - unregisters I2O PCI driver from PCI subsystem + */ +void __exit i2o_pci_exit(void) +{ + pci_unregister_driver(&i2o_pci_driver); +}; + +MODULE_DEVICE_TABLE(pci, i2o_pci_ids); diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index 940ed2399e7..72c96aa6e99 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -49,6 +49,8 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CCT] = "cct", [IIO_PRESSURE] = "pressure", [IIO_HUMIDITYRELATIVE] = "humidityrelative", + [IIO_ACTIVITY] = "activity", + [IIO_STEPS] = "steps", }; static const char * const iio_ev_type_text[] = { @@ -57,6 +59,7 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_ROC] = "roc", [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", + [IIO_EV_TYPE_CHANGE] = "change", }; static const char * const iio_ev_dir_text[] = { @@ -92,6 +95,10 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_NORTH_TRUE] = "from_north_true", [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp", [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp", + [IIO_MOD_RUNNING] = "running", + [IIO_MOD_JOGGING] = "jogging", + [IIO_MOD_WALKING] = "walking", + [IIO_MOD_STILL] = "still", }; static bool event_is_known(struct iio_event_data *event) @@ -121,6 +128,8 @@ static bool event_is_known(struct iio_event_data *event) case IIO_CCT: case IIO_PRESSURE: case IIO_HUMIDITYRELATIVE: + case IIO_ACTIVITY: + case IIO_STEPS: break; default: return false; @@ -154,6 +163,10 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_NORTH_TRUE: case IIO_MOD_NORTH_MAGN_TILT_COMP: case IIO_MOD_NORTH_TRUE_TILT_COMP: + case IIO_MOD_RUNNING: + case IIO_MOD_JOGGING: + case IIO_MOD_WALKING: + case IIO_MOD_STILL: break; default: return false; @@ -165,6 +178,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_EV_TYPE_ROC: case IIO_EV_TYPE_THRESH_ADAPTIVE: case IIO_EV_TYPE_MAG_ADAPTIVE: + case IIO_EV_TYPE_CHANGE: break; default: return false; @@ -174,6 +188,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_EV_DIR_EITHER: case IIO_EV_DIR_RISING: case IIO_EV_DIR_FALLING: + case IIO_EV_DIR_NONE: break; default: return false; @@ -214,9 +229,11 @@ static void print_event(struct iio_event_data *event) else if (chan >= 0) printf("channel: %d, ", chan); - printf("evtype: %s, direction: %s\n", - iio_ev_type_text[ev_type], - iio_ev_dir_text[dir]); + printf("evtype: %s", iio_ev_type_text[ev_type]); + + if (dir != IIO_EV_DIR_NONE) + printf(", direction: %s", iio_ev_dir_text[dir]); + printf("\n"); } int main(int argc, char **argv) diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt index e1da43381d0..18718fcaf25 100644 --- a/drivers/staging/iio/Documentation/ring.txt +++ b/drivers/staging/iio/Documentation/ring.txt @@ -39,9 +39,9 @@ request_update If parameters have changed that require reinitialization or configuration of the buffer this will trigger it. -get_bytes_per_datum, set_bytes_per_datum - Get/set the number of bytes for a complete scan. (All samples + timestamp) +set_bytes_per_datum + Set the number of bytes for a complete scan. (All samples + timestamp) -get_length / set_length - Get/set the number of complete scans that may be held by the buffer. +set_length + Set the number of complete scans that may be held by the buffer. diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index f5e145caffa..b78c9c5d558 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -716,14 +716,6 @@ static int lis3l02dq_probe(struct spi_device *spi) if (ret) return ret; - ret = iio_buffer_register(indio_dev, - lis3l02dq_channels, - ARRAY_SIZE(lis3l02dq_channels)); - if (ret) { - dev_err(&spi->dev, "failed to initialize the buffer\n"); - goto error_unreg_buffer_funcs; - } - if (spi->irq) { ret = request_threaded_irq(st->us->irq, &lis3l02dq_th, @@ -732,7 +724,7 @@ static int lis3l02dq_probe(struct spi_device *spi) "lis3l02dq", indio_dev); if (ret) - goto error_uninitialize_buffer; + goto error_unreg_buffer_funcs; ret = lis3l02dq_probe_trigger(indio_dev); if (ret) @@ -756,8 +748,6 @@ error_remove_trigger: error_free_interrupt: if (spi->irq) free_irq(st->us->irq, indio_dev); -error_uninitialize_buffer: - iio_buffer_unregister(indio_dev); error_unreg_buffer_funcs: lis3l02dq_unconfigure_buffer(indio_dev); return ret; @@ -804,7 +794,6 @@ static int lis3l02dq_remove(struct spi_device *spi) free_irq(st->us->irq, indio_dev); lis3l02dq_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); lis3l02dq_unconfigure_buffer(indio_dev); return 0; diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 9efc77b0ebd..1fd90090a63 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -393,7 +393,7 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) int ret; struct iio_buffer *buffer; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index e4e56391487..31fb2182c19 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -223,33 +223,6 @@ error_ret: return ret; } -#ifdef SCA3000_DEBUG -/** - * sca3000_check_status() check the status register - * - * Only used for debugging purposes - **/ -static int sca3000_check_status(struct device *dev) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_STATUS, 1); - if (ret < 0) - goto error_ret; - if (st->rx[0] & SCA3000_EEPROM_CS_ERROR) - dev_err(dev, "eeprom error\n"); - if (st->rx[0] & SCA3000_SPI_FRAME_ERROR) - dev_err(dev, "Previous SPI Frame was corrupt\n"); - -error_ret: - mutex_unlock(&st->lock); - return ret; -} -#endif /* SCA3000_DEBUG */ - /** * sca3000_show_rev() - sysfs interface to read the chip revision number **/ @@ -459,6 +432,8 @@ static const struct iio_chan_spec sca3000_channels_with_temp[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), + /* No buffer support */ + .scan_index = -1, }, }; @@ -1154,17 +1129,6 @@ static int sca3000_probe(struct spi_device *spi) if (ret < 0) return ret; - ret = iio_buffer_register(indio_dev, - sca3000_channels, - ARRAY_SIZE(sca3000_channels)); - if (ret < 0) - goto error_unregister_dev; - if (indio_dev->buffer) { - iio_scan_mask_set(indio_dev, indio_dev->buffer, 0); - iio_scan_mask_set(indio_dev, indio_dev->buffer, 1); - iio_scan_mask_set(indio_dev, indio_dev->buffer, 2); - } - if (spi->irq) { ret = request_threaded_irq(spi->irq, NULL, @@ -1173,7 +1137,7 @@ static int sca3000_probe(struct spi_device *spi) "sca3000", indio_dev); if (ret) - goto error_unregister_ring; + goto error_unregister_dev; } sca3000_register_ring_funcs(indio_dev); ret = sca3000_clean_setup(st); @@ -1184,8 +1148,6 @@ static int sca3000_probe(struct spi_device *spi) error_free_irq: if (spi->irq) free_irq(spi->irq, indio_dev); -error_unregister_ring: - iio_buffer_unregister(indio_dev); error_unregister_dev: iio_device_unregister(indio_dev); return ret; @@ -1219,7 +1181,6 @@ static int sca3000_remove(struct spi_device *spi) if (spi->irq) free_irq(spi->irq, indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); sca3000_unconfigure_ring(indio_dev); return 0; diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 157827651bf..f76a2688580 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -129,26 +129,11 @@ error_ret: return ret ? ret : num_read; } -/* This is only valid with all 3 elements enabled */ -static int sca3000_ring_get_length(struct iio_buffer *r) -{ - return 64; -} - -/* only valid if resolution is kept at 11bits */ -static int sca3000_ring_get_bytes_per_datum(struct iio_buffer *r) -{ - return 6; -} - static bool sca3000_ring_buf_data_available(struct iio_buffer *r) { return r->stufftoread; } -static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_LENGTH_ATTR; - /** * sca3000_query_ring_int() is the hardware ring status interrupt enabled **/ @@ -238,20 +223,13 @@ static IIO_DEVICE_ATTR(in_accel_scale, * only apply to the ring buffer. At all times full rate and accuracy * is available via direct reading from registers. */ -static struct attribute *sca3000_ring_attributes[] = { - &dev_attr_length.attr, - &dev_attr_enable.attr, +static const struct attribute *sca3000_ring_attributes[] = { &iio_dev_attr_50_percent.dev_attr.attr, &iio_dev_attr_75_percent.dev_attr.attr, &iio_dev_attr_in_accel_scale.dev_attr.attr, NULL, }; -static struct attribute_group sca3000_ring_attr = { - .attrs = sca3000_ring_attributes, - .name = "buffer", -}; - static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) { struct iio_buffer *buf; @@ -264,7 +242,8 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) ring->private = indio_dev; buf = &ring->buf; buf->stufftoread = 0; - buf->attrs = &sca3000_ring_attr; + buf->length = 64; + buf->attrs = sca3000_ring_attributes; iio_buffer_init(buf); return buf; @@ -277,8 +256,6 @@ static void sca3000_ring_release(struct iio_buffer *r) static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { .read_first_n = &sca3000_read_first_n_hw_rb, - .get_length = &sca3000_ring_get_length, - .get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum, .data_available = sca3000_ring_buf_data_available, .release = sca3000_ring_release, }; diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index f6526aa22e8..6f8ce6c6574 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -612,7 +612,7 @@ static int ad7192_probe(struct spi_device *spi) const struct ad7192_platform_data *pdata = spi->dev.platform_data; struct ad7192_state *st; struct iio_dev *indio_dev; - int ret , voltage_uv = 0; + int ret, voltage_uv = 0; if (!pdata) { dev_err(&spi->dev, "no platform data?\n"); diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index f053535385b..d9d6fad7cb0 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -436,7 +436,14 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) */ mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch)); - /* prepare the delay/loop unit according to the oversampling count */ + /* + * prepare the delay/loop unit according to the oversampling count + * + * from the datasheet: + * "The DELAY fields in HW_LRADC_DELAY0, HW_LRADC_DELAY1, + * HW_LRADC_DELAY2, and HW_LRADC_DELAY3 must be non-zero; otherwise, + * the LRADC will not trigger the delay group." + */ mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) | LRADC_DELAY_TRIGGER_DELAYS(0) | LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | @@ -1495,20 +1502,38 @@ static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc, return -EINVAL; } - lradc->over_sample_cnt = 4; - ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt); - if (ret == 0) + if (of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt)) { + lradc->over_sample_cnt = 4; + } else { + if (adapt < 1 || adapt > 32) { + dev_err(lradc->dev, "Invalid sample count (%u)\n", + adapt); + return -EINVAL; + } lradc->over_sample_cnt = adapt; + } - lradc->over_sample_delay = 2; - ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt); - if (ret == 0) + if (of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt)) { + lradc->over_sample_delay = 2; + } else { + if (adapt < 2 || adapt > LRADC_DELAY_DELAY_MASK + 1) { + dev_err(lradc->dev, "Invalid sample delay (%u)\n", + adapt); + return -EINVAL; + } lradc->over_sample_delay = adapt; + } - lradc->settling_delay = 10; - ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt); - if (ret == 0) + if (of_property_read_u32(lradc_node, "fsl,settling", &adapt)) { + lradc->settling_delay = 10; + } else { + if (adapt < 1 || adapt > LRADC_DELAY_DELAY_MASK) { + dev_err(lradc->dev, "Invalid settling delay (%u)\n", + adapt); + return -EINVAL; + } lradc->settling_delay = adapt; + } return 0; } diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c index 5a804f16ec2..59ad5a3efe9 100644 --- a/drivers/staging/iio/iio_dummy_evgen.c +++ b/drivers/staging/iio/iio_dummy_evgen.c @@ -33,6 +33,7 @@ * @base: base of irq range * @enabled: mask of which irqs are enabled * @inuse: mask of which irqs are connected + * @regs: irq regs we are faking * @lock: protect the evgen state */ struct iio_dummy_eventgen { @@ -40,6 +41,7 @@ struct iio_dummy_eventgen { int base; bool enabled[IIO_EVENTGEN_NO]; bool inuse[IIO_EVENTGEN_NO]; + struct iio_dummy_regs regs[IIO_EVENTGEN_NO]; struct mutex lock; }; @@ -136,6 +138,12 @@ int iio_dummy_evgen_release_irq(int irq) } EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq); +struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq) +{ + return &iio_evgen->regs[irq - iio_evgen->base]; +} +EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs); + static void iio_dummy_evgen_free(void) { irq_free_descs(iio_evgen->base, IIO_EVENTGEN_NO); @@ -153,6 +161,15 @@ static ssize_t iio_evgen_poke(struct device *dev, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long event; + int ret; + + ret = kstrtoul(buf, 10, &event); + if (ret) + return ret; + + iio_evgen->regs[this_attr->address].reg_id = this_attr->address; + iio_evgen->regs[this_attr->address].reg_data = event; if (iio_evgen->enabled[this_attr->address]) handle_nested_irq(iio_evgen->base + this_attr->address); diff --git a/drivers/staging/iio/iio_dummy_evgen.h b/drivers/staging/iio/iio_dummy_evgen.h index 3a180811b31..2ac293ab7c8 100644 --- a/drivers/staging/iio/iio_dummy_evgen.h +++ b/drivers/staging/iio/iio_dummy_evgen.h @@ -1,6 +1,12 @@ #ifndef _IIO_DUMMY_EVGEN_H_ #define _IIO_DUMMY_EVGEN_H_ +struct iio_dummy_regs { + u32 reg_id; + u32 reg_data; +}; + +struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq); int iio_dummy_evgen_get_irq(void); int iio_dummy_evgen_release_irq(int irq); diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index bf78e6f0311..e4520213f62 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -69,6 +69,34 @@ static const struct iio_event_spec iio_dummy_event = { .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), }; +/* + * simple step detect event - triggered when a step is detected + */ +static const struct iio_event_spec step_detect_event = { + .type = IIO_EV_TYPE_CHANGE, + .dir = IIO_EV_DIR_NONE, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), +}; + +/* + * simple transition event - triggered when the reported running confidence + * value rises above a threshold value + */ +static const struct iio_event_spec iio_running_event = { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; + +/* + * simple transition event - triggered when the reported walking confidence + * value falls under a threshold value + */ +static const struct iio_event_spec iio_walking_event = { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; #endif /* @@ -211,10 +239,44 @@ static const struct iio_chan_spec iio_dummy_channels[] = { { .type = IIO_VOLTAGE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = -1, /* No buffer support */ .output = 1, .indexed = 1, .channel = 0, }, + { + .type = IIO_STEPS, + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) | + BIT(IIO_CHAN_INFO_CALIBHEIGHT), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, /* No buffer support */ +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .event_spec = &step_detect_event, + .num_event_specs = 1, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, + { + .type = IIO_ACTIVITY, + .modified = 1, + .channel2 = IIO_MOD_RUNNING, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, /* No buffer support */ +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .event_spec = &iio_running_event, + .num_event_specs = 1, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, + { + .type = IIO_ACTIVITY, + .modified = 1, + .channel2 = IIO_MOD_WALKING, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, /* No buffer support */ +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .event_spec = &iio_walking_event, + .num_event_specs = 1, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, }; /** @@ -263,24 +325,55 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, break; } break; + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_STEPS: + *val = st->steps; + ret = IIO_VAL_INT; + break; + case IIO_ACTIVITY: + switch (chan->channel2) { + case IIO_MOD_RUNNING: + *val = st->activity_running; + ret = IIO_VAL_INT; + break; + case IIO_MOD_WALKING: + *val = st->activity_walking; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + default: + break; + } + break; case IIO_CHAN_INFO_OFFSET: /* only single ended adc -> 7 */ *val = 7; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - switch (chan->differential) { - case 0: - /* only single ended adc -> 0.001333 */ - *val = 0; - *val2 = 1333; - ret = IIO_VAL_INT_PLUS_MICRO; + switch (chan->type) { + case IIO_VOLTAGE: + switch (chan->differential) { + case 0: + /* only single ended adc -> 0.001333 */ + *val = 0; + *val2 = 1333; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case 1: + /* all differential adc channels -> + * 0.000001344 */ + *val = 0; + *val2 = 1344; + ret = IIO_VAL_INT_PLUS_NANO; + } + break; + default: break; - case 1: - /* all differential adc channels -> 0.000001344 */ - *val = 0; - *val2 = 1344; - ret = IIO_VAL_INT_PLUS_NANO; } break; case IIO_CHAN_INFO_CALIBBIAS: @@ -298,6 +391,27 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, *val2 = 33; ret = IIO_VAL_INT_PLUS_NANO; break; + case IIO_CHAN_INFO_ENABLE: + switch (chan->type) { + case IIO_STEPS: + *val = st->steps_enabled; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + case IIO_CHAN_INFO_CALIBHEIGHT: + switch (chan->type) { + case IIO_STEPS: + *val = st->height; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + default: break; } @@ -330,14 +444,45 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - if (chan->output == 0) + switch (chan->type) { + case IIO_VOLTAGE: + if (chan->output == 0) + return -EINVAL; + + /* Locking not required as writing single value */ + mutex_lock(&st->lock); + st->dac_val = val; + mutex_unlock(&st->lock); + return 0; + default: return -EINVAL; - - /* Locking not required as writing single value */ - mutex_lock(&st->lock); - st->dac_val = val; - mutex_unlock(&st->lock); - return 0; + } + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_STEPS: + mutex_lock(&st->lock); + st->steps = val; + mutex_unlock(&st->lock); + return 0; + case IIO_ACTIVITY: + if (val < 0) + val = 0; + if (val > 100) + val = 100; + switch (chan->channel2) { + case IIO_MOD_RUNNING: + st->activity_running = val; + return 0; + case IIO_MOD_WALKING: + st->activity_walking = val; + return 0; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } case IIO_CHAN_INFO_CALIBSCALE: mutex_lock(&st->lock); /* Compare against table - hard matching here */ @@ -356,6 +501,24 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, st->accel_calibbias = val; mutex_unlock(&st->lock); return 0; + case IIO_CHAN_INFO_ENABLE: + switch (chan->type) { + case IIO_STEPS: + mutex_lock(&st->lock); + st->steps_enabled = val; + mutex_unlock(&st->lock); + return 0; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_CALIBHEIGHT: + switch (chan->type) { + case IIO_STEPS: + st->height = val; + return 0; + default: + return -EINVAL; + } default: return -EINVAL; @@ -395,6 +558,9 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev) st->accel_val = 34; st->accel_calibbias = -7; st->accel_calibscale = &dummy_scales[0]; + st->steps = 47; + st->activity_running = 98; + st->activity_walking = 4; return 0; } @@ -475,13 +641,7 @@ static int iio_dummy_probe(int index) if (ret < 0) goto error_free_device; - /* - * Configure buffered capture support and register the channels with the - * buffer, but avoid the output channel being registered by reducing the - * number of channels by 1. - */ - ret = iio_simple_dummy_configure_buffer(indio_dev, - iio_dummy_channels, 5); + ret = iio_simple_dummy_configure_buffer(indio_dev); if (ret < 0) goto error_unregister_events; diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index 3027aed7909..34989bf248a 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -13,6 +13,7 @@ #include <linux/kernel.h> struct iio_dummy_accel_calibscale; +struct iio_dummy_regs; /** * struct iio_dummy_state - device instance specific state. @@ -33,8 +34,14 @@ struct iio_dummy_state { int differential_adc_val[2]; int accel_val; int accel_calibbias; + int activity_running; + int activity_walking; const struct iio_dummy_accel_calibscale *accel_calibscale; struct mutex lock; + struct iio_dummy_regs *regs; + int steps_enabled; + int steps; + int height; #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS int event_irq; int event_val; @@ -107,12 +114,10 @@ enum iio_simple_dummy_scan_elements { }; #ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels); +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev); #else -static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels) +static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) { return 0; }; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index fd74f9166a5..360a4c98072 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -115,14 +115,13 @@ static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = { .predisable = &iio_triggered_buffer_predisable, }; -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels) +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) { int ret; struct iio_buffer *buffer; /* Allocate a buffer to use - here a kfifo */ - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (buffer == NULL) { ret = -ENOMEM; goto error_ret; @@ -173,14 +172,8 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - ret = iio_buffer_register(indio_dev, channels, num_channels); - if (ret) - goto error_dealloc_pollfunc; - return 0; -error_dealloc_pollfunc: - iio_dealloc_pollfunc(indio_dev->pollfunc); error_free_buffer: iio_kfifo_free(indio_dev->buffer); error_ret: @@ -194,7 +187,6 @@ error_ret: */ void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) { - iio_buffer_unregister(indio_dev); iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index 64b45b07754..a5cd3bb219f 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -72,6 +72,22 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, st->event_en = state; else return -EINVAL; + default: + return -EINVAL; + } + break; + case IIO_ACTIVITY: + switch (type) { + case IIO_EV_TYPE_THRESH: + st->event_en = state; + break; + default: + return -EINVAL; + } + case IIO_STEPS: + switch (type) { + case IIO_EV_TYPE_CHANGE: + st->event_en = state; break; default: return -EINVAL; @@ -148,12 +164,50 @@ int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; + struct iio_dummy_state *st = iio_priv(indio_dev); + + dev_dbg(&indio_dev->dev, "id %x event %x\n", + st->regs->reg_id, st->regs->reg_data); + + switch (st->regs->reg_data) { + case 0: + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, 0, 0, 0), + iio_get_time_ns()); + break; + case 1: + if (st->activity_running > st->event_val) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_ACTIVITY, 0, + IIO_MOD_RUNNING, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, + 0, 0, 0), + iio_get_time_ns()); + break; + case 2: + if (st->activity_walking < st->event_val) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_ACTIVITY, 0, + IIO_MOD_WALKING, + IIO_EV_DIR_FALLING, + IIO_EV_TYPE_THRESH, + 0, 0, 0), + iio_get_time_ns()); + break; + case 3: + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, + IIO_EV_DIR_NONE, + IIO_EV_TYPE_CHANGE, 0, 0, 0), + iio_get_time_ns()); + break; + default: + break; + } - iio_push_event(indio_dev, - IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, - IIO_EV_DIR_RISING, - IIO_EV_TYPE_THRESH, 0, 0, 0), - iio_get_time_ns()); return IRQ_HANDLED; } @@ -179,6 +233,8 @@ int iio_simple_dummy_events_register(struct iio_dev *indio_dev) ret = st->event_irq; goto error_ret; } + st->regs = iio_dummy_evgen_get_regs(st->event_irq); + ret = request_threaded_irq(st->event_irq, NULL, &iio_simple_dummy_event_handler, diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index b6bd609c365..79194399e04 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -89,7 +89,6 @@ struct ad5933_state { struct i2c_client *client; struct regulator *reg; - struct ad5933_platform_data *pdata; struct delayed_work work; unsigned long mclk_hz; unsigned char ctrl_hb; @@ -113,7 +112,8 @@ static const struct iio_chan_spec ad5933_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), .address = AD5933_REG_TEMP_DATA, .scan_index = -1, .scan_type = { @@ -360,11 +360,11 @@ static ssize_t ad5933_show(struct device *dev, mutex_lock(&indio_dev->mlock); switch ((u32) this_attr->address) { case AD5933_OUT_RANGE: - len = sprintf(buf, "%d\n", + len = sprintf(buf, "%u\n", st->range_avail[(st->ctrl_hb >> 1) & 0x3]); break; case AD5933_OUT_RANGE_AVAIL: - len = sprintf(buf, "%d %d %d %d\n", st->range_avail[0], + len = sprintf(buf, "%u %u %u %u\n", st->range_avail[0], st->range_avail[3], st->range_avail[2], st->range_avail[1]); break; @@ -520,12 +520,11 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, { struct ad5933_state *st = iio_priv(indio_dev); __be16 dat; - int ret = -EINVAL; + int ret; - mutex_lock(&indio_dev->mlock); switch (m) { case IIO_CHAN_INFO_RAW: - case IIO_CHAN_INFO_PROCESSED: + mutex_lock(&indio_dev->mlock); if (iio_buffer_enabled(indio_dev)) { ret = -EBUSY; goto out; @@ -543,16 +542,16 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, if (ret < 0) goto out; mutex_unlock(&indio_dev->mlock); - ret = be16_to_cpu(dat); - /* Temp in Milli degrees Celsius */ - if (ret < 8192) - *val = ret * 1000 / 32; - else - *val = (ret - 16384) * 1000 / 32; + *val = sign_extend32(be16_to_cpu(dat), 13); return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 1000; + *val2 = 5; + return IIO_VAL_FRACTIONAL_LOG2; } + return -EINVAL; out: mutex_unlock(&indio_dev->mlock); return ret; @@ -626,7 +625,7 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) { struct iio_buffer *buffer; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; @@ -712,9 +711,7 @@ static int ad5933_probe(struct i2c_client *client, st->client = client; if (!pdata) - st->pdata = &ad5933_default_pdata; - else - st->pdata = pdata; + pdata = &ad5933_default_pdata; st->reg = devm_regulator_get(&client->dev, "vcc"); if (!IS_ERR(st->reg)) { @@ -727,10 +724,10 @@ static int ad5933_probe(struct i2c_client *client, if (voltage_uv) st->vref_mv = voltage_uv / 1000; else - st->vref_mv = st->pdata->vref_mv; + st->vref_mv = pdata->vref_mv; - if (st->pdata->ext_clk_Hz) { - st->mclk_hz = st->pdata->ext_clk_Hz; + if (pdata->ext_clk_Hz) { + st->mclk_hz = pdata->ext_clk_Hz; st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK; } else { st->mclk_hz = AD5933_INT_OSC_FREQ_Hz; @@ -752,27 +749,16 @@ static int ad5933_probe(struct i2c_client *client, if (ret) goto error_disable_reg; - ret = iio_buffer_register(indio_dev, ad5933_channels, - ARRAY_SIZE(ad5933_channels)); - if (ret) - goto error_unreg_ring; - - /* enable both REAL and IMAG channels by default */ - iio_scan_mask_set(indio_dev, indio_dev->buffer, 0); - iio_scan_mask_set(indio_dev, indio_dev->buffer, 1); - ret = ad5933_setup(st); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring; ret = iio_device_register(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring; return 0; -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); error_unreg_ring: iio_kfifo_free(indio_dev->buffer); error_disable_reg: @@ -788,7 +774,6 @@ static int ad5933_remove(struct i2c_client *client) struct ad5933_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); iio_kfifo_free(indio_dev->buffer); if (!IS_ERR(st->reg)) regulator_disable(st->reg); diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index cc4ddcce4ff..8afae8e33d5 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -692,7 +692,7 @@ static ssize_t taos_luxtable_show(struct device *dev, int offset = 0; for (i = 0; i < ARRAY_SIZE(taos_device_lux); i++) { - offset += sprintf(buf + offset, "%d,%d,%d,", + offset += sprintf(buf + offset, "%u,%u,%u,", taos_device_lux[i].ratio, taos_device_lux[i].ch0, taos_device_lux[i].ch1); diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index 423f96bdf59..4a5dc26fed4 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -1147,7 +1147,7 @@ static ssize_t tsl2x7x_luxtable_show(struct device *dev, int offset = 0; while (i < (TSL2X7X_MAX_LUX_TABLE_SIZE * 3)) { - offset += snprintf(buf + offset, PAGE_SIZE, "%d,%d,%d,", + offset += snprintf(buf + offset, PAGE_SIZE, "%u,%u,%u,", chip->tsl2x7x_device_lux[i].ratio, chip->tsl2x7x_device_lux[i].ch0, chip->tsl2x7x_device_lux[i].ch1); diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index e8c98cf5707..f6739e2c24b 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -145,7 +145,6 @@ ssize_t ade7758_read_data_from_ring(struct device *dev, int ade7758_configure_ring(struct iio_dev *indio_dev); void ade7758_unconfigure_ring(struct iio_dev *indio_dev); -void ade7758_uninitialize_ring(struct iio_dev *indio_dev); int ade7758_set_irq(struct device *dev, bool enable); int ade7758_spi_write_reg_8(struct device *dev, diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index fb373b89dcc..70e96b20c2e 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -850,23 +850,15 @@ static int ade7758_probe(struct spi_device *spi) if (ret) goto error_free_tx; - ret = iio_buffer_register(indio_dev, - &ade7758_channels[0], - ARRAY_SIZE(ade7758_channels)); - if (ret) { - dev_err(&spi->dev, "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - /* Get the device into a sane initial state */ ret = ade7758_initial_setup(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring_funcs; if (spi->irq) { ret = ade7758_probe_trigger(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring_funcs; } ret = iio_device_register(indio_dev); @@ -878,8 +870,6 @@ static int ade7758_probe(struct spi_device *spi) error_remove_trigger: if (spi->irq) ade7758_remove_trigger(indio_dev); -error_uninitialize_ring: - ade7758_uninitialize_ring(indio_dev); error_unreg_ring_funcs: ade7758_unconfigure_ring(indio_dev); error_free_tx: @@ -897,7 +887,6 @@ static int ade7758_remove(struct spi_device *spi) iio_device_unregister(indio_dev); ade7758_stop_device(&indio_dev->dev); ade7758_remove_trigger(indio_dev); - ade7758_uninitialize_ring(indio_dev); ade7758_unconfigure_ring(indio_dev); kfree(st->tx); kfree(st->rx); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index 6e900649074..3792b576164 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -118,7 +118,7 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) struct iio_buffer *buffer; int ret = 0; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) { ret = -ENOMEM; return ret; @@ -180,8 +180,3 @@ error_iio_kfifo_free: iio_kfifo_free(indio_dev->buffer); return ret; } - -void ade7758_uninitialize_ring(struct iio_dev *indio_dev) -{ - iio_buffer_unregister(indio_dev); -} diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index 7d217430616..b0c7dbc8a42 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -116,7 +116,7 @@ static int ade7759_spi_read_reg_40(struct device *dev, mutex_lock(&st->buf_lock); st->tx[0] = ADE7759_READ_REG(reg_address); - memset(&st->tx[1], 0 , 5); + memset(&st->tx[1], 0, 5); ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index a6b2f906bb1..4410d7fdc1b 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -85,6 +85,9 @@ static inline int __is_po2(unsigned long long val) #include <linux/list.h> +int libcfs_arch_init(void); +void libcfs_arch_cleanup(void); + /* libcfs tcpip */ int libcfs_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask); int libcfs_ipif_enumerate(char ***names); diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h index 375586bf731..808e49411a3 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h @@ -454,25 +454,23 @@ cfs_hash_bkt_size(struct cfs_hash *hs) hs->hs_extra_bytes; } -#define CFS_HOP(hs, op) (hs)->hs_ops->hs_ ## op - static inline unsigned cfs_hash_id(struct cfs_hash *hs, const void *key, unsigned mask) { - return CFS_HOP(hs, hash)(hs, key, mask); + return hs->hs_ops->hs_hash(hs, key, mask); } static inline void * cfs_hash_key(struct cfs_hash *hs, struct hlist_node *hnode) { - return CFS_HOP(hs, key)(hnode); + return hs->hs_ops->hs_key(hnode); } static inline void cfs_hash_keycpy(struct cfs_hash *hs, struct hlist_node *hnode, void *key) { - if (CFS_HOP(hs, keycpy) != NULL) - CFS_HOP(hs, keycpy)(hnode, key); + if (hs->hs_ops->hs_keycpy) + hs->hs_ops->hs_keycpy(hnode, key); } /** @@ -481,42 +479,38 @@ cfs_hash_keycpy(struct cfs_hash *hs, struct hlist_node *hnode, void *key) static inline int cfs_hash_keycmp(struct cfs_hash *hs, const void *key, struct hlist_node *hnode) { - return CFS_HOP(hs, keycmp)(key, hnode); + return hs->hs_ops->hs_keycmp(key, hnode); } static inline void * cfs_hash_object(struct cfs_hash *hs, struct hlist_node *hnode) { - return CFS_HOP(hs, object)(hnode); + return hs->hs_ops->hs_object(hnode); } static inline void cfs_hash_get(struct cfs_hash *hs, struct hlist_node *hnode) { - return CFS_HOP(hs, get)(hs, hnode); + return hs->hs_ops->hs_get(hs, hnode); } static inline void cfs_hash_put_locked(struct cfs_hash *hs, struct hlist_node *hnode) { - LASSERT(CFS_HOP(hs, put_locked) != NULL); - - return CFS_HOP(hs, put_locked)(hs, hnode); + return hs->hs_ops->hs_put_locked(hs, hnode); } static inline void cfs_hash_put(struct cfs_hash *hs, struct hlist_node *hnode) { - LASSERT(CFS_HOP(hs, put) != NULL); - - return CFS_HOP(hs, put)(hs, hnode); + return hs->hs_ops->hs_put(hs, hnode); } static inline void cfs_hash_exit(struct cfs_hash *hs, struct hlist_node *hnode) { - if (CFS_HOP(hs, exit)) - CFS_HOP(hs, exit)(hs, hnode); + if (hs->hs_ops->hs_exit) + hs->hs_ops->hs_exit(hs, hnode); } static inline void cfs_hash_lock(struct cfs_hash *hs, int excl) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index 2817112c063..3d86fb5b548 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -458,14 +458,6 @@ struct libcfs_device_userstate { struct page *ldu_memhog_root_page; }; -/* what used to be in portals_lib.h */ -#ifndef MIN -# define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef MAX -# define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif - #define MKSTR(ptr) ((ptr)) ? (ptr) : "" static inline int cfs_size_round4(int val) diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 7e89b3be1a7..0038d29a37f 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -636,6 +636,7 @@ lnet_net2rnethash(__u32 net) } extern lnd_t the_lolnd; +extern int avoid_asym_router_failure; int lnet_cpt_of_nid_locked(lnet_nid_t nid); int lnet_cpt_of_nid(lnet_nid_t nid); @@ -752,9 +753,9 @@ int lnet_fail_nid(lnet_nid_t nid, unsigned int threshold); void lnet_counters_get(lnet_counters_t *counters); void lnet_counters_reset(void); -unsigned int lnet_iov_nob(unsigned int niov, struct iovec *iov); -int lnet_extract_iov(int dst_niov, struct iovec *dst, - int src_niov, struct iovec *src, +unsigned int lnet_iov_nob(unsigned int niov, struct kvec *iov); +int lnet_extract_iov(int dst_niov, struct kvec *dst, + int src_niov, struct kvec *src, unsigned int offset, unsigned int len); unsigned int lnet_kiov_nob(unsigned int niov, lnet_kiov_t *iov); @@ -762,17 +763,17 @@ int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, int src_niov, lnet_kiov_t *src, unsigned int offset, unsigned int len); -void lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov, +void lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, - unsigned int nsiov, struct iovec *siov, + unsigned int nsiov, struct kvec *siov, unsigned int soffset, unsigned int nob); -void lnet_copy_kiov2iov(unsigned int niov, struct iovec *iov, +void lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int nob); void lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset, - unsigned int niov, struct iovec *iov, + unsigned int niov, struct kvec *iov, unsigned int iovoffset, unsigned int nob); void lnet_copy_kiov2kiov(unsigned int ndkiov, lnet_kiov_t *dkiov, unsigned int doffset, @@ -781,10 +782,10 @@ void lnet_copy_kiov2kiov(unsigned int ndkiov, lnet_kiov_t *dkiov, static inline void lnet_copy_iov2flat(int dlen, void *dest, unsigned int doffset, - unsigned int nsiov, struct iovec *siov, unsigned int soffset, + unsigned int nsiov, struct kvec *siov, unsigned int soffset, unsigned int nob) { - struct iovec diov = {/*.iov_base = */ dest, /*.iov_len = */ dlen}; + struct kvec diov = {/*.iov_base = */ dest, /*.iov_len = */ dlen}; lnet_copy_iov2iov(1, &diov, doffset, nsiov, siov, soffset, nob); @@ -795,17 +796,17 @@ lnet_copy_kiov2flat(int dlen, void *dest, unsigned int doffset, unsigned int nsiov, lnet_kiov_t *skiov, unsigned int soffset, unsigned int nob) { - struct iovec diov = {/* .iov_base = */ dest, /* .iov_len = */ dlen}; + struct kvec diov = {/* .iov_base = */ dest, /* .iov_len = */ dlen}; lnet_copy_kiov2iov(1, &diov, doffset, nsiov, skiov, soffset, nob); } static inline void -lnet_copy_flat2iov(unsigned int ndiov, struct iovec *diov, unsigned int doffset, +lnet_copy_flat2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, int slen, void *src, unsigned int soffset, unsigned int nob) { - struct iovec siov = {/*.iov_base = */ src, /*.iov_len = */slen}; + struct kvec siov = {/*.iov_base = */ src, /*.iov_len = */slen}; lnet_copy_iov2iov(ndiov, diov, doffset, 1, &siov, soffset, nob); @@ -816,7 +817,7 @@ lnet_copy_flat2kiov(unsigned int ndiov, lnet_kiov_t *dkiov, unsigned int doffset, int slen, void *src, unsigned int soffset, unsigned int nob) { - struct iovec siov = {/* .iov_base = */ src, /* .iov_len = */ slen}; + struct kvec siov = {/* .iov_base = */ src, /* .iov_len = */ slen}; lnet_copy_iov2kiov(ndiov, dkiov, doffset, 1, &siov, soffset, nob); @@ -851,6 +852,7 @@ int lnet_peer_buffer_credits(lnet_ni_t *ni); int lnet_router_checker_start(void); void lnet_router_checker_stop(void); +void lnet_router_ni_update_locked(lnet_peer_t *gw, __u32 net); void lnet_swap_pinginfo(lnet_ping_info_t *info); int lnet_ping_target_init(void); @@ -870,4 +872,12 @@ void lnet_peer_tables_destroy(void); int lnet_peer_tables_create(void); void lnet_debug_peer(lnet_nid_t nid); +static inline void lnet_peer_set_alive(lnet_peer_t *lp) +{ + lp->lp_last_alive = lp->lp_last_query = get_seconds(); + if (!lp->lp_alive) + lnet_notify_locked(lp, 0, 1, lp->lp_last_alive); +} + + #endif diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index f16213f1771..50537668f59 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -217,7 +217,7 @@ typedef struct lnet_msg { unsigned int msg_wanted; unsigned int msg_offset; unsigned int msg_niov; - struct iovec *msg_iov; + struct kvec *msg_iov; lnet_kiov_t *msg_kiov; lnet_event_t msg_ev; @@ -271,7 +271,7 @@ typedef struct lnet_libmd { lnet_eq_t *md_eq; unsigned int md_niov; /* # frags */ union { - struct iovec iov[LNET_MAX_IOV]; + struct kvec iov[LNET_MAX_IOV]; lnet_kiov_t kiov[LNET_MAX_IOV]; } md_iov; } lnet_libmd_t; @@ -346,7 +346,7 @@ typedef struct lnet_lnd { * credit if the LND does flow control. */ int (*lnd_recv)(struct lnet_ni *ni, void *private, lnet_msg_t *msg, int delayed, unsigned int niov, - struct iovec *iov, lnet_kiov_t *kiov, + struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen); /* lnet_parse() has had to delay processing of this message @@ -622,7 +622,7 @@ typedef struct lnet_portal { /* Match table for each CPT */ struct lnet_match_table **ptl_mtables; /* spread rotor of incoming "PUT" */ - int ptl_rotor; + unsigned int ptl_rotor; /* # active entries for this portal */ int ptl_mt_nmaps; /* array of active entries' cpu-partition-id */ diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 62b575deac3..65101691966 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -1538,7 +1538,7 @@ kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status) fmr->fmr_pfmr = NULL; spin_lock(&fps->fps_lock); - fpo->fpo_map_count --; /* decref the pool */ + fpo->fpo_map_count--; /* decref the pool */ list_for_each_entry_safe(fpo, tmp, &fps->fps_pool_list, fpo_list) { /* the first pool is persistent */ @@ -1547,7 +1547,7 @@ kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status) if (kiblnd_fmr_pool_is_idle(fpo, now)) { list_move(&fpo->fpo_list, &zombies); - fps->fps_version ++; + fps->fps_version++; } } spin_unlock(&fps->fps_lock); @@ -1752,7 +1752,7 @@ kiblnd_pool_free_node(kib_pool_t *pool, struct list_head *node) LASSERT (pool->po_allocated > 0); list_add(node, &pool->po_free_list); - pool->po_allocated --; + pool->po_allocated--; list_for_each_entry_safe(pool, tmp, &ps->ps_pool_list, po_list) { /* the first pool is persistent */ @@ -1781,7 +1781,7 @@ kiblnd_pool_alloc_node(kib_poolset_t *ps) if (list_empty(&pool->po_free_list)) continue; - pool->po_allocated ++; + pool->po_allocated++; pool->po_deadline = cfs_time_shift(IBLND_POOL_DEADLINE); node = pool->po_free_list.next; list_del(node); @@ -1864,7 +1864,7 @@ kiblnd_pmr_pool_map(kib_pmr_poolset_t *pps, kib_hca_dev_t *hdev, return -EAGAIN; } - for (i = 0; i < rd->rd_nfrags; i ++) { + for (i = 0; i < rd->rd_nfrags; i++) { pmr->pmr_ipb[i].addr = rd->rd_frags[i].rf_addr; pmr->pmr_ipb[i].size = rd->rd_frags[i].rf_nob; } @@ -2117,7 +2117,7 @@ kiblnd_tx_init(kib_pool_t *pool, struct list_head *node) tps_poolset); kib_tx_t *tx = list_entry(node, kib_tx_t, tx_list); - tx->tx_cookie = tps->tps_next_tx_cookie ++; + tx->tx_cookie = tps->tps_next_tx_cookie++; } static void @@ -2326,7 +2326,7 @@ kiblnd_hdev_get_attr(kib_hca_dev_t *hdev) } for (hdev->ibh_mr_shift = 0; - hdev->ibh_mr_shift < 64; hdev->ibh_mr_shift ++) { + hdev->ibh_mr_shift < 64; hdev->ibh_mr_shift++) { if (hdev->ibh_mr_size == (1ULL << hdev->ibh_mr_shift) || hdev->ibh_mr_size == (1ULL << hdev->ibh_mr_shift) - 1) return 0; diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index b02b4ec1e29..ab128dee948 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -1026,5 +1026,5 @@ int kiblnd_post_rx (kib_rx_t *rx, int credit); int kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg); int kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, - unsigned int niov, struct iovec *iov, lnet_kiov_t *kiov, + unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen); diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index b48d7edf566..48d885dc51d 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -697,7 +697,7 @@ kiblnd_map_tx(lnet_ni_t *ni, kib_tx_t *tx, static int kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, - unsigned int niov, struct iovec *iov, int offset, int nob) + unsigned int niov, struct kvec *iov, int offset, int nob) { kib_net_t *net = ni->ni_data; struct page *page; @@ -1125,8 +1125,9 @@ kiblnd_init_rdma (kib_conn_t *conn, kib_tx_t *tx, int type, break; } - wrknob = MIN(MIN(kiblnd_rd_frag_size(srcrd, srcidx), - kiblnd_rd_frag_size(dstrd, dstidx)), resid); + wrknob = min(min(kiblnd_rd_frag_size(srcrd, srcidx), + kiblnd_rd_frag_size(dstrd, dstidx)), + (__u32) resid); sge = &tx->tx_sge[tx->tx_nwrq]; sge->addr = kiblnd_rd_frag_addr(srcrd, srcidx); @@ -1461,7 +1462,7 @@ kiblnd_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) int target_is_router = lntmsg->msg_target_is_router; int routing = lntmsg->msg_routing; unsigned int payload_niov = lntmsg->msg_niov; - struct iovec *payload_iov = lntmsg->msg_iov; + struct kvec *payload_iov = lntmsg->msg_iov; lnet_kiov_t *payload_kiov = lntmsg->msg_kiov; unsigned int payload_offset = lntmsg->msg_offset; unsigned int payload_nob = lntmsg->msg_len; @@ -1628,7 +1629,7 @@ kiblnd_reply (lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) { lnet_process_id_t target = lntmsg->msg_target; unsigned int niov = lntmsg->msg_niov; - struct iovec *iov = lntmsg->msg_iov; + struct kvec *iov = lntmsg->msg_iov; lnet_kiov_t *kiov = lntmsg->msg_kiov; unsigned int offset = lntmsg->msg_offset; unsigned int nob = lntmsg->msg_len; @@ -1687,7 +1688,7 @@ kiblnd_reply (lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) int kiblnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, - unsigned int niov, struct iovec *iov, lnet_kiov_t *kiov, + unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen) { kib_rx_t *rx = private; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 9188b34e694..5956dbac5d0 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -773,7 +773,7 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips) /* Only match interfaces for additional connections * if I have > 1 interface */ n_ips = (net->ksnn_ninterfaces < 2) ? 0 : - MIN(n_peerips, net->ksnn_ninterfaces); + min(n_peerips, net->ksnn_ninterfaces); for (i = 0; peer->ksnp_n_passive_ips < n_ips; i++) { /* ^ yes really... */ diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index a29d4da6e34..03488d289c7 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -69,7 +69,7 @@ typedef struct /* per scheduler state */ int kss_nconns; struct ksock_sched_info *kss_info; /* owner of it */ struct page *kss_rx_scratch_pgs[LNET_MAX_IOV]; - struct iovec kss_scratch_iov[LNET_MAX_IOV]; + struct kvec kss_scratch_iov[LNET_MAX_IOV]; } ksock_sched_t; struct ksock_sched_info { @@ -213,7 +213,7 @@ typedef struct /* transmit packet */ int tx_nob; /* # packet bytes */ int tx_resid; /* residual bytes */ int tx_niov; /* # packet iovec frags */ - struct iovec *tx_iov; /* packet iovec frags */ + struct kvec *tx_iov; /* packet iovec frags */ int tx_nkiov; /* # packet page frags */ unsigned short tx_zc_aborted; /* aborted ZC request */ unsigned short tx_zc_capable:1; /* payload is large enough for ZC */ @@ -227,11 +227,11 @@ typedef struct /* transmit packet */ int tx_desc_size; /* size of this descriptor */ union { struct { - struct iovec iov; /* virt hdr */ + struct kvec iov; /* virt hdr */ lnet_kiov_t kiov[0]; /* paged payload */ } paged; struct { - struct iovec iov[1]; /* virt hdr + payload */ + struct kvec iov[1]; /* virt hdr + payload */ } virt; } tx_frags; } ksock_tx_t; @@ -243,7 +243,7 @@ typedef struct /* transmit packet */ /* space for the rx frag descriptors; we either read a single contiguous * header, or up to LNET_MAX_IOV frags of payload of either type. */ typedef union { - struct iovec iov[LNET_MAX_IOV]; + struct kvec iov[LNET_MAX_IOV]; lnet_kiov_t kiov[LNET_MAX_IOV]; } ksock_rxiovspace_t; @@ -284,7 +284,7 @@ typedef struct ksock_conn { int ksnc_rx_nob_left; /* # bytes to next hdr/body */ int ksnc_rx_nob_wanted; /* bytes actually wanted */ int ksnc_rx_niov; /* # iovec frags */ - struct iovec *ksnc_rx_iov; /* the iovec frags */ + struct kvec *ksnc_rx_iov; /* the iovec frags */ int ksnc_rx_nkiov; /* # page frags */ lnet_kiov_t *ksnc_rx_kiov; /* the page frags */ ksock_rxiovspace_t ksnc_rx_iov_space;/* space for frag descriptors */ @@ -517,7 +517,7 @@ int ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg); int ksocknal_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg); int ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, unsigned int niov, - struct iovec *iov, lnet_kiov_t *kiov, + struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen); int ksocknal_accept(lnet_ni_t *ni, struct socket *sock); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index e6c1d364795..92760fe9418 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -110,7 +110,7 @@ ksocknal_free_tx (ksock_tx_t *tx) static int ksocknal_send_iov (ksock_conn_t *conn, ksock_tx_t *tx) { - struct iovec *iov = tx->tx_iov; + struct kvec *iov = tx->tx_iov; int nob; int rc; @@ -251,7 +251,7 @@ ksocknal_transmit (ksock_conn_t *conn, ksock_tx_t *tx) static int ksocknal_recv_iov (ksock_conn_t *conn) { - struct iovec *iov = conn->ksnc_rx_iov; + struct kvec *iov = conn->ksnc_rx_iov; int nob; int rc; @@ -926,7 +926,7 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) int type = lntmsg->msg_type; lnet_process_id_t target = lntmsg->msg_target; unsigned int payload_niov = lntmsg->msg_niov; - struct iovec *payload_iov = lntmsg->msg_iov; + struct kvec *payload_iov = lntmsg->msg_iov; lnet_kiov_t *payload_kiov = lntmsg->msg_kiov; unsigned int payload_offset = lntmsg->msg_offset; unsigned int payload_nob = lntmsg->msg_len; @@ -1047,8 +1047,8 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) case KSOCK_PROTO_V2: case KSOCK_PROTO_V3: conn->ksnc_rx_state = SOCKNAL_RX_KSM_HEADER; - conn->ksnc_rx_iov = (struct iovec *)&conn->ksnc_rx_iov_space; - conn->ksnc_rx_iov[0].iov_base = (char *)&conn->ksnc_msg; + conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; + conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg; conn->ksnc_rx_nob_wanted = offsetof(ksock_msg_t, ksm_u); conn->ksnc_rx_nob_left = offsetof(ksock_msg_t, ksm_u); @@ -1061,8 +1061,8 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) conn->ksnc_rx_nob_wanted = sizeof(lnet_hdr_t); conn->ksnc_rx_nob_left = sizeof(lnet_hdr_t); - conn->ksnc_rx_iov = (struct iovec *)&conn->ksnc_rx_iov_space; - conn->ksnc_rx_iov[0].iov_base = (char *)&conn->ksnc_msg.ksm_u.lnetmsg; + conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; + conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; conn->ksnc_rx_iov[0].iov_len = sizeof (lnet_hdr_t); break; @@ -1082,12 +1082,12 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) conn->ksnc_rx_state = SOCKNAL_RX_SLOP; conn->ksnc_rx_nob_left = nob_to_skip; - conn->ksnc_rx_iov = (struct iovec *)&conn->ksnc_rx_iov_space; + conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; skipped = 0; niov = 0; do { - nob = MIN (nob_to_skip, sizeof (ksocknal_slop_buffer)); + nob = min_t(int, nob_to_skip, sizeof(ksocknal_slop_buffer)); conn->ksnc_rx_iov[niov].iov_base = ksocknal_slop_buffer; conn->ksnc_rx_iov[niov].iov_len = nob; @@ -1212,8 +1212,8 @@ ksocknal_process_receive (ksock_conn_t *conn) conn->ksnc_rx_nob_wanted = sizeof(ksock_lnet_msg_t); conn->ksnc_rx_nob_left = sizeof(ksock_lnet_msg_t); - conn->ksnc_rx_iov = (struct iovec *)&conn->ksnc_rx_iov_space; - conn->ksnc_rx_iov[0].iov_base = (char *)&conn->ksnc_msg.ksm_u.lnetmsg; + conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; + conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; conn->ksnc_rx_iov[0].iov_len = sizeof(ksock_lnet_msg_t); conn->ksnc_rx_niov = 1; @@ -1311,7 +1311,7 @@ ksocknal_process_receive (ksock_conn_t *conn) int ksocknal_recv (lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, - unsigned int niov, struct iovec *iov, lnet_kiov_t *kiov, + unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen) { ksock_conn_t *conn = (ksock_conn_t *)private; @@ -1950,10 +1950,10 @@ ksocknal_connect (ksock_route_t *route) /* This is a retry rather than a new connection */ route->ksnr_retry_interval *= 2; route->ksnr_retry_interval = - MAX(route->ksnr_retry_interval, + max(route->ksnr_retry_interval, cfs_time_seconds(*ksocknal_tunables.ksnd_min_reconnectms)/1000); route->ksnr_retry_interval = - MIN(route->ksnr_retry_interval, + min(route->ksnr_retry_interval, cfs_time_seconds(*ksocknal_tunables.ksnd_max_reconnectms)/1000); LASSERT (route->ksnr_retry_interval != 0); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c index 245c9d7560a..66cc509295e 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c @@ -92,11 +92,11 @@ ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx) { #if SOCKNAL_SINGLE_FRAG_TX - struct iovec scratch; - struct iovec *scratchiov = &scratch; + struct kvec scratch; + struct kvec *scratchiov = &scratch; unsigned int niov = 1; #else - struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; + struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; unsigned int niov = tx->tx_niov; #endif struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; @@ -111,7 +111,7 @@ ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx) nob < tx->tx_resid) msg.msg_flags |= MSG_MORE; - rc = kernel_sendmsg(sock, &msg, (struct kvec *)scratchiov, niov, nob); + rc = kernel_sendmsg(sock, &msg, scratchiov, niov, nob); } return rc; } @@ -153,14 +153,14 @@ ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx) } } else { #if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK - struct iovec scratch; - struct iovec *scratchiov = &scratch; + struct kvec scratch; + struct kvec *scratchiov = &scratch; unsigned int niov = 1; #else #ifdef CONFIG_HIGHMEM #warning "XXX risk of kmap deadlock on multiple frags..." #endif - struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; + struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; unsigned int niov = tx->tx_nkiov; #endif struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; @@ -203,14 +203,14 @@ int ksocknal_lib_recv_iov (ksock_conn_t *conn) { #if SOCKNAL_SINGLE_FRAG_RX - struct iovec scratch; - struct iovec *scratchiov = &scratch; + struct kvec scratch; + struct kvec *scratchiov = &scratch; unsigned int niov = 1; #else - struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; + struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; unsigned int niov = conn->ksnc_rx_niov; #endif - struct iovec *iov = conn->ksnc_rx_iov; + struct kvec *iov = conn->ksnc_rx_iov; struct msghdr msg = { .msg_flags = 0 }; @@ -232,7 +232,7 @@ ksocknal_lib_recv_iov (ksock_conn_t *conn) LASSERT (nob <= conn->ksnc_rx_nob_wanted); rc = kernel_recvmsg(conn->ksnc_sock, &msg, - (struct kvec *)scratchiov, niov, nob, MSG_DONTWAIT); + scratchiov, niov, nob, MSG_DONTWAIT); saved_csum = 0; if (conn->ksnc_proto == &ksocknal_protocol_v2x) { @@ -269,7 +269,7 @@ ksocknal_lib_kiov_vunmap(void *addr) static void * ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov, - struct iovec *iov, struct page **pages) + struct kvec *iov, struct page **pages) { void *addr; int nob; @@ -307,15 +307,15 @@ int ksocknal_lib_recv_kiov (ksock_conn_t *conn) { #if SOCKNAL_SINGLE_FRAG_RX || !SOCKNAL_RISK_KMAP_DEADLOCK - struct iovec scratch; - struct iovec *scratchiov = &scratch; + struct kvec scratch; + struct kvec *scratchiov = &scratch; struct page **pages = NULL; unsigned int niov = 1; #else #ifdef CONFIG_HIGHMEM #warning "XXX risk of kmap deadlock on multiple frags..." #endif - struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; + struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; struct page **pages = conn->ksnc_scheduler->kss_rx_scratch_pgs; unsigned int niov = conn->ksnc_rx_nkiov; #endif @@ -390,13 +390,13 @@ ksocknal_lib_csum_tx(ksock_tx_t *tx) __u32 csum; void *base; - LASSERT(tx->tx_iov[0].iov_base == (void *)&tx->tx_msg); + LASSERT(tx->tx_iov[0].iov_base == &tx->tx_msg); LASSERT(tx->tx_conn != NULL); LASSERT(tx->tx_conn->ksnc_proto == &ksocknal_protocol_v2x); tx->tx_msg.ksm_csum = 0; - csum = ksocknal_csum(~0, (void *)tx->tx_iov[0].iov_base, + csum = ksocknal_csum(~0, tx->tx_iov[0].iov_base, tx->tx_iov[0].iov_len); if (tx->tx_kiov != NULL) { diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index ea9d80f40ca..b2f88eb47bb 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -717,7 +717,7 @@ ksocknal_pack_msg_v1(ksock_tx_t *tx) LASSERT(tx->tx_msg.ksm_type != KSOCK_MSG_NOOP); LASSERT(tx->tx_lnetmsg != NULL); - tx->tx_iov[0].iov_base = (void *)&tx->tx_lnetmsg->msg_hdr; + tx->tx_iov[0].iov_base = &tx->tx_lnetmsg->msg_hdr; tx->tx_iov[0].iov_len = sizeof(lnet_hdr_t); tx->tx_resid = tx->tx_nob = tx->tx_lnetmsg->msg_len + sizeof(lnet_hdr_t); @@ -726,7 +726,7 @@ ksocknal_pack_msg_v1(ksock_tx_t *tx) static void ksocknal_pack_msg_v2(ksock_tx_t *tx) { - tx->tx_iov[0].iov_base = (void *)&tx->tx_msg; + tx->tx_iov[0].iov_base = &tx->tx_msg; if (tx->tx_lnetmsg != NULL) { LASSERT(tx->tx_msg.ksm_type != KSOCK_MSG_NOOP); diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index c8c1ed84fe5..0f53c761f1a 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -158,7 +158,7 @@ fail_peer(lnet_nid_t nid, int outgoing) } unsigned int -lnet_iov_nob(unsigned int niov, struct iovec *iov) +lnet_iov_nob(unsigned int niov, struct kvec *iov) { unsigned int nob = 0; @@ -170,8 +170,8 @@ lnet_iov_nob(unsigned int niov, struct iovec *iov) EXPORT_SYMBOL(lnet_iov_nob); void -lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov, unsigned int doffset, - unsigned int nsiov, struct iovec *siov, unsigned int soffset, +lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, + unsigned int nsiov, struct kvec *siov, unsigned int soffset, unsigned int nob) { /* NB diov, siov are READ-ONLY */ @@ -201,9 +201,9 @@ lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov, unsigned int doffset, do { LASSERT(ndiov > 0); LASSERT(nsiov > 0); - this_nob = MIN(diov->iov_len - doffset, + this_nob = min(diov->iov_len - doffset, siov->iov_len - soffset); - this_nob = MIN(this_nob, nob); + this_nob = min(this_nob, nob); memcpy((char *)diov->iov_base + doffset, (char *)siov->iov_base + soffset, this_nob); @@ -229,8 +229,8 @@ lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov, unsigned int doffset, EXPORT_SYMBOL(lnet_copy_iov2iov); int -lnet_extract_iov(int dst_niov, struct iovec *dst, - int src_niov, struct iovec *src, +lnet_extract_iov(int dst_niov, struct kvec *dst, + int src_niov, struct kvec *src, unsigned int offset, unsigned int len) { /* Initialise 'dst' to the subset of 'src' starting at 'offset', @@ -322,9 +322,9 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, do { LASSERT(ndiov > 0); LASSERT(nsiov > 0); - this_nob = MIN(diov->kiov_len - doffset, + this_nob = min(diov->kiov_len - doffset, siov->kiov_len - soffset); - this_nob = MIN(this_nob, nob); + this_nob = min(this_nob, nob); if (daddr == NULL) daddr = ((char *)kmap(diov->kiov_page)) + @@ -371,7 +371,7 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, EXPORT_SYMBOL(lnet_copy_kiov2kiov); void -lnet_copy_kiov2iov(unsigned int niov, struct iovec *iov, unsigned int iovoffset, +lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int nob) { @@ -403,9 +403,9 @@ lnet_copy_kiov2iov(unsigned int niov, struct iovec *iov, unsigned int iovoffset, do { LASSERT(niov > 0); LASSERT(nkiov > 0); - this_nob = MIN(iov->iov_len - iovoffset, - kiov->kiov_len - kiovoffset); - this_nob = MIN(this_nob, nob); + this_nob = min(iov->iov_len - iovoffset, + (__kernel_size_t) kiov->kiov_len - kiovoffset); + this_nob = min(this_nob, nob); if (addr == NULL) addr = ((char *)kmap(kiov->kiov_page)) + @@ -443,7 +443,7 @@ EXPORT_SYMBOL(lnet_copy_kiov2iov); void lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int niov, - struct iovec *iov, unsigned int iovoffset, + struct kvec *iov, unsigned int iovoffset, unsigned int nob) { /* NB kiov, iov are READ-ONLY */ @@ -474,9 +474,9 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, do { LASSERT(nkiov > 0); LASSERT(niov > 0); - this_nob = MIN(kiov->kiov_len - kiovoffset, + this_nob = min((__kernel_size_t) kiov->kiov_len - kiovoffset, iov->iov_len - iovoffset); - this_nob = MIN(this_nob, nob); + this_nob = min(this_nob, nob); if (addr == NULL) addr = ((char *)kmap(kiov->kiov_page)) + @@ -566,7 +566,7 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, unsigned int offset, unsigned int mlen, unsigned int rlen) { unsigned int niov = 0; - struct iovec *iov = NULL; + struct kvec *iov = NULL; lnet_kiov_t *kiov = NULL; int rc; @@ -1530,7 +1530,7 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg_t *msg) LASSERT(md->md_offset == 0); rlength = hdr->payload_length; - mlength = MIN(rlength, (int)md->md_length); + mlength = min_t(int, rlength, md->md_length); if (mlength < rlength && (md->md_options & LNET_MD_TRUNCATE) == 0) { @@ -1877,6 +1877,19 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, goto drop; } + if (lnet_isrouter(msg->msg_rxpeer)) { + lnet_peer_set_alive(msg->msg_rxpeer); + if (avoid_asym_router_failure && + LNET_NIDNET(src_nid) != LNET_NIDNET(from_nid)) { + /* received a remote message from router, update + * remote NI status on this router. + * NB: multi-hop routed message will be ignored. + */ + lnet_router_ni_update_locked(msg->msg_rxpeer, + LNET_NIDNET(src_nid)); + } + } + lnet_msg_commit(msg, cpt); if (!for_me) { diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c index 19ed696344f..3ba0da919b4 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c +++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c @@ -262,10 +262,10 @@ lnet_mt_of_match(struct lnet_match_info *info, struct lnet_msg *msg) { struct lnet_match_table *mtable; struct lnet_portal *ptl; - int nmaps; - int rotor; - int routed; - int cpt; + unsigned int nmaps; + unsigned int rotor; + unsigned int cpt; + bool routed; /* NB: called w/o lock */ LASSERT(info->mi_portal < the_lnet.ln_nportals); diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c index 17e1643fd67..f708c2e649d 100644 --- a/drivers/staging/lustre/lnet/lnet/lo.c +++ b/drivers/staging/lustre/lnet/lnet/lo.c @@ -47,7 +47,7 @@ lolnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) static int lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, unsigned int niov, - struct iovec *iov, lnet_kiov_t *kiov, + struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen) { lnet_msg_t *sendmsg = private; diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c index 3c23677bc28..72b7fbc8371 100644 --- a/drivers/staging/lustre/lnet/lnet/module.c +++ b/drivers/staging/lustre/lnet/lnet/module.c @@ -108,7 +108,7 @@ lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_data *data) } } -DECLARE_IOCTL_HANDLER(lnet_ioctl_handler, lnet_ioctl); +static DECLARE_IOCTL_HANDLER(lnet_ioctl_handler, lnet_ioctl); static int __init init_lnet(void) diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index c667b5b7676..52ec0ab7e3c 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -46,7 +46,7 @@ MODULE_PARM_DESC(small_router_buffers, "# of small (1 page) messages to buffer i static int large_router_buffers; module_param(large_router_buffers, int, 0444); MODULE_PARM_DESC(large_router_buffers, "# of large messages to buffer in the router"); -static int peer_buffer_credits = 0; +static int peer_buffer_credits; module_param(peer_buffer_credits, int, 0444); MODULE_PARM_DESC(peer_buffer_credits, "# router buffer credits per peer"); @@ -80,11 +80,11 @@ lnet_peer_buffer_credits(lnet_ni_t *ni) #endif -static int check_routers_before_use = 0; +static int check_routers_before_use; module_param(check_routers_before_use, int, 0444); MODULE_PARM_DESC(check_routers_before_use, "Assume routers are down and ping them before use"); -static int avoid_asym_router_failure = 1; +int avoid_asym_router_failure = 1; module_param(avoid_asym_router_failure, int, 0644); MODULE_PARM_DESC(avoid_asym_router_failure, "Avoid asymmetrical router failures (0 to disable)"); @@ -245,7 +245,7 @@ lnet_find_net_locked (__u32 net) static void lnet_shuffle_seed(void) { - static int seeded = 0; + static int seeded; int lnd_type, seed[2]; struct timeval tv; lnet_ni_t *ni; @@ -783,6 +783,21 @@ lnet_wait_known_routerstate(void) } } +void +lnet_router_ni_update_locked(lnet_peer_t *gw, __u32 net) +{ + lnet_route_t *rte; + + if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) != 0) { + list_for_each_entry(rte, &gw->lp_routes, lr_gwlist) { + if (rte->lr_net == net) { + rte->lr_downis = 0; + break; + } + } + } +} + static void lnet_update_ni_status_locked(void) { @@ -793,7 +808,7 @@ lnet_update_ni_status_locked(void) LASSERT(the_lnet.ln_routing); timeout = router_ping_timeout + - MAX(live_router_check_interval, dead_router_check_interval); + max(live_router_check_interval, dead_router_check_interval); now = get_seconds(); list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) { @@ -1578,8 +1593,8 @@ lnet_notify (lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) void lnet_router_checker (void) { - static time_t last = 0; - static int running = 0; + static time_t last; + static int running; time_t now = get_seconds(); int interval = now - last; @@ -1593,7 +1608,7 @@ lnet_router_checker (void) return; if (last != 0 && - interval > MAX(live_router_check_interval, + interval > max(live_router_check_interval, dead_router_check_interval)) CNETERR("Checker(%d/%d) not called for %d seconds\n", live_router_check_interval, dead_router_check_interval, @@ -1664,13 +1679,16 @@ lnet_get_tunables (void) char *s; s = getenv("LNET_ROUTER_PING_TIMEOUT"); - if (s != NULL) router_ping_timeout = atoi(s); + if (s != NULL) + router_ping_timeout = atoi(s); s = getenv("LNET_LIVE_ROUTER_CHECK_INTERVAL"); - if (s != NULL) live_router_check_interval = atoi(s); + if (s != NULL) + live_router_check_interval = atoi(s); s = getenv("LNET_DEAD_ROUTER_CHECK_INTERVAL"); - if (s != NULL) dead_router_check_interval = atoi(s); + if (s != NULL) + dead_router_check_interval = atoi(s); /* This replaces old lnd_notify mechanism */ check_routers_before_use = 1; diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index 46cde7036f1..c055afc86eb 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -49,7 +49,7 @@ enum { */ #define LNET_PROC_CPT_BITS (LNET_CPT_BITS + 1) /* change version, 16 bits or 8 bits */ -#define LNET_PROC_VER_BITS MAX(((MIN(LNET_LOFFT_BITS, 64)) / 4), 8) +#define LNET_PROC_VER_BITS max_t(size_t, min_t(size_t, LNET_LOFFT_BITS, 64) / 4, 8) #define LNET_PROC_HASH_BITS LNET_PEER_HASH_BITS /* diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c index 5bc615309e7..fbff84cea52 100644 --- a/drivers/staging/lustre/lnet/selftest/conctl.c +++ b/drivers/staging/lustre/lnet/selftest/conctl.c @@ -721,7 +721,7 @@ lst_stat_query_ioctl(lstio_stat_args_t *args) return rc; } -int lst_test_add_ioctl(lstio_test_args_t *args) +static int lst_test_add_ioctl(lstio_test_args_t *args) { char *batch_name; char *src_name = NULL; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 9999b0dc03e..77f02b76128 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -703,7 +703,7 @@ lstcon_statrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc) return 0; } -lnet_process_id_packed_t * +static lnet_process_id_packed_t * lstcon_next_id(int idx, int nkiov, lnet_kiov_t *kiov) { lnet_process_id_packed_t *pid; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.h b/drivers/staging/lustre/lnet/selftest/conrpc.h index fc1cb56cbab..2353889c6ea 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.h +++ b/drivers/staging/lustre/lnet/selftest/conrpc.h @@ -54,7 +54,7 @@ #define LST_TRANS_TIMEOUT 30 #define LST_TRANS_MIN_TIMEOUT 3 -#define LST_VALIDATE_TIMEOUT(t) MIN(MAX(t, LST_TRANS_MIN_TIMEOUT), LST_TRANS_TIMEOUT) +#define LST_VALIDATE_TIMEOUT(t) min(max(t, LST_TRANS_MIN_TIMEOUT), LST_TRANS_TIMEOUT) #define LST_PING_INTERVAL 8 diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 49cb6543d53..1e0afc28684 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -46,17 +46,17 @@ #include "console.h" #include "conrpc.h" -#define LST_NODE_STATE_COUNTER(nd, p) \ -do { \ - if ((nd)->nd_state == LST_NODE_ACTIVE) \ - (p)->nle_nactive ++; \ +#define LST_NODE_STATE_COUNTER(nd, p) \ +do { \ + if ((nd)->nd_state == LST_NODE_ACTIVE) \ + (p)->nle_nactive++; \ else if ((nd)->nd_state == LST_NODE_BUSY) \ - (p)->nle_nbusy ++; \ + (p)->nle_nbusy++; \ else if ((nd)->nd_state == LST_NODE_DOWN) \ - (p)->nle_ndown ++; \ - else \ - (p)->nle_nunknown ++; \ - (p)->nle_nnode ++; \ + (p)->nle_ndown++; \ + else \ + (p)->nle_nunknown++; \ + (p)->nle_nnode++; \ } while (0) lstcon_session_t console_session; @@ -223,7 +223,7 @@ lstcon_group_alloc(char *name, lstcon_group_t **grpp) static void lstcon_group_addref(lstcon_group_t *grp) { - grp->grp_ref ++; + grp->grp_ref++; } static void lstcon_group_ndlink_release(lstcon_group_t *, lstcon_ndlink_t *); @@ -298,7 +298,7 @@ lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, return 0; list_add_tail(&(*ndlpp)->ndl_link, &grp->grp_ndl_list); - grp->grp_nnode ++; + grp->grp_nnode++; return 0; } @@ -324,7 +324,7 @@ lstcon_group_ndlink_move(lstcon_group_t *old, list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]); list_add_tail(&ndl->ndl_link, &new->grp_ndl_list); - new->grp_nnode ++; + new->grp_nnode++; return; } @@ -767,7 +767,7 @@ lstcon_nodes_getent(struct list_head *head, int *index_p, &nd->nd_state, sizeof(nd->nd_state))) return -EFAULT; - count ++; + count++; } if (index <= *index_p) @@ -1343,7 +1343,7 @@ lstcon_test_add(char *batch_name, int type, int loop, /* add to test list anyway, so user can check what's going on */ list_add_tail(&test->tes_link, &batch->bat_test_list); - batch->bat_ntest ++; + batch->bat_ntest++; test->tes_hdr.tsb_index = batch->bat_ntest; /* hold groups so nobody can change them */ @@ -1986,7 +1986,7 @@ static void lstcon_init_acceptor_service(void) extern int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data); -DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry); +static DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry); /* initialize console */ int diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index cc9d1826ae6..570914828b8 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -103,7 +103,7 @@ do { \ #define sfw_test_active(t) (atomic_read(&(t)->tsi_nactive) != 0) #define sfw_batch_active(b) (atomic_read(&(b)->bat_nactive) != 0) -struct smoketest_framework { +static struct smoketest_framework { struct list_head fw_zombie_rpcs; /* RPCs to be recycled */ struct list_head fw_zombie_sessions; /* stopping sessions */ struct list_head fw_tests; /* registered test cases */ @@ -194,9 +194,9 @@ sfw_del_session_timer (void) return EBUSY; /* racing with sfw_session_expired() */ } -/* called with sfw_data.fw_lock held */ static void sfw_deactivate_session (void) + __must_hold(&sfw_data.fw_lock) { sfw_session_t *sn = sfw_data.fw_session; int nactive = 0; diff --git a/drivers/staging/lustre/lnet/selftest/module.c b/drivers/staging/lustre/lnet/selftest/module.c index c6ef5b0d8de..faf40980237 100644 --- a/drivers/staging/lustre/lnet/selftest/module.c +++ b/drivers/staging/lustre/lnet/selftest/module.c @@ -61,31 +61,31 @@ lnet_selftest_fini(void) int i; switch (lst_init_step) { - case LST_INIT_CONSOLE: - lstcon_console_fini(); - case LST_INIT_FW: - sfw_shutdown(); - case LST_INIT_RPC: - srpc_shutdown(); - case LST_INIT_WI_TEST: - for (i = 0; - i < cfs_cpt_number(lnet_cpt_table()); i++) { - if (lst_sched_test[i] == NULL) - continue; - cfs_wi_sched_destroy(lst_sched_test[i]); - } - LIBCFS_FREE(lst_sched_test, - sizeof(lst_sched_test[0]) * - cfs_cpt_number(lnet_cpt_table())); - lst_sched_test = NULL; - - case LST_INIT_WI_SERIAL: - cfs_wi_sched_destroy(lst_sched_serial); - lst_sched_serial = NULL; - case LST_INIT_NONE: - break; - default: - LBUG(); + case LST_INIT_CONSOLE: + lstcon_console_fini(); + case LST_INIT_FW: + sfw_shutdown(); + case LST_INIT_RPC: + srpc_shutdown(); + case LST_INIT_WI_TEST: + for (i = 0; + i < cfs_cpt_number(lnet_cpt_table()); i++) { + if (lst_sched_test[i] == NULL) + continue; + cfs_wi_sched_destroy(lst_sched_test[i]); + } + LIBCFS_FREE(lst_sched_test, + sizeof(lst_sched_test[0]) * + cfs_cpt_number(lnet_cpt_table())); + lst_sched_test = NULL; + + case LST_INIT_WI_SERIAL: + cfs_wi_sched_destroy(lst_sched_serial); + lst_sched_serial = NULL; + case LST_INIT_NONE: + break; + default: + LBUG(); } return; } diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index f753add7bfb..1f7d9a6248d 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -54,7 +54,7 @@ typedef enum { SRPC_STATE_STOPPING, } srpc_state_t; -struct smoketest_rpc { +static struct smoketest_rpc { spinlock_t rpc_glock; /* global lock */ srpc_service_t *rpc_services[SRPC_SERVICE_MAX_ID + 1]; lnet_handle_eq_t rpc_lnet_eq; /* _the_ LNet event queue */ @@ -468,6 +468,7 @@ srpc_post_passive_rqtbuf(int service, int local, void *buf, int len, static int srpc_service_post_buffer(struct srpc_service_cd *scd, struct srpc_buffer *buf) + __must_hold(&scd->scd_lock) { struct srpc_service *sv = scd->scd_svc; struct srpc_msg *msg = &buf->buf_msg; @@ -559,7 +560,7 @@ srpc_add_buffer(struct swi_workitem *wi) LASSERT(scd->scd_buf_posting > 0); scd->scd_buf_posting--; scd->scd_buf_total++; - scd->scd_buf_low = MAX(2, scd->scd_buf_total / 4); + scd->scd_buf_low = max(2, scd->scd_buf_total / 4); } if (rc != 0) { @@ -697,6 +698,7 @@ srpc_finish_service(struct srpc_service *sv) /* called with sv->sv_lock held */ static void srpc_service_recycle_buffer(struct srpc_service_cd *scd, srpc_buffer_t *buf) + __must_hold(&scd->scd_lock) { if (!scd->scd_svc->sv_shuttingdown && scd->scd_buf_adjust >= 0) { if (srpc_service_post_buffer(scd, buf) != 0) { @@ -1486,7 +1488,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) if (scd->scd_buf_err == 0 && /* adding buffer is enabled */ scd->scd_buf_adjust == 0 && scd->scd_buf_nposted < scd->scd_buf_low) { - scd->scd_buf_adjust = MAX(scd->scd_buf_total / 2, + scd->scd_buf_adjust = max(scd->scd_buf_total / 2, SFW_TEST_WI_MIN); swi_schedule_workitem(&scd->scd_buf_wi); } diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 9b5c5df6eb2..d48701834b1 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -609,4 +609,16 @@ srpc_wait_service_shutdown(srpc_service_t *sv) } } +extern sfw_test_client_ops_t brw_test_client; +void brw_init_test_client(void); + +extern srpc_service_t brw_test_service; +void brw_init_test_service(void); + +extern sfw_test_client_ops_t ping_test_client; +void ping_init_test_client(void); + +extern srpc_service_t ping_test_service; +void ping_init_test_service(void); + #endif /* __SELFTEST_SELFTEST_H__ */ diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c index f8352c2a7d3..441f9472a83 100644 --- a/drivers/staging/lustre/lnet/selftest/timer.c +++ b/drivers/staging/lustre/lnet/selftest/timer.c @@ -57,7 +57,7 @@ #define STTIMER_SLOT(t) (&stt_data.stt_hash[(((t) >> STTIMER_MINPOLL) & \ (STTIMER_NSLOTS - 1))]) -struct st_timer_data { +static struct st_timer_data { spinlock_t stt_lock; /* start time of the slot processed previously */ unsigned long stt_prev_slot; diff --git a/drivers/staging/lustre/lustre/fid/fid_internal.h b/drivers/staging/lustre/lustre/fid/fid_internal.h index eb607c52ef3..b5e8da8956f 100644 --- a/drivers/staging/lustre/lustre/fid/fid_internal.h +++ b/drivers/staging/lustre/lustre/fid/fid_internal.h @@ -47,7 +47,7 @@ int seq_client_alloc_super(struct lu_client_seq *seq, const struct lu_env *env); -#if defined (CONFIG_PROC_FS) +#if defined(CONFIG_PROC_FS) extern struct lprocfs_vars seq_client_proc_list[]; #endif diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c index 64b1d80c64b..063441abfcf 100644 --- a/drivers/staging/lustre/lustre/fid/fid_request.c +++ b/drivers/staging/lustre/lustre/fid/fid_request.c @@ -402,7 +402,7 @@ EXPORT_SYMBOL(seq_client_flush); static void seq_client_proc_fini(struct lu_client_seq *seq) { -#if defined (CONFIG_PROC_FS) +#if defined(CONFIG_PROC_FS) if (seq->lcs_proc_dir) { if (!IS_ERR(seq->lcs_proc_dir)) lprocfs_remove(&seq->lcs_proc_dir); @@ -413,7 +413,7 @@ static void seq_client_proc_fini(struct lu_client_seq *seq) static int seq_client_proc_init(struct lu_client_seq *seq) { -#if defined (CONFIG_PROC_FS) +#if defined(CONFIG_PROC_FS) int rc; seq->lcs_proc_dir = lprocfs_register(seq->lcs_name, diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c index 5d95d0b358b..0d0a7374506 100644 --- a/drivers/staging/lustre/lustre/fld/fld_cache.c +++ b/drivers/staging/lustre/lustre/fld/fld_cache.c @@ -257,9 +257,9 @@ void fld_cache_flush(struct fld_cache *cache) * entry accordingly. */ -void fld_cache_punch_hole(struct fld_cache *cache, - struct fld_cache_entry *f_curr, - struct fld_cache_entry *f_new) +static void fld_cache_punch_hole(struct fld_cache *cache, + struct fld_cache_entry *f_curr, + struct fld_cache_entry *f_new) { const struct lu_seq_range *range = &f_new->fce_range; const u64 new_start = range->lsr_start; diff --git a/drivers/staging/lustre/lustre/fld/fld_internal.h b/drivers/staging/lustre/lustre/fld/fld_internal.h index 8806b609695..6125bbe822b 100644 --- a/drivers/staging/lustre/lustre/fld/fld_internal.h +++ b/drivers/staging/lustre/lustre/fld/fld_internal.h @@ -111,7 +111,7 @@ struct fld_cache { /** * Cache name used for debug and messages. */ - char fci_name[80]; + char fci_name[LUSTRE_MDT_MAXNAMELEN]; unsigned int fci_no_shrink:1; }; diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index 0d361ff4321..b8d17e109a9 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -131,11 +131,20 @@ fld_rrb_scan(struct lu_client_fld *fld, u64 seq) else hash = 0; +again: list_for_each_entry(target, &fld->lcf_targets, ft_chain) { if (target->ft_idx == hash) return target; } + if (hash != 0) { + /* It is possible the remote target(MDT) are not connected to + * with client yet, so we will refer this to MDT0, which should + * be connected during mount */ + hash = 0; + goto again; + } + CERROR("%s: Can't find target by hash %d (seq %#llx). Targets (%d):\n", fld->lcf_name, hash, seq, fld->lcf_count); @@ -269,7 +278,7 @@ int fld_client_del_target(struct lu_client_fld *fld, __u64 idx) } EXPORT_SYMBOL(fld_client_del_target); -struct proc_dir_entry *fld_type_proc_dir = NULL; +static struct proc_dir_entry *fld_type_proc_dir; #if defined (CONFIG_PROC_FS) static int fld_client_proc_init(struct lu_client_fld *fld) diff --git a/drivers/staging/lustre/lustre/fld/lproc_fld.c b/drivers/staging/lustre/lustre/fld/lproc_fld.c index 95e7de18d2f..8c5a65704a3 100644 --- a/drivers/staging/lustre/lustre/fld/lproc_fld.c +++ b/drivers/staging/lustre/lustre/fld/lproc_fld.c @@ -87,13 +87,21 @@ fld_proc_hash_seq_show(struct seq_file *m, void *unused) } static ssize_t -fld_proc_hash_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +fld_proc_hash_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct lu_client_fld *fld; struct lu_fld_hash *hash = NULL; + char fh_name[8]; int i; + if (count > sizeof(fh_name)) + return -ENAMETOOLONG; + + if (copy_from_user(fh_name, buffer, count) != 0) + return -EFAULT; + fld = ((struct seq_file *)file->private_data)->private; LASSERT(fld != NULL); @@ -101,7 +109,7 @@ fld_proc_hash_seq_write(struct file *file, const char *buffer, if (count != strlen(fld_hash[i].fh_name)) continue; - if (!strncmp(fld_hash[i].fh_name, buffer, count)) { + if (!strncmp(fld_hash[i].fh_name, fh_name, count)) { hash = &fld_hash[i]; break; } @@ -146,7 +154,7 @@ static int fld_proc_cache_flush_release(struct inode *inode, struct file *file) return 0; } -struct file_operations fld_proc_cache_flush_fops = { +static struct file_operations fld_proc_cache_flush_fops = { .owner = THIS_MODULE, .open = fld_proc_cache_flush_open, .write = fld_proc_cache_flush_write, diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h index b3b841f4d6e..c5c3a8d9eaa 100644 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ b/drivers/staging/lustre/lustre/include/lclient.h @@ -135,6 +135,7 @@ static inline struct ccc_thread_info *ccc_env_info(const struct lu_env *env) static inline struct cl_attr *ccc_env_thread_attr(const struct lu_env *env) { struct cl_attr *attr = &ccc_env_info(env)->cti_attr; + memset(attr, 0, sizeof(*attr)); return attr; } @@ -142,6 +143,7 @@ static inline struct cl_attr *ccc_env_thread_attr(const struct lu_env *env) static inline struct cl_io *ccc_env_thread_io(const struct lu_env *env) { struct cl_io *io = &ccc_env_info(env)->cti_io; + memset(io, 0, sizeof(*io)); return io; } @@ -323,6 +325,7 @@ void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice); int ccc_lock_enqueue(const struct lu_env *env, const struct cl_lock_slice *slice, struct cl_io *io, __u32 enqflags); +int ccc_lock_use(const struct lu_env *env, const struct cl_lock_slice *slice); int ccc_lock_unuse(const struct lu_env *env, const struct cl_lock_slice *slice); int ccc_lock_wait(const struct lu_env *env, const struct cl_lock_slice *slice); int ccc_lock_fits_into(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index cfe503b7df6..8a25cf6f682 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -627,16 +627,16 @@ struct adaptive_timeout; extern int lprocfs_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at); extern int lprocfs_rd_timeouts(struct seq_file *m, void *data); -extern int lprocfs_wr_timeouts(struct file *file, const char *buffer, +extern int lprocfs_wr_timeouts(struct file *file, const char __user *buffer, unsigned long count, void *data); -extern int lprocfs_wr_evict_client(struct file *file, const char *buffer, +extern int lprocfs_wr_evict_client(struct file *file, const char __user *buffer, size_t count, loff_t *off); -extern int lprocfs_wr_ping(struct file *file, const char *buffer, +extern int lprocfs_wr_ping(struct file *file, const char __user *buffer, size_t count, loff_t *off); -extern int lprocfs_wr_import(struct file *file, const char *buffer, +extern int lprocfs_wr_import(struct file *file, const char __user *buffer, size_t count, loff_t *off); extern int lprocfs_rd_pinger_recov(struct seq_file *m, void *n); -extern int lprocfs_wr_pinger_recov(struct file *file, const char *buffer, +extern int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer, size_t count, loff_t *off); /* Statfs helpers */ @@ -650,8 +650,8 @@ extern int lprocfs_rd_filesfree(struct seq_file *m, void *data); extern int lprocfs_write_helper(const char __user *buffer, unsigned long count, int *val); extern int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult); -extern int lprocfs_write_u64_helper(const char *buffer, unsigned long count, - __u64 *val); +extern int lprocfs_write_u64_helper(const char __user *buffer, + unsigned long count, __u64 *val); extern int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, __u64 *val, int mult); @@ -716,7 +716,8 @@ static struct file_operations name##_fops = { \ return lprocfs_rd_##type(m, m->private); \ } \ static ssize_t name##_##type##_seq_write(struct file *file, \ - const char *buffer, size_t count, loff_t *off) \ + const char __user *buffer, size_t count, \ + loff_t *off) \ { \ struct seq_file *seq = file->private_data; \ return lprocfs_wr_##type(file, buffer, \ @@ -726,7 +727,8 @@ static struct file_operations name##_fops = { \ #define LPROC_SEQ_FOPS_WR_ONLY(name, type) \ static ssize_t name##_##type##_write(struct file *file, \ - const char *buffer, size_t count, loff_t *off) \ + const char __user *buffer, size_t count, \ + loff_t *off) \ { \ return lprocfs_wr_##type(file, buffer, count, off); \ } \ @@ -939,20 +941,24 @@ static inline int lprocfs_at_hist_helper(struct seq_file *m, static inline int lprocfs_rd_timeouts(struct seq_file *m, void *data) { return 0; } static inline int lprocfs_wr_timeouts(struct file *file, - const char *buffer, - unsigned long count, void *data) + const char __user *buffer, + unsigned long count, void *data) { return 0; } -static inline int lprocfs_wr_evict_client(struct file *file, const char *buffer, - size_t count, loff_t *off) +static inline int lprocfs_wr_evict_client(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { return 0; } -static inline int lprocfs_wr_ping(struct file *file, const char *buffer, - size_t count, loff_t *off) +static inline int lprocfs_wr_ping(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { return 0; } -static inline int lprocfs_wr_import(struct file *file, const char *buffer, - size_t count, loff_t *off) +static inline int lprocfs_wr_import(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { return 0; } -static inline int lprocfs_wr_pinger_recov(struct file *file, const char *buffer, - size_t count, loff_t *off) +static inline int lprocfs_wr_pinger_recov(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { return 0; } /* Statfs helpers */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 7b7457cf70e..305ecbee9b7 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -105,6 +105,11 @@ * FOO_BULK_PORTAL is for incoming bulk on the FOO */ +/* Lustre service names are following the format + * service name + MDT + seq name + */ +#define LUSTRE_MDT_MAXNAMELEN 80 + #define CONNMGR_REQUEST_PORTAL 1 #define CONNMGR_REPLY_PORTAL 2 //#define OSC_REQUEST_PORTAL 3 diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index 2d6fbb4b1b3..0a0929fd902 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -358,7 +358,7 @@ struct lu_client_seq { * Service uuid, passed from MDT + seq name to form unique seq name to * use it with procfs. */ - char lcs_name[80]; + char lcs_name[LUSTRE_MDT_MAXNAMELEN]; /* * Sequence width, that is how many objects may be allocated in one @@ -408,7 +408,7 @@ struct lu_server_seq { * Service uuid, passed from MDT + seq name to form unique seq name to * use it with procfs. */ - char lss_name[80]; + char lss_name[LUSTRE_MDT_MAXNAMELEN]; /* * Allocation chunks for super and meta sequences. Default values are diff --git a/drivers/staging/lustre/lustre/include/lustre_fld.h b/drivers/staging/lustre/lustre/include/lustre_fld.h index 64c504849a2..5ee4b1ed099 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fld.h +++ b/drivers/staging/lustre/lustre/include/lustre_fld.h @@ -93,7 +93,7 @@ struct lu_server_fld { /** * Fld service name in form "fld-srv-lustre-MDTXXX" */ - char lsf_name[80]; + char lsf_name[LUSTRE_MDT_MAXNAMELEN]; }; @@ -124,7 +124,7 @@ struct lu_client_fld { /** * Client fld proc entry name. */ - char lcf_name[80]; + char lcf_name[LUSTRE_MDT_MAXNAMELEN]; int lcf_flags; }; diff --git a/drivers/staging/lustre/lustre/include/lustre_update.h b/drivers/staging/lustre/lustre/include/lustre_update.h deleted file mode 100644 index 84defce0f62..00000000000 --- a/drivers/staging/lustre/lustre/include/lustre_update.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.htm - * - * GPL HEADER END - */ -/* - * Copyright (c) 2013, Intel Corporation. - */ -/* - * lustre/include/lustre_update.h - * - * Author: Di Wang <di.wang@intel.com> - */ - -#ifndef _LUSTRE_UPDATE_H -#define _LUSTRE_UPDATE_H - -#define UPDATE_BUFFER_SIZE 8192 -struct update_request { - struct dt_device *ur_dt; - struct list_head ur_list; /* attached itself to thandle */ - int ur_flags; - int ur_rc; /* request result */ - int ur_batchid; /* Current batch(trans) id */ - struct update_buf *ur_buf; /* Holding the update req */ -}; - -static inline unsigned long update_size(struct update *update) -{ - unsigned long size; - int i; - - size = cfs_size_round(offsetof(struct update, u_bufs[0])); - for (i = 0; i < UPDATE_BUF_COUNT; i++) - size += cfs_size_round(update->u_lens[i]); - - return size; -} - -static inline void *update_param_buf(struct update *update, int index, - int *size) -{ - int i; - void *ptr; - - if (index >= UPDATE_BUF_COUNT) - return NULL; - - ptr = (char *)update + cfs_size_round(offsetof(struct update, - u_bufs[0])); - for (i = 0; i < index; i++) { - LASSERT(update->u_lens[i] > 0); - ptr += cfs_size_round(update->u_lens[i]); - } - - if (size != NULL) - *size = update->u_lens[index]; - - return ptr; -} - -static inline unsigned long update_buf_size(struct update_buf *buf) -{ - unsigned long size; - int i = 0; - - size = cfs_size_round(offsetof(struct update_buf, ub_bufs[0])); - for (i = 0; i < buf->ub_count; i++) { - struct update *update; - - update = (struct update *)((char *)buf + size); - size += update_size(update); - } - LASSERT(size <= UPDATE_BUFFER_SIZE); - return size; -} - -static inline void *update_buf_get(struct update_buf *buf, int index, int *size) -{ - int count = buf->ub_count; - void *ptr; - int i = 0; - - if (index >= count) - return NULL; - - ptr = (char *)buf + cfs_size_round(offsetof(struct update_buf, - ub_bufs[0])); - for (i = 0; i < index; i++) - ptr += update_size((struct update *)ptr); - - if (size != NULL) - *size = update_size((struct update *)ptr); - - return ptr; -} - -static inline void update_init_reply_buf(struct update_reply *reply, int count) -{ - reply->ur_version = UPDATE_REPLY_V1; - reply->ur_count = count; -} - -static inline void *update_get_buf_internal(struct update_reply *reply, - int index, int *size) -{ - char *ptr; - int count = reply->ur_count; - int i; - - if (index >= count) - return NULL; - - ptr = (char *)reply + cfs_size_round(offsetof(struct update_reply, - ur_lens[count])); - for (i = 0; i < index; i++) { - LASSERT(reply->ur_lens[i] > 0); - ptr += cfs_size_round(reply->ur_lens[i]); - } - - if (size != NULL) - *size = reply->ur_lens[index]; - - return ptr; -} - -static inline void update_insert_reply(struct update_reply *reply, void *data, - int data_len, int index, int rc) -{ - char *ptr; - - ptr = update_get_buf_internal(reply, index, NULL); - LASSERT(ptr != NULL); - - *(int *)ptr = cpu_to_le32(rc); - ptr += sizeof(int); - if (data_len > 0) { - LASSERT(data != NULL); - memcpy(ptr, data, data_len); - } - reply->ur_lens[index] = data_len + sizeof(int); -} - -static inline int update_get_reply_buf(struct update_reply *reply, void **buf, - int index) -{ - char *ptr; - int size = 0; - int result; - - ptr = update_get_buf_internal(reply, index, &size); - result = *(int *)ptr; - - if (result < 0) - return result; - - LASSERT((ptr != NULL && size >= sizeof(int))); - *buf = ptr + sizeof(int); - return size - sizeof(int); -} - -static inline int update_get_reply_result(struct update_reply *reply, - void **buf, int index) -{ - void *ptr; - int size; - - ptr = update_get_buf_internal(reply, index, &size); - LASSERT(ptr != NULL && size > sizeof(int)); - return *(int *)ptr; -} - -#endif diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index 24d26ab3534..23095bb7522 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -586,6 +586,12 @@ int ccc_lock_enqueue(const struct lu_env *env, return 0; } +int ccc_lock_use(const struct lu_env *env, const struct cl_lock_slice *slice) +{ + CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); + return 0; +} + int ccc_lock_unuse(const struct lu_env *env, const struct cl_lock_slice *slice) { CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index 6c6c57ca91d..20e64cddb1f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -249,8 +249,9 @@ typedef enum ldlm_policy_res ldlm_policy_res_t; struct __##var##__dummy_read {; } /* semicolon catcher */ #define LDLM_POOL_PROC_WRITER(var, type) \ - static int lprocfs_wr_##var(struct file *file, const char *buffer, \ - unsigned long count, void *data) \ + static int lprocfs_wr_##var(struct file *file, \ + const char __user *buffer, \ + unsigned long count, void *data) \ { \ struct ldlm_pool *pl = data; \ type tmp; \ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 4c838f615a6..d20d277dc2f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -470,6 +470,7 @@ static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl) static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) { time_t recalc_interval_sec; + int ret; recalc_interval_sec = get_seconds() - pl->pl_recalc_time; if (recalc_interval_sec < pl->pl_recalc_period) @@ -490,16 +491,15 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) */ ldlm_cli_pool_pop_slv(pl); - pl->pl_recalc_time = get_seconds(); - lprocfs_counter_add(pl->pl_stats, LDLM_POOL_TIMING_STAT, - recalc_interval_sec); spin_unlock(&pl->pl_lock); /* * Do not cancel locks in case lru resize is disabled for this ns. */ - if (!ns_connect_lru_resize(ldlm_pl2ns(pl))) - return 0; + if (!ns_connect_lru_resize(ldlm_pl2ns(pl))) { + ret = 0; + goto out; + } /* * In the time of canceling locks on client we do not need to maintain @@ -507,7 +507,19 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) * It may be called when SLV has changed much, this is why we do not * take into account pl->pl_recalc_time here. */ - return ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC, LDLM_CANCEL_LRUR); + ret = ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC, LDLM_CANCEL_LRUR); + +out: + spin_lock(&pl->pl_lock); + /* + * Time of LRU resizing might be longer than period, + * so update after LRU resizing rather than before it. + */ + pl->pl_recalc_time = get_seconds(); + lprocfs_counter_add(pl->pl_stats, LDLM_POOL_TIMING_STAT, + recalc_interval_sec); + spin_unlock(&pl->pl_lock); + return ret; } /** @@ -591,6 +603,14 @@ int ldlm_pool_recalc(struct ldlm_pool *pl) } recalc_interval_sec = pl->pl_recalc_time - get_seconds() + pl->pl_recalc_period; + if (recalc_interval_sec <= 0) { + /* Prevent too frequent recalculation. */ + CDEBUG(D_DLMTRACE, "Negative interval(%ld), " + "too short period(%ld)", + recalc_interval_sec, + pl->pl_recalc_period); + recalc_interval_sec = 1; + } return recalc_interval_sec; } @@ -697,8 +717,8 @@ LPROC_SEQ_FOPS_RO(lprocfs_grant_plan); LDLM_POOL_PROC_READER_SEQ_SHOW(recalc_period, int); LDLM_POOL_PROC_WRITER(recalc_period, int); static ssize_t lprocfs_recalc_period_seq_write(struct file *file, - const char *buf, size_t len, - loff_t *off) + const char __user *buf, + size_t len, loff_t *off) { struct seq_file *seq = file->private_data; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 1f150e46f50..c6f62a91b23 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -72,7 +72,7 @@ extern unsigned int ldlm_cancel_unused_locks_before_replay; unsigned int ldlm_dump_granted_max = 256; #if defined(CONFIG_PROC_FS) -static ssize_t lprocfs_wr_dump_ns(struct file *file, const char *buffer, +static ssize_t lprocfs_wr_dump_ns(struct file *file, const char __user *buffer, size_t count, loff_t *off) { ldlm_dump_all_namespaces(LDLM_NAMESPACE_SERVER, D_DLMTRACE); @@ -287,8 +287,9 @@ static int lprocfs_elc_seq_show(struct seq_file *m, void *v) return lprocfs_rd_uint(m, &supp); } -static ssize_t lprocfs_elc_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lprocfs_elc_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct ldlm_namespace *ns = ((struct seq_file *)file->private_data)->private; unsigned int supp = -1; diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c index a7a7ac626aa..76c62e87a41 100644 --- a/drivers/staging/lustre/lustre/libcfs/debug.c +++ b/drivers/staging/lustre/lustre/libcfs/debug.c @@ -57,7 +57,7 @@ module_param(libcfs_debug, int, 0644); MODULE_PARM_DESC(libcfs_debug, "Lustre kernel debug mask"); EXPORT_SYMBOL(libcfs_debug); -unsigned int libcfs_debug_mb = 0; +static unsigned int libcfs_debug_mb; module_param(libcfs_debug_mb, uint, 0644); MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size."); EXPORT_SYMBOL(libcfs_debug_mb); @@ -93,7 +93,7 @@ EXPORT_SYMBOL(libcfs_debug_binary); unsigned int libcfs_stack = 3 * THREAD_SIZE / 4; EXPORT_SYMBOL(libcfs_stack); -unsigned int portal_enter_debugger; +static unsigned int portal_enter_debugger; EXPORT_SYMBOL(portal_enter_debugger); unsigned int libcfs_catastrophe; @@ -115,7 +115,7 @@ static wait_queue_head_t debug_ctlwq; char libcfs_debug_file_path_arr[PATH_MAX] = LIBCFS_DEBUG_FILE_PATH_DEFAULT; /* We need to pass a pointer here, but elsewhere this must be a const */ -char *libcfs_debug_file_path; +static char *libcfs_debug_file_path; module_param(libcfs_debug_file_path, charp, 0644); MODULE_PARM_DESC(libcfs_debug_file_path, "Path for dumping debug logs, set 'NONE' to prevent log dumping"); @@ -124,7 +124,7 @@ int libcfs_panic_in_progress; /* libcfs_debug_token2mask() expects the returned * string in lower-case */ -const char * +static const char * libcfs_debug_subsys2str(int subsys) { switch (1 << subsys) { @@ -185,7 +185,7 @@ libcfs_debug_subsys2str(int subsys) /* libcfs_debug_token2mask() expects the returned * string in lower-case */ -const char * +static const char * libcfs_debug_dbg2str(int debug) { switch (1 << debug) { @@ -350,7 +350,7 @@ void libcfs_debug_dumplog_internal(void *arg) current->journal_info = journal_info; } -int libcfs_debug_dumplog_thread(void *arg) +static int libcfs_debug_dumplog_thread(void *arg) { libcfs_debug_dumplog_internal(arg); wake_up(&debug_ctlwq); diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c index 2d1e6729e99..ec3a2a8b8b2 100644 --- a/drivers/staging/lustre/lustre/libcfs/hash.c +++ b/drivers/staging/lustre/lustre/libcfs/hash.c @@ -126,18 +126,21 @@ cfs_hash_nl_unlock(union cfs_hash_lock *lock, int exclusive) {} static inline void cfs_hash_spin_lock(union cfs_hash_lock *lock, int exclusive) + __acquires(&lock->spin) { spin_lock(&lock->spin); } static inline void cfs_hash_spin_unlock(union cfs_hash_lock *lock, int exclusive) + __releases(&lock->spin) { spin_unlock(&lock->spin); } static inline void cfs_hash_rw_lock(union cfs_hash_lock *lock, int exclusive) + __acquires(&lock->rw) { if (!exclusive) read_lock(&lock->rw); @@ -147,6 +150,7 @@ cfs_hash_rw_lock(union cfs_hash_lock *lock, int exclusive) static inline void cfs_hash_rw_unlock(union cfs_hash_lock *lock, int exclusive) + __releases(&lock->rw) { if (!exclusive) read_unlock(&lock->rw); @@ -1580,7 +1584,7 @@ cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, stop_on_change = cfs_hash_with_rehash_key(hs) || !cfs_hash_with_no_itemref(hs) || - CFS_HOP(hs, put_locked) == NULL; + hs->hs_ops->hs_put_locked == NULL; cfs_hash_lock(hs, 0); LASSERT(!cfs_hash_is_rehashing(hs)); @@ -1635,9 +1639,9 @@ cfs_hash_for_each_nolock(struct cfs_hash *hs, !cfs_hash_with_no_itemref(hs)) return -EOPNOTSUPP; - if (CFS_HOP(hs, get) == NULL || - (CFS_HOP(hs, put) == NULL && - CFS_HOP(hs, put_locked) == NULL)) + if (hs->hs_ops->hs_get == NULL || + (hs->hs_ops->hs_put == NULL && + hs->hs_ops->hs_put_locked == NULL)) return -EOPNOTSUPP; cfs_hash_for_each_enter(hs); @@ -1667,9 +1671,9 @@ cfs_hash_for_each_empty(struct cfs_hash *hs, if (cfs_hash_with_no_lock(hs)) return -EOPNOTSUPP; - if (CFS_HOP(hs, get) == NULL || - (CFS_HOP(hs, put) == NULL && - CFS_HOP(hs, put_locked) == NULL)) + if (hs->hs_ops->hs_get == NULL || + (hs->hs_ops->hs_put == NULL && + hs->hs_ops->hs_put_locked == NULL)) return -EOPNOTSUPP; cfs_hash_for_each_enter(hs); diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c index e2aa637abcf..d9b7c6b69db 100644 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c @@ -228,12 +228,12 @@ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, if (kkuc_groups[group].next == NULL) return 0; - down_read(&kg_sem); + down_write(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp != NULL) rc = cb_func(reg->kr_data, cb_arg); } - up_read(&kg_sem); + up_write(&kg_sem); return rc; } diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c index fb88733607a..76d4392bd28 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c @@ -47,7 +47,7 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), int *oldmask, int minmask, int allmask) { const char *debugstr; - char op = 0; + char op = '\0'; int newmask = minmask, i, len, found = 0; /* <str> must be a list of tokens separated by whitespace @@ -55,10 +55,10 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), * appears first in <str>, '*oldmask' is used as the starting point * (relative), otherwise minmask is used (absolute). An operator * applies to all following tokens up to the next operator. */ - while (*str != 0) { + while (*str != '\0') { while (isspace(*str)) str++; - if (*str == 0) + if (*str == '\0') break; if (*str == '+' || *str == '-') { op = *str++; @@ -67,13 +67,15 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), newmask = *oldmask; while (isspace(*str)) str++; - if (*str == 0) /* trailing op */ + if (*str == '\0') /* trailing op */ return -EINVAL; } /* find token length */ - for (len = 0; str[len] != 0 && !isspace(str[len]) && - str[len] != '+' && str[len] != '-'; len++); + len = 0; + while (str[len] != '\0' && !isspace(str[len]) && + str[len] != '+' && str[len] != '-') + len++; /* match token */ found = 0; @@ -132,7 +134,7 @@ char *cfs_firststr(char *str, size_t size) ++end; } - *end= '\0'; + *end = '\0'; out: return str; } diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c index d71ad5ed1f6..277f6b890e0 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c @@ -82,17 +82,12 @@ int cfs_cap_raised(cfs_cap_t cap) return cap_raised(current_cap(), cap); } -void cfs_kernel_cap_pack(kernel_cap_t kcap, cfs_cap_t *cap) +static void cfs_kernel_cap_pack(kernel_cap_t kcap, cfs_cap_t *cap) { /* XXX lost high byte */ *cap = kcap.cap[0]; } -void cfs_kernel_cap_unpack(kernel_cap_t *kcap, cfs_cap_t cap) -{ - kcap->cap[0] = cap; -} - cfs_cap_t cfs_curproc_cap_pack(void) { cfs_cap_t cap; diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c index 83d3f08a37b..c539e374158 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c @@ -232,8 +232,9 @@ static int proc_debug_mb(struct ctl_table *table, int write, __proc_debug_mb); } -int proc_console_max_delay_cs(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int proc_console_max_delay_cs(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) { int rc, max_delay_cs; struct ctl_table dummy = *table; @@ -264,8 +265,9 @@ int proc_console_max_delay_cs(struct ctl_table *table, int write, return rc; } -int proc_console_min_delay_cs(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int proc_console_min_delay_cs(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) { int rc, min_delay_cs; struct ctl_table dummy = *table; @@ -296,8 +298,8 @@ int proc_console_min_delay_cs(struct ctl_table *table, int write, return rc; } -int proc_console_backoff(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int proc_console_backoff(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) { int rc, backoff; struct ctl_table dummy = *table; @@ -324,16 +326,18 @@ int proc_console_backoff(struct ctl_table *table, int write, return rc; } -int libcfs_force_lbug(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int libcfs_force_lbug(struct ctl_table *table, int write, + void __user *buffer, + size_t *lenp, loff_t *ppos) { if (write) LBUG(); return 0; } -int proc_fail_loc(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int proc_fail_loc(struct ctl_table *table, int write, + void __user *buffer, + size_t *lenp, loff_t *ppos) { int rc; long old_fail_loc = cfs_fail_loc; diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c index b91a1f95bbd..cd2fc01dea4 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c @@ -43,7 +43,7 @@ /* For sys_open & sys_close */ #include <linux/syscalls.h> -int +static int libcfs_sock_ioctl(int cmd, unsigned long arg) { mm_segment_t oldmm = get_fs(); diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c index 976c61ed49f..c8e293002e0 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c @@ -151,6 +151,7 @@ cfs_trace_buf_type_t cfs_trace_buf_idx_get(void) * for details. */ int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking) + __acquires(&tcd->tc_lock) { __LASSERT(tcd->tcd_type < CFS_TCD_TYPE_MAX); if (tcd->tcd_type == CFS_TCD_TYPE_IRQ) @@ -165,6 +166,7 @@ int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking) } void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking) + __releases(&tcd->tcd_lock) { __LASSERT(tcd->tcd_type < CFS_TCD_TYPE_MAX); if (tcd->tcd_type == CFS_TCD_TYPE_IRQ) @@ -269,5 +271,5 @@ int cfs_trace_max_debug_mb(void) { int total_mb = (totalram_pages >> (20 - PAGE_SHIFT)); - return MAX(512, (total_mb * 80)/100); + return max(512, (total_mb * 80)/100); } diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index 2c4fc74505b..7dc77dd402b 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -42,8 +42,7 @@ #include "../../include/linux/lnet/lnet.h" #include "tracefile.h" -void -kportal_memhog_free (struct libcfs_device_userstate *ldu) +static void kportal_memhog_free (struct libcfs_device_userstate *ldu) { struct page **level0p = &ldu->ldu_memhog_root_page; struct page **level1p; @@ -86,8 +85,7 @@ kportal_memhog_free (struct libcfs_device_userstate *ldu) LASSERT (ldu->ldu_memhog_pages == 0); } -int -kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages, +static int kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages, gfp_t flags) { struct page **level0p; @@ -334,8 +332,6 @@ extern struct mutex cfs_trace_thread_mutex; extern struct cfs_wi_sched *cfs_sched_rehash; extern void libcfs_init_nidstrings(void); -extern int libcfs_arch_init(void); -extern void libcfs_arch_cleanup(void); static int init_libcfs_module(void) { diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c index 47c239f22ba..087449f4e6c 100644 --- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c +++ b/drivers/staging/lustre/lustre/libcfs/nidstrings.c @@ -81,14 +81,105 @@ libcfs_next_nidstring(void) return str; } -static int libcfs_lo_str2addr(const char *str, int nob, __u32 *addr); -static void libcfs_ip_addr2str(__u32 addr, char *str); -static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr); -static void libcfs_decnum_addr2str(__u32 addr, char *str); -static void libcfs_hexnum_addr2str(__u32 addr, char *str); -static int libcfs_num_str2addr(const char *str, int nob, __u32 *addr); -static int libcfs_num_parse(char *str, int len, struct list_head *list); -static int libcfs_num_match(__u32 addr, struct list_head *list); +static int libcfs_lo_str2addr(const char *str, int nob, __u32 *addr) +{ + *addr = 0; + return 1; +} + +static void libcfs_ip_addr2str(__u32 addr, char *str) +{ + snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u", + (addr >> 24) & 0xff, (addr >> 16) & 0xff, + (addr >> 8) & 0xff, addr & 0xff); +} + +static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) +{ + unsigned int a; + unsigned int b; + unsigned int c; + unsigned int d; + int n = nob; /* XscanfX */ + + /* numeric IP? */ + if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 && + n == nob && + (a & ~0xff) == 0 && (b & ~0xff) == 0 && + (c & ~0xff) == 0 && (d & ~0xff) == 0) { + *addr = ((a<<24)|(b<<16)|(c<<8)|d); + return 1; + } + + return 0; +} + +static void libcfs_decnum_addr2str(__u32 addr, char *str) +{ + snprintf(str, LNET_NIDSTR_SIZE, "%u", addr); +} + +static void libcfs_hexnum_addr2str(__u32 addr, char *str) +{ + snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr); +} + +static int libcfs_num_str2addr(const char *str, int nob, __u32 *addr) +{ + int n; + + n = nob; + if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob) + return 1; + + n = nob; + if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob) + return 1; + + n = nob; + if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob) + return 1; + + return 0; +} + +/** + * Nf_parse_addrlist method for networks using numeric addresses. + * + * Examples of such networks are gm and elan. + * + * \retval 0 if \a str parsed to numeric address + * \retval errno otherwise + */ +static int +libcfs_num_parse(char *str, int len, struct list_head *list) +{ + struct cfs_expr_list *el; + int rc; + + rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el); + if (rc == 0) + list_add_tail(&el->el_link, list); + + return rc; +} + +/* + * Nf_match_addr method for networks using numeric addresses + * + * \retval 1 on match + * \retval 0 otherwise + */ +static int +libcfs_num_match(__u32 addr, struct list_head *numaddr) +{ + struct cfs_expr_list *el; + + LASSERT(!list_empty(numaddr)); + el = list_entry(numaddr->next, struct cfs_expr_list, el_link); + + return cfs_expr_list_match(addr, el); +} struct netstrfns { int nf_type; @@ -197,24 +288,7 @@ static struct netstrfns libcfs_netstrfns[] = { {/* .nf_type */ -1}, }; -const int libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns); - -int -libcfs_lo_str2addr(const char *str, int nob, __u32 *addr) -{ - *addr = 0; - return 1; -} - -void -libcfs_ip_addr2str(__u32 addr, char *str) -{ -#if 0 /* never lookup */ -#endif - snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u", - (addr >> 24) & 0xff, (addr >> 16) & 0xff, - (addr >> 8) & 0xff, addr & 0xff); -} +static const int libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns); /* CAVEAT EMPTOR XscanfX * I use "%n" at the end of a sscanf format to detect trailing junk. However @@ -223,60 +297,7 @@ libcfs_ip_addr2str(__u32 addr, char *str) * fine, if it doesn't, then the scan ended at the end of the string, which is * fine too :) */ -int -libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) -{ - unsigned int a; - unsigned int b; - unsigned int c; - unsigned int d; - int n = nob; /* XscanfX */ - - /* numeric IP? */ - if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 && - n == nob && - (a & ~0xff) == 0 && (b & ~0xff) == 0 && - (c & ~0xff) == 0 && (d & ~0xff) == 0) { - *addr = ((a<<24)|(b<<16)|(c<<8)|d); - return 1; - } - - return 0; -} - -void -libcfs_decnum_addr2str(__u32 addr, char *str) -{ - snprintf(str, LNET_NIDSTR_SIZE, "%u", addr); -} - -void -libcfs_hexnum_addr2str(__u32 addr, char *str) -{ - snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr); -} - -int -libcfs_num_str2addr(const char *str, int nob, __u32 *addr) -{ - int n; - - n = nob; - if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob) - return 1; - - n = nob; - if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob) - return 1; - - n = nob; - if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob) - return 1; - - return 0; -} - -struct netstrfns * +static struct netstrfns * libcfs_lnd2netstrfns(int lnd) { int i; @@ -289,7 +310,7 @@ libcfs_lnd2netstrfns(int lnd) return NULL; } -struct netstrfns * +static struct netstrfns * libcfs_namenum2netstrfns(const char *name) { struct netstrfns *nf; @@ -304,7 +325,7 @@ libcfs_namenum2netstrfns(const char *name) return NULL; } -struct netstrfns * +static struct netstrfns * libcfs_name2netstrfns(const char *name) { int i; @@ -343,7 +364,7 @@ libcfs_lnd2str(int lnd) return nf->nf_name; str = libcfs_next_nidstring(); - snprintf(str, LNET_NIDSTR_SIZE, "?%u?", lnd); + snprintf(str, LNET_NIDSTR_SIZE, "?%d?", lnd); return str; } EXPORT_SYMBOL(libcfs_lnd2str); @@ -369,11 +390,11 @@ libcfs_net2str(__u32 net) char *str = libcfs_next_nidstring(); if (nf == NULL) - snprintf(str, LNET_NIDSTR_SIZE, "<%u:%u>", lnd, num); + snprintf(str, LNET_NIDSTR_SIZE, "<%d:%d>", lnd, num); else if (num == 0) snprintf(str, LNET_NIDSTR_SIZE, "%s", nf->nf_name); else - snprintf(str, LNET_NIDSTR_SIZE, "%s%u", nf->nf_name, num); + snprintf(str, LNET_NIDSTR_SIZE, "%s%d", nf->nf_name, num); return str; } @@ -397,7 +418,7 @@ libcfs_nid2str(lnet_nid_t nid) str = libcfs_next_nidstring(); if (nf == NULL) - snprintf(str, LNET_NIDSTR_SIZE, "%x@<%u:%u>", addr, lnd, nnum); + snprintf(str, LNET_NIDSTR_SIZE, "%x@<%d:%d>", addr, lnd, nnum); else { nf->nf_addr2str(addr, str); nob = strlen(str); @@ -405,7 +426,7 @@ libcfs_nid2str(lnet_nid_t nid) snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s", nf->nf_name); else - snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s%u", + snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s%d", nf->nf_name, nnum); } @@ -586,27 +607,6 @@ struct addrrange { }; /** - * Nf_parse_addrlist method for networks using numeric addresses. - * - * Examples of such networks are gm and elan. - * - * \retval 0 if \a str parsed to numeric address - * \retval errno otherwise - */ -static int -libcfs_num_parse(char *str, int len, struct list_head *list) -{ - struct cfs_expr_list *el; - int rc; - - rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el); - if (rc == 0) - list_add_tail(&el->el_link, list); - - return rc; -} - -/** * Parses \<addrrange\> token on the syntax. * * Allocates struct addrrange and links to \a nidrange via @@ -812,23 +812,6 @@ cfs_parse_nidlist(char *str, int len, struct list_head *nidlist) } EXPORT_SYMBOL(cfs_parse_nidlist); -/* - * Nf_match_addr method for networks using numeric addresses - * - * \retval 1 on match - * \retval 0 otherwise - */ -static int -libcfs_num_match(__u32 addr, struct list_head *numaddr) -{ - struct cfs_expr_list *el; - - LASSERT(!list_empty(numaddr)); - el = list_entry(numaddr->next, struct cfs_expr_list, el_link); - - return cfs_expr_list_match(addr, el); -} - /** * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist). * diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c index 5917c31c7ed..eb65b50f832 100644 --- a/drivers/staging/lustre/lustre/libcfs/tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c @@ -55,7 +55,7 @@ static struct tracefiled_ctl trace_tctl; struct mutex cfs_trace_thread_mutex; static int thread_running = 0; -atomic_t cfs_tage_allocated = ATOMIC_INIT(0); +static atomic_t cfs_tage_allocated = ATOMIC_INIT(0); static void put_pages_on_tcd_daemon_list(struct page_collection *pc, struct cfs_trace_cpu_data *tcd); @@ -1037,6 +1037,7 @@ static int tracefiled(void *arg) tage->used, rc); put_pages_back(&pc); __LASSERT(list_empty(&pc.pc_pages)); + break; } } MMSPACE_CLOSE; diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 1ac7a702ce2..a1820191327 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -183,7 +183,10 @@ static int ll_dir_filler(void *_hash, struct page *page0) op_data->op_offset = hash; rc = md_readpage(exp, op_data, page_pool, &request); ll_finish_md_op_data(op_data); - if (rc == 0) { + if (rc < 0) { + /* page0 is special, which was added into page cache early */ + delete_from_page_cache(page0); + } else if (rc == 0) { body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); /* Checked by mdc_readpage() */ LASSERT(body != NULL); @@ -278,7 +281,7 @@ static struct page *ll_dir_page_locate(struct inode *dir, __u64 *hash, spin_lock_irq(&mapping->tree_lock); found = radix_tree_gang_lookup(&mapping->page_tree, (void **)&page, offset, 1); - if (found > 0) { + if (found > 0 && !radix_tree_exceptional_entry(page)) { struct lu_dirpage *dp; page_cache_get(page); @@ -652,8 +655,8 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string) return rc; } -int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, - char *filename) +static int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, + char *filename) { struct ptlrpc_request *request = NULL; struct md_op_data *op_data; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 35a2df01528..7c7ef7ec908 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1553,6 +1553,11 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) struct ccc_grouplock grouplock; int rc; + if (arg == 0) { + CWARN("group id for group lock must not be 0\n"); + return -EINVAL; + } + if (ll_file_nolock(file)) return -EOPNOTSUPP; @@ -1587,7 +1592,8 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) return 0; } -int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg) +static int ll_put_grouplock(struct inode *inode, struct file *file, + unsigned long arg) { struct ll_inode_info *lli = ll_i2info(inode); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index e6a909e6faf..aaa13bd3e8d 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -399,9 +399,6 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, return -ERANGE; } - if (sbi->ll_dt_exp == NULL) - return -ENODEV; - spin_lock(&sbi->ll_lock); diff = pages_number - cache->ccc_lru_max; spin_unlock(&sbi->ll_lock); @@ -437,6 +434,11 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, if (diff <= 0) break; + if (sbi->ll_dt_exp == NULL) { /* being initialized */ + rc = -ENODEV; + break; + } + /* difficult - have to ask OSCs to drop LRU slots. */ tmp = diff << 1; rc = obd_set_info_async(NULL, sbi->ll_dt_exp, diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 6aff155651c..7c1e02a031b 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -72,21 +72,6 @@ static void ll_destroy_inode(struct inode *inode) call_rcu(&inode->i_rcu, ll_inode_destroy_callback); } -static int ll_init_inodecache(void) -{ - ll_inode_cachep = kmem_cache_create("lustre_inode_cache", - sizeof(struct ll_inode_info), - 0, SLAB_HWCACHE_ALIGN, NULL); - if (ll_inode_cachep == NULL) - return -ENOMEM; - return 0; -} - -static void ll_destroy_inodecache(void) -{ - kmem_cache_destroy(ll_inode_cachep); -} - /* exported operations */ struct super_operations lustre_super_operations = { .alloc_inode = ll_alloc_inode, @@ -104,9 +89,10 @@ void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg)); static int __init init_lustre_lite(void) { - int i, rc, seed[2]; - struct timeval tv; + struct proc_dir_entry *entry; lnet_process_id_t lnet_id; + struct timeval tv; + int i, rc, seed[2]; CLASSERT(sizeof(LUSTRE_VOLATILE_HDR) == LUSTRE_VOLATILE_HDR_LEN + 1); @@ -116,59 +102,52 @@ static int __init init_lustre_lite(void) CDEBUG(D_INFO, "Lustre client module (%p).\n", &lustre_super_operations); - rc = ll_init_inodecache(); - if (rc) - return -ENOMEM; + rc = -ENOMEM; + ll_inode_cachep = kmem_cache_create("lustre_inode_cache", + sizeof(struct ll_inode_info), + 0, SLAB_HWCACHE_ALIGN, NULL); + if (ll_inode_cachep == NULL) + goto out_cache; + ll_file_data_slab = kmem_cache_create("ll_file_data", sizeof(struct ll_file_data), 0, SLAB_HWCACHE_ALIGN, NULL); - if (ll_file_data_slab == NULL) { - ll_destroy_inodecache(); - return -ENOMEM; - } + if (ll_file_data_slab == NULL) + goto out_cache; ll_remote_perm_cachep = kmem_cache_create("ll_remote_perm_cache", sizeof(struct ll_remote_perm), 0, 0, NULL); - if (ll_remote_perm_cachep == NULL) { - kmem_cache_destroy(ll_file_data_slab); - ll_file_data_slab = NULL; - ll_destroy_inodecache(); - return -ENOMEM; - } + if (ll_remote_perm_cachep == NULL) + goto out_cache; ll_rmtperm_hash_cachep = kmem_cache_create("ll_rmtperm_hash_cache", REMOTE_PERM_HASHSIZE * sizeof(struct list_head), 0, 0, NULL); - if (ll_rmtperm_hash_cachep == NULL) { - kmem_cache_destroy(ll_remote_perm_cachep); - ll_remote_perm_cachep = NULL; - kmem_cache_destroy(ll_file_data_slab); - ll_file_data_slab = NULL; - ll_destroy_inodecache(); - return -ENOMEM; + if (ll_rmtperm_hash_cachep == NULL) + goto out_cache; + + entry = lprocfs_register("llite", proc_lustre_root, NULL, NULL); + if (IS_ERR(entry)) { + rc = PTR_ERR(entry); + CERROR("cannot register '/proc/fs/lustre/llite': rc = %d\n", + rc); + goto out_cache; } - proc_lustre_fs_root = proc_lustre_root ? - lprocfs_register("llite", proc_lustre_root, NULL, NULL) : NULL; - - lustre_register_client_fill_super(ll_fill_super); - lustre_register_kill_super_cb(ll_kill_super); - - lustre_register_client_process_config(ll_process_config); + proc_lustre_fs_root = entry; cfs_get_random_bytes(seed, sizeof(seed)); - /* Nodes with small feet have little entropy - * the NID for this node gives the most entropy in the low bits */ - for (i = 0; ; i++) { - if (LNetGetId(i, &lnet_id) == -ENOENT) { + /* Nodes with small feet have little entropy. The NID for this + * node gives the most entropy in the low bits */ + for (i = 0;; i++) { + if (LNetGetId(i, &lnet_id) == -ENOENT) break; - } - if (LNET_NETTYP(LNET_NIDNET(lnet_id.nid)) != LOLND) { + + if (LNET_NETTYP(LNET_NIDNET(lnet_id.nid)) != LOLND) seed[0] ^= LNET_NIDADDR(lnet_id.nid); - } } do_gettimeofday(&tv); @@ -177,20 +156,54 @@ static int __init init_lustre_lite(void) init_timer(&ll_capa_timer); ll_capa_timer.function = ll_capa_timer_callback; rc = ll_capa_thread_start(); - /* - * XXX normal cleanup is needed here. - */ - if (rc == 0) - rc = vvp_global_init(); + if (rc != 0) + goto out_proc; - if (rc == 0) - rc = ll_xattr_init(); + rc = vvp_global_init(); + if (rc != 0) + goto out_capa; + + rc = ll_xattr_init(); + if (rc != 0) + goto out_vvp; + + lustre_register_client_fill_super(ll_fill_super); + lustre_register_kill_super_cb(ll_kill_super); + lustre_register_client_process_config(ll_process_config); + + return 0; + +out_vvp: + vvp_global_fini(); +out_capa: + del_timer(&ll_capa_timer); + ll_capa_thread_stop(); +out_proc: + lprocfs_remove(&proc_lustre_fs_root); +out_cache: + if (ll_inode_cachep != NULL) + kmem_cache_destroy(ll_inode_cachep); + + if (ll_file_data_slab != NULL) + kmem_cache_destroy(ll_file_data_slab); + + if (ll_remote_perm_cachep != NULL) + kmem_cache_destroy(ll_remote_perm_cachep); + + if (ll_rmtperm_hash_cachep != NULL) + kmem_cache_destroy(ll_rmtperm_hash_cachep); return rc; } static void __exit exit_lustre_lite(void) { + lustre_register_client_fill_super(NULL); + lustre_register_kill_super_cb(NULL); + lustre_register_client_process_config(NULL); + + lprocfs_remove(&proc_lustre_fs_root); + ll_xattr_fini(); vvp_global_fini(); del_timer(&ll_capa_timer); @@ -199,22 +212,12 @@ static void __exit exit_lustre_lite(void) "client remaining capa count %d\n", capa_count[CAPA_SITE_CLIENT]); - lustre_register_client_fill_super(NULL); - lustre_register_kill_super_cb(NULL); - - lustre_register_client_process_config(NULL); - - ll_destroy_inodecache(); - + kmem_cache_destroy(ll_inode_cachep); kmem_cache_destroy(ll_rmtperm_hash_cachep); - ll_rmtperm_hash_cachep = NULL; kmem_cache_destroy(ll_remote_perm_cachep); - ll_remote_perm_cachep = NULL; kmem_cache_destroy(ll_file_data_slab); - if (proc_lustre_fs_root && !IS_ERR(proc_lustre_fs_root)) - lprocfs_remove(&proc_lustre_fs_root); } MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 65d610abe06..91bba79678c 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -307,18 +307,13 @@ static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io, static int vvp_io_read_lock(const struct lu_env *env, const struct cl_io_slice *ios) { - struct cl_io *io = ios->cis_io; - struct ll_inode_info *lli = ll_i2info(ccc_object_inode(io->ci_obj)); + struct cl_io *io = ios->cis_io; + struct cl_io_rw_common *rd = &io->u.ci_rd.rd; int result; - /* XXX: Layer violation, we shouldn't see lsm at llite level. */ - if (lli->lli_has_smd) /* lsm-less file doesn't need to lock */ - result = vvp_io_rw_lock(env, io, CLM_READ, - io->u.ci_rd.rd.crw_pos, - io->u.ci_rd.rd.crw_pos + - io->u.ci_rd.rd.crw_count - 1); - else - result = 0; + result = vvp_io_rw_lock(env, io, CLM_READ, rd->crw_pos, + rd->crw_pos + rd->crw_count - 1); + return result; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_lock.c b/drivers/staging/lustre/lustre/llite/vvp_lock.c index 372633e164b..f354e82d4ae 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_lock.c +++ b/drivers/staging/lustre/lustre/llite/vvp_lock.c @@ -71,6 +71,7 @@ static const struct cl_lock_operations vvp_lock_ops = { .clo_fini = ccc_lock_fini, .clo_enqueue = ccc_lock_enqueue, .clo_wait = ccc_lock_wait, + .clo_use = ccc_lock_use, .clo_unuse = ccc_lock_unuse, .clo_fits_into = ccc_lock_fits_into, .clo_state = ccc_lock_state, diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 9f3837412cd..b779f47384c 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -128,7 +128,7 @@ static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid, return rc; } -struct obd_uuid *lmv_get_uuid(struct obd_export *exp) +static struct obd_uuid *lmv_get_uuid(struct obd_export *exp) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; @@ -335,7 +335,7 @@ static int lmv_init_ea_size(struct obd_export *exp, int easize, #define MAX_STRING_SIZE 128 -int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) +static int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) { struct proc_dir_entry *lmv_proc_dir; struct lmv_obd *lmv = &obd->u.lmv; @@ -1663,10 +1663,10 @@ struct lmv_tgt_desc return tgt; } -int lmv_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, - __u32 gid, cfs_cap_t cap_effective, __u64 rdev, - struct ptlrpc_request **request) +static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, + const void *data, int datalen, int mode, __u32 uid, + __u32 gid, cfs_cap_t cap_effective, __u64 rdev, + struct ptlrpc_request **request) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2387,9 +2387,9 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, return -EINVAL; } -int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, - u32 keylen, void *key, u32 vallen, - void *val, struct ptlrpc_request_set *set) +static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, + u32 keylen, void *key, u32 vallen, + void *val, struct ptlrpc_request_set *set) { struct lmv_tgt_desc *tgt; struct obd_device *obd; @@ -2425,8 +2425,8 @@ int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, return -EINVAL; } -int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) +static int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, + struct lov_stripe_md *lsm) { struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; @@ -2473,8 +2473,8 @@ int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, return mea_size; } -int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmm, int lmm_size) +static int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, + struct lov_mds_md *lmm, int lmm_size) { struct obd_device *obd = class_exp2obd(exp); struct lmv_stripe_md **tmea = (struct lmv_stripe_md **)lsmp; @@ -2551,8 +2551,8 @@ static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, return rc; } -int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, - __u64 *bits) +static int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, + __u64 *bits) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; int rc; @@ -2561,10 +2561,10 @@ int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, return rc; } -ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags, - const struct lu_fid *fid, ldlm_type_t type, - ldlm_policy_data_t *policy, ldlm_mode_t mode, - struct lustre_handle *lockh) +static ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags, + const struct lu_fid *fid, ldlm_type_t type, + ldlm_policy_data_t *policy, ldlm_mode_t mode, + struct lustre_handle *lockh) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2594,16 +2594,18 @@ ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags, return 0; } -int lmv_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req, - struct obd_export *dt_exp, struct obd_export *md_exp, - struct lustre_md *md) +static int lmv_get_lustre_md(struct obd_export *exp, + struct ptlrpc_request *req, + struct obd_export *dt_exp, + struct obd_export *md_exp, + struct lustre_md *md) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; return md_get_lustre_md(lmv->tgts[0]->ltd_exp, req, dt_exp, md_exp, md); } -int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) +static int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2613,9 +2615,9 @@ int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) return md_free_lustre_md(lmv->tgts[0]->ltd_exp, md); } -int lmv_set_open_replay_data(struct obd_export *exp, - struct obd_client_handle *och, - struct lookup_intent *it) +static int lmv_set_open_replay_data(struct obd_export *exp, + struct obd_client_handle *och, + struct lookup_intent *it) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2628,8 +2630,8 @@ int lmv_set_open_replay_data(struct obd_export *exp, return md_set_open_replay_data(tgt->ltd_exp, och, it); } -int lmv_clear_open_replay_data(struct obd_export *exp, - struct obd_client_handle *och) +static int lmv_clear_open_replay_data(struct obd_export *exp, + struct obd_client_handle *och) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2684,17 +2686,18 @@ static int lmv_renew_capa(struct obd_export *exp, struct obd_capa *oc, return rc; } -int lmv_unpack_capa(struct obd_export *exp, struct ptlrpc_request *req, - const struct req_msg_field *field, struct obd_capa **oc) +static int lmv_unpack_capa(struct obd_export *exp, struct ptlrpc_request *req, + const struct req_msg_field *field, + struct obd_capa **oc) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; return md_unpack_capa(lmv->tgts[0]->ltd_exp, req, field, oc); } -int lmv_intent_getattr_async(struct obd_export *exp, - struct md_enqueue_info *minfo, - struct ldlm_enqueue_info *einfo) +static int lmv_intent_getattr_async(struct obd_export *exp, + struct md_enqueue_info *minfo, + struct ldlm_enqueue_info *einfo) { struct md_op_data *op_data = &minfo->mi_data; struct obd_device *obd = exp->exp_obd; @@ -2714,8 +2717,8 @@ int lmv_intent_getattr_async(struct obd_export *exp, return rc; } -int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, - struct lu_fid *fid, __u64 *bits) +static int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, + struct lu_fid *fid, __u64 *bits) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2739,8 +2742,8 @@ int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, * process with other slave MDTs. The only exception is Q_GETOQUOTA for which * we directly fetch data from the slave MDTs. */ -int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, - struct obd_quotactl *oqctl) +static int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, + struct obd_quotactl *oqctl) { struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; @@ -2786,8 +2789,8 @@ int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, return rc; } -int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, - struct obd_quotactl *oqctl) +static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, + struct obd_quotactl *oqctl) { struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; @@ -2810,7 +2813,7 @@ int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, return rc; } -struct obd_ops lmv_obd_ops = { +static struct obd_ops lmv_obd_ops = { .o_owner = THIS_MODULE, .o_setup = lmv_setup, .o_cleanup = lmv_cleanup, @@ -2830,7 +2833,7 @@ struct obd_ops lmv_obd_ops = { .o_quotactl = lmv_quotactl }; -struct md_ops lmv_md_ops = { +static struct md_ops lmv_md_ops = { .m_getstatus = lmv_getstatus, .m_null_inode = lmv_null_inode, .m_find_cbdata = lmv_find_cbdata, @@ -2864,7 +2867,7 @@ struct md_ops lmv_md_ops = { .m_revalidate_lock = lmv_revalidate_lock }; -int __init lmv_init(void) +static int __init lmv_init(void) { struct lprocfs_static_vars lvars; int rc; diff --git a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c index 117002097b2..5be4176829d 100644 --- a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c +++ b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c @@ -175,7 +175,7 @@ static int lmv_tgt_seq_show(struct seq_file *p, void *v) tgt->ltd_uuid.uuid, tgt->ltd_active ? "" : "IN"); } -struct seq_operations lmv_tgt_sops = { +static struct seq_operations lmv_tgt_sops = { .start = lmv_tgt_seq_start, .stop = lmv_tgt_seq_stop, .next = lmv_tgt_seq_next, @@ -199,7 +199,7 @@ static int lmv_target_seq_open(struct inode *inode, struct file *file) LPROC_SEQ_FOPS_RO_TYPE(lmv, uuid); -struct lprocfs_vars lprocfs_lmv_obd_vars[] = { +static struct lprocfs_vars lprocfs_lmv_obd_vars[] = { { "numobd", &lmv_numobd_fops, NULL, 0 }, { "placement", &lmv_placement_fops, NULL, 0 }, { "activeobd", &lmv_activeobd_fops, NULL, 0 }, diff --git a/drivers/staging/lustre/lustre/lov/lproc_lov.c b/drivers/staging/lustre/lustre/lov/lproc_lov.c index c993f25fb30..c99f2f44ec6 100644 --- a/drivers/staging/lustre/lustre/lov/lproc_lov.c +++ b/drivers/staging/lustre/lustre/lov/lproc_lov.c @@ -51,8 +51,9 @@ static int lov_stripesize_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%llu\n", desc->ld_default_stripe_size); } -static ssize_t lov_stripesize_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lov_stripesize_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct lov_desc *desc; @@ -81,8 +82,9 @@ static int lov_stripeoffset_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%llu\n", desc->ld_default_stripe_offset); } -static ssize_t lov_stripeoffset_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lov_stripeoffset_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct lov_desc *desc; @@ -110,8 +112,9 @@ static int lov_stripetype_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%u\n", desc->ld_pattern); } -static ssize_t lov_stripetype_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lov_stripetype_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct lov_desc *desc; @@ -140,8 +143,9 @@ static int lov_stripecount_seq_show(struct seq_file *m, void *v) (__s16)(desc->ld_default_stripe_count + 1) - 1); } -static ssize_t lov_stripecount_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lov_stripecount_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct lov_desc *desc; diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index 16341c81835..c791941bd81 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -52,7 +52,7 @@ static int mdc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v) } static ssize_t mdc_max_rpcs_in_flight_seq_write(struct file *file, - const char *buffer, + const char __user *buffer, size_t count, loff_t *off) { @@ -82,8 +82,9 @@ static int mdc_kuc_open(struct inode *inode, struct file *file) } /* temporary for testing */ -static ssize_t mdc_kuc_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t mdc_kuc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; @@ -105,6 +106,8 @@ static ssize_t mdc_kuc_write(struct file *file, const char *buffer, /* for mockup below */ 2 * cfs_size_round(sizeof(*hai)); OBD_ALLOC(lh, len); + if (!lh) + return -ENOMEM; lh->kuc_magic = KUC_MAGIC; lh->kuc_transport = KUC_TRANSPORT_HSM; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 4e59995e004..d3234cb1ea2 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -222,10 +222,9 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_fsuid = from_kuid(&init_user_ns, current_fsuid()); rec->cr_fsgid = from_kgid(&init_user_ns, current_fsgid()); rec->cr_cap = cfs_curproc_cap_pack(); - if (op_data != NULL) { - rec->cr_fid1 = op_data->op_fid1; - rec->cr_fid2 = op_data->op_fid2; - } + rec->cr_fid1 = op_data->op_fid1; + rec->cr_fid2 = op_data->op_fid2; + rec->cr_mode = mode; cr_flags = mds_pack_open_flags(flags, mode); rec->cr_rdev = rdev; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 8c9b4f5494e..d1c224ecd2b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -828,6 +828,7 @@ resend: einfo->ei_type); policy = (ldlm_policy_data_t *)lmm; res_id.name[3] = LDLM_FLOCK; + req = NULL; } else if (it->it_op & IT_OPEN) { req = mdc_intent_open_pack(exp, it, op_data, lmm, lmmsize, einfo->ei_cbdata); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 3b0f245a878..ef2744700d8 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -855,8 +855,8 @@ static void mdc_close_handle_reply(struct ptlrpc_request *req, } } -int mdc_close(struct obd_export *exp, struct md_op_data *op_data, - struct md_open_data *mod, struct ptlrpc_request **request) +static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, + struct md_open_data *mod, struct ptlrpc_request **request) { struct obd_device *obd = class_exp2obd(exp); struct ptlrpc_request *req; @@ -974,8 +974,8 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data, return rc < 0 ? rc : saved_rc; } -int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, - struct md_open_data *mod) +static int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, + struct md_open_data *mod) { struct obd_device *obd = class_exp2obd(exp); struct ptlrpc_request *req; @@ -1044,8 +1044,8 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, } -int mdc_readpage(struct obd_export *exp, struct md_op_data *op_data, - struct page **pages, struct ptlrpc_request **request) +static int mdc_readpage(struct obd_export *exp, struct md_op_data *op_data, + struct page **pages, struct ptlrpc_request **request) { struct ptlrpc_request *req; struct ptlrpc_bulk_desc *desc; @@ -1908,8 +1908,8 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, /* copy UUID */ if (copy_to_user(data->ioc_pbuf2, obd2cli_tgt(obd), - min((int) data->ioc_plen2, - (int) sizeof(struct obd_uuid)))) { + min_t(size_t, data->ioc_plen2, + sizeof(struct obd_uuid)))) { rc = -EFAULT; goto out; } @@ -1921,8 +1921,8 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, goto out; if (copy_to_user(data->ioc_pbuf1, &stat_buf, - min((int) data->ioc_plen1, - (int) sizeof(stat_buf)))) { + min_t(size_t, data->ioc_plen1, + sizeof(stat_buf)))) { rc = -EFAULT; goto out; } @@ -1974,9 +1974,9 @@ out: return rc; } -int mdc_get_info_rpc(struct obd_export *exp, - u32 keylen, void *key, - int vallen, void *val) +static int mdc_get_info_rpc(struct obd_export *exp, + u32 keylen, void *key, + int vallen, void *val) { struct obd_import *imp = class_exp2cliimp(exp); struct ptlrpc_request *req; @@ -2148,11 +2148,11 @@ static int mdc_kuc_reregister(struct obd_import *imp) (void *)imp); } -int mdc_set_info_async(const struct lu_env *env, - struct obd_export *exp, - u32 keylen, void *key, - u32 vallen, void *val, - struct ptlrpc_request_set *set) +static int mdc_set_info_async(const struct lu_env *env, + struct obd_export *exp, + u32 keylen, void *key, + u32 vallen, void *val, + struct ptlrpc_request_set *set) { struct obd_import *imp = class_exp2cliimp(exp); int rc; @@ -2199,9 +2199,9 @@ int mdc_set_info_async(const struct lu_env *env, return -EINVAL; } -int mdc_get_info(const struct lu_env *env, struct obd_export *exp, - __u32 keylen, void *key, __u32 *vallen, void *val, - struct lov_stripe_md *lsm) +static int mdc_get_info(const struct lu_env *env, struct obd_export *exp, + __u32 keylen, void *key, __u32 *vallen, void *val, + struct lov_stripe_md *lsm) { int rc = -EINVAL; @@ -2263,8 +2263,8 @@ int mdc_get_info(const struct lu_env *env, struct obd_export *exp, return rc; } -int mdc_sync(struct obd_export *exp, const struct lu_fid *fid, - struct obd_capa *oc, struct ptlrpc_request **request) +static int mdc_sync(struct obd_export *exp, const struct lu_fid *fid, + struct obd_capa *oc, struct ptlrpc_request **request) { struct ptlrpc_request *req; int rc; @@ -2356,7 +2356,7 @@ int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, return seq_client_alloc_fid(NULL, seq, fid); } -struct obd_uuid *mdc_get_uuid(struct obd_export *exp) +static struct obd_uuid *mdc_get_uuid(struct obd_export *exp) { struct client_obd *cli = &exp->exp_obd->u.cli; @@ -2390,7 +2390,7 @@ static int mdc_resource_inode_free(struct ldlm_resource *res) return 0; } -struct ldlm_valblock_ops inode_lvbo = { +static struct ldlm_valblock_ops inode_lvbo = { .lvbo_free = mdc_resource_inode_free, }; @@ -2550,9 +2550,9 @@ static int mdc_process_config(struct obd_device *obd, u32 len, void *buf) /* get remote permission for current user on fid */ -int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid, - struct obd_capa *oc, __u32 suppgid, - struct ptlrpc_request **request) +static int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid, + struct obd_capa *oc, __u32 suppgid, + struct ptlrpc_request **request) { struct ptlrpc_request *req; int rc; @@ -2647,7 +2647,7 @@ static int mdc_renew_capa(struct obd_export *exp, struct obd_capa *oc, return 0; } -struct obd_ops mdc_obd_ops = { +static struct obd_ops mdc_obd_ops = { .o_owner = THIS_MODULE, .o_setup = mdc_setup, .o_precleanup = mdc_precleanup, @@ -2670,7 +2670,7 @@ struct obd_ops mdc_obd_ops = { .o_quotacheck = mdc_quotacheck }; -struct md_ops mdc_md_ops = { +static struct md_ops mdc_md_ops = { .m_getstatus = mdc_getstatus, .m_null_inode = mdc_null_inode, .m_find_cbdata = mdc_find_cbdata, @@ -2705,7 +2705,7 @@ struct md_ops mdc_md_ops = { .m_revalidate_lock = mdc_revalidate_lock }; -int __init mdc_init(void) +static int __init mdc_init(void) { int rc; struct lprocfs_static_vars lvars = { NULL }; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index ce96bd27911..f13d1fbffd9 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -193,6 +193,7 @@ static spinlock_t *cl_object_attr_guard(struct cl_object *o) * cl_object_attr_get(), cl_object_attr_set(). */ void cl_object_attr_lock(struct cl_object *o) + __acquires(cl_object_attr_guard(o)) { spin_lock(cl_object_attr_guard(o)); } @@ -202,6 +203,7 @@ EXPORT_SYMBOL(cl_object_attr_lock); * Releases data-attributes lock, acquired by cl_object_attr_lock(). */ void cl_object_attr_unlock(struct cl_object *o) + __releases(cl_object_attr_guard(o)) { spin_unlock(cl_object_attr_guard(o)); } @@ -662,7 +664,8 @@ static int cl_env_store_init(void) { return cl_env_hash != NULL ? 0 :-ENOMEM; } -static void cl_env_store_fini(void) { +static void cl_env_store_fini(void) +{ cfs_hash_putref(cl_env_hash); } diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 89a3fb2e56b..29456e1ad22 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -61,7 +61,7 @@ __u64 obd_alloc; EXPORT_SYMBOL(obd_alloc); __u64 obd_pages; EXPORT_SYMBOL(obd_pages); -DEFINE_SPINLOCK(obd_updatemax_lock); +static DEFINE_SPINLOCK(obd_updatemax_lock); /* The following are visible and mutable through /proc/sys/lustre/. */ unsigned int obd_alloc_fail_rate = 0; diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index 736ca410aca..82508210465 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -1151,22 +1151,24 @@ void class_export_recovery_cleanup(struct obd_export *exp) exp->exp_obd->obd_stale_clients++; } spin_unlock(&obd->obd_recovery_task_lock); + + spin_lock(&exp->exp_lock); /** Cleanup req replay fields */ if (exp->exp_req_replay_needed) { - spin_lock(&exp->exp_lock); exp->exp_req_replay_needed = 0; - spin_unlock(&exp->exp_lock); + LASSERT(atomic_read(&obd->obd_req_replay_clients)); atomic_dec(&obd->obd_req_replay_clients); } + /** Cleanup lock replay data */ if (exp->exp_lock_replay_needed) { - spin_lock(&exp->exp_lock); exp->exp_lock_replay_needed = 0; - spin_unlock(&exp->exp_lock); + LASSERT(atomic_read(&obd->obd_lock_replay_clients)); atomic_dec(&obd->obd_lock_replay_clients); } + spin_unlock(&exp->exp_lock); } /* This function removes 1-3 references from the export: diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 66ceab20c74..b94aeac18a3 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -83,9 +83,8 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) int err; int offset = 0; - err = copy_from_user(&hdr, (void *)arg, sizeof(hdr)); - if (err) - return err; + if (copy_from_user(&hdr, (void *)arg, sizeof(hdr))) + return -EFAULT; if (hdr.ioc_version != OBD_IOCTL_VERSION) { CERROR("Version mismatch kernel (%x) vs application (%x)\n", @@ -117,18 +116,19 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) *len = hdr.ioc_len; data = (struct obd_ioctl_data *)*buf; - err = copy_from_user(*buf, (void *)arg, hdr.ioc_len); - if (err) { - OBD_FREE_LARGE(*buf, hdr.ioc_len); - return err; + if (copy_from_user(*buf, (void *)arg, hdr.ioc_len)) { + err = -EFAULT; + goto free_buf; + } + if (hdr.ioc_len != data->ioc_len) { + err = -EINVAL; + goto free_buf; } - if (hdr.ioc_len != data->ioc_len) - return -EINVAL; if (obd_ioctl_is_invalid(data)) { CERROR("ioctl not correctly formatted\n"); - OBD_FREE_LARGE(*buf, hdr.ioc_len); - return -EINVAL; + err = -EINVAL; + goto free_buf; } if (data->ioc_inllen1) { @@ -151,6 +151,10 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) } return 0; + +free_buf: + OBD_FREE_LARGE(*buf, hdr.ioc_len); + return err; } EXPORT_SYMBOL(obd_ioctl_getdata); @@ -272,8 +276,9 @@ static int obd_proc_jobid_var_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%s\n", obd_jobid_var); } -static ssize_t obd_proc_jobid_var_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t obd_proc_jobid_var_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { if (!count || count > JOBSTATS_JOBID_VAR_MAX_LEN) return -EINVAL; diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index d3ec90e85eb..a2d5aa105d6 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -168,7 +168,8 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) } case CHANGELOG_REC: { - struct llog_changelog_rec *cr = (struct llog_changelog_rec *)rec; + struct llog_changelog_rec *cr = + (struct llog_changelog_rec *)rec; __swab16s(&cr->cr.cr_namelen); __swab16s(&cr->cr.cr_flags); @@ -188,6 +189,8 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) } else { tail = &cr->cr_tail; } + tail = (struct llog_rec_tail *)((char *)tail + + cr->cr.cr_namelen); break; } case CHANGELOG_USER_REC: diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 3b7dfc36772..ddab94d7ee8 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -45,6 +45,7 @@ #include "../include/lprocfs_status.h" #include "../include/lustre/lustre_idl.h" #include <linux/seq_file.h> +#include <linux/ctype.h> static const char * const obd_connect_names[] = { "read_only", @@ -1849,7 +1850,7 @@ int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult) } EXPORT_SYMBOL(lprocfs_seq_read_frac_helper); -int lprocfs_write_u64_helper(const char *buffer, unsigned long count, +int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count, __u64 *val) { return lprocfs_write_frac_u64_helper(buffer, count, val, 1); @@ -1862,6 +1863,7 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, char kernbuf[22], *end, *pbuf; __u64 whole, frac = 0, units; unsigned frac_d = 1; + int sign = 1; if (count > (sizeof(kernbuf) - 1)) return -EINVAL; @@ -1872,7 +1874,7 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, kernbuf[count] = '\0'; pbuf = kernbuf; if (*pbuf == '-') { - mult = -mult; + sign = -1; pbuf++; } @@ -1880,7 +1882,7 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, if (pbuf == end) return -EINVAL; - if (end != NULL && *end == '.') { + if (*end == '.') { int i; pbuf = end + 1; @@ -1895,25 +1897,25 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, } units = 1; - switch (*end) { - case 'p': case 'P': + switch (tolower(*end)) { + case 'p': units <<= 10; - case 't': case 'T': + case 't': units <<= 10; - case 'g': case 'G': + case 'g': units <<= 10; - case 'm': case 'M': + case 'm': units <<= 10; - case 'k': case 'K': + case 'k': units <<= 10; } /* Specified units override the multiplier */ - if (units) - mult = mult < 0 ? -units : units; + if (units > 1) + mult = units; frac *= mult; do_div(frac, frac_d); - *val = whole * mult + frac; + *val = sign * (whole * mult + frac); return 0; } EXPORT_SYMBOL(lprocfs_write_frac_u64_helper); diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 4f39cdee1b5..3c0c9109cef 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -376,6 +376,11 @@ int lustre_start_mgc(struct super_block *sb) /* Random uuid for MGC allows easier reconnects */ OBD_ALLOC_PTR(uuid); + if (!uuid) { + rc = -ENOMEM; + goto out_free; + } + ll_generate_random_uuid(uuidc); class_uuid_unparse(uuidc, uuid); diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 9f719bcecab..1795d3a7a02 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -53,8 +53,9 @@ static int osc_active_seq_show(struct seq_file *m, void *v) return rc; } -static ssize_t osc_active_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_active_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; int val, rc; @@ -88,7 +89,8 @@ static int osc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v) } static ssize_t osc_max_rpcs_in_flight_seq_write(struct file *file, - const char *buffer, size_t count, loff_t *off) + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; @@ -130,8 +132,9 @@ static int osc_max_dirty_mb_seq_show(struct seq_file *m, void *v) return lprocfs_seq_read_frac_helper(m, val, mult); } -static ssize_t osc_max_dirty_mb_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_max_dirty_mb_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; @@ -233,8 +236,9 @@ static int osc_cur_grant_bytes_seq_show(struct seq_file *m, void *v) return rc; } -static ssize_t osc_cur_grant_bytes_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_cur_grant_bytes_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &obd->u.cli; @@ -290,7 +294,8 @@ static int osc_grant_shrink_interval_seq_show(struct seq_file *m, void *v) } static ssize_t osc_grant_shrink_interval_seq_write(struct file *file, - const char *buffer, size_t count, loff_t *off) + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; int val, rc; @@ -322,8 +327,9 @@ static int osc_checksum_seq_show(struct seq_file *m, void *v) obd->u.cli.cl_checksum ? 1 : 0); } -static ssize_t osc_checksum_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_checksum_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; int val, rc; @@ -358,11 +364,12 @@ static int osc_checksum_type_seq_show(struct seq_file *m, void *v) else seq_printf(m, "%s ", cksum_name[i]); } - seq_printf(m, "\n"); + seq_putc(m, '\n'); return 0; } -static ssize_t osc_checksum_type_seq_write(struct file *file, const char *buffer, +static ssize_t osc_checksum_type_seq_write(struct file *file, + const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; @@ -401,8 +408,9 @@ static int osc_resend_count_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%u\n", atomic_read(&obd->u.cli.cl_resends)); } -static ssize_t osc_resend_count_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_resend_count_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; int val, rc; @@ -428,8 +436,9 @@ static int osc_contention_seconds_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%u\n", od->od_contention_time); } -static ssize_t osc_contention_seconds_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_contention_seconds_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct osc_device *od = obd2osc_dev(obd); @@ -447,8 +456,9 @@ static int osc_lockless_truncate_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%u\n", od->od_lockless_truncate); } -static ssize_t osc_lockless_truncate_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_lockless_truncate_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct osc_device *od = obd2osc_dev(obd); @@ -472,7 +482,8 @@ static int osc_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *v) } static ssize_t osc_obd_max_pages_per_rpc_seq_write(struct file *file, - const char *buffer, size_t count, loff_t *off) + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; @@ -590,9 +601,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "pending read pages: %d\n", atomic_read(&cli->cl_pending_r_pages)); - seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); - seq_printf(seq, "pages per rpc rpcs %% cum %% |"); - seq_printf(seq, " rpcs %% cum %%\n"); + seq_puts(seq, "\n\t\t\tread\t\t\twrite\n"); + seq_puts(seq, "pages per rpc rpcs % cum % |"); + seq_puts(seq, " rpcs % cum %\n"); read_tot = lprocfs_oh_sum(&cli->cl_read_page_hist); write_tot = lprocfs_oh_sum(&cli->cl_write_page_hist); @@ -613,9 +624,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) break; } - seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); - seq_printf(seq, "rpcs in flight rpcs %% cum %% |"); - seq_printf(seq, " rpcs %% cum %%\n"); + seq_puts(seq, "\n\t\t\tread\t\t\twrite\n"); + seq_puts(seq, "rpcs in flight rpcs % cum % |"); + seq_puts(seq, " rpcs % cum %\n"); read_tot = lprocfs_oh_sum(&cli->cl_read_rpc_hist); write_tot = lprocfs_oh_sum(&cli->cl_write_rpc_hist); @@ -636,9 +647,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) break; } - seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); - seq_printf(seq, "offset rpcs %% cum %% |"); - seq_printf(seq, " rpcs %% cum %%\n"); + seq_puts(seq, "\n\t\t\tread\t\t\twrite\n"); + seq_puts(seq, "offset rpcs % cum % |"); + seq_puts(seq, " rpcs % cum %\n"); read_tot = lprocfs_oh_sum(&cli->cl_read_offset_hist); write_tot = lprocfs_oh_sum(&cli->cl_write_offset_hist); @@ -664,8 +675,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) } #undef pct -static ssize_t osc_rpc_stats_seq_write(struct file *file, const char *buf, - size_t len, loff_t *off) +static ssize_t osc_rpc_stats_seq_write(struct file *file, + const char __user *buf, + size_t len, loff_t *off) { struct seq_file *seq = file->private_data; struct obd_device *dev = seq->private; @@ -702,8 +714,9 @@ static int osc_stats_seq_show(struct seq_file *seq, void *v) return 0; } -static ssize_t osc_stats_seq_write(struct file *file, const char *buf, - size_t len, loff_t *off) +static ssize_t osc_stats_seq_write(struct file *file, + const char __user *buf, + size_t len, loff_t *off) { struct seq_file *seq = file->private_data; struct obd_device *dev = seq->private; diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 370e6d4896c..7022ed42d2d 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1820,6 +1820,9 @@ static int try_to_add_extent_for_io(struct client_obd *cli, int *pc, unsigned int *max_pages) { struct osc_extent *tmp; + struct osc_async_page *oap = list_first_entry(&ext->oe_pages, + struct osc_async_page, + oap_pending_item); EASSERT((ext->oe_state == OES_CACHE || ext->oe_state == OES_LOCK_DONE), ext); @@ -1829,6 +1832,10 @@ static int try_to_add_extent_for_io(struct client_obd *cli, return 0; list_for_each_entry(tmp, rpclist, oe_link) { + struct osc_async_page *oap2; + + oap2 = list_first_entry(&tmp->oe_pages, struct osc_async_page, + oap_pending_item); EASSERT(tmp->oe_owner == current, tmp); #if 0 if (overlapped(tmp, ext)) { @@ -1836,6 +1843,11 @@ static int try_to_add_extent_for_io(struct client_obd *cli, EASSERT(0, ext); } #endif + if (oap2cl_page(oap)->cp_type != oap2cl_page(oap2)->cp_type) { + CDEBUG(D_CACHE, "Do not permit different type of IO" + " for a same RPC\n"); + return 0; + } if (tmp->oe_srvlock != ext->oe_srvlock || !tmp->oe_grants != !ext->oe_grants) diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index d788dac93cd..af96c7bc776 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -160,11 +160,6 @@ static inline unsigned long rpcs_in_flight(struct client_obd *cli) return cli->cl_r_in_flight + cli->cl_w_in_flight; } -#ifndef min_t -#define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) -#endif - struct osc_device { struct cl_device od_cl; struct obd_export *od_exp; diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index a7f08bc4816..44565572490 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -100,14 +100,14 @@ static int osc_lock_invariant(struct osc_lock *ols) /* * If all the following "ergo"s are true, return 1, otherwise 0 */ - if (! ergo(olock != NULL, handle_used)) + if (!ergo(olock != NULL, handle_used)) return 0; - if (! ergo(olock != NULL, + if (!ergo(olock != NULL, olock->l_handle.h_cookie == ols->ols_handle.cookie)) return 0; - if (! ergo(handle_used, + if (!ergo(handle_used, ergo(lock != NULL && olock != NULL, lock == olock) && ergo(lock == NULL, olock == NULL))) return 0; @@ -115,18 +115,18 @@ static int osc_lock_invariant(struct osc_lock *ols) * Check that ->ols_handle and ->ols_lock are consistent, but * take into account that they are set at the different time. */ - if (! ergo(ols->ols_state == OLS_CANCELLED, + if (!ergo(ols->ols_state == OLS_CANCELLED, olock == NULL && !handle_used)) return 0; /* * DLM lock is destroyed only after we have seen cancellation * ast. */ - if (! ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, + if (!ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, ((olock->l_flags & LDLM_FL_DESTROYED) == 0))) return 0; - if (! ergo(ols->ols_state == OLS_GRANTED, + if (!ergo(ols->ols_state == OLS_GRANTED, olock != NULL && olock->l_req_mode == olock->l_granted_mode && ols->ols_hold)) diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index b9450b95f1c..0adfa707a76 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -3332,7 +3332,7 @@ extern struct lu_kmem_descr osc_caches[]; extern spinlock_t osc_ast_guard; extern struct lock_class_key osc_ast_guard_class; -int __init osc_init(void) +static int __init osc_init(void) { struct lprocfs_static_vars lvars = { NULL }; int rc; diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index dc9e406f321..4882dd0a448 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1247,7 +1247,9 @@ static int after_reply(struct ptlrpc_request *req) time_t now = get_seconds(); DEBUG_REQ(D_RPCTRACE, req, "Resending request on EINPROGRESS"); + spin_lock(&req->rq_lock); req->rq_resend = 1; + spin_unlock(&req->rq_lock); req->rq_nr_resend++; /* allocate new xid to avoid reply reconstruction */ @@ -1497,11 +1499,13 @@ static inline int ptlrpc_set_producer(struct ptlrpc_request_set *set) int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) { struct list_head *tmp, *next; + struct list_head comp_reqs; int force_timer_recalc = 0; if (atomic_read(&set->set_remaining) == 0) return 1; + INIT_LIST_HEAD(&comp_reqs); list_for_each_safe(tmp, next, &set->set_requests) { struct ptlrpc_request *req = list_entry(tmp, struct ptlrpc_request, @@ -1576,8 +1580,10 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) ptlrpc_rqphase_move(req, req->rq_next_phase); } - if (req->rq_phase == RQ_PHASE_COMPLETE) + if (req->rq_phase == RQ_PHASE_COMPLETE) { + list_move_tail(&req->rq_set_chain, &comp_reqs); continue; + } if (req->rq_phase == RQ_PHASE_INTERPRET) goto interpret; @@ -1860,9 +1866,15 @@ interpret: if (req->rq_status != 0) set->set_rc = req->rq_status; ptlrpc_req_finished(req); + } else { + list_move_tail(&req->rq_set_chain, &comp_reqs); } } + /* move completed request at the head of list so it's easier for + * caller to find them */ + list_splice(&comp_reqs, &set->set_requests); + /* If we hit an error, we want to recover promptly. */ return atomic_read(&set->set_remaining) == 0 || force_timer_recalc; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index dc5ceb55d00..bbef666b1d1 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -65,7 +65,6 @@ #endif /* struct ptlrpc_request, lustre_msg* */ #include "../include/lustre_req_layout.h" -#include "../include/lustre_update.h" #include "../include/lustre_acl.h" #include "../include/lustre_debug.h" diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 4011e0050fc..0e2071b8a36 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -45,7 +45,7 @@ #include "ptlrpc_internal.h" -struct ll_rpc_opcode { +static struct ll_rpc_opcode { __u32 opcode; const char *opname; } ll_rpc_opcode_table[LUSTRE_MAX_OPCODES] = { @@ -136,7 +136,7 @@ struct ll_rpc_opcode { { UPDATE_OBJ, "update_obj" }, }; -struct ll_eopcode { +static struct ll_eopcode { __u32 opcode; const char *opname; } ll_eopcode_table[EXTRA_LAST_OPC] = { @@ -175,15 +175,17 @@ const char *ll_opcode2str(__u32 opcode) return ll_rpc_opcode_table[offset].opname; } -const char *ll_eopcode2str(__u32 opcode) +static const char *ll_eopcode2str(__u32 opcode) { LASSERT(ll_eopcode_table[opcode].opcode == opcode); return ll_eopcode_table[opcode].opname; } + #if defined (CONFIG_PROC_FS) -void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir, - char *name, struct proc_dir_entry **procroot_ret, - struct lprocfs_stats **stats_ret) +static void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir, + char *name, + struct proc_dir_entry **procroot_ret, + struct lprocfs_stats **stats_ret) { struct proc_dir_entry *svc_procroot; struct lprocfs_stats *svc_stats; @@ -284,8 +286,9 @@ ptlrpc_lprocfs_req_history_max_seq_show(struct seq_file *m, void *n) } static ssize_t -ptlrpc_lprocfs_req_history_max_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +ptlrpc_lprocfs_req_history_max_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; int bufpages; @@ -329,8 +332,9 @@ ptlrpc_lprocfs_threads_min_seq_show(struct seq_file *m, void *n) } static ssize_t -ptlrpc_lprocfs_threads_min_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +ptlrpc_lprocfs_threads_min_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; int val; @@ -381,8 +385,9 @@ ptlrpc_lprocfs_threads_max_seq_show(struct seq_file *m, void *n) } static ssize_t -ptlrpc_lprocfs_threads_max_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +ptlrpc_lprocfs_threads_max_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; int val; @@ -723,7 +728,7 @@ struct ptlrpc_srh_iterator { struct ptlrpc_request *srhi_req; }; -int +static int ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part *svcpt, struct ptlrpc_srh_iterator *srhi, __u64 seq) @@ -1025,7 +1030,7 @@ static int ptlrpc_lprocfs_hp_ratio_seq_show(struct seq_file *m, void *v) } static ssize_t ptlrpc_lprocfs_hp_ratio_seq_write(struct file *file, - const char *buffer, + const char __user *buffer, size_t count, loff_t *off) { @@ -1175,7 +1180,7 @@ EXPORT_SYMBOL(ptlrpc_lprocfs_unregister_obd); #define BUFLEN (UUID_MAX + 5) -int lprocfs_wr_evict_client(struct file *file, const char *buffer, +int lprocfs_wr_evict_client(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; @@ -1223,7 +1228,7 @@ EXPORT_SYMBOL(lprocfs_wr_evict_client); #undef BUFLEN -int lprocfs_wr_ping(struct file *file, const char *buffer, +int lprocfs_wr_ping(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; @@ -1251,7 +1256,7 @@ EXPORT_SYMBOL(lprocfs_wr_ping); * The connection UUID is a node's primary NID. For example, * "echo connection=192.168.0.1@tcp0::instance > .../import". */ -int lprocfs_wr_import(struct file *file, const char *buffer, +int lprocfs_wr_import(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; @@ -1329,7 +1334,7 @@ int lprocfs_rd_pinger_recov(struct seq_file *m, void *n) } EXPORT_SYMBOL(lprocfs_rd_pinger_recov); -int lprocfs_wr_pinger_recov(struct file *file, const char *buffer, +int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index cbcc541cac4..4621b71fe0b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -306,21 +306,16 @@ static int ptlrpcd_check(struct lu_env *env, struct ptlrpcd_ctl *pc) if (atomic_read(&set->set_remaining)) rc |= ptlrpc_check_set(env, set); - if (!list_empty(&set->set_requests)) { - /* - * XXX: our set never completes, so we prune the completed - * reqs after each iteration. boy could this be smarter. - */ - list_for_each_safe(pos, tmp, &set->set_requests) { - req = list_entry(pos, struct ptlrpc_request, - rq_set_chain); - if (req->rq_phase != RQ_PHASE_COMPLETE) - continue; + /* NB: ptlrpc_check_set has already moved completed request at the + * head of seq::set_requests */ + list_for_each_safe(pos, tmp, &set->set_requests) { + req = list_entry(pos, struct ptlrpc_request, rq_set_chain); + if (req->rq_phase != RQ_PHASE_COMPLETE) + break; - list_del_init(&req->rq_set_chain); - req->rq_set = NULL; - ptlrpc_req_finished(req); - } + list_del_init(&req->rq_set_chain); + req->rq_set = NULL; + ptlrpc_req_finished(req); } if (rc == 0) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c index c500aff6619..81de68edb04 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c @@ -47,6 +47,8 @@ #include "../include/lustre_net.h" #include "../include/lustre_sec.h" +#include "ptlrpc_internal.h" + #define SEC_GC_INTERVAL (30 * 60) diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c index 704fa202ee1..a425f71dfb9 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c @@ -901,7 +901,7 @@ static int ipipe_set_gbce_params(struct vpfe_ipipe_device *ipipe, void *param) struct device *dev = ipipe->subdev.v4l2_dev->dev; if (!gbce_param) { - memset(gbce, 0 , sizeof(struct vpfe_ipipe_gbce)); + memset(gbce, 0, sizeof(struct vpfe_ipipe_gbce)); } else { memcpy(gbce, gbce_param, sizeof(struct vpfe_ipipe_gbce)); if (ipipe_validate_gbce_params(gbce) < 0) { @@ -1086,7 +1086,7 @@ static int ipipe_set_car_params(struct vpfe_ipipe_device *ipipe, void *param) struct vpfe_ipipe_car *car = &ipipe->config.car; if (!car_param) { - memset(car , 0, sizeof(struct vpfe_ipipe_car)); + memset(car, 0, sizeof(struct vpfe_ipipe_car)); } else { memcpy(car, car_param, sizeof(struct vpfe_ipipe_car)); if (ipipe_validate_car_params(car) < 0) { diff --git a/drivers/staging/mt29f_spinand/Kconfig b/drivers/staging/mt29f_spinand/Kconfig index 403174817be..f3f9cb3b5c3 100644 --- a/drivers/staging/mt29f_spinand/Kconfig +++ b/drivers/staging/mt29f_spinand/Kconfig @@ -12,5 +12,5 @@ config MTD_SPINAND_ONDIEECC bool "Use SPINAND internal ECC" depends on MTD_SPINAND_MT29F help - Internel ECC. + Internal ECC. Enables Hardware ECC support for Micron SPI NAND. diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 3628bcb840c..3b191fce45e 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -626,7 +626,8 @@ static int spinand_write_page_hwecc(struct mtd_info *mtd, static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - u8 retval, status; + int retval; + u8 status; uint8_t *p = buf; int eccsize = chip->ecc.size; int eccsteps = chip->ecc.steps; @@ -640,6 +641,13 @@ static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, while (1) { retval = spinand_read_status(info->spi, &status); + if (retval < 0) { + dev_err(&mtd->dev, + "error %d reading status register\n", + retval); + return retval; + } + if ((status & STATUS_OIP_MASK) == STATUS_READY) { if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) { pr_info("spinand: ECC error\n"); @@ -685,6 +693,13 @@ static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip) while (time_before(jiffies, timeo)) { retval = spinand_read_status(info->spi, &status); + if (retval < 0) { + dev_err(&mtd->dev, + "error %d reading status register\n", + retval); + return retval; + } + if ((status & STATUS_OIP_MASK) == STATUS_READY) return 0; diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index 5ecb3e6a5bb..e8aae09d162 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -788,7 +788,7 @@ void xlr_set_gmac_speed(struct xlr_net_priv *priv) xlr_nae_wreg(priv->base_addr, R_MAC_CONFIG_2, 0x7117); priv->phy_speed = speed; } - /* Set SGMII speed in Interface controll reg */ + /* Set SGMII speed in Interface control reg */ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { if (speed == SPEED_10) xlr_nae_wreg(priv->base_addr, diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 120b70d72d7..5868ebb8389 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -256,7 +256,7 @@ static void nvec_gpio_set_value(struct nvec_chip *nvec, int value) * and return immediately. * * Returns: 0 on success, a negative error code on failure. If a failure - * occured, the nvec driver may print an error. + * occurred, the nvec driver may print an error. */ int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data, short size) diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 6b8b108c4e6..1daeb3125a1 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -2687,7 +2687,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) /* * Read the channel config info so we can figure out how much data - * transfered + * transferred */ usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index fcbe836aa99..22667dbb10d 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -109,6 +109,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) int interface = cvmx_helper_get_interface_num(work->ipprt); int index = cvmx_helper_get_interface_index_num(work->ipprt); union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; + gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); if (gmxx_rxx_frm_ctl.s.pre_chk == 0) { @@ -214,6 +215,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) did_work_request = 0; if (work == NULL) { union cvmx_pow_wq_int wq_int; + wq_int.u64 = 0; wq_int.s.iq_dis = 1 << pow_receive_group; wq_int.s.wq_int = 1 << pow_receive_group; diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index ee321496dcd..460e8545904 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -798,7 +798,7 @@ static int cvm_oct_probe(struct platform_device *pdev) cvm_oct_rx_initialize(); /* - * 150 uS: about 10 1500-byte packtes at 1GE. + * 150 uS: about 10 1500-byte packets at 1GE. */ cvm_oct_tx_poll_interval = 150 * (octeon_get_clock_rate() / 1000000); diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c index 6a9a8815477..bc7e664cc8a 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/drivers/staging/olpc_dcon/olpc_dcon.c @@ -780,7 +780,7 @@ static const struct i2c_device_id dcon_idtable[] = { }; MODULE_DEVICE_TABLE(i2c, dcon_idtable); -struct i2c_driver dcon_driver = { +static struct i2c_driver dcon_driver = { .driver = { .name = "olpc_dcon", .pm = &dcon_pm_ops, diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c index 77e8eb5a5ab..0c5a10c6940 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c +++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c @@ -52,7 +52,7 @@ static int dcon_init_xo_1(struct dcon_priv *dcon) * Determine the current state by reading the GPIO bit; earlier * stages of the boot process have established the state. * - * Note that we read GPIO_OUPUT_VAL rather than GPIO_READ_BACK here; + * Note that we read GPIO_OUTPUT_VAL rather than GPIO_READ_BACK here; * this is because OFW will disable input for the pin and set a value.. * READ_BACK will only contain a valid value if input is enabled and * then a value is set. So, future readings of the pin can use diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 98325b7b446..6ed35b6ecf0 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -130,6 +130,30 @@ #define LCD_FLAG_N 0x0040 /* 2-rows mode */ #define LCD_FLAG_L 0x0080 /* backlight enabled */ +/* LCD commands */ +#define LCD_CMD_DISPLAY_CLEAR 0x01 /* Clear entire display */ + +#define LCD_CMD_ENTRY_MODE 0x04 /* Set entry mode */ +#define LCD_CMD_CURSOR_INC 0x02 /* Increment cursor */ + +#define LCD_CMD_DISPLAY_CTRL 0x08 /* Display control */ +#define LCD_CMD_DISPLAY_ON 0x04 /* Set display on */ +#define LCD_CMD_CURSOR_ON 0x02 /* Set cursor on */ +#define LCD_CMD_BLINK_ON 0x01 /* Set blink on */ + +#define LCD_CMD_SHIFT 0x10 /* Shift cursor/display */ +#define LCD_CMD_DISPLAY_SHIFT 0x08 /* Shift display instead of cursor */ +#define LCD_CMD_SHIFT_RIGHT 0x04 /* Shift display/cursor to the right */ + +#define LCD_CMD_FUNCTION_SET 0x20 /* Set function */ +#define LCD_CMD_DATA_LEN_8BITS 0x10 /* Set data length to 8 bits */ +#define LCD_CMD_TWO_LINES 0x08 /* Set to two display lines */ +#define LCD_CMD_FONT_5X10_DOTS 0x04 /* Set char font to 5x10 dots */ + +#define LCD_CMD_SET_CGRAM_ADDR 0x40 /* Set char generator RAM address */ + +#define LCD_CMD_SET_DDRAM_ADDR 0x80 /* Set display data RAM address */ + #define LCD_ESCAPE_LEN 24 /* max chars for LCD escape command */ #define LCD_ESCAPE_CHAR 27 /* use char 27 for escape command */ @@ -228,9 +252,6 @@ static struct { bool initialized; bool must_clear; - /* TODO: use bool here? */ - char left_shift; - int height; int width; int bwidth; @@ -759,7 +780,7 @@ static void long_sleep(int ms) if (in_interrupt()) { mdelay(ms); } else { - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((ms * HZ + 999) / 1000); } } @@ -886,7 +907,7 @@ static void lcd_write_data_tilcd(int data) static void lcd_gotoxy(void) { - lcd_write_cmd(0x80 /* set DDRAM address */ + lcd_write_cmd(LCD_CMD_SET_DDRAM_ADDR | (lcd.addr.y ? lcd.hwidth : 0) /* we force the cursor to stay at the end of the line if it wants to go farther */ @@ -994,7 +1015,7 @@ static void lcd_clear_fast_tilcd(void) /* clears the display and resets X/Y */ static void lcd_clear_display(void) { - lcd_write_cmd(0x01); /* clear display */ + lcd_write_cmd(LCD_CMD_DISPLAY_CLEAR); lcd.addr.x = 0; lcd.addr.y = 0; /* we must wait a few milliseconds (15) */ @@ -1008,26 +1029,29 @@ static void lcd_init_display(void) long_sleep(20); /* wait 20 ms after power-up for the paranoid */ - lcd_write_cmd(0x30); /* 8bits, 1 line, small fonts */ + /* 8bits, 1 line, small fonts; let's do it 3 times */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); long_sleep(10); - lcd_write_cmd(0x30); /* 8bits, 1 line, small fonts */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); long_sleep(10); - lcd_write_cmd(0x30); /* 8bits, 1 line, small fonts */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); long_sleep(10); - lcd_write_cmd(0x30 /* set font height and lines number */ - | ((lcd.flags & LCD_FLAG_F) ? 4 : 0) - | ((lcd.flags & LCD_FLAG_N) ? 8 : 0) + /* set font height and lines number */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS + | ((lcd.flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) + | ((lcd.flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0) ); long_sleep(10); - lcd_write_cmd(0x08); /* display off, cursor off, blink off */ + /* display off, cursor off, blink off */ + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL); long_sleep(10); - lcd_write_cmd(0x08 /* set display mode */ - | ((lcd.flags & LCD_FLAG_D) ? 4 : 0) - | ((lcd.flags & LCD_FLAG_C) ? 2 : 0) - | ((lcd.flags & LCD_FLAG_B) ? 1 : 0) + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL /* set display mode */ + | ((lcd.flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) + | ((lcd.flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) + | ((lcd.flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0) ); lcd_backlight((lcd.flags & LCD_FLAG_L) ? 1 : 0); @@ -1035,7 +1059,7 @@ static void lcd_init_display(void) long_sleep(10); /* entry mode set : increment, cursor shifting */ - lcd_write_cmd(0x06); + lcd_write_cmd(LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC); lcd_clear_display(); } @@ -1119,7 +1143,7 @@ static inline int handle_lcd_special_code(void) if (lcd.addr.x > 0) { /* back one char if not at end of line */ if (lcd.addr.x < lcd.bwidth) - lcd_write_cmd(0x10); + lcd_write_cmd(LCD_CMD_SHIFT); lcd.addr.x--; } processed = 1; @@ -1127,21 +1151,20 @@ static inline int handle_lcd_special_code(void) case 'r': /* shift cursor right */ if (lcd.addr.x < lcd.width) { /* allow the cursor to pass the end of the line */ - if (lcd.addr.x < - (lcd.bwidth - 1)) - lcd_write_cmd(0x14); + if (lcd.addr.x < (lcd.bwidth - 1)) + lcd_write_cmd(LCD_CMD_SHIFT | + LCD_CMD_SHIFT_RIGHT); lcd.addr.x++; } processed = 1; break; case 'L': /* shift display left */ - lcd.left_shift++; - lcd_write_cmd(0x18); + lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT); processed = 1; break; case 'R': /* shift display right */ - lcd.left_shift--; - lcd_write_cmd(0x1C); + lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT | + LCD_CMD_SHIFT_RIGHT); processed = 1; break; case 'k': { /* kill end of line */ @@ -1157,7 +1180,6 @@ static inline int handle_lcd_special_code(void) } case 'I': /* reinitialize display */ lcd_init_display(); - lcd.left_shift = 0; processed = 1; break; case 'G': { @@ -1211,7 +1233,7 @@ static inline int handle_lcd_special_code(void) esc++; } - lcd_write_cmd(0x40 | (cgaddr * 8)); + lcd_write_cmd(LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8)); for (addr = 0; addr < cgoffset; addr++) lcd_write_data(cgbytes[addr]); @@ -1244,21 +1266,29 @@ static inline int handle_lcd_special_code(void) break; } + /* TODO: This indent party here got ugly, clean it! */ /* Check whether one flag was changed */ if (oldflags != lcd.flags) { /* check whether one of B,C,D flags were changed */ if ((oldflags ^ lcd.flags) & (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D)) /* set display mode */ - lcd_write_cmd(0x08 - | ((lcd.flags & LCD_FLAG_D) ? 4 : 0) - | ((lcd.flags & LCD_FLAG_C) ? 2 : 0) - | ((lcd.flags & LCD_FLAG_B) ? 1 : 0)); + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL + | ((lcd.flags & LCD_FLAG_D) + ? LCD_CMD_DISPLAY_ON : 0) + | ((lcd.flags & LCD_FLAG_C) + ? LCD_CMD_CURSOR_ON : 0) + | ((lcd.flags & LCD_FLAG_B) + ? LCD_CMD_BLINK_ON : 0)); /* check whether one of F,N flags was changed */ else if ((oldflags ^ lcd.flags) & (LCD_FLAG_F | LCD_FLAG_N)) - lcd_write_cmd(0x30 - | ((lcd.flags & LCD_FLAG_F) ? 4 : 0) - | ((lcd.flags & LCD_FLAG_N) ? 8 : 0)); + lcd_write_cmd(LCD_CMD_FUNCTION_SET + | LCD_CMD_DATA_LEN_8BITS + | ((lcd.flags & LCD_FLAG_F) + ? LCD_CMD_TWO_LINES : 0) + | ((lcd.flags & LCD_FLAG_N) + ? LCD_CMD_FONT_5X10_DOTS + : 0)); /* check whether L flag was changed */ else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) { if (lcd.flags & (LCD_FLAG_L)) @@ -1297,13 +1327,13 @@ static void lcd_write_char(char c) end of the line */ if (lcd.addr.x < lcd.bwidth) /* back one char */ - lcd_write_cmd(0x10); + lcd_write_cmd(LCD_CMD_SHIFT); lcd.addr.x--; } /* replace with a space */ lcd_write_data(' '); /* back one char again */ - lcd_write_cmd(0x10); + lcd_write_cmd(LCD_CMD_SHIFT); break; case '\014': /* quickly clear the display */ diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index d61842ed673..da19145c49c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -509,7 +509,7 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) tx_ra_bitmap |= ((raid<<28)&0xf0000000); DBG_88E("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = 0x%x\n", - __func__ , psta->mac_id, raid , tx_ra_bitmap, arg); + __func__, psta->mac_id, raid, tx_ra_bitmap, arg); /* bitmap[0:27] = tx_rate_bitmap */ /* bitmap[28:31]= Rate Adaptive id */ diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index e4b7ee4c99d..cd12dd70dd8 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -484,17 +484,8 @@ void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame) /* fall through */ case WIFI_ASSOCREQ: case WIFI_REASSOCREQ: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; case WIFI_PROBEREQ: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - _mgt_dispatcher(padapter, ptable, precv_frame); - else - _mgt_dispatcher(padapter, ptable, precv_frame); - break; case WIFI_BEACON: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; case WIFI_ACTION: _mgt_dispatcher(padapter, ptable, precv_frame); break; @@ -577,13 +568,14 @@ unsigned int OnBeacon(struct adapter *padapter, struct recv_frame *precv_frame) uint len = precv_frame->len; struct wlan_bssid_ex *pbss; int ret = _SUCCESS; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { report_survey_event(padapter, precv_frame); return _SUCCESS; } - if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) { + if (!memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) { if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { /* we should update current network before auth, or some IE is wrong */ pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex)); @@ -1445,10 +1437,10 @@ unsigned int OnDeAuth(struct adapter *padapter, struct recv_frame *precv_frame) struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); u8 *pframe = precv_frame->rx_data; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* check A3 */ - if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), - ETH_ALEN)) + if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) return _SUCCESS; reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); @@ -1499,10 +1491,10 @@ unsigned int OnDisassoc(struct adapter *padapter, struct recv_frame *precv_frame struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); u8 *pframe = precv_frame->rx_data; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* check A3 */ - if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), - ETH_ALEN)) + if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) return _SUCCESS; reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); @@ -2018,7 +2010,7 @@ void issue_beacon(struct adapter *padapter, int timeout_ms) memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); + memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); /* pmlmeext->mgnt_seq++; */ @@ -2422,6 +2414,7 @@ void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (pmgntframe == NULL) @@ -2487,9 +2480,9 @@ void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short } else { __le32 le_tmp32; __le16 le_tmp16; - memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); + memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); /* setting auth algo number */ val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */ @@ -2582,7 +2575,7 @@ void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_i memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); @@ -2687,6 +2680,7 @@ void issue_assocreq(struct adapter *padapter) struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); int bssrate_len = 0, sta_bssrate_len = 0; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (pmgntframe == NULL) @@ -2702,9 +2696,9 @@ void issue_assocreq(struct adapter *padapter) fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -2879,6 +2873,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned struct xmit_priv *pxmitpriv; struct mlme_ext_priv *pmlmeext; struct mlme_ext_info *pmlmeinfo; + struct wlan_bssid_ex *pnetwork; if (!padapter) goto exit; @@ -2886,6 +2881,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned pxmitpriv = &(padapter->xmitpriv); pmlmeext = &(padapter->mlmeextpriv); pmlmeinfo = &(pmlmeext->mlmext_info); + pnetwork = &(pmlmeinfo->network); pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (pmgntframe == NULL) @@ -2914,7 +2910,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned memcpy(pwlanhdr->addr1, da, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -2946,10 +2942,11 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int pow u32 start = jiffies; struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* da == NULL, assume it's null data for sta to ap*/ if (da == NULL) - da = get_my_bssid(&(pmlmeinfo->network)); + da = pnetwork->MacAddress; do { ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0 ? true : false); @@ -2995,6 +2992,7 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); DBG_88E("%s\n", __func__); @@ -3038,7 +3036,7 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 memcpy(pwlanhdr->addr1, da, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -3069,10 +3067,11 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int u32 start = jiffies; struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* da == NULL, assume it's null data for sta to ap*/ if (da == NULL) - da = get_my_bssid(&(pmlmeinfo->network)); + da = pnetwork->MacAddress; do { ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0 ? true : false); @@ -3115,6 +3114,7 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); int ret = _FAIL; __le16 le_tmp; @@ -3137,7 +3137,7 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s memcpy(pwlanhdr->addr1, da, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -3288,6 +3288,7 @@ void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned ch struct sta_info *psta; struct sta_priv *pstapriv = &padapter->stapriv; struct registry_priv *pregpriv = &padapter->registrypriv; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status); @@ -3310,7 +3311,7 @@ void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned ch /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -3420,6 +3421,8 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) struct __queue *queue = &(pmlmepriv->scanned_queue); u8 InfoContent[16] = {0}; u8 ICS[8][15]; + struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); + if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0)) return; @@ -3449,9 +3452,9 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr1, cur_network->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -4042,9 +4045,10 @@ unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr { struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* check A3 */ - if (memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) + if (memcmp(MacAddr, pnetwork->MacAddress, ETH_ALEN)) return _SUCCESS; DBG_88E("%s\n", __func__); @@ -4924,11 +4928,6 @@ void addba_timer_hdl(void *function_context) } } -u8 NULL_hdl(struct adapter *padapter, u8 *pbuf) -{ - return H2C_SUCCESS; -} - u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) { u8 type; diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 324c1a7fd0b..a3ffc691be9 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -405,11 +405,6 @@ int get_bsstype(unsigned short capability) return 0; } -__inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork) -{ - return pnetwork->MacAddress; -} - u16 get_beacon_interval(struct wlan_bssid_ex *bss) { __le16 val; @@ -936,6 +931,8 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) } bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC); + if (!bssid) + return _FAIL; subtype = GetFrameSubType(pframe) >> 4; diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 9873998011d..06477e83465 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -534,13 +534,8 @@ void odm_DIGInit(struct odm_dm_struct *pDM_Odm) pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH; pDM_DigTable->FALowThresh = DM_false_ALARM_THRESH_LOW; pDM_DigTable->FAHighThresh = DM_false_ALARM_THRESH_HIGH; - if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; - } else { - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; - } + pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; + pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT; pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX; pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN; @@ -1138,16 +1133,9 @@ static void FindMinimumRSSI(struct adapter *pAdapter) { struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv; - - /* 1 1.Determine the minimum RSSI */ - if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) && - (pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0)) - pdmpriv->MinUndecoratedPWDBForDM = 0; - if (check_fwstate(pmlmepriv, _FW_LINKED) == true) /* Default port */ - pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; - else /* associated entry pwdb */ - pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; + + /* 1 1.Unconditionally set RSSI */ + pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; } void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 7f30dea1b53..86347f2ccdf 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -127,22 +127,6 @@ exit: return ret; } -u8 rtl8188e_set_rssi_cmd(struct adapter *adapt, u8 *param) -{ - u8 res = _SUCCESS; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - - if (haldata->fw_ractrl) { - ; - } else { - DBG_88E("==>%s fw dont support RA\n", __func__); - res = _FAIL; - } - - - return res; -} - u8 rtl8188e_set_raid_cmd(struct adapter *adapt, u32 mask) { u8 buf[3]; @@ -276,7 +260,7 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); + memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); SetFrameSubType(pframe, WIFI_BEACON); @@ -350,6 +334,7 @@ static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); __le16 *fctrl; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; @@ -363,7 +348,7 @@ static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) SetDuration(pframe, (pmlmeinfo->aid | 0xc000)); /* BSSID. */ - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); /* TA. */ memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); @@ -386,6 +371,7 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, struct wlan_network *cur_network = &pmlmepriv->cur_network; struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; @@ -397,21 +383,21 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, switch (cur_network->network.InfrastructureMode) { case Ndis802_11Infrastructure: SetToDs(fctrl); - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); break; case Ndis802_11APMode: SetFrDs(fctrl); memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr2, pnetwork->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr3, myid(&(adapt->eeprompriv)), ETH_ALEN); break; case Ndis802_11IBSS: default: memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); break; } @@ -498,6 +484,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) u16 BufIndex; u32 TotalPacketLen; struct rsvdpage_loc RsvdPageLoc; + struct wlan_bssid_ex *pnetwork; DBG_88E("%s\n", __func__); ReservedPagePacket = kzalloc(1000, GFP_KERNEL); @@ -510,6 +497,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) pxmitpriv = &adapt->xmitpriv; pmlmeext = &adapt->mlmeextpriv; pmlmeinfo = &pmlmeext->mlmext_info; + pnetwork = &(pmlmeinfo->network); TxDescLen = TXDESC_SIZE; PageNum = 0; @@ -541,7 +529,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) /* 3 (3) null data * 1 page */ RsvdPageLoc.LocNullData = PageNum; - ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, get_my_bssid(&pmlmeinfo->network), false, 0, 0, false); + ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, pnetwork->MacAddress, false, 0, 0, false); rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false); PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength); @@ -551,7 +539,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) /* 3 (4) probe response * 1page */ RsvdPageLoc.LocProbeRsp = PageNum; - ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, get_my_bssid(&pmlmeinfo->network), false); + ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, pnetwork->MacAddress, false); rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false); PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength); @@ -562,7 +550,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) /* 3 (5) Qos null data */ RsvdPageLoc.LocQosNull = PageNum; ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], - &QosNullLength, get_my_bssid(&pmlmeinfo->network), true, 0, 0, false); + &QosNullLength, pnetwork->MacAddress, true, 0, 0, false); rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false); PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 7d460eaafa3..3222d8d08b5 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -242,20 +242,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->hal_notch_filter = &hal_notch_filter_8188e; } -u8 GetEEPROMSize8188E(struct adapter *padapter) -{ - u8 size = 0; - u32 cr; - - cr = usb_read16(padapter, REG_9346CR); - /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */ - size = (cr & BOOT_FROM_EEPROM) ? 6 : 4; - - MSG_88E("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46"); - - return size; -} - /* */ /* */ /* LLT R/W/Init function */ diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 82f58f87656..3a274770364 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -87,7 +87,7 @@ static inline void _init_timer(struct timer_list *ptimer, static inline void _set_timer(struct timer_list *ptimer, u32 delay_time) { - mod_timer(ptimer , (jiffies+(delay_time*HZ/1000))); + mod_timer(ptimer , (jiffies+msecs_to_jiffies(delay_time))); } #define RTW_TIMER_HDL_ARGS void *FunctionContext diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h index 0e78e2a357b..42b1f22424e 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h @@ -107,7 +107,6 @@ struct P2P_PS_CTWPeriod_t { /* host message to firmware cmd */ void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode); void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus); -u8 rtl8188e_set_rssi_cmd(struct adapter *padapter, u8 *param); u8 rtl8188e_set_raid_cmd(struct adapter *padapter, u32 mask); void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 42ab1d288bd..b8c42eed98c 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -391,7 +391,6 @@ void rtl8188e_InitializeFirmwareVars(struct adapter *padapter); s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy); /* EFuse */ -u8 GetEEPROMSize8188E(struct adapter *padapter); void Hal_InitPGData88E(struct adapter *padapter); void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo); void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *hwinfo, diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 8d72ccf5f2a..4f05aee93c9 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -496,7 +496,6 @@ void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src, struct adapter *adapter, bool update_ie); int get_bsstype(unsigned short capability); -u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork); u16 get_beacon_interval(struct wlan_bssid_ex *bss); int is_client_associated_to_ap(struct adapter *padapter); @@ -516,7 +515,7 @@ void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE); void VCS_update(struct adapter *padapter, struct sta_info *psta); void update_beacon_info(struct adapter *padapter, u8 *pframe, uint len, - struct sta_info *psta); + struct sta_info *psta); int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len); void update_IOT_info(struct adapter *padapter); void update_capinfo(struct adapter *adapter, u16 updatecap); @@ -679,7 +678,6 @@ u8 read_bbreg_hdl(struct adapter *padapter, u8 *pbuf); u8 write_bbreg_hdl(struct adapter *padapter, u8 *pbuf); u8 read_rfreg_hdl(struct adapter *padapter, u8 *pbuf); u8 write_rfreg_hdl(struct adapter *padapter, u8 *pbuf); -u8 NULL_hdl(struct adapter *padapter, u8 *pbuf); u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf); u8 disconnect_hdl(struct adapter *padapter, u8 *pbuf); u8 createbss_hdl(struct adapter *padapter, u8 *pbuf); diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h index 01b3810379e..4fdc536cba7 100644 --- a/drivers/staging/rtl8188eu/include/usb_ops_linux.h +++ b/drivers/staging/rtl8188eu/include/usb_ops_linux.h @@ -79,7 +79,6 @@ void usb_read_port_cancel(struct adapter *adapter); int usb_write8(struct adapter *adapter, u32 addr, u8 val); int usb_write16(struct adapter *adapter, u32 addr, u16 val); int usb_write32(struct adapter *adapter, u32 addr, u32 val); -int usb_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata); u32 usb_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); void usb_write_port_cancel(struct adapter *adapter); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index d2efa9dfc8c..80e7ef96d80 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -615,33 +615,6 @@ int usb_write32(struct adapter *adapter, u32 addr, u32 val) return ret; } -int usb_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata) -{ - u8 request; - u8 requesttype; - u16 wvalue; - u16 index; - u16 len; - u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0}; - int ret; - - - request = 0x05; - requesttype = 0x00;/* write_out */ - index = 0;/* n/a */ - - wvalue = (u16)(addr&0x0000ffff); - len = length; - memcpy(buf, pdata, len); - - ret = usbctrl_vendorreq(adapter, request, wvalue, index, buf, len, requesttype); - - - return RTW_STATUS_CODE(ret); -} - - - static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs) { struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c index 6c64e0899ff..89ea70b0d3a 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c @@ -167,35 +167,6 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig); } -void CAM_read_entry(struct net_device *dev, u32 iIndex) -{ - u32 target_command = 0; - u32 target_content = 0; - u8 entry_i = 0; - u32 ulStatus; - s32 i = 100; - - for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { - target_command = entry_i+CAM_CONTENT_COUNT*iIndex; - target_command = target_command | BIT31; - - while ((i--) >= 0) { - ulStatus = read_nic_dword(dev, RWCAM); - if (ulStatus & BIT31) - continue; - else - break; - } - write_nic_dword(dev, RWCAM, target_command); - RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x\n", - target_command); - target_content = read_nic_dword(dev, RCAMO); - RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x\n", - target_content); - } - printk(KERN_INFO "\n"); -} - void CamRestoreAllEntry(struct net_device *dev) { u8 EntryId = 0; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h index 7d075d3cbe6..3c4c0e61c18 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h @@ -41,6 +41,4 @@ void write_cam(struct net_device *dev, u8 addr, u32 data); void CamRestoreAllEntry(struct net_device *dev); -void CAM_read_entry(struct net_device *dev, u32 iIndex); - #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index 885315cac3a..b8891c62af3 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -1661,8 +1661,8 @@ void dm_change_dynamic_initgain_thresh(struct net_device *dev, dm_digtable.rssi_low_thresh = dm_value; } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) { dm_digtable.rssi_high_power_highthresh = dm_value; - } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) { - dm_digtable.rssi_high_power_highthresh = dm_value; + } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_LOW) { + dm_digtable.rssi_high_power_lowthresh = dm_value; } else if (dm_type == DIG_TYPE_ENABLE) { dm_digtable.dig_state = DM_STA_DIG_MAX; dm_digtable.dig_enable_flag = true; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c index 8e1a5d55dce..0b4f76481bf 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c @@ -22,12 +22,6 @@ #include "r8190P_rtl8256.h" #include "rtl_pm.h" -int rtl8192E_save_state(struct pci_dev *dev, pm_message_t state) -{ - printk(KERN_NOTICE "r8192E save state call (state %u).\n", state.event); - return -EAGAIN; -} - int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state) { @@ -124,11 +118,3 @@ out: return 0; } - -int rtl8192E_enable_wake(struct pci_dev *dev, pm_message_t state, int enable) -{ - printk(KERN_NOTICE "r8192E enable wake call (state %u, enable %d).\n", - state.event, enable); - return -EAGAIN; -} - diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h index e5299fc3b34..7bfe44817f2 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h @@ -23,9 +23,7 @@ #include <linux/types.h> #include <linux/pci.h> -int rtl8192E_save_state(struct pci_dev *dev, pm_message_t state); int rtl8192E_suspend(struct pci_dev *dev, pm_message_t state); int rtl8192E_resume(struct pci_dev *dev); -int rtl8192E_enable_wake(struct pci_dev *dev, pm_message_t state, int enable); #endif diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c index c7f45080061..1ea426b7b7a 100644 --- a/drivers/staging/rtl8192e/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c @@ -34,13 +34,13 @@ u16 MCS_DATA_RATE[2][2][77] = { 468, 520, 0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, 182, 208, 156, 195, 195, 234, 273, 273, 312, 130, 156, 181, 156, 181, 208, 234, 208, 234, 260, 260, 286, 195, 234, 273, 234, 273, - 312, 351, 312, 351, 390, 390, 429} , + 312, 351, 312, 351, 390, 390, 429}, {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289, 43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, 578, 0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, 173, 217, 217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, 231, 260, 289, 289, 318, 217, 260, 303, 260, 303, 347, 390, 347, 390, - 433, 433, 477} } , + 433, 433, 477} }, {{27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, 81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, 864, 972, 1080, 12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c index 91e98e8e5bf..0cf38091f8c 100644 --- a/drivers/staging/rtl8192e/rtllib_module.c +++ b/drivers/staging/rtl8192e/rtllib_module.c @@ -202,9 +202,7 @@ void free_rtllib(struct net_device *dev) EXPORT_SYMBOL(free_rtllib); u32 rtllib_debug_level; -static int debug = \ - RTLLIB_DL_ERR - ; +static int debug = RTLLIB_DL_ERR; static struct proc_dir_entry *rtllib_proc; static int show_debug_level(struct seq_file *m, void *v) diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index cf11b042b93..1664040efda 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -70,8 +70,7 @@ rtllib_frag_cache_find(struct rtllib_device *ieee, unsigned int seq, if (entry->skb != NULL && time_after(jiffies, entry->first_frag_time + 2 * HZ)) { RTLLIB_DEBUG_FRAG( - "expiring fragment cache entry " - "seq=%u last_frag=%u\n", + "expiring fragment cache entry seq=%u last_frag=%u\n", entry->seq, entry->last_frag); dev_kfree_skb_any(entry->skb); entry->skb = NULL; @@ -188,8 +187,7 @@ static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee, if (entry == NULL) { RTLLIB_DEBUG_FRAG( - "could not invalidate fragment cache " - "entry (seq=%u)\n", seq); + "could not invalidate fragment cache entry (seq=%u)\n", seq); return -1; } @@ -305,11 +303,9 @@ rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, atomic_dec(&crypt->refcnt); if (res < 0) { RTLLIB_DEBUG_DROP( - "decryption failed (SA= %pM" - ") res=%d\n", hdr->addr2, res); + "decryption failed (SA= %pM) res=%d\n", hdr->addr2, res); if (res == -2) - RTLLIB_DEBUG_DROP("Decryption failed ICV " - "mismatch (key %d)\n", + RTLLIB_DEBUG_DROP("Decryption failed ICV mismatch (key %d)\n", skb->data[hdrlen + 3] >> 6); ieee->ieee_stats.rx_discards_undecryptable++; return -1; @@ -345,8 +341,7 @@ rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb, res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); atomic_dec(&crypt->refcnt); if (res < 0) { - printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" - " (SA= %pM keyidx=%d)\n", + printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed (SA= %pM keyidx=%d)\n", ieee->dev->name, hdr->addr2, keyidx); return -1; } @@ -559,8 +554,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, bool bMatchWinStart = false, bPktInBuf = false; unsigned long flags; - RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Seq is %d, pTS->RxIndicateSeq" - " is %d, WinSize is %d\n", __func__, SeqNum, + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Seq is %d, pTS->RxIndicateSeq is %d, WinSize is %d\n", __func__, SeqNum, pTS->RxIndicateSeq, WinSize); spin_lock_irqsave(&(ieee->reorder_spinlock), flags); @@ -600,8 +594,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, pTS->RxIndicateSeq = SeqNum + 1 - WinSize; else pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum + 1)) + 1; - RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d," - " NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum); + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum); } /* @@ -617,8 +610,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, */ if (bMatchWinStart) { /* Current packet is going to be indicated.*/ - RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packets indication!! " - "IndicateSeq: %d, NewSeq: %d\n", + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum); ieee->prxbIndicateArray[0] = prxb; index = 1; @@ -636,9 +628,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, if (!AddReorderEntry(pTS, pReorderEntry)) { RTLLIB_DEBUG(RTLLIB_DL_REORDER, - "%s(): Duplicate packet is " - "dropped!! IndicateSeq: %d, " - "NewSeq: %d\n", + "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", __func__, pTS->RxIndicateSeq, SeqNum); list_add_tail(&pReorderEntry->List, @@ -652,8 +642,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, } } else { RTLLIB_DEBUG(RTLLIB_DL_REORDER, - "Pkt insert into struct buffer!! " - "IndicateSeq: %d, NewSeq: %d\n", + "Pkt insert into struct buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum); } } else { @@ -663,9 +652,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, * indicate all the packets in struct buffer and get * reorder entries. */ - RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket():" - " There is no reorder entry!! Packet is " - "dropped!!\n"); + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n"); { int i; @@ -687,8 +674,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq)) { /* This protect struct buffer from overflow. */ if (index >= REORDER_WIN_SIZE) { - RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicate" - "Packet(): Buffer overflow!!\n"); + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!!\n"); bPktInBuf = true; break; } @@ -699,8 +685,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096; ieee->prxbIndicateArray[index] = pReorderEntry->prxb; - RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum" - " %d!\n", __func__, pReorderEntry->SeqNum); + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum %d!\n", __func__, pReorderEntry->SeqNum); index++; list_add_tail(&pReorderEntry->List, @@ -719,8 +704,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, pTS->RxTimeoutIndicateSeq = 0xffff; if (index > REORDER_WIN_SIZE) { - RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket():" - " Rx Reorder struct buffer full!!\n"); + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder struct buffer full!!\n"); spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); return; @@ -809,14 +793,11 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, (nSubframe_Length << 8); if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) { - printk(KERN_INFO "%s: A-MSDU parse error!! " - "pRfd->nTotalSubframe : %d\n",\ + printk(KERN_INFO "%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\ __func__, rxb->nr_subframes); - printk(KERN_INFO "%s: A-MSDU parse error!! " - "Subframe Length: %d\n", __func__, + printk(KERN_INFO "%s: A-MSDU parse error!! Subframe Length: %d\n", __func__, nSubframe_Length); - printk(KERN_INFO "nRemain_Length is %d and " - "nSubframe_Length is : %d\n", skb->len, + printk(KERN_INFO "nRemain_Length is %d and nSubframe_Length is : %d\n", skb->len, nSubframe_Length); printk(KERN_INFO "The Packet SeqNum is %d\n", SeqNum); return 0; @@ -844,8 +825,7 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, sub_skb->dev = ieee->dev; rxb->subframes[rxb->nr_subframes++] = sub_skb; if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) { - RTLLIB_DEBUG_RX("ParseSubframe(): Too many " - "Subframes! Packets dropped!\n"); + RTLLIB_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n"); break; } skb_pull(skb, nSubframe_Length); @@ -922,8 +902,7 @@ static int rtllib_rx_check_duplicate(struct rtllib_device *ieee, pRxTS->RxLastFragNum = frag; pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc); } else { - RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip" - " the check!!\n", __func__); + RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip the check!!\n", __func__); return -1; } } @@ -996,9 +975,7 @@ static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc, stype != RTLLIB_STYPE_QOS_DATA) { if (stype != RTLLIB_STYPE_NULLFUNC) RTLLIB_DEBUG_DROP( - "RX: dropped data frame " - "with no data (type=0x%02x, " - "subtype=0x%02x)\n", + "RX: dropped data frame with no data (type=0x%02x, subtype=0x%02x)\n", type, stype); return -1; } @@ -1041,8 +1018,7 @@ static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb, * frames from other than current BSS, so just drop the * frames silently instead of filling system log with * these reports. */ - RTLLIB_DEBUG_DROP("Decryption failed (not set)" - " (SA= %pM)\n", + RTLLIB_DEBUG_DROP("Decryption failed (not set) (SA= %pM)\n", hdr->addr2); ieee->ieee_stats.rx_discards_undecryptable++; return -1; @@ -1086,8 +1062,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, if (!frag_skb) { RTLLIB_DEBUG(RTLLIB_DL_RX | RTLLIB_DL_FRAG, - "Rx cannot get skb from fragment " - "cache (morefrag=%d seq=%u frag=%u)\n", + "Rx cannot get skb from fragment cache (morefrag=%d seq=%u frag=%u)\n", (fc & RTLLIB_FCTL_MOREFRAGS) != 0, WLAN_GET_SEQ_SEQ(sc), frag); return -1; @@ -1097,8 +1072,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, flen -= hdrlen; if (frag_skb->tail + flen > frag_skb->end) { - printk(KERN_WARNING "%s: host decrypted and " - "reassembled frame did not fit skb\n", + printk(KERN_WARNING "%s: host decrypted and reassembled frame did not fit skb\n", __func__); rtllib_frag_cache_invalidate(ieee, hdr); return -1; @@ -1152,8 +1126,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, eap_get_type(eap->type)); } else { RTLLIB_DEBUG_DROP( - "encryption configured, but RX " - "frame not encrypted (SA= %pM)\n", + "encryption configured, but RX frame not encrypted (SA= %pM)\n", hdr->addr2); return -1; } @@ -1170,9 +1143,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep && !rtllib_is_eapol_frame(ieee, skb, hdrlen)) { RTLLIB_DEBUG_DROP( - "dropped unencrypted RX data " - "frame from %pM" - " (drop_unencrypted=1)\n", + "dropped unencrypted RX data frame from %pM (drop_unencrypted=1)\n", hdr->addr2); return -1; } @@ -1762,9 +1733,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, while (length >= sizeof(*info_element)) { if (sizeof(*info_element) + info_element->len > length) { - RTLLIB_DEBUG_MGMT("Info elem: parse failed: " - "info_element->len + 2 > left : " - "info_element->len+2=%zd left=%d, id=%d.\n", + RTLLIB_DEBUG_MGMT("Info elem: parse failed: info_element->len + 2 > left : info_element->len+2=%zd left=%d, id=%d.\n", info_element->len + sizeof(*info_element), length, info_element->id); @@ -2207,34 +2176,6 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, return 0; } -static inline u8 rtllib_SignalStrengthTranslate(u8 CurrSS) -{ - u8 RetSS; - - if (CurrSS >= 71 && CurrSS <= 100) - RetSS = 90 + ((CurrSS - 70) / 3); - else if (CurrSS >= 41 && CurrSS <= 70) - RetSS = 78 + ((CurrSS - 40) / 3); - else if (CurrSS >= 31 && CurrSS <= 40) - RetSS = 66 + (CurrSS - 30); - else if (CurrSS >= 21 && CurrSS <= 30) - RetSS = 54 + (CurrSS - 20); - else if (CurrSS >= 5 && CurrSS <= 20) - RetSS = 42 + (((CurrSS - 5) * 2) / 3); - else if (CurrSS == 4) - RetSS = 36; - else if (CurrSS == 3) - RetSS = 27; - else if (CurrSS == 2) - RetSS = 18; - else if (CurrSS == 1) - RetSS = 9; - else - RetSS = CurrSS; - - return RetSS; -} - static long rtllib_translate_todbm(u8 signal_strength_index) { long signal_power; @@ -2321,8 +2262,7 @@ static inline int rtllib_network_init( } if (network->mode == 0) { - RTLLIB_DEBUG_SCAN("Filtered out '%s (%pM)' " - "network.\n", + RTLLIB_DEBUG_SCAN("Filtered out '%s (%pM)' network.\n", escape_essid(network->ssid, network->ssid_len), network->bssid); @@ -2363,13 +2303,6 @@ static inline int is_same_network(struct rtllib_network *src, (dst->capability & WLAN_CAPABILITY_ESS))); } -static inline void update_ibss_network(struct rtllib_network *dst, - struct rtllib_network *src) -{ - memcpy(&dst->stats, &src->stats, sizeof(struct rtllib_rx_stats)); - dst->last_scanned = jiffies; -} - static inline void update_network(struct rtllib_network *dst, struct rtllib_network *src) @@ -2568,8 +2501,7 @@ static inline void rtllib_process_probe_response( if (WLAN_FC_GET_STYPE(le16_to_cpu(beacon->header.frame_ctl)) == RTLLIB_STYPE_PROBE_RESP) { if (IsPassiveChannel(ieee, network->channel)) { - printk(KERN_INFO "GetScanInfo(): For Global Domain, " - "filter probe response at channel(%d).\n", + printk(KERN_INFO "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network->channel); goto free_network; } @@ -2618,8 +2550,7 @@ static inline void rtllib_process_probe_response( /* If there are no more slots, expire the oldest */ list_del(&oldest->list); target = oldest; - RTLLIB_DEBUG_SCAN("Expired '%s' ( %pM) from " - "network list.\n", + RTLLIB_DEBUG_SCAN("Expired '%s' ( %pM) from network list.\n", escape_essid(target->ssid, target->ssid_len), target->bssid); diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index cd196cec0dd..1b4623c3f95 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -4,6 +4,8 @@ * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue. * WB 2008-05-27 * *****************************************************************************************************************************/ +#include <asm/byteorder.h> +#include <asm/unaligned.h> #include "ieee80211.h" #include "rtl819x_BA.h" @@ -110,13 +112,12 @@ static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, P struct sk_buff *skb = NULL; struct ieee80211_hdr_3addr *BAReq = NULL; u8 *tag = NULL; - __le16 tmp = 0; u16 len = ieee->tx_headroom + 9; //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2)) IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __func__, type, Dst, ieee->dev); - if (pBA == NULL||ieee == NULL) + if (pBA == NULL) { - IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee); + IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA is NULL\n"); return NULL; } skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME @@ -149,17 +150,17 @@ static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, P { // Status Code printk("=====>to send ADDBARSP\n"); - tmp = cpu_to_le16(StatusCode); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(StatusCode, tag); tag += 2; } // BA Parameter Set - tmp = cpu_to_le16(pBA->BaParamSet.shortData); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(pBA->BaParamSet.shortData, tag); tag += 2; // BA Timeout Value - tmp = cpu_to_le16(pBA->BaTimeoutValue); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(pBA->BaTimeoutValue, tag); tag += 2; if (ACT_ADDBAREQ == type) @@ -196,7 +197,6 @@ static struct sk_buff *ieee80211_DELBA( struct sk_buff *skb = NULL; struct ieee80211_hdr_3addr *Delba = NULL; u8 *tag = NULL; - __le16 tmp = 0; //len = head len + DELBA Parameter Set(2) + Reason Code(2) u16 len = 6 + ieee->tx_headroom; @@ -230,12 +230,12 @@ static struct sk_buff *ieee80211_DELBA( *tag ++= ACT_DELBA; // DELBA Parameter Set - tmp = cpu_to_le16(DelbaParamSet.shortData); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(DelbaParamSet.shortData, tag); tag += 2; // Reason Code - tmp = cpu_to_le16(ReasonCode); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(ReasonCode, tag); tag += 2; IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index c4514109d0e..acaa723817e 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -241,7 +241,7 @@ static PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, { //DIRECTION_VALUE dir; u8 dir; - bool search_dir[4] = {0, 0, 0, 0}; + bool search_dir[4] = {0}; struct list_head *psearch_list; //FIXME PTS_COMMON_INFO pRet = NULL; if(ieee->iw_mode == IW_MODE_MASTER) //ap mode diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.c b/drivers/staging/rtl8192u/r8190_rtl8256.c index 45514aa9769..1868352d378 100644 --- a/drivers/staging/rtl8192u/r8190_rtl8256.c +++ b/drivers/staging/rtl8192u/r8190_rtl8256.c @@ -23,7 +23,7 @@ * Return: NONE * Note: 8226 support both 20M and 40 MHz *---------------------------------------------------------------------------*/ -void PHY_SetRF8256Bandwidth(struct net_device *dev , HT_CHANNEL_WIDTH Bandwidth) +void PHY_SetRF8256Bandwidth(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth) { u8 eRFPath; struct r8192_priv *priv = ieee80211_priv(dev); diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index 936565d4601..ee6b936efef 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -21,14 +21,13 @@ Major Change History: #include "r8190_rtl8256.h" #include "r819xU_cmdpkt.h" /*---------------------------Define Local Constant---------------------------*/ -// -// Indicate different AP vendor for IOT issue. -// -static u32 edca_setting_DL[HT_IOT_PEER_MAX] = - { 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5ea44f}; -static u32 edca_setting_UL[HT_IOT_PEER_MAX] = - { 0x5e4322, 0xa44f, 0x5e4322, 0x604322, 0x5ea44f, 0x5ea44f}; - +/* Indicate different AP vendor for IOT issue. */ +static u32 edca_setting_DL[HT_IOT_PEER_MAX] = { + 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0x00a44f, 0x5ea44f +}; +static u32 edca_setting_UL[HT_IOT_PEER_MAX] = { + 0x5e4322, 0x00a44f, 0x5e4322, 0x604322, 0x5ea44f, 0x5ea44f +}; #define RTK_UL_EDCA 0xa44f #define RTK_DL_EDCA 0x5e4322 @@ -36,11 +35,11 @@ static u32 edca_setting_UL[HT_IOT_PEER_MAX] = /*------------------------Define global variable-----------------------------*/ -// Debug variable ? +/* Debug variable ? */ dig_t dm_digtable; -// Store current software write register content for MAC PHY. -u8 dm_shadow[16][256] = {{0}}; -// For Dynamic Rx Path Selection by Signal Strength +/* Store current software write register content for MAC PHY. */ +u8 dm_shadow[16][256] = { {0} }; +/* For Dynamic Rx Path Selection by Signal Strength */ DRxPathSel DM_RxPathSelTable; /*------------------------Define global variable-----------------------------*/ @@ -56,24 +55,21 @@ extern void dm_check_fsync(struct net_device *dev); /*---------------------Define local function prototype-----------------------*/ -// DM --> Rate Adaptive +/* DM --> Rate Adaptive */ static void dm_check_rate_adaptive(struct net_device *dev); -// DM --> Bandwidth switch +/* DM --> Bandwidth switch */ static void dm_init_bandwidth_autoswitch(struct net_device *dev); static void dm_bandwidth_autoswitch(struct net_device *dev); -// DM --> TX power control -//static void dm_initialize_txpower_tracking(struct net_device *dev); +/* DM --> TX power control */ +/*static void dm_initialize_txpower_tracking(struct net_device *dev);*/ static void dm_check_txpower_tracking(struct net_device *dev); +/*static void dm_txpower_reset_recovery(struct net_device *dev);*/ - -//static void dm_txpower_reset_recovery(struct net_device *dev); - - -// DM --> Dynamic Init Gain by RSSI +/* DM --> Dynamic Init Gain by RSSI */ static void dm_dig_init(struct net_device *dev); static void dm_ctrl_initgain_byrssi(struct net_device *dev); static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev); @@ -84,61 +80,58 @@ static void dm_pd_th(struct net_device *dev); static void dm_cs_ratio(struct net_device *dev); static void dm_init_ctstoself(struct net_device *dev); -// DM --> EDCA turbo mode control +/* DM --> EDCA turbo mode control */ static void dm_check_edca_turbo(struct net_device *dev); -//static void dm_gpio_change_rf(struct net_device *dev); -// DM --> Check PBC +/*static void dm_gpio_change_rf(struct net_device *dev);*/ +/* DM --> Check PBC */ static void dm_check_pbc_gpio(struct net_device *dev); - -// DM --> Check current RX RF path state +/* DM --> Check current RX RF path state */ static void dm_check_rx_path_selection(struct net_device *dev); static void dm_init_rxpath_selection(struct net_device *dev); static void dm_rxpath_sel_byrssi(struct net_device *dev); - -// DM --> Fsync for broadcom ap +/* DM --> Fsync for broadcom ap */ static void dm_init_fsync(struct net_device *dev); static void dm_deInit_fsync(struct net_device *dev); -//Added by vivi, 20080522 +/* Added by vivi, 20080522 */ static void dm_check_txrateandretrycount(struct net_device *dev); /*---------------------Define local function prototype-----------------------*/ -/*---------------------Define of Tx Power Control For Near/Far Range --------*/ //Add by Jacken 2008/02/18 +/*---------------------Define of Tx Power Control For Near/Far Range --------*/ /*Add by Jacken 2008/02/18 */ static void dm_init_dynamic_txpower(struct net_device *dev); static void dm_dynamic_txpower(struct net_device *dev); - -// DM --> For rate adaptive and DIG, we must send RSSI to firmware +/* DM --> For rate adaptive and DIG, we must send RSSI to firmware */ static void dm_send_rssi_tofw(struct net_device *dev); static void dm_ctstoself(struct net_device *dev); /*---------------------------Define function prototype------------------------*/ -//================================================================================ -// HW Dynamic mechanism interface. -//================================================================================ - -// -// Description: -// Prepare SW resource for HW dynamic mechanism. -// -// Assumption: -// This function is only invoked at driver intialization once. -// -// +/* + * ================================================================================ + * HW Dynamic mechanism interface. + * ================================================================================ + * + * + * Description: + * Prepare SW resource for HW dynamic mechanism. + * + * Assumption: + * This function is only invoked at driver intialization once. + */ void init_hal_dm(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - // Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism. + /* Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism. */ priv->undecorated_smoothed_pwdb = -1; - //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. + /* Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. */ dm_init_dynamic_txpower(dev); init_rate_adaptive(dev); - //dm_initialize_txpower_tracking(dev); + /*dm_initialize_txpower_tracking(dev);*/ dm_dig_init(dev); dm_init_edca_turbo(dev); dm_init_bandwidth_autoswitch(dev); @@ -146,18 +139,16 @@ void init_hal_dm(struct net_device *dev) dm_init_rxpath_selection(dev); dm_init_ctstoself(dev); -} // InitHalDm +} /* InitHalDm */ void deinit_hal_dm(struct net_device *dev) { - dm_deInit_fsync(dev); - } - #ifdef USB_RX_AGGREGATION_SUPPORT -void dm_CheckRxAggregation(struct net_device *dev) { +void dm_CheckRxAggregation(struct net_device *dev) +{ struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; static unsigned long lastTxOkCnt; @@ -186,14 +177,15 @@ void dm_CheckRxAggregation(struct net_device *dev) { if ((curTxOkCnt + curRxOkCnt) < 15000000) return; - if(curTxOkCnt > 4*curRxOkCnt) { + if (curTxOkCnt > 4*curRxOkCnt) { if (priv->bCurrentRxAggrEnable) { write_nic_dword(dev, 0x1a8, 0); priv->bCurrentRxAggrEnable = false; } - }else{ + } else { if (!priv->bCurrentRxAggrEnable && !pHTInfo->bCurrentRT2RTAggregation) { u32 ulValue; + ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) | (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout); /* @@ -208,16 +200,14 @@ void dm_CheckRxAggregation(struct net_device *dev) { lastTxOkCnt = priv->stats.txbytesunicast; lastRxOkCnt = priv->stats.rxbytesunicast; -} // dm_CheckEdcaTurbo +} /* dm_CheckEdcaTurbo */ #endif - - void hal_dm_watchdog(struct net_device *dev) { - //struct r8192_priv *priv = ieee80211_priv(dev); + /*struct r8192_priv *priv = ieee80211_priv(dev);*/ - //static u8 previous_bssid[6] ={0}; + /*static u8 previous_bssid[6] ={0};*/ /*Add by amy 2008/05/15 ,porting from windows code.*/ dm_check_rate_adaptive(dev); @@ -230,25 +220,23 @@ void hal_dm_watchdog(struct net_device *dev) dm_check_rx_path_selection(dev); dm_check_fsync(dev); - // Add by amy 2008-05-15 porting from windows code. + /* Add by amy 2008-05-15 porting from windows code. */ dm_check_pbc_gpio(dev); dm_send_rssi_tofw(dev); dm_ctstoself(dev); #ifdef USB_RX_AGGREGATION_SUPPORT dm_CheckRxAggregation(dev); #endif -} //HalDmWatchDog - +} /* HalDmWatchDog */ /* - * Decide Rate Adaptive Set according to distance (signal strength) - * 01/11/2008 MHC Modify input arguments and RATR table level. - * 01/16/2008 MHC RF_Type is assigned in ReadAdapterInfo(). We must call - * the function after making sure RF_Type. - */ + * Decide Rate Adaptive Set according to distance (signal strength) + * 01/11/2008 MHC Modify input arguments and RATR table level. + * 01/16/2008 MHC RF_Type is assigned in ReadAdapterInfo(). We must call + * the function after making sure RF_Type. + */ void init_rate_adaptive(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv(dev); prate_adaptive pra = (prate_adaptive)&priv->rate_adaptive; @@ -261,36 +249,33 @@ void init_rate_adaptive(struct net_device *dev) pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M; pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M; - if(priv->CustomerID == RT_CID_819x_Netcore) + if (priv->CustomerID == RT_CID_819x_Netcore) pra->ping_rssi_enable = 1; else pra->ping_rssi_enable = 0; pra->ping_rssi_thresh_for_ra = 15; - - if (priv->rf_type == RF_2T4R) - { - // 07/10/08 MH Modify for RA smooth scheme. - /* 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code.*/ + if (priv->rf_type == RF_2T4R) { + /* + * 07/10/08 MH Modify for RA smooth scheme. + * 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code. + */ pra->upper_rssi_threshold_ratr = 0x8f0f0000; pra->middle_rssi_threshold_ratr = 0x8f0ff000; pra->low_rssi_threshold_ratr = 0x8f0ff001; pra->low_rssi_threshold_ratr_40M = 0x8f0ff005; pra->low_rssi_threshold_ratr_20M = 0x8f0ff001; - pra->ping_rssi_ratr = 0x0000000d;//cosa add for test - } - else if (priv->rf_type == RF_1T2R) - { + pra->ping_rssi_ratr = 0x0000000d;/* cosa add for test */ + } else if (priv->rf_type == RF_1T2R) { pra->upper_rssi_threshold_ratr = 0x000f0000; pra->middle_rssi_threshold_ratr = 0x000ff000; pra->low_rssi_threshold_ratr = 0x000ff001; pra->low_rssi_threshold_ratr_40M = 0x000ff005; pra->low_rssi_threshold_ratr_20M = 0x000ff001; - pra->ping_rssi_ratr = 0x0000000d;//cosa add for test + pra->ping_rssi_ratr = 0x0000000d;/* cosa add for test */ } -} // InitRateAdaptive - +} /* InitRateAdaptive */ /*----------------------------------------------------------------------------- * Function: dm_check_rate_adaptive() @@ -318,149 +303,122 @@ static void dm_check_rate_adaptive(struct net_device *dev) bool bshort_gi_enabled = false; static u8 ping_rssi_state; - - if(!priv->up) - { + if (!priv->up) { RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n"); return; } - if(pra->rate_adaptive_disabled)//this variable is set by ioctl. + if (pra->rate_adaptive_disabled) /* this variable is set by ioctl. */ return; - // TODO: Only 11n mode is implemented currently, - if(!(priv->ieee80211->mode == WIRELESS_MODE_N_24G || - priv->ieee80211->mode == WIRELESS_MODE_N_5G)) - return; + /* TODO: Only 11n mode is implemented currently, */ + if (!(priv->ieee80211->mode == WIRELESS_MODE_N_24G || + priv->ieee80211->mode == WIRELESS_MODE_N_5G)) + return; - if(priv->ieee80211->state == IEEE80211_LINKED) - { - // RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t"); + if (priv->ieee80211->state == IEEE80211_LINKED) { + /*RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t");*/ - // - // Check whether Short GI is enabled - // + /* Check whether Short GI is enabled */ bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) || (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz); - pra->upper_rssi_threshold_ratr = - (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); pra->middle_rssi_threshold_ratr = - (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { pra->low_rssi_threshold_ratr = - (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; - } - else - { + (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); + } else { pra->low_rssi_threshold_ratr = - (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); } - //cosa add for test + /* cosa add for test */ pra->ping_rssi_ratr = - (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); /* 2007/10/08 MH We support RA smooth scheme now. When it is the first time to link with AP. We will not change upper/lower threshold. If STA stay in high or low level, we must change two different threshold to prevent jumping frequently. */ - if (pra->ratr_state == DM_RATR_STA_HIGH) - { + if (pra->ratr_state == DM_RATR_STA_HIGH) { HighRSSIThreshForRA = pra->high2low_rssi_thresh_for_ra; - LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ? (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); - } - else if (pra->ratr_state == DM_RATR_STA_LOW) - { + } else if (pra->ratr_state == DM_RATR_STA_LOW) { HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra; - LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ? (pra->low2high_rssi_thresh_for_ra40M):(pra->low2high_rssi_thresh_for_ra20M); - } - else - { + } else { HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra; - LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ? (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); } - //DbgPrint("[DM] THresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA); - if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) - { - //DbgPrint("[DM] RSSI=%d STA=HIGH\n\r", pHalData->UndecoratedSmoothedPWDB); + /*DbgPrint("[DM] THresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA);*/ + if (priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) { + /*DbgPrint("[DM] RSSI=%d STA=HIGH\n\r", pHalData->UndecoratedSmoothedPWDB);*/ pra->ratr_state = DM_RATR_STA_HIGH; targetRATR = pra->upper_rssi_threshold_ratr; - }else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA) - { - //DbgPrint("[DM] RSSI=%d STA=Middle\n\r", pHalData->UndecoratedSmoothedPWDB); + } else if (priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA) { + /*DbgPrint("[DM] RSSI=%d STA=Middle\n\r", pHalData->UndecoratedSmoothedPWDB);*/ pra->ratr_state = DM_RATR_STA_MIDDLE; targetRATR = pra->middle_rssi_threshold_ratr; - }else - { - //DbgPrint("[DM] RSSI=%d STA=LOW\n\r", pHalData->UndecoratedSmoothedPWDB); + } else { + /*DbgPrint("[DM] RSSI=%d STA=LOW\n\r", pHalData->UndecoratedSmoothedPWDB);*/ pra->ratr_state = DM_RATR_STA_LOW; targetRATR = pra->low_rssi_threshold_ratr; } - //cosa add for test - if(pra->ping_rssi_enable) - { - //pHalData->UndecoratedSmoothedPWDB = 19; - if(priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5)) - { - if((priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) || - ping_rssi_state) - { - //DbgPrint("TestRSSI = %d, set RATR to 0x%x \n", pHalData->UndecoratedSmoothedPWDB, pRA->TestRSSIRATR); + /* cosa add for test */ + if (pra->ping_rssi_enable) { + /*pHalData->UndecoratedSmoothedPWDB = 19;*/ + if (priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5)) { + if ((priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) || + ping_rssi_state) { + /*DbgPrint("TestRSSI = %d, set RATR to 0x%x\n", pHalData->UndecoratedSmoothedPWDB, pRA->TestRSSIRATR);*/ pra->ratr_state = DM_RATR_STA_LOW; targetRATR = pra->ping_rssi_ratr; ping_rssi_state = 1; } - //else - // DbgPrint("TestRSSI is between the range. \n"); - } - else - { - //DbgPrint("TestRSSI Recover to 0x%x \n", targetRATR); + /*else + DbgPrint("TestRSSI is between the range.\n");*/ + } else { + /*DbgPrint("TestRSSI Recover to 0x%x\n", targetRATR);*/ ping_rssi_state = 0; } } - // 2008.04.01 - // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7. - if(priv->ieee80211->GetHalfNmodeSupportByAPsHandler(dev)) - targetRATR &= 0xf00fffff; + /* + * 2008.04.01 + * For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7. + */ + if (priv->ieee80211->GetHalfNmodeSupportByAPsHandler(dev)) + targetRATR &= 0xf00fffff; - // - // Check whether updating of RATR0 is required - // + /* Check whether updating of RATR0 is required */ read_nic_dword(dev, RATR0, ¤tRATR); - if(targetRATR != currentRATR) - { + if (targetRATR != currentRATR) { u32 ratr_value; + ratr_value = targetRATR; - RT_TRACE(COMP_RATE,"currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR); - if(priv->rf_type == RF_1T2R) - { + RT_TRACE(COMP_RATE, "currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR); + if (priv->rf_type == RF_1T2R) ratr_value &= ~(RATE_ALL_OFDM_2SS); - } write_nic_dword(dev, RATR0, ratr_value); write_nic_byte(dev, UFWP, 1); pra->last_ratr = targetRATR; } - } - else - { + } else { pra->ratr_state = DM_RATR_STA_MAX; } -} // dm_CheckRateAdaptive - +} /* dm_CheckRateAdaptive */ static void dm_init_bandwidth_autoswitch(struct net_device *dev) { @@ -471,78 +429,74 @@ static void dm_init_bandwidth_autoswitch(struct net_device *dev) priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable = false; -} // dm_init_bandwidth_autoswitch - +} /* dm_init_bandwidth_autoswitch */ static void dm_bandwidth_autoswitch(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable){ + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 || !priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable) return; - }else{ - if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){//If send packets in 40 Mhz in 20/40 - if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) - priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true; - }else{//in force send packets in 20 Mhz in 20/40 - if(priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz) - priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; - - } + if (priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false) { /* If send packets in 40 Mhz in 20/40 */ + if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) + priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true; + } else { /* in force send packets in 20 Mhz in 20/40 */ + if (priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz) + priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; } -} // dm_BandwidthAutoSwitch +} /* dm_BandwidthAutoSwitch */ -//OFDM default at 0db, index=6. +/* OFDM default at 0db, index=6. */ static u32 OFDMSwingTable[OFDM_Table_Length] = { - 0x7f8001fe, // 0, +6db - 0x71c001c7, // 1, +5db - 0x65400195, // 2, +4db - 0x5a400169, // 3, +3db - 0x50800142, // 4, +2db - 0x47c0011f, // 5, +1db - 0x40000100, // 6, +0db ===> default, upper for higher temperature, lower for low temperature - 0x390000e4, // 7, -1db - 0x32c000cb, // 8, -2db - 0x2d4000b5, // 9, -3db - 0x288000a2, // 10, -4db - 0x24000090, // 11, -5db - 0x20000080, // 12, -6db - 0x1c800072, // 13, -7db - 0x19800066, // 14, -8db - 0x26c0005b, // 15, -9db - 0x24400051, // 16, -10db - 0x12000048, // 17, -11db - 0x10000040 // 18, -12db + 0x7f8001fe, /* 0, +6db */ + 0x71c001c7, /* 1, +5db */ + 0x65400195, /* 2, +4db */ + 0x5a400169, /* 3, +3db */ + 0x50800142, /* 4, +2db */ + 0x47c0011f, /* 5, +1db */ + 0x40000100, /* 6, +0db ===> default, upper for higher temperature, lower for low temperature */ + 0x390000e4, /* 7, -1db */ + 0x32c000cb, /* 8, -2db */ + 0x2d4000b5, /* 9, -3db */ + 0x288000a2, /* 10, -4db */ + 0x24000090, /* 11, -5db */ + 0x20000080, /* 12, -6db */ + 0x1c800072, /* 13, -7db */ + 0x19800066, /* 14, -8db */ + 0x26c0005b, /* 15, -9db */ + 0x24400051, /* 16, -10db */ + 0x12000048, /* 17, -11db */ + 0x10000040 /* 18, -12db */ }; static u8 CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, // 0, +0db ===> CCK40M default - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, // 1, -1db - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, // 2, -2db - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, // 3, -3db - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, // 4, -4db - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, // 5, -5db - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, // 6, -6db ===> CCK20M default - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, // 7, -7db - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, // 8, -8db - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, // 9, -9db - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, // 10, -10db - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} // 11, -11db + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0db ===> CCK40M default */ + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 1, -1db */ + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 2, -2db */ + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 3, -3db */ + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 4, -4db */ + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 5, -5db */ + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 6, -6db ===> CCK20M default */ + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 7, -7db */ + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 8, -8db */ + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 9, -9db */ + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 10, -10db */ + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} /* 11, -11db */ }; static u8 CCKSwingTable_Ch14[CCK_Table_length][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, // 0, +0db ===> CCK40M default - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, // 1, -1db - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, // 2, -2db - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, // 3, -3db - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, // 4, -4db - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, // 5, -5db - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, // 6, -6db ===> CCK20M default - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, // 7, -7db - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, // 8, -8db - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, // 9, -9db - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, // 10, -10db - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} // 11, -11db + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0db ===> CCK40M default */ + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 1, -1db */ + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 2, -2db */ + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 3, -3db */ + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 4, -4db */ + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 5, -5db */ + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 6, -6db ===> CCK20M default */ + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 7, -7db */ + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 8, -8db */ + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 9, -9db */ + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 10, -10db */ + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} /* 11, -11db */ }; static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) @@ -551,14 +505,14 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) bool bHighpowerstate, viviflag = FALSE; DCMD_TXCMD_T tx_cmd; u8 powerlevelOFDM24G; - int i =0, j = 0, k = 0; - u8 RF_Type, tmp_report[5]={0, 0, 0, 0, 0}; + int i = 0, j = 0, k = 0; + u8 RF_Type, tmp_report[5] = {0, 0, 0, 0, 0}; u32 Value; u8 Pwr_Flag; - u16 Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0; - //RT_STATUS rtStatus = RT_STATUS_SUCCESS; + u16 Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver = 0; + /*RT_STATUS rtStatus = RT_STATUS_SUCCESS;*/ bool rtStatus = true; - u32 delta=0; + u32 delta = 0; write_nic_byte(dev, 0x1ba, 0); @@ -571,109 +525,87 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G); - for(j = 0; j<=30; j++) -{ //fill tx_cmd - - tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING; - tx_cmd.Length = 4; - tx_cmd.Value = Value; - rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12); - if (rtStatus == RT_STATUS_FAILURE) - { - RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n"); - } - mdelay(1); - //DbgPrint("hi, vivi, strange\n"); - for(i = 0;i <= 30; i++) - { - read_nic_byte(dev, 0x1ba, &Pwr_Flag); - - if (Pwr_Flag == 0) - { - mdelay(1); - continue; - } - read_nic_word(dev, 0x13c, &Avg_TSSI_Meas); - if(Avg_TSSI_Meas == 0) - { - write_nic_byte(dev, 0x1ba, 0); - break; - } + for (j = 0; j <= 30; j++) { /* fill tx_cmd */ + tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING; + tx_cmd.Length = 4; + tx_cmd.Value = Value; + rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12); + if (rtStatus == RT_STATUS_FAILURE) + RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n"); + mdelay(1); + /*DbgPrint("hi, vivi, strange\n");*/ + for (i = 0; i <= 30; i++) { + read_nic_byte(dev, 0x1ba, &Pwr_Flag); + + if (Pwr_Flag == 0) { + mdelay(1); + continue; + } + read_nic_word(dev, 0x13c, &Avg_TSSI_Meas); + if (Avg_TSSI_Meas == 0) { + write_nic_byte(dev, 0x1ba, 0); + break; + } - for(k = 0;k < 5; k++) - { - if(k !=4) - read_nic_byte(dev, 0x134+k, &tmp_report[k]); - else - read_nic_byte(dev, 0x13e, &tmp_report[k]); - RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]); - } + for (k = 0; k < 5; k++) { + if (k != 4) + read_nic_byte(dev, 0x134+k, &tmp_report[k]); + else + read_nic_byte(dev, 0x13e, &tmp_report[k]); + RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]); + } - //check if the report value is right - for(k = 0;k < 5; k++) - { - if(tmp_report[k] <= 20) - { - viviflag =TRUE; + /* check if the report value is right */ + for (k = 0; k < 5; k++) { + if (tmp_report[k] <= 20) { + viviflag = TRUE; + break; + } + } + if (viviflag == TRUE) { + write_nic_byte(dev, 0x1ba, 0); + viviflag = FALSE; + RT_TRACE(COMP_POWER_TRACKING, "we filtered the data\n"); + for (k = 0; k < 5; k++) + tmp_report[k] = 0; break; } - } - if(viviflag ==TRUE) - { - write_nic_byte(dev, 0x1ba, 0); - viviflag = FALSE; - RT_TRACE(COMP_POWER_TRACKING, "we filtered the data\n"); - for(k = 0;k < 5; k++) - tmp_report[k] = 0; - break; - } - for(k = 0;k < 5; k++) - { - Avg_TSSI_Meas_from_driver += tmp_report[k]; - } - - Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5; - RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver); - TSSI_13dBm = priv->TSSI_13dBm; - RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm); + for (k = 0; k < 5; k++) + Avg_TSSI_Meas_from_driver += tmp_report[k]; - //if(abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK) - // For MacOS-compatible - if(Avg_TSSI_Meas_from_driver > TSSI_13dBm) - delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm; - else - delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver; + Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5; + RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver); + TSSI_13dBm = priv->TSSI_13dBm; + RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm); - if(delta <= E_FOR_TX_POWER_TRACK) - { - priv->ieee80211->bdynamic_txpower_enable = TRUE; - write_nic_byte(dev, 0x1ba, 0); - RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n"); - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); - return; - } - else - { - if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) - { - if (priv->rfa_txpowertrackingindex > 0) - { + /*if (abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK)*/ + /* For MacOS-compatible */ + if (Avg_TSSI_Meas_from_driver > TSSI_13dBm) + delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm; + else + delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver; + + if (delta <= E_FOR_TX_POWER_TRACK) { + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); + RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n"); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); + return; + } + if (Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) { + if (priv->rfa_txpowertrackingindex > 0) { priv->rfa_txpowertrackingindex--; - if(priv->rfa_txpowertrackingindex_real > 4) - { + if (priv->rfa_txpowertrackingindex_real > 4) { priv->rfa_txpowertrackingindex_real--; rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); } } - } - else - { - if (priv->rfa_txpowertrackingindex < 36) - { + } else { + if (priv->rfa_txpowertrackingindex < 36) { priv->rfa_txpowertrackingindex++; priv->rfa_txpowertrackingindex_real++; rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); @@ -683,52 +615,44 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) priv->cck_present_attentuation_difference = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default; - if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) priv->cck_present_attentuation - = priv->cck_present_attentuation_20Mdefault + priv->cck_present_attentuation_difference; + = priv->cck_present_attentuation_20Mdefault + priv->cck_present_attentuation_difference; else priv->cck_present_attentuation - = priv->cck_present_attentuation_40Mdefault + priv->cck_present_attentuation_difference; + = priv->cck_present_attentuation_40Mdefault + priv->cck_present_attentuation_difference; - if(priv->cck_present_attentuation > -1&&priv->cck_present_attentuation <23) - { - if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) - { + if (priv->cck_present_attentuation > -1 && priv->cck_present_attentuation < 23) { + if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) { priv->bcck_in_ch14 = TRUE; - dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); - } - else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) - { + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) { priv->bcck_in_ch14 = FALSE; - dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); - } - else - dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } else + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); - - if (priv->cck_present_attentuation_difference <= -12||priv->cck_present_attentuation_difference >= 24) - { - priv->ieee80211->bdynamic_txpower_enable = TRUE; - write_nic_byte(dev, 0x1ba, 0); - RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n"); - return; - } + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); + if (priv->cck_present_attentuation_difference <= -12 || priv->cck_present_attentuation_difference >= 24) { + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); + RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n"); + return; + } + write_nic_byte(dev, 0x1ba, 0); + Avg_TSSI_Meas_from_driver = 0; + for (k = 0; k < 5; k++) + tmp_report[k] = 0; + break; + } } - write_nic_byte(dev, 0x1ba, 0); - Avg_TSSI_Meas_from_driver = 0; - for(k = 0;k < 5; k++) - tmp_report[k] = 0; - break; - } -} - priv->ieee80211->bdynamic_txpower_enable = TRUE; - write_nic_byte(dev, 0x1ba, 0); + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); } static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) @@ -737,107 +661,96 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) struct r8192_priv *priv = ieee80211_priv(dev); u32 tmpRegA, TempCCk; u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval; - int i =0, CCKSwingNeedUpdate=0; - - if(!priv->btxpower_trackingInit) - { - //Query OFDM default setting - tmpRegA= rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord); - for(i=0; i<OFDM_Table_Length; i++) //find the index - { - if(tmpRegA == OFDMSwingTable[i]) - { - priv->OFDM_index= (u8)i; + int i = 0, CCKSwingNeedUpdate = 0; + + if (!priv->btxpower_trackingInit) { + /* Query OFDM default setting */ + tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord); + for (i = 0; i < OFDM_Table_Length; i++) { /* find the index */ + if (tmpRegA == OFDMSwingTable[i]) { + priv->OFDM_index = (u8)i; RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index=0x%x\n", rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index); } } - //Query CCK default setting From 0xa22 + /* Query CCK default setting From 0xa22 */ TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2); - for(i=0 ; i<CCK_Table_length ; i++) - { - if(TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) - { - priv->CCK_index =(u8) i; + for (i = 0; i < CCK_Table_length; i++) { + if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) { + priv->CCK_index = (u8) i; RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, CCK_index=0x%x\n", rCCK0_TxFilter1, TempCCk, priv->CCK_index); break; } } priv->btxpower_trackingInit = TRUE; - //pHalData->TXPowercount = 0; + /*pHalData->TXPowercount = 0;*/ return; } - //========================== - // this is only for test, should be masked - //========================== - - // read and filter out unreasonable value - tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078); // 0x12: RF Reg[10:7] - RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA); - if(tmpRegA < 3 || tmpRegA > 13) + /* + * ========================== + * this is only for test, should be masked + * ========================== + */ + + /* read and filter out unreasonable value */ + tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078); /* 0x12: RF Reg[10:7] */ + RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA); + if (tmpRegA < 3 || tmpRegA > 13) return; - if(tmpRegA >= 12) // if over 12, TP will be bad when high temperature + if (tmpRegA >= 12) /* if over 12, TP will be bad when high temperature */ tmpRegA = 12; - RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA); - priv->ThermalMeter[0] = ThermalMeterVal; //We use fixed value by Bryant's suggestion - priv->ThermalMeter[1] = ThermalMeterVal; //We use fixed value by Bryant's suggestion + RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d\n", tmpRegA); + priv->ThermalMeter[0] = ThermalMeterVal; /* We use fixed value by Bryant's suggestion */ + priv->ThermalMeter[1] = ThermalMeterVal; /* We use fixed value by Bryant's suggestion */ - //Get current RF-A temperature index - if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temperature - { + /* Get current RF-A temperature index */ + if (priv->ThermalMeter[0] >= (u8)tmpRegA) { /* lower temperature */ tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA); tmpCCK40Mindex = tmpCCK20Mindex - 6; - if(tmpOFDMindex >= OFDM_Table_Length) + if (tmpOFDMindex >= OFDM_Table_Length) tmpOFDMindex = OFDM_Table_Length-1; - if(tmpCCK20Mindex >= CCK_Table_length) + if (tmpCCK20Mindex >= CCK_Table_length) tmpCCK20Mindex = CCK_Table_length-1; - if(tmpCCK40Mindex >= CCK_Table_length) + if (tmpCCK40Mindex >= CCK_Table_length) tmpCCK40Mindex = CCK_Table_length-1; - } - else - { + } else { tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]); - if(tmpval >= 6) // higher temperature - tmpOFDMindex = tmpCCK20Mindex = 0; // max to +6dB + + if (tmpval >= 6) /* higher temperature */ + tmpOFDMindex = tmpCCK20Mindex = 0; /* max to +6dB */ else tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval; tmpCCK40Mindex = 0; } - //DbgPrint("%ddb, tmpOFDMindex = %d, tmpCCK20Mindex = %d, tmpCCK40Mindex = %d", - //((u1Byte)tmpRegA - pHalData->ThermalMeter[0]), - //tmpOFDMindex, tmpCCK20Mindex, tmpCCK40Mindex); - if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) //40M + /*DbgPrint("%ddb, tmpOFDMindex = %d, tmpCCK20Mindex = %d, tmpCCK40Mindex = %d", + ((u1Byte)tmpRegA - pHalData->ThermalMeter[0]), + tmpOFDMindex, tmpCCK20Mindex, tmpCCK40Mindex);*/ + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) /* 40M */ tmpCCKindex = tmpCCK40Mindex; else tmpCCKindex = tmpCCK20Mindex; - if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) - { + if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) { priv->bcck_in_ch14 = TRUE; CCKSwingNeedUpdate = 1; - } - else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) - { + } else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) { priv->bcck_in_ch14 = FALSE; CCKSwingNeedUpdate = 1; } - if(priv->CCK_index != tmpCCKindex) - { + if (priv->CCK_index != tmpCCKindex) { priv->CCK_index = tmpCCKindex; CCKSwingNeedUpdate = 1; } - if(CCKSwingNeedUpdate) - { - //DbgPrint("Update CCK Swing, CCK_index = %d\n", pHalData->CCK_index); + if (CCKSwingNeedUpdate) { + /*DbgPrint("Update CCK Swing, CCK_index = %d\n", pHalData->CCK_index);*/ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } - if(priv->OFDM_index != tmpOFDMindex) - { + if (priv->OFDM_index != tmpOFDMindex) { priv->OFDM_index = tmpOFDMindex; rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]); RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n", @@ -848,100 +761,100 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) void dm_txpower_trackingcallback(struct work_struct *work) { - struct delayed_work *dwork = container_of(work,struct delayed_work,work); - struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq); - struct net_device *dev = priv->ieee80211->dev; + struct delayed_work *dwork = container_of(work, struct delayed_work, work); + struct r8192_priv *priv = container_of(dwork, struct r8192_priv, txpower_tracking_wq); + struct net_device *dev = priv->ieee80211->dev; - if(priv->bDcut == TRUE) + if (priv->bDcut == TRUE) dm_TXPowerTrackingCallback_TSSI(dev); else dm_TXPowerTrackingCallback_ThermalMeter(dev); } - static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv(dev); - //Initial the Tx BB index and mapping value + /* Initial the Tx BB index and mapping value */ priv->txbbgain_table[0].txbb_iq_amplifygain = 12; - priv->txbbgain_table[0].txbbgain_value=0x7f8001fe; + priv->txbbgain_table[0].txbbgain_value = 0x7f8001fe; priv->txbbgain_table[1].txbb_iq_amplifygain = 11; - priv->txbbgain_table[1].txbbgain_value=0x788001e2; + priv->txbbgain_table[1].txbbgain_value = 0x788001e2; priv->txbbgain_table[2].txbb_iq_amplifygain = 10; - priv->txbbgain_table[2].txbbgain_value=0x71c001c7; + priv->txbbgain_table[2].txbbgain_value = 0x71c001c7; priv->txbbgain_table[3].txbb_iq_amplifygain = 9; - priv->txbbgain_table[3].txbbgain_value=0x6b8001ae; + priv->txbbgain_table[3].txbbgain_value = 0x6b8001ae; priv->txbbgain_table[4].txbb_iq_amplifygain = 8; - priv->txbbgain_table[4].txbbgain_value=0x65400195; + priv->txbbgain_table[4].txbbgain_value = 0x65400195; priv->txbbgain_table[5].txbb_iq_amplifygain = 7; - priv->txbbgain_table[5].txbbgain_value=0x5fc0017f; + priv->txbbgain_table[5].txbbgain_value = 0x5fc0017f; priv->txbbgain_table[6].txbb_iq_amplifygain = 6; - priv->txbbgain_table[6].txbbgain_value=0x5a400169; + priv->txbbgain_table[6].txbbgain_value = 0x5a400169; priv->txbbgain_table[7].txbb_iq_amplifygain = 5; - priv->txbbgain_table[7].txbbgain_value=0x55400155; + priv->txbbgain_table[7].txbbgain_value = 0x55400155; priv->txbbgain_table[8].txbb_iq_amplifygain = 4; - priv->txbbgain_table[8].txbbgain_value=0x50800142; + priv->txbbgain_table[8].txbbgain_value = 0x50800142; priv->txbbgain_table[9].txbb_iq_amplifygain = 3; - priv->txbbgain_table[9].txbbgain_value=0x4c000130; + priv->txbbgain_table[9].txbbgain_value = 0x4c000130; priv->txbbgain_table[10].txbb_iq_amplifygain = 2; - priv->txbbgain_table[10].txbbgain_value=0x47c0011f; + priv->txbbgain_table[10].txbbgain_value = 0x47c0011f; priv->txbbgain_table[11].txbb_iq_amplifygain = 1; - priv->txbbgain_table[11].txbbgain_value=0x43c0010f; + priv->txbbgain_table[11].txbbgain_value = 0x43c0010f; priv->txbbgain_table[12].txbb_iq_amplifygain = 0; - priv->txbbgain_table[12].txbbgain_value=0x40000100; + priv->txbbgain_table[12].txbbgain_value = 0x40000100; priv->txbbgain_table[13].txbb_iq_amplifygain = -1; - priv->txbbgain_table[13].txbbgain_value=0x3c8000f2; + priv->txbbgain_table[13].txbbgain_value = 0x3c8000f2; priv->txbbgain_table[14].txbb_iq_amplifygain = -2; - priv->txbbgain_table[14].txbbgain_value=0x390000e4; + priv->txbbgain_table[14].txbbgain_value = 0x390000e4; priv->txbbgain_table[15].txbb_iq_amplifygain = -3; - priv->txbbgain_table[15].txbbgain_value=0x35c000d7; + priv->txbbgain_table[15].txbbgain_value = 0x35c000d7; priv->txbbgain_table[16].txbb_iq_amplifygain = -4; - priv->txbbgain_table[16].txbbgain_value=0x32c000cb; + priv->txbbgain_table[16].txbbgain_value = 0x32c000cb; priv->txbbgain_table[17].txbb_iq_amplifygain = -5; - priv->txbbgain_table[17].txbbgain_value=0x300000c0; + priv->txbbgain_table[17].txbbgain_value = 0x300000c0; priv->txbbgain_table[18].txbb_iq_amplifygain = -6; - priv->txbbgain_table[18].txbbgain_value=0x2d4000b5; + priv->txbbgain_table[18].txbbgain_value = 0x2d4000b5; priv->txbbgain_table[19].txbb_iq_amplifygain = -7; - priv->txbbgain_table[19].txbbgain_value=0x2ac000ab; + priv->txbbgain_table[19].txbbgain_value = 0x2ac000ab; priv->txbbgain_table[20].txbb_iq_amplifygain = -8; - priv->txbbgain_table[20].txbbgain_value=0x288000a2; + priv->txbbgain_table[20].txbbgain_value = 0x288000a2; priv->txbbgain_table[21].txbb_iq_amplifygain = -9; - priv->txbbgain_table[21].txbbgain_value=0x26000098; + priv->txbbgain_table[21].txbbgain_value = 0x26000098; priv->txbbgain_table[22].txbb_iq_amplifygain = -10; - priv->txbbgain_table[22].txbbgain_value=0x24000090; + priv->txbbgain_table[22].txbbgain_value = 0x24000090; priv->txbbgain_table[23].txbb_iq_amplifygain = -11; - priv->txbbgain_table[23].txbbgain_value=0x22000088; + priv->txbbgain_table[23].txbbgain_value = 0x22000088; priv->txbbgain_table[24].txbb_iq_amplifygain = -12; - priv->txbbgain_table[24].txbbgain_value=0x20000080; + priv->txbbgain_table[24].txbbgain_value = 0x20000080; priv->txbbgain_table[25].txbb_iq_amplifygain = -13; - priv->txbbgain_table[25].txbbgain_value=0x1a00006c; + priv->txbbgain_table[25].txbbgain_value = 0x1a00006c; priv->txbbgain_table[26].txbb_iq_amplifygain = -14; - priv->txbbgain_table[26].txbbgain_value=0x1c800072; + priv->txbbgain_table[26].txbbgain_value = 0x1c800072; priv->txbbgain_table[27].txbb_iq_amplifygain = -15; - priv->txbbgain_table[27].txbbgain_value=0x18000060; + priv->txbbgain_table[27].txbbgain_value = 0x18000060; priv->txbbgain_table[28].txbb_iq_amplifygain = -16; - priv->txbbgain_table[28].txbbgain_value=0x19800066; + priv->txbbgain_table[28].txbbgain_value = 0x19800066; priv->txbbgain_table[29].txbb_iq_amplifygain = -17; - priv->txbbgain_table[29].txbbgain_value=0x15800056; + priv->txbbgain_table[29].txbbgain_value = 0x15800056; priv->txbbgain_table[30].txbb_iq_amplifygain = -18; - priv->txbbgain_table[30].txbbgain_value=0x26c0005b; + priv->txbbgain_table[30].txbbgain_value = 0x26c0005b; priv->txbbgain_table[31].txbb_iq_amplifygain = -19; - priv->txbbgain_table[31].txbbgain_value=0x14400051; + priv->txbbgain_table[31].txbbgain_value = 0x14400051; priv->txbbgain_table[32].txbb_iq_amplifygain = -20; - priv->txbbgain_table[32].txbbgain_value=0x24400051; + priv->txbbgain_table[32].txbbgain_value = 0x24400051; priv->txbbgain_table[33].txbb_iq_amplifygain = -21; - priv->txbbgain_table[33].txbbgain_value=0x1300004c; + priv->txbbgain_table[33].txbbgain_value = 0x1300004c; priv->txbbgain_table[34].txbb_iq_amplifygain = -22; - priv->txbbgain_table[34].txbbgain_value=0x12000048; + priv->txbbgain_table[34].txbbgain_value = 0x12000048; priv->txbbgain_table[35].txbb_iq_amplifygain = -23; - priv->txbbgain_table[35].txbbgain_value=0x11000044; + priv->txbbgain_table[35].txbbgain_value = 0x11000044; priv->txbbgain_table[36].txbb_iq_amplifygain = -24; - priv->txbbgain_table[36].txbbgain_value=0x10000040; + priv->txbbgain_table[36].txbbgain_value = 0x10000040; - //ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 - //This Table is for CH1~CH13 + /* + * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 + * This Table is for CH1~CH13 + */ priv->cck_txbbgain_table[0].ccktxbb_valuearray[0] = 0x36; priv->cck_txbbgain_table[0].ccktxbb_valuearray[1] = 0x35; priv->cck_txbbgain_table[0].ccktxbb_valuearray[2] = 0x2e; @@ -1149,8 +1062,10 @@ static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev) priv->cck_txbbgain_table[22].ccktxbb_valuearray[6] = 0x03; priv->cck_txbbgain_table[22].ccktxbb_valuearray[7] = 0x01; - //ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 - //This Table is for CH14 + /* + * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 + * This Table is for CH14 + */ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[0] = 0x36; priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[1] = 0x35; priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[2] = 0x2e; @@ -1368,10 +1283,12 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - // Tx Power tracking by Thermal Meter requires Firmware R/W 3-wire. This mechanism - // can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w - // 3-wire by driver causes RF to go into a wrong state. - if(priv->ieee80211->FwRWRF) + /* + * Tx Power tracking by Thermal Meter requires Firmware R/W 3-wire. This mechanism + * can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w + * 3-wire by driver causes RF to go into a wrong state. + */ + if (priv->ieee80211->FwRWRF) priv->btxpower_tracking = TRUE; else priv->btxpower_tracking = FALSE; @@ -1379,57 +1296,46 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev) priv->btxpower_trackingInit = FALSE; } - void dm_initialize_txpower_tracking(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - if(priv->bDcut == TRUE) + + if (priv->bDcut == TRUE) dm_InitializeTXPowerTracking_TSSI(dev); else dm_InitializeTXPowerTracking_ThermalMeter(dev); -}// dm_InitializeTXPowerTracking - +} /* dm_InitializeTXPowerTracking */ static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); static u32 tx_power_track_counter; - if(!priv->btxpower_tracking) + if (!priv->btxpower_tracking) return; - else - { - if((tx_power_track_counter % 30 == 0)&&(tx_power_track_counter != 0)) - { - queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0); - } - tx_power_track_counter++; - } - + if ((tx_power_track_counter % 30 == 0) && (tx_power_track_counter != 0)) + queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); + tx_power_track_counter++; } - static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); static u8 TM_Trigger; - //DbgPrint("dm_CheckTXPowerTracking() \n"); - if(!priv->btxpower_tracking) + /*DbgPrint("dm_CheckTXPowerTracking()\n");*/ + if (!priv->btxpower_tracking) + return; + if (priv->txpower_count <= 2) { + priv->txpower_count++; return; - else - { - if(priv->txpower_count <= 2) - { - priv->txpower_count++; - return; - } } - if(!TM_Trigger) - { - //Attention!! You have to write all 12bits of data to RF, or it may cause RF to crash - //actually write reg0x02 bit1=0, then bit1=1. - //DbgPrint("Trigger ThermalMeter, write RF reg0x2 = 0x4d to 0x4f\n"); + if (!TM_Trigger) { + /* + * Attention!! You have to write all 12bits of data to RF, or it may cause RF to crash + * actually write reg0x02 bit1=0, then bit1=1. + * DbgPrint("Trigger ThermalMeter, write RF reg0x2 = 0x4d to 0x4f\n"); + */ rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); @@ -1437,93 +1343,84 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) TM_Trigger = 1; return; } - else - { - //DbgPrint("Schedule TxPowerTrackingWorkItem\n"); - queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0); - TM_Trigger = 0; - } + /*DbgPrint("Schedule TxPowerTrackingWorkItem\n");*/ + queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); + TM_Trigger = 0; } - static void dm_check_txpower_tracking(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - //static u32 tx_power_track_counter = 0; + /*static u32 tx_power_track_counter = 0;*/ -#ifdef RTL8190P +#ifdef RTL8190P dm_CheckTXPowerTracking_TSSI(dev); #else - if(priv->bDcut == TRUE) + if (priv->bDcut == TRUE) dm_CheckTXPowerTracking_TSSI(dev); else dm_CheckTXPowerTracking_ThermalMeter(dev); #endif -} // dm_CheckTXPowerTracking - +} /* dm_CheckTXPowerTracking */ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14) { u32 TempVal; struct r8192_priv *priv = ieee80211_priv(dev); - //Write 0xa22 0xa23 + + /* Write 0xa22 0xa23 */ TempVal = 0; - if(!bInCH14){ - //Write 0xa22 0xa23 + if (!bInCH14) { + /* Write 0xa22 0xa23 */ TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[0] + - (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8) ; + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8); rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); - //Write 0xa24 ~ 0xa27 + /* Write 0xa24 ~ 0xa27 */ TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[2] + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[3]<<8) + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[4]<<16)+ (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[5]<<24); rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); - //Write 0xa28 0xa29 + /* Write 0xa28 0xa29 */ TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] + - (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8) ; + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8); rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); - } - else - { + } else { TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[0] + - (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8) ; + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8); rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); - //Write 0xa24 ~ 0xa27 + /* Write 0xa24 ~ 0xa27 */ TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[2] + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[3]<<8) + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[4]<<16)+ (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[5]<<24); rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); - //Write 0xa28 0xa29 + /* Write 0xa28 0xa29 */ TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] + - (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8) ; + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8); rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); } - - } -static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH14) +static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH14) { u32 TempVal; struct r8192_priv *priv = ieee80211_priv(dev); TempVal = 0; - if(!bInCH14) - { - //Write 0xa22 0xa23 + if (!bInCH14) { + /* Write 0xa22 0xa23 */ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] + - (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ; + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8); rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter1, TempVal); - //Write 0xa24 ~ 0xa27 + /* Write 0xa24 ~ 0xa27 */ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16)+ @@ -1531,25 +1428,23 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter2, TempVal); - //Write 0xa28 0xa29 + /* Write 0xa28 0xa29 */ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] + - (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ; + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8); rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_DebugPort, TempVal); - } - else - { -// priv->CCKTxPowerAdjustCntNotCh14++; //cosa add for debug. - //Write 0xa22 0xa23 + } else { + /*priv->CCKTxPowerAdjustCntNotCh14++; cosa add for debug.*/ + /* Write 0xa22 0xa23 */ TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] + - (CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ; + (CCKSwingTable_Ch14[priv->CCK_index][1]<<8); rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter1, TempVal); - //Write 0xa24 ~ 0xa27 + /* Write 0xa24 ~ 0xa27 */ TempVal = CCKSwingTable_Ch14[priv->CCK_index][2] + (CCKSwingTable_Ch14[priv->CCK_index][3]<<8) + (CCKSwingTable_Ch14[priv->CCK_index][4]<<16)+ @@ -1557,9 +1452,9 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter2, TempVal); - //Write 0xa28 0xa29 + /* Write 0xa28 0xa29 */ TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] + - (CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ; + (CCKSwingTable_Ch14[priv->CCK_index][7]<<8); rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", @@ -1567,20 +1462,17 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH } } - - void dm_cck_txpower_adjust(struct net_device *dev, bool binch14) -{ // dm_CCKTxPowerAdjust - +{ /* dm_CCKTxPowerAdjust */ struct r8192_priv *priv = ieee80211_priv(dev); - if(priv->bDcut == TRUE) + + if (priv->bDcut == TRUE) dm_CCKTxPowerAdjust_TSSI(dev, binch14); else dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14); } - -#ifndef RTL8192U +#ifndef RTL8192U static void dm_txpower_reset_recovery( struct net_device *dev ) @@ -1589,75 +1481,71 @@ static void dm_txpower_reset_recovery( RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n"); rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n",priv->rfa_txpowertrackingindex); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n",priv->cck_present_attentuation); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n", priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n", priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n", priv->cck_present_attentuation); dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n",priv->rfc_txpowertrackingindex); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n", priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n", priv->rfc_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n", priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain); -} // dm_TXPowerResetRecovery +} /* dm_TXPowerResetRecovery */ void dm_restore_dynamic_mechanism_state(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); u32 reg_ratr = priv->rate_adaptive.last_ratr; - if(!priv->up) - { + if (!priv->up) { RT_TRACE(COMP_RATE, "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n"); return; } - // - // Restore previous state for rate adaptive - // - if(priv->rate_adaptive.rate_adaptive_disabled) + /* Restore previous state for rate adaptive */ + if (priv->rate_adaptive.rate_adaptive_disabled) return; - // TODO: Only 11n mode is implemented currently, - if(!(priv->ieee80211->mode==WIRELESS_MODE_N_24G || - priv->ieee80211->mode==WIRELESS_MODE_N_5G)) - return; + /* TODO: Only 11n mode is implemented currently, */ + if (!(priv->ieee80211->mode == WIRELESS_MODE_N_24G || + priv->ieee80211->mode == WIRELESS_MODE_N_5G)) + return; + { /* 2007/11/15 MH Copy from 8190PCI. */ u32 ratr_value; + ratr_value = reg_ratr; - if(priv->rf_type == RF_1T2R) // 1T2R, Spatial Stream 2 should be disabled - { + if (priv->rf_type == RF_1T2R) { /* 1T2R, Spatial Stream 2 should be disabled */ ratr_value &= ~(RATE_ALL_OFDM_2SS); - //DbgPrint("HW_VAR_TATR_0 from 0x%x ==> 0x%x\n", ((pu4Byte)(val))[0], ratr_value); + /*DbgPrint("HW_VAR_TATR_0 from 0x%x ==> 0x%x\n", ((pu4Byte)(val))[0], ratr_value);*/ } - //DbgPrint("set HW_VAR_TATR_0 = 0x%x\n", ratr_value); - //cosa PlatformEFIOWrite4Byte(Adapter, RATR0, ((pu4Byte)(val))[0]); + /*DbgPrint("set HW_VAR_TATR_0 = 0x%x\n", ratr_value);*/ + /*cosa PlatformEFIOWrite4Byte(Adapter, RATR0, ((pu4Byte)(val))[0]);*/ write_nic_dword(dev, RATR0, ratr_value); write_nic_byte(dev, UFWP, 1); } - //Restore TX Power Tracking Index + /* Restore TX Power Tracking Index */ if (priv->btxpower_trackingInit && priv->btxpower_tracking) dm_txpower_reset_recovery(dev); - // - //Restore BB Initial Gain - // + /* Restore BB Initial Gain */ dm_bb_initialgain_restore(dev); -} // DM_RestoreDynamicMechanismState +} /* DM_RestoreDynamicMechanismState */ static void dm_bb_initialgain_restore(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - u32 bit_mask = 0x7f; //Bit0~ Bit6 + u32 bit_mask = 0x7f; /* Bit0~ Bit6 */ - if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) return; - //Disable Initial Gain - //PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800); - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + /* Disable Initial Gain */ + /*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800);*/ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); /* Only clear byte 1 and rewrite. */ rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask, (u32)priv->initgain_backup.xaagccore1); rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask, (u32)priv->initgain_backup.xbagccore1); rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask, (u32)priv->initgain_backup.xcagccore1); @@ -1665,41 +1553,39 @@ static void dm_bb_initialgain_restore(struct net_device *dev) bit_mask = bMaskByte2; rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask, (u32)priv->initgain_backup.cca); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n",priv->initgain_backup.xaagccore1); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n",priv->initgain_backup.xbagccore1); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n",priv->initgain_backup.xcagccore1); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca); - //Enable Initial Gain - //PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x100); - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite. - -} // dm_BBInitialGainRestore + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n", priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n", priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n", priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n", priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n", priv->initgain_backup.cca); + /* Enable Initial Gain */ + /*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x100);*/ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); /* Only clear byte 1 and rewrite. */ +} /* dm_BBInitialGainRestore */ void dm_backup_dynamic_mechanism_state(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - // Fsync to avoid reset + /* Fsync to avoid reset */ priv->bswitch_fsync = false; priv->bfsync_processing = false; - //Backup BB InitialGain + /* Backup BB InitialGain */ dm_bb_initialgain_backup(dev); -} // DM_BackupDynamicMechanismState - +} /* DM_BackupDynamicMechanismState */ static void dm_bb_initialgain_backup(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - u32 bit_mask = bMaskByte0; //Bit0~ Bit6 + u32 bit_mask = bMaskByte0; /* Bit0~ Bit6 */ - if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) return; - //PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800); - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + /*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800);*/ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); /* Only clear byte 1 and rewrite. */ priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask); priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask); priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask); @@ -1707,13 +1593,13 @@ static void dm_bb_initialgain_backup(struct net_device *dev) bit_mask = bMaskByte2; priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n",priv->initgain_backup.xaagccore1); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n",priv->initgain_backup.xbagccore1); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n",priv->initgain_backup.xcagccore1); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n",priv->initgain_backup.xdagccore1); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n", priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n", priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n", priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n", priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n", priv->initgain_backup.cca); -} // dm_BBInitialGainBakcup +} /* dm_BBInitialGainBakcup */ #endif /*----------------------------------------------------------------------------- @@ -1736,67 +1622,44 @@ static void dm_bb_initialgain_backup(struct net_device *dev) void dm_change_dynamic_initgain_thresh(struct net_device *dev, u32 dm_type, u32 dm_value) { - if (dm_type == DIG_TYPE_THRESH_HIGH) - { + if (dm_type == DIG_TYPE_THRESH_HIGH) { dm_digtable.rssi_high_thresh = dm_value; - } - else if (dm_type == DIG_TYPE_THRESH_LOW) - { + } else if (dm_type == DIG_TYPE_THRESH_LOW) { dm_digtable.rssi_low_thresh = dm_value; - } - else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) - { + } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) { dm_digtable.rssi_high_power_highthresh = dm_value; - } - else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) - { + } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) { dm_digtable.rssi_high_power_highthresh = dm_value; - } - else if (dm_type == DIG_TYPE_ENABLE) - { + } else if (dm_type == DIG_TYPE_ENABLE) { dm_digtable.dig_state = DM_STA_DIG_MAX; dm_digtable.dig_enable_flag = true; - } - else if (dm_type == DIG_TYPE_DISABLE) - { + } else if (dm_type == DIG_TYPE_DISABLE) { dm_digtable.dig_state = DM_STA_DIG_MAX; dm_digtable.dig_enable_flag = false; - } - else if (dm_type == DIG_TYPE_DBG_MODE) - { - if(dm_value >= DM_DBG_MAX) + } else if (dm_type == DIG_TYPE_DBG_MODE) { + if (dm_value >= DM_DBG_MAX) dm_value = DM_DBG_OFF; dm_digtable.dbg_mode = (u8)dm_value; - } - else if (dm_type == DIG_TYPE_RSSI) - { - if(dm_value > 100) + } else if (dm_type == DIG_TYPE_RSSI) { + if (dm_value > 100) dm_value = 30; dm_digtable.rssi_val = (long)dm_value; - } - else if (dm_type == DIG_TYPE_ALGORITHM) - { + } else if (dm_type == DIG_TYPE_ALGORITHM) { if (dm_value >= DIG_ALGO_MAX) dm_value = DIG_ALGO_BY_FALSE_ALARM; - if(dm_digtable.dig_algorithm != (u8)dm_value) + if (dm_digtable.dig_algorithm != (u8)dm_value) dm_digtable.dig_algorithm_switch = 1; dm_digtable.dig_algorithm = (u8)dm_value; - } - else if (dm_type == DIG_TYPE_BACKOFF) - { - if(dm_value > 30) + } else if (dm_type == DIG_TYPE_BACKOFF) { + if (dm_value > 30) dm_value = 30; dm_digtable.backoff_val = (u8)dm_value; - } - else if(dm_type == DIG_TYPE_RX_GAIN_MIN) - { - if(dm_value == 0) + } else if (dm_type == DIG_TYPE_RX_GAIN_MIN) { + if (dm_value == 0) dm_value = 0x1; dm_digtable.rx_gain_range_min = (u8)dm_value; - } - else if(dm_type == DIG_TYPE_RX_GAIN_MAX) - { - if(dm_value > 0x50) + } else if (dm_type == DIG_TYPE_RX_GAIN_MAX) { + if (dm_value > 0x50) dm_value = 0x50; dm_digtable.rx_gain_range_max = (u8)dm_value; } @@ -1824,7 +1687,7 @@ static void dm_dig_init(struct net_device *dev) /* 2007/10/05 MH Disable DIG scheme now. Not tested. */ dm_digtable.dig_enable_flag = true; dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI; - dm_digtable.dbg_mode = DM_DBG_OFF; //off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig + dm_digtable.dbg_mode = DM_DBG_OFF; /* off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig */ dm_digtable.dig_algorithm_switch = 0; /* 2007/10/04 MH Define init gain threshold. */ @@ -1838,17 +1701,16 @@ static void dm_dig_init(struct net_device *dev) dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; - dm_digtable.rssi_val = 50; //for new dig debug rssi value + dm_digtable.rssi_val = 50; /* for new dig debug rssi value */ dm_digtable.backoff_val = DM_DIG_BACKOFF; dm_digtable.rx_gain_range_max = DM_DIG_MAX; - if(priv->CustomerID == RT_CID_819x_Netcore) + if (priv->CustomerID == RT_CID_819x_Netcore) dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore; else dm_digtable.rx_gain_range_min = DM_DIG_MIN; } /* dm_dig_init */ - /*----------------------------------------------------------------------------- * Function: dm_ctrl_initgain_byrssi() * @@ -1868,20 +1730,18 @@ static void dm_dig_init(struct net_device *dev) *---------------------------------------------------------------------------*/ static void dm_ctrl_initgain_byrssi(struct net_device *dev) { - if (dm_digtable.dig_enable_flag == false) return; - if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) + if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev); - else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + else if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) dm_ctrl_initgain_byrssi_by_driverrssi(dev); -// ; + /* ; */ else return; } - static void dm_ctrl_initgain_byrssi_by_driverrssi( struct net_device *dev) { @@ -1892,32 +1752,33 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi( if (dm_digtable.dig_enable_flag == false) return; - //DbgPrint("Dig by Sw Rssi \n"); - if(dm_digtable.dig_algorithm_switch) // if switched algorithm, we have to disable FW Dig. + /*DbgPrint("Dig by Sw Rssi\n");*/ + if (dm_digtable.dig_algorithm_switch) /* if switched algorithm, we have to disable FW Dig. */ fw_dig = 0; - if(fw_dig <= 3) // execute several times to make sure the FW Dig is disabled - {// FW DIG Off - for(i=0; i<3; i++) - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + + if (fw_dig <= 3) { /* execute several times to make sure the FW Dig is disabled */ + /* FW DIG Off */ + for (i = 0; i < 3; i++) + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); /* Only clear byte 1 and rewrite. */ fw_dig++; - dm_digtable.dig_state = DM_STA_DIG_OFF; //fw dig off. + dm_digtable.dig_state = DM_STA_DIG_OFF; /* fw dig off. */ } - if(priv->ieee80211->state == IEEE80211_LINKED) + if (priv->ieee80211->state == IEEE80211_LINKED) dm_digtable.cur_connect_state = DIG_CONNECT; else dm_digtable.cur_connect_state = DIG_DISCONNECT; - //DbgPrint("DM_DigTable.PreConnectState = %d, DM_DigTable.CurConnectState = %d \n", - //DM_DigTable.PreConnectState, DM_DigTable.CurConnectState); + /*DbgPrint("DM_DigTable.PreConnectState = %d, DM_DigTable.CurConnectState = %d\n", + DM_DigTable.PreConnectState, DM_DigTable.CurConnectState);*/ - if(dm_digtable.dbg_mode == DM_DBG_OFF) + if (dm_digtable.dbg_mode == DM_DBG_OFF) dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb; - //DbgPrint("DM_DigTable.Rssi_val = %d \n", DM_DigTable.Rssi_val); + /*DbgPrint("DM_DigTable.Rssi_val = %d\n", DM_DigTable.Rssi_val);*/ dm_initial_gain(dev); dm_pd_th(dev); dm_cs_ratio(dev); - if(dm_digtable.dig_algorithm_switch) + if (dm_digtable.dig_algorithm_switch) dm_digtable.dig_algorithm_switch = 0; dm_digtable.pre_connect_state = dm_digtable.cur_connect_state; @@ -1933,152 +1794,138 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( if (dm_digtable.dig_enable_flag == false) return; - if(dm_digtable.dig_algorithm_switch) - { + if (dm_digtable.dig_algorithm_switch) { dm_digtable.dig_state = DM_STA_DIG_MAX; - // Fw DIG On. - for(i=0; i<3; i++) - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite. + /* Fw DIG On. */ + for (i = 0; i < 3; i++) + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); /* Only clear byte 1 and rewrite.*/ dm_digtable.dig_algorithm_switch = 0; } if (priv->ieee80211->state != IEEE80211_LINKED) return; - // For smooth, we can not change DIG state. + /* For smooth, we can not change DIG state. */ if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) && (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh)) - { return; - } - //DbgPrint("Dig by Fw False Alarm\n"); - //if (DM_DigTable.Dig_State == DM_STA_DIG_OFF) + + /*DbgPrint("Dig by Fw False Alarm\n");*/ + /*if (DM_DigTable.Dig_State == DM_STA_DIG_OFF)*/ /*DbgPrint("DIG Check\n\r RSSI=%d LOW=%d HIGH=%d STATE=%d", pHalData->UndecoratedSmoothedPWDB, DM_DigTable.RssiLowThresh, DM_DigTable.RssiHighThresh, DM_DigTable.Dig_State);*/ /* 1. When RSSI decrease, We have to judge if it is smaller than a threshold and then execute the step below. */ - if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh)) - { + if (priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh) { /* 2008/02/05 MH When we execute silent reset, the DIG PHY parameters will be reset to init value. We must prevent the condition. */ if (dm_digtable.dig_state == DM_STA_DIG_OFF && - (priv->reset_count == reset_cnt)) - { + (priv->reset_count == reset_cnt)) { return; } - else - { - reset_cnt = priv->reset_count; - } + reset_cnt = priv->reset_count; - // If DIG is off, DIG high power state must reset. + /* If DIG is off, DIG high power state must reset. */ dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX; dm_digtable.dig_state = DM_STA_DIG_OFF; - // 1.1 DIG Off. - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + /* 1.1 DIG Off. */ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); /* Only clear byte 1 and rewrite. */ - // 1.2 Set initial gain. + /* 1.2 Set initial gain. */ write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17); write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17); write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17); write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17); - // 1.3 Lower PD_TH for OFDM. - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { - /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ - // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + /* 1.3 Lower PD_TH for OFDM. */ + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { + /* + * 2008/01/11 MH 40MHZ 90/92 register are not the same. + * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + */ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(pAdapter, rOFDM0_RxDetector1, 0x40); + else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) + else + PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x40); */ - //else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) - - - //else - //PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x40); - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); - // 1.4 Lower CS ratio for CCK. + /* 1.4 Lower CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0x08); - // 1.5 Higher EDCCA. - //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325); + /* 1.5 Higher EDCCA. */ + /*PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325);*/ return; } /* 2. When RSSI increase, We have to judge if it is larger than a threshold and then execute the step below. */ - if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)) - { + if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) { u8 reset_flag = 0; if (dm_digtable.dig_state == DM_STA_DIG_ON && - (priv->reset_count == reset_cnt)) - { + (priv->reset_count == reset_cnt)) { dm_ctrl_initgain_byrssi_highpwr(dev); return; } - else - { - if (priv->reset_count != reset_cnt) - reset_flag = 1; + if (priv->reset_count != reset_cnt) + reset_flag = 1; - reset_cnt = priv->reset_count; - } + reset_cnt = priv->reset_count; dm_digtable.dig_state = DM_STA_DIG_ON; - //DbgPrint("DIG ON\n\r"); + /*DbgPrint("DIG ON\n\r");*/ - // 2.1 Set initial gain. - // 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment. - if (reset_flag == 1) - { + /* + * 2.1 Set initial gain. + * 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment. + */ + if (reset_flag == 1) { write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c); write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c); write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c); write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c); - } - else - { + } else { write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20); write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20); write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20); write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20); } - // 2.2 Higher PD_TH for OFDM. - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { - /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ - // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + /* 2.2 Higher PD_TH for OFDM. */ + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { + /* + * 2008/01/11 MH 40MHZ 90/92 register are not the same. + * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + */ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); /* else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) + else + PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x42); */ - //else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) - - //else - //PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x42); - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); - // 2.3 Higher CS ratio for CCK. + /* 2.3 Higher CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0xcd); - // 2.4 Lower EDCCA. - /* 2008/01/11 MH 90/92 series are the same. */ - //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346); + /* + * 2.4 Lower EDCCA. + * 2008/01/11 MH 90/92 series are the same. + */ + /*PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346);*/ - // 2.5 DIG On. - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite. + /* 2.5 DIG On. */ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); /* Only clear byte 1 and rewrite. */ } @@ -2086,7 +1933,6 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( } /* dm_CtrlInitGainByRssi */ - /*----------------------------------------------------------------------------- * Function: dm_ctrl_initgain_byrssi_highpwr() * @@ -2109,58 +1955,49 @@ static void dm_ctrl_initgain_byrssi_highpwr( struct r8192_priv *priv = ieee80211_priv(dev); static u32 reset_cnt_highpwr; - // For smooth, we can not change high power DIG state in the range. + /* For smooth, we can not change high power DIG state in the range. */ if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) && (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh)) - { return; - } - /* 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if - it is larger than a threshold and then execute the step below. */ - // 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue. - if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) - { + /* + * 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if + * it is larger than a threshold and then execute the step below. + * + * 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue. + */ + if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) { if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON && (priv->reset_count == reset_cnt_highpwr)) return; - else - dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; + dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; - // 3.1 Higher PD_TH for OFDM for high power state. - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + /* 3.1 Higher PD_TH for OFDM for high power state. */ + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); - } - else - { - if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF&& + } else { + if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF && (priv->reset_count == reset_cnt_highpwr)) return; - else - dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF; + dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF; if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh && - priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) - { - // 3.2 Recover PD_TH for OFDM for normal power region. - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) { + /* 3.2 Recover PD_TH for OFDM for normal power region. */ + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); } } @@ -2169,51 +2006,42 @@ static void dm_ctrl_initgain_byrssi_highpwr( } /* dm_CtrlInitGainByRssiHighPwr */ - static void dm_initial_gain( struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - u8 initial_gain=0; + u8 initial_gain = 0; static u8 initialized, force_write; static u32 reset_cnt; u8 tmp; - if(dm_digtable.dig_algorithm_switch) - { + if (dm_digtable.dig_algorithm_switch) { initialized = 0; reset_cnt = 0; } - if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) - { - if(dm_digtable.cur_connect_state == DIG_CONNECT) - { - if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max) + if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) { + if (dm_digtable.cur_connect_state == DIG_CONNECT) { + if ((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max) dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max; - else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min) + else if ((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min) dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min; else dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val; - } - else //current state is disconnected - { - if(dm_digtable.cur_ig_value == 0) + } else { /* current state is disconnected */ + if (dm_digtable.cur_ig_value == 0) dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; else dm_digtable.cur_ig_value = dm_digtable.pre_ig_value; } - } - else // disconnected -> connected or connected -> disconnected - { + } else { /* disconnected -> connected or connected -> disconnected */ dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; dm_digtable.pre_ig_value = 0; } - //DbgPrint("DM_DigTable.CurIGValue = 0x%x, DM_DigTable.PreIGValue = 0x%x\n", DM_DigTable.CurIGValue, DM_DigTable.PreIGValue); + /*DbgPrint("DM_DigTable.CurIGValue = 0x%x, DM_DigTable.PreIGValue = 0x%x\n", DM_DigTable.CurIGValue, DM_DigTable.PreIGValue);*/ - // if silent reset happened, we should rewrite the values back - if(priv->reset_count != reset_cnt) - { + /* if silent reset happened, we should rewrite the values back */ + if (priv->reset_count != reset_cnt) { force_write = 1; reset_cnt = priv->reset_count; } @@ -2223,12 +2051,11 @@ static void dm_initial_gain( force_write = 1; { - if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) - || !initialized || force_write) - { + if ((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) + || !initialized || force_write) { initial_gain = (u8)dm_digtable.cur_ig_value; - //DbgPrint("Write initial gain = 0x%x\n", initial_gain); - // Set initial gain. + /*DbgPrint("Write initial gain = 0x%x\n", initial_gain);*/ + /* Set initial gain. */ write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain); write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain); write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain); @@ -2247,93 +2074,77 @@ static void dm_pd_th( static u8 initialized, force_write; static u32 reset_cnt; - if(dm_digtable.dig_algorithm_switch) - { + if (dm_digtable.dig_algorithm_switch) { initialized = 0; reset_cnt = 0; } - if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) - { - if(dm_digtable.cur_connect_state == DIG_CONNECT) - { + if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) { + if (dm_digtable.cur_connect_state == DIG_CONNECT) { if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh) dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER; - else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) + else if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh) dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) && (dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh)) dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER; else dm_digtable.curpd_thstate = dm_digtable.prepd_thstate; - } - else - { + } else { dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; } - } - else // disconnected -> connected or connected -> disconnected - { + } else { /* disconnected -> connected or connected -> disconnected */ dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; } - // if silent reset happened, we should rewrite the values back - if(priv->reset_count != reset_cnt) - { + /* if silent reset happened, we should rewrite the values back */ + if (priv->reset_count != reset_cnt) { force_write = 1; reset_cnt = priv->reset_count; } { - if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) || - (initialized<=3) || force_write) - { - //DbgPrint("Write PD_TH state = %d\n", DM_DigTable.CurPD_THState); - if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) - { - // Lower PD_TH for OFDM. - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { - /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ - // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + if ((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) || + (initialized <= 3) || force_write) { + /*DbgPrint("Write PD_TH state = %d\n", DM_DigTable.CurPD_THState);*/ + if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) { + /* Lower PD_TH for OFDM. */ + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { + /* + * 2008/01/11 MH 40MHZ 90/92 register are not the same. + * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + */ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x40); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); - } - else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) - { - // Higher PD_TH for OFDM. - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { - /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ - // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + } else if (dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) { + /* Higher PD_TH for OFDM. */ + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { + /* + * 2008/01/11 MH 40MHZ 90/92 register are not the same. + * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + */ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); - } - else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) - { - // Higher PD_TH for OFDM for high power state. - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + } else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) { + /* Higher PD_TH for OFDM for high power state. */ + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); } dm_digtable.prepd_thstate = dm_digtable.curpd_thstate; - if(initialized <= 3) + if (initialized <= 3) initialized++; force_write = 0; } @@ -2347,54 +2158,40 @@ static void dm_cs_ratio( static u8 initialized, force_write; static u32 reset_cnt; - if(dm_digtable.dig_algorithm_switch) - { + if (dm_digtable.dig_algorithm_switch) { initialized = 0; reset_cnt = 0; } - if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) - { - if(dm_digtable.cur_connect_state == DIG_CONNECT) - { - if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) + if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) { + if (dm_digtable.cur_connect_state == DIG_CONNECT) { + if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh) dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; - else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh)) + else if (dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER; else dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state; - } - else - { + } else { dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; } - } - else // disconnected -> connected or connected -> disconnected - { + } else /* disconnected -> connected or connected -> disconnected */ dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; - } - // if silent reset happened, we should rewrite the values back - if(priv->reset_count != reset_cnt) - { + /* if silent reset happened, we should rewrite the values back */ + if (priv->reset_count != reset_cnt) { force_write = 1; reset_cnt = priv->reset_count; } - { - if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || - !initialized || force_write) - { - //DbgPrint("Write CS_ratio state = %d\n", DM_DigTable.CurCS_ratioState); - if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) - { - // Lower CS ratio for CCK. + if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || + !initialized || force_write) { + /*DbgPrint("Write CS_ratio state = %d\n", DM_DigTable.CurCS_ratioState);*/ + if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) { + /* Lower CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0x08); - } - else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) - { - // Higher CS ratio for CCK. + } else if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) { + /* Higher CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0xcd); } dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state; @@ -2411,53 +2208,46 @@ void dm_init_edca_turbo(struct net_device *dev) priv->bcurrent_turbo_EDCA = false; priv->ieee80211->bis_any_nonbepkts = false; priv->bis_cur_rdlstate = false; -} // dm_init_edca_turbo +} /* dm_init_edca_turbo */ static void dm_check_edca_turbo( struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; - //PSTA_QOS pStaQos = pMgntInfo->pStaQos; + /*PSTA_QOS pStaQos = pMgntInfo->pStaQos;*/ - // Keep past Tx/Rx packet count for RT-to-RT EDCA turbo. + /* Keep past Tx/Rx packet count for RT-to-RT EDCA turbo. */ static unsigned long lastTxOkCnt; static unsigned long lastRxOkCnt; unsigned long curTxOkCnt = 0; unsigned long curRxOkCnt = 0; - // - // Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters - // should follow the settings from QAP. By Bruce, 2007-12-07. - // - if(priv->ieee80211->state != IEEE80211_LINKED) + /* + * Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters + * should follow the settings from QAP. By Bruce, 2007-12-07. + */ + if (priv->ieee80211->state != IEEE80211_LINKED) goto dm_CheckEdcaTurbo_EXIT; - // We do not turn on EDCA turbo mode for some AP that has IOT issue - if(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO) + /* We do not turn on EDCA turbo mode for some AP that has IOT issue */ + if (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO) goto dm_CheckEdcaTurbo_EXIT; -// printk("========>%s():bis_any_nonbepkts is %d\n",__func__,priv->bis_any_nonbepkts); - // Check the status for current condition. - if(!priv->ieee80211->bis_any_nonbepkts) - { + /*printk("========>%s():bis_any_nonbepkts is %d\n", __func__, priv->bis_any_nonbepkts);*/ + /* Check the status for current condition. */ + if (!priv->ieee80211->bis_any_nonbepkts) { curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; - // For RT-AP, we needs to turn it on when Rx>Tx - if(curRxOkCnt > 4*curTxOkCnt) - { - //printk("%s():curRxOkCnt > 4*curTxOkCnt\n"); - if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) - { + /* For RT-AP, we needs to turn it on when Rx>Tx */ + if (curRxOkCnt > 4*curTxOkCnt) { + /*printk("%s():curRxOkCnt > 4*curTxOkCnt\n");*/ + if (!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]); priv->bis_cur_rdlstate = true; } - } - else - { - - //printk("%s():curRxOkCnt < 4*curTxOkCnt\n"); - if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) - { + } else { + /*printk("%s():curRxOkCnt < 4*curTxOkCnt\n");*/ + if (priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]); priv->bis_cur_rdlstate = false; } @@ -2465,50 +2255,47 @@ static void dm_check_edca_turbo( } priv->bcurrent_turbo_EDCA = true; - } - else - { - // - // Turn Off EDCA turbo here. - // Restore original EDCA according to the declaration of AP. - // - if(priv->bcurrent_turbo_EDCA) - { - + } else { + /* + * Turn Off EDCA turbo here. + * Restore original EDCA according to the declaration of AP. + */ + if (priv->bcurrent_turbo_EDCA) { { u8 u1bAIFS; u32 u4bAcParam; struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters; u8 mode = priv->ieee80211->mode; - // For Each time updating EDCA parameter, reset EDCA turbo mode status. + /* For Each time updating EDCA parameter, reset EDCA turbo mode status. */ dm_init_edca_turbo(dev); - u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; - u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)| - (((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)| - (((u32)(qos_parameters->cw_min[0]))<< AC_PARAM_ECW_MIN_OFFSET)| + u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime; + u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0])) << AC_PARAM_TXOP_LIMIT_OFFSET)| + (((u32)(qos_parameters->cw_max[0])) << AC_PARAM_ECW_MAX_OFFSET)| + (((u32)(qos_parameters->cw_min[0])) << AC_PARAM_ECW_MIN_OFFSET)| ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET)); - //write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam); + /*write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);*/ write_nic_dword(dev, EDCAPARA_BE, u4bAcParam); - // Check ACM bit. - // If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13. + /* + * Check ACM bit. + * If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13. + */ { - // TODO: Modified this part and try to set acm control in only 1 IO processing!! + /* TODO: Modified this part and try to set acm control in only 1 IO processing!! */ PACI_AIFSN pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]); u8 AcmCtrl; + read_nic_byte(dev, AcmHwCtrl, &AcmCtrl); - if(pAciAifsn->f.ACM) - { // ACM bit is 1. + + if (pAciAifsn->f.ACM) { /* ACM bit is 1. */ AcmCtrl |= AcmHw_BeqEn; - } - else - { // ACM bit is 0. + } else { /* ACM bit is 0. */ AcmCtrl &= (~AcmHw_BeqEn); } - RT_TRACE(COMP_QOS,"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl) ; + RT_TRACE(COMP_QOS, "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl); write_nic_byte(dev, AcmHwCtrl, AcmCtrl); } } @@ -2516,13 +2303,12 @@ static void dm_check_edca_turbo( } } - dm_CheckEdcaTurbo_EXIT: - // Set variables for next time. + /* Set variables for next time. */ priv->ieee80211->bis_any_nonbepkts = false; lastTxOkCnt = priv->stats.txbytesunicast; lastRxOkCnt = priv->stats.rxbytesunicast; -} // dm_CheckEdcaTurbo +} /* dm_CheckEdcaTurbo */ static void dm_init_ctstoself(struct net_device *dev) { @@ -2541,8 +2327,7 @@ static void dm_ctstoself(struct net_device *dev) unsigned long curTxOkCnt = 0; unsigned long curRxOkCnt = 0; - if(priv->ieee80211->bCTSToSelfEnable != TRUE) - { + if (priv->ieee80211->bCTSToSelfEnable != TRUE) { pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; return; } @@ -2552,17 +2337,13 @@ static void dm_ctstoself(struct net_device *dev) 3. <50 disable, >55 enable */ - if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) - { + if (pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) { curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; - if(curRxOkCnt > 4*curTxOkCnt) //downlink, disable CTS to self - { + if (curRxOkCnt > 4*curTxOkCnt) { /* downlink, disable CTS to self */ pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; - //DbgPrint("dm_CTSToSelf() ==> CTS to self disabled -- downlink\n"); - } - else //uplink - { + /*DbgPrint("dm_CTSToSelf() ==> CTS to self disabled -- downlink\n");*/ + } else { /* uplink */ pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF; } @@ -2592,15 +2373,15 @@ static void dm_check_pbc_gpio(struct net_device *dev) struct r8192_priv *priv = ieee80211_priv(dev); u8 tmp1byte; - read_nic_byte(dev, GPI, &tmp1byte); - if(tmp1byte == 0xff) + if (tmp1byte == 0xff) return; - if (tmp1byte&BIT6 || tmp1byte&BIT0) - { - // Here we only set bPbcPressed to TRUE - // After trigger PBC, the variable will be set to FALSE + if (tmp1byte&BIT6 || tmp1byte&BIT0) { + /* + * Here we only set bPbcPressed to TRUE + * After trigger PBC, the variable will be set to FALSE + */ RT_TRACE(COMP_IO, "CheckPbcGPIO - PBC is pressed\n"); priv->bpbc_pressed = true; } @@ -2625,26 +2406,24 @@ static void dm_check_pbc_gpio(struct net_device *dev) *---------------------------------------------------------------------------*/ void dm_rf_pathcheck_workitemcallback(struct work_struct *work) { - struct delayed_work *dwork = container_of(work,struct delayed_work,work); - struct r8192_priv *priv = container_of(dwork,struct r8192_priv,rfpath_check_wq); - struct net_device *dev =priv->ieee80211->dev; - //bool bactually_set = false; + struct delayed_work *dwork = container_of(work, struct delayed_work, work); + struct r8192_priv *priv = container_of(dwork, struct r8192_priv, rfpath_check_wq); + struct net_device *dev = priv->ieee80211->dev; + /*bool bactually_set = false;*/ u8 rfpath = 0, i; - /* 2008/01/30 MH After discussing with SD3 Jerry, 0xc04/0xd04 register will always be the same. We only read 0xc04 now. */ read_nic_byte(dev, 0xc04, &rfpath); - // Check Bit 0-3, it means if RF A-D is enabled. - for (i = 0; i < RF90_PATH_MAX; i++) - { + /* Check Bit 0-3, it means if RF A-D is enabled. */ + for (i = 0; i < RF90_PATH_MAX; i++) { if (rfpath & (0x01<<i)) priv->brfpath_rxenable[i] = 1; else priv->brfpath_rxenable[i] = 0; } - if(!DM_RxPathSelTable.Enable) + if (!DM_RxPathSelTable.Enable) return; dm_rxpath_sel_byrssi(dev); @@ -2654,17 +2433,17 @@ static void dm_init_rxpath_selection(struct net_device *dev) { u8 i; struct r8192_priv *priv = ieee80211_priv(dev); - DM_RxPathSelTable.Enable = 1; //default enabled + + DM_RxPathSelTable.Enable = 1; /* default enabled */ DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low; DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH; - if(priv->CustomerID == RT_CID_819x_Netcore) + if (priv->CustomerID == RT_CID_819x_Netcore) DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; else DM_RxPathSelTable.cck_method = CCK_Rx_Version_1; DM_RxPathSelTable.DbgMode = DM_DBG_OFF; DM_RxPathSelTable.disabledRF = 0; - for(i=0; i<4; i++) - { + for (i = 0; i < 4; i++) { DM_RxPathSelTable.rf_rssi[i] = 50; DM_RxPathSelTable.cck_pwdb_sta[i] = -64; DM_RxPathSelTable.rf_enable_rssi_th[i] = 100; @@ -2674,22 +2453,21 @@ static void dm_init_rxpath_selection(struct net_device *dev) static void dm_rxpath_sel_byrssi(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - u8 i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0; - u8 tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0; - u8 cck_default_Rx=0x2; //RF-C - u8 cck_optional_Rx=0x3;//RF-D - long tmp_cck_max_pwdb=0, tmp_cck_min_pwdb=0, tmp_cck_sec_pwdb=0; - u8 cck_rx_ver2_max_index=0, cck_rx_ver2_min_index=0, cck_rx_ver2_sec_index=0; + u8 i, max_rssi_index = 0, min_rssi_index = 0, sec_rssi_index = 0, rf_num = 0; + u8 tmp_max_rssi = 0, tmp_min_rssi = 0, tmp_sec_rssi = 0; + u8 cck_default_Rx = 0x2; /* RF-C */ + u8 cck_optional_Rx = 0x3; /* RF-D */ + long tmp_cck_max_pwdb = 0, tmp_cck_min_pwdb = 0, tmp_cck_sec_pwdb = 0; + u8 cck_rx_ver2_max_index = 0, cck_rx_ver2_min_index = 0, cck_rx_ver2_sec_index = 0; u8 cur_rf_rssi; long cur_cck_pwdb; static u8 disabled_rf_cnt, cck_Rx_Path_initialized; u8 update_cck_rx_path; - if(priv->rf_type != RF_2T4R) + if (priv->rf_type != RF_2T4R) return; - if(!cck_Rx_Path_initialized) - { + if (!cck_Rx_Path_initialized) { read_nic_byte(dev, 0xa07, &DM_RxPathSelTable.cck_Rx_path); DM_RxPathSelTable.cck_Rx_path &= 0xf; cck_Rx_Path_initialized = 1; @@ -2698,90 +2476,63 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) read_nic_byte(dev, 0xc04, &DM_RxPathSelTable.disabledRF); DM_RxPathSelTable.disabledRF = ~DM_RxPathSelTable.disabledRF & 0xf; - if(priv->ieee80211->mode == WIRELESS_MODE_B) - { - DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; //pure B mode, fixed cck version2 - //DbgPrint("Pure B mode, use cck rx version2 \n"); + if (priv->ieee80211->mode == WIRELESS_MODE_B) { + DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; /* pure B mode, fixed cck version2 */ + /*DbgPrint("Pure B mode, use cck rx version2\n");*/ } - //decide max/sec/min rssi index - for (i=0; i<RF90_PATH_MAX; i++) - { - if(!DM_RxPathSelTable.DbgMode) + /* decide max/sec/min rssi index */ + for (i = 0; i < RF90_PATH_MAX; i++) { + if (!DM_RxPathSelTable.DbgMode) DM_RxPathSelTable.rf_rssi[i] = priv->stats.rx_rssi_percentage[i]; - if(priv->brfpath_rxenable[i]) - { + if (priv->brfpath_rxenable[i]) { rf_num++; cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i]; - if(rf_num == 1) // find first enabled rf path and the rssi values - { //initialize, set all rssi index to the same one + if (rf_num == 1) { /* find first enabled rf path and the rssi values */ + /* initialize, set all rssi index to the same one */ max_rssi_index = min_rssi_index = sec_rssi_index = i; tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi; - } - else if(rf_num == 2) - { // we pick up the max index first, and let sec and min to be the same one - if(cur_rf_rssi >= tmp_max_rssi) - { + } else if (rf_num == 2) { /* we pick up the max index first, and let sec and min to be the same one */ + if (cur_rf_rssi >= tmp_max_rssi) { tmp_max_rssi = cur_rf_rssi; max_rssi_index = i; - } - else - { + } else { tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi; sec_rssi_index = min_rssi_index = i; } - } - else - { - if(cur_rf_rssi > tmp_max_rssi) - { + } else { + if (cur_rf_rssi > tmp_max_rssi) { tmp_sec_rssi = tmp_max_rssi; sec_rssi_index = max_rssi_index; tmp_max_rssi = cur_rf_rssi; max_rssi_index = i; - } - else if(cur_rf_rssi == tmp_max_rssi) - { // let sec and min point to the different index + } else if (cur_rf_rssi == tmp_max_rssi) { /* let sec and min point to the different index */ tmp_sec_rssi = cur_rf_rssi; sec_rssi_index = i; - } - else if((cur_rf_rssi < tmp_max_rssi) &&(cur_rf_rssi > tmp_sec_rssi)) - { + } else if ((cur_rf_rssi < tmp_max_rssi) && (cur_rf_rssi > tmp_sec_rssi)) { tmp_sec_rssi = cur_rf_rssi; sec_rssi_index = i; - } - else if(cur_rf_rssi == tmp_sec_rssi) - { - if(tmp_sec_rssi == tmp_min_rssi) - { // let sec and min point to the different index + } else if (cur_rf_rssi == tmp_sec_rssi) { + if (tmp_sec_rssi == tmp_min_rssi) { + /* let sec and min point to the different index */ tmp_sec_rssi = cur_rf_rssi; sec_rssi_index = i; + } else { + /* This case we don't need to set any index */ } - else - { - // This case we don't need to set any index - } - } - else if((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi)) - { - // This case we don't need to set any index - } - else if(cur_rf_rssi == tmp_min_rssi) - { - if(tmp_sec_rssi == tmp_min_rssi) - { // let sec and min point to the different index + } else if ((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi)) { + /* This case we don't need to set any index */ + } else if (cur_rf_rssi == tmp_min_rssi) { + if (tmp_sec_rssi == tmp_min_rssi) { + /* let sec and min point to the different index */ tmp_min_rssi = cur_rf_rssi; min_rssi_index = i; + } else { + /* This case we don't need to set any index */ } - else - { - // This case we don't need to set any index - } - } - else if(cur_rf_rssi < tmp_min_rssi) - { + } else if (cur_rf_rssi < tmp_min_rssi) { tmp_min_rssi = cur_rf_rssi; min_rssi_index = i; } @@ -2790,83 +2541,51 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) } rf_num = 0; - // decide max/sec/min cck pwdb index - if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) - { - for (i=0; i<RF90_PATH_MAX; i++) - { - if(priv->brfpath_rxenable[i]) - { + /* decide max/sec/min cck pwdb index */ + if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) { + for (i = 0; i < RF90_PATH_MAX; i++) { + if (priv->brfpath_rxenable[i]) { rf_num++; cur_cck_pwdb = DM_RxPathSelTable.cck_pwdb_sta[i]; - if(rf_num == 1) // find first enabled rf path and the rssi values - { //initialize, set all rssi index to the same one + if (rf_num == 1) { /* find first enabled rf path and the rssi values */ + /* initialize, set all rssi index to the same one */ cck_rx_ver2_max_index = cck_rx_ver2_min_index = cck_rx_ver2_sec_index = i; tmp_cck_max_pwdb = tmp_cck_min_pwdb = tmp_cck_sec_pwdb = cur_cck_pwdb; - } - else if(rf_num == 2) - { // we pick up the max index first, and let sec and min to be the same one - if(cur_cck_pwdb >= tmp_cck_max_pwdb) - { + } else if (rf_num == 2) { /* we pick up the max index first, and let sec and min to be the same one */ + if (cur_cck_pwdb >= tmp_cck_max_pwdb) { tmp_cck_max_pwdb = cur_cck_pwdb; cck_rx_ver2_max_index = i; - } - else - { + } else { tmp_cck_sec_pwdb = tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = cck_rx_ver2_min_index = i; } - } - else - { - if(cur_cck_pwdb > tmp_cck_max_pwdb) - { + } else { + if (cur_cck_pwdb > tmp_cck_max_pwdb) { tmp_cck_sec_pwdb = tmp_cck_max_pwdb; cck_rx_ver2_sec_index = cck_rx_ver2_max_index; tmp_cck_max_pwdb = cur_cck_pwdb; cck_rx_ver2_max_index = i; - } - else if(cur_cck_pwdb == tmp_cck_max_pwdb) - { // let sec and min point to the different index + } else if (cur_cck_pwdb == tmp_cck_max_pwdb) { + /* let sec and min point to the different index */ tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - } - else if((cur_cck_pwdb < tmp_cck_max_pwdb) &&(cur_cck_pwdb > tmp_cck_sec_pwdb)) - { + } else if ((cur_cck_pwdb < tmp_cck_max_pwdb) && (cur_cck_pwdb > tmp_cck_sec_pwdb)) { tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - } - else if(cur_cck_pwdb == tmp_cck_sec_pwdb) - { - if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) - { // let sec and min point to the different index - tmp_cck_sec_pwdb = cur_cck_pwdb; - cck_rx_ver2_sec_index = i; - } - else - { - // This case we don't need to set any index - } - } - else if((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb)) - { - // This case we don't need to set any index - } - else if(cur_cck_pwdb == tmp_cck_min_pwdb) - { - if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) - { // let sec and min point to the different index - tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_min_index = i; - } - else - { - // This case we don't need to set any index - } - } - else if(cur_cck_pwdb < tmp_cck_min_pwdb) - { + } else if (cur_cck_pwdb == tmp_cck_sec_pwdb && tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { + /* let sec and min point to the different index */ + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + /* otherwise we don't need to set any index */ + } else if ((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb)) { + /* This case we don't need to set any index */ + } else if (cur_cck_pwdb == tmp_cck_min_pwdb && tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { + /* let sec and min point to the different index */ + tmp_cck_min_pwdb = cur_cck_pwdb; + cck_rx_ver2_min_index = i; + /* otherwise we don't need to set any index */ + } else if (cur_cck_pwdb < tmp_cck_min_pwdb) { tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_min_index = i; } @@ -2876,56 +2595,48 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) } } - - // Set CCK Rx path - // reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path. + /* + * Set CCK Rx path + * reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path. + */ update_cck_rx_path = 0; - if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) - { + if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) { cck_default_Rx = cck_rx_ver2_max_index; cck_optional_Rx = cck_rx_ver2_sec_index; - if(tmp_cck_max_pwdb != -64) + if (tmp_cck_max_pwdb != -64) update_cck_rx_path = 1; } - if(tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2) - { - if((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH) - { - //record the enabled rssi threshold + if (tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2) { + if ((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH) { + /* record the enabled rssi threshold */ DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5; - //disable the BB Rx path, OFDM - rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<min_rssi_index, 0x0); // 0xc04[3:0] - rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<min_rssi_index, 0x0); // 0xd04[3:0] + /* disable the BB Rx path, OFDM */ + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<min_rssi_index, 0x0); /* 0xc04[3:0] */ + rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<min_rssi_index, 0x0); /* 0xd04[3:0] */ disabled_rf_cnt++; } - if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_1) - { + if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_1) { cck_default_Rx = max_rssi_index; cck_optional_Rx = sec_rssi_index; - if(tmp_max_rssi) + if (tmp_max_rssi) update_cck_rx_path = 1; } } - if(update_cck_rx_path) - { + if (update_cck_rx_path) { DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2)|(cck_optional_Rx); rtl8192_setBBreg(dev, rCCK0_AFESetting, 0x0f000000, DM_RxPathSelTable.cck_Rx_path); } - if(DM_RxPathSelTable.disabledRF) - { - for(i=0; i<4; i++) - { - if((DM_RxPathSelTable.disabledRF>>i) & 0x1) //disabled rf - { - if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i]) - { - //enable the BB Rx path - //DbgPrint("RF-%d is enabled. \n", 0x1<<i); - rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<i, 0x1); // 0xc04[3:0] - rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<i, 0x1); // 0xd04[3:0] + if (DM_RxPathSelTable.disabledRF) { + for (i = 0; i < 4; i++) { + if ((DM_RxPathSelTable.disabledRF>>i) & 0x1) { /* disabled rf */ + if (tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i]) { + /* enable the BB Rx path */ + /*DbgPrint("RF-%d is enabled.\n", 0x1<<i);*/ + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<i, 0x1); /* 0xc04[3:0] */ + rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<i, 0x1); /* 0xd04[3:0] */ DM_RxPathSelTable.rf_enable_rssi_th[i] = 100; disabled_rf_cnt--; } @@ -2950,14 +2661,14 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) * 05/28/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ -static void dm_check_rx_path_selection(struct net_device *dev) +static void dm_check_rx_path_selection(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - queue_delayed_work(priv->priv_wq,&priv->rfpath_check_wq,0); -} /* dm_CheckRxRFPath */ + queue_delayed_work(priv->priv_wq, &priv->rfpath_check_wq, 0); +} /* dm_CheckRxRFPath */ -static void dm_init_fsync (struct net_device *dev) +static void dm_init_fsync(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -2966,20 +2677,20 @@ static void dm_init_fsync (struct net_device *dev) priv->ieee80211->fsync_rssi_threshold = 30; priv->ieee80211->bfsync_enable = false; priv->ieee80211->fsync_multiple_timeinterval = 3; - priv->ieee80211->fsync_firstdiff_ratethreshold= 100; - priv->ieee80211->fsync_seconddiff_ratethreshold= 200; + priv->ieee80211->fsync_firstdiff_ratethreshold = 100; + priv->ieee80211->fsync_seconddiff_ratethreshold = 200; priv->ieee80211->fsync_state = Default_Fsync; - priv->framesyncMonitor = 1; // current default 0xc38 monitor on + priv->framesyncMonitor = 1; /* current default 0xc38 monitor on */ init_timer(&priv->fsync_timer); priv->fsync_timer.data = (unsigned long)dev; priv->fsync_timer.function = dm_fsync_timer_callback; } - static void dm_deInit_fsync(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); + del_timer_sync(&priv->fsync_timer); } @@ -2987,102 +2698,84 @@ void dm_fsync_timer_callback(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct r8192_priv *priv = ieee80211_priv((struct net_device *)data); - u32 rate_index, rate_count = 0, rate_count_diff=0; + u32 rate_index, rate_count = 0, rate_count_diff = 0; bool bSwitchFromCountDiff = false; bool bDoubleTimeInterval = false; - if(priv->ieee80211->state == IEEE80211_LINKED && + if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->bfsync_enable && - (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) - { - // Count rate 54, MCS [7], [12, 13, 14, 15] + (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) { + /* Count rate 54, MCS [7], [12, 13, 14, 15] */ u32 rate_bitmap; - for(rate_index = 0; rate_index <= 27; rate_index++) - { + + for (rate_index = 0; rate_index <= 27; rate_index++) { rate_bitmap = 1 << rate_index; - if(priv->ieee80211->fsync_rate_bitmap & rate_bitmap) - rate_count+= priv->stats.received_rate_histogram[1][rate_index]; + if (priv->ieee80211->fsync_rate_bitmap & rate_bitmap) + rate_count += priv->stats.received_rate_histogram[1][rate_index]; } - if(rate_count < priv->rate_record) + if (rate_count < priv->rate_record) rate_count_diff = 0xffffffff - rate_count + priv->rate_record; else rate_count_diff = rate_count - priv->rate_record; - if(rate_count_diff < priv->rateCountDiffRecord) - { - + if (rate_count_diff < priv->rateCountDiffRecord) { u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff; - // Continue count - if(DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold) + /* Continue count */ + if (DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold) priv->ContinueDiffCount++; else priv->ContinueDiffCount = 0; - // Continue count over - if(priv->ContinueDiffCount >=2) - { + /* Continue count over */ + if (priv->ContinueDiffCount >= 2) { bSwitchFromCountDiff = true; priv->ContinueDiffCount = 0; } - } - else - { - // Stop the continued count + } else { + /* Stop the continued count */ priv->ContinueDiffCount = 0; } - //If Count diff <= FsyncRateCountThreshold - if(rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold) - { + /* If Count diff <= FsyncRateCountThreshold */ + if (rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold) { bSwitchFromCountDiff = true; priv->ContinueDiffCount = 0; } priv->rate_record = rate_count; priv->rateCountDiffRecord = rate_count_diff; - RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync); - // if we never receive those mcs rate and rssi > 30 % then switch fsyn - if(priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff) - { + RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff, priv->bswitch_fsync); + /* if we never receive those mcs rate and rssi > 30 % then switch fsyn */ + if (priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff) { bDoubleTimeInterval = true; priv->bswitch_fsync = !priv->bswitch_fsync; - if(priv->bswitch_fsync) - { + if (priv->bswitch_fsync) { write_nic_byte(dev, 0xC36, 0x1c); write_nic_byte(dev, 0xC3e, 0x90); - } - else - { + } else { write_nic_byte(dev, 0xC36, 0x5c); write_nic_byte(dev, 0xC3e, 0x96); } - } - else if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold) - { - if(priv->bswitch_fsync) - { + } else if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold) { + if (priv->bswitch_fsync) { priv->bswitch_fsync = false; write_nic_byte(dev, 0xC36, 0x5c); write_nic_byte(dev, 0xC3e, 0x96); } } - if(bDoubleTimeInterval){ - if(timer_pending(&priv->fsync_timer)) + if (bDoubleTimeInterval) { + if (timer_pending(&priv->fsync_timer)) del_timer_sync(&priv->fsync_timer); priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval); add_timer(&priv->fsync_timer); - } - else{ - if(timer_pending(&priv->fsync_timer)) + } else { + if (timer_pending(&priv->fsync_timer)) del_timer_sync(&priv->fsync_timer); priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval); add_timer(&priv->fsync_timer); } - } - else - { - // Let Register return to default value; - if(priv->bswitch_fsync) - { + } else { + /* Let Register return to default value; */ + if (priv->bswitch_fsync) { priv->bswitch_fsync = false; write_nic_byte(dev, 0xC36, 0x5c); write_nic_byte(dev, 0xC3e, 0x96); @@ -3091,7 +2784,7 @@ void dm_fsync_timer_callback(unsigned long data) write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); } RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount); - RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync); + RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff, priv->bswitch_fsync); } static void dm_StartHWFsync(struct net_device *dev) @@ -3108,9 +2801,8 @@ static void dm_EndSWFsync(struct net_device *dev) RT_TRACE(COMP_HALDM, "%s\n", __func__); del_timer_sync(&(priv->fsync_timer)); - // Let Register return to default value; - if(priv->bswitch_fsync) - { + /* Let Register return to default value; */ + if (priv->bswitch_fsync) { priv->bswitch_fsync = false; write_nic_byte(dev, 0xC36, 0x5c); @@ -3130,30 +2822,26 @@ static void dm_StartSWFsync(struct net_device *dev) u32 rateBitmap; RT_TRACE(COMP_HALDM, "%s\n", __func__); - // Initial rate record to zero, start to record. + /* Initial rate record to zero, start to record. */ priv->rate_record = 0; - // Initialize continue diff count to zero, start to record. + /* Initialize continue diff count to zero, start to record. */ priv->ContinueDiffCount = 0; priv->rateCountDiffRecord = 0; priv->bswitch_fsync = false; - if(priv->ieee80211->mode == WIRELESS_MODE_N_24G) - { - priv->ieee80211->fsync_firstdiff_ratethreshold= 600; + if (priv->ieee80211->mode == WIRELESS_MODE_N_24G) { + priv->ieee80211->fsync_firstdiff_ratethreshold = 600; priv->ieee80211->fsync_seconddiff_ratethreshold = 0xffff; - } - else - { - priv->ieee80211->fsync_firstdiff_ratethreshold= 200; + } else { + priv->ieee80211->fsync_firstdiff_ratethreshold = 200; priv->ieee80211->fsync_seconddiff_ratethreshold = 200; } - for(rateIndex = 0; rateIndex <= 27; rateIndex++) - { - rateBitmap = 1 << rateIndex; - if(priv->ieee80211->fsync_rate_bitmap & rateBitmap) + for (rateIndex = 0; rateIndex <= 27; rateIndex++) { + rateBitmap = 1 << rateIndex; + if (priv->ieee80211->fsync_rate_bitmap & rateBitmap) priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex]; } - if(timer_pending(&priv->fsync_timer)) + if (timer_pending(&priv->fsync_timer)) del_timer_sync(&priv->fsync_timer); priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval); add_timer(&priv->fsync_timer); @@ -3173,139 +2861,112 @@ static void dm_EndHWFsync(struct net_device *dev) void dm_check_fsync(struct net_device *dev) { #define RegC38_Default 0 -#define RegC38_NonFsync_Other_AP 1 -#define RegC38_Fsync_AP_BCM 2 +#define RegC38_NonFsync_Other_AP 1 +#define RegC38_Fsync_AP_BCM 2 struct r8192_priv *priv = ieee80211_priv(dev); - //u32 framesyncC34; - static u8 reg_c38_State=RegC38_Default; + /*u32 framesyncC34;*/ + static u8 reg_c38_State = RegC38_Default; static u32 reset_cnt; RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval %d\n", priv->ieee80211->fsync_rssi_threshold, priv->ieee80211->fsync_time_interval, priv->ieee80211->fsync_multiple_timeinterval); RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n", priv->ieee80211->fsync_rate_bitmap, priv->ieee80211->fsync_firstdiff_ratethreshold, priv->ieee80211->fsync_seconddiff_ratethreshold); - if(priv->ieee80211->state == IEEE80211_LINKED && - (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) - { - if(priv->ieee80211->bfsync_enable == 0) - { - switch (priv->ieee80211->fsync_state) - { - case Default_Fsync: - dm_StartHWFsync(dev); - priv->ieee80211->fsync_state = HW_Fsync; - break; - case SW_Fsync: - dm_EndSWFsync(dev); - dm_StartHWFsync(dev); - priv->ieee80211->fsync_state = HW_Fsync; - break; - case HW_Fsync: - default: - break; + if (priv->ieee80211->state == IEEE80211_LINKED && + (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) { + if (priv->ieee80211->bfsync_enable == 0) { + switch (priv->ieee80211->fsync_state) { + case Default_Fsync: + dm_StartHWFsync(dev); + priv->ieee80211->fsync_state = HW_Fsync; + break; + case SW_Fsync: + dm_EndSWFsync(dev); + dm_StartHWFsync(dev); + priv->ieee80211->fsync_state = HW_Fsync; + break; + case HW_Fsync: + default: + break; } - } - else - { - switch (priv->ieee80211->fsync_state) - { - case Default_Fsync: - dm_StartSWFsync(dev); - priv->ieee80211->fsync_state = SW_Fsync; - break; - case HW_Fsync: - dm_EndHWFsync(dev); - dm_StartSWFsync(dev); - priv->ieee80211->fsync_state = SW_Fsync; - break; - case SW_Fsync: - default: - break; - + } else { + switch (priv->ieee80211->fsync_state) { + case Default_Fsync: + dm_StartSWFsync(dev); + priv->ieee80211->fsync_state = SW_Fsync; + break; + case HW_Fsync: + dm_EndHWFsync(dev); + dm_StartSWFsync(dev); + priv->ieee80211->fsync_state = SW_Fsync; + break; + case SW_Fsync: + default: + break; } } - if(priv->framesyncMonitor) - { - if(reg_c38_State != RegC38_Fsync_AP_BCM) - { //For broadcom AP we write different default value + if (priv->framesyncMonitor) { + if (reg_c38_State != RegC38_Fsync_AP_BCM) { + /* For broadcom AP we write different default value */ write_nic_byte(dev, rOFDM0_RxDetector3, 0x95); reg_c38_State = RegC38_Fsync_AP_BCM; } } - } - else - { - switch (priv->ieee80211->fsync_state) - { - case HW_Fsync: - dm_EndHWFsync(dev); - priv->ieee80211->fsync_state = Default_Fsync; - break; - case SW_Fsync: - dm_EndSWFsync(dev); - priv->ieee80211->fsync_state = Default_Fsync; - break; - case Default_Fsync: - default: - break; + } else { + switch (priv->ieee80211->fsync_state) { + case HW_Fsync: + dm_EndHWFsync(dev); + priv->ieee80211->fsync_state = Default_Fsync; + break; + case SW_Fsync: + dm_EndSWFsync(dev); + priv->ieee80211->fsync_state = Default_Fsync; + break; + case Default_Fsync: + default: + break; } - if(priv->framesyncMonitor) - { - if(priv->ieee80211->state == IEEE80211_LINKED) - { - if(priv->undecorated_smoothed_pwdb <= RegC38_TH) - { - if(reg_c38_State != RegC38_NonFsync_Other_AP) - { + if (priv->framesyncMonitor) { + if (priv->ieee80211->state == IEEE80211_LINKED) { + if (priv->undecorated_smoothed_pwdb <= RegC38_TH) { + if (reg_c38_State != RegC38_NonFsync_Other_AP) { write_nic_byte(dev, rOFDM0_RxDetector3, 0x90); reg_c38_State = RegC38_NonFsync_Other_AP; } - } - else if(priv->undecorated_smoothed_pwdb >= (RegC38_TH+5)) - { - if(reg_c38_State) - { + } else if (priv->undecorated_smoothed_pwdb >= (RegC38_TH+5)) { + if (reg_c38_State) { write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; - //DbgPrint("Fsync is idle, rssi>=40, write 0xc38 = 0x%x \n", pHalData->framesync); + /*DbgPrint("Fsync is idle, rssi>=40, write 0xc38 = 0x%x\n", pHalData->framesync);*/ } } - } - else - { - if(reg_c38_State) - { + } else { + if (reg_c38_State) { write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; - //DbgPrint("Fsync is idle, not connected, write 0xc38 = 0x%x \n", pHalData->framesync); + /*DbgPrint("Fsync is idle, not connected, write 0xc38 = 0x%x\n", pHalData->framesync);*/ } } } } - if(priv->framesyncMonitor) - { - if(priv->reset_count != reset_cnt) - { //After silent reset, the reg_c38_State will be returned to default value + if (priv->framesyncMonitor) { + if (priv->reset_count != reset_cnt) { /* After silent reset, the reg_c38_State will be returned to default value */ write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; reset_cnt = priv->reset_count; - //DbgPrint("reg_c38_State = 0 for silent reset. \n"); + /*DbgPrint("reg_c38_State = 0 for silent reset.\n");*/ } - } - else - { - if(reg_c38_State) - { + } else { + if (reg_c38_State) { write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; - //DbgPrint("framesync no monitor, write 0xc38 = 0x%x \n", pHalData->framesync); + /*DbgPrint("framesync no monitor, write 0xc38 = 0x%x\n", pHalData->framesync);*/ } } } - /*----------------------------------------------------------------------------- * Function: dm_shadow_init() * @@ -3328,10 +2989,9 @@ void dm_shadow_init(struct net_device *dev) u16 offset; for (page = 0; page < 5; page++) - for (offset = 0; offset < 256; offset++) - { + for (offset = 0; offset < 256; offset++) { read_nic_byte(dev, offset+page*256, &dm_shadow[page][offset]); - //DbgPrint("P-%d/O-%02x=%02x\r\n", page, offset, DM_Shadow[page][offset]); + /*DbgPrint("P-%d/O-%02x=%02x\r\n", page, offset, DM_Shadow[page][offset]);*/ } for (page = 8; page < 11; page++) @@ -3366,8 +3026,8 @@ static void dm_init_dynamic_txpower(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. - priv->ieee80211->bdynamic_txpower_enable = true; //Default to enable Tx Power Control + /* Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. */ + priv->ieee80211->bdynamic_txpower_enable = true; /* Default to enable Tx Power Control */ priv->bLastDTPFlag_High = false; priv->bLastDTPFlag_Low = false; priv->bDynamicTxHighPower = false; @@ -3377,91 +3037,77 @@ static void dm_init_dynamic_txpower(struct net_device *dev) static void dm_dynamic_txpower(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - unsigned int txhipower_threshhold=0; - unsigned int txlowpower_threshold=0; - if(priv->ieee80211->bdynamic_txpower_enable != true) - { + unsigned int txhipower_threshhold = 0; + unsigned int txlowpower_threshold = 0; + + if (priv->ieee80211->bdynamic_txpower_enable != true) { priv->bDynamicTxHighPower = false; priv->bDynamicTxLowPower = false; return; } - //printk("priv->ieee80211->current_network.unknown_cap_exist is %d ,priv->ieee80211->current_network.broadcom_cap_exist is %d\n",priv->ieee80211->current_network.unknown_cap_exist,priv->ieee80211->current_network.broadcom_cap_exist); - if((priv->ieee80211->current_network.atheros_cap_exist) && (priv->ieee80211->mode == IEEE_G)){ + /*printk("priv->ieee80211->current_network.unknown_cap_exist is %d , priv->ieee80211->current_network.broadcom_cap_exist is %d\n", priv->ieee80211->current_network.unknown_cap_exist, priv->ieee80211->current_network.broadcom_cap_exist);*/ + if ((priv->ieee80211->current_network.atheros_cap_exist) && (priv->ieee80211->mode == IEEE_G)) { txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH; txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW; - } - else - { + } else { txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH; txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW; } -// printk("=======>%s(): txhipower_threshhold is %d,txlowpower_threshold is %d\n",__func__,txhipower_threshhold,txlowpower_threshold); - RT_TRACE(COMP_TXAGC,"priv->undecorated_smoothed_pwdb = %ld \n" , priv->undecorated_smoothed_pwdb); + /*printk("=======>%s(): txhipower_threshhold is %d, txlowpower_threshold is %d\n", __func__, txhipower_threshhold, txlowpower_threshold);*/ + RT_TRACE(COMP_TXAGC, "priv->undecorated_smoothed_pwdb = %ld\n", priv->undecorated_smoothed_pwdb); - if(priv->ieee80211->state == IEEE80211_LINKED) - { - if(priv->undecorated_smoothed_pwdb >= txhipower_threshhold) - { + if (priv->ieee80211->state == IEEE80211_LINKED) { + if (priv->undecorated_smoothed_pwdb >= txhipower_threshhold) { priv->bDynamicTxHighPower = true; priv->bDynamicTxLowPower = false; - } - else - { - // high power state check - if(priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true) - { + } else { + /* high power state check */ + if (priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true) priv->bDynamicTxHighPower = false; - } - // low power state check - if(priv->undecorated_smoothed_pwdb < 35) - { + + /* low power state check */ + if (priv->undecorated_smoothed_pwdb < 35) priv->bDynamicTxLowPower = true; - } - else if(priv->undecorated_smoothed_pwdb >= 40) - { + else if (priv->undecorated_smoothed_pwdb >= 40) priv->bDynamicTxLowPower = false; - } } - } - else - { - //pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange; + } else { + /*pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange;*/ priv->bDynamicTxHighPower = false; priv->bDynamicTxLowPower = false; } - if((priv->bDynamicTxHighPower != priv->bLastDTPFlag_High) || - (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low)) - { - RT_TRACE(COMP_TXAGC,"SetTxPowerLevel8190() channel = %d \n" , priv->ieee80211->current_network.channel); + if ((priv->bDynamicTxHighPower != priv->bLastDTPFlag_High) || + (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low)) { + RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190() channel = %d\n", priv->ieee80211->current_network.channel); #if defined(RTL8190P) || defined(RTL8192E) - SetTxPowerLevel8190(Adapter,pHalData->CurrentChannel); + SetTxPowerLevel8190(Adapter, pHalData->CurrentChannel); #endif - rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel); - //pHalData->bStartTxCtrlByTPCNFR = FALSE; //Clear th flag of Set TX Power from Sitesurvey + rtl8192_phy_setTxPower(dev, priv->ieee80211->current_network.channel); + /*pHalData->bStartTxCtrlByTPCNFR = FALSE; Clear th flag of Set TX Power from Sitesurvey*/ } priv->bLastDTPFlag_High = priv->bDynamicTxHighPower; priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower; } /* dm_dynamic_txpower */ -//added by vivi, for read tx rate and retrycount +/* added by vivi, for read tx rate and retrycount */ static void dm_check_txrateandretrycount(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); struct ieee80211_device *ieee = priv->ieee80211; - //for 11n tx rate -// priv->stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg); + /* for 11n tx rate */ + /*priv->stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg);*/ read_nic_byte(dev, Current_Tx_Rate_Reg, &ieee->softmac_stats.CurrentShowTxate); - //printk("=============>tx_rate_reg:%x\n", ieee->softmac_stats.CurrentShowTxate); - //for initial tx rate -// priv->stats.last_packet_rate = read_nic_byte(dev, Initial_Tx_Rate_Reg); + /*printk("=============>tx_rate_reg:%x\n", ieee->softmac_stats.CurrentShowTxate);*/ + /* for initial tx rate */ + /*priv->stats.last_packet_rate = read_nic_byte(dev, Initial_Tx_Rate_Reg);*/ read_nic_byte(dev, Initial_Tx_Rate_Reg, &ieee->softmac_stats.last_packet_rate); - //for tx tx retry count -// priv->stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg); + /* for tx tx retry count */ + /*priv->stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg);*/ read_nic_dword(dev, Tx_Retry_Count_Reg, &ieee->softmac_stats.txretrycount); } @@ -3469,11 +3115,12 @@ static void dm_send_rssi_tofw(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - // If we test chariot, we should stop the TX command ? - // Because 92E will always silent reset when we send tx command. We use register - // 0x1e0(byte) to notify driver. + /* + * If we test chariot, we should stop the TX command ? + * Because 92E will always silent reset when we send tx command. We use register + * 0x1e0(byte) to notify driver. + */ write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb); - return; } /*---------------------------Define function prototype------------------------*/ diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h index 3d0a98b6d8e..e62543d22b8 100644 --- a/drivers/staging/rtl8712/drv_types.h +++ b/drivers/staging/rtl8712/drv_types.h @@ -129,8 +129,8 @@ struct dvobj_priv { struct _adapter *padapter; u32 nr_endpoint; u8 ishighspeed; - uint(*inirp_init)(struct _adapter *adapter); - uint(*inirp_deinit)(struct _adapter *adapter); + uint (*inirp_init)(struct _adapter *adapter); + uint (*inirp_deinit)(struct _adapter *adapter); struct usb_device *pusbdev; }; @@ -166,7 +166,7 @@ struct _adapter { pid_t evtThread; struct task_struct *xmitThread; pid_t recvThread; - uint(*dvobj_init)(struct _adapter *adapter); + uint (*dvobj_init)(struct _adapter *adapter); void (*dvobj_deinit)(struct _adapter *adapter); struct net_device *pnetdev; int bup; diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h index 5153ad9c2c7..36348d900d3 100644 --- a/drivers/staging/rtl8712/osdep_service.h +++ b/drivers/staging/rtl8712/osdep_service.h @@ -71,7 +71,7 @@ static inline void _init_timer(struct timer_list *ptimer, static inline void _set_timer(struct timer_list *ptimer, u32 delay_time) { - mod_timer(ptimer, (jiffies+(delay_time*HZ/1000))); + mod_timer(ptimer, (jiffies+msecs_to_jiffies(delay_time))); } static inline void _cancel_timer(struct timer_list *ptimer, u8 *bcancelled) @@ -101,12 +101,9 @@ static inline void sleep_schedulable(int ms) { u32 delta; - delta = (ms * HZ) / 1000;/*(ms)*/ - if (delta == 0) - delta = 1;/* 1 ms */ + delta = msecs_to_jiffies(ms);/*(ms)*/ set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(delta) != 0) - return; + schedule_timeout(delta); } static inline unsigned char _cancel_timer_ex(struct timer_list *ptimer) diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 0631f363825..409c8c89725 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -137,20 +137,6 @@ _recv_indicatepkt_drop: precvpriv->rx_drop++; } -void r8712_os_read_port(struct _adapter *padapter, struct recv_buf *precvbuf) -{ - struct recv_priv *precvpriv = &padapter->recvpriv; - - precvbuf->ref_cnt--; - /*free skb in recv_buf*/ - dev_kfree_skb_any(precvbuf->pskb); - precvbuf->pskb = NULL; - precvbuf->reuse = false; - if (!precvbuf->irp_pending) - r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, - (unsigned char *)precvbuf); -} - static void _r8712_reordering_ctrl_timeout_handler (void *FunctionContext) { struct recv_reorder_ctrl *preorder_ctrl = diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index f4384ef0086..1f4986e940a 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -46,7 +46,6 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf); int r8712_os_recvbuf_resource_free(struct _adapter *padapter, struct recv_buf *precvbuf); -void r8712_os_read_port(struct _adapter *padapter, struct recv_buf *precvbuf); void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl); #endif diff --git a/drivers/staging/rtl8712/rtl8712_cmd.h b/drivers/staging/rtl8712/rtl8712_cmd.h index 039ab3e9717..67e9e910aef 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.h +++ b/drivers/staging/rtl8712/rtl8712_cmd.h @@ -109,16 +109,16 @@ enum rtl8712_h2c_cmd { GEN_CMD_CODE(_DisconnectCtrlEx), /*61*/ /* To do, modify these h2c cmd, add or delete */ - GEN_CMD_CODE(_GetH2cLbk) , + GEN_CMD_CODE(_GetH2cLbk), /* WPS extra IE */ - GEN_CMD_CODE(_SetProbeReqExtraIE) , - GEN_CMD_CODE(_SetAssocReqExtraIE) , - GEN_CMD_CODE(_SetProbeRspExtraIE) , - GEN_CMD_CODE(_SetAssocRspExtraIE) , + GEN_CMD_CODE(_SetProbeReqExtraIE), + GEN_CMD_CODE(_SetAssocReqExtraIE), + GEN_CMD_CODE(_SetProbeRspExtraIE), + GEN_CMD_CODE(_SetAssocRspExtraIE), /* the following is driver will do */ - GEN_CMD_CODE(_GetCurDataRate) , + GEN_CMD_CODE(_GetCurDataRate), GEN_CMD_CODE(_GetTxRetrycnt), /* to record times that Tx retry to * transmit packet after association diff --git a/drivers/staging/rtl8712/rtl8712_event.h b/drivers/staging/rtl8712/rtl8712_event.h index 3d7f79efa2c..29a4c23a0d2 100644 --- a/drivers/staging/rtl8712/rtl8712_event.h +++ b/drivers/staging/rtl8712/rtl8712_event.h @@ -27,7 +27,7 @@ #define _RTL8712_EVENT_H_ void r8712_event_handle(struct _adapter *padapter, uint *peventbuf); -void r8712_got_addbareq_event_callback(struct _adapter *adapter , u8 *pbuf); +void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf); enum rtl8712_c2h_event { GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/ diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index 73b7d864ccb..9bb364f04fd 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -196,7 +196,7 @@ static inline char *translate_scan(struct _adapter *padapter, if (p && ht_ielen > 0) { ht_cap = true; pht_capie = (struct ieee80211_ht_cap *)(p + 2); - memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2); + memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); } /* Add the protocol name */ iwe.cmd = SIOCGIWNAME; @@ -1436,7 +1436,7 @@ static int r8711_wx_get_rate(struct net_device *dev, if (p && ht_ielen > 0) { ht_cap = true; pht_capie = (struct ieee80211_ht_cap *)(p + 2); - memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2); + memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); bw_40MHz = (pht_capie->cap_info & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0; short_GI = (pht_capie->cap_info & diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index b7462e8145d..977a8335805 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -93,7 +93,7 @@ struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv) return NULL; spin_lock_irqsave(&free_queue->lock, irqL); plist = free_queue->queue.next; - pnetwork = LIST_CONTAINOR(plist , struct wlan_network, list); + pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); list_del_init(&pnetwork->list); pnetwork->last_scanned = jiffies; pmlmepriv->num_of_scanned++; @@ -499,7 +499,7 @@ static int is_desired_network(struct _adapter *adapter, } /* TODO: Perry : For Power Management */ -void r8712_atimdone_event_callback(struct _adapter *adapter , u8 *pbuf) +void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf) { } diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c index a16f15e9199..0b5461208eb 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c @@ -575,26 +575,6 @@ uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv return RNDIS_STATUS_SUCCESS; } -uint oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct ndis_802_11_ssid *pssid; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_needed = (u32)sizeof(struct ndis_802_11_ssid); - *poid_par_priv->bytes_rw = 0; - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - pssid = (struct ndis_802_11_ssid *)poid_par_priv->information_buf; - if (mp_start_joinbss(Adapter, pssid) == _FAIL) - status = RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_rw = sizeof(struct ndis_802_11_ssid); - return status; -} - uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv) { @@ -696,172 +676,6 @@ uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv) return status; } -uint oid_rt_pro_burst_read_register_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct burst_rw_reg *pBstRwReg; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - pBstRwReg = (struct burst_rw_reg *)poid_par_priv->information_buf; - r8712_read_mem(Adapter, pBstRwReg->offset, (u32)pBstRwReg->len, - pBstRwReg->Data); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_burst_write_register_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct burst_rw_reg *pBstRwReg; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - pBstRwReg = (struct burst_rw_reg *)poid_par_priv->information_buf; - r8712_write_mem(Adapter, pBstRwReg->offset, (u32)pBstRwReg->len, - pBstRwReg->Data); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_write_txcmd_hdl(struct oid_par_priv *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_read16_eeprom_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct eeprom_rw_param *pEEPROM; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - pEEPROM = (struct eeprom_rw_param *)poid_par_priv->information_buf; - pEEPROM->value = r8712_eeprom_read16(Adapter, - (u16)(pEEPROM->offset >> 1)); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_write16_eeprom_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct eeprom_rw_param *pEEPROM; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - pEEPROM = (struct eeprom_rw_param *)poid_par_priv->information_buf; - r8712_eeprom_write16(Adapter, (u16)(pEEPROM->offset >> 1), - pEEPROM->value); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro8711_wi_poll_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct mp_wiparam *pwi_param; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(struct mp_wiparam)) - return RNDIS_STATUS_INVALID_LENGTH; - if (Adapter->mppriv.workparam.bcompleted == false) - return RNDIS_STATUS_NOT_ACCEPTED; - pwi_param = (struct mp_wiparam *)poid_par_priv->information_buf; - memcpy(pwi_param, &Adapter->mppriv.workparam, - sizeof(struct mp_wiparam)); - Adapter->mppriv.act_in_progress = false; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro8711_pkt_loss_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(uint) * 2) - return RNDIS_STATUS_INVALID_LENGTH; - if (*(uint *)poid_par_priv->information_buf == 1) - Adapter->mppriv.rx_pktloss = 0; - *((uint *)poid_par_priv->information_buf+1) = - Adapter->mppriv.rx_pktloss; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_rd_attrib_mem_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_wr_attrib_mem_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_rf_intfs_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (r8712_setrfintfs_cmd(Adapter, *(unsigned char *) - poid_par_priv->information_buf) == _FAIL) - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} - -uint oid_rt_poll_rx_status_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - memcpy(poid_par_priv->information_buf, - (unsigned char *)&Adapter->mppriv.rxstat, - sizeof(struct recv_stat)); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_cfg_debug_message_hdl(struct oid_par_priv - *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_data_rate_ex_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (r8712_setdatarate_cmd(Adapter, - poid_par_priv->information_buf) != _SUCCESS) - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} - uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv) { struct _adapter *Adapter = (struct _adapter *) @@ -890,251 +704,6 @@ uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv) return RNDIS_STATUS_SUCCESS; } -uint oid_rt_pro_set_power_tracking_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u8)) - return RNDIS_STATUS_INVALID_LENGTH; - if (!r8712_setptm_cmd(Adapter, *((u8 *)poid_par_priv->information_buf))) - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} - -uint oid_rt_pro_set_basic_rate_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff}; - uint status = RNDIS_STATUS_SUCCESS; - u32 ratevalue; - u8 datarates[NumRates]; - int i; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - ratevalue = *((u32 *)poid_par_priv->information_buf); - for (i = 0; i < NumRates; i++) { - if (ratevalue == mpdatarate[i]) - datarates[i] = mpdatarate[i]; - else - datarates[i] = 0xff; - } - if (r8712_setbasicrate_cmd(Adapter, datarates) != _SUCCESS) - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} - -uint oid_rt_pro_qry_pwrstate_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < 8) - return RNDIS_STATUS_INVALID_LENGTH; - *poid_par_priv->bytes_rw = 8; - memcpy(poid_par_priv->information_buf, - &(Adapter->pwrctrlpriv.pwr_mode), 8); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_pwrstate_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint pwr_mode, smart_ps; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_rw = 0; - *poid_par_priv->bytes_needed = 8; - if (poid_par_priv->information_buf_len < 8) - return RNDIS_STATUS_INVALID_LENGTH; - pwr_mode = *(uint *)(poid_par_priv->information_buf); - smart_ps = *(uint *)((addr_t)poid_par_priv->information_buf + 4); - if (pwr_mode != Adapter->pwrctrlpriv.pwr_mode || smart_ps != - Adapter->pwrctrlpriv.smart_ps) - r8712_set_ps_mode(Adapter, pwr_mode, smart_ps); - *poid_par_priv->bytes_rw = 8; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_h2c_set_rate_table_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct setratable_parm *prate_table; - u8 res; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_needed = sizeof(struct setratable_parm); - if (poid_par_priv->information_buf_len < - sizeof(struct setratable_parm)) - return RNDIS_STATUS_INVALID_LENGTH; - prate_table = (struct setratable_parm *)poid_par_priv->information_buf; - res = r8712_setrttbl_cmd(Adapter, prate_table); - if (res == _FAIL) - status = RNDIS_STATUS_FAILURE; - return status; -} - -uint oid_rt_pro_h2c_get_rate_table_hdl(struct oid_par_priv - *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_encryption_ctrl_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct security_priv *psecuritypriv = &Adapter->securitypriv; - enum ENCRY_CTRL_STATE encry_mode = 0; - - *poid_par_priv->bytes_needed = sizeof(u8); - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - - if (poid_par_priv->type_of_oid == SET_OID) { - encry_mode = *((u8 *)poid_par_priv->information_buf); - switch (encry_mode) { - case HW_CONTROL: - psecuritypriv->sw_decrypt = false; - psecuritypriv->sw_encrypt = false; - break; - case SW_CONTROL: - psecuritypriv->sw_decrypt = true; - psecuritypriv->sw_encrypt = true; - break; - case HW_ENCRY_SW_DECRY: - psecuritypriv->sw_decrypt = true; - psecuritypriv->sw_encrypt = false; - break; - case SW_ENCRY_HW_DECRY: - psecuritypriv->sw_decrypt = false; - psecuritypriv->sw_encrypt = true; - break; - } - } else { - if ((psecuritypriv->sw_encrypt == false) && - (psecuritypriv->sw_decrypt == false)) - encry_mode = HW_CONTROL; - else if ((psecuritypriv->sw_encrypt == false) && - (psecuritypriv->sw_decrypt == true)) - encry_mode = HW_ENCRY_SW_DECRY; - else if ((psecuritypriv->sw_encrypt == true) && - (psecuritypriv->sw_decrypt == false)) - encry_mode = SW_ENCRY_HW_DECRY; - else if ((psecuritypriv->sw_encrypt == true) && - (psecuritypriv->sw_decrypt == true)) - encry_mode = SW_CONTROL; - *(u8 *)poid_par_priv->information_buf = encry_mode; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } - return RNDIS_STATUS_SUCCESS; -} -/*----------------------------------------------------------------------*/ -uint oid_rt_pro_add_sta_info_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - uint status = RNDIS_STATUS_SUCCESS; - - struct sta_info *psta = NULL; - u8 *macaddr; - - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - *poid_par_priv->bytes_needed = ETH_ALEN; - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - macaddr = (u8 *) poid_par_priv->information_buf; - psta = r8712_get_stainfo(&Adapter->stapriv, macaddr); - if (psta == NULL) { /* the sta in sta_info_queue => do nothing*/ - psta = r8712_alloc_stainfo(&Adapter->stapriv, macaddr); - if (psta == NULL) - status = RNDIS_STATUS_FAILURE; - } - return status; -} -/*-------------------------------------------------------------------------*/ -uint oid_rt_pro_dele_sta_info_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - unsigned long irqL; - - struct sta_info *psta = NULL; - u8 *macaddr; - - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - *poid_par_priv->bytes_needed = ETH_ALEN; - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - - macaddr = (u8 *)poid_par_priv->information_buf; - - psta = r8712_get_stainfo(&Adapter->stapriv, macaddr); - if (psta != NULL) { - spin_lock_irqsave(&(Adapter->stapriv.sta_hash_lock), irqL); - r8712_free_stainfo(Adapter, psta); - spin_unlock_irqrestore(&(Adapter->stapriv.sta_hash_lock), irqL); - } - - return RNDIS_STATUS_SUCCESS; -} -/*--------------------------------------------------------------------------*/ -static u32 mp_query_drv_var(struct _adapter *padapter, u8 offset, u32 var) -{ - return var; -} - -uint oid_rt_pro_query_dr_variable_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - struct DR_VARIABLE_STRUCT *pdrv_var; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_needed = sizeof(struct DR_VARIABLE_STRUCT); - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - pdrv_var = (struct DR_VARIABLE_STRUCT *)poid_par_priv->information_buf; - pdrv_var->variable = mp_query_drv_var(Adapter, pdrv_var->offset, - pdrv_var->variable); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -/*--------------------------------------------------------------------------*/ -uint oid_rt_pro_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} -/*------------------------------------------------------------------------*/ uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv) { struct _adapter *Adapter = (struct _adapter *) @@ -1192,38 +761,6 @@ uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv) return status; } /*----------------------------------------------------------------------*/ -uint oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct PGPKT_STRUCT *ppgpkt; - - *poid_par_priv->bytes_rw = 0; - if (poid_par_priv->information_buf_len < sizeof(struct PGPKT_STRUCT)) - return RNDIS_STATUS_INVALID_LENGTH; - ppgpkt = (struct PGPKT_STRUCT *)poid_par_priv->information_buf; - if (poid_par_priv->type_of_oid == QUERY_OID) { - if (r8712_efuse_pg_packet_read(Adapter, ppgpkt->offset, - ppgpkt->data) == true) - *poid_par_priv->bytes_rw = - poid_par_priv->information_buf_len; - else - status = RNDIS_STATUS_FAILURE; - } else { - if (r8712_efuse_reg_init(Adapter) == true) { - if (r8712_efuse_pg_packet_write(Adapter, ppgpkt->offset, - ppgpkt->word_en, ppgpkt->data) == true) - *poid_par_priv->bytes_rw = - poid_par_priv->information_buf_len; - else - status = RNDIS_STATUS_FAILURE; - r8712_efuse_reg_uninit(Adapter); - } else - status = RNDIS_STATUS_FAILURE; - } - return status; -} uint oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv) @@ -1319,24 +856,6 @@ uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv) return RNDIS_STATUS_SUCCESS; } -uint oid_rt_set_crystal_cap_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 crystal_cap = 0; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - crystal_cap = *((u32 *)poid_par_priv->information_buf);/*4*/ - if (crystal_cap > 0xf) - return RNDIS_STATUS_NOT_ACCEPTED; - Adapter->mppriv.curr_crystalcap = crystal_cap; - r8712_SetCrystalCap(Adapter); - return RNDIS_STATUS_SUCCESS; -} - uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv) { @@ -1378,50 +897,6 @@ uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv return RNDIS_STATUS_SUCCESS; } -uint oid_rt_pro_set_tx_agc_offset_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 txagc; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - txagc = *(u32 *)poid_par_priv->information_buf; - r8712_SetTxAGCOffset(Adapter, txagc); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_pkt_test_mode_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - struct mp_priv *pmppriv = &Adapter->mppriv; - u32 type; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - if (poid_par_priv->information_buf_len < sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - - type = *(u32 *)poid_par_priv->information_buf; - - if (_LOOPBOOK_MODE_ == type) { - pmppriv->mode = type; - set_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE); /*append txdesc*/ - } else if (_2MAC_MODE_ == type) { - pmppriv->mode = type; - _clr_fwstate_(pmlmepriv, WIFI_MP_LPBK_STATE); - } else - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} /*--------------------------------------------------------------------------*/ /*Linux*/ unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv) diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h index 850143d5dee..8e7c7f8b69f 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h @@ -86,41 +86,8 @@ struct DR_VARIABLE_STRUCT { int mp_start_joinbss(struct _adapter *padapter, struct ndis_802_11_ssid *pssid); /* oid_rtl_seg_87_11_00 */ -uint oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_burst_read_register_hdl(struct oid_par_priv* - poid_par_priv); -uint oid_rt_pro_burst_write_register_hdl(struct oid_par_priv* - poid_par_priv); -uint oid_rt_pro_write_txcmd_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_read16_eeprom_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_write16_eeprom_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro8711_wi_poll_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro8711_pkt_loss_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_rd_attrib_mem_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_wr_attrib_mem_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_rf_intfs_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_poll_rx_status_hdl(struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_87_11_20 */ -uint oid_rt_pro_cfg_debug_message_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_data_rate_ex_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_basic_rate_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_power_tracking_hdl( - struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_87_11_50 */ -uint oid_rt_pro_qry_pwrstate_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_pwrstate_hdl( - struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_87_11_F0 */ -uint oid_rt_pro_h2c_set_rate_table_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_h2c_get_rate_table_hdl( - struct oid_par_priv *poid_par_priv); /* oid_rtl_seg_81_80_00 */ uint oid_rt_pro_set_data_rate_hdl( struct oid_par_priv *poid_par_priv); @@ -159,28 +126,15 @@ uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv); /* oid_rtl_seg_81_85 */ uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_87_12_00 */ -uint oid_rt_pro_encryption_ctrl_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_add_sta_info_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_dele_sta_info_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_query_dr_variable_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_get_efuse_current_size_hdl( struct oid_par_priv *poid_par_priv); uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_set_crystal_cap_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_tx_agc_offset_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_pkt_test_mode_hdl( - struct oid_par_priv *poid_par_priv); uint oid_rt_get_thermal_meter_hdl( struct oid_par_priv *poid_par_priv); uint oid_rt_reset_phy_rx_packet_count_hdl( diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h index 0526ba077bf..dbfb5552354 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -33,17 +33,17 @@ #define CMD_ALIVE BIT(2) enum Power_Mgnt { - PS_MODE_ACTIVE = 0 , - PS_MODE_MIN , - PS_MODE_MAX , - PS_MODE_DTIM , - PS_MODE_VOIP , - PS_MODE_UAPSD_WMM , - PS_MODE_UAPSD , - PS_MODE_IBSS , - PS_MODE_WWLAN , - PM_Radio_Off , - PM_Card_Disable , + PS_MODE_ACTIVE = 0, + PS_MODE_MIN, + PS_MODE_MAX, + PS_MODE_DTIM, + PS_MODE_VOIP, + PS_MODE_UAPSD_WMM, + PS_MODE_UAPSD, + PS_MODE_IBSS, + PS_MODE_WWLAN, + PM_Radio_Off, + PM_Card_Disable, PS_MODE_NUM }; diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index 4c9b98e8210..1752121ff49 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -83,9 +83,8 @@ static void mfree_all_stainfo(struct sta_priv *pstapriv) spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL); phead = &pstapriv->free_sta_queue.queue; plist = phead->next; - while ((end_of_queue_search(phead, plist)) == false) { + while ((end_of_queue_search(phead, plist)) == false) plist = plist->next; - } spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); } @@ -228,7 +227,7 @@ void r8712_free_all_stainfo(struct _adapter *padapter) struct sta_info, hash_list); plist = plist->next; if (pbcmc_stainfo != psta) - r8712_free_stainfo(padapter , psta); + r8712_free_stainfo(padapter, psta); } } spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 62a377e7fdc..a28af03c9d8 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -471,7 +471,7 @@ static sint xmitframe_swencrypt(struct _adapter *padapter, return _SUCCESS; } -static sint make_wlanhdr(struct _adapter *padapter , u8 *hdr, +static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, struct pkt_attrib *pattrib) { u16 *qc; diff --git a/drivers/staging/rtl8712/sta_info.h b/drivers/staging/rtl8712/sta_info.h index c4e0ef2f52c..742dfa0ca81 100644 --- a/drivers/staging/rtl8712/sta_info.h +++ b/drivers/staging/rtl8712/sta_info.h @@ -135,7 +135,7 @@ u32 _r8712_init_sta_priv(struct sta_priv *pstapriv); u32 _r8712_free_sta_priv(struct sta_priv *pstapriv); struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr); -void r8712_free_stainfo(struct _adapter *padapter , struct sta_info *psta); +void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta); void r8712_free_all_stainfo(struct _adapter *padapter); struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr); void r8712_init_bcmc_stainfo(struct _adapter *padapter); diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 7d0d1719b13..f8b5b332e7c 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -366,7 +366,6 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, struct net_device *pnetdev; struct usb_device *udev; - printk(KERN_INFO "r8712u: Staging version\n"); /* In this probe function, O.S. will provide the usb interface pointer * to driver. We have to increase the reference count of the usb device * structure by using the usb_get_dev function. @@ -463,7 +462,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, /* Use the mac address stored in the Efuse * offset = 0x12 for usb in efuse */ - memcpy(mac, &pdata[0x12], ETH_ALEN); + ether_addr_copy(mac, &pdata[0x12]); } eeprom_CustomerID = pdata[0x52]; switch (eeprom_CustomerID) { @@ -580,7 +579,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, } else dev_info(&udev->dev, "r8712u: MAC Address from efuse = %pM\n", mac); - memcpy(pnetdev->dev_addr, mac, ETH_ALEN); + ether_addr_copy(pnetdev->dev_addr, mac); } /* step 6. Load the firmware asynchronously */ if (rtl871x_load_fw(padapter)) diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c index e394d12c36b..c6327c07291 100644 --- a/drivers/staging/rtl8723au/core/rtw_ap.c +++ b/drivers/staging/rtl8723au/core/rtw_ap.c @@ -456,8 +456,8 @@ static void update_bmc_sta(struct rtw_adapter *padapter) sizeof(struct stainfo_stats)); /* prepare for add_RATid23a */ - supportRateNum = rtw_get_rateset_len23a((u8*)&pcur_network->SupportedRates); - network_type = rtw_check_network_type23a((u8*)&pcur_network->SupportedRates, supportRateNum, 1); + supportRateNum = rtw_get_rateset_len23a((u8 *)&pcur_network->SupportedRates); + network_type = rtw_check_network_type23a((u8 *)&pcur_network->SupportedRates, supportRateNum, 1); memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum); psta->bssratelen = supportRateNum; @@ -897,7 +897,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, pairwise_cipher = 0; psecuritypriv->wpa_group_cipher = 0; psecuritypriv->wpa_pairwise_cipher = 0; - for (p = ie; ;p += (ie_len + 2)) { + for (p = ie; ; p += (ie_len + 2)) { p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, pbss_network->IELength - (ie_len + 2)); if ((p) && (!memcmp(p+2, RTW_WPA_OUI23A_TYPE, 4))) { @@ -924,7 +924,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, ie_len = 0; pmlmepriv->qos_option = 0; if (pregistrypriv->wmm_enable) { - for (p = ie; ;p += (ie_len + 2)) { + for (p = ie; ; p += (ie_len + 2)) { p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pbss_network->IELength - (ie_len + 2))); @@ -1204,7 +1204,7 @@ static void update_bcn_p2p_ie(struct rtw_adapter *padapter) { } -static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8*oui) +static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8 *oui) { DBG_8723A("%s\n", __func__); diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c index 60e0ded8ae0..2447a56df83 100644 --- a/drivers/staging/rtl8723au/core/rtw_cmd.c +++ b/drivers/staging/rtl8723au/core/rtw_cmd.c @@ -245,11 +245,6 @@ exit: return res; } -void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv) -{ - pcmdpriv->cmd_done_cnt++; -} - void rtw_free_cmd_obj23a(struct cmd_obj *pcmd) { @@ -852,62 +847,6 @@ exit: return res; } -/* - * This is only ever called from on_action_spct23a_ch_switch () which isn't - * called from anywhere itself - */ -int rtw_set_ch_cmd23a(struct rtw_adapter *padapter, u8 ch, u8 bw, u8 ch_offset, - u8 enqueue) -{ - struct cmd_obj *pcmdobj; - struct set_ch_parm *set_ch_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__, - padapter->pnetdev->name, ch, bw, ch_offset); - - /* check input parameter */ - - /* prepare cmd parameter */ - set_ch_parm = kzalloc(sizeof(*set_ch_parm), GFP_KERNEL); - if (!set_ch_parm) { - res = _FAIL; - goto exit; - } - set_ch_parm->ch = ch; - set_ch_parm->bw = bw; - set_ch_parm->ch_offset = ch_offset; - - if (enqueue) { - /* need enqueue, prepare cmd_obj and enqueue */ - pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmdobj) { - kfree(set_ch_parm); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, - GEN_CMD_CODE(_SetChannel)); - res = rtw_enqueue_cmd23a(pcmdpriv, pcmdobj); - } else { - /* no need to enqueue, do the cmd hdl directly and - free cmd parameter */ - if (H2C_SUCCESS != set_ch_hdl23a(padapter, (u8 *)set_ch_parm)) - res = _FAIL; - - kfree(set_ch_parm); - } - - /* do something based on res... */ -exit: - - DBG_8723A("%s(%s): res:%u\n", __func__, padapter->pnetdev->name, res); - - return res; -} - static void traffic_status_watchdog(struct rtw_adapter *padapter) { u8 bEnterPS; diff --git a/drivers/staging/rtl8723au/core/rtw_efuse.c b/drivers/staging/rtl8723au/core/rtw_efuse.c index 81960e788f8..a6deddc0229 100644 --- a/drivers/staging/rtl8723au/core/rtw_efuse.c +++ b/drivers/staging/rtl8723au/core/rtw_efuse.c @@ -327,15 +327,9 @@ EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address) *---------------------------------------------------------------------------*/ void -EFUSE_Write1Byte( - struct rtw_adapter * Adapter, - u16 Address, - u8 Value); +EFUSE_Write1Byte(struct rtw_adapter *Adapter, u16 Address, u8 Value); void -EFUSE_Write1Byte( - struct rtw_adapter * Adapter, - u16 Address, - u8 Value) +EFUSE_Write1Byte(struct rtw_adapter *Adapter, u16 Address, u8 Value) { u8 Bytetemp = {0x00}; u8 temp = {0x00}; @@ -635,10 +629,7 @@ Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse) * *---------------------------------------------------------------------------*/ static void -efuse_ShadowRead1Byte( - struct rtw_adapter * pAdapter, - u16 Offset, - u8 *Value) +efuse_ShadowRead1Byte(struct rtw_adapter *pAdapter, u16 Offset, u8 *Value) { struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); @@ -647,10 +638,7 @@ efuse_ShadowRead1Byte( /* Read Two Bytes */ static void -efuse_ShadowRead2Byte( - struct rtw_adapter * pAdapter, - u16 Offset, - u16 *Value) +efuse_ShadowRead2Byte(struct rtw_adapter *pAdapter, u16 Offset, u16 *Value) { struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); @@ -660,10 +648,7 @@ efuse_ShadowRead2Byte( /* Read Four Bytes */ static void -efuse_ShadowRead4Byte( - struct rtw_adapter * pAdapter, - u16 Offset, - u32 *Value) +efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset, u32 *Value) { struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); @@ -722,11 +707,8 @@ void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType) * *---------------------------------------------------------------------------*/ void -EFUSE_ShadowRead23a( - struct rtw_adapter * pAdapter, - u8 Type, - u16 Offset, - u32 *Value) +EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, + u8 Type, u16 Offset, u32 *Value) { if (Type == 1) efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value); diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c index 7a5e6bf0d1a..1c82dffcf59 100644 --- a/drivers/staging/rtl8723au/core/rtw_xmit.c +++ b/drivers/staging/rtl8723au/core/rtw_xmit.c @@ -2372,12 +2372,3 @@ int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms) return rtw_sctx_wait23a(pack_tx_ops); } -void rtw_ack_tx_done23a(struct xmit_priv *pxmitpriv, int status) -{ - struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops; - - if (pxmitpriv->ack_tx) - rtw23a_sctx_done_err(&pack_tx_ops, status); - else - DBG_8723A("%s ack_tx not set\n", __func__); -} diff --git a/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c b/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c index 1da4eece6f9..33777d2852f 100644 --- a/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c +++ b/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c @@ -47,11 +47,11 @@ u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion, u8 FabVersion, u8 InterfaceType, struct wlan_pwr_cfg PwrSeqCmd[]) { - struct wlan_pwr_cfg PwrCfgCmd = { 0 }; - u8 bPollingBit = false; + struct wlan_pwr_cfg PwrCfgCmd; + u8 bPollingBit; u32 AryIdx = 0; - u8 value = 0; - u32 offset = 0; + u8 value; + u32 offset; u32 pollingCount = 0; /* polling autoload done. */ u32 maxPollingCnt = 5000; diff --git a/drivers/staging/rtl8723au/hal/odm.c b/drivers/staging/rtl8723au/hal/odm.c index 1c0f106d599..5269b46445f 100644 --- a/drivers/staging/rtl8723au/hal/odm.c +++ b/drivers/staging/rtl8723au/hal/odm.c @@ -187,24 +187,13 @@ void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm); void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm); -void odm_1R_CCA23a(struct dm_odm_t *pDM_Odm); /* END---------BB POWER SAVE----------------------- */ -void odm_RefreshRateAdaptiveMask23aMP23a(struct dm_odm_t *pDM_Odm); - void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm); -void odm_RefreshRateAdaptiveMask23aAPADSL23a(struct dm_odm_t *pDM_Odm); - void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm); -void odm_RSSIMonitorInit(struct dm_odm_t *pDM_Odm); - -void odm_RSSIMonitorCheck23aMP(struct dm_odm_t *pDM_Odm); - void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm); -void odm_RSSIMonitorCheck23aAP(struct dm_odm_t *pDM_Odm); - void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm); void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm); @@ -212,16 +201,12 @@ void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm); void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm); -void odm_TXPowerTrackingCheckAP(struct dm_odm_t *pDM_Odm); - void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm); void odm_TXPowerTrackingThermalMeterInit23a(struct dm_odm_t *pDM_Odm); void odm_TXPowerTrackingInit23a(struct dm_odm_t *pDM_Odm); -void odm_TXPowerTrackingCheckMP(struct dm_odm_t *pDM_Odm); - void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm); static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm); @@ -946,47 +931,13 @@ void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm) return; } -void odm_1R_CCA23a(struct dm_odm_t *pDM_Odm) -{ - struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable; - - if (pDM_Odm->RSSI_Min != 0xFF) { - if (pDM_PSTable->PreCCAState == CCA_2R) { - if (pDM_Odm->RSSI_Min >= 35) - pDM_PSTable->CurCCAState = CCA_1R; - else - pDM_PSTable->CurCCAState = CCA_2R; - } else { - if (pDM_Odm->RSSI_Min <= 30) - pDM_PSTable->CurCCAState = CCA_2R; - else - pDM_PSTable->CurCCAState = CCA_1R; - } - } else { - pDM_PSTable->CurCCAState = CCA_MAX; - } - - if (pDM_PSTable->PreCCAState != pDM_PSTable->CurCCAState) { - if (pDM_PSTable->CurCCAState == CCA_1R) { - if (pDM_Odm->RFType == ODM_2T2R) - ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x13); - else - ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x23); - } else { - ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x33); - /* PHY_SetBBReg(pAdapter, 0xe70, bMaskByte3, 0x63); */ - } - pDM_PSTable->PreCCAState = pDM_PSTable->CurCCAState; - } -} - void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal) { struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable; - u8 Rssi_Up_bound = 30 ; + u8 Rssi_Up_bound = 30; u8 Rssi_Low_bound = 25; if (pDM_Odm->PatchID == 40) { /* RT_CID_819x_FUNAI_TV */ - Rssi_Up_bound = 50 ; + Rssi_Up_bound = 50; Rssi_Low_bound = 45; } if (pDM_PSTable->initialize == 0) { @@ -1177,10 +1128,6 @@ void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm) odm_RefreshRateAdaptiveMask23aCE23a(pDM_Odm); } -void odm_RefreshRateAdaptiveMask23aMP23a(struct dm_odm_t *pDM_Odm) -{ -} - void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm) { u8 i; @@ -1216,10 +1163,6 @@ void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm) } -void odm_RefreshRateAdaptiveMask23aAPADSL23a(struct dm_odm_t *pDM_Odm) -{ -} - /* Return Value: bool */ /* - true: RATRState is changed. */ bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate, @@ -1284,14 +1227,6 @@ void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm) pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; } -/* 3 ============================================================ */ -/* 3 RSSI Monitor */ -/* 3 ============================================================ */ - -void odm_RSSIMonitorInit(struct dm_odm_t *pDM_Odm) -{ -} - void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm) { /* For AP/ADSL use struct rtl8723a_priv * */ @@ -1306,10 +1241,6 @@ void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm) odm_RSSIMonitorCheck23aCE(pDM_Odm); } /* odm_RSSIMonitorCheck23a */ -void odm_RSSIMonitorCheck23aMP(struct dm_odm_t *pDM_Odm) -{ -} - static void FindMinimumRSSI( struct rtw_adapter *pAdapter @@ -1378,10 +1309,6 @@ void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm) ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM); } -void odm_RSSIMonitorCheck23aAP(struct dm_odm_t *pDM_Odm) -{ -} - /* endif */ /* 3 ============================================================ */ /* 3 Tx Power Tracking */ @@ -1422,19 +1349,12 @@ void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm) { } -void odm_TXPowerTrackingCheckMP(struct dm_odm_t *pDM_Odm) -{ -} - -void odm_TXPowerTrackingCheckAP(struct dm_odm_t *pDM_Odm) -{ -} - /* EDCA Turbo */ static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm) { struct rtw_adapter *Adapter = pDM_Odm->Adapter; + pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false; Adapter->recvpriv.bIsAnyNonBEPkts = false; @@ -1591,6 +1511,7 @@ ConvertTo_dB23a( void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm) { struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table; + pDM_SWAT_Table->ANTA_ON = true; pDM_SWAT_Table->ANTB_ON = true; } diff --git a/drivers/staging/rtl8723au/hal/odm_HWConfig.c b/drivers/staging/rtl8723au/hal/odm_HWConfig.c index fb3cc872f20..33aafa01f90 100644 --- a/drivers/staging/rtl8723au/hal/odm_HWConfig.c +++ b/drivers/staging/rtl8723au/hal/odm_HWConfig.c @@ -113,7 +113,7 @@ static void odm_RxPhyStatus92CSeries_Parsing(struct dm_odm_t *pDM_Odm, cck_highpwr = pDM_Odm->bCckHighPower; - cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ; + cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a; /* The RSSI formula should be modified according to the gain table */ if (!cck_highpwr) { @@ -138,16 +138,16 @@ static void odm_RxPhyStatus92CSeries_Parsing(struct dm_odm_t *pDM_Odm, report = (cck_agc_rpt & 0x60)>>5; switch (report) { case 0x3: - rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1) ; + rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1); break; case 0x2: rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f)<<1); break; case 0x1: - rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1) ; + rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1); break; case 0x0: - rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1) ; + rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1); break; } } diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c index 86a83975f4f..73cfddd6df9 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c @@ -7255,63 +7255,19 @@ btdm_2AntTdmaDurationAdjust(struct rtw_adapter *padapter, u8 bScoHid, RTPRINT(FBT, BT_TRACE, ("[BTCoex], first run TdmaDurationAdjust()!!\n")); if (bScoHid) { if (bTxPause) { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } + btdm_2AntPsTdma(padapter, true, 15); + pBtdm8723->psTdmaDuAdjType = 15; } else { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } + btdm_2AntPsTdma(padapter, true, 11); + pBtdm8723->psTdmaDuAdjType = 11; } } else { if (bTxPause) { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } + btdm_2AntPsTdma(padapter, true, 7); + pBtdm8723->psTdmaDuAdjType = 7; } else { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } + btdm_2AntPsTdma(padapter, true, 3); + pBtdm8723->psTdmaDuAdjType = 3; } } up = 0; @@ -9145,7 +9101,7 @@ u32 BTDM_BtTxRxCounterL(struct rtw_adapter *padapter) u32 counters = 0; counters = pHalData->bt_coexist.halCoex8723.lowPriorityTx+ - pHalData->bt_coexist.halCoex8723.lowPriorityRx ; + pHalData->bt_coexist.halCoex8723.lowPriorityRx; return counters; } diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c index 88e91cd8ebb..19dc5e3b2e2 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c @@ -698,7 +698,7 @@ storePwrIndexDiffRateOffset(struct rtw_adapter *Adapter, u32 RegAddr, * 11/10/2008 tynli Modify to mew files. *---------------------------------------------------------------------------*/ static int -phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter, u8 ConfigType) +phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter) { int i; u32 *Rtl819XPHY_REGArray_Table_PG; @@ -707,17 +707,15 @@ phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter, u8 ConfigType) PHY_REGArrayPGLen = Rtl8723_PHY_REG_Array_PGLength; Rtl819XPHY_REGArray_Table_PG = (u32 *)Rtl8723_PHY_REG_Array_PG; - if (ConfigType == BaseBand_Config_PHY_REG) { - for (i = 0; i < PHY_REGArrayPGLen; i = i + 3) { - storePwrIndexDiffRateOffset(Adapter, - Rtl819XPHY_REGArray_Table_PG[i], - Rtl819XPHY_REGArray_Table_PG[i+1], - Rtl819XPHY_REGArray_Table_PG[i+2]); - } + for (i = 0; i < PHY_REGArrayPGLen; i = i + 3) { + storePwrIndexDiffRateOffset(Adapter, + Rtl819XPHY_REGArray_Table_PG[i], + Rtl819XPHY_REGArray_Table_PG[i+1], + Rtl819XPHY_REGArray_Table_PG[i+2]); } return _SUCCESS; -} /* phy_ConfigBBWithPgHeaderFile */ +} static void phy_BB8192C_Config_1T(struct rtw_adapter *Adapter) @@ -768,8 +766,7 @@ phy_BB8723a_Config_ParaFile(struct rtw_adapter *Adapter) if (pEEPROM->bautoload_fail_flag == false) { pHalData->pwrGroupCnt = 0; - rtStatus = phy_ConfigBBWithPgHeaderFile(Adapter, - BaseBand_Config_PHY_REG); + rtStatus = phy_ConfigBBWithPgHeaderFile(Adapter); } if (rtStatus != _SUCCESS) @@ -923,9 +920,6 @@ _PHY_SetBWMode23a92C(struct rtw_adapter *Adapter) u8 regBwOpMode; u8 regRRSR_RSC; - if (pHalData->rf_chip == RF_PSEUDO_11N) - return; - /* There is no 40MHz mode in RF_8225. */ if (pHalData->rf_chip == RF_8225) return; @@ -1021,10 +1015,6 @@ _PHY_SetBWMode23a92C(struct rtw_adapter *Adapter) /* PHY_SetRF8258Bandwidth(); */ break; - case RF_PSEUDO_11N: - /* Do Nothing */ - break; - case RF_6052: rtl8723a_phy_rf6052set_bw(Adapter, pHalData->CurrentChannelBW); break; @@ -1074,7 +1064,7 @@ PHY_SetBWMode23a8723A(struct rtw_adapter *Adapter, static void _PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) { - u8 eRFPath; + enum RF_RADIO_PATH eRFPath; u32 param1, param2; struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); @@ -1088,7 +1078,7 @@ static void _PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) { pHalData->RfRegChnlVal[eRFPath] = (pHalData->RfRegChnlVal[eRFPath] & 0xfffffc00) | param2; - PHY_SetRFReg(Adapter, (enum RF_RADIO_PATH)eRFPath, param1, + PHY_SetRFReg(Adapter, eRFPath, param1, bRFRegOffsetMask, pHalData->RfRegChnlVal[eRFPath]); } @@ -1101,11 +1091,6 @@ void PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) u8 tmpchannel = pHalData->CurrentChannel; bool result = true; - if (pHalData->rf_chip == RF_PSEUDO_11N) { - /* return immediately if it is peudo-phy */ - return; - } - if (channel == 0) channel = 1; diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c b/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c index 6070510bb47..1759487329a 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c +++ b/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c @@ -79,7 +79,7 @@ static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxd } } -static void fill_txdesc_vcs(struct pkt_attrib *pattrib, u32 *pdw) +static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw) { /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */ @@ -114,7 +114,7 @@ static void fill_txdesc_vcs(struct pkt_attrib *pattrib, u32 *pdw) } } -static void fill_txdesc_phy(struct pkt_attrib *pattrib, u32 *pdw) +static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw) { if (pattrib->ht_en) { *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0; diff --git a/drivers/staging/rtl8723au/hal/usb_halinit.c b/drivers/staging/rtl8723au/hal/usb_halinit.c index febe5cedef8..adbf1c2dd38 100644 --- a/drivers/staging/rtl8723au/hal/usb_halinit.c +++ b/drivers/staging/rtl8723au/hal/usb_halinit.c @@ -625,10 +625,10 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter) } /* reducing 80M spur */ - PHY_SetBBReg(Adapter, RF_T_METER, bMaskDWord, 0x0381808d); - PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff83); - PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff82); - PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff83); + PHY_SetBBReg(Adapter, REG_AFE_XTAL_CTRL, bMaskDWord, 0x0381808d); + PHY_SetBBReg(Adapter, REG_AFE_PLL_CTRL, bMaskDWord, 0xf0ffff83); + PHY_SetBBReg(Adapter, REG_AFE_PLL_CTRL, bMaskDWord, 0xf0ffff82); + PHY_SetBBReg(Adapter, REG_AFE_PLL_CTRL, bMaskDWord, 0xf0ffff83); /* RFSW Control */ PHY_SetBBReg(Adapter, rFPGA0_TxInfo, bMaskDWord, 0x00000003); /* 0x804[14]= 0 */ @@ -640,8 +640,10 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter) /* */ /* Joseph Note: Keep RfRegChnlVal for later use. */ /* */ - pHalData->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, (enum RF_RADIO_PATH)0, RF_CHNLBW, bRFRegOffsetMask); - pHalData->RfRegChnlVal[1] = PHY_QueryRFReg(Adapter, (enum RF_RADIO_PATH)1, RF_CHNLBW, bRFRegOffsetMask); + pHalData->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, RF_PATH_A, + RF_CHNLBW, bRFRegOffsetMask); + pHalData->RfRegChnlVal[1] = PHY_QueryRFReg(Adapter, RF_PATH_B, + RF_CHNLBW, bRFRegOffsetMask); if (!mac_on) { _InitQueueReservedPage(Adapter); diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h index 688f20412bc..2247d987471 100644 --- a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h +++ b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h @@ -17,46 +17,9 @@ #define __INC_HAL8723PHYCFG_H__ /*--------------------------Define Parameters-------------------------------*/ -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 /* us */ -#define AntennaDiversityValue 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 - - #define MAX_AGGR_NUM 0x0909 -/*--------------------------Define Parameters-------------------------------*/ - - /*------------------------------Define structure----------------------------*/ -enum swchnlcmdid { - CmdID_End, - CmdID_SetTxPowerLevel, - CmdID_BBRegWrite10, - CmdID_WritePortUlong, - CmdID_WritePortUshort, - CmdID_WritePortUchar, - CmdID_RF_WriteReg, -}; - - -/* 1. Switch channel related */ -struct swchnlcmd { - enum swchnlcmdid CmdID; - u32 Para1; - u32 Para2; - u32 msDelay; -}; - -enum HW90_BLOCK { - HW90_BLOCK_MAC = 0, - HW90_BLOCK_PHY0 = 1, - HW90_BLOCK_PHY1 = 2, - HW90_BLOCK_RF = 3, - HW90_BLOCK_MAXIMUM = 4, /* Never use this */ -}; - enum RF_RADIO_PATH { RF_PATH_A = 0, /* Radio Path A */ RF_PATH_B = 1, /* Radio Path B */ @@ -64,7 +27,6 @@ enum RF_RADIO_PATH { }; #define CHANNEL_MAX_NUMBER 14 /* 14 is the max channel number */ -#define CHANNEL_GROUP_MAX 3 /* ch1~3, ch4~9, ch10~14 total three groups */ enum WIRELESS_MODE { WIRELESS_MODE_UNKNOWN = 0x00, @@ -77,22 +39,6 @@ enum WIRELESS_MODE { WIRELESS_MODE_AC = BIT(6) }; -enum baseband_config_type { - BaseBand_Config_PHY_REG = 0, /* Radio Path A */ - BaseBand_Config_AGC_TAB = 1, /* Radio Path B */ -}; - -enum ra_offset_area { - RA_OFFSET_LEGACY_OFDM1, - RA_OFFSET_LEGACY_OFDM2, - RA_OFFSET_HT_OFDM1, - RA_OFFSET_HT_OFDM2, - RA_OFFSET_HT_OFDM3, - RA_OFFSET_HT_OFDM4, - RA_OFFSET_HT_CCK, -}; - - /* BB/RF related */ enum rf_type_8190p { RF_TYPE_MIN, /* 0 */ @@ -100,7 +46,6 @@ enum rf_type_8190p { RF_8256 = 2, /* 2 11b/g/n */ RF_8258 = 3, /* 3 11a/b/g/n RF */ RF_6052 = 4, /* 4 11b/g/n RF */ - RF_PSEUDO_11N = 5, /* 5, It is a temporality RF. */ }; struct bb_reg_define { diff --git a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h index 4a1f58f2982..3771d6bb577 100644 --- a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h +++ b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h @@ -39,10 +39,10 @@ * { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here */ #define RTL8723A_TRANS_CARDEMU_TO_ACT \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ \ - {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x67[0] = 0 to disable BT_GPS_SEL pins*/ \ - {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS},/*Delay 1ms*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), 0}, /*0x00[5] = 1b'0 release analog Ips to digital , 1:isolation*/ \ + {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ \ + {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x67[0] = 0 to disable BT_GPS_SEL pins*/ \ + {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS},/*Delay 1ms*/ \ + {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), 0}, /*0x00[5] = 1b'0 release analog Ips to digital , 1:isolation*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), 0},/* disable SW LPS 0x04[10]= 0*/ \ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},/* wait till 0x04[17] = 1 power ready*/ \ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},/* release WLON reset 0x04[16]= 1*/ \ @@ -57,48 +57,28 @@ {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/*0x4C[23] = 0x4E[7] = 0, switch DPDT_SEL_P output from register 0x65[2] */\ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, /*0x04[9] = 1 turn off MAC by HW state machine*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, /*0x00[5] = 1b'1 analog Ips to digital , 1:isolation*/ \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/ \ + {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, /*0x00[5] = 1b'1 analog Ips to digital , 1:isolation*/ \ + {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/ \ #define RTL8723A_TRANS_CARDEMU_TO_SUS \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), (BIT(4)|BIT(3))}, /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SDIO SOP option to disable BG/MB/ACK/SWR*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4)}, /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ #define RTL8723A_TRANS_SUS_TO_CARDEMU \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ #define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07 = 0x20 , SOP option to disable BG/MB*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), BIT(2)}, /*0x04[10] = 1, enable SW LPS*/ \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 1}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ + {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ #define RTL8723A_TRANS_CARDDIS_TO_CARDEMU \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\ {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/\ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*PCIe DMA start*/ - + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ #define RTL8723A_TRANS_CARDEMU_TO_PDN \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK|PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/ \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/ \ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/\ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/ @@ -106,7 +86,6 @@ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/ #define RTL8723A_TRANS_ACT_TO_LPS \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},/*PCIe DMA stop*/ \ {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},/*Tx Pause*/ \ {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ @@ -117,13 +96,10 @@ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*Whole BB is reset*/ \ {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03},/*Reset MAC TRX*/ \ {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*check if removed later*/ \ - {0x0093, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00},/*When driver enter Sus/ Disable, enable LOP for BT*/ \ {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)},/*Respond TxOK to scheduler*/ #define RTL8723A_TRANS_LPS_TO_ACT \ - {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/\ {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\ - {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/\ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\ {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*. 0x08[4] = 0 switch TSF to 40M*/\ {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, /*Polling 0x109[7]= 0 TSF in 40M*/\ diff --git a/drivers/staging/rtl8723au/include/osdep_intf.h b/drivers/staging/rtl8723au/include/osdep_intf.h index 33afa62f31b..a157eb2e78d 100644 --- a/drivers/staging/rtl8723au/include/osdep_intf.h +++ b/drivers/staging/rtl8723au/include/osdep_intf.h @@ -19,9 +19,6 @@ #include <osdep_service.h> #include <drv_types.h> -int rtw_hw_suspend23a(struct rtw_adapter *padapter); -int rtw_hw_resume23a(struct rtw_adapter *padapter); - int rtw_init_drv_sw23a(struct rtw_adapter *padapter); int rtw_free_drv_sw23a(struct rtw_adapter *padapter); int rtw_reset_drv_sw23a(struct rtw_adapter *padapter); diff --git a/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h b/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h index 05069652bae..7add5dfe015 100644 --- a/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h +++ b/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h @@ -31,8 +31,8 @@ enum rt_media_status { void BT_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt); -void BT_HaltProcess(struct rtw_adapter * padapter); -void BT_LpsLeave(struct rtw_adapter * padapter); +void BT_HaltProcess(struct rtw_adapter *padapter); +void BT_LpsLeave(struct rtw_adapter *padapter); #define BT_HsConnectionEstablished(Adapter) false @@ -1092,17 +1092,20 @@ enum hci_ext_bp_operation { BTHCI_StateMachine(_Adapter, _StateToEnter, _StateCmd, _EntryNum);\ } -void BTHCI_EventParse(struct rtw_adapter * padapter, void *pEvntData, u32 dataLen); +void BTHCI_EventParse(struct rtw_adapter *padapter, void *pEvntData, + u32 dataLen); #define BT_EventParse BTHCI_EventParse -u8 BTHCI_HsConnectionEstablished(struct rtw_adapter * padapter); -void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter * padapter); -void BTHCI_WifiScanNotify(struct rtw_adapter * padapter, u8 scanType); -void BTHCI_StateMachine(struct rtw_adapter * padapter, u8 StateToEnter, enum hci_state_with_cmd StateCmd, u8 EntryNum); -void BTHCI_DisconnectPeer(struct rtw_adapter * padapter, u8 EntryNum); -void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter * padapter); -void BTHCI_EventAMPStatusChange(struct rtw_adapter * padapter, u8 AMP_Status); -void BTHCI_DisconnectAll(struct rtw_adapter * padapter); -enum hci_status BTHCI_HandleHCICMD(struct rtw_adapter * padapter, struct packet_irp_hcicmd_data *pHciCmd); +u8 BTHCI_HsConnectionEstablished(struct rtw_adapter *padapter); +void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter *padapter); +void BTHCI_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType); +void BTHCI_StateMachine(struct rtw_adapter *padapter, u8 StateToEnter, + enum hci_state_with_cmd StateCmd, u8 EntryNum); +void BTHCI_DisconnectPeer(struct rtw_adapter *padapter, u8 EntryNum); +void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter *padapter); +void BTHCI_EventAMPStatusChange(struct rtw_adapter *padapter, u8 AMP_Status); +void BTHCI_DisconnectAll(struct rtw_adapter *padapter); +enum hci_status BTHCI_HandleHCICMD(struct rtw_adapter *padapter, + struct packet_irp_hcicmd_data *pHciCmd); /* ===== End of sync from SD7 driver COMMON/bt_hci.h ===== */ @@ -1157,9 +1160,10 @@ struct btdm_8723a_1ant { u8 bRAChanged; }; -void BTDM_1AntSignalCompensation(struct rtw_adapter * padapter, u8 *rssi_wifi, u8 *rssi_bt); -void BTDM_1AntForDhcp(struct rtw_adapter * padapter); -void BTDM_1AntBtCoexist8723A(struct rtw_adapter * padapter); +void BTDM_1AntSignalCompensation(struct rtw_adapter *padapter, + u8 *rssi_wifi, u8 *rssi_bt); +void BTDM_1AntForDhcp(struct rtw_adapter *padapter); +void BTDM_1AntBtCoexist8723A(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.h ===== */ @@ -1241,7 +1245,7 @@ struct btdm_8723a_2ant { u8 btStatus; }; -void BTDM_2AntBtCoexist8723A(struct rtw_adapter * padapter); +void BTDM_2AntBtCoexist8723A(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.h ===== */ /* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */ @@ -1310,15 +1314,17 @@ struct bt_coexist_8723a { struct btdm_8723a_1ant btdm1Ant; }; -void BTDM_SetFwChnlInfo(struct rtw_adapter * padapter, enum rt_media_status mstatus); -u8 BTDM_IsWifiConnectionExist(struct rtw_adapter * padapter); -void BTDM_SetFw3a(struct rtw_adapter * padapter, u8 byte1, u8 byte2, u8 byte3, u8 byte4, u8 byte5); -void BTDM_QueryBtInformation(struct rtw_adapter * padapter); -void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter * padapter, u8 type); -void BTDM_SetSwPenaltyTxRateAdaptive(struct rtw_adapter * padapter, u8 raType); -void BTDM_SetFwDecBtPwr(struct rtw_adapter * padapter, u8 bDecBtPwr); -u8 BTDM_BtProfileSupport(struct rtw_adapter * padapter); -void BTDM_LpsLeave(struct rtw_adapter * padapter); +void BTDM_SetFwChnlInfo(struct rtw_adapter *padapter, + enum rt_media_status mstatus); +u8 BTDM_IsWifiConnectionExist(struct rtw_adapter *padapter); +void BTDM_SetFw3a(struct rtw_adapter *padapter, u8 byte1, u8 byte2, u8 byte3, + u8 byte4, u8 byte5); +void BTDM_QueryBtInformation(struct rtw_adapter *padapter); +void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter *padapter, u8 type); +void BTDM_SetSwPenaltyTxRateAdaptive(struct rtw_adapter *padapter, u8 raType); +void BTDM_SetFwDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr); +u8 BTDM_BtProfileSupport(struct rtw_adapter *padapter); +void BTDM_LpsLeave(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */ @@ -1340,8 +1346,9 @@ enum BT_A2DP_INDEX{ #define BTDM_ANT_BT 2 -void BTDM_SingleAnt(struct rtw_adapter * padapter, u8 bSingleAntOn, u8 bInterruptOn, u8 bMultiNAVOn); -void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter * padapter); +void BTDM_SingleAnt(struct rtw_adapter *padapter, u8 bSingleAntOn, + u8 bInterruptOn, u8 bMultiNAVOn); +void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.h ===== */ @@ -1361,7 +1368,8 @@ void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter * padapter); #define BT_DACSWING_M7 2 #define BT_DACSWING_M10 3 -void BTDM_DiminishWiFi(struct rtw_adapter * Adapter, u8 bDACOn, u8 bInterruptOn, u8 DACSwingLevel, u8 bNAVOn); +void BTDM_DiminishWiFi(struct rtw_adapter *Adapter, u8 bDACOn, u8 bInterruptOn, + u8 DACSwingLevel, u8 bNAVOn); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.h ===== */ @@ -1534,58 +1542,63 @@ struct bt_coexist_str { u8 fw3aVal[5]; }; -void BTDM_CheckAntSelMode(struct rtw_adapter * padapter); -void BTDM_FwC2hBtRssi(struct rtw_adapter * padapter, u8 *tmpBuf); +void BTDM_CheckAntSelMode(struct rtw_adapter *padapter); +void BTDM_FwC2hBtRssi(struct rtw_adapter *padapter, u8 *tmpBuf); #define BT_FwC2hBtRssi BTDM_FwC2hBtRssi -void BTDM_DisplayBtCoexInfo(struct rtw_adapter * padapter); +void BTDM_DisplayBtCoexInfo(struct rtw_adapter *padapter); #define BT_DisplayBtCoexInfo BTDM_DisplayBtCoexInfo -void BTDM_RejectAPAggregatedPacket(struct rtw_adapter * padapter, u8 bReject); -u8 BTDM_IsHT40(struct rtw_adapter * padapter); -u8 BTDM_Legacy(struct rtw_adapter * padapter); -void BTDM_CheckWiFiState(struct rtw_adapter * padapter); -s32 BTDM_GetRxSS(struct rtw_adapter * padapter); -u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter * padapter, u8 levelNum, u8 RssiThresh, u8 RssiThresh1); -u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter * padapter, u8 levelNum, u8 RssiThresh, u8 RssiThresh1); -u8 BTDM_CheckCoexRSSIState(struct rtw_adapter * padapter, u8 levelNum, u8 RssiThresh, u8 RssiThresh1); -void BTDM_Balance(struct rtw_adapter * padapter, u8 bBalanceOn, u8 ms0, u8 ms1); -void BTDM_AGCTable(struct rtw_adapter * padapter, u8 type); -void BTDM_BBBackOffLevel(struct rtw_adapter * padapter, u8 type); -void BTDM_FWCoexAllOff(struct rtw_adapter * padapter); -void BTDM_SWCoexAllOff(struct rtw_adapter * padapter); -void BTDM_HWCoexAllOff(struct rtw_adapter * padapter); -void BTDM_CoexAllOff(struct rtw_adapter * padapter); -void BTDM_TurnOffBtCoexistBeforeEnterIPS(struct rtw_adapter * padapter); -void BTDM_SignalCompensation(struct rtw_adapter * padapter, u8 *rssi_wifi, u8 *rssi_bt); -void BTDM_UpdateCoexState(struct rtw_adapter * padapter); -u8 BTDM_IsSameCoexistState(struct rtw_adapter * padapter); -void BTDM_PWDBMonitor(struct rtw_adapter * padapter); -u8 BTDM_IsBTBusy(struct rtw_adapter * padapter); +void BTDM_RejectAPAggregatedPacket(struct rtw_adapter *padapter, u8 bReject); +u8 BTDM_IsHT40(struct rtw_adapter *padapter); +u8 BTDM_Legacy(struct rtw_adapter *padapter); +void BTDM_CheckWiFiState(struct rtw_adapter *padapter); +s32 BTDM_GetRxSS(struct rtw_adapter *padapter); +u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter *padapter, u8 levelNum, + u8 RssiThresh, u8 RssiThresh1); +u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter *padapter, u8 levelNum, + u8 RssiThresh, u8 RssiThresh1); +u8 BTDM_CheckCoexRSSIState(struct rtw_adapter *padapter, u8 levelNum, + u8 RssiThresh, u8 RssiThresh1); +void BTDM_Balance(struct rtw_adapter *padapter, u8 bBalanceOn, u8 ms0, u8 ms1); +void BTDM_AGCTable(struct rtw_adapter *padapter, u8 type); +void BTDM_BBBackOffLevel(struct rtw_adapter *padapter, u8 type); +void BTDM_FWCoexAllOff(struct rtw_adapter *padapter); +void BTDM_SWCoexAllOff(struct rtw_adapter *padapter); +void BTDM_HWCoexAllOff(struct rtw_adapter *padapter); +void BTDM_CoexAllOff(struct rtw_adapter *padapter); +void BTDM_TurnOffBtCoexistBeforeEnterIPS(struct rtw_adapter *padapter); +void BTDM_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, + u8 *rssi_bt); +void BTDM_UpdateCoexState(struct rtw_adapter *padapter); +u8 BTDM_IsSameCoexistState(struct rtw_adapter *padapter); +void BTDM_PWDBMonitor(struct rtw_adapter *padapter); +u8 BTDM_IsBTBusy(struct rtw_adapter *padapter); #define BT_IsBtBusy BTDM_IsBTBusy -u8 BTDM_IsWifiBusy(struct rtw_adapter * padapter); -u8 BTDM_IsCoexistStateChanged(struct rtw_adapter * padapter); -u8 BTDM_IsWifiUplink(struct rtw_adapter * padapter); -u8 BTDM_IsWifiDownlink(struct rtw_adapter * padapter); -u8 BTDM_IsBTHSMode(struct rtw_adapter * padapter); -u8 BTDM_IsBTUplink(struct rtw_adapter * padapter); -u8 BTDM_IsBTDownlink(struct rtw_adapter * padapter); -void BTDM_AdjustForBtOperation(struct rtw_adapter * padapter); -void BTDM_ForHalt(struct rtw_adapter * padapter); -void BTDM_WifiScanNotify(struct rtw_adapter * padapter, u8 scanType); -void BTDM_WifiAssociateNotify(struct rtw_adapter * padapter, u8 action); -void BTDM_MediaStatusNotify(struct rtw_adapter * padapter, enum rt_media_status mstatus); -void BTDM_ForDhcp(struct rtw_adapter * padapter); -void BTDM_ResetActionProfileState(struct rtw_adapter * padapter); -void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter * padapter, u8 antNum); +u8 BTDM_IsWifiBusy(struct rtw_adapter *padapter); +u8 BTDM_IsCoexistStateChanged(struct rtw_adapter *padapter); +u8 BTDM_IsWifiUplink(struct rtw_adapter *padapter); +u8 BTDM_IsWifiDownlink(struct rtw_adapter *padapter); +u8 BTDM_IsBTHSMode(struct rtw_adapter *padapter); +u8 BTDM_IsBTUplink(struct rtw_adapter *padapter); +u8 BTDM_IsBTDownlink(struct rtw_adapter *padapter); +void BTDM_AdjustForBtOperation(struct rtw_adapter *padapter); +void BTDM_ForHalt(struct rtw_adapter *padapter); +void BTDM_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType); +void BTDM_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action); +void BTDM_MediaStatusNotify(struct rtw_adapter *padapter, + enum rt_media_status mstatus); +void BTDM_ForDhcp(struct rtw_adapter *padapter); +void BTDM_ResetActionProfileState(struct rtw_adapter *padapter); +void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum); #define BT_SetBtCoexCurrAntNum BTDM_SetBtCoexCurrAntNum -u8 BTDM_IsActionSCO(struct rtw_adapter * padapter); -u8 BTDM_IsActionHID(struct rtw_adapter * padapter); -u8 BTDM_IsActionA2DP(struct rtw_adapter * padapter); -u8 BTDM_IsActionPAN(struct rtw_adapter * padapter); -u8 BTDM_IsActionHIDA2DP(struct rtw_adapter * padapter); -u8 BTDM_IsActionHIDPAN(struct rtw_adapter * padapter); -u8 BTDM_IsActionPANA2DP(struct rtw_adapter * padapter); -u32 BTDM_BtTxRxCounterH(struct rtw_adapter * padapter); -u32 BTDM_BtTxRxCounterL(struct rtw_adapter * padapter); +u8 BTDM_IsActionSCO(struct rtw_adapter *padapter); +u8 BTDM_IsActionHID(struct rtw_adapter *padapter); +u8 BTDM_IsActionA2DP(struct rtw_adapter *padapter); +u8 BTDM_IsActionPAN(struct rtw_adapter *padapter); +u8 BTDM_IsActionHIDA2DP(struct rtw_adapter *padapter); +u8 BTDM_IsActionHIDPAN(struct rtw_adapter *padapter); +u8 BTDM_IsActionPANA2DP(struct rtw_adapter *padapter); +u32 BTDM_BtTxRxCounterH(struct rtw_adapter *padapter); +u32 BTDM_BtTxRxCounterL(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtCoexist.h ===== */ @@ -1593,14 +1606,14 @@ u32 BTDM_BtTxRxCounterL(struct rtw_adapter * padapter); #define RTS_CTS_NO_LEN_LIMIT 0 -u8 HALBT_GetPGAntNum(struct rtw_adapter * padapter); +u8 HALBT_GetPGAntNum(struct rtw_adapter *padapter); #define BT_GetPGAntNum HALBT_GetPGAntNum -void HALBT_SetKey(struct rtw_adapter * padapter, u8 EntryNum); -void HALBT_RemoveKey(struct rtw_adapter * padapter, u8 EntryNum); -u8 HALBT_IsBTExist(struct rtw_adapter * padapter); +void HALBT_SetKey(struct rtw_adapter *padapter, u8 EntryNum); +void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum); +u8 HALBT_IsBTExist(struct rtw_adapter *padapter); #define BT_IsBtExist HALBT_IsBTExist -u8 HALBT_BTChipType(struct rtw_adapter * padapter); -void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter * padapter); +u8 HALBT_BTChipType(struct rtw_adapter *padapter); +void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/HalBT.c ===== */ diff --git a/drivers/staging/rtl8723au/include/rtl8723a_recv.h b/drivers/staging/rtl8723au/include/rtl8723a_recv.h index 0177bbc1c1c..875d37b3b94 100644 --- a/drivers/staging/rtl8723au/include/rtl8723a_recv.h +++ b/drivers/staging/rtl8723au/include/rtl8723a_recv.h @@ -56,8 +56,8 @@ struct interrupt_msg_format { unsigned int MSG_EX; }; -int rtl8723au_init_recv_priv(struct rtw_adapter * padapter); -void rtl8723au_free_recv_priv(struct rtw_adapter * padapter); +int rtl8723au_init_recv_priv(struct rtw_adapter *padapter); +void rtl8723au_free_recv_priv(struct rtw_adapter *padapter); void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe); void update_recvframe_attrib(struct recv_frame *precvframe, struct recv_stat *prxstat); void update_recvframe_phyinfo(struct recv_frame *precvframe, struct phy_stat *pphy_info); diff --git a/drivers/staging/rtl8723au/include/rtw_cmd.h b/drivers/staging/rtl8723au/include/rtw_cmd.h index 71044107d13..775dcdc1e7b 100644 --- a/drivers/staging/rtl8723au/include/rtw_cmd.h +++ b/drivers/staging/rtl8723au/include/rtw_cmd.h @@ -99,7 +99,6 @@ int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv); u32 rtw_init_evt_priv23a (struct evt_priv *pevtpriv); void rtw_free_evt_priv23a (struct evt_priv *pevtpriv); -void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv); void rtw_evt_notify_isr(struct evt_priv *pevtpriv); enum rtw_drvextra_cmd_id @@ -689,10 +688,10 @@ int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms, boo int rtw_setopmode_cmd23a(struct rtw_adapter *padapter, enum nl80211_iftype ifmode); int rtw_setdatarate_cmd(struct rtw_adapter *padapter, u8 *rateset); int rtw_setbasicrate_cmd(struct rtw_adapter *padapter, u8 *rateset); -int rtw_setbbreg_cmd(struct rtw_adapter * padapter, u8 offset, u8 val); -int rtw_setrfreg_cmd(struct rtw_adapter * padapter, u8 offset, u32 val); -int rtw_getbbreg_cmd(struct rtw_adapter * padapter, u8 offset, u8 * pval); -int rtw_getrfreg_cmd(struct rtw_adapter * padapter, u8 offset, u8 * pval); +int rtw_setbbreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 val); +int rtw_setrfreg_cmd(struct rtw_adapter *padapter, u8 offset, u32 val); +int rtw_getbbreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); +int rtw_getrfreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); int rtw_setrfintfs_cmd(struct rtw_adapter *padapter, u8 mode); int rtw_setrttbl_cmd(struct rtw_adapter *padapter, struct setratable_parm *prate_table); int rtw_getrttbl_cmd(struct rtw_adapter *padapter, struct getratable_rsp *pval); @@ -713,7 +712,6 @@ int rtw_ps_cmd23a(struct rtw_adapter*padapter); int rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter); #endif -int rtw_set_ch_cmd23a(struct rtw_adapter*padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue); int rtw_set_chplan_cmd(struct rtw_adapter*padapter, u8 chplan, u8 enqueue); int rtw_led_blink_cmd(struct rtw_adapter*padapter, struct led_8723a *pLed); int rtw_set_csa_cmd(struct rtw_adapter*padapter, u8 new_ch_no); diff --git a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h index 51dba1fa4c5..ffb37b252fc 100644 --- a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h @@ -509,7 +509,7 @@ int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, struct ieee80211_mgmt *mgmt, u32 packet_len); void update_IOT_info23a(struct rtw_adapter *padapter); void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap); -void update_wireless_mode23a(struct rtw_adapter * padapter); +void update_wireless_mode23a(struct rtw_adapter *padapter); void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 modulation); void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id); int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, diff --git a/drivers/staging/rtl8723au/include/wifi.h b/drivers/staging/rtl8723au/include/wifi.h index fd3da3b5cf3..25d573c3e23 100644 --- a/drivers/staging/rtl8723au/include/wifi.h +++ b/drivers/staging/rtl8723au/include/wifi.h @@ -26,9 +26,9 @@ ------------------------------------------------------------------------------*/ struct AC_param { - unsigned char ACI_AIFSN; - unsigned char CW; - unsigned short TXOP_limit; + u8 ACI_AIFSN; + u8 CW; + __le16 TXOP_limit; } __packed; struct WMM_para_element { @@ -38,10 +38,10 @@ struct WMM_para_element { } __packed; struct ADDBA_request { - unsigned char dialog_token; - unsigned short BA_para_set; - unsigned short BA_timeout_value; - unsigned short BA_starting_seqctrl; + u8 dialog_token; + __le16 BA_para_set; + __le16 BA_timeout_value; + __le16 BA_starting_seqctrl; } __packed; diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c index c5800ae71fc..537bd8214ef 100644 --- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c @@ -1468,9 +1468,8 @@ static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, return 0; } - if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) { + if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK; - } /* if (wpa_version & NL80211_WPA_VERSION_2) diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c index 9966d16342b..1b23eb13222 100644 --- a/drivers/staging/rtl8723au/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723au/os_dep/os_intfs.c @@ -91,7 +91,7 @@ static int rtw_bt_iso = 2;/* 0:Low, 1:High, 2:From Efuse */ /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy, 5.OtherBusy */ static int rtw_bt_sco = 3; /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ -static int rtw_bt_ampdu = 1 ; +static int rtw_bt_ampdu = 1; #endif /* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */ diff --git a/drivers/staging/rtl8723au/os_dep/usb_intf.c b/drivers/staging/rtl8723au/os_dep/usb_intf.c index 373a617ace5..05755b870a5 100644 --- a/drivers/staging/rtl8723au/os_dep/usb_intf.c +++ b/drivers/staging/rtl8723au/os_dep/usb_intf.c @@ -80,11 +80,9 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) struct usb_config_descriptor *pconf_desc; struct usb_host_interface *phost_iface; struct usb_interface_descriptor *piface_desc; - struct usb_host_endpoint *phost_endp; struct usb_endpoint_descriptor *pendp_desc; - struct usb_device *pusbd; - int i; - int status = _FAIL; + struct usb_device *pusbd; + int i, status = _FAIL; pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL); if (!pdvobjpriv) @@ -114,42 +112,38 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints; for (i = 0; i < pdvobjpriv->nr_endpoint; i++) { - phost_endp = phost_iface->endpoint + i; - if (phost_endp) { - pendp_desc = &phost_endp->desc; - - DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i); - DBG_8723A("bLength =%x\n", pendp_desc->bLength); - DBG_8723A("bDescriptorType =%x\n", - pendp_desc->bDescriptorType); - DBG_8723A("bEndpointAddress =%x\n", - pendp_desc->bEndpointAddress); - DBG_8723A("wMaxPacketSize =%d\n", - le16_to_cpu(pendp_desc->wMaxPacketSize)); - DBG_8723A("bInterval =%x\n", pendp_desc->bInterval); - - if (usb_endpoint_is_bulk_in(pendp_desc)) { - DBG_8723A("usb_endpoint_is_bulk_in = %x\n", - usb_endpoint_num(pendp_desc)); - pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumInPipes++; - } else if (usb_endpoint_is_int_in(pendp_desc)) { - DBG_8723A("usb_endpoint_is_int_in = %x, Interval = %x\n", - usb_endpoint_num(pendp_desc), - pendp_desc->bInterval); - pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumInPipes++; - } else if (usb_endpoint_is_bulk_out(pendp_desc)) { - DBG_8723A("usb_endpoint_is_bulk_out = %x\n", - usb_endpoint_num(pendp_desc)); - pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumOutPipes++; - } - pdvobjpriv->ep_num[i] = usb_endpoint_num(pendp_desc); + pendp_desc = &phost_iface->endpoint[i].desc; + + DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i); + DBG_8723A("bLength =%x\n", pendp_desc->bLength); + DBG_8723A("bDescriptorType =%x\n", pendp_desc->bDescriptorType); + DBG_8723A("bEndpointAddress =%x\n", + pendp_desc->bEndpointAddress); + DBG_8723A("wMaxPacketSize =%d\n", + le16_to_cpu(pendp_desc->wMaxPacketSize)); + DBG_8723A("bInterval =%x\n", pendp_desc->bInterval); + + if (usb_endpoint_is_bulk_in(pendp_desc)) { + DBG_8723A("usb_endpoint_is_bulk_in = %x\n", + usb_endpoint_num(pendp_desc)); + pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = + usb_endpoint_num(pendp_desc); + pdvobjpriv->RtNumInPipes++; + } else if (usb_endpoint_is_int_in(pendp_desc)) { + DBG_8723A("usb_endpoint_is_int_in = %x, Interval = " + "%x\n", usb_endpoint_num(pendp_desc), + pendp_desc->bInterval); + pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = + usb_endpoint_num(pendp_desc); + pdvobjpriv->RtNumInPipes++; + } else if (usb_endpoint_is_bulk_out(pendp_desc)) { + DBG_8723A("usb_endpoint_is_bulk_out = %x\n", + usb_endpoint_num(pendp_desc)); + pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = + usb_endpoint_num(pendp_desc); + pdvobjpriv->RtNumOutPipes++; } + pdvobjpriv->ep_num[i] = usb_endpoint_num(pendp_desc); } DBG_8723A("nr_endpoint =%d, in_num =%d, out_num =%d\n\n", pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes, @@ -273,104 +267,6 @@ static void rtw_dev_unload(struct rtw_adapter *padapter) RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n")); } -int rtw_hw_suspend23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct net_device *pnetdev = padapter->pnetdev; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if ((!padapter->bup) || (padapter->bDriverStopped) || - (padapter->bSurpriseRemoved)) { - DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n", - padapter->bup, padapter->bDriverStopped, - padapter->bSurpriseRemoved); - goto error_exit; - } - - if (padapter) { /* system suspend */ - LeaveAllPowerSaveMode23a(padapter); - - DBG_8723A("==> rtw_hw_suspend23a\n"); - down(&pwrpriv->lock); - pwrpriv->bips_processing = true; - /* padapter->net_closed = true; */ - /* s1. */ - if (pnetdev) { - netif_carrier_off(pnetdev); - netif_tx_stop_all_queues(pnetdev); - } - - /* s2. */ - rtw_disassoc_cmd23a(padapter, 500, false); - - /* s2-2. indicate disconnect to os */ - /* rtw_indicate_disconnect23a(padapter); */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - _clr_fwstate_(pmlmepriv, _FW_LINKED); - - rtw_os_indicate_disconnect23a(padapter); - - /* donnot enqueue cmd */ - rtw_lps_ctrl_wk_cmd23a(padapter, - LPS_CTRL_DISCONNECT, 0); - } - /* s2-3. */ - rtw_free_assoc_resources23a(padapter, 1); - - /* s2-4. */ - rtw_free_network_queue23a(padapter); - rtw_ips_dev_unload23a(padapter); - pwrpriv->rf_pwrstate = rf_off; - pwrpriv->bips_processing = false; - up(&pwrpriv->lock); - } else { - goto error_exit; - } - return 0; -error_exit: - DBG_8723A("%s, failed\n", __func__); - return -1; -} - -int rtw_hw_resume23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct net_device *pnetdev = padapter->pnetdev; - - if (padapter) { /* system resume */ - DBG_8723A("==> rtw_hw_resume23a\n"); - down(&pwrpriv->lock); - pwrpriv->bips_processing = true; - rtw_reset_drv_sw23a(padapter); - - if (pm_netdev_open23a(pnetdev, false)) { - up(&pwrpriv->lock); - goto error_exit; - } - - netif_device_attach(pnetdev); - netif_carrier_on(pnetdev); - - if (!rtw_netif_queue_stopped(pnetdev)) - netif_tx_start_all_queues(pnetdev); - else - netif_tx_wake_all_queues(pnetdev); - - pwrpriv->bkeepfwalive = false; - - pwrpriv->rf_pwrstate = rf_on; - pwrpriv->bips_processing = false; - - up(&pwrpriv->lock); - } else { - goto error_exit; - } - return 0; -error_exit: - DBG_8723A("%s, Open net dev failed\n", __func__); - return -1; -} - static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) { struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index b4612fb615f..a47a19135d4 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -781,7 +781,7 @@ static int msxc_change_power(struct rtsx_chip *chip, u8 mode) buf[4] = 0; buf[5] = 0; - retval = ms_write_bytes(chip, PRO_WRITE_REG , 6, NO_WAIT_INT, buf, 6); + retval = ms_write_bytes(chip, PRO_WRITE_REG, 6, NO_WAIT_INT, buf, 6); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); @@ -1291,7 +1291,7 @@ static int ms_write_extra_data(struct rtsx_chip *chip, for (i = 6; i < MS_EXTRA_SIZE + 6; i++) data[i] = buf[i - 6]; - retval = ms_write_bytes(chip, WRITE_REG , (6+MS_EXTRA_SIZE), + retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE), NO_WAIT_INT, data, 16); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); @@ -1342,7 +1342,7 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) data[4] = 0x20; data[5] = page_num; - retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, data, 6); + retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); @@ -1619,7 +1619,7 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, data[4] = 0x20; data[5] = i; - retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, + retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); @@ -1695,7 +1695,7 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, (6+MS_EXTRA_SIZE)); + MS_EXTRA_SIZE, SystemParm, (6 + MS_EXTRA_SIZE)); ms_set_err_code(chip, MS_NO_ERROR); @@ -1988,7 +1988,7 @@ RE_SEARCH: RTSX_WRITE_REG(chip, PPBUF_BASE2, 0xFF, 0x88); RTSX_WRITE_REG(chip, PPBUF_BASE2 + 1, 0xFF, 0); - retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG , 1, + retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG, 1, NO_WAIT_INT); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c index 756a9687c29..dab1995d1a6 100644 --- a/drivers/staging/rts5208/rtsx_transport.c +++ b/drivers/staging/rts5208/rtsx_transport.c @@ -271,7 +271,7 @@ int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout) /* Wait for TRANS_OK_INT */ timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n", chip->int_reg); @@ -431,7 +431,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, spin_unlock_irq(&rtsx->reg_lock); timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); @@ -455,7 +455,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, init_completion(&trans_done); spin_unlock_irq(&rtsx->reg_lock); timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); @@ -575,7 +575,7 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, spin_unlock_irq(&rtsx->reg_lock); timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); @@ -602,7 +602,7 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, init_completion(&trans_done); spin_unlock_irq(&rtsx->reg_lock); timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); @@ -688,7 +688,7 @@ static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, /* Wait for TRANS_OK_INT */ timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); diff --git a/drivers/staging/skein/skein_block.c b/drivers/staging/skein/skein_block.c index 66261ab25c8..9bd69ce3be0 100644 --- a/drivers/staging/skein/skein_block.c +++ b/drivers/staging/skein/skein_block.c @@ -82,10 +82,7 @@ do { \ } while (0) #else /* looping version */ -#define R256(p0, p1, p2, p3, ROT, r_num) \ -do { \ - ROUND256(p0, p1, p2, p3, ROT, r_num); \ -} while (0) +#define R256(p0, p1, p2, p3, ROT, r_num) ROUND256(p0, p1, p2, p3, ROT, r_num) #define I256(R) \ do { \ @@ -174,9 +171,7 @@ do { \ #else /* looping version */ #define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) \ -do { \ - ROUND512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num); \ -} while (0) + ROUND512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) \ #define I512(R) \ do { \ @@ -263,10 +258,8 @@ do { \ #if SKEIN_UNROLL_1024 == 0 #define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, pF, \ ROT, rn) \ -do { \ ROUND1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, \ - pF, ROT, rn); \ -} while (0) + pF, ROT, rn) \ #define I1024(R) \ do { \ @@ -291,10 +284,8 @@ do { \ #else /* looping version */ #define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, pF, \ ROT, rn) \ -do { \ ROUND1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, \ - pF, ROT, rn); \ -} while (0) + pF, ROT, rn) \ #define I1024(R) \ do { \ diff --git a/drivers/staging/skein/skein_generic.c b/drivers/staging/skein/skein_generic.c index 85bd7d0168b..899078f1b8b 100644 --- a/drivers/staging/skein/skein_generic.c +++ b/drivers/staging/skein/skein_generic.c @@ -191,7 +191,6 @@ static int __init skein_generic_init(void) return 0; - unreg512: crypto_unregister_shash(&alg512); unreg256: diff --git a/drivers/staging/sm7xxfb/Kconfig b/drivers/staging/sm7xxfb/Kconfig new file mode 100644 index 00000000000..e2922ae3a3e --- /dev/null +++ b/drivers/staging/sm7xxfb/Kconfig @@ -0,0 +1,13 @@ +config FB_SM7XX + tristate "Silicon Motion SM7XX framebuffer support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Frame buffer driver for the Silicon Motion SM710, SM712, SM721 + and SM722 chips. + + This driver is also available as a module. The module will be + called sm7xxfb. If you want to compile it as a module, say M + here and read <file:Documentation/kbuild/modules.txt>. diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile new file mode 100644 index 00000000000..48f471cf9f3 --- /dev/null +++ b/drivers/staging/sm7xxfb/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO new file mode 100644 index 00000000000..7cb0b242f20 --- /dev/null +++ b/drivers/staging/sm7xxfb/TODO @@ -0,0 +1,12 @@ +TODO: +- Dual head support +- 2D acceleration support +- use kernel coding style +- refine the code and remove unused code +- move it to drivers/video/fbdev/sm7xxfb.c + +Please send any patches to + Greg Kroah-Hartman <greg@kroah.com> + Sudip Mukherjee <sudipm.mukherjee@gmail.com> + Teddy Wang <teddy.wang@siliconmotion.com> + Sudip Mukherjee <sudip@vectorindia.org> diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h new file mode 100644 index 00000000000..7cc1896938b --- /dev/null +++ b/drivers/staging/sm7xxfb/sm7xx.h @@ -0,0 +1,779 @@ +/* + * Silicon Motion SM712 frame buffer device + * + * Copyright (C) 2006 Silicon Motion Technology Corp. + * Authors: Ge Wang, gewang@siliconmotion.com + * Boyod boyod.yang@siliconmotion.com.cn + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzhangjin@gmail.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#define NR_PALETTE 256 + +#define FB_ACCEL_SMI_LYNX 88 + +#define SCREEN_X_RES 1024 +#define SCREEN_Y_RES 600 +#define SCREEN_BPP 16 + +/*Assume SM712 graphics chip has 4MB VRAM */ +#define SM712_VIDEOMEMORYSIZE 0x00400000 +/*Assume SM722 graphics chip has 8MB VRAM */ +#define SM722_VIDEOMEMORYSIZE 0x00800000 + +#define dac_reg (0x3c8) +#define dac_val (0x3c9) + +extern void __iomem *smtc_regbaseaddress; +#define smtc_mmiowb(dat, reg) writeb(dat, smtc_regbaseaddress + reg) +#define smtc_mmioww(dat, reg) writew(dat, smtc_regbaseaddress + reg) +#define smtc_mmiowl(dat, reg) writel(dat, smtc_regbaseaddress + reg) + +#define smtc_mmiorb(reg) readb(smtc_regbaseaddress + reg) +#define smtc_mmiorw(reg) readw(smtc_regbaseaddress + reg) +#define smtc_mmiorl(reg) readl(smtc_regbaseaddress + reg) + +#define SIZE_SR00_SR04 (0x04 - 0x00 + 1) +#define SIZE_SR10_SR24 (0x24 - 0x10 + 1) +#define SIZE_SR30_SR75 (0x75 - 0x30 + 1) +#define SIZE_SR80_SR93 (0x93 - 0x80 + 1) +#define SIZE_SRA0_SRAF (0xAF - 0xA0 + 1) +#define SIZE_GR00_GR08 (0x08 - 0x00 + 1) +#define SIZE_AR00_AR14 (0x14 - 0x00 + 1) +#define SIZE_CR00_CR18 (0x18 - 0x00 + 1) +#define SIZE_CR30_CR4D (0x4D - 0x30 + 1) +#define SIZE_CR90_CRA7 (0xA7 - 0x90 + 1) +#define SIZE_VPR (0x6C + 1) +#define SIZE_DPR (0x44 + 1) + +static inline void smtc_crtcw(int reg, int val) +{ + smtc_mmiowb(reg, 0x3d4); + smtc_mmiowb(val, 0x3d5); +} + +static inline unsigned int smtc_crtcr(int reg) +{ + smtc_mmiowb(reg, 0x3d4); + return smtc_mmiorb(0x3d5); +} + +static inline void smtc_grphw(int reg, int val) +{ + smtc_mmiowb(reg, 0x3ce); + smtc_mmiowb(val, 0x3cf); +} + +static inline unsigned int smtc_grphr(int reg) +{ + smtc_mmiowb(reg, 0x3ce); + return smtc_mmiorb(0x3cf); +} + +static inline void smtc_attrw(int reg, int val) +{ + smtc_mmiorb(0x3da); + smtc_mmiowb(reg, 0x3c0); + smtc_mmiorb(0x3c1); + smtc_mmiowb(val, 0x3c0); +} + +static inline void smtc_seqw(int reg, int val) +{ + smtc_mmiowb(reg, 0x3c4); + smtc_mmiowb(val, 0x3c5); +} + +static inline unsigned int smtc_seqr(int reg) +{ + smtc_mmiowb(reg, 0x3c4); + return smtc_mmiorb(0x3c5); +} + +/* The next structure holds all information relevant for a specific video mode. + */ + +struct ModeInit { + int mmsizex; + int mmsizey; + int bpp; + int hz; + unsigned char init_misc; + unsigned char init_sr00_sr04[SIZE_SR00_SR04]; + unsigned char init_sr10_sr24[SIZE_SR10_SR24]; + unsigned char init_sr30_sr75[SIZE_SR30_SR75]; + unsigned char init_sr80_sr93[SIZE_SR80_SR93]; + unsigned char init_sra0_sraf[SIZE_SRA0_SRAF]; + unsigned char init_gr00_gr08[SIZE_GR00_GR08]; + unsigned char init_ar00_ar14[SIZE_AR00_AR14]; + unsigned char init_cr00_cr18[SIZE_CR00_CR18]; + unsigned char init_cr30_cr4d[SIZE_CR30_CR4D]; + unsigned char init_cr90_cra7[SIZE_CR90_CRA7]; +}; + +/********************************************************************** + SM712 Mode table. + **********************************************************************/ +struct ModeInit vgamode[] = { + { + /* mode#0: 640 x 480 16Bpp 60Hz */ + 640, 480, 16, 60, + /* Init_MISC */ + 0xE3, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + }, + }, + { + /* mode#1: 640 x 480 24Bpp 60Hz */ + 640, 480, 24, 60, + /* Init_MISC */ + 0xE3, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + }, + }, + { + /* mode#0: 640 x 480 32Bpp 60Hz */ + 640, 480, 32, 60, + /* Init_MISC */ + 0xE3, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + }, + }, + + { /* mode#2: 800 x 600 16Bpp 60Hz */ + 800, 600, 16, 60, + /* Init_MISC */ + 0x2B, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24, + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, + 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24, + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, + 0x02, 0x45, 0x30, 0x35, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, + }, + }, + { /* mode#3: 800 x 600 24Bpp 60Hz */ + 800, 600, 24, 60, + 0x2B, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36, + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, + 0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, + 0x02, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, + }, + }, + { /* mode#7: 800 x 600 32Bpp 60Hz */ + 800, 600, 32, 60, + /* Init_MISC */ + 0x2B, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24, + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, + 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24, + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, + 0x02, 0x45, 0x30, 0x35, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, + }, + }, + /* We use 1024x768 table to light 1024x600 panel for lemote */ + { /* mode#4: 1024 x 600 16Bpp 60Hz */ + 1024, 600, 16, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20, + 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x00, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22, + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02, + 0x04, 0x45, 0x3F, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00, + 0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + { /* mode#5: 1024 x 768 24Bpp 60Hz */ + 1024, 768, 24, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00, + 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + { /* mode#4: 1024 x 768 32Bpp 60Hz */ + 1024, 768, 32, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x32, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00, + 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + { /* mode#6: 320 x 240 16Bpp 60Hz */ + 320, 240, 16, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x32, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00, + 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + + { /* mode#8: 320 x 240 32Bpp 60Hz */ + 320, 240, 32, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x32, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00, + 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, +}; + +#define numvgamodes ARRAY_SIZE(vgamode) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c new file mode 100644 index 00000000000..ebd95365ffa --- /dev/null +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -0,0 +1,1024 @@ +/* + * Silicon Motion SM7XX frame buffer device + * + * Copyright (C) 2006 Silicon Motion Technology Corp. + * Authors: Ge Wang, gewang@siliconmotion.com + * Boyod boyod.yang@siliconmotion.com.cn + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzhangjin@gmail.com + * + * Copyright (C) 2011 Igalia, S.L. + * Author: Javier M. Mellid <jmunhoz@igalia.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips + */ + +#include <linux/io.h> +#include <linux/fb.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/module.h> +#include <linux/console.h> +#include <linux/screen_info.h> + +#ifdef CONFIG_PM +#include <linux/pm.h> +#endif + +#include "sm7xx.h" + +/* +* Private structure +*/ +struct smtcfb_info { + struct pci_dev *pdev; + struct fb_info fb; + u16 chip_id; + u8 chip_rev_id; + + void __iomem *lfb; /* linear frame buffer */ + void __iomem *dp_regs; /* drawing processor control regs */ + void __iomem *vp_regs; /* video processor control regs */ + void __iomem *cp_regs; /* capture processor control regs */ + void __iomem *mmio; /* memory map IO port */ + + u_int width; + u_int height; + u_int hz; + + u32 colreg[17]; +}; + +void __iomem *smtc_regbaseaddress; /* Memory Map IO starting address */ + +static struct fb_var_screeninfo smtcfb_var = { + .xres = 1024, + .yres = 600, + .xres_virtual = 1024, + .yres_virtual = 600, + .bits_per_pixel = 16, + .red = {16, 8, 0}, + .green = {8, 8, 0}, + .blue = {0, 8, 0}, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .vmode = FB_VMODE_NONINTERLACED, + .nonstd = 0, + .accel_flags = FB_ACCELF_TEXT, +}; + +static struct fb_fix_screeninfo smtcfb_fix = { + .id = "smXXXfb", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .line_length = 800 * 3, + .accel = FB_ACCEL_SMI_LYNX, + .type_aux = 0, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, +}; + +struct vesa_mode { + char index[6]; + u16 lfb_width; + u16 lfb_height; + u16 lfb_depth; +}; + +static struct vesa_mode vesa_mode_table[] = { + {"0x301", 640, 480, 8}, + {"0x303", 800, 600, 8}, + {"0x305", 1024, 768, 8}, + {"0x307", 1280, 1024, 8}, + + {"0x311", 640, 480, 16}, + {"0x314", 800, 600, 16}, + {"0x317", 1024, 768, 16}, + {"0x31A", 1280, 1024, 16}, + + {"0x312", 640, 480, 24}, + {"0x315", 800, 600, 24}, + {"0x318", 1024, 768, 24}, + {"0x31B", 1280, 1024, 24}, +}; + +static struct screen_info smtc_scr_info; + +/* process command line options, get vga parameter */ +static int __init sm7xx_vga_setup(char *options) +{ + int i; + + if (!options || !*options) + return -EINVAL; + + smtc_scr_info.lfb_width = 0; + smtc_scr_info.lfb_height = 0; + smtc_scr_info.lfb_depth = 0; + + pr_debug("sm7xx_vga_setup = %s\n", options); + + for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) { + if (strstr(options, vesa_mode_table[i].index)) { + smtc_scr_info.lfb_width = vesa_mode_table[i].lfb_width; + smtc_scr_info.lfb_height = + vesa_mode_table[i].lfb_height; + smtc_scr_info.lfb_depth = vesa_mode_table[i].lfb_depth; + return 0; + } + } + + return -1; +} +__setup("vga=", sm7xx_vga_setup); + +static void sm712_setpalette(int regno, unsigned red, unsigned green, + unsigned blue, struct fb_info *info) +{ + /* set bit 5:4 = 01 (write LCD RAM only) */ + smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10); + + smtc_mmiowb(regno, dac_reg); + smtc_mmiowb(red >> 10, dac_val); + smtc_mmiowb(green >> 10, dac_val); + smtc_mmiowb(blue >> 10, dac_val); +} + +/* chan_to_field + * + * convert a colour value into a field position + * + * from pxafb.c + */ + +static inline unsigned int chan_to_field(unsigned int chan, + struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int smtc_blank(int blank_mode, struct fb_info *info) +{ + /* clear DPMS setting */ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + /* Screen On: HSync: On, VSync : On */ + smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20))); + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77)); + smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30))); + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0))); + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01)); + smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03)); + break; + case FB_BLANK_NORMAL: + /* Screen Off: HSync: On, VSync : On Soft blank */ + smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20))); + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30))); + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0))); + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01)); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + break; + case FB_BLANK_VSYNC_SUSPEND: + /* Screen On: HSync: On, VSync : Off */ + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); + smtc_seqw(0x6a, 0x0c); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20)); + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20)); + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); + break; + case FB_BLANK_HSYNC_SUSPEND: + /* Screen On: HSync: Off, VSync : On */ + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); + smtc_seqw(0x6a, 0x0c); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10)); + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8)); + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); + break; + case FB_BLANK_POWERDOWN: + /* Screen On: HSync: Off, VSync : Off */ + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); + smtc_seqw(0x6a, 0x0c); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30)); + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8)); + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned trans, struct fb_info *info) +{ + struct smtcfb_info *sfb; + u32 val; + + sfb = info->par; + + if (regno > 255) + return 1; + + switch (sfb->fb.fix.visual) { + case FB_VISUAL_DIRECTCOLOR: + case FB_VISUAL_TRUECOLOR: + /* + * 16/32 bit true-colour, use pseudo-palette for 16 base color + */ + if (regno < 16) { + if (sfb->fb.var.bits_per_pixel == 16) { + u32 *pal = sfb->fb.pseudo_palette; + + val = chan_to_field(red, &sfb->fb.var.red); + val |= chan_to_field(green, &sfb->fb.var.green); + val |= chan_to_field(blue, &sfb->fb.var.blue); +#ifdef __BIG_ENDIAN + pal[regno] = + ((red & 0xf800) >> 8) | + ((green & 0xe000) >> 13) | + ((green & 0x1c00) << 3) | + ((blue & 0xf800) >> 3); +#else + pal[regno] = val; +#endif + } else { + u32 *pal = sfb->fb.pseudo_palette; + + val = chan_to_field(red, &sfb->fb.var.red); + val |= chan_to_field(green, &sfb->fb.var.green); + val |= chan_to_field(blue, &sfb->fb.var.blue); +#ifdef __BIG_ENDIAN + val = + (val & 0xff00ff00 >> 8) | + (val & 0x00ff00ff << 8); +#endif + pal[regno] = val; + } + } + break; + + case FB_VISUAL_PSEUDOCOLOR: + /* color depth 8 bit */ + sm712_setpalette(regno, red, green, blue, info); + break; + + default: + return 1; /* unknown type */ + } + + return 0; +} + +#ifdef __BIG_ENDIAN +static ssize_t smtcfb_read(struct fb_info *info, char __user *buf, size_t + count, loff_t *ppos) +{ + unsigned long p = *ppos; + + u32 *buffer, *dst; + u32 __iomem *src; + int c, i, cnt = 0, err = 0; + unsigned long total_size; + + if (!info || !info->screen_base) + return -ENODEV; + + if (info->state != FBINFO_STATE_RUNNING) + return -EPERM; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p >= total_size) + return 0; + + if (count >= total_size) + count = total_size; + + if (count + p > total_size) + count = total_size - p; + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + src = (u32 __iomem *) (info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + dst = buffer; + for (i = c >> 2; i--;) { + *dst = fb_readl(src++); + *dst = + (*dst & 0xff00ff00 >> 8) | + (*dst & 0x00ff00ff << 8); + dst++; + } + if (c & 3) { + u8 *dst8 = (u8 *)dst; + u8 __iomem *src8 = (u8 __iomem *)src; + + for (i = c & 3; i--;) { + if (i & 1) { + *dst8++ = fb_readb(++src8); + } else { + *dst8++ = fb_readb(--src8); + src8 += 2; + } + } + src = (u32 __iomem *)src8; + } + + if (copy_to_user(buf, buffer, c)) { + err = -EFAULT; + break; + } + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return (err) ? err : cnt; +} + +static ssize_t +smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, + loff_t *ppos) +{ + unsigned long p = *ppos; + + u32 *buffer, *src; + u32 __iomem *dst; + int c, i, cnt = 0, err = 0; + unsigned long total_size; + + if (!info || !info->screen_base) + return -ENODEV; + + if (info->state != FBINFO_STATE_RUNNING) + return -EPERM; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p > total_size) + return -EFBIG; + + if (count > total_size) { + err = -EFBIG; + count = total_size; + } + + if (count + p > total_size) { + if (!err) + err = -ENOSPC; + + count = total_size - p; + } + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + dst = (u32 __iomem *) (info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + src = buffer; + + if (copy_from_user(src, buf, c)) { + err = -EFAULT; + break; + } + + for (i = c >> 2; i--;) { + fb_writel((*src & 0xff00ff00 >> 8) | + (*src & 0x00ff00ff << 8), dst++); + src++; + } + if (c & 3) { + u8 *src8 = (u8 *)src; + u8 __iomem *dst8 = (u8 __iomem *)dst; + + for (i = c & 3; i--;) { + if (i & 1) { + fb_writeb(*src8++, ++dst8); + } else { + fb_writeb(*src8++, --dst8); + dst8 += 2; + } + } + dst = (u32 __iomem *)dst8; + } + + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return (cnt) ? cnt : err; +} +#endif /* ! __BIG_ENDIAN */ + +static void sm7xx_set_timing(struct smtcfb_info *sfb) +{ + int i = 0, j = 0; + u32 m_nscreenstride; + + dev_dbg(&sfb->pdev->dev, + "sfb->width=%d sfb->height=%d sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n", + sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz); + + for (j = 0; j < numvgamodes; j++) { + if (vgamode[j].mmsizex == sfb->width && + vgamode[j].mmsizey == sfb->height && + vgamode[j].bpp == sfb->fb.var.bits_per_pixel && + vgamode[j].hz == sfb->hz) { + dev_dbg(&sfb->pdev->dev, + "vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n", + vgamode[j].mmsizex, vgamode[j].mmsizey, + vgamode[j].bpp, vgamode[j].hz); + + dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j); + + smtc_mmiowb(0x0, 0x3c6); + + smtc_seqw(0, 0x1); + + smtc_mmiowb(vgamode[j].init_misc, 0x3c2); + + /* init SEQ register SR00 - SR04 */ + for (i = 0; i < SIZE_SR00_SR04; i++) + smtc_seqw(i, vgamode[j].init_sr00_sr04[i]); + + /* init SEQ register SR10 - SR24 */ + for (i = 0; i < SIZE_SR10_SR24; i++) + smtc_seqw(i + 0x10, + vgamode[j].init_sr10_sr24[i]); + + /* init SEQ register SR30 - SR75 */ + for (i = 0; i < SIZE_SR30_SR75; i++) + if ((i + 0x30) != 0x62 && + (i + 0x30) != 0x6a && + (i + 0x30) != 0x6b) + smtc_seqw(i + 0x30, + vgamode[j].init_sr30_sr75[i]); + + /* init SEQ register SR80 - SR93 */ + for (i = 0; i < SIZE_SR80_SR93; i++) + smtc_seqw(i + 0x80, + vgamode[j].init_sr80_sr93[i]); + + /* init SEQ register SRA0 - SRAF */ + for (i = 0; i < SIZE_SRA0_SRAF; i++) + smtc_seqw(i + 0xa0, + vgamode[j].init_sra0_sraf[i]); + + /* init Graphic register GR00 - GR08 */ + for (i = 0; i < SIZE_GR00_GR08; i++) + smtc_grphw(i, vgamode[j].init_gr00_gr08[i]); + + /* init Attribute register AR00 - AR14 */ + for (i = 0; i < SIZE_AR00_AR14; i++) + smtc_attrw(i, vgamode[j].init_ar00_ar14[i]); + + /* init CRTC register CR00 - CR18 */ + for (i = 0; i < SIZE_CR00_CR18; i++) + smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]); + + /* init CRTC register CR30 - CR4D */ + for (i = 0; i < SIZE_CR30_CR4D; i++) + smtc_crtcw(i + 0x30, + vgamode[j].init_cr30_cr4d[i]); + + /* init CRTC register CR90 - CRA7 */ + for (i = 0; i < SIZE_CR90_CRA7; i++) + smtc_crtcw(i + 0x90, + vgamode[j].init_cr90_cra7[i]); + } + } + smtc_mmiowb(0x67, 0x3c2); + + /* set VPR registers */ + writel(0x0, sfb->vp_regs + 0x0C); + writel(0x0, sfb->vp_regs + 0x40); + + /* set data width */ + m_nscreenstride = + (sfb->width * sfb->fb.var.bits_per_pixel) / 64; + switch (sfb->fb.var.bits_per_pixel) { + case 8: + writel(0x0, sfb->vp_regs + 0x0); + break; + case 16: + writel(0x00020000, sfb->vp_regs + 0x0); + break; + case 24: + writel(0x00040000, sfb->vp_regs + 0x0); + break; + case 32: + writel(0x00030000, sfb->vp_regs + 0x0); + break; + } + writel((u32) (((m_nscreenstride + 2) << 16) | m_nscreenstride), + sfb->vp_regs + 0x10); +} + +static void smtc_set_timing(struct smtcfb_info *sfb) +{ + switch (sfb->chip_id) { + case 0x710: + case 0x712: + case 0x720: + sm7xx_set_timing(sfb); + break; + } +} + +static void smtcfb_setmode(struct smtcfb_info *sfb) +{ + switch (sfb->fb.var.bits_per_pixel) { + case 32: + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres * 4; + sfb->fb.var.red.length = 8; + sfb->fb.var.green.length = 8; + sfb->fb.var.blue.length = 8; + sfb->fb.var.red.offset = 16; + sfb->fb.var.green.offset = 8; + sfb->fb.var.blue.offset = 0; + break; + case 24: + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres * 3; + sfb->fb.var.red.length = 8; + sfb->fb.var.green.length = 8; + sfb->fb.var.blue.length = 8; + sfb->fb.var.red.offset = 16; + sfb->fb.var.green.offset = 8; + sfb->fb.var.blue.offset = 0; + break; + case 8: + sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres; + sfb->fb.var.red.length = 3; + sfb->fb.var.green.length = 3; + sfb->fb.var.blue.length = 2; + sfb->fb.var.red.offset = 5; + sfb->fb.var.green.offset = 2; + sfb->fb.var.blue.offset = 0; + break; + case 16: + default: + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres * 2; + sfb->fb.var.red.length = 5; + sfb->fb.var.green.length = 6; + sfb->fb.var.blue.length = 5; + sfb->fb.var.red.offset = 11; + sfb->fb.var.green.offset = 5; + sfb->fb.var.blue.offset = 0; + break; + } + + sfb->width = sfb->fb.var.xres; + sfb->height = sfb->fb.var.yres; + sfb->hz = 60; + smtc_set_timing(sfb); +} + +static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + /* sanity checks */ + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + + /* set valid default bpp */ + if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16) && + (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32)) + var->bits_per_pixel = 16; + + return 0; +} + +static int smtc_set_par(struct fb_info *info) +{ + smtcfb_setmode(info->par); + + return 0; +} + +static struct fb_ops smtcfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = smtc_check_var, + .fb_set_par = smtc_set_par, + .fb_setcolreg = smtc_setcolreg, + .fb_blank = smtc_blank, + .fb_fillrect = cfb_fillrect, + .fb_imageblit = cfb_imageblit, + .fb_copyarea = cfb_copyarea, +#ifdef __BIG_ENDIAN + .fb_read = smtcfb_read, + .fb_write = smtcfb_write, +#endif +}; + +/* + * alloc struct smtcfb_info and assign default values + */ +static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev) +{ + struct smtcfb_info *sfb; + + sfb = kzalloc(sizeof(*sfb), GFP_KERNEL); + + if (!sfb) + return NULL; + + sfb->pdev = pdev; + + sfb->fb.flags = FBINFO_FLAG_DEFAULT; + sfb->fb.fbops = &smtcfb_ops; + sfb->fb.fix = smtcfb_fix; + sfb->fb.var = smtcfb_var; + sfb->fb.pseudo_palette = sfb->colreg; + sfb->fb.par = sfb; + + return sfb; +} + +/* + * free struct smtcfb_info + */ +static void smtc_free_fb_info(struct smtcfb_info *sfb) +{ + kfree(sfb); +} + +/* + * Unmap in the memory mapped IO registers + */ + +static void smtc_unmap_mmio(struct smtcfb_info *sfb) +{ + if (sfb && smtc_regbaseaddress) + smtc_regbaseaddress = NULL; +} + +/* + * Map in the screen memory + */ + +static int smtc_map_smem(struct smtcfb_info *sfb, + struct pci_dev *pdev, u_long smem_len) +{ + sfb->fb.fix.smem_start = pci_resource_start(pdev, 0); + +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) + sfb->fb.fix.smem_start += 0x800000; +#endif + + sfb->fb.fix.smem_len = smem_len; + + sfb->fb.screen_base = sfb->lfb; + + if (!sfb->fb.screen_base) { + dev_err(&pdev->dev, + "%s: unable to map screen memory\n", sfb->fb.fix.id); + return -ENOMEM; + } + + return 0; +} + +/* + * Unmap in the screen memory + * + */ +static void smtc_unmap_smem(struct smtcfb_info *sfb) +{ + if (sfb && sfb->fb.screen_base) { + iounmap(sfb->fb.screen_base); + sfb->fb.screen_base = NULL; + } +} + +/* + * We need to wake up the device and make sure its in linear memory mode. + */ +static inline void sm7xx_init_hw(void) +{ + outb_p(0x18, 0x3c4); + outb_p(0x11, 0x3c5); +} + +static int smtcfb_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct smtcfb_info *sfb; + u_long smem_size = 0x00800000; /* default 8MB */ + int err; + unsigned long mmio_base; + + dev_info(&pdev->dev, "Silicon Motion display driver."); + + err = pci_enable_device(pdev); /* enable SMTC chip */ + if (err) + return err; + + sprintf(smtcfb_fix.id, "sm%Xfb", ent->device); + + sfb = smtc_alloc_fb_info(pdev); + + if (!sfb) { + err = -ENOMEM; + goto failed_free; + } + + sfb->chip_id = ent->device; + + pci_set_drvdata(pdev, sfb); + + sm7xx_init_hw(); + + /* get mode parameter from smtc_scr_info */ + if (smtc_scr_info.lfb_width != 0) { + sfb->fb.var.xres = smtc_scr_info.lfb_width; + sfb->fb.var.yres = smtc_scr_info.lfb_height; + sfb->fb.var.bits_per_pixel = smtc_scr_info.lfb_depth; + } else { + /* default resolution 1024x600 16bit mode */ + sfb->fb.var.xres = SCREEN_X_RES; + sfb->fb.var.yres = SCREEN_Y_RES; + sfb->fb.var.bits_per_pixel = SCREEN_BPP; + } + +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 24) + sfb->fb.var.bits_per_pixel = (smtc_scr_info.lfb_depth = 32); +#endif + /* Map address and memory detection */ + mmio_base = pci_resource_start(pdev, 0); + pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id); + + switch (sfb->chip_id) { + case 0x710: + case 0x712: + sfb->fb.fix.mmio_start = mmio_base + 0x00400000; + sfb->fb.fix.mmio_len = 0x00400000; + smem_size = SM712_VIDEOMEMORYSIZE; +#ifdef __BIG_ENDIAN + sfb->lfb = ioremap(mmio_base, 0x00c00000); +#else + sfb->lfb = ioremap(mmio_base, 0x00800000); +#endif + sfb->mmio = (smtc_regbaseaddress = + sfb->lfb + 0x00700000); + sfb->dp_regs = sfb->lfb + 0x00408000; + sfb->vp_regs = sfb->lfb + 0x0040c000; +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) { + sfb->lfb += 0x800000; + dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb); + } +#endif + if (!smtc_regbaseaddress) { + dev_err(&pdev->dev, + "%s: unable to map memory mapped IO!", + sfb->fb.fix.id); + err = -ENOMEM; + goto failed_fb; + } + + /* set MCLK = 14.31818 * (0x16 / 0x2) */ + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x62, 0x3e); + /* enable PCI burst */ + smtc_seqw(0x17, 0x20); + /* enable word swap */ +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) + smtc_seqw(0x17, 0x30); +#endif + break; + case 0x720: + sfb->fb.fix.mmio_start = mmio_base; + sfb->fb.fix.mmio_len = 0x00200000; + smem_size = SM722_VIDEOMEMORYSIZE; + sfb->dp_regs = ioremap(mmio_base, 0x00a00000); + sfb->lfb = sfb->dp_regs + 0x00200000; + sfb->mmio = (smtc_regbaseaddress = + sfb->dp_regs + 0x000c0000); + sfb->vp_regs = sfb->dp_regs + 0x800; + + smtc_seqw(0x62, 0xff); + smtc_seqw(0x6a, 0x0d); + smtc_seqw(0x6b, 0x02); + break; + default: + dev_err(&pdev->dev, + "No valid Silicon Motion display chip was detected!"); + + goto failed_fb; + } + + /* can support 32 bpp */ + if (15 == sfb->fb.var.bits_per_pixel) + sfb->fb.var.bits_per_pixel = 16; + + sfb->fb.var.xres_virtual = sfb->fb.var.xres; + sfb->fb.var.yres_virtual = sfb->fb.var.yres; + err = smtc_map_smem(sfb, pdev, smem_size); + if (err) + goto failed; + + smtcfb_setmode(sfb); + + err = register_framebuffer(&sfb->fb); + if (err < 0) + goto failed; + + dev_info(&pdev->dev, + "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.", + sfb->chip_id, sfb->chip_rev_id, sfb->fb.var.xres, + sfb->fb.var.yres, sfb->fb.var.bits_per_pixel); + + return 0; + +failed: + dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail."); + + smtc_unmap_smem(sfb); + smtc_unmap_mmio(sfb); +failed_fb: + smtc_free_fb_info(sfb); + +failed_free: + pci_disable_device(pdev); + + return err; +} + +/* + * 0x710 (LynxEM) + * 0x712 (LynxEM+) + * 0x720 (Lynx3DM, Lynx3DM+) + */ +static const struct pci_device_id smtcfb_pci_table[] = { + { PCI_DEVICE(0x126f, 0x710), }, + { PCI_DEVICE(0x126f, 0x712), }, + { PCI_DEVICE(0x126f, 0x720), }, + {0,} +}; + +static void smtcfb_pci_remove(struct pci_dev *pdev) +{ + struct smtcfb_info *sfb; + + sfb = pci_get_drvdata(pdev); + smtc_unmap_smem(sfb); + smtc_unmap_mmio(sfb); + unregister_framebuffer(&sfb->fb); + smtc_free_fb_info(sfb); +} + +#ifdef CONFIG_PM +static int smtcfb_pci_suspend(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct smtcfb_info *sfb; + + sfb = pci_get_drvdata(pdev); + + /* set the hw in sleep mode use external clock and self memory refresh + * so that we can turn off internal PLLs later on + */ + smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0)); + smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7)); + + console_lock(); + fb_set_suspend(&sfb->fb, 1); + console_unlock(); + + /* additionally turn off all function blocks including internal PLLs */ + smtc_seqw(0x21, 0xff); + + return 0; +} + +static int smtcfb_pci_resume(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct smtcfb_info *sfb; + + sfb = pci_get_drvdata(pdev); + + /* reinit hardware */ + sm7xx_init_hw(); + switch (sfb->chip_id) { + case 0x710: + case 0x712: + /* set MCLK = 14.31818 * (0x16 / 0x2) */ + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x62, 0x3e); + /* enable PCI burst */ + smtc_seqw(0x17, 0x20); +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) + smtc_seqw(0x17, 0x30); +#endif + break; + case 0x720: + smtc_seqw(0x62, 0xff); + smtc_seqw(0x6a, 0x0d); + smtc_seqw(0x6b, 0x02); + break; + } + + smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0)); + smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb)); + + smtcfb_setmode(sfb); + + console_lock(); + fb_set_suspend(&sfb->fb, 0); + console_unlock(); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume); +#define SM7XX_PM_OPS (&sm7xx_pm_ops) + +#else /* !CONFIG_PM */ + +#define SM7XX_PM_OPS NULL + +#endif /* !CONFIG_PM */ + +static struct pci_driver smtcfb_driver = { + .name = "smtcfb", + .id_table = smtcfb_pci_table, + .probe = smtcfb_pci_probe, + .remove = smtcfb_pci_remove, + .driver.pm = SM7XX_PM_OPS, +}; + +module_pci_driver(smtcfb_driver); + +MODULE_AUTHOR("Siliconmotion "); +MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/speakup/i18n.h b/drivers/staging/speakup/i18n.h index 16a0871373d..326d086f9d5 100644 --- a/drivers/staging/speakup/i18n.h +++ b/drivers/staging/speakup/i18n.h @@ -3,7 +3,7 @@ /* Internationalization declarations */ enum msg_index_t { - MSG_FIRST_INDEX , + MSG_FIRST_INDEX, MSG_ANNOUNCEMENTS_START = MSG_FIRST_INDEX, MSG_BLANK = MSG_ANNOUNCEMENTS_START, MSG_IAM_ALIVE, diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c index b12c76de60b..3708bc13ae8 100644 --- a/drivers/staging/speakup/kobjects.c +++ b/drivers/staging/speakup/kobjects.c @@ -566,7 +566,7 @@ ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr, if (ch >= ' ' && ch < '~') *cp1++ = ch; else - cp1 += sprintf(cp1, "\\""x%02x", ch); + cp1 += sprintf(cp1, "\\x%02x", ch); } *cp1++ = '"'; *cp1++ = '\n'; diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c index 507fc9a1776..a0315701c7d 100644 --- a/drivers/staging/speakup/selection.c +++ b/drivers/staging/speakup/selection.c @@ -157,7 +157,7 @@ static void __speakup_paste_selection(struct work_struct *work) pasted += count; } remove_wait_queue(&vc->paste_wait, &wait); - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); tty_buffer_unlock_exclusive(&vc->port); tty_ldisc_deref(ld); diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index f3aa4239dc6..01eddab93c6 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -30,9 +30,9 @@ struct speakup_info_t speakup_info = { * must be taken at each kernel->speakup transition and released at * each corresponding speakup->kernel transition. * - * The progression thread only interferes with the speakup machinery through - * the synth buffer, so only needs to take the lock while tinkering with - * the buffer. + * The progression thread only interferes with the speakup machinery + * through the synth buffer, so only needs to take the lock + * while tinkering with the buffer. * * We use spin_lock/trylock_irqsave and spin_unlock_irqrestore with this * spinlock because speakup needs to disable the keyboard IRQ. diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig index ac080c9dcf4..19fcb346550 100644 --- a/drivers/staging/unisys/Kconfig +++ b/drivers/staging/unisys/Kconfig @@ -12,7 +12,6 @@ if UNISYSSPAR source "drivers/staging/unisys/visorutil/Kconfig" source "drivers/staging/unisys/visorchannel/Kconfig" source "drivers/staging/unisys/visorchipset/Kconfig" -source "drivers/staging/unisys/channels/Kconfig" source "drivers/staging/unisys/uislib/Kconfig" source "drivers/staging/unisys/virtpci/Kconfig" source "drivers/staging/unisys/virthba/Kconfig" diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile index b988d6940aa..68b9925e7d5 100644 --- a/drivers/staging/unisys/Makefile +++ b/drivers/staging/unisys/Makefile @@ -4,7 +4,6 @@ obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil/ obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/ obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/ -obj-$(CONFIG_UNISYS_CHANNELSTUB) += channels/ obj-$(CONFIG_UNISYS_UISLIB) += uislib/ obj-$(CONFIG_UNISYS_VIRTPCI) += virtpci/ obj-$(CONFIG_UNISYS_VIRTHBA) += virthba/ diff --git a/drivers/staging/unisys/channels/Kconfig b/drivers/staging/unisys/channels/Kconfig deleted file mode 100644 index 179c6cea282..00000000000 --- a/drivers/staging/unisys/channels/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# -# Unisys channels configuration -# - -config UNISYS_CHANNELSTUB - tristate "Unisys channelstub driver" - depends on UNISYSSPAR && UNISYS_VISORUTIL - ---help--- - If you say Y here, you will enable the Unisys channels driver. - diff --git a/drivers/staging/unisys/channels/Makefile b/drivers/staging/unisys/channels/Makefile deleted file mode 100644 index adc18420603..00000000000 --- a/drivers/staging/unisys/channels/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for Unisys channelstub -# - -obj-$(CONFIG_UNISYS_CHANNELSTUB) += visorchannelstub.o - -visorchannelstub-y := channel.o chanstub.o - -ccflags-y += -Idrivers/staging/unisys/include -ccflags-y += -Idrivers/staging/unisys/common-spar/include -ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels diff --git a/drivers/staging/unisys/channels/channel.c b/drivers/staging/unisys/channels/channel.c deleted file mode 100644 index 74cc4d6b515..00000000000 --- a/drivers/staging/unisys/channels/channel.c +++ /dev/null @@ -1,219 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * 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 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#include <linux/kernel.h> -#ifdef CONFIG_MODVERSIONS -#include <config/modversions.h> -#endif -#include <linux/module.h> -#include <linux/init.h> /* for module_init and module_exit */ -#include <linux/slab.h> /* for memcpy */ -#include <linux/types.h> - -/* Implementation of exported functions for Supervisor channels */ -#include "channel.h" - -/* - * Routine Description: - * Tries to insert the prebuilt signal pointed to by pSignal into the nth - * Queue of the Channel pointed to by pChannel - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * pSignal: (IN) pointer to the signal - * - * Assumptions: - * - pChannel, Queue and pSignal are valid. - * - If insertion fails due to a full queue, the caller will determine the - * retry policy (e.g. wait & try again, report an error, etc.). - * - * Return value: - * 1 if the insertion succeeds, 0 if the queue was full. - */ -unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue, - void *sig) -{ - void __iomem *psignal; - unsigned int head, tail, nof; - - struct signal_queue_header __iomem *pqhdr = - (struct signal_queue_header __iomem *) - ((char __iomem *)ch + readq(&ch->ch_space_offset)) - + queue; - - /* capture current head and tail */ - head = readl(&pqhdr->head); - tail = readl(&pqhdr->tail); - - /* queue is full if (head + 1) % n equals tail */ - if (((head + 1) % readl(&pqhdr->max_slots)) == tail) { - nof = readq(&pqhdr->num_overflows) + 1; - writeq(nof, &pqhdr->num_overflows); - return 0; - } - - /* increment the head index */ - head = (head + 1) % readl(&pqhdr->max_slots); - - /* copy signal to the head location from the area pointed to - * by pSignal - */ - psignal = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + - (head * readl(&pqhdr->signal_size)); - memcpy_toio(psignal, sig, readl(&pqhdr->signal_size)); - - mb(); /* channel synch */ - writel(head, &pqhdr->head); - - writeq(readq(&pqhdr->num_sent) + 1, &pqhdr->num_sent); - return 1; -} -EXPORT_SYMBOL_GPL(spar_signal_insert); - -/* - * Routine Description: - * Removes one signal from Channel pChannel's nth Queue at the - * time of the call and copies it into the memory pointed to by - * pSignal. - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * pSignal: (IN) pointer to where the signals are to be copied - * - * Assumptions: - * - pChannel and Queue are valid. - * - pSignal points to a memory area large enough to hold queue's SignalSize - * - * Return value: - * 1 if the removal succeeds, 0 if the queue was empty. - */ -unsigned char -spar_signal_remove(struct channel_header __iomem *ch, u32 queue, void *sig) -{ - void __iomem *psource; - unsigned int head, tail; - struct signal_queue_header __iomem *pqhdr = - (struct signal_queue_header __iomem *)((char __iomem *)ch + - readq(&ch->ch_space_offset)) + queue; - - /* capture current head and tail */ - head = readl(&pqhdr->head); - tail = readl(&pqhdr->tail); - - /* queue is empty if the head index equals the tail index */ - if (head == tail) { - writeq(readq(&pqhdr->num_empty) + 1, &pqhdr->num_empty); - return 0; - } - - /* advance past the 'empty' front slot */ - tail = (tail + 1) % readl(&pqhdr->max_slots); - - /* copy signal from tail location to the area pointed to by pSignal */ - psource = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + - (tail * readl(&pqhdr->signal_size)); - memcpy_fromio(sig, psource, readl(&pqhdr->signal_size)); - - mb(); /* channel synch */ - writel(tail, &pqhdr->tail); - - writeq(readq(&pqhdr->num_received) + 1, - &pqhdr->num_received); - return 1; -} -EXPORT_SYMBOL_GPL(spar_signal_remove); - -/* - * Routine Description: - * Removes all signals present in Channel pChannel's nth Queue at the - * time of the call and copies them into the memory pointed to by - * pSignal. Returns the # of signals copied as the value of the routine. - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * pSignal: (IN) pointer to where the signals are to be copied - * - * Assumptions: - * - pChannel and Queue are valid. - * - pSignal points to a memory area large enough to hold Queue's MaxSignals - * # of signals, each of which is Queue's SignalSize. - * - * Return value: - * # of signals copied. - */ -unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, - void *sig) -{ - void *psource; - unsigned int head, tail, count = 0; - struct signal_queue_header *pqhdr = - (struct signal_queue_header *)((char *)ch + - ch->ch_space_offset) + queue; - - /* capture current head and tail */ - head = pqhdr->head; - tail = pqhdr->tail; - - /* queue is empty if the head index equals the tail index */ - if (head == tail) - return 0; - - while (head != tail) { - /* advance past the 'empty' front slot */ - tail = (tail + 1) % pqhdr->max_slots; - - /* copy signal from tail location to the area pointed - * to by pSignal - */ - psource = - (char *)pqhdr + pqhdr->sig_base_offset + - (tail * pqhdr->signal_size); - memcpy((char *)sig + (pqhdr->signal_size * count), - psource, pqhdr->signal_size); - - mb(); /* channel synch */ - pqhdr->tail = tail; - - count++; - pqhdr->num_received++; - } - - return count; -} - -/* - * Routine Description: - * Determine whether a signal queue is empty. - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * - * Return value: - * 1 if the signal queue is empty, 0 otherwise. - */ -unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, - u32 queue) -{ - struct signal_queue_header __iomem *pqhdr = - (struct signal_queue_header __iomem *)((char __iomem *)ch + - readq(&ch->ch_space_offset)) + queue; - return readl(&pqhdr->head) == readl(&pqhdr->tail); -} -EXPORT_SYMBOL_GPL(spar_signalqueue_empty); - diff --git a/drivers/staging/unisys/channels/chanstub.c b/drivers/staging/unisys/channels/chanstub.c deleted file mode 100644 index b6fd126f16f..00000000000 --- a/drivers/staging/unisys/channels/chanstub.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * 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 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#define EXPORT_SYMTAB -#include <linux/kernel.h> -#ifdef CONFIG_MODVERSIONS -#include <config/modversions.h> -#endif -#include <linux/module.h> -#include <linux/init.h> /* for module_init and module_exit */ -#include <linux/slab.h> /* for memcpy */ -#include <linux/types.h> - -#include "channel.h" -#include "chanstub.h" -#include "timskmod.h" -#include "version.h" - -static __init int -channel_mod_init(void) -{ - if (!unisys_spar_platform) - return -ENODEV; - return 0; -} - -static __exit void -channel_mod_exit(void) -{ -} - -unsigned char -SignalInsert_withLock(struct channel_header __iomem *pChannel, u32 Queue, - void *pSignal, spinlock_t *lock) -{ - unsigned char result; - unsigned long flags; - - spin_lock_irqsave(lock, flags); - result = spar_signal_insert(pChannel, Queue, pSignal); - spin_unlock_irqrestore(lock, flags); - return result; -} - -unsigned char -SignalRemove_withLock(struct channel_header __iomem *pChannel, u32 Queue, - void *pSignal, spinlock_t *lock) -{ - unsigned char result; - - spin_lock(lock); - result = spar_signal_remove(pChannel, Queue, pSignal); - spin_unlock(lock); - return result; -} - -module_init(channel_mod_init); -module_exit(channel_mod_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Bryan Glaudel"); -MODULE_ALIAS("uischan"); - /* this is extracted during depmod and kept in modules.dep */ diff --git a/drivers/staging/unisys/channels/chanstub.h b/drivers/staging/unisys/channels/chanstub.h deleted file mode 100644 index 1531759a1b3..00000000000 --- a/drivers/staging/unisys/channels/chanstub.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * 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 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __CHANSTUB_H__ -#define __CHANSTUB_H__ -unsigned char SignalInsert_withLock(struct channel_header __iomem *pChannel, - u32 Queue, void *pSignal, spinlock_t *lock); -unsigned char SignalRemove_withLock(struct channel_header __iomem *pChannel, - u32 Queue, void *pSignal, spinlock_t *lock); - -#endif diff --git a/drivers/staging/unisys/common-spar/include/version.h b/drivers/staging/unisys/common-spar/include/version.h index f25208fc3ed..83d1da7a2f8 100644 --- a/drivers/staging/unisys/common-spar/include/version.h +++ b/drivers/staging/unisys/common-spar/include/version.h @@ -30,7 +30,6 @@ #define SPARVER4 "0" #define VERSION SPARVER1 "." SPARVER2 "." SPARVER3 "." SPARVER4 -#define VERSIONDATE __DATE__ /* Here are various version forms needed in Windows environments. */ diff --git a/drivers/staging/unisys/include/timskmod.h b/drivers/staging/unisys/include/timskmod.h index cff7983dab8..4019a0d6364 100644 --- a/drivers/staging/unisys/include/timskmod.h +++ b/drivers/staging/unisys/include/timskmod.h @@ -133,7 +133,7 @@ * x - the number of seconds to sleep. */ #define SLEEP(x) \ - do { current->state = TASK_INTERRUPTIBLE; \ + do { __set_current_state(TASK_INTERRUPTIBLE); \ schedule_timeout((x)*HZ); \ } while (0) @@ -141,7 +141,7 @@ * x - the number of jiffies to sleep. */ #define SLEEPJIFFIES(x) \ - do { current->state = TASK_INTERRUPTIBLE; \ + do { __set_current_state(TASK_INTERRUPTIBLE); \ schedule_timeout(x); \ } while (0) diff --git a/drivers/staging/unisys/uislib/Kconfig b/drivers/staging/unisys/uislib/Kconfig index 6b134e26790..a712eb82224 100644 --- a/drivers/staging/unisys/uislib/Kconfig +++ b/drivers/staging/unisys/uislib/Kconfig @@ -4,7 +4,7 @@ config UNISYS_UISLIB tristate "Unisys uislib driver" - depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_CHANNELSTUB && HAS_IOMEM + depends on UNISYSSPAR && UNISYS_VISORCHIPSET && HAS_IOMEM ---help--- If you say Y here, you will enable the Unisys uislib driver. diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 7c87452a9f1..a9eeddeba73 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -41,7 +41,6 @@ #include "sparstop.h" #include "visorchipset.h" -#include "chanstub.h" #include "version.h" #include "guestlinuxdebug.h" @@ -59,8 +58,8 @@ /* global function pointers that act as callback functions into virtpcimod */ int (*virt_control_chan_func)(struct guest_msgs *); -static int ProcReadBufferValid; -static char *ProcReadBuffer; /* Note this MUST be global, +static int debug_buf_valid; +static char *debug_buf; /* Note this MUST be global, * because the contents must */ static unsigned int chipset_inited; @@ -71,24 +70,24 @@ static unsigned int chipset_inited; UIS_THREAD_WAIT; \ } while (1) -static struct bus_info *BusListHead; -static rwlock_t BusListLock; -static int BusListCount; /* number of buses in the list */ -static int MaxBusCount; /* maximum number of buses expected */ -static u64 PhysicalDataChan; -static int PlatformNumber; +static struct bus_info *bus_list; +static rwlock_t bus_list_lock; +static int bus_list_count; /* number of buses in the list */ +static int max_bus_count; /* maximum number of buses expected */ +static u64 phys_data_chan; +static int platform_no; -static struct uisthread_info Incoming_ThreadInfo; -static BOOL Incoming_Thread_Started = FALSE; -static LIST_HEAD(List_Polling_Device_Channels); +static struct uisthread_info incoming_ti; +static BOOL incoming_started = FALSE; +static LIST_HEAD(poll_dev_chan); static unsigned long long tot_moved_to_tail_cnt; static unsigned long long tot_wait_cnt; static unsigned long long tot_wakeup_cnt; static unsigned long long tot_schedule_cnt; static int en_smart_wakeup = 1; -static DEFINE_SEMAPHORE(Lock_Polling_Device_Channels); /* unlocked */ -static DECLARE_WAIT_QUEUE_HEAD(Wakeup_Polling_Device_Channels); -static int Go_Polling_Device_Channels; +static DEFINE_SEMAPHORE(poll_dev_lock); /* unlocked */ +static DECLARE_WAIT_QUEUE_HEAD(poll_dev_wake_q); +static int poll_dev_start; #define CALLHOME_PROC_ENTRY_FN "callhome" #define CALLHOME_THROTTLED_PROC_ENTRY_FN "callhome_throttled" @@ -115,7 +114,7 @@ static unsigned long long cycles_before_wait, wait_cycles; /*****************************************************/ static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset); + size_t len, loff_t *offset); static const struct file_operations debugfs_info_fops = { .read = info_debugfs_read, }; @@ -129,58 +128,52 @@ init_msg_header(struct controlvm_message *msg, u32 id, uint rsp, uint svr) msg->hdr.flags.server = svr; } -static __iomem void * -init_vbus_channel(u64 channelAddr, u32 channelBytes) +static __iomem void *init_vbus_channel(u64 ch_addr, u32 ch_bytes) { - void __iomem *rc = NULL; - void __iomem *pChan = uislib_ioremap_cache(channelAddr, channelBytes); + void __iomem *ch = uislib_ioremap_cache(ch_addr, ch_bytes); - if (!pChan) { + if (!ch) { LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed", - (unsigned long long) channelAddr, - (unsigned long long) channelBytes); - rc = NULL; - goto Away; + (unsigned long long)ch_addr, + (unsigned long long)ch_bytes); + return NULL; } - if (!SPAR_VBUS_CHANNEL_OK_CLIENT(pChan)) { + if (!SPAR_VBUS_CHANNEL_OK_CLIENT(ch)) { ERRDRV("%s channel cannot be used", __func__); - uislib_iounmap(pChan); - rc = NULL; - goto Away; + uislib_iounmap(ch); + return NULL; } - rc = pChan; -Away: - return rc; + return ch; } static int create_bus(struct controlvm_message *msg, char *buf) { - u32 busNo, deviceCount; + u32 bus_no, dev_count; struct bus_info *tmp, *bus; size_t size; - if (MaxBusCount == BusListCount) { + if (max_bus_count == bus_list_count) { LOGERR("CONTROLVM_BUS_CREATE Failed: max buses:%d already created\n", - MaxBusCount); - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, MaxBusCount, + max_bus_count); + POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, max_bus_count, POSTCODE_SEVERITY_ERR); return CONTROLVM_RESP_ERROR_MAX_BUSES; } - busNo = msg->cmd.create_bus.bus_no; - deviceCount = msg->cmd.create_bus.dev_count; + bus_no = msg->cmd.create_bus.bus_no; + dev_count = msg->cmd.create_bus.dev_count; - POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, busNo, deviceCount, + POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, bus_no, dev_count, POSTCODE_SEVERITY_INFO); size = sizeof(struct bus_info) + - (deviceCount * sizeof(struct device_info *)); + (dev_count * sizeof(struct device_info *)); bus = kzalloc(size, GFP_ATOMIC); if (!bus) { LOGERR("CONTROLVM_BUS_CREATE Failed: kmalloc for bus failed.\n"); - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo, + POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); return CONTROLVM_RESP_ERROR_KMALLOC_FAILED; } @@ -191,27 +184,29 @@ create_bus(struct controlvm_message *msg, char *buf) if (msg->hdr.flags.test_message) { /* This implies we're the IOVM so set guest handle to 0... */ bus->guest_handle = 0; - bus->bus_no = busNo; + bus->bus_no = bus_no; bus->local_vnic = 1; - } else - bus->bus_no = bus->guest_handle = busNo; - sprintf(bus->name, "%d", (int) bus->bus_no); - bus->device_count = deviceCount; + } else { + bus->bus_no = bus_no; + bus->guest_handle = bus_no; + } + sprintf(bus->name, "%d", (int)bus->bus_no); + bus->device_count = dev_count; bus->device = - (struct device_info **) ((char *) bus + sizeof(struct bus_info)); + (struct device_info **)((char *)bus + sizeof(struct bus_info)); bus->bus_inst_uuid = msg->cmd.create_bus.bus_inst_uuid; bus->bus_channel_bytes = 0; bus->bus_channel = NULL; /* add bus to our bus list - but check for duplicates first */ - read_lock(&BusListLock); - for (tmp = BusListHead; tmp; tmp = tmp->next) { + read_lock(&bus_list_lock); + for (tmp = bus_list; tmp; tmp = tmp->next) { if (tmp->bus_no == bus->bus_no) break; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (tmp) { - /* found a bus already in the list with same busNo - + /* found a bus already in the list with same bus_no - * reject add */ LOGERR("CONTROLVM_BUS_CREATE Failed: bus %d already exists.\n", @@ -221,8 +216,8 @@ create_bus(struct controlvm_message *msg, char *buf) kfree(bus); return CONTROLVM_RESP_ERROR_ALREADY_DONE; } - if ((msg->cmd.create_bus.channel_addr != 0) - && (msg->cmd.create_bus.channel_bytes != 0)) { + if ((msg->cmd.create_bus.channel_addr != 0) && + (msg->cmd.create_bus.channel_bytes != 0)) { bus->bus_channel_bytes = msg->cmd.create_bus.channel_bytes; bus->bus_channel = init_vbus_channel(msg->cmd.create_bus.channel_addr, @@ -233,9 +228,9 @@ create_bus(struct controlvm_message *msg, char *buf) struct guest_msgs cmd; cmd.msgtype = GUEST_ADD_VBUS; - cmd.add_vbus.bus_no = busNo; + cmd.add_vbus.bus_no = bus_no; cmd.add_vbus.chanptr = bus->bus_channel; - cmd.add_vbus.dev_count = deviceCount; + cmd.add_vbus.dev_count = dev_count; cmd.add_vbus.bus_uuid = msg->cmd.create_bus.bus_data_type_uuid; cmd.add_vbus.instance_uuid = msg->cmd.create_bus.bus_inst_uuid; if (!virt_control_chan_func) { @@ -256,15 +251,15 @@ create_bus(struct controlvm_message *msg, char *buf) } /* add bus at the head of our list */ - write_lock(&BusListLock); - if (!BusListHead) - BusListHead = bus; - else { - bus->next = BusListHead; - BusListHead = bus; + write_lock(&bus_list_lock); + if (!bus_list) { + bus_list = bus; + } else { + bus->next = bus_list; + bus_list = bus; } - BusListCount++; - write_unlock(&BusListLock); + bus_list_count++; + write_unlock(&bus_list_lock); POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus->bus_no, POSTCODE_SEVERITY_INFO); @@ -277,15 +272,15 @@ destroy_bus(struct controlvm_message *msg, char *buf) int i; struct bus_info *bus, *prev = NULL; struct guest_msgs cmd; - u32 busNo; + u32 bus_no; - busNo = msg->cmd.destroy_bus.bus_no; + bus_no = msg->cmd.destroy_bus.bus_no; - read_lock(&BusListLock); + read_lock(&bus_list_lock); - bus = BusListHead; + bus = bus_list; while (bus) { - if (bus->bus_no == busNo) + if (bus->bus_no == bus_no) break; prev = bus; bus = bus->next; @@ -293,8 +288,8 @@ destroy_bus(struct controlvm_message *msg, char *buf) if (!bus) { LOGERR("CONTROLVM_BUS_DESTROY Failed: failed to find bus %d.\n", - busNo); - read_unlock(&BusListLock); + bus_no); + read_unlock(&bus_list_lock); return CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -302,12 +297,12 @@ destroy_bus(struct controlvm_message *msg, char *buf) for (i = 0; i < bus->device_count; i++) { if (bus->device[i] != NULL) { LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.", - i, busNo); - read_unlock(&BusListLock); + i, bus_no); + read_unlock(&bus_list_lock); return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED; } } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (msg->hdr.flags.server) goto remove; @@ -315,7 +310,7 @@ destroy_bus(struct controlvm_message *msg, char *buf) /* client messages require us to call the virtpci callback associated with this bus. */ cmd.msgtype = GUEST_DEL_VBUS; - cmd.del_vbus.bus_no = busNo; + cmd.del_vbus.bus_no = bus_no; if (!virt_control_chan_func) { LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered."); return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; @@ -327,13 +322,13 @@ destroy_bus(struct controlvm_message *msg, char *buf) /* finally, remove the bus from the list */ remove: - write_lock(&BusListLock); + write_lock(&bus_list_lock); if (prev) /* not at head */ prev->next = bus->next; else - BusListHead = bus->next; - BusListCount--; - write_unlock(&BusListLock); + bus_list = bus->next; + bus_list_count--; + write_unlock(&bus_list_lock); if (bus->bus_channel) { uislib_iounmap(bus->bus_channel); @@ -344,26 +339,26 @@ remove: return CONTROLVM_RESP_SUCCESS; } -static int -create_device(struct controlvm_message *msg, char *buf) +static int create_device(struct controlvm_message *msg, char *buf) { struct device_info *dev; struct bus_info *bus; - u32 busNo, devNo; + struct guest_msgs cmd; + u32 bus_no, dev_no; int result = CONTROLVM_RESP_SUCCESS; - u64 minSize = MIN_IO_CHANNEL_SIZE; - struct req_handler_info *pReqHandler; + u64 min_size = MIN_IO_CHANNEL_SIZE; + struct req_handler_info *req_handler; - busNo = msg->cmd.create_device.bus_no; - devNo = msg->cmd.create_device.dev_no; + bus_no = msg->cmd.create_device.bus_no; + dev_no = msg->cmd.create_device.dev_no; - POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo, + POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no, POSTCODE_SEVERITY_INFO); - dev = kzalloc(sizeof(struct device_info), GFP_ATOMIC); + dev = kzalloc(sizeof(*dev), GFP_ATOMIC); if (!dev) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: kmalloc for dev failed.\n"); - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); return CONTROLVM_RESP_ERROR_KMALLOC_FAILED; } @@ -371,169 +366,157 @@ create_device(struct controlvm_message *msg, char *buf) dev->channel_uuid = msg->cmd.create_device.data_type_uuid; dev->intr = msg->cmd.create_device.intr; dev->channel_addr = msg->cmd.create_device.channel_addr; - dev->bus_no = busNo; - dev->dev_no = devNo; + dev->bus_no = bus_no; + dev->dev_no = dev_no; sema_init(&dev->interrupt_callback_lock, 1); /* unlocked */ - sprintf(dev->devid, "vbus%u:dev%u", (unsigned) busNo, (unsigned) devNo); + sprintf(dev->devid, "vbus%u:dev%u", (unsigned)bus_no, (unsigned)dev_no); /* map the channel memory for the device. */ - if (msg->hdr.flags.test_message) + if (msg->hdr.flags.test_message) { dev->chanptr = (void __iomem *)__va(dev->channel_addr); - else { - pReqHandler = req_handler_find(dev->channel_uuid); - if (pReqHandler) + } else { + req_handler = req_handler_find(dev->channel_uuid); + if (req_handler) /* generic service handler registered for this * channel */ - minSize = pReqHandler->min_channel_bytes; - if (minSize > msg->cmd.create_device.channel_bytes) { + min_size = req_handler->min_channel_bytes; + if (min_size > msg->cmd.create_device.channel_bytes) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: channel size is too small, channel size:0x%lx, required size:0x%lx", - (ulong) msg->cmd.create_device.channel_bytes, - (ulong) minSize); - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, - POSTCODE_SEVERITY_ERR); + (ulong)msg->cmd.create_device.channel_bytes, + (ulong)min_size); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL; - goto Away; + goto cleanup; } dev->chanptr = uislib_ioremap_cache(dev->channel_addr, msg->cmd.create_device.channel_bytes); if (!dev->chanptr) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed", - dev->channel_addr, - msg->cmd.create_device.channel_bytes); + dev->channel_addr, + msg->cmd.create_device.channel_bytes); result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED; - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, - POSTCODE_SEVERITY_ERR); - goto Away; + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + goto cleanup; } } dev->instance_uuid = msg->cmd.create_device.dev_inst_uuid; dev->channel_bytes = msg->cmd.create_device.channel_bytes; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { - if (bus->bus_no == busNo) { - /* make sure the device number is valid */ - if (devNo >= bus->device_count) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).", - devNo, bus->device_count); - result = CONTROLVM_RESP_ERROR_MAX_DEVICES; + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { + if (bus->bus_no != bus_no) + continue; + /* make sure the device number is valid */ + if (dev_no >= bus->device_count) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).", + dev_no, bus->device_count); + result = CONTROLVM_RESP_ERROR_MAX_DEVICES; + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + read_unlock(&bus_list_lock); + goto cleanup; + } + /* make sure this device is not already set */ + if (bus->device[dev_no]) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.", + dev_no); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, + dev_no, bus_no, + POSTCODE_SEVERITY_ERR); + result = CONTROLVM_RESP_ERROR_ALREADY_DONE; + read_unlock(&bus_list_lock); + goto cleanup; + } + read_unlock(&bus_list_lock); + /* the msg is bound for virtpci; send + * guest_msgs struct to callback + */ + if (msg->hdr.flags.server) { + bus->device[dev_no] = dev; + POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, dev_no, + bus_no, POSTCODE_SEVERITY_INFO); + return CONTROLVM_RESP_SUCCESS; + } + if (uuid_le_cmp(dev->channel_uuid, + spar_vhba_channel_protocol_uuid) == 0) { + wait_for_valid_guid(&((struct channel_header __iomem *) + (dev->chanptr))->chtype); + if (!SPAR_VHBA_CHANNEL_OK_CLIENT(dev->chanptr)) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.", + dev_no); POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, - devNo, busNo, + dev_no, bus_no, POSTCODE_SEVERITY_ERR); - read_unlock(&BusListLock); - goto Away; + result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; + goto cleanup; } - /* make sure this device is not already set */ - if (bus->device[devNo]) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.", - devNo); + cmd.msgtype = GUEST_ADD_VHBA; + cmd.add_vhba.chanptr = dev->chanptr; + cmd.add_vhba.bus_no = bus_no; + cmd.add_vhba.device_no = dev_no; + cmd.add_vhba.instance_uuid = dev->instance_uuid; + cmd.add_vhba.intr = dev->intr; + } else if (uuid_le_cmp(dev->channel_uuid, + spar_vnic_channel_protocol_uuid) == 0) { + wait_for_valid_guid(&((struct channel_header __iomem *) + (dev->chanptr))->chtype); + if (!SPAR_VNIC_CHANNEL_OK_CLIENT(dev->chanptr)) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.", + dev_no); POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, - devNo, busNo, + dev_no, bus_no, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_ALREADY_DONE; - read_unlock(&BusListLock); - goto Away; + result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; + goto cleanup; } - read_unlock(&BusListLock); - /* the msg is bound for virtpci; send - * guest_msgs struct to callback - */ - if (!msg->hdr.flags.server) { - struct guest_msgs cmd; - - if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { - wait_for_valid_guid(&(( - struct channel_header - __iomem *) (dev-> - chanptr))-> - chtype); - if (!SPAR_VHBA_CHANNEL_OK_CLIENT - (dev->chanptr)) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.", - devNo); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, - devNo, busNo, - POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; - goto Away; - } - cmd.msgtype = GUEST_ADD_VHBA; - cmd.add_vhba.chanptr = dev->chanptr; - cmd.add_vhba.bus_no = busNo; - cmd.add_vhba.device_no = devNo; - cmd.add_vhba.instance_uuid = - dev->instance_uuid; - cmd.add_vhba.intr = dev->intr; - } else - if (!uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid)) { - wait_for_valid_guid(&(( - struct channel_header - __iomem *) (dev-> - chanptr))-> - chtype); - if (!SPAR_VNIC_CHANNEL_OK_CLIENT - (dev->chanptr)) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.", - devNo); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, - devNo, busNo, - POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; - goto Away; - } - cmd.msgtype = GUEST_ADD_VNIC; - cmd.add_vnic.chanptr = dev->chanptr; - cmd.add_vnic.bus_no = busNo; - cmd.add_vnic.device_no = devNo; - cmd.add_vnic.instance_uuid = - dev->instance_uuid; - cmd.add_vhba.intr = dev->intr; - } else { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n"); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, devNo, - busNo, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; - goto Away; - } + cmd.msgtype = GUEST_ADD_VNIC; + cmd.add_vnic.chanptr = dev->chanptr; + cmd.add_vnic.bus_no = bus_no; + cmd.add_vnic.device_no = dev_no; + cmd.add_vnic.instance_uuid = dev->instance_uuid; + cmd.add_vhba.intr = dev->intr; + } else { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n"); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; + goto cleanup; + } - if (!virt_control_chan_func) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered."); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, devNo, - busNo, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; - goto Away; - } + if (!virt_control_chan_func) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered."); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; + goto cleanup; + } - if (!virt_control_chan_func(&cmd)) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error."); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, devNo, - busNo, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; - goto Away; - } - } - bus->device[devNo] = dev; - POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, devNo, busNo, - POSTCODE_SEVERITY_INFO); - return CONTROLVM_RESP_SUCCESS; + if (!virt_control_chan_func(&cmd)) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error."); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + result = + CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; + goto cleanup; } + + bus->device[dev_no] = dev; + POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, dev_no, + bus_no, POSTCODE_SEVERITY_INFO); + return CONTROLVM_RESP_SUCCESS; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); - LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", busNo); - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, + LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", + bus_no); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); result = CONTROLVM_RESP_ERROR_BUS_INVALID; -Away: +cleanup: if (!msg->hdr.flags.test_message) { uislib_iounmap(dev->chanptr); dev->chanptr = NULL; @@ -543,32 +526,31 @@ Away: return result; } -static int -pause_device(struct controlvm_message *msg) +static int pause_device(struct controlvm_message *msg) { - u32 busNo, devNo; + u32 bus_no, dev_no; struct bus_info *bus; struct device_info *dev; struct guest_msgs cmd; int retval = CONTROLVM_RESP_SUCCESS; - busNo = msg->cmd.device_change_state.bus_no; - devNo = msg->cmd.device_change_state.dev_no; + bus_no = msg->cmd.device_change_state.bus_no; + dev_no = msg->cmd.device_change_state.dev_no; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { - if (bus->bus_no == busNo) { + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { + if (bus->bus_no == bus_no) { /* make sure the device number is valid */ - if (devNo >= bus->device_count) { + if (dev_no >= bus->device_count) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device(%d) >= deviceCount(%d).", - devNo, bus->device_count); + dev_no, bus->device_count); retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; } else { /* make sure this device exists */ - dev = bus->device[devNo]; + dev = bus->device[dev_no]; if (!dev) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.", - devNo); + dev_no); retval = CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -578,20 +560,20 @@ pause_device(struct controlvm_message *msg) } if (!bus) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: bus %d does not exist", - busNo); + bus_no); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (retval == CONTROLVM_RESP_SUCCESS) { /* the msg is bound for virtpci; send * guest_msgs struct to callback */ - if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { + if (uuid_le_cmp(dev->channel_uuid, + spar_vhba_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_PAUSE_VHBA; cmd.pause_vhba.chanptr = dev->chanptr; - } else if (!uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid)) { + } else if (uuid_le_cmp(dev->channel_uuid, + spar_vnic_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_PAUSE_VNIC; cmd.pause_vnic.chanptr = dev->chanptr; } else { @@ -611,32 +593,31 @@ pause_device(struct controlvm_message *msg) return retval; } -static int -resume_device(struct controlvm_message *msg) +static int resume_device(struct controlvm_message *msg) { - u32 busNo, devNo; + u32 bus_no, dev_no; struct bus_info *bus; struct device_info *dev; struct guest_msgs cmd; int retval = CONTROLVM_RESP_SUCCESS; - busNo = msg->cmd.device_change_state.bus_no; - devNo = msg->cmd.device_change_state.dev_no; + bus_no = msg->cmd.device_change_state.bus_no; + dev_no = msg->cmd.device_change_state.dev_no; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { - if (bus->bus_no == busNo) { + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { + if (bus->bus_no == bus_no) { /* make sure the device number is valid */ - if (devNo >= bus->device_count) { + if (dev_no >= bus->device_count) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device(%d) >= deviceCount(%d).", - devNo, bus->device_count); + dev_no, bus->device_count); retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; } else { /* make sure this device exists */ - dev = bus->device[devNo]; + dev = bus->device[dev_no]; if (!dev) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.", - devNo); + dev_no); retval = CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -647,20 +628,20 @@ resume_device(struct controlvm_message *msg) if (!bus) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: bus %d does not exist", - busNo); + bus_no); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); /* the msg is bound for virtpci; send * guest_msgs struct to callback */ if (retval == CONTROLVM_RESP_SUCCESS) { - if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { + if (uuid_le_cmp(dev->channel_uuid, + spar_vhba_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_RESUME_VHBA; cmd.resume_vhba.chanptr = dev->chanptr; - } else if (!uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid)) { + } else if (uuid_le_cmp(dev->channel_uuid, + spar_vnic_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_RESUME_VNIC; cmd.resume_vnic.chanptr = dev->chanptr; } else { @@ -680,33 +661,33 @@ resume_device(struct controlvm_message *msg) return retval; } -static int -destroy_device(struct controlvm_message *msg, char *buf) +static int destroy_device(struct controlvm_message *msg, char *buf) { - u32 busNo, devNo; + u32 bus_no, dev_no; struct bus_info *bus; struct device_info *dev; struct guest_msgs cmd; int retval = CONTROLVM_RESP_SUCCESS; - busNo = msg->cmd.destroy_device.bus_no; - devNo = msg->cmd.destroy_device.bus_no; + bus_no = msg->cmd.destroy_device.bus_no; + dev_no = msg->cmd.destroy_device.bus_no; - read_lock(&BusListLock); - LOGINF("destroy_device called for busNo=%u, devNo=%u", busNo, devNo); - for (bus = BusListHead; bus; bus = bus->next) { - if (bus->bus_no == busNo) { + read_lock(&bus_list_lock); + LOGINF("destroy_device called for bus_no=%u, dev_no=%u", bus_no, + dev_no); + for (bus = bus_list; bus; bus = bus->next) { + if (bus->bus_no == bus_no) { /* make sure the device number is valid */ - if (devNo >= bus->device_count) { - LOGERR("CONTROLVM_DEVICE_DESTORY Failed: device(%d) >= deviceCount(%d).", - devNo, bus->device_count); + if (dev_no >= bus->device_count) { + LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device(%d) >= device_count(%d).", + dev_no, bus->device_count); retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; } else { /* make sure this device exists */ - dev = bus->device[devNo]; + dev = bus->device[dev_no]; if (!dev) { LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.", - devNo); + dev_no); retval = CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -717,20 +698,20 @@ destroy_device(struct controlvm_message *msg, char *buf) if (!bus) { LOGERR("CONTROLVM_DEVICE_DESTROY Failed: bus %d does not exist", - busNo); + bus_no); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (retval == CONTROLVM_RESP_SUCCESS) { /* the msg is bound for virtpci; send * guest_msgs struct to callback */ - if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { + if (uuid_le_cmp(dev->channel_uuid, + spar_vhba_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_DEL_VHBA; cmd.del_vhba.chanptr = dev->chanptr; - } else if (!uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid)) { + } else if (uuid_le_cmp(dev->channel_uuid, + spar_vnic_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_DEL_VNIC; cmd.del_vnic.chanptr = dev->chanptr; } else { @@ -739,7 +720,7 @@ destroy_device(struct controlvm_message *msg, char *buf) CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; } if (!virt_control_chan_func) { - LOGERR("CONTROLVM_DEVICE_DESTORY Failed: virtpci callback not registered."); + LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci callback not registered."); return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; } @@ -755,7 +736,7 @@ destroy_device(struct controlvm_message *msg, char *buf) */ if (dev->polling) { LOGINF("calling uislib_disable_channel_interrupts"); - uislib_disable_channel_interrupts(busNo, devNo); + uislib_disable_channel_interrupts(bus_no, dev_no); } /* unmap the channel memory for the device. */ if (!msg->hdr.flags.test_message) { @@ -763,7 +744,7 @@ destroy_device(struct controlvm_message *msg, char *buf) uislib_iounmap(dev->chanptr); } kfree(dev); - bus->device[devNo] = NULL; + bus->device[dev_no] = NULL; } return retval; } @@ -773,9 +754,9 @@ init_chipset(struct controlvm_message *msg, char *buf) { POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO); - MaxBusCount = msg->cmd.init_chipset.bus_count; - PlatformNumber = msg->cmd.init_chipset.platform_number; - PhysicalDataChan = 0; + max_bus_count = msg->cmd.init_chipset.bus_count; + platform_no = msg->cmd.init_chipset.platform_number; + phys_data_chan = 0; /* We need to make sure we have our functions registered * before processing messages. If we are a test vehicle the @@ -793,31 +774,29 @@ init_chipset(struct controlvm_message *msg, char *buf) return CONTROLVM_RESP_SUCCESS; } -static int -delete_bus_glue(u32 busNo) +static int delete_bus_glue(u32 bus_no) { struct controlvm_message msg; init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0); - msg.cmd.destroy_bus.bus_no = busNo; + msg.cmd.destroy_bus.bus_no = bus_no; if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) { - LOGERR("destroy_bus failed. busNo=0x%x\n", busNo); + LOGERR("destroy_bus failed. bus_no=0x%x\n", bus_no); return 0; } return 1; } -static int -delete_device_glue(u32 busNo, u32 devNo) +static int delete_device_glue(u32 bus_no, u32 dev_no) { struct controlvm_message msg; init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0); - msg.cmd.destroy_device.bus_no = busNo; - msg.cmd.destroy_device.dev_no = devNo; + msg.cmd.destroy_device.bus_no = bus_no; + msg.cmd.destroy_device.dev_no = dev_no; if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) { - LOGERR("destroy_device failed. busNo=0x%x devNo=0x%x\n", busNo, - devNo); + LOGERR("destroy_device failed. bus_no=0x%x dev_no=0x%x\n", + bus_no, dev_no); return 0; } return 1; @@ -874,7 +853,6 @@ uislib_client_inject_add_bus(u32 bus_no, uuid_le inst_uuid, } EXPORT_SYMBOL_GPL(uislib_client_inject_add_bus); - int uislib_client_inject_del_bus(u32 bus_no) { @@ -919,7 +897,6 @@ uislib_client_inject_resume_vhba(u32 bus_no, u32 dev_no) return rc; } return 0; - } EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vhba); @@ -956,7 +933,7 @@ uislib_client_inject_add_vhba(u32 bus_no, u32 dev_no, msg.cmd.create_device.channel_addr = phys_chan_addr; if (chan_bytes < MIN_IO_CHANNEL_SIZE) { LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n", - chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE); + chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE); POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes, MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR); return 0; @@ -1015,7 +992,7 @@ uislib_client_inject_add_vnic(u32 bus_no, u32 dev_no, msg.cmd.create_device.channel_addr = phys_chan_addr; if (chan_bytes < MIN_IO_CHANNEL_SIZE) { LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n", - chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE); + chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE); POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes, MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR); return 0; @@ -1072,7 +1049,6 @@ uislib_client_inject_resume_vnic(u32 bus_no, u32 dev_no) return -1; } return 0; - } EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vnic); @@ -1129,14 +1105,12 @@ info_debugfs_read_helper(char **buff, int *buff_len) if (PLINE("\nBuses:\n") < 0) goto err_done; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { - + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { if (PLINE(" bus=0x%p, busNo=%d, deviceCount=%d\n", bus, bus->bus_no, bus->device_count) < 0) goto err_done_unlock; - if (PLINE(" Devices:\n") < 0) goto err_done_unlock; @@ -1156,7 +1130,7 @@ info_debugfs_read_helper(char **buff, int *buff_len) } } } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (PLINE("UisUtils_Registered_Services: %d\n", atomic_read(&uisutils_registered_services)) < 0) @@ -1175,70 +1149,68 @@ info_debugfs_read_helper(char **buff, int *buff_len) return tot; err_done_unlock: - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); err_done: return -1; } -static ssize_t -info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) +static ssize_t info_debugfs_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) { char *temp; - int totalBytes = 0; + int total_bytes = 0; int remaining_bytes = PROC_READ_BUFFER_SIZE; /* *start = buf; */ - if (ProcReadBuffer == NULL) { - DBGINF("ProcReadBuffer == NULL; allocating buffer.\n."); - ProcReadBuffer = vmalloc(PROC_READ_BUFFER_SIZE); + if (debug_buf == NULL) { + DBGINF("debug_buf == NULL; allocating buffer.\n."); + debug_buf = vmalloc(PROC_READ_BUFFER_SIZE); - if (ProcReadBuffer == NULL) { + if (debug_buf == NULL) { LOGERR("failed to allocate buffer to provide proc data.\n"); return -ENOMEM; } } - temp = ProcReadBuffer; + temp = debug_buf; - if ((*offset == 0) || (!ProcReadBufferValid)) { + if ((*offset == 0) || (!debug_buf_valid)) { DBGINF("calling info_debugfs_read_helper.\n"); /* if the read fails, then -1 will be returned */ - totalBytes = info_debugfs_read_helper(&temp, &remaining_bytes); - ProcReadBufferValid = 1; - } else - totalBytes = strlen(ProcReadBuffer); + total_bytes = info_debugfs_read_helper(&temp, &remaining_bytes); + debug_buf_valid = 1; + } else { + total_bytes = strlen(debug_buf); + } return simple_read_from_buffer(buf, len, offset, - ProcReadBuffer, totalBytes); + debug_buf, total_bytes); } -static struct device_info * -find_dev(u32 busNo, u32 devNo) +static struct device_info *find_dev(u32 bus_no, u32 dev_no) { struct bus_info *bus; struct device_info *dev = NULL; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { - if (bus->bus_no == busNo) { + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { + if (bus->bus_no == bus_no) { /* make sure the device number is valid */ - if (devNo >= bus->device_count) { - LOGERR("%s bad busNo, devNo=%d,%d", + if (dev_no >= bus->device_count) { + LOGERR("%s bad bus_no, dev_no=%d,%d", __func__, - (int) (busNo), (int) (devNo)); - goto Away; + (int)bus_no, (int)dev_no); + break; } - dev = bus->device[devNo]; + dev = bus->device[dev_no]; if (!dev) - LOGERR("%s bad busNo, devNo=%d,%d", + LOGERR("%s bad bus_no, dev_no=%d,%d", __func__, - (int) (busNo), (int) (devNo)); - goto Away; + (int)bus_no, (int)dev_no); + break; } } -Away: - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); return dev; } @@ -1262,8 +1234,7 @@ Away: * less-busy ones. * */ -static int -Process_Incoming(void *v) +static int process_incoming(void *v) { unsigned long long cur_cycles, old_cycles, idle_cycles, delta_cycles; struct list_head *new_tail = NULL; @@ -1272,7 +1243,7 @@ Process_Incoming(void *v) UIS_DAEMONIZE("dev_incoming"); for (i = 0; i < 16; i++) { old_cycles = get_cycles(); - wait_event_timeout(Wakeup_Polling_Device_Channels, + wait_event_timeout(poll_dev_wake_q, 0, POLLJIFFIES_NORMAL); cur_cycles = get_cycles(); if (wait_cycles == 0) { @@ -1285,15 +1256,15 @@ Process_Incoming(void *v) LOGINF("wait_cycles=%llu", wait_cycles); cycles_before_wait = wait_cycles; idle_cycles = 0; - Go_Polling_Device_Channels = 0; + poll_dev_start = 0; while (1) { struct list_head *lelt, *tmp; struct device_info *dev = NULL; /* poll each channel for input */ - down(&Lock_Polling_Device_Channels); + down(&poll_dev_lock); new_tail = NULL; - list_for_each_safe(lelt, tmp, &List_Polling_Device_Channels) { + list_for_each_safe(lelt, tmp, &poll_dev_chan) { int rc = 0; dev = list_entry(lelt, struct device_info, @@ -1315,22 +1286,22 @@ Process_Incoming(void *v) if (! (list_is_last (lelt, - &List_Polling_Device_Channels))) { + &poll_dev_chan))) { new_tail = lelt; dev->moved_to_tail_cnt++; - } else + } else { dev->last_on_list_cnt++; + } } - } - if (Incoming_ThreadInfo.should_stop) + if (incoming_ti.should_stop) break; } if (new_tail != NULL) { tot_moved_to_tail_cnt++; - list_move_tail(new_tail, &List_Polling_Device_Channels); + list_move_tail(new_tail, &poll_dev_chan); } - up(&Lock_Polling_Device_Channels); + up(&poll_dev_lock); cur_cycles = get_cycles(); delta_cycles = cur_cycles - old_cycles; old_cycles = cur_cycles; @@ -1340,24 +1311,24 @@ Process_Incoming(void *v) * - there is no input waiting on any of the channels * - we have received a signal to stop this thread */ - if (Incoming_ThreadInfo.should_stop) + if (incoming_ti.should_stop) break; if (en_smart_wakeup == 0xFF) { LOGINF("en_smart_wakeup set to 0xff, to force exiting process_incoming"); break; } /* wait for POLLJIFFIES_NORMAL jiffies, or until - * someone wakes up Wakeup_Polling_Device_Channels, + * someone wakes up poll_dev_wake_q, * whichever comes first only do a wait when we have * been idle for cycles_before_wait cycles. */ if (idle_cycles > cycles_before_wait) { - Go_Polling_Device_Channels = 0; + poll_dev_start = 0; tot_wait_cnt++; - wait_event_timeout(Wakeup_Polling_Device_Channels, - Go_Polling_Device_Channels, + wait_event_timeout(poll_dev_wake_q, + poll_dev_start, POLLJIFFIES_NORMAL); - Go_Polling_Device_Channels = 1; + poll_dev_start = 1; } else { tot_schedule_cnt++; schedule(); @@ -1365,25 +1336,25 @@ Process_Incoming(void *v) } } DBGINF("exiting.\n"); - complete_and_exit(&Incoming_ThreadInfo.has_stopped, 0); + complete_and_exit(&incoming_ti.has_stopped, 0); } static BOOL -Initialize_incoming_thread(void) +initialize_incoming_thread(void) { - if (Incoming_Thread_Started) + if (incoming_started) return TRUE; - if (!uisthread_start(&Incoming_ThreadInfo, - &Process_Incoming, NULL, "dev_incoming")) { - LOGERR("uisthread_start Initialize_incoming_thread ****FAILED"); + if (!uisthread_start(&incoming_ti, + &process_incoming, NULL, "dev_incoming")) { + LOGERR("uisthread_start initialize_incoming_thread ****FAILED"); return FALSE; } - Incoming_Thread_Started = TRUE; + incoming_started = TRUE; return TRUE; } /* Add a new device/channel to the list being processed by - * Process_Incoming(). + * process_incoming(). * <interrupt> - indicates the function to call periodically. * <interrupt_context> - indicates the data to pass to the <interrupt> * function. @@ -1397,23 +1368,23 @@ uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no, dev = find_dev(bus_no, dev_no); if (!dev) { - LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (bus_no), - (int) (dev_no)); + LOGERR("%s busNo=%d, devNo=%d", __func__, (int)(bus_no), + (int)(dev_no)); return; } - down(&Lock_Polling_Device_Channels); - Initialize_incoming_thread(); + down(&poll_dev_lock); + initialize_incoming_thread(); dev->interrupt = interrupt; dev->interrupt_context = interrupt_context; dev->polling = TRUE; - list_add_tail(&(dev->list_polling_device_channels), - &List_Polling_Device_Channels); - up(&Lock_Polling_Device_Channels); + list_add_tail(&dev->list_polling_device_channels, + &poll_dev_chan); + up(&poll_dev_lock); } EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts); /* Remove a device/channel from the list being processed by - * Process_Incoming(). + * process_incoming(). */ void uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no) @@ -1422,31 +1393,31 @@ uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no) dev = find_dev(bus_no, dev_no); if (!dev) { - LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (bus_no), - (int) (dev_no)); + LOGERR("%s busNo=%d, devNo=%d", __func__, (int)(bus_no), + (int)(dev_no)); return; } - down(&Lock_Polling_Device_Channels); + down(&poll_dev_lock); list_del(&dev->list_polling_device_channels); dev->polling = FALSE; dev->interrupt = NULL; - up(&Lock_Polling_Device_Channels); + up(&poll_dev_lock); } EXPORT_SYMBOL_GPL(uislib_disable_channel_interrupts); static void do_wakeup_polling_device_channels(struct work_struct *dummy) { - if (!Go_Polling_Device_Channels) { - Go_Polling_Device_Channels = 1; - wake_up(&Wakeup_Polling_Device_Channels); + if (!poll_dev_start) { + poll_dev_start = 1; + wake_up(&poll_dev_wake_q); } } -static DECLARE_WORK(Work_wakeup_polling_device_channels, +static DECLARE_WORK(work_wakeup_polling_device_channels, do_wakeup_polling_device_channels); -/* Call this function when you want to send a hint to Process_Incoming() that +/* Call this function when you want to send a hint to process_incoming() that * your device might have more requests. */ void @@ -1454,14 +1425,14 @@ uislib_force_channel_interrupt(u32 bus_no, u32 dev_no) { if (en_smart_wakeup == 0) return; - if (Go_Polling_Device_Channels) + if (poll_dev_start) return; /* The point of using schedule_work() instead of just doing * the work inline is to force a slight delay before waking up - * the Process_Incoming() thread. + * the process_incoming() thread. */ tot_wakeup_cnt++; - schedule_work(&Work_wakeup_polling_device_channels); + schedule_work(&work_wakeup_polling_device_channels); } EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt); @@ -1472,35 +1443,35 @@ EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt); static int __init uislib_mod_init(void) { - if (!unisys_spar_platform) return -ENODEV; LOGINF("MONITORAPIS"); LOGINF("sizeof(struct uiscmdrsp):%lu bytes\n", - (ulong) sizeof(struct uiscmdrsp)); + (ulong)sizeof(struct uiscmdrsp)); LOGINF("sizeof(struct phys_info):%lu\n", - (ulong) sizeof(struct phys_info)); + (ulong)sizeof(struct phys_info)); LOGINF("sizeof(uiscmdrsp_scsi):%lu\n", - (ulong) sizeof(struct uiscmdrsp_scsi)); + (ulong)sizeof(struct uiscmdrsp_scsi)); LOGINF("sizeof(uiscmdrsp_net):%lu\n", - (ulong) sizeof(struct uiscmdrsp_net)); + (ulong)sizeof(struct uiscmdrsp_net)); LOGINF("sizeof(CONTROLVM_MESSAGE):%lu bytes\n", - (ulong) sizeof(struct controlvm_message)); + (ulong)sizeof(struct controlvm_message)); LOGINF("sizeof(struct spar_controlvm_channel_protocol):%lu bytes\n", - (ulong) sizeof(struct spar_controlvm_channel_protocol)); + (ulong)sizeof(struct spar_controlvm_channel_protocol)); LOGINF("sizeof(CHANNEL_HEADER):%lu bytes\n", - (ulong) sizeof(struct channel_header)); + (ulong)sizeof(struct channel_header)); LOGINF("sizeof(struct spar_io_channel_protocol):%lu bytes\n", - (ulong) sizeof(struct spar_io_channel_protocol)); + (ulong)sizeof(struct spar_io_channel_protocol)); LOGINF("SIZEOF_CMDRSP:%lu bytes\n", SIZEOF_CMDRSP); LOGINF("SIZEOF_PROTOCOL:%lu bytes\n", SIZEOF_PROTOCOL); /* initialize global pointers to NULL */ - BusListHead = NULL; - BusListCount = MaxBusCount = 0; - rwlock_init(&BusListLock); + bus_list = NULL; + bus_list_count = 0; + max_bus_count = 0; + rwlock_init(&bus_list_lock); virt_control_chan_func = NULL; /* Issue VMCALL_GET_CONTROLVM_ADDR to get CtrlChanPhysAddr and @@ -1515,7 +1486,7 @@ uislib_mod_init(void) platformnumber_debugfs_read = debugfs_create_u32( PLATFORMNUMBER_DEBUGFS_ENTRY_FN, 0444, dir_debugfs, - &PlatformNumber); + &platform_no); cycles_before_wait_debugfs_read = debugfs_create_u64( CYCLES_BEFORE_WAIT_DEBUGFS_ENTRY_FN, 0666, dir_debugfs, @@ -1533,9 +1504,9 @@ uislib_mod_init(void) static void __exit uislib_mod_exit(void) { - if (ProcReadBuffer) { - vfree(ProcReadBuffer); - ProcReadBuffer = NULL; + if (debug_buf) { + vfree(debug_buf); + debug_buf = NULL; } debugfs_remove(info_debugfs_entry); diff --git a/drivers/staging/unisys/uislib/uisqueue.c b/drivers/staging/unisys/uislib/uisqueue.c index f9f8442d58c..71bb7b608e9 100644 --- a/drivers/staging/unisys/uislib/uisqueue.c +++ b/drivers/staging/unisys/uislib/uisqueue.c @@ -21,8 +21,6 @@ #include "uisutils.h" -#include "chanstub.h" - /* this is shorter than using __FILE__ (full path name) in * debug/info/error messages */ #define CURRENT_FILE_PC UISLIB_PC_uisqueue_c @@ -33,9 +31,202 @@ /*****************************************************/ /* Exported functions */ /*****************************************************/ + +/* + * Routine Description: + * Tries to insert the prebuilt signal pointed to by pSignal into the nth + * Queue of the Channel pointed to by pChannel + * + * Parameters: + * pChannel: (IN) points to the IO Channel + * Queue: (IN) nth Queue of the IO Channel + * pSignal: (IN) pointer to the signal + * + * Assumptions: + * - pChannel, Queue and pSignal are valid. + * - If insertion fails due to a full queue, the caller will determine the + * retry policy (e.g. wait & try again, report an error, etc.). + * + * Return value: + * 1 if the insertion succeeds, 0 if the queue was full. + */ +unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue, + void *sig) +{ + void __iomem *psignal; + unsigned int head, tail, nof; + + struct signal_queue_header __iomem *pqhdr = + (struct signal_queue_header __iomem *) + ((char __iomem *)ch + readq(&ch->ch_space_offset)) + + queue; + + /* capture current head and tail */ + head = readl(&pqhdr->head); + tail = readl(&pqhdr->tail); + + /* queue is full if (head + 1) % n equals tail */ + if (((head + 1) % readl(&pqhdr->max_slots)) == tail) { + nof = readq(&pqhdr->num_overflows) + 1; + writeq(nof, &pqhdr->num_overflows); + return 0; + } + + /* increment the head index */ + head = (head + 1) % readl(&pqhdr->max_slots); + + /* copy signal to the head location from the area pointed to + * by pSignal + */ + psignal = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + + (head * readl(&pqhdr->signal_size)); + memcpy_toio(psignal, sig, readl(&pqhdr->signal_size)); + + mb(); /* channel synch */ + writel(head, &pqhdr->head); + + writeq(readq(&pqhdr->num_sent) + 1, &pqhdr->num_sent); + return 1; +} +EXPORT_SYMBOL_GPL(spar_signal_insert); + +/* + * Routine Description: + * Removes one signal from Channel pChannel's nth Queue at the + * time of the call and copies it into the memory pointed to by + * pSignal. + * + * Parameters: + * pChannel: (IN) points to the IO Channel + * Queue: (IN) nth Queue of the IO Channel + * pSignal: (IN) pointer to where the signals are to be copied + * + * Assumptions: + * - pChannel and Queue are valid. + * - pSignal points to a memory area large enough to hold queue's SignalSize + * + * Return value: + * 1 if the removal succeeds, 0 if the queue was empty. + */ +unsigned char +spar_signal_remove(struct channel_header __iomem *ch, u32 queue, void *sig) +{ + void __iomem *psource; + unsigned int head, tail; + struct signal_queue_header __iomem *pqhdr = + (struct signal_queue_header __iomem *)((char __iomem *)ch + + readq(&ch->ch_space_offset)) + queue; + + /* capture current head and tail */ + head = readl(&pqhdr->head); + tail = readl(&pqhdr->tail); + + /* queue is empty if the head index equals the tail index */ + if (head == tail) { + writeq(readq(&pqhdr->num_empty) + 1, &pqhdr->num_empty); + return 0; + } + + /* advance past the 'empty' front slot */ + tail = (tail + 1) % readl(&pqhdr->max_slots); + + /* copy signal from tail location to the area pointed to by pSignal */ + psource = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + + (tail * readl(&pqhdr->signal_size)); + memcpy_fromio(sig, psource, readl(&pqhdr->signal_size)); + + mb(); /* channel synch */ + writel(tail, &pqhdr->tail); + + writeq(readq(&pqhdr->num_received) + 1, + &pqhdr->num_received); + return 1; +} +EXPORT_SYMBOL_GPL(spar_signal_remove); + +/* + * Routine Description: + * Removes all signals present in Channel pChannel's nth Queue at the + * time of the call and copies them into the memory pointed to by + * pSignal. Returns the # of signals copied as the value of the routine. + * + * Parameters: + * pChannel: (IN) points to the IO Channel + * Queue: (IN) nth Queue of the IO Channel + * pSignal: (IN) pointer to where the signals are to be copied + * + * Assumptions: + * - pChannel and Queue are valid. + * - pSignal points to a memory area large enough to hold Queue's MaxSignals + * # of signals, each of which is Queue's SignalSize. + * + * Return value: + * # of signals copied. + */ +unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, + void *sig) +{ + void *psource; + unsigned int head, tail, count = 0; + struct signal_queue_header *pqhdr = + (struct signal_queue_header *)((char *)ch + + ch->ch_space_offset) + queue; + + /* capture current head and tail */ + head = pqhdr->head; + tail = pqhdr->tail; + + /* queue is empty if the head index equals the tail index */ + if (head == tail) + return 0; + + while (head != tail) { + /* advance past the 'empty' front slot */ + tail = (tail + 1) % pqhdr->max_slots; + + /* copy signal from tail location to the area pointed + * to by pSignal + */ + psource = + (char *)pqhdr + pqhdr->sig_base_offset + + (tail * pqhdr->signal_size); + memcpy((char *)sig + (pqhdr->signal_size * count), + psource, pqhdr->signal_size); + + mb(); /* channel synch */ + pqhdr->tail = tail; + + count++; + pqhdr->num_received++; + } + + return count; +} + +/* + * Routine Description: + * Determine whether a signal queue is empty. + * + * Parameters: + * pChannel: (IN) points to the IO Channel + * Queue: (IN) nth Queue of the IO Channel + * + * Return value: + * 1 if the signal queue is empty, 0 otherwise. + */ +unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, + u32 queue) +{ + struct signal_queue_header __iomem *pqhdr = + (struct signal_queue_header __iomem *)((char __iomem *)ch + + readq(&ch->ch_space_offset)) + queue; + return readl(&pqhdr->head) == readl(&pqhdr->tail); +} +EXPORT_SYMBOL_GPL(spar_signalqueue_empty); + unsigned long long uisqueue_interlocked_or(unsigned long long __iomem *tgt, - unsigned long long set) + unsigned long long set) { unsigned long long i; unsigned long long j; @@ -53,7 +244,7 @@ EXPORT_SYMBOL_GPL(uisqueue_interlocked_or); unsigned long long uisqueue_interlocked_and(unsigned long long __iomem *tgt, - unsigned long long set) + unsigned long long set) { unsigned long long i; unsigned long long j; @@ -72,22 +263,21 @@ EXPORT_SYMBOL_GPL(uisqueue_interlocked_and); static u8 do_locked_client_insert(struct uisqueue_info *queueinfo, unsigned int whichqueue, - void *pSignal, + void *signal, spinlock_t *lock, - unsigned char issueInterruptIfEmpty, - u64 interruptHandle, u8 *channelId) + u8 *channel_id) { unsigned long flags; u8 rc = 0; spin_lock_irqsave(lock, flags); - if (!spar_channel_client_acquire_os(queueinfo->chan, channelId)) + if (!spar_channel_client_acquire_os(queueinfo->chan, channel_id)) goto unlock; - if (spar_signal_insert(queueinfo->chan, whichqueue, pSignal)) { + if (spar_signal_insert(queueinfo->chan, whichqueue, signal)) { queueinfo->packets_sent++; rc = 1; } - spar_channel_client_release_os(queueinfo->chan, channelId); + spar_channel_client_release_os(queueinfo->chan, channel_id); unlock: spin_unlock_irqrestore((spinlock_t *)lock, flags); return rc; @@ -103,9 +293,8 @@ uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo, char oktowait, u8 *channel_id) { while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp, - (spinlock_t *) insertlock, - issue_irq_if_empty, - irq_handle, channel_id)) { + (spinlock_t *)insertlock, + channel_id)) { if (oktowait != OK_TO_WAIT) { LOGERR("****FAILED visor_signal_insert failed; cannot wait; insert aborted\n"); return 0; /* failed to queue */ diff --git a/drivers/staging/unisys/uislib/uisthread.c b/drivers/staging/unisys/uislib/uisthread.c index c0fc812f751..25adf1a7307 100644 --- a/drivers/staging/unisys/uislib/uisthread.c +++ b/drivers/staging/unisys/uislib/uisthread.c @@ -53,7 +53,6 @@ uisthread_start(struct uisthread_info *thrinfo, wake_up_process(thrinfo->task); LOGINF("started thread pid:%d\n", thrinfo->id); return 1; - } EXPORT_SYMBOL_GPL(uisthread_start); diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c index 4a5b8677392..31318d24625 100644 --- a/drivers/staging/unisys/uislib/uisutils.c +++ b/drivers/staging/unisys/uislib/uisutils.c @@ -42,14 +42,13 @@ atomic_t uisutils_registered_services = ATOMIC_INIT(0); * uisctrl_register_req_handler() or * uisctrl_register_req_handler_ex() */ - /*****************************************************/ /* Utility functions */ /*****************************************************/ int uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining, - char *format, ...) + char *format, ...) { va_list args; int len; @@ -57,6 +56,7 @@ uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining, DBGINF("buffer = 0x%p : *buffer = 0x%p.\n", buffer, *buffer); va_start(args, format); len = vsnprintf(*buffer, *buffer_remaining, format, args); + va_end(args); if (len >= *buffer_remaining) { *buffer += *buffer_remaining; *total += *buffer_remaining; @@ -96,7 +96,7 @@ uisctrl_register_req_handler(int type, void *fptr, } if (chipset_driver_info) bus_device_info_init(chipset_driver_info, "chipset", "uislib", - VERSION, NULL); + VERSION, NULL); return 1; } @@ -113,66 +113,57 @@ uisctrl_register_req_handler_ex(uuid_le switch_uuid, u32 client_str_len, u64 bytes), struct ultra_vbus_deviceinfo *chipset_driver_info) { - struct req_handler_info *pReqHandlerInfo; - int rc = 0; /* assume failure */ + struct req_handler_info *req_handler; LOGINF("type=%pUL, controlfunc=0x%p.\n", &switch_uuid, controlfunc); if (!controlfunc) { LOGERR("%pUL: controlfunc must be supplied\n", &switch_uuid); - goto Away; + return 0; } if (!server_channel_ok) { LOGERR("%pUL: Server_Channel_Ok must be supplied\n", &switch_uuid); - goto Away; + return 0; } if (!server_channel_init) { LOGERR("%pUL: Server_Channel_Init must be supplied\n", &switch_uuid); - goto Away; + return 0; } - pReqHandlerInfo = req_handler_add(switch_uuid, - switch_type_name, - controlfunc, - min_channel_bytes, - server_channel_ok, server_channel_init); - if (!pReqHandlerInfo) { + req_handler = req_handler_add(switch_uuid, + switch_type_name, + controlfunc, + min_channel_bytes, + server_channel_ok, server_channel_init); + if (!req_handler) { LOGERR("failed to add %pUL to server list\n", &switch_uuid); - goto Away; + return 0; } atomic_inc(&uisutils_registered_services); - rc = 1; /* success */ -Away: - if (rc) { - if (chipset_driver_info) - bus_device_info_init(chipset_driver_info, "chipset", - "uislib", VERSION, NULL); - } else - LOGERR("failed to register type %pUL.\n", &switch_uuid); + if (chipset_driver_info) { + bus_device_info_init(chipset_driver_info, "chipset", + "uislib", VERSION, NULL); + return 1; + } - return rc; + LOGERR("failed to register type %pUL.\n", &switch_uuid); + return 0; } EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex); int uisctrl_unregister_req_handler_ex(uuid_le switch_uuid) { - int rc = 0; /* assume failure */ - LOGINF("type=%pUL.\n", &switch_uuid); if (req_handler_del(switch_uuid) < 0) { LOGERR("failed to remove %pUL from server list\n", - &switch_uuid); - goto Away; + &switch_uuid); + return 0; } atomic_dec(&uisutils_registered_services); - rc = 1; /* success */ -Away: - if (!rc) - LOGERR("failed to unregister type %pUL.\n", &switch_uuid); - return rc; + return 1; } EXPORT_SYMBOL_GPL(uisctrl_unregister_req_handler_ex); @@ -214,10 +205,10 @@ uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, void *skb_in, frags[count].pi_pfn = page_to_pfn(virt_to_page(skb->data + offset)); frags[count].pi_off = - (unsigned long) (skb->data + offset) & PI_PAGE_MASK; + (unsigned long)(skb->data + offset) & PI_PAGE_MASK; size = min(firstfraglen, - (unsigned int) (PI_PAGE_SIZE - frags[count].pi_off)); + (unsigned int)(PI_PAGE_SIZE - frags[count].pi_off)); /* can take smallest of firstfraglen(what's left) OR * bytes left in the page */ @@ -231,7 +222,7 @@ uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, void *skb_in, if ((count + numfrags) > frags_max) { LOGERR("**** FAILED %s frags array too small: max:%d count+nr_frags:%d\n", - calling_ctx, frags_max, count + numfrags); + calling_ctx, frags_max, count + numfrags); return -1; /* failure */ } @@ -255,7 +246,6 @@ dolist: if (skb_shinfo(skb)->frag_list) { for (skbinlist = skb_shinfo(skb)->frag_list; skbinlist; skbinlist = skbinlist->next) { - c = uisutil_copy_fragsinfo_from_skb("recursive", skbinlist, skbinlist->len - skbinlist->data_len, @@ -272,17 +262,18 @@ dolist: if (skb_shinfo(skb)->frag_list) { } EXPORT_SYMBOL_GPL(uisutil_copy_fragsinfo_from_skb); -static LIST_HEAD(ReqHandlerInfo_list); /* list of struct req_handler_info */ -static DEFINE_SPINLOCK(ReqHandlerInfo_list_lock); +static LIST_HEAD(req_handler_info_list); /* list of struct req_handler_info */ +static DEFINE_SPINLOCK(req_handler_info_list_lock); struct req_handler_info * req_handler_add(uuid_le switch_uuid, const char *switch_type_name, int (*controlfunc)(struct io_msgs *), unsigned long min_channel_bytes, - int (*Server_Channel_Ok)(unsigned long channelBytes), - int (*Server_Channel_Init) - (void *x, unsigned char *clientStr, u32 clientStrLen, u64 bytes)) + int (*server_channel_ok)(unsigned long channel_bytes), + int (*server_channel_init) + (void *x, unsigned char *clientstr, u32 clientstr_len, + u64 bytes)) { struct req_handler_info *rc = NULL; @@ -292,14 +283,14 @@ req_handler_add(uuid_le switch_uuid, rc->switch_uuid = switch_uuid; rc->controlfunc = controlfunc; rc->min_channel_bytes = min_channel_bytes; - rc->server_channel_ok = Server_Channel_Ok; - rc->server_channel_init = Server_Channel_Init; + rc->server_channel_ok = server_channel_ok; + rc->server_channel_init = server_channel_init; if (switch_type_name) strncpy(rc->switch_type_name, switch_type_name, sizeof(rc->switch_type_name) - 1); - spin_lock(&ReqHandlerInfo_list_lock); - list_add_tail(&(rc->list_link), &ReqHandlerInfo_list); - spin_unlock(&ReqHandlerInfo_list_lock); + spin_lock(&req_handler_info_list_lock); + list_add_tail(&rc->list_link, &req_handler_info_list); + spin_unlock(&req_handler_info_list_lock); return rc; } @@ -310,15 +301,15 @@ req_handler_find(uuid_le switch_uuid) struct list_head *lelt, *tmp; struct req_handler_info *entry = NULL; - spin_lock(&ReqHandlerInfo_list_lock); - list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) { + spin_lock(&req_handler_info_list_lock); + list_for_each_safe(lelt, tmp, &req_handler_info_list) { entry = list_entry(lelt, struct req_handler_info, list_link); if (uuid_le_cmp(entry->switch_uuid, switch_uuid) == 0) { - spin_unlock(&ReqHandlerInfo_list_lock); + spin_unlock(&req_handler_info_list_lock); return entry; } } - spin_unlock(&ReqHandlerInfo_list_lock); + spin_unlock(&req_handler_info_list_lock); return NULL; } @@ -329,8 +320,8 @@ req_handler_del(uuid_le switch_uuid) struct req_handler_info *entry = NULL; int rc = -1; - spin_lock(&ReqHandlerInfo_list_lock); - list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) { + spin_lock(&req_handler_info_list_lock); + list_for_each_safe(lelt, tmp, &req_handler_info_list) { entry = list_entry(lelt, struct req_handler_info, list_link); if (uuid_le_cmp(entry->switch_uuid, switch_uuid) == 0) { list_del(lelt); @@ -338,6 +329,6 @@ req_handler_del(uuid_le switch_uuid) rc++; } } - spin_unlock(&ReqHandlerInfo_list_lock); + spin_unlock(&req_handler_info_list_lock); return rc; } diff --git a/drivers/staging/unisys/virthba/Kconfig b/drivers/staging/unisys/virthba/Kconfig index c0d7986e78c..9af98fc7acb 100644 --- a/drivers/staging/unisys/virthba/Kconfig +++ b/drivers/staging/unisys/virthba/Kconfig @@ -4,7 +4,7 @@ config UNISYS_VIRTHBA tristate "Unisys virthba driver" - depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_CHANNELSTUB && UNISYS_UISLIB && UNISYS_VIRTPCI && SCSI + depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_UISLIB && UNISYS_VIRTPCI && SCSI ---help--- If you say Y here, you will enable the Unisys virthba driver. diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index d7a629b5f11..e6ecea56049 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -85,7 +85,8 @@ static int virthba_host_reset_handler(struct scsi_cmnd *scsicmd); static const char *virthba_get_info(struct Scsi_Host *shp); static int virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg); static int virthba_queue_command_lck(struct scsi_cmnd *scsicmd, - void (*virthba_cmnd_done)(struct scsi_cmnd *)); + void (*virthba_cmnd_done) + (struct scsi_cmnd *)); static const struct x86_cpu_id unisys_spar_ids[] = { { X86_VENDOR_INTEL, 6, 62, X86_FEATURE_ANY }, @@ -107,19 +108,20 @@ static void virthba_slave_destroy(struct scsi_device *scsidev); static int process_incoming_rsps(void *); static int virthba_serverup(struct virtpci_dev *virtpcidev); static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state); -static void doDiskAddRemove(struct work_struct *work); +static void do_disk_add_remove(struct work_struct *work); static void virthba_serverdown_complete(struct work_struct *work); static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset); + size_t len, loff_t *offset); static ssize_t enable_ints_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos); + const char __user *buffer, size_t count, + loff_t *ppos); /*****************************************************/ /* Globals */ /*****************************************************/ static int rsltq_wait_usecs = 4000; /* Default 4ms */ -static unsigned int MaxBuffLen; +static unsigned int max_buff_len; /* Module options */ static char *virthba_options = "NONE"; @@ -165,6 +167,7 @@ struct virtdisk_info { atomic_t error_count; struct virtdisk_info *next; }; + /* Each Scsi_Host has a host_data area that contains this struct. */ struct virthba_info { struct Scsi_Host *scsihost; @@ -193,7 +196,7 @@ struct virthba_info { struct virtdisk_info head; }; -/* Work Data for DARWorkQ */ +/* Work Data for dar_work_queue */ struct diskaddremove { u8 add; /* 0-remove, 1-add */ struct Scsi_Host *shost; /* Scsi Host for this virthba instance */ @@ -244,7 +247,7 @@ static const struct file_operations debugfs_enable_ints_fops = { #define VIRTHBASOPENMAX 1 /* array of open devices maintained by open() and close(); */ -static struct virthba_devices_open VirtHbasOpen[VIRTHBASOPENMAX]; +static struct virthba_devices_open virthbas_open[VIRTHBASOPENMAX]; static struct dentry *virthba_debugfs_dir; /*****************************************************/ @@ -260,7 +263,7 @@ add_scsipending_entry(struct virthba_info *vhbainfo, char cmdtype, void *new) insert_location = vhbainfo->nextinsert; while (vhbainfo->pending[insert_location].sent != NULL) { insert_location = (insert_location + 1) % MAX_PENDING_REQUESTS; - if (insert_location == (int) vhbainfo->nextinsert) { + if (insert_location == (int)vhbainfo->nextinsert) { LOGERR("Queue should be full. insert_location<<%d>> Unable to find open slot for pending commands.\n", insert_location); spin_unlock_irqrestore(&vhbainfo->privlock, flags); @@ -289,7 +292,7 @@ add_scsipending_entry_with_wait(struct virthba_info *vhbainfo, char cmdtype, insert_location = add_scsipending_entry(vhbainfo, cmdtype, new); } - return (unsigned int) insert_location; + return (unsigned int)insert_location; } static void * @@ -300,13 +303,13 @@ del_scsipending_entry(struct virthba_info *vhbainfo, uintptr_t del) if (del >= MAX_PENDING_REQUESTS) { LOGERR("Invalid queue position <<%lu>> given to delete. MAX_PENDING_REQUESTS <<%d>>\n", - (unsigned long) del, MAX_PENDING_REQUESTS); + (unsigned long)del, MAX_PENDING_REQUESTS); } else { spin_lock_irqsave(&vhbainfo->privlock, flags); if (vhbainfo->pending[del].sent == NULL) LOGERR("Deleting already cleared queue entry at <<%lu>>.\n", - (unsigned long) del); + (unsigned long)del); sent = vhbainfo->pending[del].sent; @@ -318,30 +321,30 @@ del_scsipending_entry(struct virthba_info *vhbainfo, uintptr_t del) return sent; } -/* DARWorkQ (Disk Add/Remove) */ -static struct work_struct DARWorkQ; -static struct diskaddremove *DARWorkQHead; -static spinlock_t DARWorkQLock; -static unsigned short DARWorkQSched; +/* dar_work_queue (Disk Add/Remove) */ +static struct work_struct dar_work_queue; +static struct diskaddremove *dar_work_queue_head; +static spinlock_t dar_work_queue_lock; +static unsigned short dar_work_queue_sched; #define QUEUE_DISKADDREMOVE(dar) { \ - spin_lock_irqsave(&DARWorkQLock, flags); \ - if (!DARWorkQHead) { \ - DARWorkQHead = dar; \ + spin_lock_irqsave(&dar_work_queue_lock, flags); \ + if (!dar_work_queue_head) { \ + dar_work_queue_head = dar; \ dar->next = NULL; \ } \ else { \ - dar->next = DARWorkQHead; \ - DARWorkQHead = dar; \ + dar->next = dar_work_queue_head; \ + dar_work_queue_head = dar; \ } \ - if (!DARWorkQSched) { \ - schedule_work(&DARWorkQ); \ - DARWorkQSched = 1; \ + if (!dar_work_queue_sched) { \ + schedule_work(&dar_work_queue); \ + dar_work_queue_sched = 1; \ } \ - spin_unlock_irqrestore(&DARWorkQLock, flags); \ + spin_unlock_irqrestore(&dar_work_queue_lock, flags); \ } static inline void -SendDiskAddRemove(struct diskaddremove *dar) +send_disk_add_remove(struct diskaddremove *dar) { struct scsi_device *sdev; int error; @@ -365,31 +368,31 @@ SendDiskAddRemove(struct diskaddremove *dar) } /*****************************************************/ -/* DARWorkQ Handler Thread */ +/* dar_work_queue Handler Thread */ /*****************************************************/ static void -doDiskAddRemove(struct work_struct *work) +do_disk_add_remove(struct work_struct *work) { struct diskaddremove *dar; struct diskaddremove *tmphead; int i = 0; unsigned long flags; - spin_lock_irqsave(&DARWorkQLock, flags); - tmphead = DARWorkQHead; - DARWorkQHead = NULL; - DARWorkQSched = 0; - spin_unlock_irqrestore(&DARWorkQLock, flags); + spin_lock_irqsave(&dar_work_queue_lock, flags); + tmphead = dar_work_queue_head; + dar_work_queue_head = NULL; + dar_work_queue_sched = 0; + spin_unlock_irqrestore(&dar_work_queue_lock, flags); while (tmphead) { dar = tmphead; tmphead = dar->next; - SendDiskAddRemove(dar); + send_disk_add_remove(dar); i++; } } /*****************************************************/ -/* Routine to add entry to DARWorkQ */ +/* Routine to add entry to dar_work_queue */ /*****************************************************/ static void process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp) @@ -397,7 +400,7 @@ process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp) struct diskaddremove *dar; unsigned long flags; - dar = kzalloc(sizeof(struct diskaddremove), GFP_ATOMIC); + dar = kzalloc(sizeof(*dar), GFP_ATOMIC); if (dar) { dar->add = cmdrsp->disknotify.add; dar->shost = shost; @@ -416,10 +419,10 @@ process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp) /* Probe Remove Functions */ /*****************************************************/ static irqreturn_t -virthba_ISR(int irq, void *dev_id) +virthba_isr(int irq, void *dev_id) { - struct virthba_info *virthbainfo = (struct virthba_info *) dev_id; - struct channel_header __iomem *pChannelHeader; + struct virthba_info *virthbainfo = (struct virthba_info *)dev_id; + struct channel_header __iomem *channel_header; struct signal_queue_header __iomem *pqhdr; u64 mask; unsigned long long rc1; @@ -427,23 +430,23 @@ virthba_ISR(int irq, void *dev_id) if (virthbainfo == NULL) return IRQ_NONE; virthbainfo->interrupts_rcvd++; - pChannelHeader = virthbainfo->chinfo.queueinfo->chan; - if (((readq(&pChannelHeader->features) - & ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS) != 0) - && ((readq(&pChannelHeader->features) & + channel_header = virthbainfo->chinfo.queueinfo->chan; + if (((readq(&channel_header->features) + & ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS) != 0) && + ((readq(&channel_header->features) & ULTRA_IO_DRIVER_DISABLES_INTS) != 0)) { virthbainfo->interrupts_disabled++; mask = ~ULTRA_CHANNEL_ENABLE_INTS; rc1 = uisqueue_interlocked_and(virthbainfo->flags_addr, mask); } - if (spar_signalqueue_empty(pChannelHeader, IOCHAN_FROM_IOPART)) { + if (spar_signalqueue_empty(channel_header, IOCHAN_FROM_IOPART)) { virthbainfo->interrupts_notme++; return IRQ_NONE; } pqhdr = (struct signal_queue_header __iomem *) - ((char __iomem *) pChannelHeader + - readq(&pChannelHeader->ch_space_offset)) + IOCHAN_FROM_IOPART; + ((char __iomem *)channel_header + + readq(&channel_header->ch_space_offset)) + IOCHAN_FROM_IOPART; writeq(readq(&pqhdr->num_irq_received) + 1, &pqhdr->num_irq_received); atomic_set(&virthbainfo->interrupt_rcvd, 1); @@ -459,8 +462,8 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) struct virthba_info *virthbainfo; int rsp; int i; - irq_handler_t handler = virthba_ISR; - struct channel_header __iomem *pChannelHeader; + irq_handler_t handler = virthba_isr; + struct channel_header __iomem *channel_header; struct signal_queue_header __iomem *pqhdr; u64 mask; @@ -476,7 +479,7 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) * instance - this virthba that has just been created is an * instance of a scsi host adapter. This scsi_host_alloc * function allocates a new Scsi_Host struct & performs basic - * initializatoin. The host is not published to the scsi + * initialization. The host is not published to the scsi * midlayer until scsi_add_host is called. */ DBGINF("calling scsi_host_alloc.\n"); @@ -501,19 +504,19 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) * the max-channel value. */ LOGINF("virtpcidev->scsi.max.max_channel=%u, max_id=%u, max_lun=%u, cmd_per_lun=%u, max_io_size=%u\n", - (unsigned) virtpcidev->scsi.max.max_channel - 1, - (unsigned) virtpcidev->scsi.max.max_id, - (unsigned) virtpcidev->scsi.max.max_lun, - (unsigned) virtpcidev->scsi.max.cmd_per_lun, - (unsigned) virtpcidev->scsi.max.max_io_size); - scsihost->max_channel = (unsigned) virtpcidev->scsi.max.max_channel; - scsihost->max_id = (unsigned) virtpcidev->scsi.max.max_id; - scsihost->max_lun = (unsigned) virtpcidev->scsi.max.max_lun; - scsihost->cmd_per_lun = (unsigned) virtpcidev->scsi.max.cmd_per_lun; + (unsigned)virtpcidev->scsi.max.max_channel - 1, + (unsigned)virtpcidev->scsi.max.max_id, + (unsigned)virtpcidev->scsi.max.max_lun, + (unsigned)virtpcidev->scsi.max.cmd_per_lun, + (unsigned)virtpcidev->scsi.max.max_io_size); + scsihost->max_channel = (unsigned)virtpcidev->scsi.max.max_channel; + scsihost->max_id = (unsigned)virtpcidev->scsi.max.max_id; + scsihost->max_lun = (unsigned)virtpcidev->scsi.max.max_lun; + scsihost->cmd_per_lun = (unsigned)virtpcidev->scsi.max.cmd_per_lun; scsihost->max_sectors = - (unsigned short) (virtpcidev->scsi.max.max_io_size >> 9); + (unsigned short)(virtpcidev->scsi.max.max_io_size >> 9); scsihost->sg_tablesize = - (unsigned short) (virtpcidev->scsi.max.max_io_size / PAGE_SIZE); + (unsigned short)(virtpcidev->scsi.max.max_io_size / PAGE_SIZE); if (scsihost->sg_tablesize > MAX_PHYS_INFO) scsihost->sg_tablesize = MAX_PHYS_INFO; LOGINF("scsihost->max_channel=%u, max_id=%u, max_lun=%llu, cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n", @@ -544,11 +547,11 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) return -ENODEV; } - virthbainfo = (struct virthba_info *) scsihost->hostdata; + virthbainfo = (struct virthba_info *)scsihost->hostdata; memset(virthbainfo, 0, sizeof(struct virthba_info)); for (i = 0; i < VIRTHBASOPENMAX; i++) { - if (VirtHbasOpen[i].virthbainfo == NULL) { - VirtHbasOpen[i].virthbainfo = virthbainfo; + if (virthbas_open[i].virthbainfo == NULL) { + virthbas_open[i].virthbainfo = virthbainfo; break; } } @@ -584,10 +587,10 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) DBGINF("starting rsp thread -- queueinfo: 0x%p, threadinfo: 0x%p.\n", virthbainfo->chinfo.queueinfo, &virthbainfo->chinfo.threadinfo); - pChannelHeader = virthbainfo->chinfo.queueinfo->chan; + channel_header = virthbainfo->chinfo.queueinfo->chan; pqhdr = (struct signal_queue_header __iomem *) - ((char __iomem *)pChannelHeader + - readq(&pChannelHeader->ch_space_offset)) + IOCHAN_FROM_IOPART; + ((char __iomem *)channel_header + + readq(&channel_header->ch_space_offset)) + IOCHAN_FROM_IOPART; virthbainfo->flags_addr = &pqhdr->features; if (!uisthread_start(&virthbainfo->chinfo.threadinfo, @@ -646,11 +649,11 @@ virthba_remove(struct virtpci_dev *virtpcidev) { struct virthba_info *virthbainfo; struct Scsi_Host *scsihost = - (struct Scsi_Host *) virtpcidev->scsi.scsihost; + (struct Scsi_Host *)virtpcidev->scsi.scsihost; LOGINF("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no, virtpcidev->device_no); - virthbainfo = (struct virthba_info *) scsihost->hostdata; + virthbainfo = (struct virthba_info *)scsihost->hostdata; if (virthbainfo->interrupt_vector != -1) free_irq(virthbainfo->interrupt_vector, virthbainfo); LOGINF("Removing virtpcidev: 0x%p, virthbainfo: 0x%p\n", virtpcidev, @@ -679,7 +682,7 @@ forward_vdiskmgmt_command(enum vdisk_mgmt_types vdiskcmdtype, { struct uiscmdrsp *cmdrsp; struct virthba_info *virthbainfo = - (struct virthba_info *) scsihost->hostdata; + (struct virthba_info *)scsihost->hostdata; int notifyresult = 0xffff; wait_queue_head_t notifyevent; @@ -706,8 +709,8 @@ forward_vdiskmgmt_command(enum vdisk_mgmt_types vdiskcmdtype, /* specify the event that has to be triggered when this cmd is * complete */ - cmdrsp->vdiskmgmt.notify = (void *) ¬ifyevent; - cmdrsp->vdiskmgmt.notifyresult = (void *) ¬ifyresult; + cmdrsp->vdiskmgmt.notify = (void *)¬ifyevent; + cmdrsp->vdiskmgmt.notifyresult = (void *)¬ifyresult; /* save destination */ cmdrsp->vdiskmgmt.vdisktype = vdiskcmdtype; @@ -715,14 +718,14 @@ forward_vdiskmgmt_command(enum vdisk_mgmt_types vdiskcmdtype, cmdrsp->vdiskmgmt.vdest.id = vdest->id; cmdrsp->vdiskmgmt.vdest.lun = vdest->lun; cmdrsp->vdiskmgmt.scsicmd = - (void *) (uintptr_t) + (void *)(uintptr_t) add_scsipending_entry_with_wait(virthbainfo, CMD_VDISKMGMT_TYPE, - (void *) cmdrsp); + (void *)cmdrsp); uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, cmdrsp, IOCHAN_TO_IOPART, &virthbainfo->chinfo.insertlock, - DONT_ISSUE_INTERRUPT, (u64) NULL, + DONT_ISSUE_INTERRUPT, (u64)NULL, OK_TO_WAIT, "vhba"); LOGINF("VdiskMgmt waiting on event notifyevent=0x%p\n", cmdrsp->scsitaskmgmt.notify); @@ -742,7 +745,7 @@ forward_taskmgmt_command(enum task_mgmt_types tasktype, { struct uiscmdrsp *cmdrsp; struct virthba_info *virthbainfo = - (struct virthba_info *) scsidev->host->hostdata; + (struct virthba_info *)scsidev->host->hostdata; int notifyresult = 0xffff; wait_queue_head_t notifyevent; @@ -767,8 +770,8 @@ forward_taskmgmt_command(enum task_mgmt_types tasktype, cmdrsp->cmdtype = CMD_SCSITASKMGMT_TYPE; /* specify the event that has to be triggered when this */ /* cmd is complete */ - cmdrsp->scsitaskmgmt.notify = (void *) ¬ifyevent; - cmdrsp->scsitaskmgmt.notifyresult = (void *) ¬ifyresult; + cmdrsp->scsitaskmgmt.notify = (void *)¬ifyevent; + cmdrsp->scsitaskmgmt.notifyresult = (void *)¬ifyresult; /* save destination */ cmdrsp->scsitaskmgmt.tasktype = tasktype; @@ -776,15 +779,15 @@ forward_taskmgmt_command(enum task_mgmt_types tasktype, cmdrsp->scsitaskmgmt.vdest.id = scsidev->id; cmdrsp->scsitaskmgmt.vdest.lun = scsidev->lun; cmdrsp->scsitaskmgmt.scsicmd = - (void *) (uintptr_t) + (void *)(uintptr_t) add_scsipending_entry_with_wait(virthbainfo, CMD_SCSITASKMGMT_TYPE, - (void *) cmdrsp); + (void *)cmdrsp); uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, cmdrsp, IOCHAN_TO_IOPART, &virthbainfo->chinfo.insertlock, - DONT_ISSUE_INTERRUPT, (u64) NULL, + DONT_ISSUE_INTERRUPT, (u64)NULL, OK_TO_WAIT, "vhba"); LOGINF("TaskMgmt waiting on event notifyevent=0x%p\n", cmdrsp->scsitaskmgmt.notify); @@ -805,11 +808,11 @@ virthba_abort_handler(struct scsi_cmnd *scsicmd) struct virtdisk_info *vdisk; scsidev = scsicmd->device; - for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; + for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel == vdisk->channel) - && (scsidev->id == vdisk->id) - && (scsidev->lun == vdisk->lun)) { + if ((scsidev->channel == vdisk->channel) && + (scsidev->id == vdisk->id) && + (scsidev->lun == vdisk->lun)) { if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { atomic_inc(&vdisk->error_count); @@ -831,11 +834,11 @@ virthba_bus_reset_handler(struct scsi_cmnd *scsicmd) struct virtdisk_info *vdisk; scsidev = scsicmd->device; - for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; + for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel == vdisk->channel) - && (scsidev->id == vdisk->id) - && (scsidev->lun == vdisk->lun)) { + if ((scsidev->channel == vdisk->channel) && + (scsidev->id == vdisk->id) && + (scsidev->lun == vdisk->lun)) { if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { atomic_inc(&vdisk->error_count); @@ -857,11 +860,11 @@ virthba_device_reset_handler(struct scsi_cmnd *scsicmd) struct virtdisk_info *vdisk; scsidev = scsicmd->device; - for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; + for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel == vdisk->channel) - && (scsidev->id == vdisk->id) - && (scsidev->lun == vdisk->lun)) { + if ((scsidev->channel == vdisk->channel) && + (scsidev->id == vdisk->id) && + (scsidev->lun == vdisk->lun)) { if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { atomic_inc(&vdisk->error_count); @@ -915,7 +918,7 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, struct uiscmdrsp *cmdrsp; unsigned int i; struct virthba_info *virthbainfo = - (struct virthba_info *) scsihost->hostdata; + (struct virthba_info *)scsihost->hostdata; struct scatterlist *sg = NULL; struct scatterlist *sgl = NULL; int sg_failed = 0; @@ -940,9 +943,9 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, * will return the scsicmd pointer for completion */ insert_location = - add_scsipending_entry(virthbainfo, CMD_SCSI_TYPE, (void *) scsicmd); + add_scsipending_entry(virthbainfo, CMD_SCSI_TYPE, (void *)scsicmd); if (insert_location != -1) { - cmdrsp->scsi.scsicmd = (void *) (uintptr_t) insert_location; + cmdrsp->scsi.scsicmd = (void *)(uintptr_t)insert_location; } else { LOGERR("Queue is full. Returning busy.\n"); kfree(cmdrsp); @@ -961,13 +964,13 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, cmdrsp->scsi.bufflen = scsi_bufflen(scsicmd); /* keep track of the max buffer length so far. */ - if (cmdrsp->scsi.bufflen > MaxBuffLen) - MaxBuffLen = cmdrsp->scsi.bufflen; + if (cmdrsp->scsi.bufflen > max_buff_len) + max_buff_len = cmdrsp->scsi.bufflen; if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO) { LOGERR("scsicmd use_sg:%d greater than MAX:%d\n", scsi_sg_count(scsicmd), MAX_PHYS_INFO); - del_scsipending_entry(virthbainfo, (uintptr_t) insert_location); + del_scsipending_entry(virthbainfo, (uintptr_t)insert_location); kfree(cmdrsp); return 1; /* reject the command */ } @@ -989,22 +992,21 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, sgl = scsi_sglist(scsicmd); for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) { - cmdrsp->scsi.gpi_list[i].address = sg_phys(sg); cmdrsp->scsi.gpi_list[i].length = sg->length; if ((i != 0) && (sg->offset != 0)) LOGINF("Offset on a sg_entry other than zero =<<%d>>.\n", - sg->offset); + sg->offset); } if (sg_failed) { LOGERR("Start sg_list dump (entries %d, bufflen %d)...\n", - scsi_sg_count(scsicmd), cmdrsp->scsi.bufflen); + scsi_sg_count(scsicmd), cmdrsp->scsi.bufflen); for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) { LOGERR(" Entry(%d): page->[0x%p], phys->[0x%Lx], off(%d), len(%d)\n", - i, sg_page(sg), - (unsigned long long) sg_phys(sg), - sg->offset, sg->length); + i, sg_page(sg), + (unsigned long long)sg_phys(sg), + sg->offset, sg->length); } LOGERR("Done sg_list dump.\n"); /* BUG(); ***** For now, let it fail in uissd @@ -1022,12 +1024,12 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, &virthbainfo->chinfo. insertlock, DONT_ISSUE_INTERRUPT, - (u64) NULL, DONT_WAIT, "vhba"); + (u64)NULL, DONT_WAIT, "vhba"); if (i == 0) { /* queue must be full - and we said don't wait - return busy */ LOGERR("uisqueue_put_cmdrsp_with_lock ****FAILED\n"); kfree(cmdrsp); - del_scsipending_entry(virthbainfo, (uintptr_t) insert_location); + del_scsipending_entry(virthbainfo, (uintptr_t)insert_location); return SCSI_MLQUEUE_DEVICE_BUSY; } @@ -1047,9 +1049,9 @@ virthba_slave_alloc(struct scsi_device *scsidev) struct virtdisk_info *vdisk; struct virtdisk_info *tmpvdisk; struct virthba_info *virthbainfo; - struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host; + struct Scsi_Host *scsihost = (struct Scsi_Host *)scsidev->host; - virthbainfo = (struct virthba_info *) scsihost->hostdata; + virthbainfo = (struct virthba_info *)scsihost->hostdata; if (!virthbainfo) { LOGERR("Could not find virthba_info for scsihost\n"); return 0; /* even though we errored, treat as success */ @@ -1061,7 +1063,7 @@ virthba_slave_alloc(struct scsi_device *scsidev) (vdisk->next->lun == scsidev->lun)) return 0; } - tmpvdisk = kzalloc(sizeof(struct virtdisk_info), GFP_ATOMIC); + tmpvdisk = kzalloc(sizeof(*tmpvdisk), GFP_ATOMIC); if (!tmpvdisk) { /* error allocating */ LOGERR("Could not allocate memory for disk\n"); return 0; @@ -1089,9 +1091,9 @@ virthba_slave_destroy(struct scsi_device *scsidev) */ struct virtdisk_info *vdisk, *delvdisk; struct virthba_info *virthbainfo; - struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host; + struct Scsi_Host *scsihost = (struct Scsi_Host *)scsidev->host; - virthbainfo = (struct virthba_info *) scsihost->hostdata; + virthbainfo = (struct virthba_info *)scsihost->hostdata; if (!virthbainfo) LOGERR("Could not find virthba_info for scsihost\n"); for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) { @@ -1120,7 +1122,7 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) scsidev = scsicmd->device; memcpy(scsicmd->sense_buffer, cmdrsp->scsi.sensebuf, MAX_SENSE_SIZE); - sd = (struct sense_data *) scsicmd->sense_buffer; + sd = (struct sense_data *)scsicmd->sense_buffer; /* Do not log errors for disk-not-present inquiries */ if ((cmdrsp->scsi.cmnd[0] == INQUIRY) && @@ -1129,11 +1131,11 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) return; /* Okay see what our error_count is here.... */ - for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; + for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel != vdisk->channel) - || (scsidev->id != vdisk->id) - || (scsidev->lun != vdisk->lun)) + if ((scsidev->channel != vdisk->channel) || + (scsidev->id != vdisk->id) || + (scsidev->lun != vdisk->lun)) continue; if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { @@ -1148,8 +1150,8 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) if (atomic_read(&vdisk->error_count) == VIRTHBA_ERROR_COUNT) { LOGERR("Throtling SCSICMD errors disk <%d:%d:%d:%llu>\n", - scsidev->host->host_no, scsidev->id, - scsidev->channel, scsidev->lun); + scsidev->host->host_no, scsidev->id, + scsidev->channel, scsidev->lun); } atomic_set(&vdisk->ios_threshold, IOS_ERROR_THRESHOLD); } @@ -1169,8 +1171,8 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) struct virtdisk_info *vdisk; scsidev = scsicmd->device; - if ((cmdrsp->scsi.cmnd[0] == INQUIRY) - && (cmdrsp->scsi.bufflen >= MIN_INQUIRY_RESULT_LEN)) { + if ((cmdrsp->scsi.cmnd[0] == INQUIRY) && + (cmdrsp->scsi.bufflen >= MIN_INQUIRY_RESULT_LEN)) { if (cmdrsp->scsi.no_disk_result == 0) return; @@ -1198,21 +1200,20 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) sg = scsi_sglist(scsicmd); for (i = 0; i < scsi_sg_count(scsicmd); i++) { DBGVER("copying OUT OF buf into 0x%p %d\n", - sg_page(sg + i), sg[i].length); + sg_page(sg + i), sg[i].length); thispage_orig = kmap_atomic(sg_page(sg + i)); - thispage = (void *) ((unsigned long)thispage_orig | + thispage = (void *)((unsigned long)thispage_orig | sg[i].offset); memcpy(thispage, buf + bufind, sg[i].length); kunmap_atomic(thispage_orig); bufind += sg[i].length; } } else { - vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; for ( ; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel != vdisk->channel) - || (scsidev->id != vdisk->id) - || (scsidev->lun != vdisk->lun)) + if ((scsidev->channel != vdisk->channel) || + (scsidev->id != vdisk->id) || + (scsidev->lun != vdisk->lun)) continue; if (atomic_read(&vdisk->ios_threshold) > 0) { @@ -1249,8 +1250,8 @@ complete_vdiskmgmt_command(struct uiscmdrsp *cmdrsp) { /* copy the result of the taskmgmt and */ /* wake up the error handler that is waiting for this */ - *(int *) cmdrsp->vdiskmgmt.notifyresult = cmdrsp->vdiskmgmt.result; - wake_up_all((wait_queue_head_t *) cmdrsp->vdiskmgmt.notify); + *(int *)cmdrsp->vdiskmgmt.notifyresult = cmdrsp->vdiskmgmt.result; + wake_up_all((wait_queue_head_t *)cmdrsp->vdiskmgmt.notify); LOGINF("set notify result to %d\n", cmdrsp->vdiskmgmt.result); } @@ -1259,15 +1260,15 @@ complete_taskmgmt_command(struct uiscmdrsp *cmdrsp) { /* copy the result of the taskmgmt and */ /* wake up the error handler that is waiting for this */ - *(int *) cmdrsp->scsitaskmgmt.notifyresult = + *(int *)cmdrsp->scsitaskmgmt.notifyresult = cmdrsp->scsitaskmgmt.result; - wake_up_all((wait_queue_head_t *) cmdrsp->scsitaskmgmt.notify); + wake_up_all((wait_queue_head_t *)cmdrsp->scsitaskmgmt.notify); LOGINF("set notify result to %d\n", cmdrsp->scsitaskmgmt.result); } static void drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, - struct uiscmdrsp *cmdrsp) + struct uiscmdrsp *cmdrsp) { unsigned long flags; int qrslt = 0; @@ -1277,7 +1278,7 @@ drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, while (1) { spin_lock_irqsave(&virthbainfo->chinfo.insertlock, flags); if (!spar_channel_client_acquire_os(dc->queueinfo->chan, - "vhba")) { + "vhba")) { spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock, flags); virthbainfo->acquire_failed_cnt++; @@ -1294,14 +1295,15 @@ drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, * deletion */ scsicmd = del_scsipending_entry(virthbainfo, - (uintptr_t) cmdrsp->scsi.scsicmd); + (uintptr_t) + cmdrsp->scsi.scsicmd); if (!scsicmd) break; /* complete the orig cmd */ complete_scsi_command(cmdrsp, scsicmd); } else if (cmdrsp->cmdtype == CMD_SCSITASKMGMT_TYPE) { if (!del_scsipending_entry(virthbainfo, - (uintptr_t) cmdrsp->scsitaskmgmt.scsicmd)) + (uintptr_t)cmdrsp->scsitaskmgmt.scsicmd)) break; complete_taskmgmt_command(cmdrsp); } else if (cmdrsp->cmdtype == CMD_NOTIFYGUEST_TYPE) { @@ -1313,7 +1315,8 @@ drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, process_disk_notify(shost, cmdrsp); } else if (cmdrsp->cmdtype == CMD_VDISKMGMT_TYPE) { if (!del_scsipending_entry(virthbainfo, - (uintptr_t) cmdrsp->vdiskmgmt.scsicmd)) + (uintptr_t) + cmdrsp->vdiskmgmt.scsicmd)) break; complete_vdiskmgmt_command(cmdrsp); } else @@ -1347,7 +1350,7 @@ process_incoming_rsps(void *v) while (1) { wait_event_interruptible_timeout(virthbainfo->rsp_queue, (atomic_read(&virthbainfo->interrupt_rcvd) == 1), - usecs_to_jiffies(rsltq_wait_usecs)); + usecs_to_jiffies(rsltq_wait_usecs)); atomic_set(&virthbainfo->interrupt_rcvd, 0); /* drain queue */ drain_queue(virthbainfo, dc, cmdrsp); @@ -1367,7 +1370,7 @@ process_incoming_rsps(void *v) /*****************************************************/ static ssize_t info_debugfs_read(struct file *file, - char __user *buf, size_t len, loff_t *offset) + char __user *buf, size_t len, loff_t *offset) { ssize_t bytes_read = 0; int str_pos = 0; @@ -1383,13 +1386,14 @@ static ssize_t info_debugfs_read(struct file *file, return -ENOMEM; for (i = 0; i < VIRTHBASOPENMAX; i++) { - if (VirtHbasOpen[i].virthbainfo == NULL) + if (virthbas_open[i].virthbainfo == NULL) continue; - virthbainfo = VirtHbasOpen[i].virthbainfo; + virthbainfo = virthbas_open[i].virthbainfo; str_pos += scnprintf(vbuf + str_pos, - len - str_pos, "MaxBuffLen:%u\n", MaxBuffLen); + len - str_pos, "max_buff_len:%u\n", + max_buff_len); str_pos += scnprintf(vbuf + str_pos, len - str_pos, "\nvirthba result queue poll wait:%d usecs.\n", @@ -1418,14 +1422,14 @@ static ssize_t info_debugfs_read(struct file *file, return bytes_read; } -static ssize_t enable_ints_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos) +static ssize_t enable_ints_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { char buf[4]; int i, new_value; struct virthba_info *virthbainfo; - u64 __iomem *Features_addr; + u64 __iomem *features_addr; u64 mask; if (count >= ARRAY_SIZE(buf)) @@ -1434,37 +1438,37 @@ static ssize_t enable_ints_write(struct file *file, buf[count] = '\0'; if (copy_from_user(buf, buffer, count)) { LOGERR("copy_from_user failed. buf<<%.*s>> count<<%lu>>\n", - (int) count, buf, count); + (int)count, buf, count); return -EFAULT; } - i = kstrtoint(buf, 10 , &new_value); + i = kstrtoint(buf, 10, &new_value); if (i != 0) { LOGERR("Failed to scan value for enable_ints, buf<<%.*s>>", - (int) count, buf); + (int)count, buf); return -EFAULT; } /* set all counts to new_value usually 0 */ for (i = 0; i < VIRTHBASOPENMAX; i++) { - if (VirtHbasOpen[i].virthbainfo != NULL) { - virthbainfo = VirtHbasOpen[i].virthbainfo; - Features_addr = + if (virthbas_open[i].virthbainfo != NULL) { + virthbainfo = virthbas_open[i].virthbainfo; + features_addr = &virthbainfo->chinfo.queueinfo->chan->features; if (new_value == 1) { mask = ~(ULTRA_IO_CHANNEL_IS_POLLING | ULTRA_IO_DRIVER_DISABLES_INTS); - uisqueue_interlocked_and(Features_addr, mask); + uisqueue_interlocked_and(features_addr, mask); mask = ULTRA_IO_DRIVER_ENABLES_INTS; - uisqueue_interlocked_or(Features_addr, mask); + uisqueue_interlocked_or(features_addr, mask); rsltq_wait_usecs = 4000000; } else { mask = ~(ULTRA_IO_DRIVER_ENABLES_INTS | ULTRA_IO_DRIVER_DISABLES_INTS); - uisqueue_interlocked_and(Features_addr, mask); + uisqueue_interlocked_and(features_addr, mask); mask = ULTRA_IO_CHANNEL_IS_POLLING; - uisqueue_interlocked_or(Features_addr, mask); + uisqueue_interlocked_or(features_addr, mask); rsltq_wait_usecs = 4000; } } @@ -1477,7 +1481,7 @@ static int virthba_serverup(struct virtpci_dev *virtpcidev) { struct virthba_info *virthbainfo = - (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi. + (struct virthba_info *)((struct Scsi_Host *)virtpcidev->scsi. scsihost)->hostdata; DBGINF("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no, @@ -1535,26 +1539,26 @@ virthba_serverdown_complete(struct work_struct *work) /* Fail Commands that weren't completed */ spin_lock_irqsave(&virthbainfo->privlock, flags); for (i = 0; i < MAX_PENDING_REQUESTS; i++) { - pendingdel = &(virthbainfo->pending[i]); + pendingdel = &virthbainfo->pending[i]; switch (pendingdel->cmdtype) { case CMD_SCSI_TYPE: - scsicmd = (struct scsi_cmnd *) pendingdel->sent; + scsicmd = (struct scsi_cmnd *)pendingdel->sent; scsicmd->result = (DID_RESET << 16); if (scsicmd->scsi_done) scsicmd->scsi_done(scsicmd); break; case CMD_SCSITASKMGMT_TYPE: - cmdrsp = (struct uiscmdrsp *) pendingdel->sent; + cmdrsp = (struct uiscmdrsp *)pendingdel->sent; DBGINF("cmdrsp=0x%x, notify=0x%x\n", cmdrsp, cmdrsp->scsitaskmgmt.notify); - *(int *) cmdrsp->scsitaskmgmt.notifyresult = + *(int *)cmdrsp->scsitaskmgmt.notifyresult = TASK_MGMT_FAILED; wake_up_all((wait_queue_head_t *) cmdrsp->scsitaskmgmt.notify); break; case CMD_VDISKMGMT_TYPE: - cmdrsp = (struct uiscmdrsp *) pendingdel->sent; - *(int *) cmdrsp->vdiskmgmt.notifyresult = + cmdrsp = (struct uiscmdrsp *)pendingdel->sent; + *(int *)cmdrsp->vdiskmgmt.notifyresult = VDISK_MGMT_FAILED; wake_up_all((wait_queue_head_t *) cmdrsp->vdiskmgmt.notify); @@ -1584,8 +1588,10 @@ virthba_serverdown_complete(struct work_struct *work) static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state) { + int stat = 1; + struct virthba_info *virthbainfo = - (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi. + (struct virthba_info *)((struct Scsi_Host *)virtpcidev->scsi. scsihost)->hostdata; DBGINF("virthba_serverdown"); @@ -1598,11 +1604,12 @@ virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state) &virthbainfo->serverdown_completion); } else if (virthbainfo->serverchangingstate) { LOGERR("Server already processing change state message\n"); - return 0; - } else + stat = 0; + } else { LOGERR("Server already down, but another server down message received."); + } - return 1; + return stat; } /*****************************************************/ @@ -1655,23 +1662,22 @@ virthba_mod_init(void) POSTCODE_LINUX_3(VHBA_CREATE_FAILURE_PC, error, POSTCODE_SEVERITY_ERR); } else { - /* create the debugfs directories and entries */ virthba_debugfs_dir = debugfs_create_dir("virthba", NULL); debugfs_create_file("info", S_IRUSR, virthba_debugfs_dir, - NULL, &debugfs_info_fops); + NULL, &debugfs_info_fops); debugfs_create_u32("rqwait_usecs", S_IRUSR | S_IWUSR, - virthba_debugfs_dir, &rsltq_wait_usecs); + virthba_debugfs_dir, &rsltq_wait_usecs); debugfs_create_file("enable_ints", S_IWUSR, - virthba_debugfs_dir, NULL, - &debugfs_enable_ints_fops); - /* Initialize DARWorkQ */ - INIT_WORK(&DARWorkQ, doDiskAddRemove); - spin_lock_init(&DARWorkQLock); + virthba_debugfs_dir, NULL, + &debugfs_enable_ints_fops); + /* Initialize dar_work_queue */ + INIT_WORK(&dar_work_queue, do_disk_add_remove); + spin_lock_init(&dar_work_queue_lock); /* clear out array */ for (i = 0; i < VIRTHBASOPENMAX; i++) - VirtHbasOpen[i].virthbainfo = NULL; + virthbas_open[i].virthbainfo = NULL; /* Initialize the serverdown workqueue */ virthba_serverdown_workqueue = create_singlethread_workqueue("virthba_serverdown"); @@ -1746,7 +1752,6 @@ virthba_mod_exit(void) debugfs_remove_recursive(virthba_debugfs_dir); LOGINF("Leaving virthba_mod_exit\n"); - } /* specify function to be run at module insertion time */ diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c index 39b828dce50..8fdfd6f3605 100644 --- a/drivers/staging/unisys/virtpci/virtpci.c +++ b/drivers/staging/unisys/virtpci/virtpci.c @@ -104,8 +104,6 @@ static ssize_t virtpci_driver_attr_store(struct kobject *kobj, const char *buf, size_t count); static int virtpci_bus_match(struct device *dev, struct device_driver *drv); static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env); -static int virtpci_device_suspend(struct device *dev, pm_message_t state); -static int virtpci_device_resume(struct device *dev); static int virtpci_device_probe(struct device *dev); static int virtpci_device_remove(struct device *dev); @@ -128,8 +126,6 @@ static struct bus_type virtpci_bus_type = { .name = "uisvirtpci", .match = virtpci_bus_match, .uevent = virtpci_uevent, - .suspend = virtpci_device_suspend, - .resume = virtpci_device_resume, }; static struct device virtpci_rootbus_device = { @@ -279,9 +275,9 @@ static int add_vbus(struct add_vbus_guestpart *addparams) POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR); return 0; } - write_vbus_chp_info(vbus->platform_data /* chanptr */ , + write_vbus_chp_info(vbus->platform_data /* chanptr */, &chipset_driver_info); - write_vbus_bus_info(vbus->platform_data /* chanptr */ , + write_vbus_bus_info(vbus->platform_data /* chanptr */, &bus_driver_info); LOGINF("Added vbus %d; device %s created successfully\n", addparams->bus_no, BUS_ID(vbus)); @@ -466,7 +462,7 @@ static int pause_vhba(struct pause_virt_guestpart *pauseparams) GET_SCSIADAPINFO_FROM_CHANPTR(pauseparams->chanptr); LOGINF("Pausing vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2); - i = virtpci_device_serverdown(NULL /*no parent bus */ , VIRTHBA_TYPE, + i = virtpci_device_serverdown(NULL /*no parent bus */, VIRTHBA_TYPE, &scsi.wwnn, NULL); if (i) LOGINF("Paused vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, @@ -487,7 +483,7 @@ static int pause_vnic(struct pause_virt_guestpart *pauseparams) LOGINF("Pausing vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", net.mac_addr[0], net.mac_addr[1], net.mac_addr[2], net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]); - i = virtpci_device_serverdown(NULL /*no parent bus */ , VIRTNIC_TYPE, + i = virtpci_device_serverdown(NULL /*no parent bus */, VIRTNIC_TYPE, NULL, net.mac_addr); if (i) { LOGINF(" Paused vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", @@ -508,7 +504,7 @@ static int resume_vhba(struct resume_virt_guestpart *resumeparams) GET_SCSIADAPINFO_FROM_CHANPTR(resumeparams->chanptr); LOGINF("Resuming vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2); - i = virtpci_device_serverup(NULL /*no parent bus */ , VIRTHBA_TYPE, + i = virtpci_device_serverup(NULL /*no parent bus */, VIRTHBA_TYPE, &scsi.wwnn, NULL); if (i) LOGINF("Resumed vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, @@ -530,7 +526,7 @@ resume_vnic(struct resume_virt_guestpart *resumeparams) LOGINF("Resuming vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", net.mac_addr[0], net.mac_addr[1], net.mac_addr[2], net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]); - i = virtpci_device_serverup(NULL /*no parent bus */ , VIRTNIC_TYPE, + i = virtpci_device_serverup(NULL /*no parent bus */, VIRTNIC_TYPE, NULL, net.mac_addr); if (i) { LOGINF(" Resumed vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", @@ -551,7 +547,7 @@ static int delete_vhba(struct del_virt_guestpart *delparams) GET_SCSIADAPINFO_FROM_CHANPTR(delparams->chanptr); LOGINF("Deleting vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2); - i = virtpci_device_del(NULL /*no parent bus */ , VIRTHBA_TYPE, + i = virtpci_device_del(NULL /*no parent bus */, VIRTHBA_TYPE, &scsi.wwnn, NULL); if (i) { LOGINF("Deleted vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, @@ -574,7 +570,7 @@ static int delete_vnic(struct del_virt_guestpart *delparams) LOGINF("Deleting vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", net.mac_addr[0], net.mac_addr[1], net.mac_addr[2], net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]); - i = virtpci_device_del(NULL /*no parent bus */ , VIRTNIC_TYPE, NULL, + i = virtpci_device_del(NULL /*no parent bus */, VIRTNIC_TYPE, NULL, net.mac_addr); if (i) { LOGINF("Deleted vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", @@ -757,18 +753,6 @@ static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } -static int virtpci_device_suspend(struct device *dev, pm_message_t state) -{ - DBGINF("In virtpci_device_suspend -NYI ****\n"); - return 0; -} - -static int virtpci_device_resume(struct device *dev) -{ - DBGINF("In virtpci_device_resume -NYI ****\n"); - return 0; -} - /* For a child device just created on a client bus, fill in * information about the driver that is controlling this device into * the appropriate slot within the vbus channel of the bus @@ -1338,18 +1322,13 @@ static ssize_t virtpci_driver_attr_show(struct kobject *kobj, ssize_t ret = 0; struct driver_private *dprivate = to_driver(kobj); - struct device_driver *driver; + struct device_driver *driver = dprivate->driver; - if (dprivate != NULL) - driver = dprivate->driver; - else - driver = NULL; + DBGINF("In virtpci_driver_attr_show driver->name:%s\n", driver->name); + + if (dattr->show) + ret = dattr->show(driver, buf); - DBGINF("In virtpci_driver_attr_show driver->name:%s\n", driver->name); - if (driver) { - if (dattr->show) - ret = dattr->show(driver, buf); - } return ret; } @@ -1361,19 +1340,13 @@ static ssize_t virtpci_driver_attr_store(struct kobject *kobj, ssize_t ret = 0; struct driver_private *dprivate = to_driver(kobj); - struct device_driver *driver; - - if (dprivate != NULL) - driver = dprivate->driver; - else - driver = NULL; + struct device_driver *driver = dprivate->driver; DBGINF("In virtpci_driver_attr_store driver->name:%s\n", driver->name); - if (driver) { - if (dattr->store) - ret = dattr->store(driver, buf, count); - } + if (dattr->store) + ret = dattr->store(driver, buf, count); + return ret; } diff --git a/drivers/staging/unisys/visorchannel/visorchannel.h b/drivers/staging/unisys/visorchannel/visorchannel.h index 5061edff959..63f1b976037 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel.h +++ b/drivers/staging/unisys/visorchannel/visorchannel.h @@ -29,49 +29,48 @@ #define BOOL int #endif -/* VISORCHANNEL is an opaque structure to users. - * Fields are declared only in the implementation .c files. - */ -typedef struct VISORCHANNEL_Tag VISORCHANNEL; - /* Note that for visorchannel_create() and visorchannel_create_overlapped(), - * <channelBytes> and <guid> arguments may be 0 if we are a channel CLIENT. + * <channel_bytes> and <guid> arguments may be 0 if we are a channel CLIENT. * In this case, the values can simply be read from the channel header. */ -VISORCHANNEL *visorchannel_create(HOSTADDRESS physaddr, - ulong channelBytes, uuid_le guid); -VISORCHANNEL *visorchannel_create_overlapped(ulong channelBytes, - VISORCHANNEL *parent, ulong off, - uuid_le guid); -VISORCHANNEL *visorchannel_create_with_lock(HOSTADDRESS physaddr, - ulong channelBytes, uuid_le guid); -VISORCHANNEL *visorchannel_create_overlapped_with_lock(ulong channelBytes, - VISORCHANNEL *parent, - ulong off, uuid_le guid); -void visorchannel_destroy(VISORCHANNEL *channel); -int visorchannel_read(VISORCHANNEL *channel, ulong offset, +struct visorchannel *visorchannel_create(HOSTADDRESS physaddr, + ulong channel_bytes, uuid_le guid); +struct visorchannel *visorchannel_create_overlapped(ulong channel_bytes, + struct visorchannel *parent, + ulong off, uuid_le guid); +struct visorchannel *visorchannel_create_with_lock(HOSTADDRESS physaddr, + ulong channel_bytes, + uuid_le guid); +struct visorchannel *visorchannel_create_overlapped_with_lock( + ulong channel_bytes, + struct visorchannel *parent, + ulong off, uuid_le guid); +void visorchannel_destroy(struct visorchannel *channel); +int visorchannel_read(struct visorchannel *channel, ulong offset, void *local, ulong nbytes); -int visorchannel_write(VISORCHANNEL *channel, ulong offset, +int visorchannel_write(struct visorchannel *channel, ulong offset, void *local, ulong nbytes); -int visorchannel_clear(VISORCHANNEL *channel, ulong offset, +int visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, ulong nbytes); -BOOL visorchannel_signalremove(VISORCHANNEL *channel, u32 queue, void *msg); -BOOL visorchannel_signalinsert(VISORCHANNEL *channel, u32 queue, void *msg); -int visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, u32 queue); -int visorchannel_signalqueue_max_slots(VISORCHANNEL *channel, u32 queue); - -HOSTADDRESS visorchannel_get_physaddr(VISORCHANNEL *channel); -ulong visorchannel_get_nbytes(VISORCHANNEL *channel); -char *visorchannel_id(VISORCHANNEL *channel, char *s); -char *visorchannel_zoneid(VISORCHANNEL *channel, char *s); -u64 visorchannel_get_clientpartition(VISORCHANNEL *channel); -uuid_le visorchannel_get_uuid(VISORCHANNEL *channel); -struct memregion *visorchannel_get_memregion(VISORCHANNEL *channel); +BOOL visorchannel_signalremove(struct visorchannel *channel, u32 queue, + void *msg); +BOOL visorchannel_signalinsert(struct visorchannel *channel, u32 queue, + void *msg); +int visorchannel_signalqueue_slots_avail(struct visorchannel *channel, + u32 queue); +int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue); +HOSTADDRESS visorchannel_get_physaddr(struct visorchannel *channel); +ulong visorchannel_get_nbytes(struct visorchannel *channel); +char *visorchannel_id(struct visorchannel *channel, char *s); +char *visorchannel_zoneid(struct visorchannel *channel, char *s); +u64 visorchannel_get_clientpartition(struct visorchannel *channel); +uuid_le visorchannel_get_uuid(struct visorchannel *channel); +struct memregion *visorchannel_get_memregion(struct visorchannel *channel); char *visorchannel_uuid_id(uuid_le *guid, char *s); -void visorchannel_debug(VISORCHANNEL *channel, int nQueues, +void visorchannel_debug(struct visorchannel *channel, int num_queues, struct seq_file *seq, u32 off); -void visorchannel_dump_section(VISORCHANNEL *chan, char *s, +void visorchannel_dump_section(struct visorchannel *chan, char *s, int off, int len, struct seq_file *seq); -void __iomem *visorchannel_get_header(VISORCHANNEL *channel); +void __iomem *visorchannel_get_header(struct visorchannel *channel); #endif diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c index 36559d5fa67..0188ef866fd 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c +++ b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c @@ -28,14 +28,15 @@ #define MYDRVNAME "visorchannel" -struct VISORCHANNEL_Tag { +struct visorchannel { struct memregion *memregion; /* from visor_memregion_create() */ struct channel_header chan_hdr; uuid_le guid; ulong size; - BOOL needs_lock; - spinlock_t insert_lock; - spinlock_t remove_lock; + BOOL needs_lock; /* channel creator knows if more than one + * thread will be inserting or removing */ + spinlock_t insert_lock; /* protect head writes in chan_hdr */ + spinlock_t remove_lock; /* protect tail writes in chan_hdr */ struct { struct signal_queue_header req_queue; @@ -45,18 +46,18 @@ struct VISORCHANNEL_Tag { } safe_uis_queue; }; -/* Creates the VISORCHANNEL abstraction for a data area in memory, but does - * NOT modify this data area. +/* Creates the struct visorchannel abstraction for a data area in memory, + * but does NOT modify this data area. */ -static VISORCHANNEL * -visorchannel_create_guts(HOSTADDRESS physaddr, ulong channelBytes, - VISORCHANNEL *parent, ulong off, uuid_le guid, +static struct visorchannel * +visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes, + struct visorchannel *parent, ulong off, uuid_le guid, BOOL needs_lock) { - VISORCHANNEL *p = NULL; + struct visorchannel *p = NULL; void *rc = NULL; - p = kmalloc(sizeof(VISORCHANNEL), GFP_KERNEL|__GFP_NORETRY); + p = kmalloc(sizeof(*p), GFP_KERNEL|__GFP_NORETRY); if (p == NULL) { ERRDRV("allocation failed: (status=0)\n"); rc = NULL; @@ -87,18 +88,18 @@ visorchannel_create_guts(HOSTADDRESS physaddr, ulong channelBytes, rc = NULL; goto cleanup; } - if (channelBytes == 0) + if (channel_bytes == 0) /* we had better be a CLIENT of this channel */ - channelBytes = (ulong)p->chan_hdr.size; + channel_bytes = (ulong)p->chan_hdr.size; if (uuid_le_cmp(guid, NULL_UUID_LE) == 0) /* we had better be a CLIENT of this channel */ guid = p->chan_hdr.chtype; - if (visor_memregion_resize(p->memregion, channelBytes) < 0) { + if (visor_memregion_resize(p->memregion, channel_bytes) < 0) { ERRDRV("visor_memregion_resize failed: (status=0)\n"); rc = NULL; goto cleanup; } - p->size = channelBytes; + p->size = channel_bytes; p->guid = guid; rc = p; @@ -113,44 +114,45 @@ cleanup: return rc; } -VISORCHANNEL * -visorchannel_create(HOSTADDRESS physaddr, ulong channelBytes, uuid_le guid) +struct visorchannel * +visorchannel_create(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid) { - return visorchannel_create_guts(physaddr, channelBytes, NULL, 0, guid, + return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid, FALSE); } EXPORT_SYMBOL_GPL(visorchannel_create); -VISORCHANNEL * -visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channelBytes, +struct visorchannel * +visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid) { - return visorchannel_create_guts(physaddr, channelBytes, NULL, 0, guid, + return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid, TRUE); } EXPORT_SYMBOL_GPL(visorchannel_create_with_lock); -VISORCHANNEL * -visorchannel_create_overlapped(ulong channelBytes, - VISORCHANNEL *parent, ulong off, uuid_le guid) +struct visorchannel * +visorchannel_create_overlapped(ulong channel_bytes, + struct visorchannel *parent, ulong off, + uuid_le guid) { - return visorchannel_create_guts(0, channelBytes, parent, off, guid, + return visorchannel_create_guts(0, channel_bytes, parent, off, guid, FALSE); } EXPORT_SYMBOL_GPL(visorchannel_create_overlapped); -VISORCHANNEL * -visorchannel_create_overlapped_with_lock(ulong channelBytes, - VISORCHANNEL *parent, ulong off, +struct visorchannel * +visorchannel_create_overlapped_with_lock(ulong channel_bytes, + struct visorchannel *parent, ulong off, uuid_le guid) { - return visorchannel_create_guts(0, channelBytes, parent, off, guid, + return visorchannel_create_guts(0, channel_bytes, parent, off, guid, TRUE); } EXPORT_SYMBOL_GPL(visorchannel_create_overlapped_with_lock); void -visorchannel_destroy(VISORCHANNEL *channel) +visorchannel_destroy(struct visorchannel *channel) { if (channel == NULL) return; @@ -163,14 +165,14 @@ visorchannel_destroy(VISORCHANNEL *channel) EXPORT_SYMBOL_GPL(visorchannel_destroy); HOSTADDRESS -visorchannel_get_physaddr(VISORCHANNEL *channel) +visorchannel_get_physaddr(struct visorchannel *channel) { return visor_memregion_get_physaddr(channel->memregion); } EXPORT_SYMBOL_GPL(visorchannel_get_physaddr); ulong -visorchannel_get_nbytes(VISORCHANNEL *channel) +visorchannel_get_nbytes(struct visorchannel *channel) { return channel->size; } @@ -185,42 +187,42 @@ visorchannel_uuid_id(uuid_le *guid, char *s) EXPORT_SYMBOL_GPL(visorchannel_uuid_id); char * -visorchannel_id(VISORCHANNEL *channel, char *s) +visorchannel_id(struct visorchannel *channel, char *s) { return visorchannel_uuid_id(&channel->guid, s); } EXPORT_SYMBOL_GPL(visorchannel_id); char * -visorchannel_zoneid(VISORCHANNEL *channel, char *s) +visorchannel_zoneid(struct visorchannel *channel, char *s) { return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s); } EXPORT_SYMBOL_GPL(visorchannel_zoneid); HOSTADDRESS -visorchannel_get_clientpartition(VISORCHANNEL *channel) +visorchannel_get_clientpartition(struct visorchannel *channel) { return channel->chan_hdr.partition_handle; } EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition); uuid_le -visorchannel_get_uuid(VISORCHANNEL *channel) +visorchannel_get_uuid(struct visorchannel *channel) { return channel->guid; } EXPORT_SYMBOL_GPL(visorchannel_get_uuid); struct memregion * -visorchannel_get_memregion(VISORCHANNEL *channel) +visorchannel_get_memregion(struct visorchannel *channel) { return channel->memregion; } EXPORT_SYMBOL_GPL(visorchannel_get_memregion); int -visorchannel_read(VISORCHANNEL *channel, ulong offset, +visorchannel_read(struct visorchannel *channel, ulong offset, void *local, ulong nbytes) { int rc = visor_memregion_read(channel->memregion, offset, @@ -235,7 +237,7 @@ visorchannel_read(VISORCHANNEL *channel, ulong offset, EXPORT_SYMBOL_GPL(visorchannel_read); int -visorchannel_write(VISORCHANNEL *channel, ulong offset, +visorchannel_write(struct visorchannel *channel, ulong offset, void *local, ulong nbytes) { if (offset == 0 && nbytes >= sizeof(struct channel_header)) @@ -246,7 +248,8 @@ visorchannel_write(VISORCHANNEL *channel, ulong offset, EXPORT_SYMBOL_GPL(visorchannel_write); int -visorchannel_clear(VISORCHANNEL *channel, ulong offset, u8 ch, ulong nbytes) +visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, + ulong nbytes) { int rc = -1; int bufsize = 65536; @@ -285,7 +288,7 @@ cleanup: EXPORT_SYMBOL_GPL(visorchannel_clear); void __iomem * -visorchannel_get_header(VISORCHANNEL *channel) +visorchannel_get_header(struct visorchannel *channel) { return (void __iomem *)&channel->chan_hdr; } @@ -316,7 +319,7 @@ EXPORT_SYMBOL_GPL(visorchannel_get_header); sizeof((sig_hdr)->FIELD)) >= 0) static BOOL -sig_read_header(VISORCHANNEL *channel, u32 queue, +sig_read_header(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr) { BOOL rc = FALSE; @@ -344,7 +347,7 @@ cleanup: } static BOOL -sig_do_data(VISORCHANNEL *channel, u32 queue, +sig_do_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data, BOOL is_write) { @@ -373,14 +376,14 @@ cleanup: } static inline BOOL -sig_read_data(VISORCHANNEL *channel, u32 queue, +sig_read_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data) { return sig_do_data(channel, queue, sig_hdr, slot, data, FALSE); } static inline BOOL -sig_write_data(VISORCHANNEL *channel, u32 queue, +sig_write_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data) { return sig_do_data(channel, queue, sig_hdr, slot, data, TRUE); @@ -408,27 +411,21 @@ safe_sig_queue_validate(struct signal_queue_header *psafe_sqh, return 1; } /* end safe_sig_queue_validate */ -BOOL -visorchannel_signalremove(VISORCHANNEL *channel, u32 queue, void *msg) +static BOOL +signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) { - BOOL rc = FALSE; struct signal_queue_header sig_hdr; - if (channel->needs_lock) - spin_lock(&channel->remove_lock); - if (!sig_read_header(channel, queue, &sig_hdr)) { - rc = FALSE; - goto cleanup; - } - if (sig_hdr.head == sig_hdr.tail) { - rc = FALSE; /* no signals to remove */ - goto cleanup; + return FALSE; } + if (sig_hdr.head == sig_hdr.tail) + return FALSE; /* no signals to remove */ + sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg)) { - ERRDRV("sig_read_data failed: (status=%d)\n", rc); - goto cleanup; + ERRDRV("sig_read_data failed\n"); + return FALSE; } sig_hdr.num_received++; @@ -437,53 +434,54 @@ visorchannel_signalremove(VISORCHANNEL *channel, u32 queue, void *msg) */ mb(); /* required for channel synch */ if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail)) { - ERRDRV("visor_memregion_write of Tail failed: (status=%d)\n", - rc); - goto cleanup; + ERRDRV("visor_memregion_write of Tail failed\n"); + return FALSE; } if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received)) { - ERRDRV("visor_memregion_write of NumSignalsReceived failed: (status=%d)\n", - rc); - goto cleanup; + ERRDRV("visor_memregion_write of NumSignalsReceived failed\n"); + return FALSE; } - rc = TRUE; -cleanup: - if (channel->needs_lock) + return TRUE; +} + +BOOL +visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) +{ + BOOL rc; + + if (channel->needs_lock) { + spin_lock(&channel->remove_lock); + rc = signalremove_inner(channel, queue, msg); spin_unlock(&channel->remove_lock); + } else { + rc = signalremove_inner(channel, queue, msg); + } return rc; } EXPORT_SYMBOL_GPL(visorchannel_signalremove); -BOOL -visorchannel_signalinsert(VISORCHANNEL *channel, u32 queue, void *msg) +static BOOL +signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) { - BOOL rc = FALSE; struct signal_queue_header sig_hdr; - if (channel->needs_lock) - spin_lock(&channel->insert_lock); - if (!sig_read_header(channel, queue, &sig_hdr)) { - rc = FALSE; - goto cleanup; + return FALSE; } sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots); if (sig_hdr.head == sig_hdr.tail) { sig_hdr.num_overflows++; - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows)) { - ERRDRV("visor_memregion_write of NumOverflows failed: (status=%d)\n", - rc); - goto cleanup; - } - rc = FALSE; - goto cleanup; + if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows)) + ERRDRV("visor_memregion_write of NumOverflows failed\n"); + + return FALSE; } if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg)) { - ERRDRV("sig_write_data failed: (status=%d)\n", rc); - goto cleanup; + ERRDRV("sig_write_data failed\n"); + return FALSE; } sig_hdr.num_sent++; @@ -492,26 +490,36 @@ visorchannel_signalinsert(VISORCHANNEL *channel, u32 queue, void *msg) */ mb(); /* required for channel synch */ if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head)) { - ERRDRV("visor_memregion_write of Head failed: (status=%d)\n", - rc); - goto cleanup; + ERRDRV("visor_memregion_write of Head failed\n"); + return FALSE; } if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent)) { - ERRDRV("visor_memregion_write of NumSignalsSent failed: (status=%d)\n", - rc); - goto cleanup; + ERRDRV("visor_memregion_write of NumSignalsSent failed\n"); + return FALSE; } - rc = TRUE; -cleanup: - if (channel->needs_lock) + + return TRUE; +} + +BOOL +visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) +{ + BOOL rc; + + if (channel->needs_lock) { + spin_lock(&channel->insert_lock); + rc = signalinsert_inner(channel, queue, msg); spin_unlock(&channel->insert_lock); + } else { + rc = signalinsert_inner(channel, queue, msg); + } return rc; } EXPORT_SYMBOL_GPL(visorchannel_signalinsert); int -visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, u32 queue) +visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue) { struct signal_queue_header sig_hdr; u32 slots_avail, slots_used; @@ -530,7 +538,7 @@ visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, u32 queue) EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail); int -visorchannel_signalqueue_max_slots(VISORCHANNEL *channel, u32 queue) +visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue) { struct signal_queue_header sig_hdr; @@ -565,7 +573,7 @@ sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq) } void -visorchannel_debug(VISORCHANNEL *channel, int nQueues, +visorchannel_debug(struct visorchannel *channel, int num_queues, struct seq_file *seq, u32 off) { HOSTADDRESS addr = 0; @@ -625,7 +633,7 @@ visorchannel_debug(VISORCHANNEL *channel, int nQueues, if ((phdr->ch_space_offset == 0) || (errcode < 0)) ; else - for (i = 0; i < nQueues; i++) { + for (i = 0; i < num_queues; i++) { struct signal_queue_header q; errcode = visorchannel_read(channel, @@ -647,7 +655,7 @@ visorchannel_debug(VISORCHANNEL *channel, int nQueues, EXPORT_SYMBOL_GPL(visorchannel_debug); void -visorchannel_dump_section(VISORCHANNEL *chan, char *s, +visorchannel_dump_section(struct visorchannel *chan, char *s, int off, int len, struct seq_file *seq) { char *buf, *tbuf, *fmtbuf; diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index 373fa36b711..e51fd4e3fa2 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -28,85 +28,75 @@ #define CURRENT_FILE_PC VISOR_CHIPSET_PC_file_c -static struct cdev Cdev; -static VISORCHANNEL **PControlVm_channel; -static dev_t MajorDev = -1; /**< indicates major num for device */ -static BOOL Registered = FALSE; +static struct cdev file_cdev; +static struct visorchannel **file_controlvm_channel; +static dev_t majordev = -1; /**< indicates major num for device */ +static BOOL registered = FALSE; static int visorchipset_open(struct inode *inode, struct file *file); static int visorchipset_release(struct inode *inode, struct file *file); static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma); -#ifdef HAVE_UNLOCKED_IOCTL long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -#else -int visorchipset_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -#endif static const struct file_operations visorchipset_fops = { .owner = THIS_MODULE, .open = visorchipset_open, .read = NULL, .write = NULL, -#ifdef HAVE_UNLOCKED_IOCTL .unlocked_ioctl = visorchipset_ioctl, -#else - .ioctl = visorchipset_ioctl, -#endif .release = visorchipset_release, .mmap = visorchipset_mmap, }; int -visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel) +visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) { - int rc = -1; + int rc = 0; - PControlVm_channel = pControlVm_channel; - MajorDev = majorDev; - cdev_init(&Cdev, &visorchipset_fops); - Cdev.owner = THIS_MODULE; - if (MAJOR(MajorDev) == 0) { + file_controlvm_channel = controlvm_channel; + majordev = major_dev; + cdev_init(&file_cdev, &visorchipset_fops); + file_cdev.owner = THIS_MODULE; + if (MAJOR(majordev) == 0) { /* dynamic major device number registration required */ - if (alloc_chrdev_region(&MajorDev, 0, 1, MYDRVNAME) < 0) { + if (alloc_chrdev_region(&majordev, 0, 1, MYDRVNAME) < 0) { ERRDRV("Unable to allocate+register char device %s", MYDRVNAME); - goto Away; + return -1; } - Registered = TRUE; - INFODRV("New major number %d registered\n", MAJOR(MajorDev)); + registered = TRUE; + INFODRV("New major number %d registered\n", MAJOR(majordev)); } else { /* static major device number registration required */ - if (register_chrdev_region(MajorDev, 1, MYDRVNAME) < 0) { + if (register_chrdev_region(majordev, 1, MYDRVNAME) < 0) { ERRDRV("Unable to register char device %s", MYDRVNAME); - goto Away; + return -1; } - Registered = TRUE; - INFODRV("Static major number %d registered\n", MAJOR(MajorDev)); + registered = TRUE; + INFODRV("Static major number %d registered\n", MAJOR(majordev)); } - if (cdev_add(&Cdev, MKDEV(MAJOR(MajorDev), 0), 1) < 0) { + rc = cdev_add(&file_cdev, MKDEV(MAJOR(majordev), 0), 1); + if (rc < 0) { ERRDRV("failed to create char device: (status=%d)\n", rc); - goto Away; + return -1; } INFODRV("Registered char device for %s (major=%d)", - MYDRVNAME, MAJOR(MajorDev)); - rc = 0; -Away: - return rc; + MYDRVNAME, MAJOR(majordev)); + return 0; } void visorchipset_file_cleanup(void) { - if (Cdev.ops != NULL) - cdev_del(&Cdev); - Cdev.ops = NULL; - if (Registered) { - if (MAJOR(MajorDev) >= 0) { - unregister_chrdev_region(MajorDev, 1); - MajorDev = MKDEV(0, 0); + if (file_cdev.ops != NULL) + cdev_del(&file_cdev); + file_cdev.ops = NULL; + if (registered) { + if (MAJOR(majordev) >= 0) { + unregister_chrdev_region(majordev, 1); + majordev = MKDEV(0, 0); } - Registered = FALSE; + registered = FALSE; } } @@ -114,17 +104,12 @@ static int visorchipset_open(struct inode *inode, struct file *file) { unsigned minor_number = iminor(inode); - int rc = -ENODEV; DEBUGDRV("%s", __func__); if (minor_number != 0) - goto Away; + return -ENODEV; file->private_data = NULL; - rc = 0; -Away: - if (rc < 0) - ERRDRV("%s minor=%d failed", __func__, minor_number); - return rc; + return 0; } static int @@ -137,7 +122,7 @@ visorchipset_release(struct inode *inode, struct file *file) static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma) { - ulong physAddr = 0; + ulong physaddr = 0; ulong offset = vma->vm_pgoff << PAGE_SHIFT; GUEST_PHYSICAL_ADDRESS addr = 0; @@ -150,11 +135,11 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) switch (offset) { case VISORCHIPSET_MMAP_CONTROLCHANOFFSET: vma->vm_flags |= VM_IO; - if (*PControlVm_channel == NULL) { + if (*file_controlvm_channel == NULL) { ERRDRV("%s no controlvm channel yet", __func__); return -ENXIO; } - visorchannel_read(*PControlVm_channel, + visorchannel_read(*file_controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, gp_control_channel), &addr, sizeof(addr)); @@ -162,10 +147,10 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) ERRDRV("%s control channel address is 0", __func__); return -ENXIO; } - physAddr = (ulong) (addr); - DEBUGDRV("mapping physical address = 0x%lx", physAddr); + physaddr = (ulong)addr; + DEBUGDRV("mapping physical address = 0x%lx", physaddr); if (remap_pfn_range(vma, vma->vm_start, - physAddr >> PAGE_SHIFT, + physaddr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, /*pgprot_noncached */ (vma->vm_page_prot))) { @@ -180,16 +165,8 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -#ifdef HAVE_UNLOCKED_IOCTL -long -visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -#else -int -visorchipset_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -#endif +long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int rc = SUCCESS; s64 adjustment; s64 vrtc_offset; @@ -200,28 +177,21 @@ visorchipset_ioctl(struct inode *inode, struct file *file, vrtc_offset = issue_vmcall_query_guest_virtual_time_offset(); if (copy_to_user ((void __user *)arg, &vrtc_offset, sizeof(vrtc_offset))) { - rc = -EFAULT; - goto Away; + return -EFAULT; } DBGINF("insde visorchipset_ioctl, cmd=%d, vrtc_offset=%lld", cmd, vrtc_offset); - break; + return SUCCESS; case VMCALL_UPDATE_PHYSICAL_TIME: if (copy_from_user (&adjustment, (void __user *)arg, sizeof(adjustment))) { - rc = -EFAULT; - goto Away; + return -EFAULT; } DBGINF("insde visorchipset_ioctl, cmd=%d, adjustment=%lld", cmd, adjustment); - rc = issue_vmcall_update_physical_time(adjustment); - break; + return issue_vmcall_update_physical_time(adjustment); default: LOGERR("visorchipset_ioctl received invalid command"); - rc = -EFAULT; - break; + return -EFAULT; } -Away: - DBGINF("exiting %d!", rc); - return rc; } diff --git a/drivers/staging/unisys/visorchipset/file.h b/drivers/staging/unisys/visorchipset/file.h index 21bb906242e..dc7a19556b3 100644 --- a/drivers/staging/unisys/visorchipset/file.h +++ b/drivers/staging/unisys/visorchipset/file.h @@ -20,7 +20,8 @@ #include "globals.h" -int visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel); +int visorchipset_file_init(dev_t majorDev, + struct visorchannel **pControlVm_channel); void visorchipset_file_cleanup(void); #endif diff --git a/drivers/staging/unisys/visorchipset/globals.h b/drivers/staging/unisys/visorchipset/globals.h index 0fe14599f18..a1d35d4bef2 100644 --- a/drivers/staging/unisys/visorchipset/globals.h +++ b/drivers/staging/unisys/visorchipset/globals.h @@ -15,7 +15,6 @@ * details. */ - #ifndef __VISORCHIPSET_GLOBALS_H__ #define __VISORCHIPSET_GLOBALS_H__ @@ -28,7 +27,6 @@ #define MYDRVNAME "visorchipset" - /* module parameters */ extern int visorchipset_testvnic; diff --git a/drivers/staging/unisys/visorchipset/testing.h b/drivers/staging/unisys/visorchipset/testing.h deleted file mode 100644 index 573aa8b5ba6..00000000000 --- a/drivers/staging/unisys/visorchipset/testing.h +++ /dev/null @@ -1,43 +0,0 @@ -/* testing.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * 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 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VISORCHIPSET_TESTING_H__ -#define __VISORCHIPSET_TESTING_H__ - -#define VISORCHIPSET_TEST_PROC -#include <linux/uuid.h> -#include "globals.h" -#include "controlvmchannel.h" - -void test_produce_test_message(struct controlvm_message *msg, - int isLocalTestAddr); -BOOL test_consume_test_message(struct controlvm_message *msg); -void test_manufacture_vnic_client_add(void *p); -void test_manufacture_vnic_client_add_phys(HOSTADDRESS addr); -void test_manufacture_preamble_messages(void); -void test_manufacture_device_attach(ulong busNo, ulong devNo); -void test_manufacture_device_add(ulong busNo, ulong devNo, uuid_le dataTypeGuid, - void *pChannel); -void test_manufacture_add_bus(ulong busNo, ulong maxDevices, - uuid_le id, u8 *name, BOOL isServer); -void test_manufacture_device_destroy(ulong busNo, ulong devNo); -void test_manufacture_bus_destroy(ulong busNo); -void test_manufacture_detach_externalPort(ulong switchNo, ulong externalPortNo); -void test_manufacture_detach_internalPort(ulong switchNo, ulong internalPortNo); -void test_cleanup(void); - -#endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 46dad63fa2c..98f3ba4c13a 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -158,61 +158,6 @@ findbus(struct list_head *list, u32 bus_no) return NULL; } -/** Attributes for a particular Supervisor switch. - */ -struct visorchipset_switch_info { - u32 switch_no; - struct visorchipset_state state; - uuid_le switch_type_uuid; - u8 *authservice1; - u8 *authservice2; - u8 *authservice3; - u8 *security_context; - u64 reserved; - u32 reserved2; /* control_vm_id */ - struct device dev; - BOOL dev_exists; - struct controlvm_message_header pending_msg_hdr; -}; - -/** Attributes for a particular Supervisor external port, which is connected - * to a specific switch. - */ -struct visorchipset_externalport_info { - u32 switch_no; - u32 external_port_no; - struct visorchipset_state state; - uuid_le network_zone_uuid; - int pd_port; - u8 *ip; - u8 *ip_netmask; - u8 *ip_broadcast; - u8 *ip_network; - u8 *ip_gateway; - u8 *ip_dns; - u64 reserved1; - u32 reserved2; /* control_vm_id */ - struct device dev; - BOOL dev_exists; - struct controlvm_message_header pending_msg_hdr; -}; - -/** Attributes for a particular Supervisor internal port, which is how a - * device connects to a particular switch. - */ -struct visorchipset_internalport_info { - u32 switch_no; - u32 internal_port_no; - struct visorchipset_state state; - u32 bus_no; /* valid only when state.attached == 1 */ - u32 dev_no; /* valid only when state.attached == 1 */ - u64 reserved1; - u32 reserved2; /* CONTROLVM_ID */ - struct controlvm_message_header pending_msg_hdr; - MYPROCOBJECT *proc_object; - -}; - /* These functions will be called from within visorchipset when certain * events happen. (The implementation of these functions is outside of * visorchipset.) diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 7e6be32cf7b..f606ee9e0de 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -20,7 +20,6 @@ #include "procobjecttree.h" #include "visorchannel.h" #include "periodic_work.h" -#include "testing.h" #include "file.h" #include "parser.h" #include "uniklog.h" @@ -102,7 +101,7 @@ static struct controlvm_message_packet g_DeviceChangeStatePacket; static LIST_HEAD(BusInfoList); static LIST_HEAD(DevInfoList); -static VISORCHANNEL *ControlVm_channel; +static struct visorchannel *ControlVm_channel; typedef struct { u8 __iomem *ptr; /* pointer to base address of payload pool */ @@ -1595,7 +1594,7 @@ parahotplug_next_id(void) static unsigned long parahotplug_next_expiration(void) { - return jiffies + PARAHOTPLUG_TIMEOUT_MS * HZ / 1000; + return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS); } /* diff --git a/drivers/staging/unisys/visorchipset/visorchipset_umode.h b/drivers/staging/unisys/visorchipset/visorchipset_umode.h index 06ba5b7e425..6cf6eccb3f4 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_umode.h +++ b/drivers/staging/unisys/visorchipset/visorchipset_umode.h @@ -26,8 +26,6 @@ #ifndef __VISORCHIPSET_UMODE_H #define __VISORCHIPSET_UMODE_H - - /** The user-mode program can access the control channel buffer directly * via this memory map. */ diff --git a/drivers/staging/unisys/visorutil/charqueue.c b/drivers/staging/unisys/visorutil/charqueue.c index 1ce7003c3a9..ac7acb7c5b7 100644 --- a/drivers/staging/unisys/visorutil/charqueue.c +++ b/drivers/staging/unisys/visorutil/charqueue.c @@ -28,7 +28,7 @@ struct charqueue { int alloc_size; int nslots; - spinlock_t lock; + spinlock_t lock; /* read/write lock for this structure */ int head, tail; unsigned char buf[0]; }; diff --git a/drivers/staging/unisys/visorutil/procobjecttree.c b/drivers/staging/unisys/visorutil/procobjecttree.c index 195772d22c9..82279ca5fbe 100644 --- a/drivers/staging/unisys/visorutil/procobjecttree.c +++ b/drivers/staging/unisys/visorutil/procobjecttree.c @@ -25,12 +25,12 @@ * need in order to call the callback function that supplies the /proc read * info for that file. */ -typedef struct { +struct proc_dir_entry_context { void (*show_property)(struct seq_file *, void *, int); MYPROCOBJECT *procObject; int propertyIndex; -} PROCDIRENTRYCONTEXT; +}; /** This describes the attributes of a tree rooted at * <procDirRoot>/<name[0]>/<name[1]>/... @@ -86,7 +86,7 @@ struct MYPROCOBJECT_Tag { /** this is a holding area for the context information that is needed * to run the /proc callback function */ - PROCDIRENTRYCONTEXT *procDirPropertyContexts; + struct proc_dir_entry_context *procDirPropertyContexts; }; @@ -254,15 +254,16 @@ MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type, goto Away; } obj->procDirPropertyContexts = - kzalloc((type->nProperties + 1) * sizeof(PROCDIRENTRYCONTEXT), + kzalloc((type->nProperties + 1) * + sizeof(struct proc_dir_entry_context), GFP_KERNEL | __GFP_NORETRY); if (obj->procDirPropertyContexts == NULL) { ERRDRV("out of memory\n"); goto Away; } - obj->procDirProperties = - kzalloc((type->nProperties + 1) * sizeof(struct proc_dir_entry *), - GFP_KERNEL | __GFP_NORETRY); + obj->procDirProperties = kzalloc((type->nProperties + 1) * + sizeof(struct proc_dir_entry *), + GFP_KERNEL | __GFP_NORETRY); if (obj->procDirProperties == NULL) { ERRDRV("out of memory\n"); goto Away; @@ -276,8 +277,8 @@ MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type, /* only create properties that have names */ obj->procDirProperties[i] = createProcFile(type->propertyNames[i], - obj->procDir, &proc_fops, - &obj->procDirPropertyContexts[i]); + obj->procDir, &proc_fops, + &obj->procDirPropertyContexts[i]); if (obj->procDirProperties[i] == NULL) { rc = NULL; goto Away; @@ -340,7 +341,7 @@ EXPORT_SYMBOL_GPL(visor_proc_DestroyObject); static int seq_show(struct seq_file *seq, void *offset) { - PROCDIRENTRYCONTEXT *ctx = (PROCDIRENTRYCONTEXT *)(seq->private); + struct proc_dir_entry_context *ctx = seq->private; if (ctx == NULL) { ERRDRV("I don't have a freakin' clue..."); diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index f8c5fc371c4..565ba189afb 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -27,7 +27,8 @@ * * Functions: * BBuGetFrameTime - Calculate data frame transmitting time - * BBvCaculateParameter - Caculate PhyLength, PhyService and Phy Signal parameter for baseband Tx + * BBvCaculateParameter - Caculate PhyLength, PhyService and Phy Signal + * parameter for baseband Tx * BBbReadEmbedded - Embedded read baseband register via MAC * BBbWriteEmbedded - Embedded write baseband register via MAC * BBbVT3253Init - VIA VT3253 baseband chip init code @@ -1698,46 +1699,6 @@ static const unsigned short awcFrameTime[MAX_RATE] = { 10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216 }; -/*--------------------- Static Functions --------------------------*/ - -static -unsigned long -s_ulGetRatio(struct vnt_private *priv); - -static -void -s_vChangeAntenna( - struct vnt_private *priv -); - -static -void -s_vChangeAntenna( - struct vnt_private *priv -) -{ - if (priv->dwRxAntennaSel == 0) { - priv->dwRxAntennaSel = 1; - if (priv->bTxRxAntInv == true) - BBvSetRxAntennaMode(priv, ANT_A); - else - BBvSetRxAntennaMode(priv, ANT_B); - } else { - priv->dwRxAntennaSel = 0; - if (priv->bTxRxAntInv == true) - BBvSetRxAntennaMode(priv, ANT_B); - else - BBvSetRxAntennaMode(priv, ANT_A); - } - if (priv->dwTxAntennaSel == 0) { - priv->dwTxAntennaSel = 1; - BBvSetTxAntennaMode(priv, ANT_B); - } else { - priv->dwTxAntennaSel = 0; - BBvSetTxAntennaMode(priv, ANT_A); - } -} - /*--------------------- Export Variables --------------------------*/ /* * Description: Calculate data frame transmitting time @@ -2412,303 +2373,3 @@ BBvExitDeepSleep(struct vnt_private *priv, unsigned char byLocalID) BBbWriteEmbedded(priv, 0x0C, 0x00); /* CR12 */ BBbWriteEmbedded(priv, 0x0D, 0x01); /* CR13 */ } - -static -unsigned long -s_ulGetRatio(struct vnt_private *priv) -{ - unsigned long ulRatio = 0; - unsigned long ulMaxPacket; - unsigned long ulPacketNum; - - /* This is a thousand-ratio */ - ulMaxPacket = priv->uNumSQ3[RATE_54M]; - if (priv->uNumSQ3[RATE_54M] != 0) { - ulPacketNum = priv->uNumSQ3[RATE_54M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_54M; - } - if (priv->uNumSQ3[RATE_48M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_48M; - ulMaxPacket = priv->uNumSQ3[RATE_48M]; - } - if (priv->uNumSQ3[RATE_36M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M] + - priv->uNumSQ3[RATE_36M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_36M; - ulMaxPacket = priv->uNumSQ3[RATE_36M]; - } - if (priv->uNumSQ3[RATE_24M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M] + - priv->uNumSQ3[RATE_36M] + priv->uNumSQ3[RATE_24M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_24M; - ulMaxPacket = priv->uNumSQ3[RATE_24M]; - } - if (priv->uNumSQ3[RATE_18M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M] + - priv->uNumSQ3[RATE_36M] + priv->uNumSQ3[RATE_24M] + - priv->uNumSQ3[RATE_18M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_18M; - ulMaxPacket = priv->uNumSQ3[RATE_18M]; - } - if (priv->uNumSQ3[RATE_12M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M] + - priv->uNumSQ3[RATE_36M] + priv->uNumSQ3[RATE_24M] + - priv->uNumSQ3[RATE_18M] + priv->uNumSQ3[RATE_12M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_12M; - ulMaxPacket = priv->uNumSQ3[RATE_12M]; - } - if (priv->uNumSQ3[RATE_11M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M] - - priv->uNumSQ3[RATE_2M] - priv->uNumSQ3[RATE_5M] - - priv->uNumSQ3[RATE_6M] - priv->uNumSQ3[RATE_9M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_11M; - ulMaxPacket = priv->uNumSQ3[RATE_11M]; - } - if (priv->uNumSQ3[RATE_9M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M] - - priv->uNumSQ3[RATE_2M] - priv->uNumSQ3[RATE_5M] - - priv->uNumSQ3[RATE_6M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_9M; - ulMaxPacket = priv->uNumSQ3[RATE_9M]; - } - if (priv->uNumSQ3[RATE_6M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M] - - priv->uNumSQ3[RATE_2M] - priv->uNumSQ3[RATE_5M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_6M; - ulMaxPacket = priv->uNumSQ3[RATE_6M]; - } - if (priv->uNumSQ3[RATE_5M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M] - - priv->uNumSQ3[RATE_2M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_55M; - ulMaxPacket = priv->uNumSQ3[RATE_5M]; - } - if (priv->uNumSQ3[RATE_2M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_2M; - ulMaxPacket = priv->uNumSQ3[RATE_2M]; - } - if (priv->uNumSQ3[RATE_1M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_1M; - } - - return ulRatio; -} - -void -BBvClearAntDivSQ3Value(struct vnt_private *priv) -{ - unsigned int ii; - - priv->uDiversityCnt = 0; - for (ii = 0; ii < MAX_RATE; ii++) - priv->uNumSQ3[ii] = 0; -} - -/* - * Description: Antenna Diversity - * - * Parameters: - * In: - * priv - Device Structure - * byRSR - RSR from received packet - * bySQ3 - SQ3 value from received packet - * Out: - * none - * - * Return Value: none - * - */ - -void BBvAntennaDiversity(struct vnt_private *priv, - unsigned char byRxRate, unsigned char bySQ3) -{ - if ((byRxRate >= MAX_RATE) || (priv->wAntDiversityMaxRate >= MAX_RATE)) - return; - - priv->uDiversityCnt++; - - priv->uNumSQ3[byRxRate]++; - - if (priv->byAntennaState == 0) { - if (priv->uDiversityCnt > priv->ulDiversityNValue) { - pr_debug("ulDiversityNValue=[%d],54M-[%d]\n", - (int)priv->ulDiversityNValue, - (int)priv->uNumSQ3[(int)priv->wAntDiversityMaxRate]); - - if (priv->uNumSQ3[priv->wAntDiversityMaxRate] < priv->uDiversityCnt/2) { - priv->ulRatio_State0 = s_ulGetRatio(priv); - pr_debug("SQ3_State0, rate = [%08x]\n", - (int)priv->ulRatio_State0); - - if (priv->byTMax == 0) - return; - pr_debug("1.[%08x], uNumSQ3[%d]=%d, %d\n", - (int)priv->ulRatio_State0, - (int)priv->wAntDiversityMaxRate, - (int)priv->uNumSQ3[(int)priv->wAntDiversityMaxRate], - (int)priv->uDiversityCnt); - - s_vChangeAntenna(priv); - priv->byAntennaState = 1; - del_timer(&priv->TimerSQ3Tmax3); - del_timer(&priv->TimerSQ3Tmax2); - priv->TimerSQ3Tmax1.expires = RUN_AT(priv->byTMax * HZ); - add_timer(&priv->TimerSQ3Tmax1); - - } else { - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - } - BBvClearAntDivSQ3Value(priv); - - } - } else { /* byAntennaState == 1 */ - - if (priv->uDiversityCnt > priv->ulDiversityMValue) { - del_timer(&priv->TimerSQ3Tmax1); - - priv->ulRatio_State1 = s_ulGetRatio(priv); - pr_debug("RX:SQ3_State1, rate0 = %08x,rate1 = %08x\n", - (int)priv->ulRatio_State0, - (int)priv->ulRatio_State1); - - if (priv->ulRatio_State1 < priv->ulRatio_State0) { - pr_debug("2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n", - (int)priv->ulRatio_State0, - (int)priv->ulRatio_State1, - (int)priv->wAntDiversityMaxRate, - (int)priv->uNumSQ3[(int)priv->wAntDiversityMaxRate], - (int)priv->uDiversityCnt); - - s_vChangeAntenna(priv); - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - priv->TimerSQ3Tmax2.expires = RUN_AT(priv->byTMax2 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - add_timer(&priv->TimerSQ3Tmax2); - } - priv->byAntennaState = 0; - BBvClearAntDivSQ3Value(priv); - } - } /* byAntennaState */ -} - -/*+ - * - * Description: - * Timer for SQ3 antenna diversity - * - * Parameters: - * In: - * Out: - * none - * - * Return Value: none - * - -*/ - -void -TimerSQ3CallBack( - unsigned long data -) -{ - struct vnt_private *priv = (struct vnt_private *)data; - unsigned long flags; - - pr_debug("TimerSQ3CallBack...\n"); - - spin_lock_irqsave(&priv->lock, flags); - - pr_debug("3.[%08x][%08x], %d\n", - (int)priv->ulRatio_State0, (int)priv->ulRatio_State1, - (int)priv->uDiversityCnt); - - s_vChangeAntenna(priv); - priv->byAntennaState = 0; - BBvClearAntDivSQ3Value(priv); - - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - priv->TimerSQ3Tmax2.expires = RUN_AT(priv->byTMax2 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - add_timer(&priv->TimerSQ3Tmax2); - - spin_unlock_irqrestore(&priv->lock, flags); -} - -/*+ - * - * Description: - * Timer for SQ3 antenna diversity - * - * Parameters: - * In: - * pvSysSpec1 - * hDeviceContext - Pointer to the adapter - * pvSysSpec2 - * pvSysSpec3 - * Out: - * none - * - * Return Value: none - * - -*/ - -void -TimerState1CallBack( - unsigned long data -) -{ - struct vnt_private *priv = (struct vnt_private *)data; - unsigned long flags; - - pr_debug("TimerState1CallBack...\n"); - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->uDiversityCnt < priv->ulDiversityMValue/100) { - s_vChangeAntenna(priv); - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - priv->TimerSQ3Tmax2.expires = RUN_AT(priv->byTMax2 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - add_timer(&priv->TimerSQ3Tmax2); - } else { - priv->ulRatio_State1 = s_ulGetRatio(priv); - pr_debug("SQ3_State1, rate0 = %08x,rate1 = %08x\n", - (int)priv->ulRatio_State0, - (int)priv->ulRatio_State1); - - if (priv->ulRatio_State1 < priv->ulRatio_State0) { - pr_debug("2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n", - (int)priv->ulRatio_State0, - (int)priv->ulRatio_State1, - (int)priv->wAntDiversityMaxRate, - (int)priv->uNumSQ3[(int)priv->wAntDiversityMaxRate], - (int)priv->uDiversityCnt); - - s_vChangeAntenna(priv); - - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - priv->TimerSQ3Tmax2.expires = RUN_AT(priv->byTMax2 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - add_timer(&priv->TimerSQ3Tmax2); - } - } - priv->byAntennaState = 0; - BBvClearAntDivSQ3Value(priv); - - spin_unlock_irqrestore(&priv->lock, flags); -} diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index d9f6d63e4ab..43a4fb1f357 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -93,21 +93,4 @@ void BBvSetRxAntennaMode(struct vnt_private *, unsigned char byAntennaMode); void BBvSetDeepSleep(struct vnt_private *, unsigned char byLocalID); void BBvExitDeepSleep(struct vnt_private *, unsigned char byLocalID); -/* timer for antenna diversity */ - -void -TimerSQ3CallBack( - unsigned long -); - -void -TimerState1CallBack( - unsigned long -); - -void BBvAntennaDiversity(struct vnt_private *, - unsigned char byRxRate, unsigned char bySQ3); -void -BBvClearAntDivSQ3Value(struct vnt_private *); - #endif /* __BASEBAND_H__ */ diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index a0796405c30..1cdcf49b244 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -68,8 +68,8 @@ /*--------------------- Static Variables --------------------------*/ -static const unsigned short cwRXBCNTSFOff[MAX_RATE] = -{17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3}; +static const unsigned short cwRXBCNTSFOff[MAX_RATE] = { + 17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3}; /*--------------------- Static Functions --------------------------*/ @@ -670,6 +670,9 @@ void CARDvSetRSPINF(struct vnt_private *pDevice, u8 bb_type) { union vnt_phy_field_swap phy; unsigned char byTxRate, byRsvTime; /* For OFDM */ + unsigned long flags; + + spin_lock_irqsave(&pDevice->lock, flags); /* Set to Page1 */ MACvSelectPage1(pDevice->PortOffset); @@ -767,6 +770,8 @@ void CARDvSetRSPINF(struct vnt_private *pDevice, u8 bb_type) VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_72, MAKEWORD(byTxRate, byRsvTime)); /* Set to Page0 */ MACvSelectPage0(pDevice->PortOffset); + + spin_unlock_irqrestore(&pDevice->lock, flags); } void CARDvUpdateBasicTopRate(struct vnt_private *pDevice) diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 70f870541f9..3c17725d591 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -174,12 +174,12 @@ void vnt_init_bands(struct vnt_private *priv) * Return Value: true if succeeded; false if failed. * */ -bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel) +bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch) { struct vnt_private *pDevice = pDeviceHandler; bool bResult = true; - if (pDevice->byCurrentCh == uConnectionChannel) + if (pDevice->byCurrentCh == ch->hw_value) return bResult; /* Set VGA to max sensitivity */ @@ -197,19 +197,23 @@ bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel) if (pDevice->byRFType == RF_AIROHA7230) RFbAL7230SelectChannelPostProcess(pDevice, pDevice->byCurrentCh, - (unsigned char)uConnectionChannel); + ch->hw_value); - pDevice->byCurrentCh = (unsigned char)uConnectionChannel; + pDevice->byCurrentCh = ch->hw_value; bResult &= RFbSelectChannel(pDevice, pDevice->byRFType, - (unsigned char)uConnectionChannel); + ch->hw_value); /* Init Synthesizer Table */ if (pDevice->bEnablePSMode) - RFvWriteWakeProgSyn(pDevice, pDevice->byRFType, uConnectionChannel); + RFvWriteWakeProgSyn(pDevice, pDevice->byRFType, ch->hw_value); BBvSoftwareReset(pDevice); if (pDevice->byLocalID > REV_ID_VT3253_B1) { + unsigned long flags; + + spin_lock_irqsave(&pDevice->lock, flags); + /* set HW default power register */ MACvSelectPage1(pDevice->PortOffset); RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh); @@ -217,6 +221,8 @@ bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel) RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh); VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWROFDM, pDevice->byCurPwr); MACvSelectPage0(pDevice->PortOffset); + + spin_unlock_irqrestore(&pDevice->lock, flags); } if (pDevice->byBBType == BB_TYPE_11B) diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h index 4f4264e2346..e2be6fca5f2 100644 --- a/drivers/staging/vt6655/channel.h +++ b/drivers/staging/vt6655/channel.h @@ -27,6 +27,6 @@ void vnt_init_bands(struct vnt_private *); -bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel); +bool set_channel(void *pDeviceHandler, struct ieee80211_channel *); #endif /* _CHANNEL_H_ */ diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 83efbfb57c7..440537e4712 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -367,7 +367,7 @@ struct vnt_private { bool bIsBeaconBufReadySet; unsigned int cbBeaconBufReadySetCnt; bool bFixRate; - unsigned char byCurrentCh; + u16 byCurrentCh; bool bAES; @@ -407,29 +407,6 @@ struct vnt_private { unsigned char byBBCR88; unsigned char byBBCR09; - bool bDiversityRegCtlON; - bool bDiversityEnable; - unsigned long ulDiversityNValue; - unsigned long ulDiversityMValue; - unsigned char byTMax; - unsigned char byTMax2; - unsigned char byTMax3; - unsigned long ulSQ3TH; - - /* ANT diversity */ - unsigned long uDiversityCnt; - unsigned char byAntennaState; - unsigned long ulRatio_State0; - unsigned long ulRatio_State1; - - /* SQ3 functions for antenna diversity */ - struct timer_list TimerSQ3Tmax1; - struct timer_list TimerSQ3Tmax2; - struct timer_list TimerSQ3Tmax3; - - unsigned long uNumSQ3[MAX_RATE]; - unsigned short wAntDiversityMaxRate; - unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE]; /* unsigned long alignment */ unsigned short wBeaconInterval; diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index cd1a277d853..4324282afe4 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -126,10 +126,6 @@ DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); DEVICE_PARAM(BasebandType, "baseband type"); -#define DIVERSITY_ANT_DEF 0 - -DEVICE_PARAM(bDiversityANTEnable, "ANT diversity mode"); - // // Static vars definitions // @@ -152,7 +148,6 @@ static void vt6655_init_info(struct pci_dev *pcid, static void device_free_info(struct vnt_private *pDevice); static bool device_get_pci_info(struct vnt_private *, struct pci_dev *pcid); static void device_print_info(struct vnt_private *pDevice); -static void device_init_diversity_timer(struct vnt_private *pDevice); static irqreturn_t device_intr(int irq, void *dev_instance); #ifdef CONFIG_PM @@ -216,7 +211,6 @@ static void device_get_options(struct vnt_private *pDevice) pOpts->short_retry = SHORT_RETRY_DEF; pOpts->long_retry = LONG_RETRY_DEF; pOpts->bbp_type = BBP_TYPE_DEF; - pOpts->flags |= DEVICE_FLAGS_DiversityANT; } static void @@ -224,7 +218,6 @@ device_set_options(struct vnt_private *pDevice) { pDevice->byShortRetryLimit = pDevice->sOpts.short_retry; pDevice->byLongRetryLimit = pDevice->sOpts.long_retry; - pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0; pDevice->byBBType = pDevice->sOpts.bbp_type; pDevice->byPacketType = pDevice->byBBType; pDevice->byAutoFBCtrl = AUTO_FB_0; @@ -236,8 +229,6 @@ device_set_options(struct vnt_private *pDevice) pr_debug(" byPreambleType= %d\n", (int)pDevice->byPreambleType); pr_debug(" byShortPreamble= %d\n", (int)pDevice->byShortPreamble); pr_debug(" byBBType= %d\n", (int)pDevice->byBBType); - pr_debug(" pDevice->bDiversityRegCtlON= %d\n", - (int)pDevice->bDiversityRegCtlON); } // @@ -249,7 +240,6 @@ static void device_init_registers(struct vnt_private *pDevice) unsigned long flags; unsigned int ii; unsigned char byValue; - unsigned char byValue1; unsigned char byCCKPwrdBm = 0; unsigned char byOFDMPwrdBm = 0; @@ -301,13 +291,6 @@ static void device_init_registers(struct vnt_private *pDevice) if (byValue == 0) byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); - pDevice->ulDiversityNValue = 100*260; - pDevice->ulDiversityMValue = 100*16; - pDevice->byTMax = 1; - pDevice->byTMax2 = 4; - pDevice->ulSQ3TH = 0; - pDevice->byTMax3 = 64; - if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { pDevice->byAntennaCount = 2; pDevice->byTxAntennaMode = ANT_B; @@ -318,16 +301,7 @@ static void device_init_registers(struct vnt_private *pDevice) pDevice->byRxAntennaMode = ANT_A; else pDevice->byRxAntennaMode = ANT_B; - - byValue1 = SROMbyReadEmbedded(pDevice->PortOffset, - EEP_OFS_ANTENNA); - - if ((byValue1 & 0x08) == 0) - pDevice->bDiversityEnable = false; - else - pDevice->bDiversityEnable = true; } else { - pDevice->bDiversityEnable = false; pDevice->byAntennaCount = 1; pDevice->dwTxAntennaSel = 0; pDevice->dwRxAntennaSel = 0; @@ -349,10 +323,9 @@ static void device_init_registers(struct vnt_private *pDevice) } } - pr_debug("bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n", - pDevice->bDiversityEnable, (int)pDevice->ulDiversityNValue, - (int)pDevice->ulDiversityMValue, pDevice->byTMax, - pDevice->byTMax2); + /* Set initial antenna mode */ + BBvSetTxAntennaMode(pDevice, pDevice->byTxAntennaMode); + BBvSetRxAntennaMode(pDevice, pDevice->byRxAntennaMode); /* zonetype initial */ pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; @@ -493,24 +466,6 @@ static void device_init_registers(struct vnt_private *pDevice) MACvStart(pDevice->PortOffset); } -static void device_init_diversity_timer(struct vnt_private *pDevice) -{ - init_timer(&pDevice->TimerSQ3Tmax1); - pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice; - pDevice->TimerSQ3Tmax1.function = TimerSQ3CallBack; - pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ); - - init_timer(&pDevice->TimerSQ3Tmax2); - pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice; - pDevice->TimerSQ3Tmax2.function = TimerSQ3CallBack; - pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ); - - init_timer(&pDevice->TimerSQ3Tmax3); - pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice; - pDevice->TimerSQ3Tmax3.function = TimerState1CallBack; - pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ); -} - static void device_print_info(struct vnt_private *pDevice) { dev_info(&pDevice->pcid->dev, "%s\n", get_chip_name(pDevice->chip_id)); @@ -1053,6 +1008,58 @@ static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc) pTDInfo->byFlags = 0; } +static void vnt_check_bb_vga(struct vnt_private *priv) +{ + long dbm; + int i; + + if (!priv->bUpdateBBVGA) + return; + + if (priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; + + if (!(priv->vif->bss_conf.assoc && priv->uCurrRSSI)) + return; + + RFvRSSITodBm(priv, (u8)priv->uCurrRSSI, &dbm); + + for (i = 0; i < BB_VGA_LEVEL; i++) { + if (dbm < priv->ldBmThreshold[i]) { + priv->byBBVGANew = priv->abyBBVGA[i]; + break; + } + } + + if (priv->byBBVGANew == priv->byBBVGACurrent) { + priv->uBBVGADiffCount = 1; + return; + } + + priv->uBBVGADiffCount++; + + if (priv->uBBVGADiffCount == 1) { + /* first VGA diff gain */ + BBvSetVGAGainOffset(priv, priv->byBBVGANew); + + dev_dbg(&priv->pcid->dev, + "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)dbm, priv->byBBVGANew, + priv->byBBVGACurrent, + (int)priv->uBBVGADiffCount); + } + + if (priv->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { + dev_dbg(&priv->pcid->dev, + "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)dbm, priv->byBBVGANew, + priv->byBBVGACurrent, + (int)priv->uBBVGADiffCount); + + BBvSetVGAGainOffset(priv, priv->byBBVGANew); + } +} + static irqreturn_t device_intr(int irq, void *dev_instance) { struct vnt_private *pDevice = dev_instance; @@ -1060,7 +1067,6 @@ static irqreturn_t device_intr(int irq, void *dev_instance) unsigned long dwMIBCounter = 0; unsigned char byOrgPageSel = 0; int handled = 0; - int ii = 0; unsigned long flags; MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); @@ -1090,7 +1096,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) // Must do this after doing rx/tx, cause ISR bit is slow // than RD/TD write back // update ISR counter - STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter); + STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic, dwMIBCounter); while (pDevice->dwIsr != 0) { STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr); MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr); @@ -1104,44 +1110,8 @@ static irqreturn_t device_intr(int irq, void *dev_instance) if (pDevice->dwIsr & ISR_TBTT) { if (pDevice->vif && - pDevice->op_mode != NL80211_IFTYPE_ADHOC) { - if (pDevice->bUpdateBBVGA && - !(pDevice->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && - pDevice->vif->bss_conf.assoc && - pDevice->uCurrRSSI) { - long ldBm; - - RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm); - for (ii = 0; ii < BB_VGA_LEVEL; ii++) { - if (ldBm < pDevice->ldBmThreshold[ii]) { - pDevice->byBBVGANew = pDevice->abyBBVGA[ii]; - break; - } - } - if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) { - pDevice->uBBVGADiffCount++; - if (pDevice->uBBVGADiffCount == 1) { - // first VGA diff gain - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); - pr_debug("First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", - (int)ldBm, - pDevice->byBBVGANew, - pDevice->byBBVGACurrent, - (int)pDevice->uBBVGADiffCount); - } - if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { - pr_debug("RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", - (int)ldBm, - pDevice->byBBVGANew, - pDevice->byBBVGACurrent, - (int)pDevice->uBBVGADiffCount); - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); - } - } else { - pDevice->uBBVGADiffCount = 1; - } - } - } + pDevice->op_mode != NL80211_IFTYPE_ADHOC) + vnt_check_bb_vga(pDevice); pDevice->bBeaconSent = false; if (pDevice->bEnablePSMode) @@ -1262,12 +1232,15 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) head_td->m_td1TD1.wReqCount = cpu_to_le16((u16)head_td->pTDInfo->dwReqCount); - head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB; + head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma); + + if (dma_idx == TYPE_AC0DMA) { + head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB; - if (dma_idx == TYPE_AC0DMA) MACvTransmitAC0(priv->PortOffset); - else + } else { MACvTransmit0(priv->PortOffset); + } spin_unlock_irqrestore(&priv->lock, flags); @@ -1348,8 +1321,6 @@ static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) switch (vif->type) { case NL80211_IFTYPE_STATION: - if (priv->bDiversityRegCtlON) - device_init_diversity_timer(priv); break; case NL80211_IFTYPE_ADHOC: MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST); @@ -1379,11 +1350,6 @@ static void vnt_remove_interface(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_STATION: - if (priv->bDiversityRegCtlON) { - del_timer(&priv->TimerSQ3Tmax1); - del_timer(&priv->TimerSQ3Tmax2); - del_timer(&priv->TimerSQ3Tmax3); - } break; case NL80211_IFTYPE_ADHOC: MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); @@ -1420,7 +1386,7 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed) if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { - set_channel(priv, conf->chandef.chan->hw_value); + set_channel(priv, conf->chandef.chan); if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) bb_type = BB_TYPE_11A; @@ -1572,6 +1538,10 @@ static void vnt_configure(struct ieee80211_hw *hw, if (changed_flags & FIF_ALLMULTI) { if (*total_flags & FIF_ALLMULTI) { + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->mc_list_count > 2) { MACvSelectPage1(priv->PortOffset); @@ -1593,6 +1563,8 @@ static void vnt_configure(struct ieee80211_hw *hw, MACvSelectPage0(priv->PortOffset); } + spin_unlock_irqrestore(&priv->lock, flags); + rx_mode |= RCR_MULTICAST | RCR_BROADCAST; } else { rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST); @@ -1676,7 +1648,7 @@ static const struct ieee80211_ops vnt_mac_ops = { .reset_tsf = vnt_reset_tsf, }; -int vnt_init(struct vnt_private *priv) +static int vnt_init(struct vnt_private *priv) { SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr); diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 977683cb739..3c5b87ffdca 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -91,6 +91,8 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, new_rsr = skb_data + bytes_received - 3; rssi = skb_data + bytes_received - 2; rsr = skb_data + bytes_received - 1; + if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) + return false; RFvRSSITodBm(priv, *rssi, &rx_dbm); @@ -106,6 +108,9 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, rx_status.flag = 0; rx_status.freq = hw->conf.chandef.chan->center_freq; + if (!(*rsr & RSR_CRCOK)) + rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; + hdr = (struct ieee80211_hdr *)(skb->data); fc = hdr->frame_control; @@ -113,13 +118,11 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, if (ieee80211_has_protected(fc)) { if (priv->byLocalID > REV_ID_VT3253_A1) - rx_status.flag = RX_FLAG_DECRYPTED; - } + rx_status.flag |= RX_FLAG_DECRYPTED; - if (priv->vif && priv->bDiversityEnable) { - if (ieee80211_is_data(fc) && - (frame_size > 50) && priv->vif->bss_conf.assoc) - BBvAntennaDiversity(priv, priv->rx_rate, 0); + /* Drop packet */ + if (!(*new_rsr & NEWRSR_DECRYPTOK)) + return false; } memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 8f0d652fea7..3653a2bd1e3 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -30,7 +30,6 @@ * MACbIsRegBitsOff - Test if All test Bits Off * MACbIsIntDisable - Test if MAC interrupt disable * MACvSetShortRetryLimit - Set 802.11 Short Retry limit - * MACvGetShortRetryLimit - Get 802.11 Short Retry limit * MACvSetLongRetryLimit - Set 802.11 Long Retry limit * MACvSetLoopbackMode - Set MAC Loopback Mode * MACvSaveContext - Save Context of MAC Registers @@ -146,24 +145,6 @@ void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) VNSvOutPortB(dwIoBase + MAC_REG_SRT, byRetryLimit); } -/* - * Description: - * Get 802.11 Short Retry Limit - * - * Parameters: - * In: - * dwIoBase - Base Address for MAC - * Out: - * pbyRetryLimit - Retry Limit Get - * - * Return Value: none - * - */ -void MACvGetShortRetryLimit(void __iomem *dwIoBase, unsigned char *pbyRetryLimit) -{ - // get SRT - VNSvInPortB(dwIoBase + MAC_REG_SRT, pbyRetryLimit); -} /* * Description: @@ -356,7 +337,7 @@ bool MACbSafeSoftwareReset(void __iomem *dwIoBase) /* * Description: - * Trun Off MAC Rx + * Turn Off MAC Rx * * Parameters: * In: @@ -417,7 +398,7 @@ bool MACbSafeRxOff(void __iomem *dwIoBase) /* * Description: - * Trun Off MAC Tx + * Turn Off MAC Tx * * Parameters: * In: @@ -808,7 +789,7 @@ bool MACbPSWakeup(void __iomem *dwIoBase) // Check if SyncFlushOK for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - VNSvInPortB(dwIoBase + MAC_REG_PSCTL , &byOrgValue); + VNSvInPortB(dwIoBase + MAC_REG_PSCTL, &byOrgValue); if (byOrgValue & PSCTL_WAKEDONE) break; } diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index e1e7e10435f..8e0200a78b1 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -38,13 +38,11 @@ #include "upc.h" /*--------------------- Export Definitions -------------------------*/ -// -// Registers in the MAC -// +/* Registers in the MAC */ #define MAC_MAX_CONTEXT_SIZE_PAGE0 256 #define MAC_MAX_CONTEXT_SIZE_PAGE1 128 -// Registers not related to 802.11b +/* Registers not related to 802.11b */ #define MAC_REG_BCFG0 0x00 #define MAC_REG_BCFG1 0x01 #define MAC_REG_FCR0 0x02 @@ -69,15 +67,16 @@ #define MAC_REG_TMCTL0 0x18 #define MAC_REG_TMCTL1 0x19 #define MAC_REG_TMDATA0 0x1C -// MAC Parameter related -#define MAC_REG_LRT 0x20 // -#define MAC_REG_SRT 0x21 // -#define MAC_REG_SIFS 0x22 // -#define MAC_REG_DIFS 0x23 // -#define MAC_REG_EIFS 0x24 // -#define MAC_REG_SLOT 0x25 // -#define MAC_REG_BI 0x26 // -#define MAC_REG_CWMAXMIN0 0x28 // + +/* MAC Parameter related */ +#define MAC_REG_LRT 0x20 +#define MAC_REG_SRT 0x21 +#define MAC_REG_SIFS 0x22 +#define MAC_REG_DIFS 0x23 +#define MAC_REG_EIFS 0x24 +#define MAC_REG_SLOT 0x25 +#define MAC_REG_BI 0x26 +#define MAC_REG_CWMAXMIN0 0x28 #define MAC_REG_LINKOFFTOTM 0x2A #define MAC_REG_SWTMOT 0x2B #define MAC_REG_MIBCNTR 0x2C @@ -85,26 +84,29 @@ #define MAC_REG_RTSFAILCNT 0x2D #define MAC_REG_ACKFAILCNT 0x2E #define MAC_REG_FCSERRCNT 0x2F -// TSF Related -#define MAC_REG_TSFCNTR 0x30 // -#define MAC_REG_NEXTTBTT 0x38 // -#define MAC_REG_TSFOFST 0x40 // -#define MAC_REG_TFTCTL 0x48 // -// WMAC Control/Status Related -#define MAC_REG_ENCFG 0x4C // -#define MAC_REG_PAGE1SEL 0x4F // -#define MAC_REG_CFG 0x50 // -#define MAC_REG_TEST 0x52 // -#define MAC_REG_HOSTCR 0x54 // -#define MAC_REG_MACCR 0x55 // -#define MAC_REG_RCR 0x56 // -#define MAC_REG_TCR 0x57 // -#define MAC_REG_IMR 0x58 // + +/* TSF Related */ +#define MAC_REG_TSFCNTR 0x30 +#define MAC_REG_NEXTTBTT 0x38 +#define MAC_REG_TSFOFST 0x40 +#define MAC_REG_TFTCTL 0x48 + +/* WMAC Control/Status Related */ +#define MAC_REG_ENCFG 0x4C +#define MAC_REG_PAGE1SEL 0x4F +#define MAC_REG_CFG 0x50 +#define MAC_REG_TEST 0x52 +#define MAC_REG_HOSTCR 0x54 +#define MAC_REG_MACCR 0x55 +#define MAC_REG_RCR 0x56 +#define MAC_REG_TCR 0x57 +#define MAC_REG_IMR 0x58 #define MAC_REG_ISR 0x5C -// Power Saving Related -#define MAC_REG_PSCFG 0x60 // -#define MAC_REG_PSCTL 0x61 // -#define MAC_REG_PSPWRSIG 0x62 // + +/* Power Saving Related */ +#define MAC_REG_PSCFG 0x60 +#define MAC_REG_PSCTL 0x61 +#define MAC_REG_PSPWRSIG 0x62 #define MAC_REG_BBCR13 0x63 #define MAC_REG_AIDATIM 0x64 #define MAC_REG_PWBT 0x66 @@ -112,41 +114,45 @@ #define MAC_REG_CALTMR 0x69 #define MAC_REG_SYNSPACCNT 0x6A #define MAC_REG_WAKSYNOPT 0x6B -// Baseband/IF Control Group -#define MAC_REG_BBREGCTL 0x6C // + +/* Baseband/IF Control Group */ +#define MAC_REG_BBREGCTL 0x6C #define MAC_REG_CHANNEL 0x6D #define MAC_REG_BBREGADR 0x6E #define MAC_REG_BBREGDATA 0x6F -#define MAC_REG_IFREGCTL 0x70 // -#define MAC_REG_IFDATA 0x71 // -#define MAC_REG_ITRTMSET 0x74 // +#define MAC_REG_IFREGCTL 0x70 +#define MAC_REG_IFDATA 0x71 +#define MAC_REG_ITRTMSET 0x74 #define MAC_REG_PAPEDELAY 0x77 -#define MAC_REG_SOFTPWRCTL 0x78 // -#define MAC_REG_GPIOCTL0 0x7A // -#define MAC_REG_GPIOCTL1 0x7B // - -// MAC DMA Related Group -#define MAC_REG_TXDMACTL0 0x7C // -#define MAC_REG_TXDMAPTR0 0x80 // -#define MAC_REG_AC0DMACTL 0x84 // -#define MAC_REG_AC0DMAPTR 0x88 // -#define MAC_REG_BCNDMACTL 0x8C // -#define MAC_REG_BCNDMAPTR 0x90 // -#define MAC_REG_RXDMACTL0 0x94 // -#define MAC_REG_RXDMAPTR0 0x98 // -#define MAC_REG_RXDMACTL1 0x9C // -#define MAC_REG_RXDMAPTR1 0xA0 // -#define MAC_REG_SYNCDMACTL 0xA4 // +#define MAC_REG_SOFTPWRCTL 0x78 +#define MAC_REG_GPIOCTL0 0x7A +#define MAC_REG_GPIOCTL1 0x7B + +/* MAC DMA Related Group */ +#define MAC_REG_TXDMACTL0 0x7C +#define MAC_REG_TXDMAPTR0 0x80 +#define MAC_REG_AC0DMACTL 0x84 +#define MAC_REG_AC0DMAPTR 0x88 +#define MAC_REG_BCNDMACTL 0x8C +#define MAC_REG_BCNDMAPTR 0x90 +#define MAC_REG_RXDMACTL0 0x94 +#define MAC_REG_RXDMAPTR0 0x98 +#define MAC_REG_RXDMACTL1 0x9C +#define MAC_REG_RXDMAPTR1 0xA0 +#define MAC_REG_SYNCDMACTL 0xA4 #define MAC_REG_SYNCDMAPTR 0xA8 #define MAC_REG_ATIMDMACTL 0xAC #define MAC_REG_ATIMDMAPTR 0xB0 -// MiscFF PIO related + +/* MiscFF PIO related */ #define MAC_REG_MISCFFNDEX 0xB4 #define MAC_REG_MISCFFCTL 0xB6 #define MAC_REG_MISCFFDATA 0xB8 -// Extend SW Timer + +/* Extend SW Timer */ #define MAC_REG_TMDATA1 0xBC -// WOW Related Group + +/* WOW Related Group */ #define MAC_REG_WAKEUPEN0 0xC0 #define MAC_REG_WAKEUPEN1 0xC1 #define MAC_REG_WAKEUPSR0 0xC2 @@ -156,19 +162,21 @@ #define MAC_REG_WAKE128_2 0xE4 #define MAC_REG_WAKE128_3 0xF4 -/////////////// Page 1 /////////////////// +/************** Page 1 ******************/ #define MAC_REG_CRC_128_0 0x04 #define MAC_REG_CRC_128_1 0x06 #define MAC_REG_CRC_128_2 0x08 #define MAC_REG_CRC_128_3 0x0A -// MAC Configuration Group + +/* MAC Configuration Group */ #define MAC_REG_PAR0 0x0C #define MAC_REG_PAR4 0x10 #define MAC_REG_BSSID0 0x14 #define MAC_REG_BSSID4 0x18 #define MAC_REG_MAR0 0x1C #define MAC_REG_MAR4 0x20 -// MAC RSPPKT INFO Group + +/* MAC RSPPKT INFO Group */ #define MAC_REG_RSPINF_B_1 0x24 #define MAC_REG_RSPINF_B_2 0x28 #define MAC_REG_RSPINF_B_5 0x2C @@ -183,7 +191,7 @@ #define MAC_REG_RSPINF_A_54 0x42 #define MAC_REG_RSPINF_A_72 0x44 -// 802.11h relative +/* 802.11h relative */ #define MAC_REG_QUIETINIT 0x60 #define MAC_REG_QUIETGAP 0x62 #define MAC_REG_QUIETDUR 0x64 @@ -195,9 +203,7 @@ #define MAC_REG_PWRCCK 0x73 #define MAC_REG_PWROFDM 0x7C -// -// Bits in the BCFG0 register -// +/* Bits in the BCFG0 register */ #define BCFG0_PERROFF 0x40 #define BCFG0_MRDMDIS 0x20 #define BCFG0_MRDLDIS 0x10 @@ -205,9 +211,7 @@ #define BCFG0_VSERREN 0x02 #define BCFG0_LATMEN 0x01 -// -// Bits in the BCFG1 register -// +/* Bits in the BCFG1 register */ #define BCFG1_CFUNOPT 0x80 #define BCFG1_CREQOPT 0x40 #define BCFG1_DMA8 0x10 @@ -216,25 +220,23 @@ #define BCFG1_MIOEN 0x02 #define BCFG1_CISDLYEN 0x01 -// Bits in RAMBIST registers -#define BISTCMD_TSTPAT5 0x00 // -#define BISTCMD_TSTPATA 0x80 // -#define BISTCMD_TSTERR 0x20 // -#define BISTCMD_TSTPATF 0x18 // -#define BISTCMD_TSTPAT0 0x10 // -#define BISTCMD_TSTMODE 0x04 // -#define BISTCMD_TSTITTX 0x03 // -#define BISTCMD_TSTATRX 0x02 // -#define BISTCMD_TSTATTX 0x01 // -#define BISTCMD_TSTRX 0x00 // -#define BISTSR0_BISTGO 0x01 // -#define BISTSR1_TSTSR 0x01 // -#define BISTSR2_CMDPRTEN 0x02 // -#define BISTSR2_RAMTSTEN 0x01 // - -// -// Bits in the I2MCFG EEPROM register -// +/* Bits in RAMBIST registers */ +#define BISTCMD_TSTPAT5 0x00 +#define BISTCMD_TSTPATA 0x80 +#define BISTCMD_TSTERR 0x20 +#define BISTCMD_TSTPATF 0x18 +#define BISTCMD_TSTPAT0 0x10 +#define BISTCMD_TSTMODE 0x04 +#define BISTCMD_TSTITTX 0x03 +#define BISTCMD_TSTATRX 0x02 +#define BISTCMD_TSTATTX 0x01 +#define BISTCMD_TSTRX 0x00 +#define BISTSR0_BISTGO 0x01 +#define BISTSR1_TSTSR 0x01 +#define BISTSR2_CMDPRTEN 0x02 +#define BISTSR2_RAMTSTEN 0x01 + +/* Bits in the I2MCFG EEPROM register */ #define I2MCFG_BOUNDCTL 0x80 #define I2MCFG_WAITCTL 0x20 #define I2MCFG_SCLOECTL 0x10 @@ -243,50 +245,38 @@ #define I2MCFG_I2MLDSEQ 0x02 #define I2MCFG_I2CMFAST 0x01 -// -// Bits in the I2MCSR EEPROM register -// +/* Bits in the I2MCSR EEPROM register */ #define I2MCSR_EEMW 0x80 #define I2MCSR_EEMR 0x40 #define I2MCSR_AUTOLD 0x08 #define I2MCSR_NACK 0x02 #define I2MCSR_DONE 0x01 -// -// Bits in the PMC1 register -// +/* Bits in the PMC1 register */ #define SPS_RST 0x80 #define PCISTIKY 0x40 #define PME_OVR 0x02 -// -// Bits in the STICKYHW register -// +/* Bits in the STICKYHW register */ #define STICKHW_DS1_SHADOW 0x02 #define STICKHW_DS0_SHADOW 0x01 -// -// Bits in the TMCTL register -// +/* Bits in the TMCTL register */ #define TMCTL_TSUSP 0x04 #define TMCTL_TMD 0x02 #define TMCTL_TE 0x01 -// -// Bits in the TFTCTL register -// -#define TFTCTL_HWUTSF 0x80 // +/* Bits in the TFTCTL register */ +#define TFTCTL_HWUTSF 0x80 #define TFTCTL_TBTTSYNC 0x40 #define TFTCTL_HWUTSFEN 0x20 -#define TFTCTL_TSFCNTRRD 0x10 // -#define TFTCTL_TBTTSYNCEN 0x08 // -#define TFTCTL_TSFSYNCEN 0x04 // -#define TFTCTL_TSFCNTRST 0x02 // -#define TFTCTL_TSFCNTREN 0x01 // - -// -// Bits in the EnhanceCFG register -// +#define TFTCTL_TSFCNTRRD 0x10 +#define TFTCTL_TBTTSYNCEN 0x08 +#define TFTCTL_TSFSYNCEN 0x04 +#define TFTCTL_TSFCNTRST 0x02 +#define TFTCTL_TSFCNTREN 0x01 + +/* Bits in the EnhanceCFG register */ #define EnCFG_BarkerPream 0x00020000 #define EnCFG_NXTBTTCFPSTR 0x00010000 #define EnCFG_BcnSusClr 0x00000200 @@ -300,14 +290,10 @@ #define EnCFG_BBType_b 0x00000001 #define EnCFG_BBType_a 0x00000000 -// -// Bits in the Page1Sel register -// +/* Bits in the Page1Sel register */ #define PAGE1_SEL 0x01 -// -// Bits in the CFG register -// +/* Bits in the CFG register */ #define CFG_TKIPOPT 0x80 #define CFG_RXDMAOPT 0x40 #define CFG_TMOT_SW 0x20 @@ -318,242 +304,196 @@ #define CFG_NOTXTIMEOUT 0x02 #define CFG_NOBUFOPT 0x01 -// -// Bits in the TEST register -// -#define TEST_LBEXT 0x80 // -#define TEST_LBINT 0x40 // -#define TEST_LBNONE 0x00 // -#define TEST_SOFTINT 0x20 // -#define TEST_CONTTX 0x10 // -#define TEST_TXPE 0x08 // -#define TEST_NAVDIS 0x04 // -#define TEST_NOCTS 0x02 // -#define TEST_NOACK 0x01 // - -// -// Bits in the HOSTCR register -// -#define HOSTCR_TXONST 0x80 // -#define HOSTCR_RXONST 0x40 // -#define HOSTCR_ADHOC 0x20 // Network Type 1 = Ad-hoc -#define HOSTCR_AP 0x10 // Port Type 1 = AP -#define HOSTCR_TXON 0x08 //0000 1000 -#define HOSTCR_RXON 0x04 //0000 0100 -#define HOSTCR_MACEN 0x02 //0000 0010 -#define HOSTCR_SOFTRST 0x01 //0000 0001 - -// -// Bits in the MACCR register -// -#define MACCR_SYNCFLUSHOK 0x04 // -#define MACCR_SYNCFLUSH 0x02 // -#define MACCR_CLRNAV 0x01 // - -// Bits in the MAC_REG_GPIOCTL0 register -// -#define LED_ACTSET 0x01 // -#define LED_RFOFF 0x02 // -#define LED_NOCONNECT 0x04 // -// -// Bits in the RCR register -// +/* Bits in the TEST register */ +#define TEST_LBEXT 0x80 +#define TEST_LBINT 0x40 +#define TEST_LBNONE 0x00 +#define TEST_SOFTINT 0x20 +#define TEST_CONTTX 0x10 +#define TEST_TXPE 0x08 +#define TEST_NAVDIS 0x04 +#define TEST_NOCTS 0x02 +#define TEST_NOACK 0x01 + +/* Bits in the HOSTCR register */ +#define HOSTCR_TXONST 0x80 +#define HOSTCR_RXONST 0x40 +#define HOSTCR_ADHOC 0x20 /* Network Type 1 = Ad-hoc */ +#define HOSTCR_AP 0x10 /* Port Type 1 = AP */ +#define HOSTCR_TXON 0x08 /* 0000 1000 */ +#define HOSTCR_RXON 0x04 /* 0000 0100 */ +#define HOSTCR_MACEN 0x02 /* 0000 0010 */ +#define HOSTCR_SOFTRST 0x01 /* 0000 0001 */ + +/* Bits in the MACCR register */ +#define MACCR_SYNCFLUSHOK 0x04 +#define MACCR_SYNCFLUSH 0x02 +#define MACCR_CLRNAV 0x01 + +/* Bits in the MAC_REG_GPIOCTL0 register */ +#define LED_ACTSET 0x01 +#define LED_RFOFF 0x02 +#define LED_NOCONNECT 0x04 + +/* Bits in the RCR register */ #define RCR_SSID 0x80 -#define RCR_RXALLTYPE 0x40 // -#define RCR_UNICAST 0x20 // -#define RCR_BROADCAST 0x10 // -#define RCR_MULTICAST 0x08 // -#define RCR_WPAERR 0x04 // -#define RCR_ERRCRC 0x02 // -#define RCR_BSSID 0x01 // - -// -// Bits in the TCR register -// -#define TCR_SYNCDCFOPT 0x02 // -#define TCR_AUTOBCNTX 0x01 // Beacon automatically transmit enable - -// -// Bits in the IMR register -// -#define IMR_MEASURESTART 0x80000000 // -#define IMR_QUIETSTART 0x20000000 // -#define IMR_RADARDETECT 0x10000000 // -#define IMR_MEASUREEND 0x08000000 // -#define IMR_SOFTTIMER1 0x00200000 // -#define IMR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 -#define IMR_RXNOBUF 0x00000800 // -#define IMR_MIBNEARFULL 0x00000400 // -#define IMR_SOFTINT 0x00000200 // -#define IMR_FETALERR 0x00000100 // -#define IMR_WATCHDOG 0x00000080 // -#define IMR_SOFTTIMER 0x00000040 // -#define IMR_GPIO 0x00000020 // -#define IMR_TBTT 0x00000010 // -#define IMR_RXDMA0 0x00000008 // -#define IMR_BNTX 0x00000004 // -#define IMR_AC0DMA 0x00000002 // -#define IMR_TXDMA0 0x00000001 // - -// -// Bits in the ISR register -// - -#define ISR_MEASURESTART 0x80000000 // -#define ISR_QUIETSTART 0x20000000 // -#define ISR_RADARDETECT 0x10000000 // -#define ISR_MEASUREEND 0x08000000 // -#define ISR_SOFTTIMER1 0x00200000 // -#define ISR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 -#define ISR_RXNOBUF 0x00000800 //0000 0000 0000 1000 0000 0000 -#define ISR_MIBNEARFULL 0x00000400 //0000 0000 0000 0100 0000 0000 -#define ISR_SOFTINT 0x00000200 // -#define ISR_FETALERR 0x00000100 // -#define ISR_WATCHDOG 0x00000080 // -#define ISR_SOFTTIMER 0x00000040 // -#define ISR_GPIO 0x00000020 // -#define ISR_TBTT 0x00000010 // -#define ISR_RXDMA0 0x00000008 // -#define ISR_BNTX 0x00000004 // -#define ISR_AC0DMA 0x00000002 // -#define ISR_TXDMA0 0x00000001 // - -// -// Bits in the PSCFG register -// -#define PSCFG_PHILIPMD 0x40 // -#define PSCFG_WAKECALEN 0x20 // -#define PSCFG_WAKETMREN 0x10 // -#define PSCFG_BBPSPROG 0x08 // -#define PSCFG_WAKESYN 0x04 // -#define PSCFG_SLEEPSYN 0x02 // -#define PSCFG_AUTOSLEEP 0x01 // - -// -// Bits in the PSCTL register -// -#define PSCTL_WAKEDONE 0x20 // -#define PSCTL_PS 0x10 // -#define PSCTL_GO2DOZE 0x08 // -#define PSCTL_LNBCN 0x04 // -#define PSCTL_ALBCN 0x02 // -#define PSCTL_PSEN 0x01 // - -// -// Bits in the PSPWSIG register -// -#define PSSIG_WPE3 0x80 // -#define PSSIG_WPE2 0x40 // -#define PSSIG_WPE1 0x20 // -#define PSSIG_WRADIOPE 0x10 // -#define PSSIG_SPE3 0x08 // -#define PSSIG_SPE2 0x04 // -#define PSSIG_SPE1 0x02 // -#define PSSIG_SRADIOPE 0x01 // - -// -// Bits in the BBREGCTL register -// -#define BBREGCTL_DONE 0x04 // -#define BBREGCTL_REGR 0x02 // -#define BBREGCTL_REGW 0x01 // - -// -// Bits in the IFREGCTL register -// -#define IFREGCTL_DONE 0x04 // -#define IFREGCTL_IFRF 0x02 // -#define IFREGCTL_REGW 0x01 // - -// -// Bits in the SOFTPWRCTL register -// -#define SOFTPWRCTL_RFLEOPT 0x0800 // -#define SOFTPWRCTL_TXPEINV 0x0200 // -#define SOFTPWRCTL_SWPECTI 0x0100 // -#define SOFTPWRCTL_SWPAPE 0x0020 // -#define SOFTPWRCTL_SWCALEN 0x0010 // -#define SOFTPWRCTL_SWRADIO_PE 0x0008 // -#define SOFTPWRCTL_SWPE2 0x0004 // -#define SOFTPWRCTL_SWPE1 0x0002 // -#define SOFTPWRCTL_SWPE3 0x0001 // - -// -// Bits in the GPIOCTL1 register -// -#define GPIO1_DATA1 0x20 // -#define GPIO1_MD1 0x10 // -#define GPIO1_DATA0 0x02 // -#define GPIO1_MD0 0x01 // - -// -// Bits in the DMACTL register -// -#define DMACTL_CLRRUN 0x00080000 // -#define DMACTL_RUN 0x00000008 // -#define DMACTL_WAKE 0x00000004 // -#define DMACTL_DEAD 0x00000002 // -#define DMACTL_ACTIVE 0x00000001 // -// -// Bits in the RXDMACTL0 register -// -#define RX_PERPKT 0x00000100 // -#define RX_PERPKTCLR 0x01000000 // -// -// Bits in the BCNDMACTL register -// -#define BEACON_READY 0x01 // -// -// Bits in the MISCFFCTL register -// -#define MISCFFCTL_WRITE 0x0001 // - -// -// Bits in WAKEUPEN0 -// +#define RCR_RXALLTYPE 0x40 +#define RCR_UNICAST 0x20 +#define RCR_BROADCAST 0x10 +#define RCR_MULTICAST 0x08 +#define RCR_WPAERR 0x04 +#define RCR_ERRCRC 0x02 +#define RCR_BSSID 0x01 + +/* Bits in the TCR register */ +#define TCR_SYNCDCFOPT 0x02 +#define TCR_AUTOBCNTX 0x01 /* Beacon automatically transmit enable */ + +/* Bits in the IMR register */ +#define IMR_MEASURESTART 0x80000000 +#define IMR_QUIETSTART 0x20000000 +#define IMR_RADARDETECT 0x10000000 +#define IMR_MEASUREEND 0x08000000 +#define IMR_SOFTTIMER1 0x00200000 +#define IMR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */ +#define IMR_RXNOBUF 0x00000800 +#define IMR_MIBNEARFULL 0x00000400 +#define IMR_SOFTINT 0x00000200 +#define IMR_FETALERR 0x00000100 +#define IMR_WATCHDOG 0x00000080 +#define IMR_SOFTTIMER 0x00000040 +#define IMR_GPIO 0x00000020 +#define IMR_TBTT 0x00000010 +#define IMR_RXDMA0 0x00000008 +#define IMR_BNTX 0x00000004 +#define IMR_AC0DMA 0x00000002 +#define IMR_TXDMA0 0x00000001 + +/* Bits in the ISR register */ +#define ISR_MEASURESTART 0x80000000 +#define ISR_QUIETSTART 0x20000000 +#define ISR_RADARDETECT 0x10000000 +#define ISR_MEASUREEND 0x08000000 +#define ISR_SOFTTIMER1 0x00200000 +#define ISR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */ +#define ISR_RXNOBUF 0x00000800 /* 0000 0000 0000 1000 0000 0000 */ +#define ISR_MIBNEARFULL 0x00000400 /* 0000 0000 0000 0100 0000 0000 */ +#define ISR_SOFTINT 0x00000200 +#define ISR_FETALERR 0x00000100 +#define ISR_WATCHDOG 0x00000080 +#define ISR_SOFTTIMER 0x00000040 +#define ISR_GPIO 0x00000020 +#define ISR_TBTT 0x00000010 +#define ISR_RXDMA0 0x00000008 +#define ISR_BNTX 0x00000004 +#define ISR_AC0DMA 0x00000002 +#define ISR_TXDMA0 0x00000001 + +/* Bits in the PSCFG register */ +#define PSCFG_PHILIPMD 0x40 +#define PSCFG_WAKECALEN 0x20 +#define PSCFG_WAKETMREN 0x10 +#define PSCFG_BBPSPROG 0x08 +#define PSCFG_WAKESYN 0x04 +#define PSCFG_SLEEPSYN 0x02 +#define PSCFG_AUTOSLEEP 0x01 + +/* Bits in the PSCTL register */ +#define PSCTL_WAKEDONE 0x20 +#define PSCTL_PS 0x10 +#define PSCTL_GO2DOZE 0x08 +#define PSCTL_LNBCN 0x04 +#define PSCTL_ALBCN 0x02 +#define PSCTL_PSEN 0x01 + +/* Bits in the PSPWSIG register */ +#define PSSIG_WPE3 0x80 +#define PSSIG_WPE2 0x40 +#define PSSIG_WPE1 0x20 +#define PSSIG_WRADIOPE 0x10 +#define PSSIG_SPE3 0x08 +#define PSSIG_SPE2 0x04 +#define PSSIG_SPE1 0x02 +#define PSSIG_SRADIOPE 0x01 + +/* Bits in the BBREGCTL register */ +#define BBREGCTL_DONE 0x04 +#define BBREGCTL_REGR 0x02 +#define BBREGCTL_REGW 0x01 + +/* Bits in the IFREGCTL register */ +#define IFREGCTL_DONE 0x04 +#define IFREGCTL_IFRF 0x02 +#define IFREGCTL_REGW 0x01 + +/* Bits in the SOFTPWRCTL register */ +#define SOFTPWRCTL_RFLEOPT 0x0800 +#define SOFTPWRCTL_TXPEINV 0x0200 +#define SOFTPWRCTL_SWPECTI 0x0100 +#define SOFTPWRCTL_SWPAPE 0x0020 +#define SOFTPWRCTL_SWCALEN 0x0010 +#define SOFTPWRCTL_SWRADIO_PE 0x0008 +#define SOFTPWRCTL_SWPE2 0x0004 +#define SOFTPWRCTL_SWPE1 0x0002 +#define SOFTPWRCTL_SWPE3 0x0001 + +/* Bits in the GPIOCTL1 register */ +#define GPIO1_DATA1 0x20 +#define GPIO1_MD1 0x10 +#define GPIO1_DATA0 0x02 +#define GPIO1_MD0 0x01 + +/* Bits in the DMACTL register */ +#define DMACTL_CLRRUN 0x00080000 +#define DMACTL_RUN 0x00000008 +#define DMACTL_WAKE 0x00000004 +#define DMACTL_DEAD 0x00000002 +#define DMACTL_ACTIVE 0x00000001 + +/* Bits in the RXDMACTL0 register */ +#define RX_PERPKT 0x00000100 +#define RX_PERPKTCLR 0x01000000 + +/* Bits in the BCNDMACTL register */ +#define BEACON_READY 0x01 + +/* Bits in the MISCFFCTL register */ +#define MISCFFCTL_WRITE 0x0001 + +/* Bits in WAKEUPEN0 */ #define WAKEUPEN0_DIRPKT 0x10 #define WAKEUPEN0_LINKOFF 0x08 #define WAKEUPEN0_ATIMEN 0x04 #define WAKEUPEN0_TIMEN 0x02 #define WAKEUPEN0_MAGICEN 0x01 -// -// Bits in WAKEUPEN1 -// +/* Bits in WAKEUPEN1 */ #define WAKEUPEN1_128_3 0x08 #define WAKEUPEN1_128_2 0x04 #define WAKEUPEN1_128_1 0x02 #define WAKEUPEN1_128_0 0x01 -// -// Bits in WAKEUPSR0 -// +/* Bits in WAKEUPSR0 */ #define WAKEUPSR0_DIRPKT 0x10 #define WAKEUPSR0_LINKOFF 0x08 #define WAKEUPSR0_ATIMEN 0x04 #define WAKEUPSR0_TIMEN 0x02 #define WAKEUPSR0_MAGICEN 0x01 -// -// Bits in WAKEUPSR1 -// +/* Bits in WAKEUPSR1 */ #define WAKEUPSR1_128_3 0x08 #define WAKEUPSR1_128_2 0x04 #define WAKEUPSR1_128_1 0x02 #define WAKEUPSR1_128_0 0x01 -// -// Bits in the MAC_REG_GPIOCTL register -// -#define GPIO0_MD 0x01 // -#define GPIO0_DATA 0x02 // -#define GPIO0_INTMD 0x04 // -#define GPIO1_MD 0x10 // -#define GPIO1_DATA 0x20 // - -// -// Bits in the MSRCTL register -// +/* Bits in the MAC_REG_GPIOCTL register */ +#define GPIO0_MD 0x01 +#define GPIO0_DATA 0x02 +#define GPIO0_INTMD 0x04 +#define GPIO1_MD 0x10 +#define GPIO1_DATA 0x20 + +/* Bits in the MSRCTL register */ #define MSRCTL_FINISH 0x80 #define MSRCTL_READY 0x40 #define MSRCTL_RADARDETECT 0x20 @@ -562,28 +502,27 @@ #define MSRCTL_QUIETRPT 0x04 #define MSRCTL_QUIETINT 0x02 #define MSRCTL_QUIETEN 0x01 -// -// Bits in the MSRCTL1 register -// + +/* Bits in the MSRCTL1 register */ #define MSRCTL1_TXPWR 0x08 #define MSRCTL1_CSAPAREN 0x04 #define MSRCTL1_TXPAUSE 0x01 -// Loopback mode -#define MAC_LB_EXT 0x02 // -#define MAC_LB_INTERNAL 0x01 // -#define MAC_LB_NONE 0x00 // +/* Loopback mode */ +#define MAC_LB_EXT 0x02 +#define MAC_LB_INTERNAL 0x01 +#define MAC_LB_NONE 0x00 #define Default_BI 0x200 -// MiscFIFO Offset +/* MiscFIFO Offset */ #define MISCFIFO_KEYETRY0 32 #define MISCFIFO_KEYENTRYSIZE 22 #define MISCFIFO_SYNINFO_IDX 10 #define MISCFIFO_SYNDATA_IDX 11 #define MISCFIFO_SYNDATASIZE 21 -// enabled mask value of irq +/* enabled mask value of irq */ #define IMR_MASK_VALUE (IMR_SOFTTIMER1 | \ IMR_RXDMA1 | \ IMR_RXNOBUF | \ @@ -599,15 +538,13 @@ IMR_AC0DMA | \ IMR_TXDMA0) -// max time out delay time -#define W_MAX_TIMEOUT 0xFFF0U // +/* max time out delay time */ +#define W_MAX_TIMEOUT 0xFFF0U -// wait time within loop -#define CB_DELAY_LOOP_WAIT 10 // 10ms +/* wait time within loop */ +#define CB_DELAY_LOOP_WAIT 10 /* 10ms */ -// -// revision id -// +/* revision id */ #define REV_ID_VT3253_A0 0x00 #define REV_ID_VT3253_A1 0x01 #define REV_ID_VT3253_B0 0x08 @@ -691,12 +628,12 @@ do { \ VNSvInPortD(dwIoBase + MAC_REG_ATIMDMAPTR, \ (unsigned long *)pdwCurrDescAddr) -// set the chip with current BCN tx descriptor address +/* set the chip with current BCN tx descriptor address */ #define MACvSetCurrBCNTxDescAddr(dwIoBase, dwCurrDescAddr) \ VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, \ dwCurrDescAddr) -// set the chip with current BCN length +/* set the chip with current BCN length */ #define MACvSetCurrBCNLength(dwIoBase, wCurrBCNLength) \ VNSvOutPortW(dwIoBase + MAC_REG_BCNDMACTL+2, \ wCurrBCNLength) @@ -888,7 +825,7 @@ do { \ VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1) #define MACvReadMIBCounter(dwIoBase, pdwCounter) \ - VNSvInPortD(dwIoBase + MAC_REG_MIBCNTR , pdwCounter) + VNSvInPortD(dwIoBase + MAC_REG_MIBCNTR, pdwCounter) #define MACvPwrEvntDisable(dwIoBase) \ VNSvOutPortW(dwIoBase + MAC_REG_WAKEUPEN0, 0x0000) @@ -896,7 +833,7 @@ do { \ #define MACvEnableProtectMD(dwIoBase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue | EnCFG_ProtectMd; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) @@ -904,7 +841,7 @@ do { \ #define MACvDisableProtectMD(dwIoBase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue & ~EnCFG_ProtectMd; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) @@ -912,7 +849,7 @@ do { \ #define MACvEnableBarkerPreambleMd(dwIoBase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue | EnCFG_BarkerPream; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) @@ -920,7 +857,7 @@ do { \ #define MACvDisableBarkerPreambleMd(dwIoBase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue & ~EnCFG_BarkerPream; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) @@ -928,7 +865,7 @@ do { \ #define MACvSetBBType(dwIoBase, byTyp) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue & ~EnCFG_BBType_MASK; \ dwOrgValue = dwOrgValue | (unsigned long)byTyp; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ @@ -953,15 +890,18 @@ do { \ #define MACvSetRFLE_LatchBase(dwIoBase) \ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT) -bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, unsigned char byTestBits); -bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, unsigned char byTestBits); +bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, + unsigned char byTestBits); +bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, + unsigned char byTestBits); bool MACbIsIntDisable(void __iomem *dwIoBase); void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit); void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit); -void MACvGetLongRetryLimit(void __iomem *dwIoBase, unsigned char *pbyRetryLimit); +void MACvGetLongRetryLimit(void __iomem *dwIoBase, + unsigned char *pbyRetryLimit); void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode); @@ -975,22 +915,32 @@ bool MACbSafeTxOff(void __iomem *dwIoBase); bool MACbSafeStop(void __iomem *dwIoBase); bool MACbShutdown(void __iomem *dwIoBase); void MACvInitialize(void __iomem *dwIoBase); -void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrSyncDescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrATIMDescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); +void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrSyncDescAddrEx(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrATIMDescAddrEx(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay); void MACvOneShotTimer1MicroSec(void __iomem *dwIoBase, unsigned int uDelayTime); -void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, unsigned long dwData); +void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, + unsigned long dwData); bool MACbPSWakeup(void __iomem *dwIoBase); -void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, unsigned int uEntryIdx, - unsigned int uKeyIdx, unsigned char *pbyAddr, u32 *pdwKey, unsigned char byLocalID); +void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, + unsigned int uEntryIdx, unsigned int uKeyIdx, + unsigned char *pbyAddr, u32 *pdwKey, + unsigned char byLocalID); void MACvDisableKeyEntry(void __iomem *dwIoBase, unsigned int uEntryIdx); -#endif // __MAC_H__ +#endif /* __MAC_H__ */ diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index e826f07e91c..be3c4e949b6 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -71,33 +71,33 @@ PSvEnablePowerSaving( struct vnt_private *pDevice = hDeviceContext; u16 wAID = pDevice->current_aid | BIT(14) | BIT(15); - // set period of power up before TBTT + /* set period of power up before TBTT */ VNSvOutPortW(pDevice->PortOffset + MAC_REG_PWBT, C_PWBT); if (pDevice->op_mode != NL80211_IFTYPE_ADHOC) { - // set AID + /* set AID */ VNSvOutPortW(pDevice->PortOffset + MAC_REG_AIDATIM, wAID); } else { - // set ATIM Window + /* set ATIM Window */ #if 0 /* TODO atim window */ MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); #endif } - // Set AutoSleep + /* Set AutoSleep */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); - // Set HWUTSF + /* Set HWUTSF */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); if (wListenInterval >= 2) { - // clear always listen beacon + /* clear always listen beacon */ MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); - // first time set listen next beacon + /* first time set listen next beacon */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); } else { - // always listen beacon + /* always listen beacon */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); } - // enable power saving hw function + /* enable power saving hw function */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); pDevice->bEnablePSMode = true; @@ -122,13 +122,13 @@ PSvDisablePowerSaving( { struct vnt_private *pDevice = hDeviceContext; - // disable power saving hw function + /* disable power saving hw function */ MACbPSWakeup(pDevice->PortOffset); - //clear AutoSleep + /* clear AutoSleep */ MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); - //clear HWUTSF + /* clear HWUTSF */ MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); - // set always listen beacon + /* set always listen beacon */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); pDevice->bEnablePSMode = false; diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 32ef99341e2..941b2adca95 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -651,7 +651,8 @@ bool RFbInit( * Return Value: true if succeeded; false if failed. * */ -bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, unsigned char byChannel) +bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, + u16 byChannel) { bool bResult = true; @@ -687,7 +688,8 @@ bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, unsigned * Return Value: None. * */ -bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, unsigned int uChannel) +bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, + u16 uChannel) { void __iomem *dwIoBase = priv->PortOffset; int ii; @@ -767,13 +769,12 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, unsig bool RFbSetPower( struct vnt_private *priv, unsigned int uRATE, - unsigned int uCH + u16 uCH ) { bool bResult = true; unsigned char byPwr = 0; unsigned char byDec = 0; - unsigned char byPwrdBm = 0; if (priv->dwDiagRefCount != 0) return true; @@ -786,8 +787,10 @@ bool RFbSetPower( case RATE_2M: case RATE_5M: case RATE_11M: + if (uCH > CB_MAX_CHANNEL_24G) + return false; + byPwr = priv->abyCCKPwrTbl[uCH]; - byPwrdBm = priv->abyCCKDefaultPwr[uCH]; break; case RATE_6M: case RATE_9M: @@ -801,15 +804,6 @@ bool RFbSetPower( if (byDec >= priv->byMaxPwrLevel) byDec = priv->byMaxPwrLevel-1; - if (priv->byRFType == RF_UW2452) { - byPwrdBm = byDec - byPwr; - byPwrdBm /= 3; - } else { - byPwrdBm = byDec - byPwr; - byPwrdBm >>= 1; - } - - byPwrdBm += priv->abyOFDMDefaultPwr[uCH]; byPwr = byDec; break; case RATE_24M: @@ -817,7 +811,6 @@ bool RFbSetPower( case RATE_48M: case RATE_54M: byPwr = priv->abyOFDMPwrTbl[uCH]; - byPwrdBm = priv->abyOFDMDefaultPwr[uCH]; break; } @@ -937,8 +930,8 @@ RFvRSSITodBm( /* Post processing for the 11b/g and 11a. * for save time on changing Reg2,3,5,7,10,12,15 */ bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, - unsigned char byOldChannel, - unsigned char byNewChannel) + u16 byOldChannel, + u16 byNewChannel) { bool bResult; diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h index 8a6e2cfedaa..2ea21e2b00f 100644 --- a/drivers/staging/vt6655/rf.h +++ b/drivers/staging/vt6655/rf.h @@ -74,12 +74,12 @@ /*--------------------- Export Functions --------------------------*/ bool IFRFbWriteEmbedded(struct vnt_private *, unsigned long dwData); -bool RFbSelectChannel(struct vnt_private *, unsigned char byRFType, unsigned char byChannel); +bool RFbSelectChannel(struct vnt_private *, unsigned char byRFType, u16); bool RFbInit( struct vnt_private * ); -bool RFvWriteWakeProgSyn(struct vnt_private *, unsigned char byRFType, unsigned int uChannel); -bool RFbSetPower(struct vnt_private *, unsigned int uRATE, unsigned int uCH); +bool RFvWriteWakeProgSyn(struct vnt_private *, unsigned char byRFType, u16); +bool RFbSetPower(struct vnt_private *, unsigned int uRATE, u16); bool RFbRawSetPower( struct vnt_private *, unsigned char byPwr, @@ -94,7 +94,7 @@ RFvRSSITodBm( ); //{{ RobertYu: 20050104 -bool RFbAL7230SelectChannelPostProcess(struct vnt_private *, unsigned char byOldChannel, unsigned char byNewChannel); +bool RFbAL7230SelectChannelPostProcess(struct vnt_private *, u16, u16); //}} RobertYu #endif // __RF_H__ diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index b5b0155961f..07ce3fd88e7 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -205,7 +205,7 @@ s_uGetRTSCTSRsvTime( unsigned short wCurrentRate ) { - unsigned int uRrvTime , uRTSTime, uCTSTime, uAckTime, uDataTime; + unsigned int uRrvTime, uRTSTime, uCTSTime, uAckTime, uDataTime; uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0; @@ -1207,7 +1207,6 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, ptdCurr->pTDInfo->dwReqCount = cbReqCount; ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength; ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma; - ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma); return cbHeaderLength; } diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index c53703a772f..cc63dc8d47f 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -33,9 +33,9 @@ /*--------------------- Export Definitions -------------------------*/ -// -// For memory mapped IO -// + +/* For memory mapped IO */ + #define VNSvInPortB(dwIOAddress, pbyData) \ do { \ @@ -86,4 +86,4 @@ do { \ /*--------------------- Export Functions --------------------------*/ -#endif // __UPC_H__ +#endif /* __UPC_H__ */ diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 9340f1508cf..67ff13f4f73 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -78,7 +78,7 @@ void vnt_set_channel(struct vnt_private *priv, u32 connection_channel) /* Set Channel[7] = 0 to tell H/W channel is changing now. */ vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL, 0xb0); - vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNLE, + vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL, connection_channel, 0, 0, NULL); vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL, diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 5a7ca527106..f71d59fa3b2 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -160,7 +160,7 @@ #define MESSAGE_TYPE_CLRKEYENTRY 0x9 #define MESSAGE_TYPE_WRITE_MISCFF 0xa #define MESSAGE_TYPE_SET_ANTMD 0xb -#define MESSAGE_TYPE_SELECT_CHANNLE 0xc +#define MESSAGE_TYPE_SELECT_CHANNEL 0xc #define MESSAGE_TYPE_SET_TSFTBTT 0xd #define MESSAGE_TYPE_SET_SSTIFS 0xe #define MESSAGE_TYPE_CHANGE_BBTYPE 0xf @@ -307,8 +307,8 @@ struct vnt_private { struct vnt_cmd_card_init init_command; struct vnt_rsp_card_init init_response; - u8 current_net_addr[ETH_ALEN]; - u8 permanent_net_addr[ETH_ALEN]; + u8 current_net_addr[ETH_ALEN] __aligned(2); + u8 permanent_net_addr[ETH_ALEN] __aligned(2); u8 exist_sw_net_addr; diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h index fab195f8c3f..95e0e83a487 100644 --- a/drivers/staging/vt6656/dpc.h +++ b/drivers/staging/vt6656/dpc.h @@ -32,6 +32,6 @@ #include "device.h" int vnt_rx_data(struct vnt_private *, struct vnt_rcb *, - unsigned long bytes_recieved); + unsigned long bytes_received); #endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index b95d5b1efcc..71adc1f6183 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -34,6 +34,7 @@ */ #undef __NO_VERSION__ +#include <linux/etherdevice.h> #include <linux/file.h> #include "device.h" #include "card.h" @@ -319,7 +320,7 @@ static int vnt_init_registers(struct vnt_private *priv) /* get permanent network address */ memcpy(priv->permanent_net_addr, init_rsp->net_addr, 6); - memcpy(priv->current_net_addr, priv->permanent_net_addr, ETH_ALEN); + ether_addr_copy(priv->current_net_addr, priv->permanent_net_addr); /* if exist SW network address, use it */ dev_dbg(&priv->usb->dev, "Network address = %pM\n", diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index ea5140ab2b4..33baf26de4b 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -36,6 +36,7 @@ * */ +#include <linux/etherdevice.h> #include "device.h" #include "rxtx.h" #include "card.h" @@ -55,7 +56,7 @@ static const u16 vnt_fb_opt0[2][5] = { static const u16 vnt_fb_opt1[2][5] = { {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, /* fallback_rate0 */ - {RATE_6M , RATE_6M, RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */ + {RATE_6M, RATE_6M, RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */ }; #define RTSDUR_BB 0 @@ -392,8 +393,8 @@ static int vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context, rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); - memcpy(rts->ra, hdr->addr1, ETH_ALEN); - memcpy(rts->ta, hdr->addr2, ETH_ALEN); + ether_addr_copy(rts->ra, hdr->addr1); + ether_addr_copy(rts->ta, hdr->addr2); return 0; } @@ -517,65 +518,66 @@ static u16 vnt_rxtx_rts_a_fb_head(struct vnt_usb_send_context *tx_context, return vnt_rxtx_datahead_a_fb(tx_context, &buf->data_head); } -static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, - union vnt_tx_data_head *head) +static u16 vnt_fill_cts_fb_head(struct vnt_usb_send_context *tx_context, + union vnt_tx_data_head *head) { struct vnt_private *priv = tx_context->priv; + struct vnt_cts_fb *buf = &head->cts_g_fb; u32 cts_frame_len = 14; u16 current_rate = tx_context->tx_rate; - if (!head) - return 0; + /* Get SignalField,ServiceField,Length */ + vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate, + PK_TYPE_11B, &buf->b); - if (tx_context->fb_option) { - /* Auto Fall back */ - struct vnt_cts_fb *buf = &head->cts_g_fb; - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, cts_frame_len, - priv->top_cck_basic_rate, PK_TYPE_11B, &buf->b); - buf->duration_ba = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, - tx_context->pkt_type, - current_rate); - /* Get CTSDuration_ba_f0 */ - buf->cts_duration_ba_f0 = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F0, - tx_context->pkt_type, - priv->tx_rate_fb0); - /* Get CTSDuration_ba_f1 */ - buf->cts_duration_ba_f1 = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F1, - tx_context->pkt_type, - priv->tx_rate_fb1); - /* Get CTS Frame body */ - buf->data.duration = buf->duration_ba; - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); + buf->duration_ba = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, + tx_context->pkt_type, + current_rate); + /* Get CTSDuration_ba_f0 */ + buf->cts_duration_ba_f0 = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F0, + tx_context->pkt_type, + priv->tx_rate_fb0); + /* Get CTSDuration_ba_f1 */ + buf->cts_duration_ba_f1 = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F1, + tx_context->pkt_type, + priv->tx_rate_fb1); + /* Get CTS Frame body */ + buf->data.duration = buf->duration_ba; + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); - memcpy(buf->data.ra, priv->current_net_addr, ETH_ALEN); + ether_addr_copy(buf->data.ra, priv->current_net_addr); - return vnt_rxtx_datahead_g_fb(tx_context, &buf->data_head); - } else { - struct vnt_cts *buf = &head->cts_g; - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, cts_frame_len, - priv->top_cck_basic_rate, PK_TYPE_11B, &buf->b); - /* Get CTSDuration_ba */ - buf->duration_ba = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, - tx_context->pkt_type, - current_rate); - /*Get CTS Frame body*/ - buf->data.duration = buf->duration_ba; - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); + return vnt_rxtx_datahead_g_fb(tx_context, &buf->data_head); +} + +static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, + union vnt_tx_data_head *head) +{ + struct vnt_private *priv = tx_context->priv; + struct vnt_cts *buf = &head->cts_g; + u32 cts_frame_len = 14; + u16 current_rate = tx_context->tx_rate; - memcpy(buf->data.ra, priv->current_net_addr, ETH_ALEN); + /* Get SignalField,ServiceField,Length */ + vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate, + PK_TYPE_11B, &buf->b); + /* Get CTSDuration_ba */ + buf->duration_ba = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, + tx_context->pkt_type, + current_rate); + /*Get CTS Frame body*/ + buf->data.duration = buf->duration_ba; + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); - return vnt_rxtx_datahead_g(tx_context, &buf->data_head); - } + ether_addr_copy(buf->data.ra, priv->current_net_addr); - return 0; + return vnt_rxtx_datahead_g(tx_context, &buf->data_head); } static u16 vnt_rxtx_rts(struct vnt_usb_send_context *tx_context, @@ -632,6 +634,9 @@ static u16 vnt_rxtx_cts(struct vnt_usb_send_context *tx_context, head = &tx_head->tx_cts.tx.mic.head; /* Fill CTS */ + if (tx_context->fb_option) + return vnt_fill_cts_fb_head(tx_context, head); + return vnt_fill_cts_head(tx_context, head); } @@ -739,7 +744,7 @@ static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context, mic_hdr->id = 0x59; mic_hdr->payload_len = cpu_to_be16(payload_len); - memcpy(mic_hdr->mic_addr2, hdr->addr2, ETH_ALEN); + ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2); ieee80211_get_key_tx_seq(tx_key, &seq); diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 20d146b61ba..8f209107049 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -879,7 +879,7 @@ typedef struct hfa384x_usb_error { /* Unions for packaging all the known packet types together */ typedef union hfa384x_usbout { - u16 type; + __le16 type; hfa384x_usb_txfrm_t txfrm; hfa384x_usb_cmdreq_t cmdreq; hfa384x_usb_wridreq_t wridreq; @@ -889,7 +889,7 @@ typedef union hfa384x_usbout { } __packed hfa384x_usbout_t; typedef union hfa384x_usbin { - u16 type; + __le16 type; hfa384x_usb_rxfrm_t rxfrm; hfa384x_usb_txfrm_t txfrm; hfa384x_usb_infofrm_t infofrm; @@ -1268,7 +1268,7 @@ typedef struct hfa384x { hfa384x_downloadbuffer_t bufinfo; u16 dltimeout; - int scanflag; /* to signal scan comlete */ + int scanflag; /* to signal scan complete */ int join_ap; /* are we joined to a specific ap */ int join_retries; /* number of join retries till we fail */ hfa384x_JoinRequest_data_t joinreq; /* join request saved data */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 55d2f563e30..28cd1c4c02c 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -382,7 +382,7 @@ done: * * Arguments: * hw device struct -* tx_urb URB of data for tranmission +* tx_urb URB of data for transmission * memflags memory allocation flags * * Returns: @@ -2391,7 +2391,7 @@ int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) * 0 success * >0 f/w reported error - f/w status code * <0 driver reported error -* -ETIMEDOUT timout waiting for the cmd regs to become +* -ETIMEDOUT timeout waiting for the cmd regs to become * available, or waiting for the control reg * to indicate the Aux port is enabled. * -ENODATA the buffer does NOT contain a valid PDA. @@ -3346,7 +3346,7 @@ retry: if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) run_queue = 1; } else { - const u16 intype = (usbin->type & ~cpu_to_le16(0x8000)); + const __le16 intype = (usbin->type & ~cpu_to_le16(0x8000)); /* * Check that our message is what we're expecting ... @@ -4123,12 +4123,11 @@ static int hfa384x_isgood_pdrcode(u16 pdrcode) pr_debug("Encountered unknown PDR#=0x%04x, assuming it's ok.\n", pdrcode); return 1; - } else { - /* bad code */ - pr_debug("Encountered unknown PDR#=0x%04x, (>=0x1000), assuming it's bad.\n", - pdrcode); - return 0; } + break; } - return 0; /* avoid compiler warnings */ + /* bad code */ + pr_debug("Encountered unknown PDR#=0x%04x, (>=0x1000), assuming it's bad.\n", + pdrcode); + return 0; } diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 7eaaf9a6350..bd69e8cf200 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -511,7 +511,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, * protocol. * * Arguments: -* proto protocl number (in host order) to search for. +* proto protocol number (in host order) to search for. * * Returns: * 1 - if the table is empty or a match is found. diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 7221379c974..4b84b568f6c 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -80,7 +80,7 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, /*---------------------------------------------------------------- * p80211req_dorequest * -* Handles an MLME reqest/confirm message. +* Handles an MLME request/confirm message. * * Arguments: * wlandev WLAN device struct diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index b62fdcba94e..16f12395910 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -45,7 +45,7 @@ * -------------------------------------------------------------------- * * This file contains the constants and data structures for interaction -* with the hfa384x Wireless LAN (WLAN) Media Access Contoller (MAC). +* with the hfa384x Wireless LAN (WLAN) Media Access Controller (MAC). * The hfa384x is a portion of the Harris PRISM(tm) WLAN chipset. * * [Implementation and usage notes] diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index df577dfe7ff..10ad24a89dd 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -199,7 +199,7 @@ static int prism2sta_close(wlandevice_t *wlandev) /*---------------------------------------------------------------- * prism2sta_reset * -* Not currently implented. +* Currently not implemented. * * Arguments: * wlandev wlan device structure @@ -662,7 +662,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) "ident: ap f/w: id=0x%02x %d.%d.%d\n", hw->ident_sta_fw.id, hw->ident_sta_fw.major, hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); - netdev_err(wlandev->netdev, "Unsupported Tertiary AP firmeare loaded!\n"); + netdev_err(wlandev->netdev, "Unsupported Tertiary AP firmware loaded!\n"); goto failed; } diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 709d49e7f3c..935c714f592 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -930,7 +930,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, + var->hsync_len; unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) u8 cr_data; #endif unsigned int drate = 0, hrate = 0; @@ -952,7 +952,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, } pr_debug("var->pixclock=%d, htotal=%d, vtotal=%d\n", var->pixclock, htotal, vtotal); - if (var->pixclock && htotal && vtotal) { + if (var->pixclock) { drate = 1000000000 / var->pixclock; hrate = (drate * 1000) / htotal; xgifb_info->refresh_rate = (unsigned int) (hrate * 2 @@ -1044,7 +1044,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->DstColor = 0x0000; xgifb_info->XGI310_AccelDepth = 0x00000000; xgifb_info->video_cmap_len = 256; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) cr_data = xgifb_reg_get(XGICR, 0x4D); xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0)); #endif @@ -1052,7 +1052,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, case 16: xgifb_info->DstColor = 0x8000; xgifb_info->XGI310_AccelDepth = 0x00010000; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) cr_data = xgifb_reg_get(XGICR, 0x4D); xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B)); #endif @@ -1062,7 +1062,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->DstColor = 0xC000; xgifb_info->XGI310_AccelDepth = 0x00020000; xgifb_info->video_cmap_len = 16; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) cr_data = xgifb_reg_get(XGICR, 0x4D); xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15)); #endif |