Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 23 Dec 2009 21:35:19 +0000 (13:35 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 23 Dec 2009 21:35:19 +0000 (13:35 -0800)
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (30 commits)
  USB: Fix a bug on appledisplay.c regarding signedness
  USB: option: support hi speed for modem Haier CE100
  USB: audio gadget: free alsa devices when unloading
  USB: audio gadget: fix wTotalLength calculation
  usb: otg: isp1301_omap: fix compile error
  USB: musb: workaround Blackfin FIFO anomalies
  USB: musb: Fix array index out of bounds issue
  USB: musb: Fix null pointer dereference issue
  USB: musb: correct DMA address for tx
  USB: musb: gadget_ep0: avoid SetupEnd interrupt
  USB: musb: fix for crash in DM646x USB when (CPPI)DMA is enabled
  USB: musb: do not work if no gadget driver is loaded
  USB: musb: gadget: set otg tranceiver to idle when registering gadget
  USB: musb: Populate the VBUS GPIO with the correct GPIO number
  USB: musb: MAINTAINERS: Fix my tree's address
  USB: musb: fix compiling warning with min() macro
  USB: musb: move musb_remove to __exit
  USB: musb_gadget: fix kernel oops in txstate()
  USB: ftdi_sio: sort PID/VID entries in new ftdi_sio_ids.h header
  USB: ftdi_sio: isolate all device IDs to new ftdi_sio_ids.h header
  ...

97 files changed:
Documentation/driver-model/driver.txt
Documentation/filesystems/sysfs.txt
Documentation/sound/alsa/HD-Audio-Models.txt
Documentation/stable_kernel_rules.txt
drivers/base/bus.c
drivers/base/core.c
drivers/base/devtmpfs.c
drivers/base/driver.c
drivers/base/platform.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/batman-adv/Kconfig
drivers/staging/batman-adv/send.c
drivers/staging/comedi/comedi.h
drivers/staging/comedi/drivers/jr3_pci.c
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/dst/Kconfig [deleted file]
drivers/staging/dst/Makefile [deleted file]
drivers/staging/dst/crypto.c [deleted file]
drivers/staging/dst/dcore.c [deleted file]
drivers/staging/dst/export.c [deleted file]
drivers/staging/dst/state.c [deleted file]
drivers/staging/dst/thread_pool.c [deleted file]
drivers/staging/dst/trans.c [deleted file]
drivers/staging/panel/Kconfig
drivers/staging/panel/panel.c
drivers/staging/ramzswap/TODO
drivers/staging/ramzswap/ramzswap_drv.c
drivers/staging/rtl8187se/ieee80211/ieee80211.h
drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
drivers/staging/rtl8187se/r8180_core.c
drivers/staging/rtl8187se/r8180_wx.c
drivers/staging/rtl8192e/ieee80211.h
drivers/staging/rtl8192e/ieee80211/ieee80211.h
drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
drivers/staging/rtl8192e/r8192E_core.c
drivers/staging/rtl8192su/ieee80211/ieee80211.h
drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
drivers/staging/rtl8192su/r8192U_core.c
drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
drivers/staging/sm7xx/Kconfig [new file with mode: 0644]
drivers/staging/sm7xx/Makefile [new file with mode: 0644]
drivers/staging/sm7xx/TODO [new file with mode: 0644]
drivers/staging/sm7xx/smtc2d.c [new file with mode: 0644]
drivers/staging/sm7xx/smtc2d.h [new file with mode: 0644]
drivers/staging/sm7xx/smtcfb.c [new file with mode: 0644]
drivers/staging/sm7xx/smtcfb.h [new file with mode: 0644]
drivers/staging/vt6655/Kconfig
drivers/staging/vt6656/Kconfig
drivers/staging/wlan-ng/prism2fw.c
fs/ext3/inode.c
fs/ext3/namei.c
fs/ext3/resize.c
fs/ext3/super.c
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/jbd/journal.c
fs/jbd2/journal.c
fs/ocfs2/alloc.c
fs/ocfs2/alloc.h
fs/ocfs2/namei.c
fs/ocfs2/refcounttree.c
fs/quota/dquot.c
fs/quota/quota_v2.c
fs/stat.c
fs/super.c
fs/sysfs/bin.c
include/linux/device.h
include/linux/dst.h [deleted file]
include/linux/ext3_fs_sb.h
include/linux/ext3_jbd.h
include/linux/fs.h
include/linux/kfifo.h
include/linux/quota.h
include/linux/sysfs.h
kernel/sched.c
sound/core/Kconfig
sound/core/pcm_timer.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_sigmatel.c
sound/soc/codecs/wm9712.c
sound/soc/imx/mx27vis_wm8974.c
sound/soc/sh/fsi.c

index 60120fb..d2cd6fb 100644 (file)
@@ -226,5 +226,5 @@ struct driver_attribute driver_attr_debug;
 This can then be used to add and remove the attribute from the
 driver's directory using:
 
-int driver_create_file(struct device_driver *, struct driver_attribute *);
-void driver_remove_file(struct device_driver *, struct driver_attribute *);
+int driver_create_file(struct device_driver *, const struct driver_attribute *);
+void driver_remove_file(struct device_driver *, const struct driver_attribute *);
index b245d52..931c806 100644 (file)
@@ -91,8 +91,8 @@ struct device_attribute {
                         const char *buf, size_t count);
 };
 
-int device_create_file(struct device *, struct device_attribute *);
-void device_remove_file(struct device *, struct device_attribute *);
+int device_create_file(struct device *, const struct device_attribute *);
+void device_remove_file(struct device *, const struct device_attribute *);
 
 It also defines this helper for defining device attributes: 
 
@@ -316,8 +316,8 @@ DEVICE_ATTR(_name, _mode, _show, _store);
 
 Creation/Removal:
 
-int device_create_file(struct device *device, struct device_attribute * attr);
-void device_remove_file(struct device * dev, struct device_attribute * attr);
+int device_create_file(struct device *dev, const struct device_attribute * attr);
+void device_remove_file(struct device *dev, const struct device_attribute * attr);
 
 
 - bus drivers (include/linux/device.h)
@@ -358,7 +358,7 @@ DRIVER_ATTR(_name, _mode, _show, _store)
 
 Creation/Removal:
 
-int driver_create_file(struct device_driver *, struct driver_attribute *);
-void driver_remove_file(struct device_driver *, struct driver_attribute *);
+int driver_create_file(struct device_driver *, const struct driver_attribute *);
+void driver_remove_file(struct device_driver *, const struct driver_attribute *);
 
 
index e93afff..e72cee9 100644 (file)
@@ -403,4 +403,5 @@ STAC9872
 Cirrus Logic CS4206/4207
 ========================
   mbp55                MacBook Pro 5,5
+  imac27       IMac 27 Inch
   auto         BIOS setup (default)
index a452227..5effa5b 100644 (file)
@@ -26,13 +26,33 @@ Procedure for submitting patches to the -stable tree:
 
  - Send the patch, after verifying that it follows the above rules, to
    stable@kernel.org.
+ - To have the patch automatically included in the stable tree, add the
+   the tag
+     Cc: stable@kernel.org
+   in the sign-off area. Once the patch is merged it will be applied to
+   the stable tree without anything else needing to be done by the author
+   or subsystem maintainer.
+ - If the patch requires other patches as prerequisites which can be
+   cherry-picked than this can be specified in the following format in
+   the sign-off area:
+
+     Cc: <stable@kernel.org> # .32.x: a1f84a3: sched: Check for idle
+     Cc: <stable@kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
+     Cc: <stable@kernel.org> # .32.x: fd21073: sched: Fix affinity logic
+     Cc: <stable@kernel.org> # .32.x
+    Signed-off-by: Ingo Molnar <mingo@elte.hu>
+
+   The tag sequence has the meaning of:
+     git cherry-pick a1f84a3
+     git cherry-pick 1b9508f
+     git cherry-pick fd21073
+     git cherry-pick <this commit>
+
  - The sender will receive an ACK when the patch has been accepted into the
    queue, or a NAK if the patch is rejected.  This response might take a few
    days, according to the developer's schedules.
  - If accepted, the patch will be added to the -stable queue, for review by
    other developers and by the relevant subsystem maintainer.
- - If the stable@kernel.org address is added to a patch, when it goes into
-   Linus's tree it will automatically be emailed to the stable team.
  - Security patches should not be sent to this alias, but instead to the
    documented security@kernel.org address.
 
index 63c143e..c0c5a43 100644 (file)
@@ -703,9 +703,9 @@ int bus_add_driver(struct device_driver *drv)
        return 0;
 
 out_unregister:
+       kobject_put(&priv->kobj);
        kfree(drv->p);
        drv->p = NULL;
-       kobject_put(&priv->kobj);
 out_put_bus:
        bus_put(bus);
        return error;
index f1290cb..2820257 100644 (file)
@@ -446,7 +446,8 @@ struct kset *devices_kset;
  * @dev: device.
  * @attr: device attribute descriptor.
  */
-int device_create_file(struct device *dev, struct device_attribute *attr)
+int device_create_file(struct device *dev,
+                      const struct device_attribute *attr)
 {
        int error = 0;
        if (dev)
@@ -459,7 +460,8 @@ int device_create_file(struct device *dev, struct device_attribute *attr)
  * @dev: device.
  * @attr: device attribute descriptor.
  */
-void device_remove_file(struct device *dev, struct device_attribute *attr)
+void device_remove_file(struct device *dev,
+                       const struct device_attribute *attr)
 {
        if (dev)
                sysfs_remove_file(&dev->kobj, &attr->attr);
@@ -470,7 +472,8 @@ void device_remove_file(struct device *dev, struct device_attribute *attr)
  * @dev: device.
  * @attr: device binary attribute descriptor.
  */
-int device_create_bin_file(struct device *dev, struct bin_attribute *attr)
+int device_create_bin_file(struct device *dev,
+                          const struct bin_attribute *attr)
 {
        int error = -EINVAL;
        if (dev)
@@ -484,7 +487,8 @@ EXPORT_SYMBOL_GPL(device_create_bin_file);
  * @dev: device.
  * @attr: device binary attribute descriptor.
  */
-void device_remove_bin_file(struct device *dev, struct bin_attribute *attr)
+void device_remove_bin_file(struct device *dev,
+                           const struct bin_attribute *attr)
 {
        if (dev)
                sysfs_remove_bin_file(&dev->kobj, attr);
@@ -905,8 +909,10 @@ int device_add(struct device *dev)
                dev->init_name = NULL;
        }
 
-       if (!dev_name(dev))
+       if (!dev_name(dev)) {
+               error = -EINVAL;
                goto name_error;
+       }
 
        pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
 
index 50375bb..090dd48 100644 (file)
@@ -32,7 +32,7 @@ static int dev_mount = 1;
 static int dev_mount;
 #endif
 
-static rwlock_t dirlock;
+static DEFINE_MUTEX(dirlock);
 
 static int __init mount_param(char *str)
 {
@@ -93,7 +93,7 @@ static int create_path(const char *nodepath)
 {
        int err;
 
-       read_lock(&dirlock);
+       mutex_lock(&dirlock);
        err = dev_mkdir(nodepath, 0755);
        if (err == -ENOENT) {
                char *path;
@@ -101,8 +101,10 @@ static int create_path(const char *nodepath)
 
                /* parent directories do not exist, create them */
                path = kstrdup(nodepath, GFP_KERNEL);
-               if (!path)
-                       return -ENOMEM;
+               if (!path) {
+                       err = -ENOMEM;
+                       goto out;
+               }
                s = path;
                for (;;) {
                        s = strchr(s, '/');
@@ -117,7 +119,8 @@ static int create_path(const char *nodepath)
                }
                kfree(path);
        }
-       read_unlock(&dirlock);
+out:
+       mutex_unlock(&dirlock);
        return err;
 }
 
@@ -229,7 +232,7 @@ static int delete_path(const char *nodepath)
        if (!path)
                return -ENOMEM;
 
-       write_lock(&dirlock);
+       mutex_lock(&dirlock);
        for (;;) {
                char *base;
 
@@ -241,7 +244,7 @@ static int delete_path(const char *nodepath)
                if (err)
                        break;
        }
-       write_unlock(&dirlock);
+       mutex_unlock(&dirlock);
 
        kfree(path);
        return err;
@@ -352,8 +355,6 @@ int __init devtmpfs_init(void)
        int err;
        struct vfsmount *mnt;
 
-       rwlock_init(&dirlock);
-
        err = register_filesystem(&dev_fs_type);
        if (err) {
                printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
index f367885..90c9fff 100644 (file)
@@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(driver_find_device);
  * @attr: driver attribute descriptor.
  */
 int driver_create_file(struct device_driver *drv,
-                      struct driver_attribute *attr)
+                      const struct driver_attribute *attr)
 {
        int error;
        if (drv)
@@ -115,7 +115,7 @@ EXPORT_SYMBOL_GPL(driver_create_file);
  * @attr: driver attribute descriptor.
  */
 void driver_remove_file(struct device_driver *drv,
-                       struct driver_attribute *attr)
+                       const struct driver_attribute *attr)
 {
        if (drv)
                sysfs_remove_file(&drv->p->kobj, &attr->attr);
index 9d2ee25..58efaf2 100644 (file)
@@ -441,6 +441,7 @@ error:
        platform_device_put(pdev);
        return ERR_PTR(retval);
 }
+EXPORT_SYMBOL_GPL(platform_device_register_data);
 
 static int platform_drv_probe(struct device *_dev)
 {
index 093f57a..94eb863 100644 (file)
@@ -87,8 +87,6 @@ source "drivers/staging/frontier/Kconfig"
 
 source "drivers/staging/dream/Kconfig"
 
-source "drivers/staging/dst/Kconfig"
-
 source "drivers/staging/pohmelfs/Kconfig"
 
 source "drivers/staging/b3dfg/Kconfig"
@@ -145,5 +143,7 @@ source "drivers/staging/wavelan/Kconfig"
 
 source "drivers/staging/netwave/Kconfig"
 
+source "drivers/staging/sm7xx/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
index 069864f..b5e67b8 100644 (file)
@@ -26,7 +26,6 @@ obj-$(CONFIG_RTL8192E)                += rtl8192e/
 obj-$(CONFIG_INPUT_MIMIO)      += mimio/
 obj-$(CONFIG_TRANZPORT)                += frontier/
 obj-$(CONFIG_DREAM)            += dream/
-obj-$(CONFIG_DST)              += dst/
 obj-$(CONFIG_POHMELFS)         += pohmelfs/
 obj-$(CONFIG_B3DFG)            += b3dfg/
 obj-$(CONFIG_IDE_PHISON)       += phison/
@@ -53,3 +52,4 @@ obj-$(CONFIG_ARLAN)           += arlan/
 obj-$(CONFIG_WAVELAN)          += wavelan/
 obj-$(CONFIG_PCMCIA_WAVELAN)   += wavelan/
 obj-$(CONFIG_PCMCIA_NETWAVE)   += netwave/
+obj-$(CONFIG_FB_SM7XX)         += sm7xx/
index 7632f57..1d74dab 100644 (file)
@@ -4,6 +4,7 @@
 
 config BATMAN_ADV
        tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
+       depends on PROC_FS && PACKET
         default n
        ---help---
 
index d724798..eb61750 100644 (file)
@@ -363,8 +363,10 @@ void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len)
                return;
 
        forw_packet->packet_buff = kmalloc(packet_len, GFP_ATOMIC);
-       if (!forw_packet->packet_buff)
+       if (!forw_packet->packet_buff) {
+               kfree(forw_packet);
                return;
+       }
 
        forw_packet->packet_len = packet_len;
        memcpy(forw_packet->packet_buff, packet_buff, forw_packet->packet_len);
index ccc5cdc..b559a9c 100644 (file)
 
 #define COMEDI_CB_EOS          1       /* end of scan */
 #define COMEDI_CB_EOA          2       /* end of acquisition */
-#define COMEDI_CB_BLOCK                4       /* DEPRECATED: convenient block size */
+#define COMEDI_CB_BLOCK                4       /* data has arrived: wakes up read() / write() */
 #define COMEDI_CB_EOBUF                8       /* DEPRECATED: end of buffer */
 #define COMEDI_CB_ERROR                16      /* card error during acquisition */
 #define COMEDI_CB_OVERFLOW     32      /* buffer overflow/underflow */
index 0d2c2eb..bd39784 100644 (file)
@@ -849,8 +849,11 @@ static int jr3_pci_attach(struct comedi_device *dev,
        }
 
        devpriv->pci_enabled = 1;
-       devpriv->iobase =
-           ioremap(pci_resource_start(card, 0), sizeof(struct jr3_t));
+       devpriv->iobase = ioremap(pci_resource_start(card, 0),
+                       offsetof(struct jr3_t, channel[devpriv->n_channels]));
+       if (!devpriv->iobase)
+               return -ENOMEM;
+
        result = alloc_subdevices(dev, devpriv->n_channels);
        if (result < 0)
                goto out;
index 06c0204..9a1b559 100644 (file)
@@ -1,4 +1,4 @@
-#define DRIVER_VERSION "v2.3"
+#define DRIVER_VERSION "v2.4"
 #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
 #define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com"
 /*
@@ -81,6 +81,8 @@ sampling rate. If you sample two channels you get 4kHz and so on.
  * 2.1:  changed PWM API
  * 2.2:  added firmware kernel request to fix an udev problem
  * 2.3:  corrected a bug in bulk timeouts which were far too short
+ * 2.4:  fixed a bug which causes the driver to hang when it ran out of data.
+ *       Thanks to Jan-Matthias Braun and Ian to spot the bug and fix it.
  *
  */
 
@@ -532,6 +534,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
                }
        }
        /* tell comedi that data is there */
+       s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
        comedi_event(this_usbduxsub->comedidev, s);
 }
 
diff --git a/drivers/staging/dst/Kconfig b/drivers/staging/dst/Kconfig
deleted file mode 100644 (file)
index 448d342..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-config DST
-       tristate "Distributed storage"
-       depends on NET && CRYPTO && SYSFS && BLK_DEV
-       select CONNECTOR
-       ---help---
-       DST is a network block device storage, which can be used to organize
-       exported storage on the remote nodes into the local block device.
-
-       DST works on top of any network media and protocol; it is just a matter
-       of configuration utility to understand the correct addresses. The most
-       common example is TCP over IP, which allows to pass through firewalls and
-       create remote backup storage in a different datacenter. DST requires
-       single port to be enabled on the exporting node and outgoing connections
-       on the local node.
-
-       DST works with in-kernel client and server, which improves performance by
-       eliminating unneded data copies and by not depending on the version
-       of the external IO components. It requires userspace configuration utility
-       though.
-
-       DST uses transaction model, when each store has to be explicitly acked
-       from the remote node to be considered as successfully written. There
-       may be lots of in-flight transactions. When remote host does not ack
-       the transaction it will be resent predefined number of times with specified
-       timeouts between them. All those parameters are configurable. Transactions
-       are marked as failed after all resends complete unsuccessfully; having
-       long enough resend timeout and/or large number of resends allows not to
-       return error to the higher (FS usually) layer in case of short network
-       problems or remote node outages. In case of network RAID setup this means
-       that storage will not degrade until transactions are marked as failed, and
-       thus will not force checksum recalculation and data rebuild. In case of
-       connection failure DST will try to reconnect to the remote node automatically.
-       DST sends ping commands at idle time to detect if remote node is alive.
-
-       Because of transactional model it is possible to use zero-copy sending
-       without worry of data corruption (which in turn could be detected by the
-       strong checksums though).
-
-       DST may fully encrypt the data channel in case of untrusted channel and implement
-       strong checksum of the transferred data. It is possible to configure algorithms
-       and crypto keys; they should match on both sides of the network channel.
-       Crypto processing does not introduce noticeble performance overhead, since DST
-       uses configurable pool of threads to perform crypto processing.
-
-       DST utilizes memory pool model of all its transaction allocations (it is the
-       only additional allocation on the client) and server allocations (bio pools,
-       while pages are allocated from the slab).
-
-       At startup DST performs a simple negotiation with the export node to determine
-       access permissions and size of the exported storage. It can be extended if
-       new parameters should be autonegotiated.
-
-       DST carries block IO flags in the protocol, which allows to transparently implement
-       barriers and sync/flush operations. Those flags are used in the export node where
-       IO against the local storage is performed, which means that sync write will be sync
-       on the remote node too, which in turn improves data integrity and improved resistance
-       to errors and data corruption during power outages or storage damages.
-
-       Homepage: http://www.ioremap.net/projects/dst
-       Userspace configuration utility and the latest releases: http://www.ioremap.net/archive/dst/
-
-config DST_DEBUG
-       bool "DST debug"
-       depends on DST
-       ---help---
-       This option will enable HEAVY debugging of the DST.
-       Turn it on ONLY if you have to debug some really obscure problem.
diff --git a/drivers/staging/dst/Makefile b/drivers/staging/dst/Makefile
deleted file mode 100644 (file)
index 3a8b0cf..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DST) += nst.o
-
-nst-y := dcore.o state.o export.o thread_pool.o crypto.o trans.o
diff --git a/drivers/staging/dst/crypto.c b/drivers/staging/dst/crypto.c
deleted file mode 100644 (file)
index 351295c..0000000
+++ /dev/null
@@ -1,733 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * 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.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/bio.h>
-#include <linux/crypto.h>
-#include <linux/dst.h>
-#include <linux/kernel.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-
-/*
- * Tricky bastard, but IV can be more complex with time...
- */
-static inline u64 dst_gen_iv(struct dst_trans *t)
-{
-       return t->gen;
-}
-
-/*
- * Crypto machinery: hash/cipher support for the given crypto controls.
- */
-static struct crypto_hash *dst_init_hash(struct dst_crypto_ctl *ctl, u8 *key)
-{
-       int err;
-       struct crypto_hash *hash;
-
-       hash = crypto_alloc_hash(ctl->hash_algo, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(hash)) {
-               err = PTR_ERR(hash);
-               dprintk("%s: failed to allocate hash '%s', err: %d.\n",
-                               __func__, ctl->hash_algo, err);
-               goto err_out_exit;
-       }
-
-       ctl->crypto_attached_size = crypto_hash_digestsize(hash);
-
-       if (!ctl->hash_keysize)
-               return hash;
-
-       err = crypto_hash_setkey(hash, key, ctl->hash_keysize);
-       if (err) {
-               dprintk("%s: failed to set key for hash '%s', err: %d.\n",
-                               __func__, ctl->hash_algo, err);
-               goto err_out_free;
-       }
-
-       return hash;
-
-err_out_free:
-       crypto_free_hash(hash);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-static struct crypto_ablkcipher *dst_init_cipher(struct dst_crypto_ctl *ctl,
-               u8 *key)
-{
-       int err = -EINVAL;
-       struct crypto_ablkcipher *cipher;
-
-       if (!ctl->cipher_keysize)
-               goto err_out_exit;
-
-       cipher = crypto_alloc_ablkcipher(ctl->cipher_algo, 0, 0);
-       if (IS_ERR(cipher)) {
-               err = PTR_ERR(cipher);
-               dprintk("%s: failed to allocate cipher '%s', err: %d.\n",
-                               __func__, ctl->cipher_algo, err);
-               goto err_out_exit;
-       }
-
-       crypto_ablkcipher_clear_flags(cipher, ~0);
-
-       err = crypto_ablkcipher_setkey(cipher, key, ctl->cipher_keysize);
-       if (err) {
-               dprintk("%s: failed to set key for cipher '%s', err: %d.\n",
-                               __func__, ctl->cipher_algo, err);
-               goto err_out_free;
-       }
-
-       return cipher;
-
-err_out_free:
-       crypto_free_ablkcipher(cipher);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-/*
- * Crypto engine has a pool of pages to encrypt data into before sending
- * it over the network. This pool is freed/allocated here.
- */
-static void dst_crypto_pages_free(struct dst_crypto_engine *e)
-{
-       unsigned int i;
-
-       for (i = 0; i < e->page_num; ++i)
-               __free_page(e->pages[i]);
-       kfree(e->pages);
-}
-
-static int dst_crypto_pages_alloc(struct dst_crypto_engine *e, int num)
-{
-       int i;
-
-       e->pages = kmalloc(num * sizeof(struct page **), GFP_KERNEL);
-       if (!e->pages)
-               return -ENOMEM;
-
-       for (i = 0; i < num; ++i) {
-               e->pages[i] = alloc_page(GFP_KERNEL);
-               if (!e->pages[i])
-                       goto err_out_free_pages;
-       }
-
-       e->page_num = num;
-       return 0;
-
-err_out_free_pages:
-       while (--i >= 0)
-               __free_page(e->pages[i]);
-
-       kfree(e->pages);
-       return -ENOMEM;
-}
-
-/*
- * Initialize crypto engine for given node.
- * Setup cipher/hash, keys, pool of threads and private data.
- */
-static int dst_crypto_engine_init(struct dst_crypto_engine *e,
-               struct dst_node *n)
-{
-       int err;
-       struct dst_crypto_ctl *ctl = &n->crypto;
-
-       err = dst_crypto_pages_alloc(e, n->max_pages);
-       if (err)
-               goto err_out_exit;
-
-       e->size = PAGE_SIZE;
-       e->data = kmalloc(e->size, GFP_KERNEL);
-       if (!e->data) {
-               err = -ENOMEM;
-               goto err_out_free_pages;
-       }
-
-       if (ctl->hash_algo[0]) {
-               e->hash = dst_init_hash(ctl, n->hash_key);
-               if (IS_ERR(e->hash)) {
-                       err = PTR_ERR(e->hash);
-                       e->hash = NULL;
-                       goto err_out_free;
-               }
-       }
-
-       if (ctl->cipher_algo[0]) {
-               e->cipher = dst_init_cipher(ctl, n->cipher_key);
-               if (IS_ERR(e->cipher)) {
-                       err = PTR_ERR(e->cipher);
-                       e->cipher = NULL;
-                       goto err_out_free_hash;
-               }
-       }
-
-       return 0;
-
-err_out_free_hash:
-       crypto_free_hash(e->hash);
-err_out_free:
-       kfree(e->data);
-err_out_free_pages:
-       dst_crypto_pages_free(e);
-err_out_exit:
-       return err;
-}
-
-static void dst_crypto_engine_exit(struct dst_crypto_engine *e)
-{
-       if (e->hash)
-               crypto_free_hash(e->hash);
-       if (e->cipher)
-               crypto_free_ablkcipher(e->cipher);
-       dst_crypto_pages_free(e);
-       kfree(e->data);
-}
-
-/*
- * Waiting for cipher processing to be completed.
- */
-struct dst_crypto_completion {
-       struct completion               complete;
-       int                             error;
-};
-
-static void dst_crypto_complete(struct crypto_async_request *req, int err)
-{
-       struct dst_crypto_completion *c = req->data;
-
-       if (err == -EINPROGRESS)
-               return;
-
-       dprintk("%s: req: %p, err: %d.\n", __func__, req, err);
-       c->error = err;
-       complete(&c->complete);
-}
-
-static int dst_crypto_process(struct ablkcipher_request *req,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src,
-               void *iv, int enc, unsigned long timeout)
-{
-       struct dst_crypto_completion c;
-       int err;
-
-       init_completion(&c.complete);
-       c.error = -EINPROGRESS;
-
-       ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                       dst_crypto_complete, &c);
-
-       ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv);
-
-       if (enc)
-               err = crypto_ablkcipher_encrypt(req);
-       else
-               err = crypto_ablkcipher_decrypt(req);
-
-       switch (err) {
-       case -EINPROGRESS:
-       case -EBUSY:
-               err = wait_for_completion_interruptible_timeout(&c.complete,
-                               timeout);
-               if (!err)
-                       err = -ETIMEDOUT;
-               else
-                       err = c.error;
-               break;
-       default:
-               break;
-       }
-
-       return err;
-}
-
-/*
- * DST uses generic iteration approach for data crypto processing.
- * Single block IO request is switched into array of scatterlists,
- * which are submitted to the crypto processing iterator.
- *
- * Input and output iterator initialization are different, since
- * in output case we can not encrypt data in-place and need a
- * temporary storage, which is then being sent to the remote peer.
- */
-static int dst_trans_iter_out(struct bio *bio, struct dst_crypto_engine *e,
-               int (*iterator) (struct dst_crypto_engine *e,
-                                 struct scatterlist *dst,
-                                 struct scatterlist *src))
-{
-       struct bio_vec *bv;
-       int err, i;
-
-       sg_init_table(e->src, bio->bi_vcnt);
-       sg_init_table(e->dst, bio->bi_vcnt);
-
-       bio_for_each_segment(bv, bio, i) {
-               sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset);
-               sg_set_page(&e->dst[i], e->pages[i], bv->bv_len, bv->bv_offset);
-
-               err = iterator(e, &e->dst[i], &e->src[i]);
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int dst_trans_iter_in(struct bio *bio, struct dst_crypto_engine *e,
-               int (*iterator) (struct dst_crypto_engine *e,
-                                 struct scatterlist *dst,
-                                 struct scatterlist *src))
-{
-       struct bio_vec *bv;
-       int err, i;
-
-       sg_init_table(e->src, bio->bi_vcnt);
-       sg_init_table(e->dst, bio->bi_vcnt);
-
-       bio_for_each_segment(bv, bio, i) {
-               sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset);
-               sg_set_page(&e->dst[i], bv->bv_page, bv->bv_len, bv->bv_offset);
-
-               err = iterator(e, &e->dst[i], &e->src[i]);
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int dst_crypt_iterator(struct dst_crypto_engine *e,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
-       struct ablkcipher_request *req = e->data;
-       u8 iv[32];
-
-       memset(iv, 0, sizeof(iv));
-
-       memcpy(iv, &e->iv, sizeof(e->iv));
-
-       return dst_crypto_process(req, sg_dst, sg_src, iv, e->enc, e->timeout);
-}
-
-static int dst_crypt(struct dst_crypto_engine *e, struct bio *bio)
-{
-       struct ablkcipher_request *req = e->data;
-
-       memset(req, 0, sizeof(struct ablkcipher_request));
-       ablkcipher_request_set_tfm(req, e->cipher);
-
-       if (e->enc)
-               return dst_trans_iter_out(bio, e, dst_crypt_iterator);
-       else
-               return dst_trans_iter_in(bio, e, dst_crypt_iterator);
-}
-
-static int dst_hash_iterator(struct dst_crypto_engine *e,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
-       return crypto_hash_update(e->data, sg_src, sg_src->length);
-}
-
-static int dst_hash(struct dst_crypto_engine *e, struct bio *bio, void *dst)
-{
-       struct hash_desc *desc = e->data;
-       int err;
-
-       desc->tfm = e->hash;
-       desc->flags = 0;
-
-       err = crypto_hash_init(desc);
-       if (err)
-               return err;
-
-       err = dst_trans_iter_in(bio, e, dst_hash_iterator);
-       if (err)
-               return err;
-
-       err = crypto_hash_final(desc, dst);
-       if (err)
-               return err;
-
-       return 0;
-}
-
-/*
- * Initialize/cleanup a crypto thread. The only thing it should
- * do is to allocate a pool of pages as temporary storage.
- * And to setup cipher and/or hash.
- */
-static void *dst_crypto_thread_init(void *data)
-{
-       struct dst_node *n = data;
-       struct dst_crypto_engine *e;
-       int err = -ENOMEM;
-
-       e = kzalloc(sizeof(struct dst_crypto_engine), GFP_KERNEL);
-       if (!e)
-               goto err_out_exit;
-       e->src = kcalloc(2 * n->max_pages, sizeof(struct scatterlist),
-                       GFP_KERNEL);
-       if (!e->src)
-               goto err_out_free;
-
-       e->dst = e->src + n->max_pages;
-
-       err = dst_crypto_engine_init(e, n);
-       if (err)
-               goto err_out_free_all;
-
-       return e;
-
-err_out_free_all:
-       kfree(e->src);
-err_out_free:
-       kfree(e);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-static void dst_crypto_thread_cleanup(void *private)
-{
-       struct dst_crypto_engine *e = private;
-
-       dst_crypto_engine_exit(e);
-       kfree(e->src);
-       kfree(e);
-}
-
-/*
- * Initialize crypto engine for given node: store keys, create pool
- * of threads, initialize each one.
- *
- * Each thread has unique ID, but 0 and 1 are reserved for receiving and
- * accepting threads (if export node), so IDs could start from 2, but starting
- * them from 10 allows easily understand what this thread is for.
- */
-int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl)
-{
-       void *key = (ctl + 1);
-       int err = -ENOMEM, i;
-       char name[32];
-
-       if (ctl->hash_keysize) {
-               n->hash_key = kmalloc(ctl->hash_keysize, GFP_KERNEL);
-               if (!n->hash_key)
-                       goto err_out_exit;
-               memcpy(n->hash_key, key, ctl->hash_keysize);
-       }
-
-       if (ctl->cipher_keysize) {
-               n->cipher_key = kmalloc(ctl->cipher_keysize, GFP_KERNEL);
-               if (!n->cipher_key)
-                       goto err_out_free_hash;
-               memcpy(n->cipher_key, key, ctl->cipher_keysize);
-       }
-       memcpy(&n->crypto, ctl, sizeof(struct dst_crypto_ctl));
-
-       for (i = 0; i < ctl->thread_num; ++i) {
-               snprintf(name, sizeof(name), "%s-crypto-%d", n->name, i);
-               /* Unique ids... */
-               err = thread_pool_add_worker(n->pool, name, i + 10,
-                       dst_crypto_thread_init, dst_crypto_thread_cleanup, n);
-               if (err)
-                       goto err_out_free_threads;
-       }
-
-       return 0;
-
-err_out_free_threads:
-       while (--i >= 0)
-               thread_pool_del_worker_id(n->pool, i+10);
-
-       if (ctl->cipher_keysize)
-               kfree(n->cipher_key);
-       ctl->cipher_keysize = 0;
-err_out_free_hash:
-       if (ctl->hash_keysize)
-               kfree(n->hash_key);
-       ctl->hash_keysize = 0;
-err_out_exit:
-       return err;
-}
-
-void dst_node_crypto_exit(struct dst_node *n)
-{
-       struct dst_crypto_ctl *ctl = &n->crypto;
-
-       if (ctl->cipher_algo[0] || ctl->hash_algo[0]) {
-               kfree(n->hash_key);
-               kfree(n->cipher_key);
-       }
-}
-
-/*
- * Thrad pool setup callback. Just stores a transaction in private data.
- */
-static int dst_trans_crypto_setup(void *crypto_engine, void *trans)
-{
-       struct dst_crypto_engine *e = crypto_engine;
-
-       e->private = trans;
-       return 0;
-}
-
-#if 0
-static void dst_dump_bio(struct bio *bio)
-{
-       u8 *p;
-       struct bio_vec *bv;
-       int i;
-
-       bio_for_each_segment(bv, bio, i) {
-               dprintk("%s: %llu/%u: size: %u, offset: %u, data: ",
-                               __func__, bio->bi_sector, bio->bi_size,
-                               bv->bv_len, bv->bv_offset);
-
-               p = kmap(bv->bv_page) + bv->bv_offset;
-               for (i = 0; i < bv->bv_len; ++i)
-                       printk(KERN_DEBUG "%02x ", p[i]);
-               kunmap(bv->bv_page);
-               printk("\n");
-       }
-}
-#endif
-
-/*
- * Encrypt/hash data and send it to the network.
- */
-static int dst_crypto_process_sending(struct dst_crypto_engine *e,
-               struct bio *bio, u8 *hash)
-{
-       int err;
-
-       if (e->cipher) {
-               err = dst_crypt(e, bio);
-               if (err)
-                       goto err_out_exit;
-       }
-
-       if (e->hash) {
-               err = dst_hash(e, bio, hash);
-               if (err)
-                       goto err_out_exit;
-
-#ifdef CONFIG_DST_DEBUG
-               {
-                       unsigned int i;
-
-                       /* dst_dump_bio(bio); */
-
-                       printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash: ",
-                               __func__, (u64)bio->bi_sector,
-                               bio->bi_size, bio_data_dir(bio));
-                       for (i = 0; i < crypto_hash_digestsize(e->hash); ++i)
-                                       printk("%02x ", hash[i]);
-                       printk("\n");
-               }
-#endif
-       }
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-/*
- * Check if received data is valid. Decipher if it is.
- */
-static int dst_crypto_process_receiving(struct dst_crypto_engine *e,
-               struct bio *bio, u8 *hash, u8 *recv_hash)
-{
-       int err;
-
-       if (e->hash) {
-               int mismatch;
-
-               err = dst_hash(e, bio, hash);
-               if (err)
-                       goto err_out_exit;
-
-               mismatch = !!memcmp(recv_hash, hash,
-                               crypto_hash_digestsize(e->hash));
-#ifdef CONFIG_DST_DEBUG
-               /* dst_dump_bio(bio); */
-
-               printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash mismatch: %d",
-                       __func__, (u64)bio->bi_sector, bio->bi_size,
-                       bio_data_dir(bio), mismatch);
-               if (mismatch) {
-                       unsigned int i;
-
-                       printk(", recv/calc: ");
-                       for (i = 0; i < crypto_hash_digestsize(e->hash); ++i)
-                               printk("%02x/%02x ", recv_hash[i], hash[i]);
-
-               }
-               printk("\n");
-#endif
-               err = -1;
-               if (mismatch)
-                       goto err_out_exit;
-       }
-
-       if (e->cipher) {
-               err = dst_crypt(e, bio);
-               if (err)
-                       goto err_out_exit;
-       }
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-/*
- * Thread pool callback to encrypt data and send it to the netowork.
- */
-static int dst_trans_crypto_action(void *crypto_engine, void *schedule_data)
-{
-       struct dst_crypto_engine *e = crypto_engine;
-       struct dst_trans *t = schedule_data;
-       struct bio *bio = t->bio;
-       int err;
-
-       dprintk("%s: t: %p, gen: %llu, cipher: %p, hash: %p.\n",
-                       __func__, t, t->gen, e->cipher, e->hash);
-
-       e->enc = t->enc;
-       e->iv = dst_gen_iv(t);
-
-       if (bio_data_dir(bio) == WRITE) {
-               err = dst_crypto_process_sending(e, bio, t->cmd.hash);
-               if (err)
-                       goto err_out_exit;
-
-               if (e->hash) {
-                       t->cmd.csize = crypto_hash_digestsize(e->hash);
-                       t->cmd.size += t->cmd.csize;
-               }
-
-               return dst_trans_send(t);
-       } else {
-               u8 *hash = e->data + e->size/2;
-
-               err = dst_crypto_process_receiving(e, bio, hash, t->cmd.hash);
-               if (err)
-                       goto err_out_exit;
-
-               dst_trans_remove(t);
-               dst_trans_put(t);
-       }
-
-       return 0;
-
-err_out_exit:
-       t->error = err;
-       dst_trans_put(t);
-       return err;
-}
-
-/*
- * Schedule crypto processing for given transaction.
- */
-int dst_trans_crypto(struct dst_trans *t)
-{
-       struct dst_node *n = t->n;
-       int err;
-
-       err = thread_pool_schedule(n->pool,
-               dst_trans_crypto_setup, dst_trans_crypto_action,
-               t, MAX_SCHEDULE_TIMEOUT);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       dst_trans_put(t);
-       return err;
-}
-
-/*
- * Crypto machinery for the export node.
- */
-static int dst_export_crypto_setup(void *crypto_engine, void *bio)
-{
-       struct dst_crypto_engine *e = crypto_engine;
-
-       e->private = bio;
-       return 0;
-}
-
-static int dst_export_crypto_action(void *crypto_engine, void *schedule_data)
-{
-       struct dst_crypto_engine *e = crypto_engine;
-       struct bio *bio = schedule_data;
-       struct dst_export_priv *p = bio->bi_private;
-       int err;
-
-       dprintk("%s: e: %p, data: %p, bio: %llu/%u, dir: %lu.\n",
-                       __func__, e, e->data, (u64)bio->bi_sector,
-                       bio->bi_size, bio_data_dir(bio));
-
-       e->enc = (bio_data_dir(bio) == READ);
-       e->iv = p->cmd.id;
-
-       if (bio_data_dir(bio) == WRITE) {
-               u8 *hash = e->data + e->size/2;
-
-               err = dst_crypto_process_receiving(e, bio, hash, p->cmd.hash);
-               if (err)
-                       goto err_out_exit;
-
-               generic_make_request(bio);
-       } else {
-               err = dst_crypto_process_sending(e, bio, p->cmd.hash);
-               if (err)
-                       goto err_out_exit;
-
-               if (e->hash) {
-                       p->cmd.csize = crypto_hash_digestsize(e->hash);
-                       p->cmd.size += p->cmd.csize;
-               }
-
-               err = dst_export_send_bio(bio);
-       }
-       return 0;
-
-err_out_exit:
-       bio_put(bio);
-       return err;
-}
-
-int dst_export_crypto(struct dst_node *n, struct bio *bio)
-{
-       int err;
-
-       err = thread_pool_schedule(n->pool,
-               dst_export_crypto_setup, dst_export_crypto_action,
-               bio, MAX_SCHEDULE_TIMEOUT);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       bio_put(bio);
-       return err;
-}
diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c
deleted file mode 100644 (file)
index c83ca7e..0000000
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * 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.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/buffer_head.h>
-#include <linux/connector.h>
-#include <linux/dst.h>
-#include <linux/device.h>
-#include <linux/jhash.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/namei.h>
-#include <linux/slab.h>
-#include <linux/socket.h>
-
-#include <linux/in.h>
-#include <linux/in6.h>
-
-#include <net/sock.h>
-
-static int dst_major;
-
-static DEFINE_MUTEX(dst_hash_lock);
-static struct list_head *dst_hashtable;
-static unsigned int dst_hashtable_size = 128;
-module_param(dst_hashtable_size, uint, 0644);
-
-static char dst_name[] = "Dementianting goldfish";
-
-static DEFINE_IDR(dst_index_idr);
-static struct cb_id cn_dst_id = { CN_DST_IDX, CN_DST_VAL };
-
-/*
- * DST sysfs tree for device called 'storage':
- *
- * /sys/bus/dst/devices/storage/
- * /sys/bus/dst/devices/storage/type : 192.168.4.80:1025
- * /sys/bus/dst/devices/storage/size : 800
- * /sys/bus/dst/devices/storage/name : storage
- */
-
-static int dst_dev_match(struct device *dev, struct device_driver *drv)
-{
-       return 1;
-}
-
-static struct bus_type dst_dev_bus_type = {
-       .name           = "dst",
-       .match          = &dst_dev_match,
-};
-
-static void dst_node_release(struct device *dev)
-{
-       struct dst_info *info = container_of(dev, struct dst_info, device);
-
-       kfree(info);
-}
-
-static struct device dst_node_dev = {
-       .bus            = &dst_dev_bus_type,
-       .release        = &dst_node_release
-};
-
-/*
- * Setting size of the node after it was changed.
- */
-static void dst_node_set_size(struct dst_node *n)
-{
-       struct block_device *bdev;
-
-       set_capacity(n->disk, n->size >> 9);
-
-       bdev = bdget_disk(n->disk, 0);
-       if (bdev) {
-               mutex_lock(&bdev->bd_inode->i_mutex);
-               i_size_write(bdev->bd_inode, n->size);
-               mutex_unlock(&bdev->bd_inode->i_mutex);
-               bdput(bdev);
-       }
-}
-
-/*
- * Distributed storage request processing function.
- */
-static int dst_request(struct request_queue *q, struct bio *bio)
-{
-       struct dst_node *n = q->queuedata;
-       int err = -EIO;
-
-       if (bio_empty_barrier(bio) && !blk_queue_discard(q)) {
-               /*
-                * This is a dirty^Wnice hack, but if we complete this
-                * operation with -EOPNOTSUPP like intended, XFS
-                * will stuck and freeze the machine. This may be
-                * not particulary XFS problem though, but it is the
-                * only FS which sends empty barrier at umount time
-                * I worked with.
-                *
-                * Empty barriers are not allowed anyway, see 51fd77bd9f512
-                * for example, although later it was changed to
-                * bio_rw_flagged(bio, BIO_RW_DISCARD) only, which does not
-                * work in this case.
-                */
-               /* err = -EOPNOTSUPP; */
-               err = 0;
-               goto end_io;
-       }
-
-       bio_get(bio);
-
-       return dst_process_bio(n, bio);
-
-end_io:
-       bio_endio(bio, err);
-       return err;
-}
-
-/*
- * Open/close callbacks for appropriate block device.
- */
-static int dst_bdev_open(struct block_device *bdev, fmode_t mode)
-{
-       struct dst_node *n = bdev->bd_disk->private_data;
-
-       dst_node_get(n);
-       return 0;
-}
-
-static int dst_bdev_release(struct gendisk *disk, fmode_t mode)
-{
-       struct dst_node *n = disk->private_data;
-
-       dst_node_put(n);
-       return 0;
-}
-
-static struct block_device_operations dst_blk_ops = {
-       .open           = dst_bdev_open,
-       .release        = dst_bdev_release,
-       .owner          = THIS_MODULE,
-};
-
-/*
- * Block layer binding - disk is created when array is fully configured
- * by userspace request.
- */
-static int dst_node_create_disk(struct dst_node *n)
-{
-       int err = -ENOMEM;
-       u32 index = 0;
-
-       n->queue = blk_init_queue(NULL, NULL);
-       if (!n->queue)
-               goto err_out_exit;
-
-       n->queue->queuedata = n;
-       blk_queue_make_request(n->queue, dst_request);
-       blk_queue_max_phys_segments(n->queue, n->max_pages);
-       blk_queue_max_hw_segments(n->queue, n->max_pages);
-
-       err = -ENOMEM;
-       n->disk = alloc_disk(1);
-       if (!n->disk)
-               goto err_out_free_queue;
-
-       if (!(n->state->permissions & DST_PERM_WRITE)) {
-               printk(KERN_INFO "DST node %s attached read-only.\n", n->name);
-               set_disk_ro(n->disk, 1);
-       }
-
-       if (!idr_pre_get(&dst_index_idr, GFP_KERNEL))
-               goto err_out_put;
-
-       mutex_lock(&dst_hash_lock);
-       err = idr_get_new(&dst_index_idr, NULL, &index);
-       mutex_unlock(&dst_hash_lock);
-       if (err)
-               goto err_out_put;
-
-       n->disk->major = dst_major;
-       n->disk->first_minor = index;
-       n->disk->fops = &dst_blk_ops;
-       n->disk->queue = n->queue;
-       n->disk->private_data = n;
-       snprintf(n->disk->disk_name, sizeof(n->disk->disk_name),
-                       "dst-%s", n->name);
-
-       return 0;
-
-err_out_put:
-       put_disk(n->disk);
-err_out_free_queue:
-       blk_cleanup_queue(n->queue);
-err_out_exit:
-       return err;
-}
-
-/*
- * Sysfs machinery: show device's size.
- */
-static ssize_t dst_show_size(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct dst_info *info = container_of(dev, struct dst_info, device);
-
-       return sprintf(buf, "%llu\n", info->size);
-}
-
-/*
- * Show local exported device.
- */
-static ssize_t dst_show_local(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct dst_info *info = container_of(dev, struct dst_info, device);
-
-       return sprintf(buf, "%s\n", info->local);
-}
-
-/*
- * Shows type of the remote node - device major/minor number
- * for local nodes and address (af_inet ipv4/ipv6 only) for remote nodes.
- */
-static ssize_t dst_show_type(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct dst_info *info = container_of(dev, struct dst_info, device);
-       int family = info->net.addr.sa_family;
-
-       if (family == AF_INET) {
-               struct sockaddr_in *sin = (struct sockaddr_in *)&info->net.addr;
-               return sprintf(buf, "%u.%u.%u.%u:%d\n",
-                       NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port));
-       } else if (family == AF_INET6) {
-               struct sockaddr_in6 *sin = (struct sockaddr_in6 *)
-                               &info->net.addr;
-               return sprintf(buf,
-                       "%pi6:%d\n",
-                       &sin->sin6_addr, ntohs(sin->sin6_port));
-       } else {
-               int i, sz = PAGE_SIZE - 2; /* 0 symbol and '\n' below */
-               int size, addrlen = info->net.addr.sa_data_len;
-               unsigned char *a = (unsigned char *)&info->net.addr.sa_data;
-               char *buf_orig = buf;
-
-               size = snprintf(buf, sz, "family: %d, addrlen: %u, addr: ",
-                               family, addrlen);
-               sz -= size;
-               buf += size;
-
-               for (i = 0; i < addrlen; ++i) {
-                       if (sz < 3)
-                               break;
-
-                       size = snprintf(buf, sz, "%02x ", a[i]);
-                       sz -= size;
-                       buf += size;
-               }
-               buf += sprintf(buf, "\n");
-
-               return buf - buf_orig;
-       }
-       return 0;
-}
-
-static struct device_attribute dst_node_attrs[] = {
-       __ATTR(size, 0444, dst_show_size, NULL),
-       __ATTR(type, 0444, dst_show_type, NULL),
-       __ATTR(local, 0444, dst_show_local, NULL),
-};
-
-static int dst_create_node_attributes(struct dst_node *n)
-{
-       int err, i;
-
-       for (i = 0; i < ARRAY_SIZE(dst_node_attrs); ++i) {
-               err = device_create_file(&n->info->device,
-                               &dst_node_attrs[i]);
-               if (err)
-                       goto err_out_remove_all;
-       }
-       return 0;
-
-err_out_remove_all:
-       while (--i >= 0)
-               device_remove_file(&n->info->device,
-                               &dst_node_attrs[i]);
-
-       return err;
-}
-
-static void dst_remove_node_attributes(struct dst_node *n)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(dst_node_attrs); ++i)
-               device_remove_file(&n->info->device,
-                               &dst_node_attrs[i]);
-}
-
-/*
- * Sysfs cleanup and initialization.
- * Shows number of useful parameters.
- */
-static void dst_node_sysfs_exit(struct dst_node *n)
-{
-       if (n->info) {
-               dst_remove_node_attributes(n);
-               device_unregister(&n->info->device);
-               n->info = NULL;
-       }
-}
-
-static int dst_node_sysfs_init(struct dst_node *n)
-{
-       int err;
-
-       n->info = kzalloc(sizeof(struct dst_info), GFP_KERNEL);
-       if (!n->info)
-               return -ENOMEM;
-
-       memcpy(&n->info->device, &dst_node_dev, sizeof(struct device));
-       n->info->size = n->size;
-
-       dev_set_name(&n->info->device, "dst-%s", n->name);
-       err = device_register(&n->info->device);
-       if (err) {
-               dprintk(KERN_ERR "Failed to register node '%s', err: %d.\n",
-                               n->name, err);
-               goto err_out_exit;
-       }
-
-       dst_create_node_attributes(n);
-
-       return 0;
-
-err_out_exit:
-       kfree(n->info);
-       n->info = NULL;
-       return err;
-}
-
-/*
- * DST node hash tables machinery.
- */
-static inline unsigned int dst_hash(char *str, unsigned int size)
-{
-       return jhash(str, size, 0) % dst_hashtable_size;
-}
-
-static void dst_node_remove(struct dst_node *n)
-{
-       mutex_lock(&dst_hash_lock);
-       list_del_init(&n->node_entry);
-       mutex_unlock(&dst_hash_lock);
-}
-
-static void dst_node_add(struct dst_node *n)
-{
-       unsigned hash = dst_hash(n->name, sizeof(n->name));
-
-       mutex_lock(&dst_hash_lock);
-       list_add_tail(&n->node_entry, &dst_hashtable[hash]);
-       mutex_unlock(&dst_hash_lock);
-}
-
-/*
- * Cleaning node when it is about to be freed.
- * There are still users of the socket though,
- * so connection cleanup should be protected.
- */
-static void dst_node_cleanup(struct dst_node *n)
-{
-       struct dst_state *st = n->state;
-
-       if (!st)
-               return;
-
-       if (n->queue) {
-               blk_cleanup_queue(n->queue);
-
-               mutex_lock(&dst_hash_lock);
-               idr_remove(&dst_index_idr, n->disk->first_minor);
-               mutex_unlock(&dst_hash_lock);
-
-               put_disk(n->disk);
-       }
-
-       if (n->bdev) {
-               sync_blockdev(n->bdev);
-               close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
-       }
-
-       dst_state_lock(st);
-       st->need_exit = 1;
-       dst_state_exit_connected(st);
-       dst_state_unlock(st);
-
-       wake_up(&st->thread_wait);
-
-       dst_state_put(st);
-       n->state = NULL;
-}
-
-/*
- * Free security attributes attached to given node.
- */
-static void dst_security_exit(struct dst_node *n)
-{
-       struct dst_secure *s, *tmp;
-
-       list_for_each_entry_safe(s, tmp, &n->security_list, sec_entry) {
-               list_del(&s->sec_entry);
-               kfree(s);
-       }
-}
-
-/*
- * Free node when there are no more users.
- * Actually node has to be freed on behalf od userspace process,
- * since there are number of threads, which are embedded in the
- * node, so they can not exit and free node from there, that is
- * why there is a wakeup if reference counter is not equal to zero.
- */
-void dst_node_put(struct dst_node *n)
-{
-       if (unlikely(!n))
-               return;
-
-       dprintk("%s: n: %p, refcnt: %d.\n",
-                       __func__, n, atomic_read(&n->refcnt));
-
-       if (atomic_dec_and_test(&n->refcnt)) {
-               dst_node_remove(n);
-               n->trans_scan_timeout = 0;
-               dst_node_cleanup(n);
-               thread_pool_destroy(n->pool);
-               dst_node_sysfs_exit(n);
-               dst_node_crypto_exit(n);
-               dst_security_exit(n);
-               dst_node_trans_exit(n);
-
-               kfree(n);
-
-               dprintk("%s: freed n: %p.\n", __func__, n);
-       } else {
-               wake_up(&n->wait);
-       }
-}
-
-/*
- * Setting up export device: lookup by the name, get its size
- * and setup listening socket, which will accept clients, which
- * will submit IO for given storage.
- */
-static int dst_setup_export(struct dst_node *n, struct dst_ctl *ctl,
-               struct dst_export_ctl *le)
-{
-       int err;
-
-       snprintf(n->info->local, sizeof(n->info->local), "%s", le->device);
-
-       n->bdev = open_bdev_exclusive(le->device, FMODE_READ|FMODE_WRITE, NULL);
-       if (IS_ERR(n->bdev))
-               return PTR_ERR(n->bdev);
-
-       if (n->size != 0)
-               n->size = min_t(loff_t, n->bdev->bd_inode->i_size, n->size);
-       else
-               n->size = n->bdev->bd_inode->i_size;
-
-       n->info->size = n->size;
-       err = dst_node_init_listened(n, le);
-       if (err)
-               goto err_out_cleanup;
-
-       return 0;
-
-err_out_cleanup:
-       close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
-       n->bdev = NULL;
-
-       return err;
-}
-
-/* Empty thread pool callbacks for the network processing threads. */
-static inline void *dst_thread_network_init(void *data)
-{
-       dprintk("%s: data: %p.\n", __func__, data);
-       return data;
-}
-
-static inline void dst_thread_network_cleanup(void *data)
-{
-       dprintk("%s: data: %p.\n", __func__, data);
-}
-
-/*
- * Allocate DST node and initialize some of its parameters.
- */
-static struct dst_node *dst_alloc_node(struct dst_ctl *ctl,
-               int (*start)(struct dst_node *),
-               int num)
-{
-       struct dst_node *n;
-       int err;
-
-       n = kzalloc(sizeof(struct dst_node), GFP_KERNEL);
-       if (!n)
-               return NULL;
-
-       INIT_LIST_HEAD(&n->node_entry);
-
-       INIT_LIST_HEAD(&n->security_list);
-       mutex_init(&n->security_lock);
-
-       init_waitqueue_head(&n->wait);
-
-       n->trans_scan_timeout = msecs_to_jiffies(ctl->trans_scan_timeout);
-       if (!n->trans_scan_timeout)
-               n->trans_scan_timeout = HZ;
-
-       n->trans_max_retries = ctl->trans_max_retries;
-       if (!n->trans_max_retries)
-               n->trans_max_retries = 10;
-
-       /*
-        * Pretty much arbitrary default numbers.
-        * 32 matches maximum number of pages in bio originated from ext3 (31).
-        */
-       n->max_pages = ctl->max_pages;
-       if (!n->max_pages)
-               n->max_pages = 32;
-
-       if (n->max_pages > 1024)
-               n->max_pages = 1024;
-
-       n->start = start;
-       n->size = ctl->size;
-
-       atomic_set(&n->refcnt, 1);
-       atomic_long_set(&n->gen, 0);
-       snprintf(n->name, sizeof(n->name), "%s", ctl->name);
-
-       err = dst_node_sysfs_init(n);
-       if (err)
-               goto err_out_free;
-
-       n->pool = thread_pool_create(num, n->name, dst_thread_network_init,
-                       dst_thread_network_cleanup, n);
-       if (IS_ERR(n->pool)) {
-               err = PTR_ERR(n->pool);
-               goto err_out_sysfs_exit;
-       }
-
-       dprintk("%s: n: %p, name: %s.\n", __func__, n, n->name);
-
-       return n;
-
-err_out_sysfs_exit:
-       dst_node_sysfs_exit(n);
-err_out_free:
-       kfree(n);
-       return NULL;
-}
-
-/*
- * Starting a node, connected to the remote server:
- * register block device and initialize transaction mechanism.
- * In revers order though.
- *
- * It will autonegotiate some parameters with the remote node
- * and update local if needed.
- *
- * Transaction initialization should be the last thing before
- * starting the node, since transaction should include not only
- * block IO, but also crypto related data (if any), which are
- * initialized separately.
- */
-static int dst_start_remote(struct dst_node *n)
-{
-       int err;
-
-       err = dst_node_trans_init(n, sizeof(struct dst_trans));
-       if (err)
-               return err;
-
-       err = dst_node_create_disk(n);
-       if (err)
-               return err;
-
-       dst_node_set_size(n);
-       add_disk(n->disk);
-
-       dprintk("DST: started remote node '%s', minor: %d.\n",
-                       n->name, n->disk->first_minor);
-
-       return 0;
-}
-
-/*
- * Adding remote node and initialize connection.
- */
-static int dst_add_remote(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       int err;
-       struct dst_network_ctl *rctl = data;
-
-       if (n)
-               return -EEXIST;
-
-       if (size != sizeof(struct dst_network_ctl))
-               return -EINVAL;
-
-       n = dst_alloc_node(ctl, dst_start_remote, 1);
-       if (!n)
-               return -ENOMEM;
-
-       memcpy(&n->info->net, rctl, sizeof(struct dst_network_ctl));
-       err = dst_node_init_connected(n, rctl);
-       if (err)
-               goto err_out_free;
-
-       dst_node_add(n);
-
-       return 0;
-
-err_out_free:
-       dst_node_put(n);
-       return err;
-}
-
-/*
- * Adding export node: initializing block device and listening socket.
- */
-static int dst_add_export(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       int err;
-       struct dst_export_ctl *le = data;
-
-       if (n)
-               return -EEXIST;
-
-       if (size != sizeof(struct dst_export_ctl))
-               return -EINVAL;
-
-       n = dst_alloc_node(ctl, dst_start_export, 2);
-       if (!n)
-               return -EINVAL;
-
-       err = dst_setup_export(n, ctl, le);
-       if (err)
-               goto err_out_free;
-
-       dst_node_add(n);
-
-       return 0;
-
-err_out_free:
-       dst_node_put(n);
-       return err;
-}
-
-static int dst_node_remove_unload(struct dst_node *n)
-{
-       printk(KERN_INFO "STOPPED name: '%s', size: %llu.\n",
-                       n->name, n->size);
-
-       if (n->disk)
-               del_gendisk(n->disk);
-
-       dst_node_remove(n);
-       dst_node_sysfs_exit(n);
-
-       /*
-        * This is not a hack. Really.
-        * Node's reference counter allows to implement fine grained
-        * node freeing, but since all transactions (which hold node's
-        * reference counter) are processed in the dedicated thread,
-        * it is possible that reference will hit zero in that thread,
-        * so we will not be able to exit thread and cleanup the node.
-        *
-        * So, we remove disk, so no new activity is possible, and
-        * wait until all pending transaction are completed (either
-        * in receiving thread or by timeout in workqueue), in this
-        * case reference counter will be less or equal to 2 (once set in
-        * dst_alloc_node() and then in connector message parser;
-        * or when we force module unloading, and connector message
-        * parser does not hold a reference, in this case reference
-        * counter will be equal to 1),
-        * and subsequent dst_node_put() calls will free the node.
-        */
-       dprintk("%s: going to sleep with %d refcnt.\n",
-                       __func__, atomic_read(&n->refcnt));
-       wait_event(n->wait, atomic_read(&n->refcnt) <= 2);
-
-       dst_node_put(n);
-       return 0;
-}
-
-/*
- * Remove node from the hash table.
- */
-static int dst_del_node(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       if (!n)
-               return -ENODEV;
-
-       return dst_node_remove_unload(n);
-}
-
-/*
- * Initialize crypto processing for given node.
- */
-static int dst_crypto_init(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       struct dst_crypto_ctl *crypto = data;
-
-       if (!n)
-               return -ENODEV;
-
-       if (size != sizeof(struct dst_crypto_ctl) + crypto->hash_keysize +
-                       crypto->cipher_keysize)
-               return -EINVAL;
-
-       if (n->trans_cache)
-               return -EEXIST;
-
-       return dst_node_crypto_init(n, crypto);
-}
-
-/*
- * Security attributes for given node.
- */
-static int dst_security_init(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       struct dst_secure *s;
-
-       if (!n)
-               return -ENODEV;
-
-       if (size != sizeof(struct dst_secure_user))
-               return -EINVAL;
-
-       s = kmalloc(sizeof(struct dst_secure), GFP_KERNEL);
-       if (!s)
-               return -ENOMEM;
-
-       memcpy(&s->sec, data, size);
-
-       mutex_lock(&n->security_lock);
-       list_add_tail(&s->sec_entry, &n->security_list);
-       mutex_unlock(&n->security_lock);
-
-       return 0;
-}
-
-/*
- * Kill'em all!
- */
-static int dst_start_node(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size)
-{
-       int err;
-
-       if (!n)
-               return -ENODEV;
-
-       if (n->trans_cache)
-               return 0;
-
-       err = n->start(n);
-       if (err)
-               return err;
-
-       printk(KERN_INFO "STARTED name: '%s', size: %llu.\n", n->name, n->size);
-       return 0;
-}
-
-typedef int (*dst_command_func)(struct dst_node *n, struct dst_ctl *ctl,
-               void *data, unsigned int size);
-
-/*
- * List of userspace commands.
- */
-static dst_command_func dst_commands[] = {
-       [DST_ADD_REMOTE] = &dst_add_remote,
-       [DST_ADD_EXPORT] = &dst_add_export,
-       [DST_DEL_NODE] = &dst_del_node,
-       [DST_CRYPTO] = &dst_crypto_init,
-       [DST_SECURITY] = &dst_security_init,
-       [DST_START] = &dst_start_node,
-};
-
-/*
- * Configuration parser.
- */
-static void cn_dst_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
-{
-       struct dst_ctl *ctl;
-       int err;
-       struct dst_ctl_ack ack;
-       struct dst_node *n = NULL, *tmp;
-       unsigned int hash;
-
-       if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) {
-               err = -EPERM;
-               goto out;
-       }
-
-       if (msg->len < sizeof(struct dst_ctl)) {
-               err = -EBADMSG;
-               goto out;
-       }
-
-       ctl = (struct dst_ctl *)msg->data;
-
-       if (ctl->cmd >= DST_CMD_MAX) {
-               err = -EINVAL;
-               goto out;
-       }
-       hash = dst_hash(ctl->name, sizeof(ctl->name));
-
-       mutex_lock(&dst_hash_lock);
-       list_for_each_entry(tmp, &dst_hashtable[hash], node_entry) {
-               if (!memcmp(tmp->name, ctl->name, sizeof(tmp->name))) {
-                       n = tmp;
-                       dst_node_get(n);
-                       break;
-               }
-       }
-       mutex_unlock(&dst_hash_lock);
-
-       err = dst_commands[ctl->cmd](n, ctl, msg->data + sizeof(struct dst_ctl),
-                       msg->len - sizeof(struct dst_ctl));
-
-       dst_node_put(n);
-out:
-       memcpy(&ack.msg, msg, sizeof(struct cn_msg));
-
-       ack.msg.ack = msg->ack + 1;
-       ack.msg.len = sizeof(struct dst_ctl_ack) - sizeof(struct cn_msg);
-
-       ack.error = err;
-
-       cn_netlink_send(&ack.msg, 0, GFP_KERNEL);
-}
-
-/*
- * Global initialization: sysfs, hash table, block device registration,
- * connector and various caches.
- */
-static int __init dst_sysfs_init(void)
-{
-       return bus_register(&dst_dev_bus_type);
-}
-
-static void dst_sysfs_exit(void)
-{
-       bus_unregister(&dst_dev_bus_type);
-}
-
-static int __init dst_hashtable_init(void)
-{
-       unsigned int i;
-
-       dst_hashtable = kcalloc(dst_hashtable_size, sizeof(struct list_head),
-                       GFP_KERNEL);
-       if (!dst_hashtable)
-               return -ENOMEM;
-
-       for (i = 0; i < dst_hashtable_size; ++i)
-               INIT_LIST_HEAD(&dst_hashtable[i]);
-
-       return 0;
-}
-
-static void dst_hashtable_exit(void)
-{
-       unsigned int i;
-       struct dst_node *n, *tmp;
-
-       for (i = 0; i < dst_hashtable_size; ++i) {
-               list_for_each_entry_safe(n, tmp, &dst_hashtable[i], node_entry) {
-                       dst_node_remove_unload(n);
-               }
-       }
-
-       kfree(dst_hashtable);
-}
-
-static int __init dst_sys_init(void)
-{
-       int err = -ENOMEM;
-
-       err = dst_hashtable_init();
-       if (err)
-               goto err_out_exit;
-
-       err = dst_export_init();
-       if (err)
-               goto err_out_hashtable_exit;
-
-       err = register_blkdev(dst_major, DST_NAME);
-       if (err < 0)
-               goto err_out_export_exit;
-       if (err)
-               dst_major = err;
-
-       err = dst_sysfs_init();
-       if (err)
-               goto err_out_unregister;
-
-       err = cn_add_callback(&cn_dst_id, "DST", cn_dst_callback);
-       if (err)
-               goto err_out_sysfs_exit;
-
-       printk(KERN_INFO "Distributed storage, '%s' release.\n", dst_name);
-
-       return 0;
-
-err_out_sysfs_exit:
-       dst_sysfs_exit();
-err_out_unregister:
-       unregister_blkdev(dst_major, DST_NAME);
-err_out_export_exit:
-       dst_export_exit();
-err_out_hashtable_exit:
-       dst_hashtable_exit();
-err_out_exit:
-       return err;
-}
-
-static void __exit dst_sys_exit(void)
-{
-       cn_del_callback(&cn_dst_id);
-       unregister_blkdev(dst_major, DST_NAME);
-       dst_hashtable_exit();
-       dst_sysfs_exit();
-       dst_export_exit();
-}
-
-module_init(dst_sys_init);
-module_exit(dst_sys_exit);
-
-MODULE_DESCRIPTION("Distributed storage");
-MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/dst/export.c b/drivers/staging/dst/export.c
deleted file mode 100644 (file)
index c324230..0000000
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * 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.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/dst.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/socket.h>
-
-#include <net/sock.h>
-
-/*
- * Export bioset is used for server block IO requests.
- */
-static struct bio_set *dst_bio_set;
-
-int __init dst_export_init(void)
-{
-       int err = -ENOMEM;
-
-       dst_bio_set = bioset_create(32, sizeof(struct dst_export_priv));
-       if (!dst_bio_set)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-void dst_export_exit(void)
-{
-       bioset_free(dst_bio_set);
-}
-
-/*
- * When client connects and autonegotiates with the server node,
- * its permissions are checked in a security attributes and sent
- * back.
- */
-static unsigned int dst_check_permissions(struct dst_state *main,
-               struct dst_state *st)
-{
-       struct dst_node *n = main->node;
-       struct dst_secure *sentry;
-       struct dst_secure_user *s;
-       struct saddr *sa = &st->ctl.addr;
-       unsigned int perm = 0;
-
-       mutex_lock(&n->security_lock);
-       list_for_each_entry(sentry, &n->security_list, sec_entry) {
-               s = &sentry->sec;
-
-               if (s->addr.sa_family != sa->sa_family)
-                       continue;
-
-               if (s->addr.sa_data_len != sa->sa_data_len)
-                       continue;
-
-               /*
-                * This '2' below is a port field. This may be very wrong to do
-                * in atalk for example though. If there will be any need
-                * to extent protocol to something else, I can create
-                * per-family helpers and use them instead of this memcmp.
-                */
-               if (memcmp(s->addr.sa_data + 2, sa->sa_data + 2,
-                                       sa->sa_data_len - 2))
-                       continue;
-
-               perm = s->permissions;
-       }
-       mutex_unlock(&n->security_lock);
-
-       return perm;
-}
-
-/*
- * Accept new client: allocate appropriate network state and check permissions.
- */
-static struct dst_state *dst_accept_client(struct dst_state *st)
-{
-       unsigned int revents = 0;
-       unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP;
-       unsigned int mask = err_mask | POLLIN;
-       struct dst_node *n = st->node;
-       int err = 0;
-       struct socket *sock = NULL;
-       struct dst_state *new;
-
-       while (!err && !sock) {
-               revents = dst_state_poll(st);
-
-               if (!(revents & mask)) {
-                       DEFINE_WAIT(wait);
-
-                       for (;;) {
-                               prepare_to_wait(&st->thread_wait,
-                                               &wait, TASK_INTERRUPTIBLE);
-                               if (!n->trans_scan_timeout || st->need_exit)
-                                       break;
-
-                               revents = dst_state_poll(st);
-
-                               if (revents & mask)
-                                       break;
-
-                               if (signal_pending(current))
-                                       break;
-
-                               /*
-                                * Magic HZ? Polling check above is not safe in
-                                * all cases (like socket reset in BH context),
-                                * so it is simpler just to postpone it to the
-                                * process context instead of implementing
-                                * special locking there.
-                                */
-                               schedule_timeout(HZ);
-                       }
-                       finish_wait(&st->thread_wait, &wait);
-               }
-
-               err = -ECONNRESET;
-               dst_state_lock(st);
-
-               dprintk("%s: st: %p, revents: %x [err: %d, in: %d].\n",
-                       __func__, st, revents, revents & err_mask,
-                       revents & POLLIN);
-
-               if (revents & err_mask) {
-                       dprintk("%s: revents: %x, socket: %p, err: %d.\n",
-                                       __func__, revents, st->socket, err);
-                       err = -ECONNRESET;
-               }
-
-               if (!n->trans_scan_timeout || st->need_exit)
-                       err = -ENODEV;
-
-               if (st->socket && (revents & POLLIN))
-                       err = kernel_accept(st->socket, &sock, 0);
-
-               dst_state_unlock(st);
-       }
-
-       if (err)
-               goto err_out_exit;
-
-       new = dst_state_alloc(st->node);
-       if (IS_ERR(new)) {
-               err = -ENOMEM;
-               goto err_out_release;
-       }
-       new->socket = sock;
-
-       new->ctl.addr.sa_data_len = sizeof(struct sockaddr);
-       err = kernel_getpeername(sock, (struct sockaddr *)&new->ctl.addr,
-                       (int *)&new->ctl.addr.sa_data_len);
-       if (err)
-               goto err_out_put;
-
-       new->permissions = dst_check_permissions(st, new);
-       if (new->permissions == 0) {
-               err = -EPERM;
-               dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr,
-                               "Client is not allowed to connect");
-               goto err_out_put;
-       }
-
-       err = dst_poll_init(new);
-       if (err)
-               goto err_out_put;
-
-       dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr,
-                       "Connected client");
-
-       return new;
-
-err_out_put:
-       dst_state_put(new);
-err_out_release:
-       sock_release(sock);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-/*
- * Each server's block request sometime finishes.
- * Usually it happens in hard irq context of the appropriate controller,
- * so to play good with all cases we just queue BIO into the queue
- * and wake up processing thread, which gets completed request and
- * send (encrypting if needed) it back to the client (if it was a read
- * request), or sends back reply that writing successfully completed.
- */
-static int dst_export_process_request_queue(struct dst_state *st)
-{
-       unsigned long flags;
-       struct dst_export_priv *p = NULL;
-       struct bio *bio;
-       int err = 0;
-
-       while (!list_empty(&st->request_list)) {
-               spin_lock_irqsave(&st->request_lock, flags);
-               if (!list_empty(&st->request_list)) {
-                       p = list_first_entry(&st->request_list,
-                               struct dst_export_priv, request_entry);
-                       list_del(&p->request_entry);
-               }
-               spin_unlock_irqrestore(&st->request_lock, flags);
-
-               if (!p)
-                       break;
-
-               bio = p->bio;
-
-               if (dst_need_crypto(st->node) && (bio_data_dir(bio) == READ))
-                       err = dst_export_crypto(st->node, bio);
-               else
-                       err = dst_export_send_bio(bio);
-
-               if (err)
-                       break;
-       }
-
-       return err;
-}
-
-/*
- * Cleanup export state.
- * It has to wait until all requests are finished,
- * and then free them all.
- */
-static void dst_state_cleanup_export(struct dst_state *st)
-{
-       struct dst_export_priv *p;
-       unsigned long flags;
-
-       /*
-        * This loop waits for all pending bios to be completed and freed.
-        */
-       while (atomic_read(&st->refcnt) > 1) {
-               dprintk("%s: st: %p, refcnt: %d, list_empty: %d.\n",
-                               __func__, st, atomic_read(&st->refcnt),
-                               list_empty(&st->request_list));
-               wait_event_timeout(st->thread_wait,
-                               (atomic_read(&st->refcnt) == 1) ||
-                               !list_empty(&st->request_list),
-                               HZ/2);
-
-               while (!list_empty(&st->request_list)) {
-                       p = NULL;
-                       spin_lock_irqsave(&st->request_lock, flags);
-                       if (!list_empty(&st->request_list)) {
-                               p = list_first_entry(&st->request_list,
-                                       struct dst_export_priv, request_entry);
-                               list_del(&p->request_entry);
-                       }
-                       spin_unlock_irqrestore(&st->request_lock, flags);
-
-                       if (p)
-                               bio_put(p->bio);
-
-                       dprintk("%s: st: %p, refcnt: %d, list_empty: %d, p: "
-                               "%p.\n", __func__, st, atomic_read(&st->refcnt),
-                               list_empty(&st->request_list), p);
-               }
-       }
-
-       dst_state_put(st);
-}
-
-/*
- * Client accepting thread.
- * Not only accepts new connection, but also schedules receiving thread
- * and performs request completion described above.
- */
-static int dst_accept(void *init_data, void *schedule_data)
-{
-       struct dst_state *main_st = schedule_data;
-       struct dst_node *n = init_data;
-       struct dst_state *st;
-       int err;
-
-       while (n->trans_scan_timeout && !main_st->need_exit) {
-               dprintk("%s: main_st: %p, n: %p.\n", __func__, main_st, n);
-               st = dst_accept_client(main_st);
-               if (IS_ERR(st))
-                       continue;
-
-               err = dst_state_schedule_receiver(st);
-               if (!err) {
-                       while (n->trans_scan_timeout) {
-                               err = wait_event_interruptible_timeout(st->thread_wait,
-                                       !list_empty(&st->request_list) ||
-                                       !n->trans_scan_timeout ||
-                                       st->need_exit,
-                                       HZ);
-
-                               if (!n->trans_scan_timeout || st->need_exit)
-                                       break;
-
-                               if (list_empty(&st->request_list))
-                                       continue;
-
-                               err = dst_export_process_request_queue(st);
-                               if (err)
-                                       break;
-                       }
-
-                       st->need_exit = 1;
-                       wake_up(&st->thread_wait);
-               }
-
-               dst_state_cleanup_export(st);
-       }
-
-       dprintk("%s: freeing listening socket st: %p.\n", __func__, main_st);
-
-       dst_state_lock(main_st);
-       dst_poll_exit(main_st);
-       dst_state_socket_release(main_st);
-       dst_state_unlock(main_st);
-       dst_state_put(main_st);
-       dprintk("%s: freed listening socket st: %p.\n", __func__, main_st);
-
-       return 0;
-}
-
-int dst_start_export(struct dst_node *n)
-{
-       if (list_empty(&n->security_list)) {
-               printk(KERN_ERR "You are trying to export node '%s' "
-                               "without security attributes.\nNo clients will "
-                               "be allowed to connect. Exiting.\n", n->name);
-               return -EINVAL;
-       }
-       return dst_node_trans_init(n, sizeof(struct dst_export_priv));
-}
-
-/*
- * Initialize listening state and schedule accepting thread.
- */
-int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le)
-{
-       struct dst_state *st;
-       int err = -ENOMEM;
-       struct dst_network_ctl *ctl = &le->ctl;
-
-       memcpy(&n->info->net, ctl, sizeof(struct dst_network_ctl));
-
-       st = dst_state_alloc(n);
-       if (IS_ERR(st)) {
-               err = PTR_ERR(st);
-               goto err_out_exit;
-       }
-       memcpy(&st->ctl, ctl, sizeof(struct dst_network_ctl));
-
-       err = dst_state_socket_create(st);
-       if (err)
-               goto err_out_put;
-
-       st->socket->sk->sk_reuse = 1;
-
-       err = kernel_bind(st->socket, (struct sockaddr *)&ctl->addr,
-                       ctl->addr.sa_data_len);
-       if (err)
-               goto err_out_socket_release;
-
-       err = kernel_listen(st->socket, 1024);
-       if (err)
-               goto err_out_socket_release;
-       n->state = st;
-
-       err = dst_poll_init(st);
-       if (err)
-               goto err_out_socket_release;
-
-       dst_state_get(st);
-
-       err = thread_pool_schedule(n->pool, dst_thread_setup,
-                       dst_accept, st, MAX_SCHEDULE_TIMEOUT);
-       if (err)
-               goto err_out_poll_exit;
-
-       return 0;
-
-err_out_poll_exit:
-       dst_poll_exit(st);
-err_out_socket_release:
-       dst_state_socket_release(st);
-err_out_put:
-       dst_state_put(st);
-err_out_exit:
-       n->state = NULL;
-       return err;
-}
-
-/*
- * Free bio and related private data.
- * Also drop a reference counter for appropriate state,
- * which waits when there are no more block IOs in-flight.
- */
-static void dst_bio_destructor(struct bio *bio)
-{
-       struct bio_vec *bv;
-       struct dst_export_priv *priv = bio->bi_private;
-       int i;
-
-       bio_for_each_segment(bv, bio, i) {
-               if (!bv->bv_page)
-                       break;
-
-               __free_page(bv->bv_page);
-       }
-
-       if (priv)
-               dst_state_put(priv->state);
-       bio_free(bio, dst_bio_set);
-}
-
-/*
- * Block IO completion. Queue request to be sent back to
- * the client (or just confirmation).
- */
-static void dst_bio_end_io(struct bio *bio, int err)
-{
-       struct dst_export_priv *p = bio->bi_private;
-       struct dst_state *st = p->state;
-       unsigned long flags;
-
-       spin_lock_irqsave(&st->request_lock, flags);
-       list_add_tail(&p->request_entry, &st->request_list);
-       spin_unlock_irqrestore(&st->request_lock, flags);
-
-       wake_up(&st->thread_wait);
-}
-
-/*
- * Allocate read request for the server.
- */
-static int dst_export_read_request(struct bio *bio, unsigned int total_size)
-{
-       unsigned int size;
-       struct page *page;
-       int err;
-
-       while (total_size) {
-               err = -ENOMEM;
-               page = alloc_page(GFP_KERNEL);
-               if (!page)
-                       goto err_out_exit;
-
-               size = min_t(unsigned int, PAGE_SIZE, total_size);
-
-               err = bio_add_page(bio, page, size, 0);
-               dprintk("%s: bio: %llu/%u, size: %u, err: %d.\n",
-                               __func__, (u64)bio->bi_sector, bio->bi_size,
-                               size, err);
-               if (err <= 0)
-                       goto err_out_free_page;
-
-               total_size -= size;
-       }
-
-       return 0;
-
-err_out_free_page:
-       __free_page(page);
-err_out_exit:
-       return err;
-}
-
-/*
- * Allocate write request for the server.
- * Should not only get pages, but also read data from the network.
- */
-static int dst_export_write_request(struct dst_state *st,
-               struct bio *bio, unsigned int total_size)
-{
-       unsigned int size;
-       struct page *page;
-       void *data;
-       int err;
-
-       while (total_size) {
-               err = -ENOMEM;
-               page = alloc_page(GFP_KERNEL);
-               if (!page)
-                       goto err_out_exit;
-
-               data = kmap(page);
-               if (!data)
-                       goto err_out_free_page;
-
-               size = min_t(unsigned int, PAGE_SIZE, total_size);
-
-               err = dst_data_recv(st, data, size);
-               if (err)
-                       goto err_out_unmap_page;
-
-               err = bio_add_page(bio, page, size, 0);
-               if (err <= 0)
-                       goto err_out_unmap_page;
-
-               kunmap(page);
-
-               total_size -= size;
-       }
-
-       return 0;
-
-err_out_unmap_page:
-       kunmap(page);
-err_out_free_page:
-       __free_page(page);
-err_out_exit:
-       return err;
-}
-
-/*
- * Groovy, we've gotten an IO request from the client.
- * Allocate BIO from the bioset, private data from the mempool
- * and lots of pages for IO.
- */
-int dst_process_io(struct dst_state *st)
-{
-       struct dst_node *n = st->node;
-       struct dst_cmd *cmd = st->data;
-       struct bio *bio;
-       struct dst_export_priv *priv;
-       int err = -ENOMEM;
-
-       if (unlikely(!n->bdev)) {
-               err = -EINVAL;
-               goto err_out_exit;
-       }
-
-       bio = bio_alloc_bioset(GFP_KERNEL,
-                       PAGE_ALIGN(cmd->size) >> PAGE_SHIFT,
-                       dst_bio_set);
-       if (!bio)
-               goto err_out_exit;
-
-       priv = (struct dst_export_priv *)(((void *)bio) -
-                       sizeof (struct dst_export_priv));
-
-       priv->state = dst_state_get(st);
-       priv->bio = bio;
-
-       bio->bi_private = priv;
-       bio->bi_end_io = dst_bio_end_io;
-       bio->bi_destructor = dst_bio_destructor;
-       bio->bi_bdev = n->bdev;
-
-       /*
-        * Server side is only interested in two low bits:
-        * uptodate (set by itself actually) and rw block
-        */
-       bio->bi_flags |= cmd->flags & 3;
-
-       bio->bi_rw = cmd->rw;
-       bio->bi_size = 0;
-       bio->bi_sector = cmd->sector;
-
-       dst_bio_to_cmd(bio, &priv->cmd, DST_IO_RESPONSE, cmd->id);
-
-       priv->cmd.flags = 0;
-       priv->cmd.size = cmd->size;
-
-       if (bio_data_dir(bio) == WRITE) {
-               err = dst_recv_cdata(st, priv->cmd.hash);
-               if (err)
-                       goto err_out_free;
-
-               err = dst_export_write_request(st, bio, cmd->size);
-               if (err)
-                       goto err_out_free;
-
-               if (dst_need_crypto(n))
-                       return dst_export_crypto(n, bio);
-       } else {
-               err = dst_export_read_request(bio, cmd->size);
-               if (err)
-                       goto err_out_free;
-       }
-
-       dprintk("%s: bio: %llu/%u, rw: %lu, dir: %lu, flags: %lx, phys: %d.\n",
-                       __func__, (u64)bio->bi_sector, bio->bi_size,
-                       bio->bi_rw, bio_data_dir(bio),
-                       bio->bi_flags, bio->bi_phys_segments);
-
-       generic_make_request(bio);
-
-       return 0;
-
-err_out_free:
-       bio_put(bio);
-err_out_exit:
-       return err;
-}
-
-/*
- * Ok, block IO is ready, let's send it back to the client...
- */
-int dst_export_send_bio(struct bio *bio)
-{
-       struct dst_export_priv *p = bio->bi_private;
-       struct dst_state *st = p->state;
-       struct dst_cmd *cmd = &p->cmd;
-       int err;
-
-       dprintk("%s: id: %llu, bio: %llu/%u, csize: %u, flags: %lu, rw: %lu.\n",
-                       __func__, cmd->id, (u64)bio->bi_sector, bio->bi_size,
-                       cmd->csize, bio->bi_flags, bio->bi_rw);
-
-       dst_convert_cmd(cmd);
-
-       dst_state_lock(st);
-       if (!st->socket) {
-               err = -ECONNRESET;
-               goto err_out_unlock;
-       }
-
-       if (bio_data_dir(bio) == WRITE) {
-               /* ... or just confirmation that writing has completed. */
-               cmd->size = cmd->csize = 0;
-               err = dst_data_send_header(st->socket, cmd,
-                               sizeof(struct dst_cmd), 0);
-               if (err)
-                       goto err_out_unlock;
-       } else {
-               err = dst_send_bio(st, cmd, bio);
-               if (err)
-                       goto err_out_unlock;
-       }
-
-       dst_state_unlock(st);
-
-       bio_put(bio);
-       return 0;
-
-err_out_unlock:
-       dst_state_unlock(st);
-
-       bio_put(bio);
-       return err;
-}
diff --git a/drivers/staging/dst/state.c b/drivers/staging/dst/state.c
deleted file mode 100644 (file)
index 02a05e6..0000000
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * 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.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/buffer_head.h>
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/connector.h>
-#include <linux/dst.h>
-#include <linux/device.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/socket.h>
-#include <linux/slab.h>
-
-#include <net/sock.h>
-
-/*
- * Polling machinery.
- */
-
-struct dst_poll_helper {
-       poll_table              pt;
-       struct dst_state        *st;
-};
-
-static int dst_queue_wake(wait_queue_t *wait, unsigned mode,
-               int sync, void *key)
-{
-       struct dst_state *st = container_of(wait, struct dst_state, wait);
-
-       wake_up(&st->thread_wait);
-       return 1;
-}
-
-static void dst_queue_func(struct file *file, wait_queue_head_t *whead,
-                                poll_table *pt)
-{
-       struct dst_state *st = container_of(pt, struct dst_poll_helper, pt)->st;
-
-       st->whead = whead;
-       init_waitqueue_func_entry(&st->wait, dst_queue_wake);
-       add_wait_queue(whead, &st->wait);
-}
-
-void dst_poll_exit(struct dst_state *st)
-{
-       if (st->whead) {
-               remove_wait_queue(st->whead, &st->wait);
-               st->whead = NULL;
-       }
-}
-
-int dst_poll_init(struct dst_state *st)
-{
-       struct dst_poll_helper ph;
-
-       ph.st = st;
-       init_poll_funcptr(&ph.pt, &dst_queue_func);
-
-       st->socket->ops->poll(NULL, st->socket, &ph.pt);
-       return 0;
-}
-
-/*
- * Header receiving function - may block.
- */
-static int dst_data_recv_header(struct socket *sock,
-               void *data, unsigned int size, int block)
-{
-       struct msghdr msg;
-       struct kvec iov;
-       int err;
-
-       iov.iov_base = data;
-       iov.iov_len = size;
-
-       msg.msg_iov = (struct iovec *)&iov;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = (block) ? MSG_WAITALL : MSG_DONTWAIT;
-
-       err = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len,
-                       msg.msg_flags);
-       if (err != size)
-               return -1;
-
-       return 0;
-}
-
-/*
- * Header sending function - may block.
- */
-int dst_data_send_header(struct socket *sock,
-               void *data, unsigned int size, int more)
-{
-       struct msghdr msg;
-       struct kvec iov;
-       int err;
-
-       iov.iov_base = data;
-       iov.iov_len = size;
-
-       msg.msg_iov = (struct iovec *)&iov;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_WAITALL | (more ? MSG_MORE : 0);
-
-       err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
-       if (err != size) {
-               dprintk("%s: size: %u, more: %d, err: %d.\n",
-                               __func__, size, more, err);
-               return -1;
-       }
-
-       return 0;
-}
-
-/*
- * Block autoconfiguration: request size of the storage and permissions.
- */
-static int dst_request_remote_config(struct dst_state *st)
-{
-       struct dst_node *n = st->node;
-       int err = -EINVAL;
-       struct dst_cmd *cmd = st->data;
-
-       memset(cmd, 0, sizeof(struct dst_cmd));
-       cmd->cmd = DST_CFG;
-
-       dst_convert_cmd(cmd);
-
-       err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0);
-       if (err)
-               goto out;
-
-       err = dst_data_recv_header(st->socket, cmd, sizeof(struct dst_cmd), 1);
-       if (err)
-               goto out;
-
-       dst_convert_cmd(cmd);
-
-       if (cmd->cmd != DST_CFG) {
-               err = -EINVAL;
-               dprintk("%s: checking result: cmd: %d, size reported: %llu.\n",
-                       __func__, cmd->cmd, cmd->sector);
-               goto out;
-       }
-
-       if (n->size != 0)
-               n->size = min_t(loff_t, n->size, cmd->sector);
-       else
-               n->size = cmd->sector;
-
-       n->info->size = n->size;
-       st->permissions = cmd->rw;
-
-out:
-       dprintk("%s: n: %p, err: %d, size: %llu, permission: %x.\n",
-                       __func__, n, err, n->size, st->permissions);
-       return err;
-}
-
-/*
- * Socket machinery.
- */
-
-#define DST_DEFAULT_TIMEO      20000
-
-int dst_state_socket_create(struct dst_state *st)
-{
-       int err;
-       struct socket *sock;
-       struct dst_network_ctl *ctl = &st->ctl;
-
-       err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &sock);
-       if (err < 0)
-               return err;
-
-       sock->sk->sk_sndtimeo = sock->sk->sk_rcvtimeo =
-               msecs_to_jiffies(DST_DEFAULT_TIMEO);
-       sock->sk->sk_allocation = GFP_NOIO;
-
-       st->socket = st->read_socket = sock;
-       return 0;
-}
-
-void dst_state_socket_release(struct dst_state *st)
-{
-       dprintk("%s: st: %p, socket: %p, n: %p.\n",
-                       __func__, st, st->socket, st->node);
-       if (st->socket) {
-               sock_release(st->socket);
-               st->socket = NULL;
-               st->read_socket = NULL;
-       }
-}
-
-void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str)
-{
-       if (sk->ops->family == AF_INET) {
-               struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-               printk(KERN_INFO "%s %u.%u.%u.%u:%d.\n", str,
-                       NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port));
-       } else if (sk->ops->family == AF_INET6) {
-               struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa;
-               printk(KERN_INFO "%s %pi6:%d",
-                       str, &sin->sin6_addr, ntohs(sin->sin6_port));
-       }
-}
-
-void dst_state_exit_connected(struct dst_state *st)
-{
-       if (st->socket) {
-               dst_poll_exit(st);
-               st->socket->ops->shutdown(st->socket, 2);
-
-               dst_dump_addr(st->socket, (struct sockaddr *)&st->ctl.addr,
-                               "Disconnected peer");
-               dst_state_socket_release(st);
-       }
-}
-
-static int dst_state_init_connected(struct dst_state *st)
-{
-       int err;
-       struct dst_network_ctl *ctl = &st->ctl;
-
-       err = dst_state_socket_create(st);
-       if (err)
-               goto err_out_exit;
-
-       err = kernel_connect(st->socket, (struct sockaddr *)&st->ctl.addr,
-                       st->ctl.addr.sa_data_len, 0);
-       if (err)
-               goto err_out_release;
-
-       err = dst_poll_init(st);
-       if (err)
-               goto err_out_release;
-
-       dst_dump_addr(st->socket, (struct sockaddr *)&ctl->addr,
-                       "Connected to peer");
-
-       return 0;
-
-err_out_release:
-       dst_state_socket_release(st);
-err_out_exit:
-       return err;
-}
-
-/*
- * State reset is used to reconnect to the remote peer.
- * May fail, but who cares, we will try again later.
- */
-static inline void dst_state_reset_nolock(struct dst_state *st)
-{
-       dst_state_exit_connected(st);
-       dst_state_init_connected(st);
-}
-
-static inline void dst_state_reset(struct dst_state *st)
-{
-       dst_state_lock(st);
-       dst_state_reset_nolock(st);
-       dst_state_unlock(st);
-}
-
-/*
- * Basic network sending/receiving functions.
- * Blocked mode is used.
- */
-static int dst_data_recv_raw(struct dst_state *st, void *buf, u64 size)
-{
-       struct msghdr msg;
-       struct kvec iov;
-       int err;
-
-       BUG_ON(!size);
-
-       iov.iov_base = buf;
-       iov.iov_len = size;
-
-       msg.msg_iov = (struct iovec *)&iov;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_DONTWAIT;
-
-       err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len,
-                       msg.msg_flags);
-       if (err <= 0) {
-               dprintk("%s: failed to recv data: size: %llu, err: %d.\n",
-                               __func__, size, err);
-               if (err == 0)
-                       err = -ECONNRESET;
-
-               dst_state_exit_connected(st);
-       }
-
-       return err;
-}
-
-/*
- * Ping command to early detect failed nodes.
- */
-static int dst_send_ping(struct dst_state *st)
-{
-       struct dst_cmd *cmd = st->data;
-       int err = -ECONNRESET;
-
-       dst_state_lock(st);
-       if (st->socket) {
-               memset(cmd, 0, sizeof(struct dst_cmd));
-
-               cmd->cmd = __cpu_to_be32(DST_PING);
-
-               err = dst_data_send_header(st->socket, cmd,
-                               sizeof(struct dst_cmd), 0);
-       }
-       dprintk("%s: st: %p, socket: %p, err: %d.\n", __func__,
-                       st, st->socket, err);
-       dst_state_unlock(st);
-
-       return err;
-}
-
-/*
- * Receiving function, which should either return error or read
- * whole block request. If there was no traffic for a one second,
- * send a ping, since remote node may die.
- */
-int dst_data_recv(struct dst_state *st, void *data, unsigned int size)
-{
-       unsigned int revents = 0;
-       unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP;
-       unsigned int mask = err_mask | POLLIN;
-       struct dst_node *n = st->node;
-       int err = 0;
-
-       while (size && !err) {
-               revents = dst_state_poll(st);
-
-               if (!(revents & mask)) {
-                       DEFINE_WAIT(wait);
-
-                       for (;;) {
-                               prepare_to_wait(&st->thread_wait, &wait,
-                                               TASK_INTERRUPTIBLE);
-                               if (!n->trans_scan_timeout || st->need_exit)
-                                       break;
-
-                               revents = dst_state_poll(st);
-
-                               if (revents & mask)
-                                       break;
-
-                               if (signal_pending(current))
-                                       break;
-
-                               if (!schedule_timeout(HZ)) {
-                                       err = dst_send_ping(st);
-                                       if (err)
-                                               return err;
-                               }
-
-                               continue;
-                       }
-                       finish_wait(&st->thread_wait, &wait);
-               }
-
-               err = -ECONNRESET;
-               dst_state_lock(st);
-
-               if (st->socket && (st->read_socket == st->socket) &&
-                               (revents & POLLIN)) {
-                       err = dst_data_recv_raw(st, data, size);
-                       if (err > 0) {
-                               data += err;
-                               size -= err;
-                               err = 0;
-                       }
-               }
-
-               if (revents & err_mask || !st->socket) {
-                       dprintk("%s: revents: %x, socket: %p, size: %u, "
-                                       "err: %d.\n", __func__, revents,
-                                       st->socket, size, err);
-                       err = -ECONNRESET;
-               }
-
-               dst_state_unlock(st);
-
-               if (!n->trans_scan_timeout)
-                       err = -ENODEV;
-       }
-
-       return err;
-}
-
-/*
- * Send block autoconf reply.
- */
-static int dst_process_cfg(struct dst_state *st)
-{
-       struct dst_node *n = st->node;
-       struct dst_cmd *cmd = st->data;
-       int err;
-
-       cmd->sector = n->size;
-       cmd->rw = st->permissions;
-
-       dst_convert_cmd(cmd);
-
-       dst_state_lock(st);
-       err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0);
-       dst_state_unlock(st);
-
-       return err;
-}
-
-/*
- * Receive block IO from the network.
- */
-static int dst_recv_bio(struct dst_state *st, struct bio *bio,
-               unsigned int total_size)
-{
-       struct bio_vec *bv;
-       int i, err;
-       void *data;
-       unsigned int sz;
-
-       bio_for_each_segment(bv, bio, i) {
-               sz = min(total_size, bv->bv_len);
-
-               dprintk("%s: bio: %llu/%u, total: %u, len: %u, sz: %u, "
-                               "off: %u.\n", __func__, (u64)bio->bi_sector,
-                               bio->bi_size, total_size, bv->bv_len, sz,
-                               bv->bv_offset);
-
-               data = kmap(bv->bv_page) + bv->bv_offset;
-               err = dst_data_recv(st, data, sz);
-               kunmap(bv->bv_page);
-
-               bv->bv_len = sz;
-
-               if (err)
-                       return err;
-
-               total_size -= sz;
-               if (total_size == 0)
-                       break;
-       }
-
-       return 0;
-}
-
-/*
- * Our block IO has just completed and arrived: get it.
- */
-static int dst_process_io_response(struct dst_state *st)
-{
-       struct dst_node *n = st->node;
-       struct dst_cmd *cmd = st->data;
-       struct dst_trans *t;
-       int err = 0;
-       struct bio *bio;
-
-       mutex_lock(&n->trans_lock);
-       t = dst_trans_search(n, cmd->id);
-       mutex_unlock(&n->trans_lock);
-
-       if (!t)
-               goto err_out_exit;
-
-       bio = t->bio;
-
-       dprintk("%s: bio: %llu/%u, cmd_size: %u, csize: %u, dir: %lu.\n",
-               __func__, (u64)bio->bi_sector, bio->bi_size, cmd->size,
-               cmd->csize, bio_data_dir(bio));
-
-       if (bio_data_dir(bio) == READ) {
-               if (bio->bi_size != cmd->size - cmd->csize)
-                       goto err_out_exit;
-
-               if (dst_need_crypto(n)) {
-                       err = dst_recv_cdata(st, t->cmd.hash);
-                       if (err)
-                               goto err_out_exit;
-               }
-
-               err = dst_recv_bio(st, t->bio, bio->bi_size);
-               if (err)
-                       goto err_out_exit;
-
-               if (dst_need_crypto(n))
-                       return dst_trans_crypto(t);
-       } else {
-               err = -EBADMSG;
-               if (cmd->size || cmd->csize)
-                       goto err_out_exit;
-       }
-
-       dst_trans_remove(t);
-       dst_trans_put(t);
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-/*
- * Receive crypto data.
- */
-int dst_recv_cdata(struct dst_state *st, void *cdata)
-{
-       struct dst_cmd *cmd = st->data;
-       struct dst_node *n = st->node;
-       struct dst_crypto_ctl *c = &n->crypto;
-       int err;
-
-       if (cmd->csize != c->crypto_attached_size) {
-               dprintk("%s: cmd: cmd: %u, sector: %llu, size: %u, "
-                               "csize: %u != digest size %u.\n",
-                               __func__, cmd->cmd, cmd->sector, cmd->size,
-                               cmd->csize, c->crypto_attached_size);
-               err = -EINVAL;
-               goto err_out_exit;
-       }
-
-       err = dst_data_recv(st, cdata, cmd->csize);
-       if (err)
-               goto err_out_exit;
-
-       cmd->size -= cmd->csize;
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-/*
- * Receive the command and start its processing.
- */
-static int dst_recv_processing(struct dst_state *st)
-{
-       int err = -EINTR;
-       struct dst_cmd *cmd = st->data;
-
-       /*
-        * If socket will be reset after this statement, then
-        * dst_data_recv() will just fail and loop will
-        * start again, so it can be done without any locks.
-        *
-        * st->read_socket is needed to prevents state machine
-        * breaking between this data reading and subsequent one
-        * in protocol specific functions during connection reset.
-        * In case of reset we have to read next command and do
-        * not expect data for old command to magically appear in
-        * new connection.
-        */
-       st->read_socket = st->socket;
-       err = dst_data_recv(st, cmd, sizeof(struct dst_cmd));
-       if (err)
-               goto out_exit;
-
-       dst_convert_cmd(cmd);
-
-       dprintk("%s: cmd: %u, size: %u, csize: %u, id: %llu, "
-                       "sector: %llu, flags: %llx, rw: %llx.\n",
-                       __func__, cmd->cmd, cmd->size,
-                       cmd->csize, cmd->id, cmd->sector,
-                       cmd->flags, cmd->rw);
-
-       /*
-        * This should catch protocol breakage and random garbage
-        * instead of commands.
-        */
-       if (unlikely(cmd->csize > st->size - sizeof(struct dst_cmd))) {
-               err = -EBADMSG;
-               goto out_exit;
-       }
-
-       err = -EPROTO;
-       switch (cmd->cmd) {
-       case DST_IO_RESPONSE:
-               err = dst_process_io_response(st);
-               break;
-       case DST_IO:
-               err = dst_process_io(st);
-               break;
-       case DST_CFG:
-               err = dst_process_cfg(st);
-               break;
-       case DST_PING:
-               err = 0;
-               break;
-       default:
-               break;
-       }
-
-out_exit:
-       return err;
-}
-
-/*
- * Receiving thread. For the client node we should try to reconnect,
- * for accepted client we just drop the state and expect it to reconnect.
- */
-static int dst_recv(void *init_data, void *schedule_data)
-{
-       struct dst_state *st = schedule_data;
-       struct dst_node *n = init_data;
-       int err = 0;
-
-       dprintk("%s: start st: %p, n: %p, scan: %lu, need_exit: %d.\n",
-                       __func__, st, n, n->trans_scan_timeout, st->need_exit);
-
-       while (n->trans_scan_timeout && !st->need_exit) {
-               err = dst_recv_processing(st);
-               if (err < 0) {
-                       if (!st->ctl.type)
-                               break;
-
-                       if (!n->trans_scan_timeout || st->need_exit)
-                               break;
-
-                       dst_state_reset(st);
-                       msleep(1000);
-               }
-       }
-
-       st->need_exit = 1;
-       wake_up(&st->thread_wait);
-
-       dprintk("%s: freeing receiving socket st: %p.\n", __func__, st);
-       dst_state_lock(st);
-       dst_state_exit_connected(st);
-       dst_state_unlock(st);
-       dst_state_put(st);
-
-       dprintk("%s: freed receiving socket st: %p.\n", __func__, st);
-
-       return err;
-}
-
-/*
- * Network state dies here and borns couple of lines below.
- * This object is the main network state processing engine:
- * sending, receiving, reconnections, all network related
- * tasks are handled on behalf of the state.
- */
-static void dst_state_free(struct dst_state *st)
-{
-       dprintk("%s: st: %p.\n", __func__, st);
-       if (st->cleanup)
-               st->cleanup(st);
-       kfree(st->data);
-       kfree(st);
-}
-
-struct dst_state *dst_state_alloc(struct dst_node *n)
-{
-       struct dst_state *st;
-       int err = -ENOMEM;
-
-       st = kzalloc(sizeof(struct dst_state), GFP_KERNEL);
-       if (!st)
-               goto err_out_exit;
-
-       st->node = n;
-       st->need_exit = 0;
-
-       st->size = PAGE_SIZE;
-       st->data = kmalloc(st->size, GFP_KERNEL);
-       if (!st->data)
-               goto err_out_free;
-
-       spin_lock_init(&st->request_lock);
-       INIT_LIST_HEAD(&st->request_list);
-
-       mutex_init(&st->state_lock);
-       init_waitqueue_head(&st->thread_wait);
-
-       /*
-        * One for processing thread, another one for node itself.
-        */
-       atomic_set(&st->refcnt, 2);
-
-       dprintk("%s: st: %p, n: %p.\n", __func__, st, st->node);
-
-       return st;
-
-err_out_free:
-       kfree(st);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-int dst_state_schedule_receiver(struct dst_state *st)
-{
-       return thread_pool_schedule_private(st->node->pool, dst_thread_setup,
-                       dst_recv, st, MAX_SCHEDULE_TIMEOUT, st->node);
-}
-
-/*
- * Initialize client's connection to the remote peer: allocate state,
- * connect and perform block IO autoconfiguration.
- */
-int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r)
-{
-       struct dst_state *st;
-       int err = -ENOMEM;
-
-       st = dst_state_alloc(n);
-       if (IS_ERR(st)) {
-               err = PTR_ERR(st);
-               goto err_out_exit;
-       }
-       memcpy(&st->ctl, r, sizeof(struct dst_network_ctl));
-
-       err = dst_state_init_connected(st);
-       if (err)
-               goto err_out_free_data;
-
-       err = dst_request_remote_config(st);
-       if (err)
-               goto err_out_exit_connected;
-       n->state = st;
-
-       err = dst_state_schedule_receiver(st);
-       if (err)
-               goto err_out_exit_connected;
-
-       return 0;
-
-err_out_exit_connected:
-       dst_state_exit_connected(st);
-err_out_free_data:
-       dst_state_free(st);
-err_out_exit:
-       n->state = NULL;
-       return err;
-}
-
-void dst_state_put(struct dst_state *st)
-{
-       dprintk("%s: st: %p, refcnt: %d.\n",
-                       __func__, st, atomic_read(&st->refcnt));
-       if (atomic_dec_and_test(&st->refcnt))
-               dst_state_free(st);
-}
-
-/*
- * Send block IO to the network one by one using zero-copy ->sendpage().
- */
-int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio)
-{
-       struct bio_vec *bv;
-       struct dst_crypto_ctl *c = &st->node->crypto;
-       int err, i = 0;
-       int flags = MSG_WAITALL;
-
-       err = dst_data_send_header(st->socket, cmd,
-               sizeof(struct dst_cmd) + c->crypto_attached_size, bio->bi_vcnt);
-       if (err)
-               goto err_out_exit;
-
-       bio_for_each_segment(bv, bio, i) {
-               if (i < bio->bi_vcnt - 1)
-                       flags |= MSG_MORE;
-
-               err = kernel_sendpage(st->socket, bv->bv_page, bv->bv_offset,
-                               bv->bv_len, flags);
-               if (err <= 0)
-                       goto err_out_exit;
-       }
-
-       return 0;
-
-err_out_exit:
-       dprintk("%s: %d/%d, flags: %x, err: %d.\n",
-                       __func__, i, bio->bi_vcnt, flags, err);
-       return err;
-}
-
-/*
- * Send transaction to the remote peer.
- */
-int dst_trans_send(struct dst_trans *t)
-{
-       int err;
-       struct dst_state *st = t->n->state;
-       struct bio *bio = t->bio;
-
-       dst_convert_cmd(&t->cmd);
-
-       dst_state_lock(st);
-       if (!st->socket) {
-               err = dst_state_init_connected(st);
-               if (err)
-                       goto err_out_unlock;
-       }
-
-       if (bio_data_dir(bio) == WRITE) {
-               err = dst_send_bio(st, &t->cmd, t->bio);
-       } else {
-               err = dst_data_send_header(st->socket, &t->cmd,
-                               sizeof(struct dst_cmd), 0);
-       }
-       if (err)
-               goto err_out_reset;
-
-       dst_state_unlock(st);
-       return 0;
-
-err_out_reset:
-       dst_state_reset_nolock(st);
-err_out_unlock:
-       dst_state_unlock(st);
-
-       return err;
-}
diff --git a/drivers/staging/dst/thread_pool.c b/drivers/staging/dst/thread_pool.c
deleted file mode 100644 (file)
index 29a82b2..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * 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.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/dst.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-
-/*
- * Thread pool abstraction allows to schedule a work to be performed
- * on behalf of kernel thread. One does not operate with threads itself,
- * instead user provides setup and cleanup callbacks for thread pool itself,
- * and action and cleanup callbacks for each submitted work.
- *
- * Each worker has private data initialized at creation time and data,
- * provided by user at scheduling time.
- *
- * When action is being performed, thread can not be used by other users,
- * instead they will sleep until there is free thread to pick their work.
- */
-struct thread_pool_worker {
-       struct list_head        worker_entry;
-
-       struct task_struct      *thread;
-
-       struct thread_pool      *pool;
-
-       int                     error;
-       int                     has_data;
-       int                     need_exit;
-       unsigned int            id;
-
-       wait_queue_head_t       wait;
-
-       void                    *private;
-       void                    *schedule_data;
-
-       int                     (*action)(void *private, void *schedule_data);
-       void                    (*cleanup)(void *private);
-};
-
-static void thread_pool_exit_worker(struct thread_pool_worker *w)
-{
-       kthread_stop(w->thread);
-
-       w->cleanup(w->private);
-       kfree(w);
-}
-
-/*
- * Called to mark thread as ready and allow users to schedule new work.
- */
-static void thread_pool_worker_make_ready(struct thread_pool_worker *w)
-{
-       struct thread_pool *p = w->pool;
-
-       mutex_lock(&p->thread_lock);
-
-       if (!w->need_exit) {
-               list_move_tail(&w->worker_entry, &p->ready_list);
-               w->has_data = 0;
-               mutex_unlock(&p->thread_lock);
-
-               wake_up(&p->wait);
-       } else {
-               p->thread_num--;
-               list_del(&w->worker_entry);
-               mutex_unlock(&p->thread_lock);
-
-               thread_pool_exit_worker(w);
-       }
-}
-
-/*
- * Thread action loop: waits until there is new work.
- */
-static int thread_pool_worker_func(void *data)
-{
-       struct thread_pool_worker *w = data;
-
-       while (!kthread_should_stop()) {
-               wait_event_interruptible(w->wait,
-                       kthread_should_stop() || w->has_data);
-
-               if (kthread_should_stop())
-                       break;
-
-               if (!w->has_data)
-                       continue;
-
-               w->action(w->private, w->schedule_data);
-               thread_pool_worker_make_ready(w);
-       }
-
-       return 0;
-}
-
-/*
- * Remove single worker without specifying which one.
- */
-void thread_pool_del_worker(struct thread_pool *p)
-{
-       struct thread_pool_worker *w = NULL;
-
-       while (!w && p->thread_num) {
-               wait_event(p->wait, !list_empty(&p->ready_list) ||
-                               !p->thread_num);
-
-               dprintk("%s: locking list_empty: %d, thread_num: %d.\n",
-                               __func__, list_empty(&p->ready_list),
-                               p->thread_num);
-
-               mutex_lock(&p->thread_lock);
-               if (!list_empty(&p->ready_list)) {
-                       w = list_first_entry(&p->ready_list,
-                                       struct thread_pool_worker,
-                                       worker_entry);
-
-                       dprintk("%s: deleting w: %p, thread_num: %d, "
-                                       "list: %p [%p.%p].\n", __func__,
-                                       w, p->thread_num, &p->ready_list,
-                                       p->ready_list.prev, p->ready_list.next);
-
-                       p->thread_num--;
-                       list_del(&w->worker_entry);
-               }
-               mutex_unlock(&p->thread_lock);
-       }
-
-       if (w)
-               thread_pool_exit_worker(w);
-       dprintk("%s: deleted w: %p, thread_num: %d.\n",
-                       __func__, w, p->thread_num);
-}
-
-/*
- * Remove a worker with given ID.
- */
-void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id)
-{
-       struct thread_pool_worker *w;
-       int found = 0;
-
-       mutex_lock(&p->thread_lock);
-       list_for_each_entry(w, &p->ready_list, worker_entry) {
-               if (w->id == id) {
-                       found = 1;
-                       p->thread_num--;
-                       list_del(&w->worker_entry);
-                       break;
-               }
-       }
-
-       if (!found) {
-               list_for_each_entry(w, &p->active_list, worker_entry) {
-                       if (w->id == id) {
-                               w->need_exit = 1;
-                               break;
-                       }
-               }
-       }
-       mutex_unlock(&p->thread_lock);
-
-       if (found)
-               thread_pool_exit_worker(w);
-}
-
-/*
- * Add new worker thread with given parameters.
- * If initialization callback fails, return error.
- */
-int thread_pool_add_worker(struct thread_pool *p,
-               char *name,
-               unsigned int id,
-               void *(*init)(void *private),
-               void (*cleanup)(void *private),
-               void *private)
-{
-       struct thread_pool_worker *w;
-       int err = -ENOMEM;
-
-       w = kzalloc(sizeof(struct thread_pool_worker), GFP_KERNEL);
-       if (!w)
-               goto err_out_exit;
-
-       w->pool = p;
-       init_waitqueue_head(&w->wait);
-       w->cleanup = cleanup;
-       w->id = id;
-
-       w->thread = kthread_run(thread_pool_worker_func, w, "%s", name);
-       if (IS_ERR(w->thread)) {
-               err = PTR_ERR(w->thread);
-               goto err_out_free;
-       }
-
-       w->private = init(private);
-       if (IS_ERR(w->private)) {
-               err = PTR_ERR(w->private);
-               goto err_out_stop_thread;
-       }
-
-       mutex_lock(&p->thread_lock);
-       list_add_tail(&w->worker_entry, &p->ready_list);
-       p->thread_num++;
-       mutex_unlock(&p->thread_lock);
-
-       return 0;
-
-err_out_stop_thread:
-       kthread_stop(w->thread);
-err_out_free:
-       kfree(w);
-err_out_exit:
-       return err;
-}
-
-/*
- * Destroy the whole pool.
- */
-void thread_pool_destroy(struct thread_pool *p)
-{
-       while (p->thread_num) {
-               dprintk("%s: num: %d.\n", __func__, p->thread_num);
-               thread_pool_del_worker(p);
-       }
-
-       kfree(p);
-}
-
-/*
- * Create a pool with given number of threads.
- * They will have sequential IDs started from zero.
- */
-struct thread_pool *thread_pool_create(int num, char *name,
-               void *(*init)(void *private),
-               void (*cleanup)(void *private),
-               void *private)
-{
-       struct thread_pool_worker *w, *tmp;
-       struct thread_pool *p;
-       int err = -ENOMEM;
-       int i;
-
-       p = kzalloc(sizeof(struct thread_pool), GFP_KERNEL);
-       if (!p)
-               goto err_out_exit;
-
-       init_waitqueue_head(&p->wait);
-       mutex_init(&p->thread_lock);
-       INIT_LIST_HEAD(&p->ready_list);
-       INIT_LIST_HEAD(&p->active_list);
-       p->thread_num = 0;
-
-       for (i = 0; i < num; ++i) {
-               err = thread_pool_add_worker(p, name, i, init,
-                               cleanup, private);
-               if (err)
-                       goto err_out_free_all;
-       }
-
-       return p;
-
-err_out_free_all:
-       list_for_each_entry_safe(w, tmp, &p->ready_list, worker_entry) {
-               list_del(&w->worker_entry);
-               thread_pool_exit_worker(w);
-       }
-       kfree(p);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-/*
- * Schedule execution of the action on a given thread,
- * provided ID pointer has to match previously stored
- * private data.
- */
-int thread_pool_schedule_private(struct thread_pool *p,
-               int (*setup)(void *private, void *data),
-               int (*action)(void *private, void *data),
-               void *data, long timeout, void *id)
-{
-       struct thread_pool_worker *w, *tmp, *worker = NULL;
-       int err = 0;
-
-       while (!worker && !err) {
-               timeout = wait_event_interruptible_timeout(p->wait,
-                               !list_empty(&p->ready_list),
-                               timeout);
-
-               if (!timeout) {
-                       err = -ETIMEDOUT;
-                       break;
-               }
-
-               worker = NULL;
-               mutex_lock(&p->thread_lock);
-               list_for_each_entry_safe(w, tmp, &p->ready_list, worker_entry) {
-                       if (id && id != w->private)
-                               continue;
-
-                       worker = w;
-
-                       list_move_tail(&w->worker_entry, &p->active_list);
-
-                       err = setup(w->private, data);
-                       if (!err) {
-                               w->schedule_data = data;
-                               w->action = action;
-                               w->has_data = 1;
-                               wake_up(&w->wait);
-                       } else {
-                               list_move_tail(&w->worker_entry,
-                                               &p->ready_list);
-                       }
-
-                       break;
-               }
-               mutex_unlock(&p->thread_lock);
-       }
-
-       return err;
-}
-
-/*
- * Schedule execution on arbitrary thread from the pool.
- */
-int thread_pool_schedule(struct thread_pool *p,
-               int (*setup)(void *private, void *data),
-               int (*action)(void *private, void *data),
-               void *data, long timeout)
-{
-       return thread_pool_schedule_private(p, setup,
-                       action, data, timeout, NULL);
-}
diff --git a/drivers/staging/dst/trans.c b/drivers/staging/dst/trans.c
deleted file mode 100644 (file)
index 1c36a6b..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * 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.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/bio.h>
-#include <linux/dst.h>
-#include <linux/slab.h>
-#include <linux/mempool.h>
-
-/*
- * Transaction memory pool size.
- */
-static int dst_mempool_num = 32;
-module_param(dst_mempool_num, int, 0644);
-
-/*
- * Transaction tree management.
- */
-static inline int dst_trans_cmp(dst_gen_t gen, dst_gen_t new)
-{
-       if (gen < new)
-               return 1;
-       if (gen > new)
-               return -1;
-       return 0;
-}
-
-struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen)
-{
-       struct rb_root *root = &node->trans_root;
-       struct rb_node *n = root->rb_node;
-       struct dst_trans *t, *ret = NULL;
-       int cmp;
-
-       while (n) {
-               t = rb_entry(n, struct dst_trans, trans_entry);
-
-               cmp = dst_trans_cmp(t->gen, gen);
-               if (cmp < 0)
-                       n = n->rb_left;
-               else if (cmp > 0)
-                       n = n->rb_right;
-               else {
-                       ret = t;
-                       break;
-               }
-       }
-
-       dprintk("%s: %s transaction: id: %llu.\n", __func__,
-                       (ret) ? "found" : "not found", gen);
-
-       return ret;
-}
-
-static int dst_trans_insert(struct dst_trans *new)
-{
-       struct rb_root *root = &new->n->trans_root;
-       struct rb_node **n = &root->rb_node, *parent = NULL;
-       struct dst_trans *ret = NULL, *t;
-       int cmp;
-
-       while (*n) {
-               parent = *n;
-
-               t = rb_entry(parent, struct dst_trans, trans_entry);
-
-               cmp = dst_trans_cmp(t->gen, new->gen);
-               if (cmp < 0)
-                       n = &parent->rb_left;
-               else if (cmp > 0)
-                       n = &parent->rb_right;
-               else {
-                       ret = t;
-                       break;
-               }
-       }
-
-       new->send_time = jiffies;
-       if (ret) {
-               printk(KERN_DEBUG "%s: exist: old: gen: %llu, bio: %llu/%u, "
-                       "send_time: %lu, new: gen: %llu, bio: %llu/%u, "
-                       "send_time: %lu.\n", __func__,
-                       ret->gen, (u64)ret->bio->bi_sector,
-                       ret->bio->bi_size, ret->send_time,
-                       new->gen, (u64)new->bio->bi_sector,
-                       new->bio->bi_size, new->send_time);
-               return -EEXIST;
-       }
-
-       rb_link_node(&new->trans_entry, parent, n);
-       rb_insert_color(&new->trans_entry, root);
-
-       dprintk("%s: inserted: gen: %llu, bio: %llu/%u, send_time: %lu.\n",
-               __func__, new->gen, (u64)new->bio->bi_sector,
-               new->bio->bi_size, new->send_time);
-
-       return 0;
-}
-
-int dst_trans_remove_nolock(struct dst_trans *t)
-{
-       struct dst_node *n = t->n;
-
-       if (t->trans_entry.rb_parent_color) {
-               rb_erase(&t->trans_entry, &n->trans_root);
-               t->trans_entry.rb_parent_color = 0;
-       }
-       return 0;
-}
-
-int dst_trans_remove(struct dst_trans *t)
-{
-       int ret;
-       struct dst_node *n = t->n;
-
-       mutex_lock(&n->trans_lock);
-       ret = dst_trans_remove_nolock(t);
-       mutex_unlock(&n->trans_lock);
-
-       return ret;
-}
-
-/*
- * When transaction is completed and there are no more users,
- * we complete appriate block IO request with given error status.
- */
-void dst_trans_put(struct dst_trans *t)
-{
-       if (atomic_dec_and_test(&t->refcnt)) {
-               struct bio *bio = t->bio;
-
-               dprintk("%s: completed t: %p, gen: %llu, bio: %p.\n",
-                               __func__, t, t->gen, bio);
-
-               bio_endio(bio, t->error);
-               bio_put(bio);
-
-               dst_node_put(t->n);
-               mempool_free(t, t->n->trans_pool);
-       }
-}
-
-/*
- * Process given block IO request: allocate transaction, insert it into the tree
- * and send/schedule crypto processing.
- */
-int dst_process_bio(struct dst_node *n, struct bio *bio)
-{
-       struct dst_trans *t;
-       int err = -ENOMEM;
-
-       t = mempool_alloc(n->trans_pool, GFP_NOFS);
-       if (!t)
-               goto err_out_exit;
-
-       t->n = dst_node_get(n);
-       t->bio = bio;
-       t->error = 0;
-       t->retries = 0;
-       atomic_set(&t->refcnt, 1);
-       t->gen = atomic_long_inc_return(&n->gen);
-
-       t->enc = bio_data_dir(bio);
-       dst_bio_to_cmd(bio, &t->cmd, DST_IO, t->gen);
-
-       mutex_lock(&n->trans_lock);
-       err = dst_trans_insert(t);
-       mutex_unlock(&n->trans_lock);
-       if (err)
-               goto err_out_free;
-
-       dprintk("%s: gen: %llu, bio: %llu/%u, dir/enc: %d, need_crypto: %d.\n",
-                       __func__, t->gen, (u64)bio->bi_sector,
-                       bio->bi_size, t->enc, dst_need_crypto(n));
-
-       if (dst_need_crypto(n) && t->enc)
-               dst_trans_crypto(t);
-       else
-               dst_trans_send(t);
-
-       return 0;
-
-err_out_free:
-       dst_node_put(n);
-       mempool_free(t, n->trans_pool);
-err_out_exit:
-       bio_endio(bio, err);
-       bio_put(bio);
-       return err;
-}
-
-/*
- * Scan for timeout/stale transactions.
- * Each transaction is being resent multiple times before error completion.
- */
-static void dst_trans_scan(struct work_struct *work)
-{
-       struct dst_node *n = container_of(work, struct dst_node,
-                       trans_work.work);
-       struct rb_node *rb_node;
-       struct dst_trans *t;
-       unsigned long timeout = n->trans_scan_timeout;
-       int num = 10 * n->trans_max_retries;
-
-       mutex_lock(&n->trans_lock);
-
-       for (rb_node = rb_first(&n->trans_root); rb_node; ) {
-               t = rb_entry(rb_node, struct dst_trans, trans_entry);
-
-               if (timeout && time_after(t->send_time + timeout, jiffies)
-                               && t->retries == 0)
-                       break;
-#if 0
-               dprintk("%s: t: %p, gen: %llu, n: %s, retries: %u, max: %u.\n",
-                       __func__, t, t->gen, n->name,
-                       t->retries, n->trans_max_retries);
-#endif
-               if (--num == 0)
-                       break;
-
-               dst_trans_get(t);
-
-               rb_node = rb_next(rb_node);
-
-               if (timeout && (++t->retries < n->trans_max_retries)) {
-                       dst_trans_send(t);
-               } else {
-                       t->error = -ETIMEDOUT;
-                       dst_trans_remove_nolock(t);
-                       dst_trans_put(t);
-               }
-
-               dst_trans_put(t);
-       }
-
-       mutex_unlock(&n->trans_lock);
-
-       /*
-        * If no timeout specified then system is in the middle of exiting
-        * process, so no need to reschedule scanning process again.
-        */
-       if (timeout) {
-               if (!num)
-                       timeout = HZ;
-               schedule_delayed_work(&n->trans_work, timeout);
-       }
-}
-
-/*
- * Flush all transactions and mark them as timed out.
- * Destroy transaction pools.
- */
-void dst_node_trans_exit(struct dst_node *n)
-{
-       struct dst_trans *t;
-       struct rb_node *rb_node;
-
-       if (!n->trans_cache)
-               return;
-
-       dprintk("%s: n: %p, cancelling the work.\n", __func__, n);
-       cancel_delayed_work_sync(&n->trans_work);
-       flush_scheduled_work();
-       dprintk("%s: n: %p, work has been cancelled.\n", __func__, n);
-
-       for (rb_node = rb_first(&n->trans_root); rb_node; ) {
-               t = rb_entry(rb_node, struct dst_trans, trans_entry);
-
-               dprintk("%s: t: %p, gen: %llu, n: %s.\n",
-                       __func__, t, t->gen, n->name);
-
-               rb_node = rb_next(rb_node);
-
-               t->error = -ETIMEDOUT;
-               dst_trans_remove_nolock(t);
-               dst_trans_put(t);
-       }
-
-       mempool_destroy(n->trans_pool);
-       kmem_cache_destroy(n->trans_cache);
-}
-
-/*
- * Initialize transaction storage for given node.
- * Transaction stores not only control information,
- * but also network command and crypto data (if needed)
- * to reduce number of allocations. Thus transaction size
- * differs from node to node.
- */
-int dst_node_trans_init(struct dst_node *n, unsigned int size)
-{
-       /*
-        * We need this, since node with given name can be dropped from the
-        * hash table, but be still alive, so subsequent creation of the node
-        * with the same name may collide with existing cache name.
-        */
-
-       snprintf(n->cache_name, sizeof(n->cache_name), "%s-%p", n->name, n);
-
-       n->trans_cache = kmem_cache_create(n->cache_name,
-                       size + n->crypto.crypto_attached_size,
-                       0, 0, NULL);
-       if (!n->trans_cache)
-               goto err_out_exit;
-
-       n->trans_pool = mempool_create_slab_pool(dst_mempool_num,
-                       n->trans_cache);
-       if (!n->trans_pool)
-               goto err_out_cache_destroy;
-
-       mutex_init(&n->trans_lock);
-       n->trans_root = RB_ROOT;
-
-       INIT_DELAYED_WORK(&n->trans_work, dst_trans_scan);
-       schedule_delayed_work(&n->trans_work, n->trans_scan_timeout);
-
-       dprintk("%s: n: %p, size: %u, crypto: %u.\n",
-               __func__, n, size, n->crypto.crypto_attached_size);
-
-       return 0;
-
-err_out_cache_destroy:
-       kmem_cache_destroy(n->trans_cache);
-err_out_exit:
-       return -ENOMEM;
-}
index 3abe7c9..3defa01 100644 (file)
@@ -47,7 +47,7 @@ config PANEL_PROFILE
 config PANEL_KEYPAD
        depends on PANEL && PANEL_PROFILE="0"
        int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)"
-       range 0 4
+       range 0 3
        default 0
        ---help---
          This enables and configures a keypad connected to the parallel port.
index f98a524..95c93e8 100644 (file)
@@ -378,7 +378,7 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
 
 #ifdef CONFIG_PANEL_LCD_CHARSET
 #undef DEFAULT_LCD_CHARSET
-#define DEFAULT_LCD_CHARSET
+#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET
 #endif
 
 #endif /* DEFAULT_PROFILE == 0 */
index bac40d6..8d64e28 100644 (file)
@@ -1,6 +1,5 @@
 TODO:
        - Add support for swap notifiers
-       - Remove CONFIG_ARM hack
 
 Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
 Nitin Gupta <ngupta@vflare.org>
index b839f05..989fac5 100644 (file)
@@ -222,28 +222,6 @@ out:
        return ret;
 }
 
-static void ramzswap_flush_dcache_page(struct page *page)
-{
-#ifdef CONFIG_ARM
-       int flag = 0;
-       /*
-        * Ugly hack to get flush_dcache_page() work on ARM.
-        * page_mapping(page) == NULL after clearing this swap cache flag.
-        * Without clearing this flag, flush_dcache_page() will simply set
-        * "PG_dcache_dirty" bit and return.
-        */
-       if (PageSwapCache(page)) {
-               flag = 1;
-               ClearPageSwapCache(page);
-       }
-#endif
-       flush_dcache_page(page);
-#ifdef CONFIG_ARM
-       if (flag)
-               SetPageSwapCache(page);
-#endif
-}
-
 void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
                        struct ramzswap_ioctl_stats *s)
 {
@@ -655,7 +633,7 @@ static int handle_zero_page(struct bio *bio)
        memset(user_mem, 0, PAGE_SIZE);
        kunmap_atomic(user_mem, KM_USER0);
 
-       ramzswap_flush_dcache_page(page);
+       flush_dcache_page(page);
 
        set_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_endio(bio, 0);
@@ -679,7 +657,7 @@ static int handle_uncompressed_page(struct ramzswap *rzs, struct bio *bio)
        kunmap_atomic(user_mem, KM_USER0);
        kunmap_atomic(cmem, KM_USER1);
 
-       ramzswap_flush_dcache_page(page);
+       flush_dcache_page(page);
 
        set_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_endio(bio, 0);
@@ -779,7 +757,7 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)
                goto out;
        }
 
-       ramzswap_flush_dcache_page(page);
+       flush_dcache_page(page);
 
        set_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_endio(bio, 0);
index 3222c22..0d490c1 100644 (file)
@@ -1318,13 +1318,13 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
+extern int ieee80211_rtl_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                             struct ieee80211_hdr_4addr *header,
@@ -1376,8 +1376,8 @@ extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
@@ -1385,7 +1385,7 @@ extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct
 extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
 extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
 extern void SendDisassociation(struct ieee80211_device *ieee,u8* asSta,u8 asRsn);
-extern void ieee80211_start_scan(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee);
 
 //Add for RF power on power off by lizhaoming 080512
 extern void SendDisassociation(struct ieee80211_device *ieee,
index f882dd8..9128c18 100644 (file)
@@ -469,7 +469,7 @@ drop:
 /* All received frames are sent to this function. @skb contains the frame in
  * IEEE 802.11 format, i.e., in the format it was sent over air.
  * This function is called only as a tasklet (software IRQ). */
-int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                 struct ieee80211_rx_stats *rx_stats)
 {
        struct net_device *dev = ieee->dev;
index 1fe19c3..c7c645a 100644 (file)
@@ -689,7 +689,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee)
 }
 
 /* called with ieee->lock held */
-void ieee80211_start_scan(struct ieee80211_device *ieee)
+void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 {
        if(IS_DOT11D_ENABLE(ieee) )
        {
@@ -1196,7 +1196,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee)
        }
 }
 
-void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
+void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
 {
        u8 *c;
        struct sk_buff *skb;
@@ -1898,7 +1898,7 @@ associate_complete:
 
                                                                ieee80211_associate_step2(ieee);
                                                        }else{
-                                                               ieee80211_auth_challenge(ieee, challenge, chlen);
+                                                               ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
                                                        }
                                                }else{
                                                        ieee->softmac_stats.rx_auth_rs_err++;
@@ -2047,7 +2047,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee)
 
 }
 
-void ieee80211_wake_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
 {
 
        unsigned long flags;
@@ -2089,7 +2089,7 @@ exit :
 }
 
 
-void ieee80211_stop_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
 {
        //unsigned long flags;
        //spin_lock_irqsave(&ieee->lock,flags);
@@ -2301,7 +2301,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
 //#else
        if (ieee->state == IEEE80211_NOLINK){
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
 //#endif
        spin_unlock_irqrestore(&ieee->lock, flags);
@@ -2357,7 +2357,7 @@ void ieee80211_associate_retry_wq(struct work_struct *work)
        if(ieee->state == IEEE80211_NOLINK){
                ieee->beinretry = false;
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        //YJ,add,080828, notify os here
        if(ieee->state == IEEE80211_NOLINK)
index dde1f2e..69bd021 100644 (file)
@@ -304,7 +304,7 @@ ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
 }
 
 /* SKBs are added to the ieee->tx_queue. */
-int ieee80211_xmit(struct sk_buff *skb,
+int ieee80211_rtl_xmit(struct sk_buff *skb,
                   struct net_device *dev)
 {
        struct ieee80211_device *ieee = netdev_priv(dev);
index 57c62b0..e0f13ef 100644 (file)
@@ -1811,7 +1811,7 @@ void rtl8180_rx(struct net_device *dev)
                        if(priv->rx_skb->len > 4)
                                skb_trim(priv->rx_skb,priv->rx_skb->len-4);
 #ifndef RX_DONT_PASS_UL
-                       if(!ieee80211_rx(priv->ieee80211,
+                       if(!ieee80211_rtl_rx(priv->ieee80211,
                                         priv->rx_skb, &stats)){
 #endif // RX_DONT_PASS_UL
 
@@ -1917,11 +1917,11 @@ rate)
        if (!check_nic_enought_desc(dev, priority)){
                DMESGW("Error: no descriptor left by previous TX (avail %d) ",
                        get_curr_tx_free_desc(dev, priority));
-               ieee80211_stop_queue(priv->ieee80211);
+               ieee80211_rtl_stop_queue(priv->ieee80211);
        }
        rtl8180_tx(dev, skb->data, skb->len, priority, morefrag,0,rate);
        if (!check_nic_enought_desc(dev, priority))
-               ieee80211_stop_queue(priv->ieee80211);
+               ieee80211_rtl_stop_queue(priv->ieee80211);
 
        spin_unlock_irqrestore(&priv->tx_lock,flags);
 }
@@ -3680,7 +3680,7 @@ static const struct net_device_ops rtl8180_netdev_ops = {
        .ndo_set_mac_address    = r8180_set_mac_adr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
-       .ndo_start_xmit         = ieee80211_xmit,
+       .ndo_start_xmit         = ieee80211_rtl_xmit,
 };
 
 static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
@@ -3900,7 +3900,7 @@ void rtl8180_try_wake_queue(struct net_device *dev, int pri)
        spin_unlock_irqrestore(&priv->tx_lock,flags);
 
        if(enough_desc)
-               ieee80211_wake_queue(priv->ieee80211);
+               ieee80211_rtl_wake_queue(priv->ieee80211);
 }
 
 void rtl8180_tx_isr(struct net_device *dev, int pri,short error)
index 536cb6e..124cde3 100644 (file)
@@ -377,7 +377,7 @@ static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
        //      queue_work(priv->ieee80211->wq, &priv->ieee80211->wx_sync_scan_wq);
                //printk("start scan============================>\n");
                ieee80211_softmac_ips_scan_syncro(priv->ieee80211);
-//ieee80211_start_scan(priv->ieee80211);
+//ieee80211_rtl_start_scan(priv->ieee80211);
                /* intentionally forget to up sem */
 //                     up(&priv->ieee80211->wx_sem);
                        ret = 0;
index 97137dd..3ba9e9e 100644 (file)
@@ -303,8 +303,8 @@ enum        _ReasonCode{
 #define ieee80211_rx_mgt               ieee80211_rx_mgt_rsl
 
 #define ieee80211_get_beacon           ieee80211_get_beacon_rsl
-#define ieee80211_wake_queue           ieee80211_wake_queue_rsl
-#define ieee80211_stop_queue           ieee80211_stop_queue_rsl
+#define ieee80211_rtl_wake_queue               ieee80211_rtl_wake_queue_rsl
+#define ieee80211_rtl_stop_queue               ieee80211_rtl_stop_queue_rsl
 #define ieee80211_reset_queue          ieee80211_reset_queue_rsl
 #define ieee80211_softmac_stop_protocol        ieee80211_softmac_stop_protocol_rsl
 #define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl
@@ -2435,13 +2435,13 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
+extern int ieee80211_rtl_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                             struct ieee80211_hdr_4addr *header,
@@ -2502,8 +2502,8 @@ extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
index 83c8452..aa76390 100644 (file)
@@ -333,8 +333,8 @@ enum        _ReasonCode{
 #define ieee80211_rx_mgt               ieee80211_rx_mgt_rsl
 
 #define ieee80211_get_beacon           ieee80211_get_beacon_rsl
-#define ieee80211_wake_queue           ieee80211_wake_queue_rsl
-#define ieee80211_stop_queue           ieee80211_stop_queue_rsl
+#define ieee80211_rtl_wake_queue               ieee80211_rtl_wake_queue_rsl
+#define ieee80211_rtl_stop_queue               ieee80211_rtl_stop_queue_rsl
 #define ieee80211_reset_queue          ieee80211_reset_queue_rsl
 #define ieee80211_softmac_stop_protocol        ieee80211_softmac_stop_protocol_rsl
 #define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl
@@ -2546,13 +2546,13 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
+extern int ieee80211_rtl_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                             struct ieee80211_hdr_4addr *header,
@@ -2613,8 +2613,8 @@ extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
index 2644155..f43a7db 100644 (file)
@@ -119,7 +119,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
        ieee = (struct ieee80211_device *)dev->priv;
 #endif
 #if 0
-       dev->hard_start_xmit = ieee80211_xmit;
+       dev->hard_start_xmit = ieee80211_rtl_xmit;
 #endif
 
        memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv);
@@ -333,7 +333,7 @@ extern void ieee80211_crypto_ccmp_exit(void);
 extern int ieee80211_crypto_wep_init(void);
 extern void ieee80211_crypto_wep_exit(void);
 
-int __init ieee80211_init(void)
+int __init ieee80211_rtl_init(void)
 {
        struct proc_dir_entry *e;
        int retval;
@@ -389,7 +389,7 @@ int __init ieee80211_init(void)
        return 0;
 }
 
-void __exit ieee80211_exit(void)
+void __exit ieee80211_rtl_exit(void)
 {
        if (ieee80211_proc) {
                remove_proc_entry("debug_level", ieee80211_proc);
@@ -412,8 +412,8 @@ module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "debug output mask");
 
 
-//module_exit(ieee80211_exit);
-//module_init(ieee80211_init);
+//module_exit(ieee80211_rtl_exit);
+//module_init(ieee80211_rtl_init);
 #endif
 #endif
 
index 5dc478b..06d9171 100644 (file)
@@ -923,7 +923,7 @@ u8 parse_subframe(struct sk_buff *skb,
 /* All received frames are sent to this function. @skb contains the frame in
  * IEEE 802.11 format, i.e., in the format it was sent over air.
  * This function is called only as a tasklet (software IRQ). */
-int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                 struct ieee80211_rx_stats *rx_stats)
 {
        struct net_device *dev = ieee->dev;
index 593d228..6d1ddec 100644 (file)
@@ -684,7 +684,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee)
 }
 
 /* called with ieee->lock held */
-void ieee80211_start_scan(struct ieee80211_device *ieee)
+void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 {
 #ifdef ENABLE_DOT11D
        if(IS_DOT11D_ENABLE(ieee) )
@@ -1430,7 +1430,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee)
        }
 }
 
-void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
+void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
 {
        u8 *c;
        struct sk_buff *skb;
@@ -2262,7 +2262,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 
                                                                ieee80211_associate_step2(ieee);
                                                        }else{
-                                                               ieee80211_auth_challenge(ieee, challenge, chlen);
+                                                               ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
                                                        }
                                                }else{
                                                        ieee->softmac_stats.rx_auth_rs_err++;
@@ -2376,7 +2376,7 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *
                         * to check it any more.
                         * */
                        //printk("error:no descriptor left@queue_index %d\n", queue_index);
-                       //ieee80211_stop_queue(ieee);
+                       //ieee80211_rtl_stop_queue(ieee);
 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
                        skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
 #else
@@ -2440,7 +2440,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee)
 
 }
 
-void ieee80211_wake_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
 {
 
        unsigned long flags;
@@ -2481,7 +2481,7 @@ exit :
 }
 
 
-void ieee80211_stop_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
 {
        //unsigned long flags;
        //spin_lock_irqsave(&ieee->lock,flags);
@@ -2706,7 +2706,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
 
        if (ieee->state == IEEE80211_NOLINK){
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
 }
@@ -2775,7 +2775,7 @@ void ieee80211_associate_retry_wq(struct ieee80211_device *ieee)
        {
                ieee->is_roaming= false;
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
 
@@ -3497,8 +3497,8 @@ void notify_wx_assoc_event(struct ieee80211_device *ieee)
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 //EXPORT_SYMBOL(ieee80211_get_beacon);
-//EXPORT_SYMBOL(ieee80211_wake_queue);
-//EXPORT_SYMBOL(ieee80211_stop_queue);
+//EXPORT_SYMBOL(ieee80211_rtl_wake_queue);
+//EXPORT_SYMBOL(ieee80211_rtl_stop_queue);
 //EXPORT_SYMBOL(ieee80211_reset_queue);
 //EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
 //EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
@@ -3518,8 +3518,8 @@ void notify_wx_assoc_event(struct ieee80211_device *ieee)
 //EXPORT_SYMBOL(ieee80211_start_scan_syncro);
 #else
 EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
-EXPORT_SYMBOL_NOVERS(ieee80211_wake_queue);
-EXPORT_SYMBOL_NOVERS(ieee80211_stop_queue);
+EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue);
+EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue);
 EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
index 103b33c..798fb41 100644 (file)
@@ -604,7 +604,7 @@ void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u
        }
 }
 
-int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
+int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
        struct ieee80211_device *ieee = netdev_priv(dev);
index 4e34a1f..3441b72 100644 (file)
@@ -976,7 +976,7 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
        {
                if (len != ie[1]+2)
                {
-                       printk("len:%d, ie:%d\n", len, ie[1]);
+                       printk("len:%zu, ie:%d\n", len, ie[1]);
                        return -EINVAL;
                }
                buf = kmalloc(len, GFP_KERNEL);
index 98b3bb6..e41e8a0 100644 (file)
@@ -382,7 +382,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 9));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
                return -1;
        }
 
@@ -481,7 +481,7 @@ int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 9));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
                return -1;
        }
        rsp = ( struct ieee80211_hdr_3addr*)skb->data;
@@ -611,7 +611,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 6));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 6));
                return -1;
        }
 
index ff8fe7e..0ca5d8b 100644 (file)
@@ -5795,7 +5795,7 @@ static void rtl8192_rx(struct net_device *dev)
                 stats.fragoffset = 0;
                 stats.ntotalfrag = 1;
 
-                if(!ieee80211_rx(priv->ieee80211, skb, &stats)){
+                if(!ieee80211_rtl_rx(priv->ieee80211, skb, &stats)){
                     dev_kfree_skb_any(skb);
                 } else {
                     priv->stats.rxok++;
@@ -5837,7 +5837,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
        .ndo_do_ioctl =                 rtl8192_ioctl,
        .ndo_set_multicast_list =       r8192_set_multicast,
        .ndo_set_mac_address =          r8192_set_mac_adr,
-       .ndo_start_xmit =               ieee80211_xmit,
+       .ndo_start_xmit =               ieee80211_rtl_xmit,
 };
 
 /****************************************************************************
@@ -6121,14 +6121,14 @@ static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
        RT_TRACE(COMP_DOWN, "wlan driver removed\n");
 }
 
-extern int ieee80211_init(void);
-extern void ieee80211_exit(void);
+extern int ieee80211_rtl_init(void);
+extern void ieee80211_rtl_exit(void);
 
 static int __init rtl8192_pci_module_init(void)
 {
        int retval;
 
-       retval = ieee80211_init();
+       retval = ieee80211_rtl_init();
        if (retval)
                return retval;
 
@@ -6153,7 +6153,7 @@ static void __exit rtl8192_pci_module_exit(void)
 
        RT_TRACE(COMP_DOWN, "Exiting");
        rtl8192_proc_module_remove();
-       ieee80211_exit();
+       ieee80211_rtl_exit();
 }
 
 //warning message WB
@@ -6313,7 +6313,7 @@ void rtl8192_try_wake_queue(struct net_device *dev, int pri)
         spin_unlock_irqrestore(&priv->tx_lock,flags);
 
        if(enough_desc)
-               ieee80211_wake_queue(priv->ieee80211);
+               ieee80211_rtl_wake_queue(priv->ieee80211);
 #endif
 }
 
index f22d024..9a4c858 100644 (file)
@@ -1721,13 +1721,13 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int rtl8192_ieee80211_xmit(struct sk_buff *skb,
+extern int rtl8192_ieee80211_rtl_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                             struct ieee80211_hdr_4addr *header,
@@ -1783,8 +1783,8 @@ extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
index ac223ce..fecfa12 100644 (file)
@@ -208,7 +208,7 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
  *
  * Responsible for handling management control frames
  *
- * Called by ieee80211_rx */
+ * Called by ieee80211_rtl_rx */
 static inline int
 ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats, u16 type,
@@ -289,7 +289,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
        return 0;
 }
 
-/* Called only as a tasklet (software IRQ), by ieee80211_rx */
+/* Called only as a tasklet (software IRQ), by ieee80211_rtl_rx */
 static inline int
 ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
                           struct ieee80211_crypt_data *crypt)
@@ -858,7 +858,7 @@ u8 parse_subframe(struct sk_buff *skb,
 /* All received frames are sent to this function. @skb contains the frame in
  * IEEE 802.11 format, i.e., in the format it was sent over air.
  * This function is called only as a tasklet (software IRQ). */
-int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                 struct ieee80211_rx_stats *rx_stats)
 {
        struct net_device *dev = ieee->dev;
index 203c0a5..95d4f84 100644 (file)
@@ -610,7 +610,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee)
 }
 
 /* called with ieee->lock held */
-void ieee80211_start_scan(struct ieee80211_device *ieee)
+void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 {
        if(IS_DOT11D_ENABLE(ieee) )
        {
@@ -1281,7 +1281,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee)
        }
 }
 
-void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
+void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
 {
        u8 *c;
        struct sk_buff *skb;
@@ -2054,7 +2054,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 
                                                                ieee80211_associate_step2(ieee);
                                                        }else{
-                                                               ieee80211_auth_challenge(ieee, challenge, chlen);
+                                                               ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
                                                        }
                                                }else{
                                                        ieee->softmac_stats.rx_auth_rs_err++;
@@ -2162,7 +2162,7 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *
                         * to check it any more.
                         * */
                        //printk("error:no descriptor left@queue_index %d, %d, %d\n", queue_index, skb_queue_len(&ieee->skb_waitQ[queue_index]), ieee->check_nic_enough_desc(ieee->dev,queue_index));
-                       //ieee80211_stop_queue(ieee);
+                       //ieee80211_rtl_stop_queue(ieee);
                        skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
                }else{
                        ieee->softmac_data_hard_start_xmit(
@@ -2222,7 +2222,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee)
 
 }
 
-void ieee80211_wake_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
 {
 
        unsigned long flags;
@@ -2263,7 +2263,7 @@ exit :
 }
 
 
-void ieee80211_stop_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
 {
        //unsigned long flags;
        //spin_lock_irqsave(&ieee->lock,flags);
@@ -2479,7 +2479,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
 
        if (ieee->state == IEEE80211_NOLINK){
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
 }
@@ -2552,7 +2552,7 @@ void ieee80211_associate_retry_wq(struct work_struct *work)
        if(ieee->state == IEEE80211_NOLINK)
        {
                ieee->actscanning = true;
-               ieee80211_start_scan(ieee);
+               ieee80211_rtl_start_scan(ieee);
        }
        spin_unlock_irqrestore(&ieee->lock, flags);
 
index 60621d6..4d54e1e 100644 (file)
@@ -604,7 +604,7 @@ void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u
        }
 }
 
-int rtl8192_ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
+int rtl8192_ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ieee80211_device *ieee = netdev_priv(dev);
        struct ieee80211_txb *txb = NULL;
index 66274d7..ccb9d5b 100644 (file)
@@ -126,6 +126,8 @@ static struct usb_device_id rtl8192_usb_id_tbl[] = {
        {USB_DEVICE(0x2001, 0x3301)},
        /* Zinwell */
        {USB_DEVICE(0x5a57, 0x0290)},
+       /* Guillemot */
+       {USB_DEVICE(0x06f8, 0xe031)},
        //92SU
        {USB_DEVICE(0x0bda, 0x8172)},
        {}
@@ -1501,7 +1503,7 @@ static void rtl8192_rx_isr(struct urb *urb)
         urb->context = skb;
         skb_queue_tail(&priv->rx_queue, skb);
         err = usb_submit_urb(urb, GFP_ATOMIC);
-       if(err && err != EPERM)
+       if(err && err != -EPERM)
                printk("can not submit rxurb, err is %x,URB status is %x\n",err,urb->status);
 }
 
@@ -7155,7 +7157,7 @@ void rtl8192SU_rx_nomal(struct sk_buff* skb)
                        unicast_packet = true;
                }
 
-               if(!ieee80211_rx(priv->ieee80211,skb, &stats)) {
+               if(!ieee80211_rtl_rx(priv->ieee80211,skb, &stats)) {
                        dev_kfree_skb_any(skb);
                } else {
                //      priv->stats.rxoktotal++;  //YJ,test,090108
@@ -7426,7 +7428,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
        .ndo_set_mac_address    = r8192_set_mac_adr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
-       .ndo_start_xmit         = rtl8192_ieee80211_xmit,
+       .ndo_start_xmit         = rtl8192_ieee80211_rtl_xmit,
 };
 
 static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
@@ -7619,7 +7621,7 @@ void rtl8192_try_wake_queue(struct net_device *dev, int pri)
         spin_unlock_irqrestore(&priv->tx_lock,flags);
 
        if(enough_desc)
-               ieee80211_wake_queue(priv->ieee80211);
+               ieee80211_rtl_wake_queue(priv->ieee80211);
 }
 
 void EnableHWSecurityConfig8192(struct net_device *dev)
index d397f1d..5f12d62 100644 (file)
@@ -845,7 +845,7 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
        {
                if (len != ie[1]+2)
                {
-                       printk("len:%d, ie:%d\n", len, ie[1]);
+                       printk("len:%zu, ie:%d\n", len, ie[1]);
                        return -EINVAL;
                }
                buf = kmalloc(len, GFP_KERNEL);
index 26af43b..512a57a 100644 (file)
@@ -340,7 +340,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 9));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
                return -1;
        }
 
@@ -439,7 +439,7 @@ int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 9));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
                return -1;
        }
        rsp = ( struct ieee80211_hdr_3addr*)skb->data;
@@ -569,7 +569,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
 
        if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
        {
-               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len,     (sizeof( struct ieee80211_hdr_3addr) + 6));
+               IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 6));
                return -1;
        }
 
diff --git a/drivers/staging/sm7xx/Kconfig b/drivers/staging/sm7xx/Kconfig
new file mode 100644 (file)
index 0000000..204dbfc
--- /dev/null
@@ -0,0 +1,15 @@
+config FB_SM7XX
+       tristate "Silicon Motion SM7XX Frame Buffer Support"
+       depends on FB
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         Frame Buffer driver for the Silicon Motion SM7XX serial graphic card.
+
+config FB_SM7XX_ACCEL
+       bool "Siliconmotion Acceleration functions (EXPERIMENTAL)"
+       depends on FB_SM7XX && EXPERIMENTAL
+       help
+         This will compile the Trident frame buffer device with
+         acceleration functions.
diff --git a/drivers/staging/sm7xx/Makefile b/drivers/staging/sm7xx/Makefile
new file mode 100644 (file)
index 0000000..f43cb91
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_FB_SM7XX) += sm7xx.o
+
+sm7xx-y := smtcfb.o
diff --git a/drivers/staging/sm7xx/TODO b/drivers/staging/sm7xx/TODO
new file mode 100644 (file)
index 0000000..1f61f5e
--- /dev/null
@@ -0,0 +1,10 @@
+TODO:
+- Dual head support
+- use kernel coding style
+- checkpatch.pl clean
+- refine the code and remove unused code
+- use kernel framebuffer mode setting instead of hard code
+- move it to drivers/video/sm7xx/ or make it be drivers/video/sm7xxfb.c
+
+Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and
+Teddy Wang <teddy.wang@siliconmotion.com.cn>.
diff --git a/drivers/staging/sm7xx/smtc2d.c b/drivers/staging/sm7xx/smtc2d.c
new file mode 100644 (file)
index 0000000..133b86c
--- /dev/null
@@ -0,0 +1,979 @@
+/*
+ * Silicon Motion SM7XX 2D drawing engine functions.
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Author: Boyod boyod.yang@siliconmotion.com.cn
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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.
+ *
+ * Version 0.10.26192.21.01
+ *     - Add PowerPC support
+ *     - Add 2D support for Lynx -
+ * Verified on 2.6.19.2
+ *     Boyod.yang  <boyod.yang@siliconmotion.com.cn>
+ */
+
+unsigned char smtc_de_busy;
+
+void SMTC_write2Dreg(unsigned long nOffset, unsigned long nData)
+{
+       writel(nData, smtc_2DBaseAddress + nOffset);
+}
+
+unsigned long SMTC_read2Dreg(unsigned long nOffset)
+{
+       return readl(smtc_2DBaseAddress + nOffset);
+}
+
+void SMTC_write2Ddataport(unsigned long nOffset, unsigned long nData)
+{
+       writel(nData, smtc_2Ddataport + nOffset);
+}
+
+/**********************************************************************
+ *
+ * deInit
+ *
+ * Purpose
+ *    Drawing engine initialization.
+ *
+ **********************************************************************/
+
+void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
+               unsigned int bpp)
+{
+       /* Get current power configuration. */
+       unsigned char clock;
+       clock = smtc_seqr(0x21);
+
+       /* initialize global 'mutex lock' variable */
+       smtc_de_busy = 0;
+
+       /* Enable 2D Drawing Engine */
+       smtc_seqw(0x21, clock & 0xF8);
+
+       SMTC_write2Dreg(DE_CLIP_TL,
+                       FIELD_VALUE(0, DE_CLIP_TL, TOP, 0) |
+                       FIELD_SET(0, DE_CLIP_TL, STATUS, DISABLE) |
+                       FIELD_SET(0, DE_CLIP_TL, INHIBIT, OUTSIDE) |
+                       FIELD_VALUE(0, DE_CLIP_TL, LEFT, 0));
+
+       if (bpp >= 24) {
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           nModeWidth * 3) | FIELD_VALUE(0,
+                                                                 DE_PITCH,
+                                                                 SOURCE,
+                                                                 nModeWidth
+                                                                 * 3));
+       } else {
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           nModeWidth) | FIELD_VALUE(0,
+                                                             DE_PITCH,
+                                                             SOURCE,
+                                                             nModeWidth));
+       }
+
+       SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                   nModeWidth) | FIELD_VALUE(0,
+                                                             DE_WINDOW_WIDTH,
+                                                             SOURCE,
+                                                             nModeWidth));
+
+       switch (bpp) {
+       case 8:
+               SMTC_write2Dreg(DE_STRETCH_FORMAT,
+                               FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
+                                         NORMAL) | FIELD_VALUE(0,
+                                                       DE_STRETCH_FORMAT,
+                                                       PATTERN_Y,
+                                                       0) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
+                                   0) | FIELD_SET(0, DE_STRETCH_FORMAT,
+                                                  PIXEL_FORMAT,
+                                                  8) | FIELD_SET(0,
+                                                         DE_STRETCH_FORMAT,
+                                                         ADDRESSING,
+                                                         XY) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT,
+                                       SOURCE_HEIGHT, 3));
+               break;
+       case 24:
+               SMTC_write2Dreg(DE_STRETCH_FORMAT,
+                               FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
+                                         NORMAL) | FIELD_VALUE(0,
+                                                       DE_STRETCH_FORMAT,
+                                                       PATTERN_Y,
+                                                       0) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
+                                   0) | FIELD_SET(0, DE_STRETCH_FORMAT,
+                                                          PIXEL_FORMAT,
+                                                          24) | FIELD_SET(0,
+                                                          DE_STRETCH_FORMAT,
+                                                          ADDRESSING,
+                                                          XY) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT,
+                                       SOURCE_HEIGHT, 3));
+               break;
+       case 16:
+       default:
+               SMTC_write2Dreg(DE_STRETCH_FORMAT,
+                               FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
+                                         NORMAL) | FIELD_VALUE(0,
+                                                       DE_STRETCH_FORMAT,
+                                                       PATTERN_Y,
+                                                       0) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
+                                   0) | FIELD_SET(0, DE_STRETCH_FORMAT,
+                                                          PIXEL_FORMAT,
+                                                          16) | FIELD_SET(0,
+                                                          DE_STRETCH_FORMAT,
+                                                          ADDRESSING,
+                                                          XY) |
+                               FIELD_VALUE(0, DE_STRETCH_FORMAT,
+                                       SOURCE_HEIGHT, 3));
+               break;
+       }
+
+       SMTC_write2Dreg(DE_MASKS,
+                       FIELD_VALUE(0, DE_MASKS, BYTE_MASK, 0xFFFF) |
+                       FIELD_VALUE(0, DE_MASKS, BIT_MASK, 0xFFFF));
+       SMTC_write2Dreg(DE_COLOR_COMPARE_MASK,
+                       FIELD_VALUE(0, DE_COLOR_COMPARE_MASK, MASKS, \
+                               0xFFFFFF));
+       SMTC_write2Dreg(DE_COLOR_COMPARE,
+                       FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 0xFFFFFF));
+}
+
+void deVerticalLine(unsigned long dst_base,
+                   unsigned long dst_pitch,
+                   unsigned long nX,
+                   unsigned long nY,
+                   unsigned long dst_height, unsigned long nColor)
+{
+       deWaitForNotBusy();
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+                                   dst_base));
+
+       SMTC_write2Dreg(DE_PITCH,
+                       FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
+                       FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
+
+       SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                           dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
+                                                    SOURCE,
+                                                    dst_pitch));
+
+       SMTC_write2Dreg(DE_FOREGROUND,
+                       FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+       SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_DESTINATION, X, nX) |
+                       FIELD_VALUE(0, DE_DESTINATION, Y, nY));
+
+       SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X, 1) |
+                       FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
+
+       SMTC_write2Dreg(DE_CONTROL,
+                       FIELD_SET(0, DE_CONTROL, STATUS, START) |
+                       FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
+                       FIELD_SET(0, DE_CONTROL, MAJOR, Y) |
+                       FIELD_SET(0, DE_CONTROL, STEP_X, NEGATIVE) |
+                       FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
+                       FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
+                       FIELD_SET(0, DE_CONTROL, COMMAND, SHORT_STROKE) |
+                       FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+                       FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
+
+       smtc_de_busy = 1;
+}
+
+void deHorizontalLine(unsigned long dst_base,
+                     unsigned long dst_pitch,
+                     unsigned long nX,
+                     unsigned long nY,
+                     unsigned long dst_width, unsigned long nColor)
+{
+       deWaitForNotBusy();
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+                                   dst_base));
+
+       SMTC_write2Dreg(DE_PITCH,
+                       FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
+                       FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
+
+       SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                           dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
+                                                    SOURCE,
+                                                    dst_pitch));
+       SMTC_write2Dreg(DE_FOREGROUND,
+                       FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+       SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP,
+                         DISABLE) | FIELD_VALUE(0, DE_DESTINATION, X,
+                                                nX) | FIELD_VALUE(0,
+                                                          DE_DESTINATION,
+                                                          Y,
+                                                          nY));
+       SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X,
+                           dst_width) | FIELD_VALUE(0, DE_DIMENSION,
+                                                    Y_ET, 1));
+       SMTC_write2Dreg(DE_CONTROL,
+               FIELD_SET(0, DE_CONTROL, STATUS, START) | FIELD_SET(0,
+                                                           DE_CONTROL,
+                                                           DIRECTION,
+                                                           RIGHT_TO_LEFT)
+               | FIELD_SET(0, DE_CONTROL, MAJOR, X) | FIELD_SET(0,
+                                                        DE_CONTROL,
+                                                        STEP_X,
+                                                        POSITIVE)
+               | FIELD_SET(0, DE_CONTROL, STEP_Y,
+                           NEGATIVE) | FIELD_SET(0, DE_CONTROL,
+                                                 LAST_PIXEL,
+                                                 OFF) | FIELD_SET(0,
+                                                          DE_CONTROL,
+                                                          COMMAND,
+                                                          SHORT_STROKE)
+               | FIELD_SET(0, DE_CONTROL, ROP_SELECT,
+                           ROP2) | FIELD_VALUE(0, DE_CONTROL, ROP,
+                                               0x0C));
+
+       smtc_de_busy = 1;
+}
+
+void deLine(unsigned long dst_base,
+           unsigned long dst_pitch,
+           unsigned long nX1,
+           unsigned long nY1,
+           unsigned long nX2, unsigned long nY2, unsigned long nColor)
+{
+       unsigned long nCommand =
+           FIELD_SET(0, DE_CONTROL, STATUS, START) |
+           FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
+           FIELD_SET(0, DE_CONTROL, MAJOR, X) |
+           FIELD_SET(0, DE_CONTROL, STEP_X, POSITIVE) |
+           FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
+           FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
+           FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+           FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C);
+       unsigned long DeltaX;
+       unsigned long DeltaY;
+
+       /* Calculate delta X */
+       if (nX1 <= nX2)
+               DeltaX = nX2 - nX1;
+       else {
+               DeltaX = nX1 - nX2;
+               nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_X, NEGATIVE);
+       }
+
+       /* Calculate delta Y */
+       if (nY1 <= nY2)
+               DeltaY = nY2 - nY1;
+       else {
+               DeltaY = nY1 - nY2;
+               nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_Y, NEGATIVE);
+       }
+
+       /* Determine the major axis */
+       if (DeltaX < DeltaY)
+               nCommand = FIELD_SET(nCommand, DE_CONTROL, MAJOR, Y);
+
+       /* Vertical line? */
+       if (nX1 == nX2)
+               deVerticalLine(dst_base, dst_pitch, nX1, nY1, DeltaY, nColor);
+
+       /* Horizontal line? */
+       else if (nY1 == nY2)
+               deHorizontalLine(dst_base, dst_pitch, nX1, nY1, \
+                               DeltaX, nColor);
+
+       /* Diagonal line? */
+       else if (DeltaX == DeltaY) {
+               deWaitForNotBusy();
+
+               SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                               FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
+                                           ADDRESS, dst_base));
+
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_PITCH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                               FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_WINDOW_WIDTH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_FOREGROUND,
+                               FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+               SMTC_write2Dreg(DE_DESTINATION,
+                               FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                               FIELD_VALUE(0, DE_DESTINATION, X, 1) |
+                               FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
+
+               SMTC_write2Dreg(DE_DIMENSION,
+                               FIELD_VALUE(0, DE_DIMENSION, X, 1) |
+                               FIELD_VALUE(0, DE_DIMENSION, Y_ET, DeltaX));
+
+               SMTC_write2Dreg(DE_CONTROL,
+                               FIELD_SET(nCommand, DE_CONTROL, COMMAND,
+                                         SHORT_STROKE));
+       }
+
+       /* Generic line */
+       else {
+               unsigned int k1, k2, et, w;
+               if (DeltaX < DeltaY) {
+                       k1 = 2 * DeltaX;
+                       et = k1 - DeltaY;
+                       k2 = et - DeltaY;
+                       w = DeltaY + 1;
+               } else {
+                       k1 = 2 * DeltaY;
+                       et = k1 - DeltaX;
+                       k2 = et - DeltaX;
+                       w = DeltaX + 1;
+               }
+
+               deWaitForNotBusy();
+
+               SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                               FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
+                                           ADDRESS, dst_base));
+
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_PITCH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                               FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_WINDOW_WIDTH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_FOREGROUND,
+                               FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+               SMTC_write2Dreg(DE_SOURCE,
+                               FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+                               FIELD_VALUE(0, DE_SOURCE, X_K1, k1) |
+                               FIELD_VALUE(0, DE_SOURCE, Y_K2, k2));
+
+               SMTC_write2Dreg(DE_DESTINATION,
+                               FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                               FIELD_VALUE(0, DE_DESTINATION, X, nX1) |
+                               FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
+
+               SMTC_write2Dreg(DE_DIMENSION,
+                               FIELD_VALUE(0, DE_DIMENSION, X, w) |
+                               FIELD_VALUE(0, DE_DIMENSION, Y_ET, et));
+
+               SMTC_write2Dreg(DE_CONTROL,
+                               FIELD_SET(nCommand, DE_CONTROL, COMMAND,
+                                         LINE_DRAW));
+       }
+
+       smtc_de_busy = 1;
+}
+
+void deFillRect(unsigned long dst_base,
+               unsigned long dst_pitch,
+               unsigned long dst_X,
+               unsigned long dst_Y,
+               unsigned long dst_width,
+               unsigned long dst_height, unsigned long nColor)
+{
+       deWaitForNotBusy();
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+                                   dst_base));
+
+       if (dst_pitch) {
+               SMTC_write2Dreg(DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_PITCH,
+                                                            SOURCE,
+                                                            dst_pitch));
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                               FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                           dst_pitch) | FIELD_VALUE(0,
+                                                            DE_WINDOW_WIDTH,
+                                                            SOURCE,
+                                                            dst_pitch));
+       }
+
+       SMTC_write2Dreg(DE_FOREGROUND,
+                       FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+       SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
+                       FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
+
+       SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
+                       FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
+
+       SMTC_write2Dreg(DE_CONTROL,
+                       FIELD_SET(0, DE_CONTROL, STATUS, START) |
+                       FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
+                       FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
+                       FIELD_SET(0, DE_CONTROL, COMMAND, RECTANGLE_FILL) |
+                       FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+                       FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
+
+       smtc_de_busy = 1;
+}
+
+/**********************************************************************
+ *
+ * deRotatePattern
+ *
+ * Purpose
+ *    Rotate the given pattern if necessary
+ *
+ * Parameters
+ *    [in]
+ *        pPattern  - Pointer to DE_SURFACE structure containing
+ *                    pattern attributes
+ *        patternX  - X position (0-7) of pattern origin
+ *        patternY  - Y position (0-7) of pattern origin
+ *
+ *    [out]
+ *        pattern_dstaddr - Pointer to pre-allocated buffer containing
+ *        rotated pattern
+ *
+ **********************************************************************/
+void deRotatePattern(unsigned char *pattern_dstaddr,
+                    unsigned long pattern_src_addr,
+                    unsigned long pattern_BPP,
+                    unsigned long pattern_stride, int patternX, int patternY)
+{
+       unsigned int i;
+       unsigned long pattern[PATTERN_WIDTH * PATTERN_HEIGHT];
+       unsigned int x, y;
+       unsigned char *pjPatByte;
+
+       if (pattern_dstaddr != NULL) {
+               deWaitForNotBusy();
+
+               if (patternX || patternY) {
+                       /* Rotate pattern */
+                       pjPatByte = (unsigned char *)pattern;
+
+                       switch (pattern_BPP) {
+                       case 8:
+                               {
+                                       for (y = 0; y < 8; y++) {
+                                               unsigned char *pjBuffer =
+                                                   pattern_dstaddr +
+                                                   ((patternY + y) & 7) * 8;
+                                               for (x = 0; x < 8; x++) {
+                                                       pjBuffer[(patternX +
+                                                                 x) & 7] =
+                                                           pjPatByte[x];
+                                               }
+                                               pjPatByte += pattern_stride;
+                                       }
+                                       break;
+                               }
+
+                       case 16:
+                               {
+                                       for (y = 0; y < 8; y++) {
+                                               unsigned short *pjBuffer =
+                                                   (unsigned short *)
+                                                   pattern_dstaddr +
+                                                   ((patternY + y) & 7) * 8;
+                                               for (x = 0; x < 8; x++) {
+                                                       pjBuffer[(patternX +
+                                                                 x) & 7] =
+                                                           ((unsigned short *)
+                                                            pjPatByte)[x];
+                                               }
+                                               pjPatByte += pattern_stride;
+                                       }
+                                       break;
+                               }
+
+                       case 32:
+                               {
+                                       for (y = 0; y < 8; y++) {
+                                               unsigned long *pjBuffer =
+                                                   (unsigned long *)
+                                                   pattern_dstaddr +
+                                                   ((patternY + y) & 7) * 8;
+                                               for (x = 0; x < 8; x++) {
+                                                       pjBuffer[(patternX +
+                                                                 x) & 7] =
+                                                           ((unsigned long *)
+                                                            pjPatByte)[x];
+                                               }
+                                               pjPatByte += pattern_stride;
+                                       }
+                                       break;
+                               }
+                       }
+               } else {
+                       /*Don't rotate,just copy pattern into pattern_dstaddr*/
+                       for (i = 0; i < (pattern_BPP * 2); i++) {
+                               ((unsigned long *)pattern_dstaddr)[i] =
+                                   pattern[i];
+                       }
+               }
+
+       }
+}
+
+/**********************************************************************
+ *
+ * deCopy
+ *
+ * Purpose
+ *    Copy a rectangular area of the source surface to a destination surface
+ *
+ * Remarks
+ *    Source bitmap must have the same color depth (BPP) as the destination
+ *    bitmap.
+ *
+**********************************************************************/
+void deCopy(unsigned long dst_base,
+           unsigned long dst_pitch,
+           unsigned long dst_BPP,
+           unsigned long dst_X,
+           unsigned long dst_Y,
+           unsigned long dst_width,
+           unsigned long dst_height,
+           unsigned long src_base,
+           unsigned long src_pitch,
+           unsigned long src_X,
+           unsigned long src_Y, pTransparent pTransp, unsigned char nROP2)
+{
+       unsigned long nDirection = 0;
+       unsigned long nTransparent = 0;
+       /* Direction of ROP2 operation:
+        * 1 = Left to Right,
+        * (-1) = Right to Left
+        */
+       unsigned long opSign = 1;
+       /* xWidth is in pixels */
+       unsigned long xWidth = 192 / (dst_BPP / 8);
+       unsigned long de_ctrl = 0;
+
+       deWaitForNotBusy();
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+                                   dst_base));
+
+       SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE,
+                       FIELD_VALUE(0, DE_WINDOW_SOURCE_BASE, ADDRESS,
+                                   src_base));
+
+       if (dst_pitch && src_pitch) {
+               SMTC_write2Dreg(DE_PITCH,
+                       FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                                   dst_pitch) | FIELD_VALUE(0,
+                                                    DE_PITCH,
+                                                    SOURCE,
+                                                    src_pitch));
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                                   dst_pitch) | FIELD_VALUE(0,
+                                                    DE_WINDOW_WIDTH,
+                                                    SOURCE,
+                                                    src_pitch));
+       }
+
+       /* Set transparent bits if necessary */
+       if (pTransp != NULL) {
+               nTransparent =
+                   pTransp->match | pTransp->select | pTransp->control;
+
+               /* Set color compare register */
+               SMTC_write2Dreg(DE_COLOR_COMPARE,
+                               FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR,
+                                           pTransp->color));
+       }
+
+       /* Determine direction of operation */
+       if (src_Y < dst_Y) {
+               /* +----------+
+                  |S         |
+                  |          +----------+
+                  |          |      |   |
+                  |          |      |   |
+                  +---|------+      |
+                  |               D |
+                  +----------+ */
+
+               nDirection = BOTTOM_TO_TOP;
+       } else if (src_Y > dst_Y) {
+               /* +----------+
+                  |D         |
+                  |          +----------+
+                  |          |      |   |
+                  |          |      |   |
+                  +---|------+      |
+                  |               S |
+                  +----------+ */
+
+               nDirection = TOP_TO_BOTTOM;
+       } else {
+               /* src_Y == dst_Y */
+
+               if (src_X <= dst_X) {
+                       /* +------+---+------+
+                          |S     |   |     D|
+                          |      |   |      |
+                          |      |   |      |
+                          |      |   |      |
+                          +------+---+------+ */
+
+                       nDirection = RIGHT_TO_LEFT;
+               } else {
+                       /* src_X > dst_X */
+
+                       /* +------+---+------+
+                          |D     |   |     S|
+                          |      |   |      |
+                          |      |   |      |
+                          |      |   |      |
+                          +------+---+------+ */
+
+                       nDirection = LEFT_TO_RIGHT;
+               }
+       }
+
+       if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
+               src_X += dst_width - 1;
+               src_Y += dst_height - 1;
+               dst_X += dst_width - 1;
+               dst_Y += dst_height - 1;
+               opSign = (-1);
+       }
+
+       if (dst_BPP >= 24) {
+               src_X *= 3;
+               src_Y *= 3;
+               dst_X *= 3;
+               dst_Y *= 3;
+               dst_width *= 3;
+               if ((nDirection == BOTTOM_TO_TOP)
+                   || (nDirection == RIGHT_TO_LEFT)) {
+                       src_X += 2;
+                       dst_X += 2;
+               }
+       }
+
+       /* Workaround for 192 byte hw bug */
+       if ((nROP2 != 0x0C) && ((dst_width * (dst_BPP / 8)) >= 192)) {
+               /*
+                * Perform the ROP2 operation in chunks of (xWidth *
+                * dst_height)
+                */
+               while (1) {
+                       deWaitForNotBusy();
+
+                       SMTC_write2Dreg(DE_SOURCE,
+                               FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+                               FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
+                               FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
+
+                       SMTC_write2Dreg(DE_DESTINATION,
+                               FIELD_SET(0, DE_DESTINATION, WRAP,
+                                 DISABLE) | FIELD_VALUE(0,
+                                                        DE_DESTINATION,
+                                                        X,
+                                                        dst_X)
+                       | FIELD_VALUE(0, DE_DESTINATION, Y,
+                                                     dst_Y));
+
+                       SMTC_write2Dreg(DE_DIMENSION,
+                               FIELD_VALUE(0, DE_DIMENSION, X,
+                                   xWidth) | FIELD_VALUE(0,
+                                                         DE_DIMENSION,
+                                                         Y_ET,
+                                                         dst_height));
+
+                       de_ctrl =
+                           FIELD_VALUE(0, DE_CONTROL, ROP,
+                               nROP2) | nTransparent | FIELD_SET(0,
+                                                         DE_CONTROL,
+                                                         ROP_SELECT,
+                                                         ROP2)
+                           | FIELD_SET(0, DE_CONTROL, COMMAND,
+                               BITBLT) | ((nDirection ==
+                                           1) ? FIELD_SET(0,
+                                                  DE_CONTROL,
+                                                  DIRECTION,
+                                                  RIGHT_TO_LEFT)
+                                          : FIELD_SET(0, DE_CONTROL,
+                                              DIRECTION,
+                                              LEFT_TO_RIGHT)) |
+                           FIELD_SET(0, DE_CONTROL, STATUS, START);
+
+                       SMTC_write2Dreg(DE_CONTROL, de_ctrl);
+
+                       src_X += (opSign * xWidth);
+                       dst_X += (opSign * xWidth);
+                       dst_width -= xWidth;
+
+                       if (dst_width <= 0) {
+                               /* ROP2 operation is complete */
+                               break;
+                       }
+
+                       if (xWidth > dst_width)
+                               xWidth = dst_width;
+               }
+       } else {
+               deWaitForNotBusy();
+               SMTC_write2Dreg(DE_SOURCE,
+                       FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
+                       FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
+
+               SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
+                       FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
+
+               SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
+                       FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
+
+               de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, nROP2) |
+                   nTransparent |
+                   FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+                   FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
+                   ((nDirection == 1) ? FIELD_SET(0, DE_CONTROL, DIRECTION,
+                                                  RIGHT_TO_LEFT)
+                    : FIELD_SET(0, DE_CONTROL, DIRECTION,
+                                LEFT_TO_RIGHT)) | FIELD_SET(0, DE_CONTROL,
+                                                            STATUS, START);
+               SMTC_write2Dreg(DE_CONTROL, de_ctrl);
+       }
+
+       smtc_de_busy = 1;
+}
+
+/*
+ * This function sets the pixel format that will apply to the 2D Engine.
+ */
+void deSetPixelFormat(unsigned long bpp)
+{
+       unsigned long de_format;
+
+       de_format = SMTC_read2Dreg(DE_STRETCH_FORMAT);
+
+       switch (bpp) {
+       case 8:
+               de_format =
+                   FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 8);
+               break;
+       default:
+       case 16:
+               de_format =
+                   FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 16);
+               break;
+       case 32:
+               de_format =
+                   FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 32);
+               break;
+       }
+
+       SMTC_write2Dreg(DE_STRETCH_FORMAT, de_format);
+}
+
+/*
+ * System memory to Video memory monochrome expansion.
+ *
+ * Source is monochrome image in system memory.  This function expands the
+ * monochrome data to color image in video memory.
+ */
+
+long deSystemMem2VideoMemMonoBlt(const char *pSrcbuf,
+                                long srcDelta,
+                                unsigned long startBit,
+                                unsigned long dBase,
+                                unsigned long dPitch,
+                                unsigned long bpp,
+                                unsigned long dx, unsigned long dy,
+                                unsigned long width, unsigned long height,
+                                unsigned long fColor,
+                                unsigned long bColor,
+                                unsigned long rop2) {
+       unsigned long bytePerPixel;
+       unsigned long ulBytesPerScan;
+       unsigned long ul4BytesPerScan;
+       unsigned long ulBytesRemain;
+       unsigned long de_ctrl = 0;
+       unsigned char ajRemain[4];
+       long i, j;
+
+       bytePerPixel = bpp / 8;
+
+       /* Just make sure the start bit is within legal range */
+       startBit &= 7;
+
+       ulBytesPerScan = (width + startBit + 7) / 8;
+       ul4BytesPerScan = ulBytesPerScan & ~3;
+       ulBytesRemain = ulBytesPerScan & 3;
+
+       if (smtc_de_busy)
+               deWaitForNotBusy();
+
+       /*
+        * 2D Source Base.  Use 0 for HOST Blt.
+        */
+
+       SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE, 0);
+
+       /*
+        * 2D Destination Base.
+        *
+        * It is an address offset (128 bit aligned) from the beginning of
+        * frame buffer.
+        */
+
+       SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, dBase);
+
+       if (dPitch) {
+
+               /*
+                * Program pitch (distance between the 1st points of two
+                * adjacent lines).
+                *
+                * Note that input pitch is BYTE value, but the 2D Pitch
+                * register uses pixel values. Need Byte to pixel convertion.
+                */
+
+               SMTC_write2Dreg(DE_PITCH,
+                       FIELD_VALUE(0, DE_PITCH, DESTINATION,
+                           dPitch /
+                           bytePerPixel) | FIELD_VALUE(0,
+                                                       DE_PITCH,
+                                                       SOURCE,
+                                                       dPitch /
+                                                       bytePerPixel));
+
+               /* Screen Window width in Pixels.
+                *
+                * 2D engine uses this value to calculate the linear address in
+                * frame buffer for a given point.
+                */
+
+               SMTC_write2Dreg(DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+                           (dPitch /
+                            bytePerPixel)) | FIELD_VALUE(0,
+                                                         DE_WINDOW_WIDTH,
+                                                         SOURCE,
+                                                         (dPitch
+                                                          /
+                                                          bytePerPixel)));
+       }
+       /* Note: For 2D Source in Host Write, only X_K1 field is needed, and
+        * Y_K2 field is not used. For mono bitmap, use startBit for X_K1.
+        */
+
+       SMTC_write2Dreg(DE_SOURCE,
+                       FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_SOURCE, X_K1, startBit) |
+                       FIELD_VALUE(0, DE_SOURCE, Y_K2, 0));
+
+       SMTC_write2Dreg(DE_DESTINATION,
+                       FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                       FIELD_VALUE(0, DE_DESTINATION, X, dx) |
+                       FIELD_VALUE(0, DE_DESTINATION, Y, dy));
+
+       SMTC_write2Dreg(DE_DIMENSION,
+                       FIELD_VALUE(0, DE_DIMENSION, X, width) |
+                       FIELD_VALUE(0, DE_DIMENSION, Y_ET, height));
+
+       SMTC_write2Dreg(DE_FOREGROUND, fColor);
+       SMTC_write2Dreg(DE_BACKGROUND, bColor);
+
+       if (bpp)
+               deSetPixelFormat(bpp);
+       /* Set the pixel format of the destination */
+
+       de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
+           FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+           FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) |
+           FIELD_SET(0, DE_CONTROL, HOST, MONO) |
+           FIELD_SET(0, DE_CONTROL, STATUS, START);
+
+       SMTC_write2Dreg(DE_CONTROL, de_ctrl | deGetTransparency());
+
+       /* Write MONO data (line by line) to 2D Engine data port */
+       for (i = 0; i < height; i++) {
+               /* For each line, send the data in chunks of 4 bytes */
+               for (j = 0; j < (ul4BytesPerScan / 4); j++)
+                       SMTC_write2Ddataport(0,
+                                            *(unsigned long *)(pSrcbuf +
+                                                               (j * 4)));
+
+               if (ulBytesRemain) {
+                       memcpy(ajRemain, pSrcbuf + ul4BytesPerScan,
+                              ulBytesRemain);
+                       SMTC_write2Ddataport(0, *(unsigned long *)ajRemain);
+               }
+
+               pSrcbuf += srcDelta;
+       }
+       smtc_de_busy = 1;
+
+       return 0;
+}
+
+/*
+ * This function gets the transparency status from DE_CONTROL register.
+ * It returns a double word with the transparent fields properly set,
+ * while other fields are 0.
+ */
+unsigned long deGetTransparency(void)
+{
+       unsigned long de_ctrl;
+
+       de_ctrl = SMTC_read2Dreg(DE_CONTROL);
+
+       de_ctrl &=
+           FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
+           FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT) |
+           FIELD_MASK(DE_CONTROL_TRANSPARENCY);
+
+       return de_ctrl;
+}
diff --git a/drivers/staging/sm7xx/smtc2d.h b/drivers/staging/sm7xx/smtc2d.h
new file mode 100644 (file)
index 0000000..38d0c33
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ * Silicon Motion SM712 2D drawing engine functions.
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Author: Ge Wang, gewang@siliconmotion.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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.
+ */
+
+#ifndef NULL
+#define NULL    0
+#endif
+
+/* Internal macros */
+
+#define _F_START(f)            (0 ? f)
+#define _F_END(f)              (1 ? f)
+#define _F_SIZE(f)             (1 + _F_END(f) - _F_START(f))
+#define _F_MASK(f)             (((1ULL << _F_SIZE(f)) - 1) << _F_START(f))
+#define _F_NORMALIZE(v, f)     (((v) & _F_MASK(f)) >> _F_START(f))
+#define _F_DENORMALIZE(v, f)   (((v) << _F_START(f)) & _F_MASK(f))
+
+/* Global macros */
+
+#define FIELD_GET(x, reg, field) \
+( \
+    _F_NORMALIZE((x), reg ## _ ## field) \
+)
+
+#define FIELD_SET(x, reg, field, value) \
+( \
+    (x & ~_F_MASK(reg ## _ ## field)) \
+    | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
+)
+
+#define FIELD_VALUE(x, reg, field, value) \
+( \
+    (x & ~_F_MASK(reg ## _ ## field)) \
+    | _F_DENORMALIZE(value, reg ## _ ## field) \
+)
+
+#define FIELD_CLEAR(reg, field) \
+( \
+    ~_F_MASK(reg ## _ ## field) \
+)
+
+/* Field Macros                        */
+
+#define FIELD_START(field)     (0 ? field)
+#define FIELD_END(field)       (1 ? field)
+#define FIELD_SIZE(field) \
+       (1 + FIELD_END(field) - FIELD_START(field))
+
+#define FIELD_MASK(field) \
+       (((1 << (FIELD_SIZE(field)-1)) \
+       | ((1 << (FIELD_SIZE(field)-1)) - 1)) \
+       << FIELD_START(field))
+
+#define FIELD_NORMALIZE(reg, field) \
+       (((reg) & FIELD_MASK(field)) >> FIELD_START(field))
+
+#define FIELD_DENORMALIZE(field, value) \
+       (((value) << FIELD_START(field)) & FIELD_MASK(field))
+
+#define FIELD_INIT(reg, field, value) \
+       FIELD_DENORMALIZE(reg ## _ ## field, \
+               reg ## _ ## field ## _ ## value)
+
+#define FIELD_INIT_VAL(reg, field, value) \
+       (FIELD_DENORMALIZE(reg ## _ ## field, value))
+
+#define FIELD_VAL_SET(x, r, f, v) ({ \
+       x = (x & ~FIELD_MASK(r ## _ ## f)) \
+       | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v) \
+})
+
+#define RGB(r, g, b)   ((unsigned long)(((r) << 16) | ((g) << 8) | (b)))
+
+/* Transparent info definition */
+typedef struct {
+       unsigned long match;    /* Matching pixel is OPAQUE/TRANSPARENT */
+       unsigned long select;   /* Transparency controlled by SRC/DST */
+       unsigned long control;  /* ENABLE/DISABLE transparency */
+       unsigned long color;    /* Transparent color */
+} Transparent, *pTransparent;
+
+#define PIXEL_DEPTH_1_BP       0       /* 1 bit per pixel */
+#define PIXEL_DEPTH_8_BPP      1       /* 8 bits per pixel */
+#define PIXEL_DEPTH_16_BPP     2       /* 16 bits per pixel */
+#define PIXEL_DEPTH_32_BPP     3       /* 32 bits per pixel */
+#define PIXEL_DEPTH_YUV422     8       /* 16 bits per pixel YUV422 */
+#define PIXEL_DEPTH_YUV420     9       /* 16 bits per pixel YUV420 */
+
+#define PATTERN_WIDTH          8
+#define PATTERN_HEIGHT         8
+
+#define        TOP_TO_BOTTOM           0
+#define        BOTTOM_TO_TOP           1
+#define RIGHT_TO_LEFT          BOTTOM_TO_TOP
+#define LEFT_TO_RIGHT          TOP_TO_BOTTOM
+
+/* Constants used in Transparent structure */
+#define MATCH_OPAQUE           0x00000000
+#define MATCH_TRANSPARENT      0x00000400
+#define SOURCE                 0x00000000
+#define DESTINATION            0x00000200
+
+/* 2D registers. */
+
+#define        DE_SOURCE                       0x000000
+#define        DE_SOURCE_WRAP                  31 : 31
+#define        DE_SOURCE_WRAP_DISABLE          0
+#define        DE_SOURCE_WRAP_ENABLE           1
+#define        DE_SOURCE_X_K1                  29 : 16
+#define        DE_SOURCE_Y_K2                  15 : 0
+
+#define        DE_DESTINATION                  0x000004
+#define        DE_DESTINATION_WRAP             31 : 31
+#define        DE_DESTINATION_WRAP_DISABLE     0
+#define        DE_DESTINATION_WRAP_ENABLE      1
+#define        DE_DESTINATION_X                28 : 16
+#define        DE_DESTINATION_Y                15 : 0
+
+#define        DE_DIMENSION                    0x000008
+#define        DE_DIMENSION_X                  28 : 16
+#define        DE_DIMENSION_Y_ET               15 : 0
+
+#define        DE_CONTROL                      0x00000C
+#define        DE_CONTROL_STATUS               31 : 31
+#define        DE_CONTROL_STATUS_STOP          0
+#define        DE_CONTROL_STATUS_START         1
+#define        DE_CONTROL_PATTERN              30 : 30
+#define        DE_CONTROL_PATTERN_MONO         0
+#define        DE_CONTROL_PATTERN_COLOR        1
+#define        DE_CONTROL_UPDATE_DESTINATION_X         29 : 29
+#define        DE_CONTROL_UPDATE_DESTINATION_X_DISABLE 0
+#define        DE_CONTROL_UPDATE_DESTINATION_X_ENABLE  1
+#define        DE_CONTROL_QUICK_START                  28 : 28
+#define        DE_CONTROL_QUICK_START_DISABLE          0
+#define        DE_CONTROL_QUICK_START_ENABLE           1
+#define        DE_CONTROL_DIRECTION                    27 : 27
+#define        DE_CONTROL_DIRECTION_LEFT_TO_RIGHT      0
+#define        DE_CONTROL_DIRECTION_RIGHT_TO_LEFT      1
+#define        DE_CONTROL_MAJOR                        26 : 26
+#define        DE_CONTROL_MAJOR_X                      0
+#define        DE_CONTROL_MAJOR_Y                      1
+#define        DE_CONTROL_STEP_X                       25 : 25
+#define        DE_CONTROL_STEP_X_POSITIVE              1
+#define        DE_CONTROL_STEP_X_NEGATIVE              0
+#define        DE_CONTROL_STEP_Y                       24 : 24
+#define        DE_CONTROL_STEP_Y_POSITIVE              1
+#define        DE_CONTROL_STEP_Y_NEGATIVE              0
+#define        DE_CONTROL_STRETCH                      23 : 23
+#define        DE_CONTROL_STRETCH_DISABLE              0
+#define        DE_CONTROL_STRETCH_ENABLE               1
+#define        DE_CONTROL_HOST                         22 : 22
+#define        DE_CONTROL_HOST_COLOR                   0
+#define        DE_CONTROL_HOST_MONO                    1
+#define        DE_CONTROL_LAST_PIXEL                   21 : 21
+#define        DE_CONTROL_LAST_PIXEL_OFF               0
+#define        DE_CONTROL_LAST_PIXEL_ON                1
+#define        DE_CONTROL_COMMAND                      20 : 16
+#define        DE_CONTROL_COMMAND_BITBLT               0
+#define        DE_CONTROL_COMMAND_RECTANGLE_FILL       1
+#define        DE_CONTROL_COMMAND_DE_TILE              2
+#define        DE_CONTROL_COMMAND_TRAPEZOID_FILL       3
+#define        DE_CONTROL_COMMAND_ALPHA_BLEND          4
+#define        DE_CONTROL_COMMAND_RLE_STRIP            5
+#define        DE_CONTROL_COMMAND_SHORT_STROKE         6
+#define        DE_CONTROL_COMMAND_LINE_DRAW            7
+#define        DE_CONTROL_COMMAND_HOST_WRITE           8
+#define        DE_CONTROL_COMMAND_HOST_READ            9
+#define        DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP 10
+#define        DE_CONTROL_COMMAND_ROTATE               11
+#define        DE_CONTROL_COMMAND_FONT                 12
+#define        DE_CONTROL_COMMAND_TEXTURE_LOAD         15
+#define        DE_CONTROL_ROP_SELECT                   15 : 15
+#define        DE_CONTROL_ROP_SELECT_ROP3              0
+#define        DE_CONTROL_ROP_SELECT_ROP2              1
+#define        DE_CONTROL_ROP2_SOURCE                  14 : 14
+#define        DE_CONTROL_ROP2_SOURCE_BITMAP           0
+#define        DE_CONTROL_ROP2_SOURCE_PATTERN          1
+#define        DE_CONTROL_MONO_DATA                    13 : 12
+#define        DE_CONTROL_MONO_DATA_NOT_PACKED         0
+#define        DE_CONTROL_MONO_DATA_8_PACKED           1
+#define        DE_CONTROL_MONO_DATA_16_PACKED          2
+#define        DE_CONTROL_MONO_DATA_32_PACKED          3
+#define        DE_CONTROL_REPEAT_ROTATE                11 : 11
+#define        DE_CONTROL_REPEAT_ROTATE_DISABLE        0
+#define        DE_CONTROL_REPEAT_ROTATE_ENABLE         1
+#define        DE_CONTROL_TRANSPARENCY_MATCH           10 : 10
+#define        DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE            0
+#define        DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT       1
+#define        DE_CONTROL_TRANSPARENCY_SELECT                  9 : 9
+#define        DE_CONTROL_TRANSPARENCY_SELECT_SOURCE           0
+#define        DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION      1
+#define        DE_CONTROL_TRANSPARENCY                         8 : 8
+#define        DE_CONTROL_TRANSPARENCY_DISABLE                 0
+#define        DE_CONTROL_TRANSPARENCY_ENABLE                  1
+#define        DE_CONTROL_ROP                                  7 : 0
+
+/* Pseudo fields. */
+
+#define        DE_CONTROL_SHORT_STROKE_DIR                     27 : 24
+#define        DE_CONTROL_SHORT_STROKE_DIR_225                 0
+#define        DE_CONTROL_SHORT_STROKE_DIR_135                 1
+#define        DE_CONTROL_SHORT_STROKE_DIR_315                 2
+#define        DE_CONTROL_SHORT_STROKE_DIR_45                  3
+#define        DE_CONTROL_SHORT_STROKE_DIR_270                 4
+#define        DE_CONTROL_SHORT_STROKE_DIR_90                  5
+#define        DE_CONTROL_SHORT_STROKE_DIR_180                 8
+#define        DE_CONTROL_SHORT_STROKE_DIR_0                   10
+#define        DE_CONTROL_ROTATION                             25 : 24
+#define        DE_CONTROL_ROTATION_0                           0
+#define        DE_CONTROL_ROTATION_270                         1
+#define        DE_CONTROL_ROTATION_90                          2
+#define        DE_CONTROL_ROTATION_180                         3
+
+#define        DE_PITCH                                        0x000010
+#define        DE_PITCH_DESTINATION                            28 : 16
+#define        DE_PITCH_SOURCE                                 12 : 0
+
+#define        DE_FOREGROUND                                   0x000014
+#define        DE_FOREGROUND_COLOR                             31 : 0
+
+#define        DE_BACKGROUND                                   0x000018
+#define        DE_BACKGROUND_COLOR                             31 : 0
+
+#define        DE_STRETCH_FORMAT                               0x00001C
+#define        DE_STRETCH_FORMAT_PATTERN_XY                    30 : 30
+#define        DE_STRETCH_FORMAT_PATTERN_XY_NORMAL             0
+#define        DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE          1
+#define        DE_STRETCH_FORMAT_PATTERN_Y                     29 : 27
+#define        DE_STRETCH_FORMAT_PATTERN_X                     25 : 23
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT                  21 : 20
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT_8                0
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT_16               1
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT_24               3
+#define        DE_STRETCH_FORMAT_PIXEL_FORMAT_32               2
+#define        DE_STRETCH_FORMAT_ADDRESSING                    19 : 16
+#define        DE_STRETCH_FORMAT_ADDRESSING_XY                 0
+#define        DE_STRETCH_FORMAT_ADDRESSING_LINEAR             15
+#define        DE_STRETCH_FORMAT_SOURCE_HEIGHT                 11 : 0
+
+#define        DE_COLOR_COMPARE                                0x000020
+#define        DE_COLOR_COMPARE_COLOR                          23 : 0
+
+#define        DE_COLOR_COMPARE_MASK                           0x000024
+#define        DE_COLOR_COMPARE_MASK_MASKS                     23 : 0
+
+#define        DE_MASKS                                        0x000028
+#define        DE_MASKS_BYTE_MASK                              31 : 16
+#define        DE_MASKS_BIT_MASK                               15 : 0
+
+#define        DE_CLIP_TL                                      0x00002C
+#define        DE_CLIP_TL_TOP                                  31 : 16
+#define        DE_CLIP_TL_STATUS                               13 : 13
+#define        DE_CLIP_TL_STATUS_DISABLE                       0
+#define        DE_CLIP_TL_STATUS_ENABLE                        1
+#define        DE_CLIP_TL_INHIBIT                              12 : 12
+#define        DE_CLIP_TL_INHIBIT_OUTSIDE                      0
+#define        DE_CLIP_TL_INHIBIT_INSIDE                       1
+#define        DE_CLIP_TL_LEFT                                 11 : 0
+
+#define        DE_CLIP_BR                                      0x000030
+#define        DE_CLIP_BR_BOTTOM                               31 : 16
+#define        DE_CLIP_BR_RIGHT                                12 : 0
+
+#define        DE_MONO_PATTERN_LOW                             0x000034
+#define        DE_MONO_PATTERN_LOW_PATTERN                     31 : 0
+
+#define        DE_MONO_PATTERN_HIGH                            0x000038
+#define        DE_MONO_PATTERN_HIGH_PATTERN                    31 : 0
+
+#define        DE_WINDOW_WIDTH                                 0x00003C
+#define        DE_WINDOW_WIDTH_DESTINATION                     28 : 16
+#define        DE_WINDOW_WIDTH_SOURCE                          12 : 0
+
+#define        DE_WINDOW_SOURCE_BASE                           0x000040
+#define        DE_WINDOW_SOURCE_BASE_EXT                       27 : 27
+#define        DE_WINDOW_SOURCE_BASE_EXT_LOCAL                 0
+#define        DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL              1
+#define        DE_WINDOW_SOURCE_BASE_CS                        26 : 26
+#define        DE_WINDOW_SOURCE_BASE_CS_0                      0
+#define        DE_WINDOW_SOURCE_BASE_CS_1                      1
+#define        DE_WINDOW_SOURCE_BASE_ADDRESS                   25 : 0
+
+#define        DE_WINDOW_DESTINATION_BASE                      0x000044
+#define        DE_WINDOW_DESTINATION_BASE_EXT                  27 : 27
+#define        DE_WINDOW_DESTINATION_BASE_EXT_LOCAL            0
+#define        DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL         1
+#define        DE_WINDOW_DESTINATION_BASE_CS                   26 : 26
+#define        DE_WINDOW_DESTINATION_BASE_CS_0                 0
+#define        DE_WINDOW_DESTINATION_BASE_CS_1                 1
+#define        DE_WINDOW_DESTINATION_BASE_ADDRESS              25 : 0
+
+#define        DE_ALPHA                                        0x000048
+#define        DE_ALPHA_VALUE                                  7 : 0
+
+#define        DE_WRAP                                         0x00004C
+#define        DE_WRAP_X                                       31 : 16
+#define        DE_WRAP_Y                                       15 : 0
+
+#define        DE_STATUS                                       0x000050
+#define        DE_STATUS_CSC                                   1 : 1
+#define        DE_STATUS_CSC_CLEAR                             0
+#define        DE_STATUS_CSC_NOT_ACTIVE                        0
+#define        DE_STATUS_CSC_ACTIVE                            1
+#define        DE_STATUS_2D                                    0 : 0
+#define        DE_STATUS_2D_CLEAR                              0
+#define        DE_STATUS_2D_NOT_ACTIVE                         0
+#define        DE_STATUS_2D_ACTIVE                             1
+
+/* Color Space Conversion registers. */
+
+#define        CSC_Y_SOURCE_BASE                               0x0000C8
+#define        CSC_Y_SOURCE_BASE_EXT                           27 : 27
+#define        CSC_Y_SOURCE_BASE_EXT_LOCAL                     0
+#define        CSC_Y_SOURCE_BASE_EXT_EXTERNAL                  1
+#define        CSC_Y_SOURCE_BASE_CS                            26 : 26
+#define        CSC_Y_SOURCE_BASE_CS_0                          0
+#define        CSC_Y_SOURCE_BASE_CS_1                          1
+#define        CSC_Y_SOURCE_BASE_ADDRESS                       25 : 0
+
+#define        CSC_CONSTANTS                                   0x0000CC
+#define        CSC_CONSTANTS_Y                                 31 : 24
+#define        CSC_CONSTANTS_R                                 23 : 16
+#define        CSC_CONSTANTS_G                                 15 : 8
+#define        CSC_CONSTANTS_B                                 7 : 0
+
+#define        CSC_Y_SOURCE_X                                  0x0000D0
+#define        CSC_Y_SOURCE_X_INTEGER                          26 : 16
+#define        CSC_Y_SOURCE_X_FRACTION                         15 : 3
+
+#define        CSC_Y_SOURCE_Y                                  0x0000D4
+#define        CSC_Y_SOURCE_Y_INTEGER                          27 : 16
+#define        CSC_Y_SOURCE_Y_FRACTION                         15 : 3
+
+#define        CSC_U_SOURCE_BASE                               0x0000D8
+#define        CSC_U_SOURCE_BASE_EXT                           27 : 27
+#define        CSC_U_SOURCE_BASE_EXT_LOCAL                     0
+#define        CSC_U_SOURCE_BASE_EXT_EXTERNAL                  1
+#define        CSC_U_SOURCE_BASE_CS                            26 : 26
+#define        CSC_U_SOURCE_BASE_CS_0                          0
+#define        CSC_U_SOURCE_BASE_CS_1                          1
+#define        CSC_U_SOURCE_BASE_ADDRESS                       25 : 0
+
+#define        CSC_V_SOURCE_BASE                               0x0000DC
+#define        CSC_V_SOURCE_BASE_EXT                           27 : 27
+#define        CSC_V_SOURCE_BASE_EXT_LOCAL                     0
+#define        CSC_V_SOURCE_BASE_EXT_EXTERNAL                  1
+#define        CSC_V_SOURCE_BASE_CS                            26 : 26
+#define        CSC_V_SOURCE_BASE_CS_0                          0
+#define        CSC_V_SOURCE_BASE_CS_1                          1
+#define        CSC_V_SOURCE_BASE_ADDRESS                       25 : 0
+
+#define        CSC_SOURCE_DIMENSION                            0x0000E0
+#define        CSC_SOURCE_DIMENSION_X                          31 : 16
+#define        CSC_SOURCE_DIMENSION_Y                          15 : 0
+
+#define        CSC_SOURCE_PITCH                                0x0000E4
+#define        CSC_SOURCE_PITCH_Y                              31 : 16
+#define        CSC_SOURCE_PITCH_UV                             15 : 0
+
+#define        CSC_DESTINATION                                 0x0000E8
+#define        CSC_DESTINATION_WRAP                            31 : 31
+#define        CSC_DESTINATION_WRAP_DISABLE                    0
+#define        CSC_DESTINATION_WRAP_ENABLE                     1
+#define        CSC_DESTINATION_X                               27 : 16
+#define        CSC_DESTINATION_Y                               11 : 0
+
+#define        CSC_DESTINATION_DIMENSION                       0x0000EC
+#define        CSC_DESTINATION_DIMENSION_X                     31 : 16
+#define        CSC_DESTINATION_DIMENSION_Y                     15 : 0
+
+#define        CSC_DESTINATION_PITCH                           0x0000F0
+#define        CSC_DESTINATION_PITCH_X                         31 : 16
+#define        CSC_DESTINATION_PITCH_Y                         15 : 0
+
+#define        CSC_SCALE_FACTOR                                0x0000F4
+#define        CSC_SCALE_FACTOR_HORIZONTAL                     31 : 16
+#define        CSC_SCALE_FACTOR_VERTICAL                       15 : 0
+
+#define        CSC_DESTINATION_BASE                            0x0000F8
+#define        CSC_DESTINATION_BASE_EXT                        27 : 27
+#define        CSC_DESTINATION_BASE_EXT_LOCAL                  0
+#define        CSC_DESTINATION_BASE_EXT_EXTERNAL               1
+#define        CSC_DESTINATION_BASE_CS                         26 : 26
+#define        CSC_DESTINATION_BASE_CS_0                       0
+#define        CSC_DESTINATION_BASE_CS_1                       1
+#define        CSC_DESTINATION_BASE_ADDRESS                    25 : 0
+
+#define        CSC_CONTROL                                     0x0000FC
+#define        CSC_CONTROL_STATUS                              31 : 31
+#define        CSC_CONTROL_STATUS_STOP                         0
+#define        CSC_CONTROL_STATUS_START                        1
+#define        CSC_CONTROL_SOURCE_FORMAT                       30 : 28
+#define        CSC_CONTROL_SOURCE_FORMAT_YUV422                0
+#define        CSC_CONTROL_SOURCE_FORMAT_YUV420I               1
+#define        CSC_CONTROL_SOURCE_FORMAT_YUV420                2
+#define        CSC_CONTROL_SOURCE_FORMAT_YVU9                  3
+#define        CSC_CONTROL_SOURCE_FORMAT_IYU1                  4
+#define        CSC_CONTROL_SOURCE_FORMAT_IYU2                  5
+#define        CSC_CONTROL_SOURCE_FORMAT_RGB565                6
+#define        CSC_CONTROL_SOURCE_FORMAT_RGB8888               7
+#define        CSC_CONTROL_DESTINATION_FORMAT                  27 : 26
+#define        CSC_CONTROL_DESTINATION_FORMAT_RGB565           0
+#define        CSC_CONTROL_DESTINATION_FORMAT_RGB8888          1
+#define        CSC_CONTROL_HORIZONTAL_FILTER                   25 : 25
+#define        CSC_CONTROL_HORIZONTAL_FILTER_DISABLE           0
+#define        CSC_CONTROL_HORIZONTAL_FILTER_ENABLE            1
+#define        CSC_CONTROL_VERTICAL_FILTER                     24 : 24
+#define        CSC_CONTROL_VERTICAL_FILTER_DISABLE             0
+#define        CSC_CONTROL_VERTICAL_FILTER_ENABLE              1
+#define        CSC_CONTROL_BYTE_ORDER                          23 : 23
+#define        CSC_CONTROL_BYTE_ORDER_YUYV                     0
+#define        CSC_CONTROL_BYTE_ORDER_UYVY                     1
+
+#define        DE_DATA_PORT_501                                0x110000
+#define        DE_DATA_PORT_712                                0x400000
+#define        DE_DATA_PORT_722                                0x6000
+
+/* point to virtual Memory Map IO starting address */
+extern char *smtc_RegBaseAddress;
+/* point to virtual video memory starting address */
+extern char *smtc_VRAMBaseAddress;
+extern unsigned char smtc_de_busy;
+
+extern unsigned long memRead32(unsigned long nOffset);
+extern void memWrite32(unsigned long nOffset, unsigned long nData);
+extern unsigned long SMTC_read2Dreg(unsigned long nOffset);
+
+/* 2D functions */
+extern void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
+                  unsigned int bpp);
+
+extern void deWaitForNotBusy(void);
+
+extern void deVerticalLine(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long nX,
+       unsigned long nY,
+       unsigned long dst_height,
+       unsigned long nColor);
+
+extern void deHorizontalLine(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long nX,
+       unsigned long nY,
+       unsigned long dst_width,
+       unsigned long nColor);
+
+extern void deLine(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long nX1,
+       unsigned long nY1,
+       unsigned long nX2,
+       unsigned long nY2,
+       unsigned long nColor);
+
+extern void deFillRect(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long dst_X,
+       unsigned long dst_Y,
+       unsigned long dst_width,
+       unsigned long dst_height,
+       unsigned long nColor);
+
+extern void deRotatePattern(unsigned char *pattern_dstaddr,
+       unsigned long pattern_src_addr,
+       unsigned long pattern_BPP,
+       unsigned long pattern_stride,
+       int     patternX,
+       int     patternY);
+
+extern void deCopy(unsigned long dst_base,
+       unsigned long dst_pitch,
+       unsigned long dst_BPP,
+       unsigned long dst_X,
+       unsigned long dst_Y,
+       unsigned long dst_width,
+       unsigned long dst_height,
+       unsigned long src_base,
+       unsigned long src_pitch,
+       unsigned long src_X,
+       unsigned long src_Y,
+       pTransparent    pTransp,
+       unsigned char nROP2);
+
+/*
+ * System memory to Video memory monochrome expansion.
+ *
+ * Source is monochrome image in system memory.  This function expands the
+ * monochrome data to color image in video memory.
+ *
+ * @pSrcbuf: pointer to start of source buffer in system memory
+ * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top
+ *             down and -ive mean button up
+ * @startBit: Mono data can start at any bit in a byte, this value should
+ *             be 0 to 7
+ * @dBase: Address of destination :  offset in frame buffer
+ * @dPitch: Pitch value of destination surface in BYTE
+ * @bpp: Color depth of destination surface
+ * @dx, dy: Starting coordinate of destination surface
+ * @width, height: width and height of rectange in pixel value
+ * @fColor,bColor: Foreground, Background color (corresponding to a 1, 0 in
+ *     the monochrome data)
+ * @rop2: ROP value
+ */
+
+extern long deSystemMem2VideoMemMonoBlt(
+       const char *pSrcbuf,
+       long srcDelta,
+       unsigned long startBit,
+       unsigned long dBase,
+       unsigned long dPitch,
+       unsigned long bpp,
+       unsigned long dx, unsigned long dy,
+       unsigned long width, unsigned long height,
+       unsigned long fColor,
+       unsigned long bColor,
+       unsigned long rop2);
+
+extern unsigned long deGetTransparency(void);
+extern void deSetPixelFormat(unsigned long bpp);
diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c
new file mode 100644 (file)
index 0000000..161dbc9
--- /dev/null
@@ -0,0 +1,1253 @@
+/*
+ * 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, wuzj@lemote.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.
+ *
+ * Version 0.10.26192.21.01
+ *     - Add PowerPC/Big endian support
+ *     - Add 2D support for Lynx
+ *     - Verified on2.6.19.2  Boyod.yang <boyod.yang@siliconmotion.com.cn>
+ *
+ * Version 0.09.2621.00.01
+ *     - Only support Linux Kernel's version 2.6.21.
+ *     Boyod.yang  <boyod.yang@siliconmotion.com.cn>
+ *
+ * Version 0.09
+ *     - Only support Linux Kernel's version 2.6.12.
+ *     Boyod.yang <boyod.yang@siliconmotion.com.cn>
+ */
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <linux/io.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/console.h>
+#include <linux/screen_info.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+struct screen_info smtc_screen_info;
+
+#include "smtcfb.h"
+#include "smtc2d.h"
+
+#ifdef DEBUG
+#define smdbg(format, arg...)  printk(KERN_DEBUG format , ## arg)
+#else
+#define smdbg(format, arg...)
+#endif
+
+/*
+* Private structure
+*/
+struct smtcfb_info {
+       /*
+        * The following is a pointer to be passed into the
+        * functions below.  The modules outside the main
+        * voyager.c driver have no knowledge as to what
+        * is within this structure.
+        */
+       struct fb_info fb;
+       struct display_switch *dispsw;
+       struct pci_dev *dev;
+       signed int currcon;
+
+       struct {
+               u8 red, green, blue;
+       } palette[NR_RGB];
+
+       u_int palette_size;
+};
+
+struct par_info {
+       /*
+        * Hardware
+        */
+       u16 chipID;
+       unsigned char __iomem *m_pMMIO;
+       char __iomem *m_pLFB;
+       char *m_pDPR;
+       char *m_pVPR;
+       char *m_pCPR;
+
+       u_int width;
+       u_int height;
+       u_int hz;
+       u_long BaseAddressInVRAM;
+       u8 chipRevID;
+};
+
+struct vesa_mode_table {
+       char mode_index[6];
+       u16 lfb_width;
+       u16 lfb_height;
+       u16 lfb_depth;
+};
+
+static struct vesa_mode_table vesa_mode[] = {
+       {"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},
+};
+
+char __iomem *smtc_RegBaseAddress;     /* Memory Map IO starting address */
+char __iomem *smtc_VRAMBaseAddress;    /* video memory starting address */
+
+char *smtc_2DBaseAddress;      /* 2D engine starting address */
+char *smtc_2Ddataport;         /* 2D data port offset */
+short smtc_2Dacceleration;
+
+static u32 colreg[17];
+static struct par_info hw;     /* hardware information */
+
+u16 smtc_ChipIDs[] = {
+       0x710,
+       0x712,
+       0x720
+};
+
+#define numSMTCchipIDs (sizeof(smtc_ChipIDs) / sizeof(u16))
+
+void deWaitForNotBusy(void)
+{
+       unsigned long i = 0x1000000;
+       while (i--) {
+               if ((smtc_seqr(0x16) & 0x18) == 0x10)
+                       break;
+       }
+       smtc_de_busy = 0;
+}
+
+static void sm712_set_timing(struct smtcfb_info *sfb,
+                            struct par_info *ppar_info)
+{
+       int i = 0, j = 0;
+       u32 m_nScreenStride;
+
+       smdbg("\nppar_info->width = %d ppar_info->height = %d"
+                       "sfb->fb.var.bits_per_pixel = %d ppar_info->hz = %d\n",
+                       ppar_info->width, ppar_info->height,
+                       sfb->fb.var.bits_per_pixel, ppar_info->hz);
+
+       for (j = 0; j < numVGAModes; j++) {
+               if (VGAMode[j].mmSizeX == ppar_info->width &&
+                   VGAMode[j].mmSizeY == ppar_info->height &&
+                   VGAMode[j].bpp == sfb->fb.var.bits_per_pixel &&
+                   VGAMode[j].hz == ppar_info->hz) {
+
+                       smdbg("\nVGAMode[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);
+
+                       smdbg("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, ppar_info->m_pVPR + 0x0C);
+       writel(0x0, ppar_info->m_pVPR + 0x40);
+
+       /* set data width */
+       m_nScreenStride =
+               (ppar_info->width * sfb->fb.var.bits_per_pixel) / 64;
+       switch (sfb->fb.var.bits_per_pixel) {
+       case 8:
+               writel(0x0, ppar_info->m_pVPR + 0x0);
+               break;
+       case 16:
+               writel(0x00020000, ppar_info->m_pVPR + 0x0);
+               break;
+       case 24:
+               writel(0x00040000, ppar_info->m_pVPR + 0x0);
+               break;
+       case 32:
+               writel(0x00030000, ppar_info->m_pVPR + 0x0);
+               break;
+       }
+       writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride),
+              ppar_info->m_pVPR + 0x10);
+
+}
+
+static void sm712_setpalette(int regno, unsigned red, unsigned green,
+                            unsigned blue, struct fb_info *info)
+{
+       struct par_info *cur_par = (struct par_info *)info->par;
+
+       if (cur_par->BaseAddressInVRAM)
+               /*
+                * second display palette for dual head. Enable CRT RAM, 6-bit
+                * RAM
+                */
+               smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x20);
+       else
+               /* primary display palette. Enable LCD RAM only, 6-bit RAM */
+               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);
+}
+
+static void smtc_set_timing(struct smtcfb_info *sfb, struct par_info
+               *ppar_info)
+{
+       switch (ppar_info->chipID) {
+       case 0x710:
+       case 0x712:
+       case 0x720:
+               sm712_set_timing(sfb, ppar_info);
+               break;
+       }
+}
+
+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,
+};
+
+static struct fb_fix_screeninfo smtcfb_fix = {
+       .id = "sm712fb",
+       .type = FB_TYPE_PACKED_PIXELS,
+       .visual = FB_VISUAL_TRUECOLOR,
+       .line_length = 800 * 3,
+       .accel = FB_ACCEL_SMI_LYNX,
+};
+
+/* 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 smtcfb_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 = (struct smtcfb_info *)info;
+       u32 val;
+
+       if (regno > 255)
+               return 1;
+
+       switch (sfb->fb.fix.visual) {
+       case FB_VISUAL_DIRECTCOLOR:
+       case FB_VISUAL_TRUECOLOR:
+               /*
+                * 16/32 bit true-colour, use pseuo-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 */
+
+#include "smtc2d.c"
+
+void smtcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+       struct par_info *p = (struct par_info *)info->par;
+
+       if (smtc_2Dacceleration) {
+               if (!area->width || !area->height)
+                       return;
+
+               deCopy(p->BaseAddressInVRAM, 0, info->var.bits_per_pixel,
+                      area->dx, area->dy, area->width, area->height,
+                      p->BaseAddressInVRAM, 0, area->sx, area->sy, 0, 0xC);
+
+       } else
+               cfb_copyarea(info, area);
+}
+
+void smtcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+       struct par_info *p = (struct par_info *)info->par;
+
+       if (smtc_2Dacceleration) {
+               if (!rect->width || !rect->height)
+                       return;
+               if (info->var.bits_per_pixel >= 24)
+                       deFillRect(p->BaseAddressInVRAM, 0, rect->dx * 3,
+                                  rect->dy * 3, rect->width * 3, rect->height,
+                                  rect->color);
+               else
+                       deFillRect(p->BaseAddressInVRAM, 0, rect->dx, rect->dy,
+                                  rect->width, rect->height, rect->color);
+       } else
+               cfb_fillrect(info, rect);
+}
+
+void smtcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       struct par_info *p = (struct par_info *)info->par;
+       u32 bg_col = 0, fg_col = 0;
+
+       if ((smtc_2Dacceleration) && (image->depth == 1)) {
+               if (smtc_de_busy)
+                       deWaitForNotBusy();
+
+               switch (info->var.bits_per_pixel) {
+               case 8:
+                       bg_col = image->bg_color;
+                       fg_col = image->fg_color;
+                       break;
+               case 16:
+                       bg_col =
+                           ((u32 *) (info->pseudo_palette))[image->bg_color];
+                       fg_col =
+                           ((u32 *) (info->pseudo_palette))[image->fg_color];
+                       break;
+               case 32:
+                       bg_col =
+                           ((u32 *) (info->pseudo_palette))[image->bg_color];
+                       fg_col =
+                           ((u32 *) (info->pseudo_palette))[image->fg_color];
+                       break;
+               }
+
+               deSystemMem2VideoMemMonoBlt(
+                       image->data,
+                       image->width / 8,
+                       0,
+                       p->BaseAddressInVRAM,
+                       0,
+                       0,
+                       image->dx, image->dy,
+                       image->width, image->height,
+                       fg_col, bg_col,
+                       0x0C);
+
+       } else
+               cfb_imageblit(info, image);
+}
+
+static struct fb_ops smtcfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_setcolreg = smtc_setcolreg,
+       .fb_blank = smtcfb_blank,
+       .fb_fillrect = smtcfb_fillrect,
+       .fb_imageblit = smtcfb_imageblit,
+       .fb_copyarea = smtcfb_copyarea,
+#ifdef __BIG_ENDIAN
+       .fb_read = smtcfb_read,
+       .fb_write = smtcfb_write,
+#endif
+
+};
+
+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 8:
+               sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+               sfb->fb.fix.line_length = sfb->fb.var.xres;
+               sfb->fb.var.red.offset = 5;
+               sfb->fb.var.red.length = 3;
+               sfb->fb.var.green.offset = 2;
+               sfb->fb.var.green.length = 3;
+               sfb->fb.var.blue.offset = 0;
+               sfb->fb.var.blue.length = 2;
+               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 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;
+       }
+
+       hw.width = sfb->fb.var.xres;
+       hw.height = sfb->fb.var.yres;
+       hw.hz = 60;
+       smtc_set_timing(sfb, &hw);
+       if (smtc_2Dacceleration) {
+               printk("2D acceleration enabled!\n");
+               /* Init smtc drawing engine */
+               deInit(sfb->fb.var.xres, sfb->fb.var.yres,
+                               sfb->fb.var.bits_per_pixel);
+       }
+}
+
+/*
+ * Alloc struct smtcfb_info and assign the default value
+ */
+static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *dev,
+                                                       char *name)
+{
+       struct smtcfb_info *sfb;
+
+       sfb = kmalloc(sizeof(struct smtcfb_info), GFP_KERNEL);
+
+       if (!sfb)
+               return NULL;
+
+       memset(sfb, 0, sizeof(struct smtcfb_info));
+
+       sfb->currcon = -1;
+       sfb->dev = dev;
+
+       /*** Init sfb->fb with default value ***/
+       sfb->fb.flags = FBINFO_FLAG_DEFAULT;
+       sfb->fb.fbops = &smtcfb_ops;
+       sfb->fb.var = smtcfb_var;
+       sfb->fb.fix = smtcfb_fix;
+
+       strcpy(sfb->fb.fix.id, name);
+
+       sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
+       sfb->fb.fix.type_aux = 0;
+       sfb->fb.fix.xpanstep = 0;
+       sfb->fb.fix.ypanstep = 0;
+       sfb->fb.fix.ywrapstep = 0;
+       sfb->fb.fix.accel = FB_ACCEL_SMI_LYNX;
+
+       sfb->fb.var.nonstd = 0;
+       sfb->fb.var.activate = FB_ACTIVATE_NOW;
+       sfb->fb.var.height = -1;
+       sfb->fb.var.width = -1;
+       /* text mode acceleration */
+       sfb->fb.var.accel_flags = FB_ACCELF_TEXT;
+       sfb->fb.var.vmode = FB_VMODE_NONINTERLACED;
+       sfb->fb.par = &hw;
+       sfb->fb.pseudo_palette = colreg;
+
+       return 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 *dev, u_long smem_len)
+{
+       if (sfb->fb.var.bits_per_pixel == 32) {
+#ifdef __BIG_ENDIAN
+               sfb->fb.fix.smem_start = pci_resource_start(dev, 0)
+                       + 0x800000;
+#else
+               sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+#endif
+       } else {
+               sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+       }
+
+       sfb->fb.fix.smem_len = smem_len;
+
+       sfb->fb.screen_base = smtc_VRAMBaseAddress;
+
+       if (!sfb->fb.screen_base) {
+               printk(KERN_INFO "%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 LynxEM+, and make sure its in linear memory mode.
+ */
+static inline void sm7xx_init_hw(void)
+{
+       outb_p(0x18, 0x3c4);
+       outb_p(0x11, 0x3c5);
+}
+
+static void smtc_free_fb_info(struct smtcfb_info *sfb)
+{
+       if (sfb) {
+               fb_alloc_cmap(&sfb->fb.cmap, 0, 0);
+               kfree(sfb);
+       }
+}
+
+/*
+ *     sm712vga_setup - process command line options, get vga parameter
+ *     @options: string of options
+ *     Returns zero.
+ *
+ */
+static int __init __maybe_unused sm712vga_setup(char *options)
+{
+       int index;
+
+       if (!options || !*options) {
+               smdbg("\n No vga parameter\n");
+               return -EINVAL;
+       }
+
+       smtc_screen_info.lfb_width = 0;
+       smtc_screen_info.lfb_height = 0;
+       smtc_screen_info.lfb_depth = 0;
+
+       smdbg("\nsm712vga_setup = %s\n", options);
+
+       for (index = 0;
+            index < (sizeof(vesa_mode) / sizeof(struct vesa_mode_table));
+            index++) {
+               if (strstr(options, vesa_mode[index].mode_index)) {
+                       smtc_screen_info.lfb_width = vesa_mode[index].lfb_width;
+                       smtc_screen_info.lfb_height =
+                                       vesa_mode[index].lfb_height;
+                       smtc_screen_info.lfb_depth = vesa_mode[index].lfb_depth;
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+__setup("vga=", sm712vga_setup);
+
+/* Jason (08/13/2009)
+ * Original init function changed to probe method to be used by pci_drv
+ * process used to detect chips replaced with kernel process in pci_drv
+ */
+static int __init smtcfb_pci_probe(struct pci_dev *pdev,
+                                  const struct pci_device_id *ent)
+{
+       struct smtcfb_info *sfb;
+       u_long smem_size = 0x00800000;  /* default 8MB */
+       char name[16];
+       int err;
+       unsigned long pFramebufferPhysical;
+
+       printk(KERN_INFO
+               "Silicon Motion display driver " SMTC_LINUX_FB_VERSION "\n");
+
+       err = pci_enable_device(pdev);  /* enable SMTC chip */
+
+       if (err)
+               return err;
+       err = -ENOMEM;
+
+       hw.chipID = ent->device;
+       sprintf(name, "sm%Xfb", hw.chipID);
+
+       sfb = smtc_alloc_fb_info(pdev, name);
+
+       if (!sfb)
+               goto failed;
+       /* Jason (08/13/2009)
+        * Store fb_info to be further used when suspending and resuming
+        */
+       pci_set_drvdata(pdev, sfb);
+
+       sm7xx_init_hw();
+
+       /*get mode parameter from smtc_screen_info */
+       if (smtc_screen_info.lfb_width != 0) {
+               sfb->fb.var.xres = smtc_screen_info.lfb_width;
+               sfb->fb.var.yres = smtc_screen_info.lfb_height;
+               sfb->fb.var.bits_per_pixel = smtc_screen_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_screen_info.lfb_depth = 32);
+#endif
+       /* Map address and memory detection */
+       pFramebufferPhysical = pci_resource_start(pdev, 0);
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &hw.chipRevID);
+
+       switch (hw.chipID) {
+       case 0x710:
+       case 0x712:
+               sfb->fb.fix.mmio_start = pFramebufferPhysical + 0x00400000;
+               sfb->fb.fix.mmio_len = 0x00400000;
+               smem_size = SM712_VIDEOMEMORYSIZE;
+#ifdef __BIG_ENDIAN
+               hw.m_pLFB = (smtc_VRAMBaseAddress =
+                   ioremap(pFramebufferPhysical, 0x00c00000));
+#else
+               hw.m_pLFB = (smtc_VRAMBaseAddress =
+                   ioremap(pFramebufferPhysical, 0x00800000));
+#endif
+               hw.m_pMMIO = (smtc_RegBaseAddress =
+                   smtc_VRAMBaseAddress + 0x00700000);
+               smtc_2DBaseAddress = (hw.m_pDPR =
+                   smtc_VRAMBaseAddress + 0x00408000);
+               smtc_2Ddataport = smtc_VRAMBaseAddress + DE_DATA_PORT_712;
+               hw.m_pVPR = hw.m_pLFB + 0x0040c000;
+#ifdef __BIG_ENDIAN
+               if (sfb->fb.var.bits_per_pixel == 32) {
+                       smtc_VRAMBaseAddress += 0x800000;
+                       hw.m_pLFB += 0x800000;
+                       printk(KERN_INFO
+                               "\nsmtc_VRAMBaseAddress=%p hw.m_pLFB=%p\n",
+                                       smtc_VRAMBaseAddress, hw.m_pLFB);
+               }
+#endif
+               if (!smtc_RegBaseAddress) {
+                       printk(KERN_INFO
+                               "%s: unable to map memory mapped IO\n",
+                               sfb->fb.fix.id);
+                       return -ENOMEM;
+               }
+
+               /* 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
+#ifdef CONFIG_FB_SM7XX_ACCEL
+               smtc_2Dacceleration = 1;
+#endif
+               break;
+       case 0x720:
+               sfb->fb.fix.mmio_start = pFramebufferPhysical;
+               sfb->fb.fix.mmio_len = 0x00200000;
+               smem_size = SM722_VIDEOMEMORYSIZE;
+               smtc_2DBaseAddress = (hw.m_pDPR =
+                   ioremap(pFramebufferPhysical, 0x00a00000));
+               hw.m_pLFB = (smtc_VRAMBaseAddress =
+                   smtc_2DBaseAddress + 0x00200000);
+               hw.m_pMMIO = (smtc_RegBaseAddress =
+                   smtc_2DBaseAddress + 0x000c0000);
+               smtc_2Ddataport = smtc_2DBaseAddress + DE_DATA_PORT_722;
+               hw.m_pVPR = smtc_2DBaseAddress + 0x800;
+
+               smtc_seqw(0x62, 0xff);
+               smtc_seqw(0x6a, 0x0d);
+               smtc_seqw(0x6b, 0x02);
+               smtc_2Dacceleration = 0;
+               break;
+       default:
+               printk(KERN_INFO
+               "No valid Silicon Motion display chip was detected!\n");
+
+               smtc_free_fb_info(sfb);
+               return err;
+       }
+
+       /* 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);
+       /* Primary display starting from 0 postion */
+       hw.BaseAddressInVRAM = 0;
+       sfb->fb.par = &hw;
+
+       err = register_framebuffer(&sfb->fb);
+       if (err < 0)
+               goto failed;
+
+       printk(KERN_INFO "Silicon Motion SM%X Rev%X primary display mode"
+                       "%dx%d-%d Init Complete.\n", hw.chipID, hw.chipRevID,
+                       sfb->fb.var.xres, sfb->fb.var.yres,
+                       sfb->fb.var.bits_per_pixel);
+
+       return 0;
+
+ failed:
+       printk(KERN_INFO "Silicon Motion, Inc.  primary display init fail\n");
+
+       smtc_unmap_smem(sfb);
+       smtc_unmap_mmio(sfb);
+       smtc_free_fb_info(sfb);
+
+       return err;
+}
+
+
+/* Jason (08/11/2009) PCI_DRV wrapper essential structs */
+static struct pci_device_id smtcfb_pci_table[] = {
+       {0x126f, 0x710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x126f, 0x712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x126f, 0x720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0,}
+};
+
+
+/* Jason (08/14/2009)
+ * do some clean up when the driver module is removed
+ */
+static void __devexit smtcfb_pci_remove(struct pci_dev *pdev)
+{
+       struct smtcfb_info *sfb;
+
+       sfb = pci_get_drvdata(pdev);
+       pci_set_drvdata(pdev, NULL);
+       smtc_unmap_smem(sfb);
+       smtc_unmap_mmio(sfb);
+       unregister_framebuffer(&sfb->fb);
+       smtc_free_fb_info(sfb);
+}
+
+/* Jason (08/14/2009)
+ * suspend function, called when the suspend event is triggered
+ */
+static int __maybe_unused smtcfb_suspend(struct pci_dev *pdev, pm_message_t msg)
+{
+       struct smtcfb_info *sfb;
+       int retv;
+
+       sfb = pci_get_drvdata(pdev);
+
+       /* set the hw in sleep mode use externel 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));
+
+       switch (msg.event) {
+       case PM_EVENT_FREEZE:
+       case PM_EVENT_PRETHAW:
+               pdev->dev.power.power_state = msg;
+               return 0;
+       }
+
+       /* when doing suspend, call fb apis and pci apis */
+       if (msg.event == PM_EVENT_SUSPEND) {
+               acquire_console_sem();
+               fb_set_suspend(&sfb->fb, 1);
+               release_console_sem();
+               retv = pci_save_state(pdev);
+               pci_disable_device(pdev);
+               retv = pci_choose_state(pdev, msg);
+               retv = pci_set_power_state(pdev, retv);
+       }
+
+       pdev->dev.power.power_state = msg;
+
+       /* additionaly turn off all function blocks including internal PLLs */
+       smtc_seqw(0x21, 0xff);
+
+       return 0;
+}
+
+static int __maybe_unused smtcfb_resume(struct pci_dev *pdev)
+{
+       struct smtcfb_info *sfb;
+       int retv;
+
+       sfb = pci_get_drvdata(pdev);
+
+       /* when resuming, restore pci data and fb cursor */
+       if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) {
+               retv = pci_set_power_state(pdev, PCI_D0);
+               retv = pci_restore_state(pdev);
+               if (pci_enable_device(pdev))
+                       return -1;
+               pci_set_master(pdev);
+       }
+
+       /* reinit hardware */
+       sm7xx_init_hw();
+       switch (hw.chipID) {
+       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);
+
+       acquire_console_sem();
+       fb_set_suspend(&sfb->fb, 0);
+       release_console_sem();
+
+       return 0;
+}
+
+/* Jason (08/13/2009)
+ * pci_driver struct used to wrap the original driver
+ * so that it can be registered into the kernel and
+ * the proper method would be called when suspending and resuming
+ */
+static struct pci_driver smtcfb_driver = {
+       .name = "smtcfb",
+       .id_table = smtcfb_pci_table,
+       .probe = smtcfb_pci_probe,
+       .remove = __devexit_p(smtcfb_pci_remove),
+#ifdef CONFIG_PM
+       .suspend = smtcfb_suspend,
+       .resume = smtcfb_resume,
+#endif
+};
+
+static int __init smtcfb_init(void)
+{
+       return pci_register_driver(&smtcfb_driver);
+}
+
+static void __exit smtcfb_exit(void)
+{
+       pci_unregister_driver(&smtcfb_driver);
+}
+
+module_init(smtcfb_init);
+module_exit(smtcfb_exit);
+
+MODULE_AUTHOR("Siliconmotion ");
+MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/sm7xx/smtcfb.h b/drivers/staging/sm7xx/smtcfb.h
new file mode 100644 (file)
index 0000000..7f2c341
--- /dev/null
@@ -0,0 +1,793 @@
+/*
+ * 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, wuzj@lemote.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 SMTC_LINUX_FB_VERSION  "version 0.11.2619.21.01 July 27, 2008"
+
+#define NR_PALETTE        256
+#define NR_RGB            2
+
+#define FB_ACCEL_SMI_LYNX 88
+
+#ifdef __BIG_ENDIAN
+#define PC_VGA            0
+#else
+#define PC_VGA            1
+#endif
+
+#define SCREEN_X_RES      1024
+#define SCREEN_Y_RES      600
+#define SCREEN_BPP        16
+
+#ifndef FIELD_OFFSET
+#define FIELD_OFSFET(type, field) \
+       ((unsigned long) (PUCHAR) & (((type *)0)->field))
+#endif
+
+/*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 char *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            (sizeof(VGAMode) / sizeof(struct ModeInit))
index 825bbc4..061e730 100644 (file)
@@ -1,6 +1,6 @@
 config VT6655
    tristate "VIA Technologies VT6655 support"
-   depends on PCI
+   depends on PCI && WLAN
    select WIRELESS_EXT
    select WEXT_PRIV
    ---help---
index 87bcd26..1055b52 100644 (file)
@@ -1,6 +1,6 @@
 config VT6656
        tristate "VIA Technologies VT6656 support"
-       depends on USB
+       depends on USB && WLAN
        select WIRELESS_EXT
        select WEXT_PRIV
        ---help---
index 7d76a7f..aaa70ed 100644 (file)
@@ -439,7 +439,7 @@ void free_chunks(imgchunk_t *fchunk, unsigned int *nfchunks)
                }
        }
        *nfchunks = 0;
-       memset(fchunk, 0, sizeof(fchunk));
+       memset(fchunk, 0, sizeof(*fchunk));
 
 }
 
index ad14227..455e6e6 100644 (file)
@@ -970,7 +970,7 @@ static int ext3_get_block(struct inode *inode, sector_t iblock,
                if (max_blocks > DIO_MAX_BLOCKS)
                        max_blocks = DIO_MAX_BLOCKS;
                handle = ext3_journal_start(inode, DIO_CREDITS +
-                               2 * EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb));
+                               EXT3_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb));
                if (IS_ERR(handle)) {
                        ret = PTR_ERR(handle);
                        goto out;
@@ -3146,8 +3146,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
 
                /* (user+group)*(old+new) structure, inode write (sb,
                 * inode block, ? - but truncate inode update has it) */
-               handle = ext3_journal_start(inode, 2*(EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)+
-                                       EXT3_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
+               handle = ext3_journal_start(inode, EXT3_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)+
+                                       EXT3_MAXQUOTAS_DEL_BLOCKS(inode->i_sb)+3);
                if (IS_ERR(handle)) {
                        error = PTR_ERR(handle);
                        goto err_out;
@@ -3239,7 +3239,7 @@ static int ext3_writepage_trans_blocks(struct inode *inode)
 #ifdef CONFIG_QUOTA
        /* We know that structure was already allocated during vfs_dq_init so
         * we will be updating only the data blocks + inodes */
-       ret += 2*EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb);
+       ret += EXT3_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb);
 #endif
 
        return ret;
index aad6400..7b0e44f 100644 (file)
@@ -1699,7 +1699,7 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
+                                       EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -1733,7 +1733,7 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
+                                       EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -1769,7 +1769,7 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
+                                       EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -1920,7 +1920,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
        struct ext3_iloc iloc;
        int err = 0, rc;
 
-       lock_super(sb);
+       mutex_lock(&EXT3_SB(sb)->s_orphan_lock);
        if (!list_empty(&EXT3_I(inode)->i_orphan))
                goto out_unlock;
 
@@ -1929,9 +1929,13 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
 
        /* @@@ FIXME: Observation from aviro:
         * I think I can trigger J_ASSERT in ext3_orphan_add().  We block
-        * here (on lock_super()), so race with ext3_link() which might bump
+        * here (on s_orphan_lock), so race with ext3_link() which might bump
         * ->i_nlink. For, say it, character device. Not a regular file,
         * not a directory, not a symlink and ->i_nlink > 0.
+        *
+        * tytso, 4/25/2009: I'm not sure how that could happen;
+        * shouldn't the fs core protect us from these sort of
+        * unlink()/link() races?
         */
        J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
                S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
@@ -1968,7 +1972,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
        jbd_debug(4, "orphan inode %lu will point to %d\n",
                        inode->i_ino, NEXT_ORPHAN(inode));
 out_unlock:
-       unlock_super(sb);
+       mutex_unlock(&EXT3_SB(sb)->s_orphan_lock);
        ext3_std_error(inode->i_sb, err);
        return err;
 }
@@ -1986,11 +1990,9 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode)
        struct ext3_iloc iloc;
        int err = 0;
 
-       lock_super(inode->i_sb);
-       if (list_empty(&ei->i_orphan)) {
-               unlock_super(inode->i_sb);
-               return 0;
-       }
+       mutex_lock(&EXT3_SB(inode->i_sb)->s_orphan_lock);
+       if (list_empty(&ei->i_orphan))
+               goto out;
 
        ino_next = NEXT_ORPHAN(inode);
        prev = ei->i_orphan.prev;
@@ -2040,7 +2042,7 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode)
 out_err:
        ext3_std_error(inode->i_sb, err);
 out:
-       unlock_super(inode->i_sb);
+       mutex_unlock(&EXT3_SB(inode->i_sb)->s_orphan_lock);
        return err;
 
 out_brelse:
@@ -2175,7 +2177,7 @@ static int ext3_symlink (struct inode * dir,
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
+                                       EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
index 5f83b61..54351ac 100644 (file)
@@ -209,7 +209,7 @@ static int setup_new_group_blocks(struct super_block *sb,
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_resize_lock);
        if (input->group != sbi->s_groups_count) {
                err = -EBUSY;
                goto exit_journal;
@@ -324,7 +324,7 @@ exit_bh:
        brelse(bh);
 
 exit_journal:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_resize_lock);
        if ((err2 = ext3_journal_stop(handle)) && !err)
                err = err2;
 
@@ -662,11 +662,12 @@ exit_free:
  * important part is that the new block and inode counts are in the backup
  * superblocks, and the location of the new group metadata in the GDT backups.
  *
- * We do not need lock_super() for this, because these blocks are not
- * otherwise touched by the filesystem code when it is mounted.  We don't
- * need to worry about last changing from sbi->s_groups_count, because the
- * worst that can happen is that we do not copy the full number of backups
- * at this time.  The resize which changed s_groups_count will backup again.
+ * We do not need take the s_resize_lock for this, because these
+ * blocks are not otherwise touched by the filesystem code when it is
+ * mounted.  We don't need to worry about last changing from
+ * sbi->s_groups_count, because the worst that can happen is that we
+ * do not copy the full number of backups at this time.  The resize
+ * which changed s_groups_count will backup again.
  */
 static void update_backups(struct super_block *sb,
                           int blk_off, char *data, int size)
@@ -825,7 +826,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
                goto exit_put;
        }
 
-       lock_super(sb);
+       mutex_lock(&sbi->s_resize_lock);
        if (input->group != sbi->s_groups_count) {
                ext3_warning(sb, __func__,
                             "multiple resizers run on filesystem!");
@@ -856,7 +857,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
        /*
         * OK, now we've set up the new group.  Time to make it active.
         *
-        * Current kernels don't lock all allocations via lock_super(),
+        * We do not lock all allocations via s_resize_lock
         * so we have to be safe wrt. concurrent accesses the group
         * data.  So we need to be careful to set all of the relevant
         * group descriptor data etc. *before* we enable the group.
@@ -900,12 +901,12 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
         *
         * The precise rules we use are:
         *
-        * * Writers of s_groups_count *must* hold lock_super
+        * * Writers of s_groups_count *must* hold s_resize_lock
         * AND
         * * Writers must perform a smp_wmb() after updating all dependent
         *   data and before modifying the groups count
         *
-        * * Readers must hold lock_super() over the access
+        * * Readers must hold s_resize_lock over the access
         * OR
         * * Readers must perform an smp_rmb() after reading the groups count
         *   and before reading any dependent data.
@@ -936,7 +937,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
        ext3_journal_dirty_metadata(handle, sbi->s_sbh);
 
 exit_journal:
-       unlock_super(sb);
+       mutex_unlock(&sbi->s_resize_lock);
        if ((err2 = ext3_journal_stop(handle)) && !err)
                err = err2;
        if (!err) {
@@ -973,7 +974,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
 
        /* We don't need to worry about locking wrt other resizers just
         * yet: we're going to revalidate es->s_blocks_count after
-        * taking lock_super() below. */
+        * taking the s_resize_lock below. */
        o_blocks_count = le32_to_cpu(es->s_blocks_count);
        o_groups_count = EXT3_SB(sb)->s_groups_count;
 
@@ -1045,11 +1046,11 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
                goto exit_put;
        }
 
-       lock_super(sb);
+       mutex_lock(&EXT3_SB(sb)->s_resize_lock);
        if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
                ext3_warning(sb, __func__,
                             "multiple resizers run on filesystem!");
-               unlock_super(sb);
+               mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
                ext3_journal_stop(handle);
                err = -EBUSY;
                goto exit_put;
@@ -1059,13 +1060,13 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
                                                 EXT3_SB(sb)->s_sbh))) {
                ext3_warning(sb, __func__,
                             "error %d on journal write access", err);
-               unlock_super(sb);
+               mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
                ext3_journal_stop(handle);
                goto exit_put;
        }
        es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
        ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-       unlock_super(sb);
+       mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
        ext3_debug("freeing blocks %lu through "E3FSBLK"\n", o_blocks_count,
                   o_blocks_count + add);
        ext3_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks);
index 7ad1e8c..afa2b56 100644 (file)
@@ -1928,6 +1928,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sb->dq_op = &ext3_quota_operations;
 #endif
        INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
+       mutex_init(&sbi->s_orphan_lock);
+       mutex_init(&sbi->s_resize_lock);
 
        sb->s_root = NULL;
 
@@ -2014,14 +2016,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        }
 
        ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-       /*
-        * akpm: core read_super() calls in here with the superblock locked.
-        * That deadlocks, because orphan cleanup needs to lock the superblock
-        * in numerous places.  Here we just pop the lock - it's relatively
-        * harmless, because we are now ready to accept write_super() requests,
-        * and aviro says that's the only reason for hanging onto the
-        * superblock lock.
-        */
+
        EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS;
        ext3_orphan_cleanup(sb, es);
        EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;
@@ -2403,13 +2398,11 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
        if (journal_flush(journal) < 0)
                goto out;
 
-       lock_super(sb);
        if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
            sb->s_flags & MS_RDONLY) {
                EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
                ext3_commit_super(sb, es, 1);
        }
-       unlock_super(sb);
 
 out:
        journal_unlock_updates(journal);
@@ -2601,13 +2594,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                            (sbi->s_mount_state & EXT3_VALID_FS))
                                es->s_state = cpu_to_le16(sbi->s_mount_state);
 
-                       /*
-                        * We have to unlock super so that we can wait for
-                        * transactions.
-                        */
-                       unlock_super(sb);
                        ext3_mark_recovery_complete(sb, es);
-                       lock_super(sb);
                } else {
                        __le32 ret;
                        if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
index ab31e65..56f9271 100644 (file)
@@ -704,6 +704,10 @@ struct ext4_inode_info {
        __u16 i_extra_isize;
 
        spinlock_t i_block_reservation_lock;
+#ifdef CONFIG_QUOTA
+       /* quota space reservation, managed internally by quota code */
+       qsize_t i_reserved_quota;
+#endif
 
        /* completed async DIOs that might need unwritten extents handling */
        struct list_head i_aio_dio_complete_list;
@@ -1435,7 +1439,7 @@ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks);
 extern int ext4_block_truncate_page(handle_t *handle,
                struct address_space *mapping, loff_t from);
 extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
-extern qsize_t ext4_get_reserved_space(struct inode *inode);
+extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern int flush_aio_dio_completed_IO(struct inode *inode);
 /* ioctl.c */
 extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
index 5352db1..ab80796 100644 (file)
@@ -1003,17 +1003,12 @@ out:
        return err;
 }
 
-qsize_t ext4_get_reserved_space(struct inode *inode)
+#ifdef CONFIG_QUOTA
+qsize_t *ext4_get_reserved_space(struct inode *inode)
 {
-       unsigned long long total;
-
-       spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
-       total = EXT4_I(inode)->i_reserved_data_blocks +
-               EXT4_I(inode)->i_reserved_meta_blocks;
-       spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
-
-       return (total << inode->i_blkbits);
+       return &EXT4_I(inode)->i_reserved_quota;
 }
+#endif
 /*
  * Calculate the number of metadata blocks need to reserve
  * to allocate @blocks for non extent file based file
@@ -1051,7 +1046,7 @@ static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
 static void ext4_da_update_reserve_space(struct inode *inode, int used)
 {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-       int total, mdb, mdb_free;
+       int total, mdb, mdb_free, mdb_claim = 0;
 
        spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
        /* recalculate the number of metablocks still need to be reserved */
@@ -1064,7 +1059,9 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
 
        if (mdb_free) {
                /* Account for allocated meta_blocks */
-               mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks;
+               mdb_claim = EXT4_I(inode)->i_allocated_meta_blocks;
+               BUG_ON(mdb_free < mdb_claim);
+               mdb_free -= mdb_claim;
 
                /* update fs dirty blocks counter */
                percpu_counter_sub(&sbi->s_dirtyblocks_counter, mdb_free);
@@ -1075,8 +1072,11 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
        /* update per-inode reservations */
        BUG_ON(used  > EXT4_I(inode)->i_reserved_data_blocks);
        EXT4_I(inode)->i_reserved_data_blocks -= used;
+       percpu_counter_sub(&sbi->s_dirtyblocks_counter, used + mdb_claim);
        spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
+       vfs_dq_claim_block(inode, used + mdb_claim);
+
        /*
         * free those over-booking quota for metadata blocks
         */
@@ -1816,19 +1816,17 @@ repeat:
 
        md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks;
        total = md_needed + nrblocks;
+       spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
        /*
         * Make quota reservation here to prevent quota overflow
         * later. Real quota accounting is done at pages writeout
         * time.
         */
-       if (vfs_dq_reserve_block(inode, total)) {
-               spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+       if (vfs_dq_reserve_block(inode, total))
                return -EDQUOT;
-       }
 
        if (ext4_claim_free_blocks(sbi, total)) {
-               spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
                vfs_dq_release_reservation_block(inode, total);
                if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
                        yield();
@@ -1836,10 +1834,11 @@ repeat:
                }
                return -ENOSPC;
        }
+       spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
        EXT4_I(inode)->i_reserved_data_blocks += nrblocks;
-       EXT4_I(inode)->i_reserved_meta_blocks = mdblocks;
-
+       EXT4_I(inode)->i_reserved_meta_blocks += md_needed;
        spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+
        return 0;       /* success */
 }
 
@@ -4794,6 +4793,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
                        ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
        inode->i_size = ext4_isize(raw_inode);
        ei->i_disksize = inode->i_size;
+#ifdef CONFIG_QUOTA
+       ei->i_reserved_quota = 0;
+#endif
        inode->i_generation = le32_to_cpu(raw_inode->i_generation);
        ei->i_block_group = iloc.block_group;
        ei->i_last_alloc_group = ~0;
index b1fd3da..d34afad 100644 (file)
@@ -2755,12 +2755,6 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
                /* release all the reserved blocks if non delalloc */
                percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks);
-       else {
-               percpu_counter_sub(&sbi->s_dirtyblocks_counter,
-                                               ac->ac_b_ex.fe_len);
-               /* convert reserved quota blocks to real quota blocks */
-               vfs_dq_claim_block(ac->ac_inode, ac->ac_b_ex.fe_len);
-       }
 
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi,
index 827bde1..6ed9aa9 100644 (file)
@@ -704,6 +704,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        ei->i_allocated_meta_blocks = 0;
        ei->i_delalloc_reserved_flag = 0;
        spin_lock_init(&(ei->i_block_reservation_lock));
+#ifdef CONFIG_QUOTA
+       ei->i_reserved_quota = 0;
+#endif
        INIT_LIST_HEAD(&ei->i_aio_dio_complete_list);
        ei->cur_aio_dio = NULL;
        ei->i_sync_tid = 0;
@@ -1014,7 +1017,9 @@ static const struct dquot_operations ext4_quota_operations = {
        .reserve_space  = dquot_reserve_space,
        .claim_space    = dquot_claim_space,
        .release_rsv    = dquot_release_reserved_space,
+#ifdef CONFIG_QUOTA
        .get_reserved_space = ext4_get_reserved_space,
+#endif
        .alloc_inode    = dquot_alloc_inode,
        .free_space     = dquot_free_space,
        .free_inode     = dquot_free_inode,
index 4160afa..bd224ee 100644 (file)
@@ -1913,7 +1913,7 @@ static void __init jbd_create_debugfs_entry(void)
 {
        jbd_debugfs_dir = debugfs_create_dir("jbd", NULL);
        if (jbd_debugfs_dir)
-               jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO,
+               jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO | S_IWUSR,
                                               jbd_debugfs_dir,
                                               &journal_enable_debug);
 }
index b7ca3a9..17af879 100644 (file)
@@ -2115,7 +2115,8 @@ static void __init jbd2_create_debugfs_entry(void)
 {
        jbd2_debugfs_dir = debugfs_create_dir("jbd2", NULL);
        if (jbd2_debugfs_dir)
-               jbd2_debug = debugfs_create_u8(JBD2_DEBUG_NAME, S_IRUGO,
+               jbd2_debug = debugfs_create_u8(JBD2_DEBUG_NAME,
+                                              S_IRUGO | S_IWUSR,
                                               jbd2_debugfs_dir,
                                               &jbd2_journal_enable_debug);
 }
index fb4e672..d17bdc7 100644 (file)
@@ -1765,9 +1765,9 @@ set_and_inc:
  *
  * The array index of the subtree root is passed back.
  */
-static int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
-                                  struct ocfs2_path *left,
-                                  struct ocfs2_path *right)
+int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
+                           struct ocfs2_path *left,
+                           struct ocfs2_path *right)
 {
        int i = 0;
 
@@ -2872,8 +2872,8 @@ out:
  * This looks similar, but is subtly different to
  * ocfs2_find_cpos_for_left_leaf().
  */
-static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
-                                         struct ocfs2_path *path, u32 *cpos)
+int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+                                  struct ocfs2_path *path, u32 *cpos)
 {
        int i, j, ret = 0;
        u64 blkno;
index 9c122d5..1db4359 100644 (file)
@@ -317,4 +317,9 @@ int ocfs2_path_bh_journal_access(handle_t *handle,
 int ocfs2_journal_access_path(struct ocfs2_caching_info *ci,
                              handle_t *handle,
                              struct ocfs2_path *path);
+int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+                                  struct ocfs2_path *path, u32 *cpos);
+int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
+                           struct ocfs2_path *left,
+                           struct ocfs2_path *right);
 #endif /* OCFS2_ALLOC_H */
index f010b22..3e9b460 100644 (file)
@@ -2108,6 +2108,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
        }
        did_quota_inode = 1;
 
+       inode->i_nlink = 0;
        /* do the real work now. */
        status = ocfs2_mknod_locked(osb, dir, inode,
                                    0, &new_di_bh, parent_di_bh, handle,
@@ -2136,6 +2137,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
        if (status < 0)
                mlog_errno(status);
 
+       insert_inode_hash(inode);
 leave:
        if (status < 0 && did_quota_inode)
                vfs_dq_free_inode(inode);
@@ -2267,6 +2269,8 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
        di = (struct ocfs2_dinode *)di_bh->b_data;
        le32_add_cpu(&di->i_flags, -OCFS2_ORPHANED_FL);
        di->i_orphaned_slot = 0;
+       inode->i_nlink = 1;
+       ocfs2_set_links_count(di, inode->i_nlink);
        ocfs2_journal_dirty(handle, di_bh);
 
        status = ocfs2_add_entry(handle, dentry, inode,
@@ -2284,7 +2288,6 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
                goto out_commit;
        }
 
-       insert_inode_hash(inode);
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
        status = 0;
index 30967e3..74db2be 100644 (file)
@@ -276,7 +276,7 @@ static void ocfs2_erase_refcount_tree_from_list(struct ocfs2_super *osb,
        spin_unlock(&osb->osb_lock);
 }
 
-void ocfs2_kref_remove_refcount_tree(struct kref *kref)
+static void ocfs2_kref_remove_refcount_tree(struct kref *kref)
 {
        struct ocfs2_refcount_tree *tree =
                container_of(kref, struct ocfs2_refcount_tree, rf_getcnt);
@@ -524,23 +524,6 @@ out:
        return ret;
 }
 
-int ocfs2_lock_refcount_tree_by_inode(struct inode *inode, int rw,
-                                     struct ocfs2_refcount_tree **ret_tree,
-                                     struct buffer_head **ref_bh)
-{
-       int ret;
-       u64 ref_blkno;
-
-       ret = ocfs2_get_refcount_block(inode, &ref_blkno);
-       if (ret) {
-               mlog_errno(ret);
-               return ret;
-       }
-
-       return ocfs2_lock_refcount_tree(OCFS2_SB(inode->i_sb), ref_blkno,
-                                       rw, ret_tree, ref_bh);
-}
-
 void ocfs2_unlock_refcount_tree(struct ocfs2_super *osb,
                                struct ocfs2_refcount_tree *tree, int rw)
 {
@@ -969,6 +952,103 @@ out:
 }
 
 /*
+ * Find the end range for a leaf refcount block indicated by
+ * el->l_recs[index].e_blkno.
+ */
+static int ocfs2_get_refcount_cpos_end(struct ocfs2_caching_info *ci,
+                                      struct buffer_head *ref_root_bh,
+                                      struct ocfs2_extent_block *eb,
+                                      struct ocfs2_extent_list *el,
+                                      int index,  u32 *cpos_end)
+{
+       int ret, i, subtree_root;
+       u32 cpos;
+       u64 blkno;
+       struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
+       struct ocfs2_path *left_path = NULL, *right_path = NULL;
+       struct ocfs2_extent_tree et;
+       struct ocfs2_extent_list *tmp_el;
+
+       if (index < le16_to_cpu(el->l_next_free_rec) - 1) {
+               /*
+                * We have a extent rec after index, so just use the e_cpos
+                * of the next extent rec.
+                */
+               *cpos_end = le32_to_cpu(el->l_recs[index+1].e_cpos);
+               return 0;
+       }
+
+       if (!eb || (eb && !eb->h_next_leaf_blk)) {
+               /*
+                * We are the last extent rec, so any high cpos should
+                * be stored in this leaf refcount block.
+                */
+               *cpos_end = UINT_MAX;
+               return 0;
+       }
+
+       /*
+        * If the extent block isn't the last one, we have to find
+        * the subtree root between this extent block and the next
+        * leaf extent block and get the corresponding e_cpos from
+        * the subroot. Otherwise we may corrupt the b-tree.
+        */
+       ocfs2_init_refcount_extent_tree(&et, ci, ref_root_bh);
+
+       left_path = ocfs2_new_path_from_et(&et);
+       if (!left_path) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       cpos = le32_to_cpu(eb->h_list.l_recs[index].e_cpos);
+       ret = ocfs2_find_path(ci, left_path, cpos);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       right_path = ocfs2_new_path_from_path(left_path);
+       if (!right_path) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_find_cpos_for_right_leaf(sb, left_path, &cpos);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_find_path(ci, right_path, cpos);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       subtree_root = ocfs2_find_subtree_root(&et, left_path,
+                                              right_path);
+
+       tmp_el = left_path->p_node[subtree_root].el;
+       blkno = left_path->p_node[subtree_root+1].bh->b_blocknr;
+       for (i = 0; i < le32_to_cpu(tmp_el->l_next_free_rec); i++) {
+               if (le64_to_cpu(tmp_el->l_recs[i].e_blkno) == blkno) {
+                       *cpos_end = le32_to_cpu(tmp_el->l_recs[i+1].e_cpos);
+                       break;
+               }
+       }
+
+       BUG_ON(i == le32_to_cpu(tmp_el->l_next_free_rec));
+
+out:
+       ocfs2_free_path(left_path);
+       ocfs2_free_path(right_path);
+       return ret;
+}
+
+/*
  * Given a cpos and len, try to find the refcount record which contains cpos.
  * 1. If cpos can be found in one refcount record, return the record.
  * 2. If cpos can't be found, return a fake record which start from cpos
@@ -983,10 +1063,10 @@ static int ocfs2_get_refcount_rec(struct ocfs2_caching_info *ci,
                                  struct buffer_head **ret_bh)
 {
        int ret = 0, i, found;
-       u32 low_cpos;
+       u32 low_cpos, uninitialized_var(cpos_end);
        struct ocfs2_extent_list *el;
-       struct ocfs2_extent_rec *tmp, *rec = NULL;
-       struct ocfs2_extent_block *eb;
+       struct ocfs2_extent_rec *rec = NULL;
+       struct ocfs2_extent_block *eb = NULL;
        struct buffer_head *eb_bh = NULL, *ref_leaf_bh = NULL;
        struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
        struct ocfs2_refcount_block *rb =
@@ -1034,12 +1114,16 @@ static int ocfs2_get_refcount_rec(struct ocfs2_caching_info *ci,
                }
        }
 
-       /* adjust len when we have ocfs2_extent_rec after it. */
-       if (found && i < le16_to_cpu(el->l_next_free_rec) - 1) {
-               tmp = &el->l_recs[i+1];
+       if (found) {
+               ret = ocfs2_get_refcount_cpos_end(ci, ref_root_bh,
+                                                 eb, el, i, &cpos_end);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
 
-               if (le32_to_cpu(tmp->e_cpos) < cpos + len)
-                       len = le32_to_cpu(tmp->e_cpos) - cpos;
+               if (cpos_end < low_cpos + len)
+                       len = cpos_end - low_cpos;
        }
 
        ret = ocfs2_read_refcount_block(ci, le64_to_cpu(rec->e_blkno),
@@ -1418,7 +1502,7 @@ static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh,
 
        /* change old and new rl_used accordingly. */
        le16_add_cpu(&rl->rl_used, -num_moved);
-       new_rl->rl_used = cpu_to_le32(num_moved);
+       new_rl->rl_used = cpu_to_le16(num_moved);
 
        sort(&rl->rl_recs, le16_to_cpu(rl->rl_used),
             sizeof(struct ocfs2_refcount_rec),
@@ -1797,7 +1881,8 @@ static int ocfs2_split_refcount_rec(handle_t *handle,
                recs_need++;
 
        /* If the leaf block don't have enough record, expand it. */
-       if (le16_to_cpu(rf_list->rl_used) + recs_need > rf_list->rl_count) {
+       if (le16_to_cpu(rf_list->rl_used) + recs_need >
+                                        le16_to_cpu(rf_list->rl_count)) {
                struct ocfs2_refcount_rec tmp_rec;
                u64 cpos = le64_to_cpu(orig_rec->r_cpos);
                len = le32_to_cpu(orig_rec->r_clusters);
@@ -1859,7 +1944,7 @@ static int ocfs2_split_refcount_rec(handle_t *handle,
                memcpy(tail_rec, orig_rec, sizeof(struct ocfs2_refcount_rec));
                le64_add_cpu(&tail_rec->r_cpos,
                             le32_to_cpu(tail_rec->r_clusters) - len);
-               tail_rec->r_clusters = le32_to_cpu(len);
+               tail_rec->r_clusters = cpu_to_le32(len);
        }
 
        /*
@@ -3840,8 +3925,7 @@ static int ocfs2_add_refcounted_extent(struct inode *inode,
        }
 
        ret = ocfs2_insert_extent(handle, et, cpos,
-                       cpu_to_le64(ocfs2_clusters_to_blocks(inode->i_sb,
-                                                            p_cluster)),
+                       ocfs2_clusters_to_blocks(inode->i_sb, p_cluster),
                        num_clusters, ext_flags, meta_ac);
        if (ret) {
                mlog_errno(ret);
@@ -4253,8 +4337,8 @@ static int ocfs2_user_path_parent(const char __user *path,
  * @new_dentry:        target dentry
  * @preserve:  if true, preserve all file attributes
  */
-int ocfs2_vfs_reflink(struct dentry *old_dentry, struct inode *dir,
-                     struct dentry *new_dentry, bool preserve)
+static int ocfs2_vfs_reflink(struct dentry *old_dentry, struct inode *dir,
+                            struct dentry *new_dentry, bool preserve)
 {
        struct inode *inode = old_dentry->d_inode;
        int error;
index cd6bb9a..dea86ab 100644 (file)
@@ -323,6 +323,30 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
 }
 EXPORT_SYMBOL(dquot_mark_dquot_dirty);
 
+/* Dirtify all the dquots - this can block when journalling */
+static inline int mark_all_dquot_dirty(struct dquot * const *dquot)
+{
+       int ret, err, cnt;
+
+       ret = err = 0;
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               if (dquot[cnt])
+                       /* Even in case of error we have to continue */
+                       ret = mark_dquot_dirty(dquot[cnt]);
+               if (!err)
+                       err = ret;
+       }
+       return err;
+}
+
+static inline void dqput_all(struct dquot **dquot)
+{
+       unsigned int cnt;
+
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               dqput(dquot[cnt]);
+}
+
 /* This function needs dq_list_lock */
 static inline int clear_dquot_dirty(struct dquot *dquot)
 {
@@ -1268,8 +1292,7 @@ int dquot_initialize(struct inode *inode, int type)
 out_err:
        up_write(&sb_dqopt(sb)->dqptr_sem);
        /* Drop unused references */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               dqput(got[cnt]);
+       dqput_all(got);
        return ret;
 }
 EXPORT_SYMBOL(dquot_initialize);
@@ -1288,9 +1311,7 @@ int dquot_drop(struct inode *inode)
                inode->i_dquot[cnt] = NULL;
        }
        up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               dqput(put[cnt]);
+       dqput_all(put);
        return 0;
 }
 EXPORT_SYMBOL(dquot_drop);
@@ -1319,6 +1340,67 @@ void vfs_dq_drop(struct inode *inode)
 EXPORT_SYMBOL(vfs_dq_drop);
 
 /*
+ * inode_reserved_space is managed internally by quota, and protected by
+ * i_lock similar to i_blocks+i_bytes.
+ */
+static qsize_t *inode_reserved_space(struct inode * inode)
+{
+       /* Filesystem must explicitly define it's own method in order to use
+        * quota reservation interface */
+       BUG_ON(!inode->i_sb->dq_op->get_reserved_space);
+       return inode->i_sb->dq_op->get_reserved_space(inode);
+}
+
+static void inode_add_rsv_space(struct inode *inode, qsize_t number)
+{
+       spin_lock(&inode->i_lock);
+       *inode_reserved_space(inode) += number;
+       spin_unlock(&inode->i_lock);
+}
+
+
+static void inode_claim_rsv_space(struct inode *inode, qsize_t number)
+{
+       spin_lock(&inode->i_lock);
+       *inode_reserved_space(inode) -= number;
+       __inode_add_bytes(inode, number);
+       spin_unlock(&inode->i_lock);
+}
+
+static void inode_sub_rsv_space(struct inode *inode, qsize_t number)
+{
+       spin_lock(&inode->i_lock);
+       *inode_reserved_space(inode) -= number;
+       spin_unlock(&inode->i_lock);
+}
+
+static qsize_t inode_get_rsv_space(struct inode *inode)
+{
+       qsize_t ret;
+       spin_lock(&inode->i_lock);
+       ret = *inode_reserved_space(inode);
+       spin_unlock(&inode->i_lock);
+       return ret;
+}
+
+static void inode_incr_space(struct inode *inode, qsize_t number,
+                               int reserve)
+{
+       if (reserve)
+               inode_add_rsv_space(inode, number);
+       else
+               inode_add_bytes(inode, number);
+}
+
+static void inode_decr_space(struct inode *inode, qsize_t number, int reserve)
+{
+       if (reserve)
+               inode_sub_rsv_space(inode, number);
+       else
+               inode_sub_bytes(inode, number);
+}
+
+/*
  * Following four functions update i_blocks+i_bytes fields and
  * quota information (together with appropriate checks)
  * NOTE: We absolutely rely on the fact that caller dirties
@@ -1336,6 +1418,21 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number,
        int cnt, ret = QUOTA_OK;
        char warntype[MAXQUOTAS];
 
+       /*
+        * First test before acquiring mutex - solves deadlocks when we
+        * re-enter the quota code and are already holding the mutex
+        */
+       if (IS_NOQUOTA(inode)) {
+               inode_incr_space(inode, number, reserve);
+               goto out;
+       }
+
+       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+       if (IS_NOQUOTA(inode)) {
+               inode_incr_space(inode, number, reserve);
+               goto out_unlock;
+       }
+
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
                warntype[cnt] = QUOTA_NL_NOWARN;
 
@@ -1346,7 +1443,8 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number,
                if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt)
                    == NO_QUOTA) {
                        ret = NO_QUOTA;
-                       goto out_unlock;
+                       spin_unlock(&dq_data_lock);
+                       goto out_flush_warn;
                }
        }
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1357,64 +1455,29 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number,
                else
                        dquot_incr_space(inode->i_dquot[cnt], number);
        }
-       if (!reserve)
-               inode_add_bytes(inode, number);
-out_unlock:
+       inode_incr_space(inode, number, reserve);
        spin_unlock(&dq_data_lock);
+
+       if (reserve)
+               goto out_flush_warn;
+       mark_all_dquot_dirty(inode->i_dquot);
+out_flush_warn:
        flush_warnings(inode->i_dquot, warntype);
+out_unlock:
+       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
        return ret;
 }
 
 int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
 {
-       int cnt, ret = QUOTA_OK;
-
-       /*
-        * First test before acquiring mutex - solves deadlocks when we
-        * re-enter the quota code and are already holding the mutex
-        */
-       if (IS_NOQUOTA(inode)) {
-               inode_add_bytes(inode, number);
-               goto out;
-       }
-
-       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-       if (IS_NOQUOTA(inode)) {
-               inode_add_bytes(inode, number);
-               goto out_unlock;
-       }
-
-       ret = __dquot_alloc_space(inode, number, warn, 0);
-       if (ret == NO_QUOTA)
-               goto out_unlock;
-
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if (inode->i_dquot[cnt])
-                       mark_dquot_dirty(inode->i_dquot[cnt]);
-out_unlock:
-       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-out:
-       return ret;
+       return __dquot_alloc_space(inode, number, warn, 0);
 }
 EXPORT_SYMBOL(dquot_alloc_space);
 
 int dquot_reserve_space(struct inode *inode, qsize_t number, int warn)
 {
-       int ret = QUOTA_OK;
-
-       if (IS_NOQUOTA(inode))
-               goto out;
-
-       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-       if (IS_NOQUOTA(inode))
-               goto out_unlock;
-
-       ret = __dquot_alloc_space(inode, number, warn, 1);
-out_unlock:
-       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-out:
-       return ret;
+       return __dquot_alloc_space(inode, number, warn, 1);
 }
 EXPORT_SYMBOL(dquot_reserve_space);
 
@@ -1455,10 +1518,7 @@ int dquot_alloc_inode(const struct inode *inode, qsize_t number)
 warn_put_all:
        spin_unlock(&dq_data_lock);
        if (ret == QUOTA_OK)
-               /* Dirtify all the dquots - this can block when journalling */
-               for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-                       if (inode->i_dquot[cnt])
-                               mark_dquot_dirty(inode->i_dquot[cnt]);
+               mark_all_dquot_dirty(inode->i_dquot);
        flush_warnings(inode->i_dquot, warntype);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        return ret;
@@ -1471,14 +1531,14 @@ int dquot_claim_space(struct inode *inode, qsize_t number)
        int ret = QUOTA_OK;
 
        if (IS_NOQUOTA(inode)) {
-               inode_add_bytes(inode, number);
+               inode_claim_rsv_space(inode, number);
                goto out;
        }
 
        down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        if (IS_NOQUOTA(inode))  {
                up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-               inode_add_bytes(inode, number);
+               inode_claim_rsv_space(inode, number);
                goto out;
        }
 
@@ -1490,12 +1550,9 @@ int dquot_claim_space(struct inode *inode, qsize_t number)
                                                        number);
        }
        /* Update inode bytes */
-       inode_add_bytes(inode, number);
+       inode_claim_rsv_space(inode, number);
        spin_unlock(&dq_data_lock);
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if (inode->i_dquot[cnt])
-                       mark_dquot_dirty(inode->i_dquot[cnt]);
+       mark_all_dquot_dirty(inode->i_dquot);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 out:
        return ret;
@@ -1503,38 +1560,9 @@ out:
 EXPORT_SYMBOL(dquot_claim_space);
 
 /*
- * Release reserved quota space
- */
-void dquot_release_reserved_space(struct inode *inode, qsize_t number)
-{
-       int cnt;
-
-       if (IS_NOQUOTA(inode))
-               goto out;
-
-       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-       if (IS_NOQUOTA(inode))
-               goto out_unlock;
-
-       spin_lock(&dq_data_lock);
-       /* Release reserved dquots */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               if (inode->i_dquot[cnt])
-                       dquot_free_reserved_space(inode->i_dquot[cnt], number);
-       }
-       spin_unlock(&dq_data_lock);
-
-out_unlock:
-       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-out:
-       return;
-}
-EXPORT_SYMBOL(dquot_release_reserved_space);
-
-/*
  * This operation can block, but only after everything is updated
  */
-int dquot_free_space(struct inode *inode, qsize_t number)
+int __dquot_free_space(struct inode *inode, qsize_t number, int reserve)
 {
        unsigned int cnt;
        char warntype[MAXQUOTAS];
@@ -1543,7 +1571,7 @@ int dquot_free_space(struct inode *inode, qsize_t number)
          * re-enter the quota code and are already holding the mutex */
        if (IS_NOQUOTA(inode)) {
 out_sub:
-               inode_sub_bytes(inode, number);
+               inode_decr_space(inode, number, reserve);
                return QUOTA_OK;
        }
 
@@ -1558,21 +1586,40 @@ out_sub:
                if (!inode->i_dquot[cnt])
                        continue;
                warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number);
-               dquot_decr_space(inode->i_dquot[cnt], number);
+               if (reserve)
+                       dquot_free_reserved_space(inode->i_dquot[cnt], number);
+               else
+                       dquot_decr_space(inode->i_dquot[cnt], number);
        }
-       inode_sub_bytes(inode, number);
+       inode_decr_space(inode, number, reserve);
        spin_unlock(&dq_data_lock);
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if (inode->i_dquot[cnt])
-                       mark_dquot_dirty(inode->i_dquot[cnt]);
+
+       if (reserve)
+               goto out_unlock;
+       mark_all_dquot_dirty(inode->i_dquot);
+out_unlock:
        flush_warnings(inode->i_dquot, warntype);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        return QUOTA_OK;
 }
+
+int dquot_free_space(struct inode *inode, qsize_t number)
+{
+       return  __dquot_free_space(inode, number, 0);
+}
 EXPORT_SYMBOL(dquot_free_space);
 
 /*
+ * Release reserved quota space
+ */
+void dquot_release_reserved_space(struct inode *inode, qsize_t number)
+{
+       __dquot_free_space(inode, number, 1);
+
+}
+EXPORT_SYMBOL(dquot_release_reserved_space);
+
+/*
  * This operation can block, but only after everything is updated
  */
 int dquot_free_inode(const struct inode *inode, qsize_t number)
@@ -1599,10 +1646,7 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
                dquot_decr_inodes(inode->i_dquot[cnt], number);
        }
        spin_unlock(&dq_data_lock);
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if (inode->i_dquot[cnt])
-                       mark_dquot_dirty(inode->i_dquot[cnt]);
+       mark_all_dquot_dirty(inode->i_dquot);
        flush_warnings(inode->i_dquot, warntype);
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        return QUOTA_OK;
@@ -1610,19 +1654,6 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
 EXPORT_SYMBOL(dquot_free_inode);
 
 /*
- * call back function, get reserved quota space from underlying fs
- */
-qsize_t dquot_get_reserved_space(struct inode *inode)
-{
-       qsize_t reserved_space = 0;
-
-       if (sb_any_quota_active(inode->i_sb) &&
-           inode->i_sb->dq_op->get_reserved_space)
-               reserved_space = inode->i_sb->dq_op->get_reserved_space(inode);
-       return reserved_space;
-}
-
-/*
  * Transfer the number of inode and blocks from one diskquota to an other.
  *
  * This operation can block, but only after everything is updated
@@ -1665,7 +1696,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
        }
        spin_lock(&dq_data_lock);
        cur_space = inode_get_bytes(inode);
-       rsv_space = dquot_get_reserved_space(inode);
+       rsv_space = inode_get_rsv_space(inode);
        space = cur_space + rsv_space;
        /* Build the transfer_from list and check the limits */
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1709,25 +1740,18 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
        spin_unlock(&dq_data_lock);
        up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
 
-       /* Dirtify all the dquots - this can block when journalling */
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               if (transfer_from[cnt])
-                       mark_dquot_dirty(transfer_from[cnt]);
-               if (transfer_to[cnt]) {
-                       mark_dquot_dirty(transfer_to[cnt]);
-                       /* The reference we got is transferred to the inode */
-                       transfer_to[cnt] = NULL;
-               }
-       }
+       mark_all_dquot_dirty(transfer_from);
+       mark_all_dquot_dirty(transfer_to);
+       /* The reference we got is transferred to the inode */
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               transfer_to[cnt] = NULL;
 warn_put_all:
        flush_warnings(transfer_to, warntype_to);
        flush_warnings(transfer_from, warntype_from_inodes);
        flush_warnings(transfer_from, warntype_from_space);
 put_all:
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               dqput(transfer_from[cnt]);
-               dqput(transfer_to[cnt]);
-       }
+       dqput_all(transfer_from);
+       dqput_all(transfer_to);
        return ret;
 over_quota:
        spin_unlock(&dq_data_lock);
index 3dfc23e..e3da02f 100644 (file)
@@ -97,8 +97,11 @@ static int v2_read_file_info(struct super_block *sb, int type)
        unsigned int version;
 
        if (!v2_read_header(sb, type, &dqhead))
-               return 0;
+               return -1;
        version = le32_to_cpu(dqhead.dqh_version);
+       if ((info->dqi_fmt_id == QFMT_VFS_V0 && version != 0) ||
+           (info->dqi_fmt_id == QFMT_VFS_V1 && version != 1))
+               return -1;
 
        size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
               sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
@@ -120,8 +123,8 @@ static int v2_read_file_info(struct super_block *sb, int type)
                info->dqi_maxilimit = 0xffffffff;
        } else {
                /* used space is stored as unsigned 64-bit value */
-               info->dqi_maxblimit = 0xffffffffffffffff;       /* 2^64-1 */
-               info->dqi_maxilimit = 0xffffffffffffffff;
+               info->dqi_maxblimit = 0xffffffffffffffffULL;    /* 2^64-1 */
+               info->dqi_maxilimit = 0xffffffffffffffffULL;
        }
        info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
        info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
index 075694e..c4ecd52 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -401,9 +401,9 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, char __user *, filename,
 }
 #endif /* __ARCH_WANT_STAT64 */
 
-void inode_add_bytes(struct inode *inode, loff_t bytes)
+/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
+void __inode_add_bytes(struct inode *inode, loff_t bytes)
 {
-       spin_lock(&inode->i_lock);
        inode->i_blocks += bytes >> 9;
        bytes &= 511;
        inode->i_bytes += bytes;
@@ -411,6 +411,12 @@ void inode_add_bytes(struct inode *inode, loff_t bytes)
                inode->i_blocks++;
                inode->i_bytes -= 512;
        }
+}
+
+void inode_add_bytes(struct inode *inode, loff_t bytes)
+{
+       spin_lock(&inode->i_lock);
+       __inode_add_bytes(inode, bytes);
        spin_unlock(&inode->i_lock);
 }
 
index 19eb70b..aff046b 100644 (file)
@@ -901,8 +901,9 @@ int get_sb_single(struct file_system_type *fs_type,
                        return error;
                }
                s->s_flags |= MS_ACTIVE;
+       } else {
+               do_remount_sb(s, flags, data, 0);
        }
-       do_remount_sb(s, flags, data, 0);
        simple_set_mnt(mnt, s);
        return 0;
 }
index 60c702b..a0a500a 100644 (file)
@@ -483,7 +483,8 @@ void unmap_bin_file(struct sysfs_dirent *attr_sd)
  *     @attr:  attribute descriptor.
  */
 
-int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+int sysfs_create_bin_file(struct kobject *kobj,
+                         const struct bin_attribute *attr)
 {
        BUG_ON(!kobj || !kobj->sd || !attr);
 
@@ -497,7 +498,8 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
  *     @attr:  attribute descriptor.
  */
 
-void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+void sysfs_remove_bin_file(struct kobject *kobj,
+                          const struct bin_attribute *attr)
 {
        sysfs_hash_and_remove(kobj->sd, attr->attr.name);
 }
index 2a73d9b..a62799f 100644 (file)
@@ -166,9 +166,9 @@ struct driver_attribute driver_attr_##_name =               \
        __ATTR(_name, _mode, _show, _store)
 
 extern int __must_check driver_create_file(struct device_driver *driver,
-                                          struct driver_attribute *attr);
+                                       const struct driver_attribute *attr);
 extern void driver_remove_file(struct device_driver *driver,
-                              struct driver_attribute *attr);
+                              const struct driver_attribute *attr);
 
 extern int __must_check driver_add_kobj(struct device_driver *drv,
                                        struct kobject *kobj,
@@ -319,13 +319,13 @@ struct device_attribute {
 struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
 
 extern int __must_check device_create_file(struct device *device,
-                                          struct device_attribute *entry);
+                                       const struct device_attribute *entry);
 extern void device_remove_file(struct device *dev,
-                              struct device_attribute *attr);
+                              const struct device_attribute *attr);
 extern int __must_check device_create_bin_file(struct device *dev,
-                                              struct bin_attribute *attr);
+                                       const struct bin_attribute *attr);
 extern void device_remove_bin_file(struct device *dev,
-                                  struct bin_attribute *attr);
+                                  const struct bin_attribute *attr);
 extern int device_schedule_callback_owner(struct device *dev,
                void (*func)(struct device *dev), struct module *owner);
 
diff --git a/include/linux/dst.h b/include/linux/dst.h
deleted file mode 100644 (file)
index e26fed8..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 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.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __DST_H
-#define __DST_H
-
-#include <linux/types.h>
-#include <linux/connector.h>
-
-#define DST_NAMELEN            32
-#define DST_NAME               "dst"
-
-enum {
-       /* Remove node with given id from storage */
-       DST_DEL_NODE    = 0,
-       /* Add remote node with given id to the storage */
-       DST_ADD_REMOTE,
-       /* Add local node with given id to the storage to be exported and used by remote peers */
-       DST_ADD_EXPORT,
-       /* Crypto initialization command (hash/cipher used to protect the connection) */
-       DST_CRYPTO,
-       /* Security attributes for given connection (permissions for example) */
-       DST_SECURITY,
-       /* Register given node in the block layer subsystem */
-       DST_START,
-       DST_CMD_MAX
-};
-
-struct dst_ctl
-{
-       /* Storage name */
-       char                    name[DST_NAMELEN];
-       /* Command flags */
-       __u32                   flags;
-       /* Command itself (see above) */
-       __u32                   cmd;
-       /* Maximum number of pages per single request in this device */
-       __u32                   max_pages;
-       /* Stale/error transaction scanning timeout in milliseconds */
-       __u32                   trans_scan_timeout;
-       /* Maximum number of retry sends before completing transaction as broken */
-       __u32                   trans_max_retries;
-       /* Storage size */
-       __u64                   size;
-};
-
-/* Reply command carries completion status */
-struct dst_ctl_ack
-{
-       struct cn_msg           msg;
-       int                     error;
-       int                     unused[3];
-};
-
-/*
- * Unfortunaltely socket address structure is not exported to userspace
- * and is redefined there.
- */
-#define SADDR_MAX_DATA 128
-
-struct saddr {
-       /* address family, AF_xxx       */
-       unsigned short          sa_family;
-       /* 14 bytes of protocol address */
-       char                    sa_data[SADDR_MAX_DATA];
-       /* Number of bytes used in sa_data */
-       unsigned short          sa_data_len;
-};
-
-/* Address structure */
-struct dst_network_ctl
-{
-       /* Socket type: datagram, stream...*/
-       unsigned int            type;
-       /* Let me guess, is it a Jupiter diameter? */
-       unsigned int            proto;
-       /* Peer's address */
-       struct saddr            addr;
-};
-
-struct dst_crypto_ctl
-{
-       /* Cipher and hash names */
-       char                    cipher_algo[DST_NAMELEN];
-       char                    hash_algo[DST_NAMELEN];
-
-       /* Key sizes. Can be zero for digest for example */
-       unsigned int            cipher_keysize, hash_keysize;
-       /* Alignment. Calculated by the DST itself. */
-       unsigned int            crypto_attached_size;
-       /* Number of threads to perform crypto operations */
-       int                     thread_num;
-};
-
-/* Export security attributes have this bits checked in when client connects */
-#define DST_PERM_READ          (1<<0)
-#define DST_PERM_WRITE         (1<<1)
-
-/*
- * Right now it is simple model, where each remote address
- * is assigned to set of permissions it is allowed to perform.
- * In real world block device does not know anything but
- * reading and writing, so it should be more than enough.
- */
-struct dst_secure_user
-{
-       unsigned int            permissions;
-       struct saddr            addr;
-};
-
-/*
- * Export control command: device to export and network address to accept
- * clients to work with given device
- */
-struct dst_export_ctl
-{
-       char                    device[DST_NAMELEN];
-       struct dst_network_ctl  ctl;
-};
-
-enum {
-       DST_CFG = 1,            /* Request remote configuration */
-       DST_IO,                 /* IO command */
-       DST_IO_RESPONSE,        /* IO response */
-       DST_PING,               /* Keepalive message */
-       DST_NCMD_MAX,
-};
-
-struct dst_cmd
-{
-       /* Network command itself, see above */
-       __u32                   cmd;
-       /*
-        * Size of the attached data
-        * (in most cases, for READ command it means how many bytes were requested)
-        */
-       __u32                   size;
-       /* Crypto size: number of attached bytes with digest/hmac */
-       __u32                   csize;
-       /* Here we can carry secret data */
-       __u32                   reserved;
-       /* Read/write bits, see how they are encoded in bio structure */
-       __u64                   rw;
-       /* BIO flags */
-       __u64                   flags;
-       /* Unique command id (like transaction ID) */
-       __u64                   id;
-       /* Sector to start IO from */
-       __u64                   sector;
-       /* Hash data is placed after this header */
-       __u8                    hash[0];
-};
-
-/*
- * Convert command to/from network byte order.
- * We do not use hton*() functions, since there is
- * no 64-bit implementation.
- */
-static inline void dst_convert_cmd(struct dst_cmd *c)
-{
-       c->cmd = __cpu_to_be32(c->cmd);
-       c->csize = __cpu_to_be32(c->csize);
-       c->size = __cpu_to_be32(c->size);
-       c->sector = __cpu_to_be64(c->sector);
-       c->id = __cpu_to_be64(c->id);
-       c->flags = __cpu_to_be64(c->flags);
-       c->rw = __cpu_to_be64(c->rw);
-}
-
-/* Transaction id */
-typedef __u64 dst_gen_t;
-
-#ifdef __KERNEL__
-
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/device.h>
-#include <linux/mempool.h>
-#include <linux/net.h>
-#include <linux/poll.h>
-#include <linux/rbtree.h>
-
-#ifdef CONFIG_DST_DEBUG
-#define dprintk(f, a...) printk(KERN_NOTICE f, ##a)
-#else
-static inline void __attribute__ ((format (printf, 1, 2)))
-       dprintk(const char *fmt, ...) {}
-#endif
-
-struct dst_node;
-
-struct dst_trans
-{
-       /* DST node we are working with */
-       struct dst_node         *n;
-
-       /* Entry inside transaction tree */
-       struct rb_node          trans_entry;
-
-       /* Merlin kills this transaction when this memory cell equals zero */
-       atomic_t                refcnt;
-
-       /* How this transaction should be processed by crypto engine */
-       short                   enc;
-       /* How many times this transaction was resent */
-       short                   retries;
-       /* Completion status */
-       int                     error;
-
-       /* When did we send it to the remote peer */
-       long                    send_time;
-
-       /* My name is...
-        * Well, computers does not speak, they have unique id instead */
-       dst_gen_t               gen;
-
-       /* Block IO we are working with */
-       struct bio              *bio;
-
-       /* Network command for above block IO request */
-       struct dst_cmd          cmd;
-};
-
-struct dst_crypto_engine
-{
-       /* What should we do with all block requests */
-       struct crypto_hash      *hash;
-       struct crypto_ablkcipher        *cipher;
-
-       /* Pool of pages used to encrypt data into before sending */
-       int                     page_num;
-       struct page             **pages;
-
-       /* What to do with current request */
-       int                     enc;
-       /* Who we are and where do we go */
-       struct scatterlist      *src, *dst;
-
-       /* Maximum timeout waiting for encryption to be completed */
-       long                    timeout;
-       /* IV is a 64-bit sequential counter */
-       u64                     iv;
-
-       /* Secret data */
-       void                    *private;
-
-       /* Cached temporary data lives here */
-       int                     size;
-       void                    *data;
-};
-
-struct dst_state
-{
-       /* The main state protection */
-       struct mutex            state_lock;
-
-       /* Polling machinery for sockets */
-       wait_queue_t            wait;
-       wait_queue_head_t       *whead;
-       /* Most of events are being waited here */
-       wait_queue_head_t       thread_wait;
-
-       /* Who owns this? */
-       struct dst_node         *node;
-
-       /* Network address for this state */
-       struct dst_network_ctl  ctl;
-
-       /* Permissions to work with: read-only or rw connection */
-       u32                     permissions;
-
-       /* Called when we need to clean private data */
-       void                    (* cleanup)(struct dst_state *st);
-
-       /* Used by the server: BIO completion queues BIOs here */
-       struct list_head        request_list;
-       spinlock_t              request_lock;
-
-       /* Guess what? No, it is not number of planets */
-       atomic_t                refcnt;
-
-       /* This flags is set when connection should be dropped */
-       int                     need_exit;
-
-       /*
-        * Socket to work with. Second pointer is used for
-        * lockless check if socket was changed before performing
-        * next action (like working with cached polling result)
-        */
-       struct socket           *socket, *read_socket;
-
-       /* Cached preallocated data */
-       void                    *data;
-       unsigned int            size;
-
-       /* Currently processed command */
-       struct dst_cmd          cmd;
-};
-
-struct dst_info
-{
-       /* Device size */
-       u64                     size;
-
-       /* Local device name for export devices */
-       char                    local[DST_NAMELEN];
-
-       /* Network setup */
-       struct dst_network_ctl  net;
-
-       /* Sysfs bits use this */
-       struct device           device;
-};
-
-struct dst_node
-{
-       struct list_head        node_entry;
-
-       /* Hi, my name is stored here */
-       char                    name[DST_NAMELEN];
-       /* My cache name is stored here */
-       char                    cache_name[DST_NAMELEN];
-
-       /* Block device attached to given node.
-        * Only valid for exporting nodes */
-       struct block_device     *bdev;
-       /* Network state machine for given peer */
-       struct dst_state        *state;
-
-       /* Block IO machinery */
-       struct request_queue    *queue;
-       struct gendisk          *disk;
-
-       /* Number of threads in processing pool */
-       int                     thread_num;
-       /* Maximum number of pages in single IO */
-       int                     max_pages;
-
-       /* I'm that big in bytes */
-       loff_t                  size;
-
-       /* Exported to userspace node information */
-       struct dst_info         *info;
-
-       /*
-        * Security attribute list.
-        * Used only by exporting node currently.
-        */
-       struct list_head        security_list;
-       struct mutex            security_lock;
-
-       /*
-        * When this unerflows below zero, university collapses.
-        * But this will not happen, since node will be freed,
-        * when reference counter reaches zero.
-        */
-       atomic_t                refcnt;
-
-       /* How precisely should I be started? */
-       int                     (*start)(struct dst_node *);
-
-       /* Crypto capabilities */
-       struct dst_crypto_ctl   crypto;
-       u8                      *hash_key;
-       u8                      *cipher_key;
-
-       /* Pool of processing thread */
-       struct thread_pool      *pool;
-
-       /* Transaction IDs live here */
-       atomic_long_t           gen;
-
-       /*
-        * How frequently and how many times transaction
-        * tree should be scanned to drop stale objects.
-        */
-       long                    trans_scan_timeout;
-       int                     trans_max_retries;
-
-       /* Small gnomes live here */
-       struct rb_root          trans_root;
-       struct mutex            trans_lock;
-
-       /*
-        * Transaction cache/memory pool.
-        * It is big enough to contain not only transaction
-        * itself, but additional crypto data (digest/hmac).
-        */
-       struct kmem_cache       *trans_cache;
-       mempool_t               *trans_pool;
-
-       /* This entity scans transaction tree */
-       struct delayed_work     trans_work;
-
-       wait_queue_head_t       wait;
-};
-
-/* Kernel representation of the security attribute */
-struct dst_secure
-{
-       struct list_head        sec_entry;
-       struct dst_secure_user  sec;
-};
-
-int dst_process_bio(struct dst_node *n, struct bio *bio);
-
-int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r);
-int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le);
-
-static inline struct dst_state *dst_state_get(struct dst_state *st)
-{
-       BUG_ON(atomic_read(&st->refcnt) == 0);
-       atomic_inc(&st->refcnt);
-       return st;
-}
-
-void dst_state_put(struct dst_state *st);
-
-struct dst_state *dst_state_alloc(struct dst_node *n);
-int dst_state_socket_create(struct dst_state *st);
-void dst_state_socket_release(struct dst_state *st);
-
-void dst_state_exit_connected(struct dst_state *st);
-
-int dst_state_schedule_receiver(struct dst_state *st);
-
-void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str);
-
-static inline void dst_state_lock(struct dst_state *st)
-{
-       mutex_lock(&st->state_lock);
-}
-
-static inline void dst_state_unlock(struct dst_state *st)
-{
-       mutex_unlock(&st->state_lock);
-}
-
-void dst_poll_exit(struct dst_state *st);
-int dst_poll_init(struct dst_state *st);
-
-static inline unsigned int dst_state_poll(struct dst_state *st)
-{
-       unsigned int revents = POLLHUP | POLLERR;
-
-       dst_state_lock(st);
-       if (st->socket)
-               revents = st->socket->ops->poll(NULL, st->socket, NULL);
-       dst_state_unlock(st);
-
-       return revents;
-}
-
-static inline int dst_thread_setup(void *private, void *data)
-{
-       return 0;
-}
-
-void dst_node_put(struct dst_node *n);
-
-static inline struct dst_node *dst_node_get(struct dst_node *n)
-{
-       atomic_inc(&n->refcnt);
-       return n;
-}
-
-int dst_data_recv(struct dst_state *st, void *data, unsigned int size);
-int dst_recv_cdata(struct dst_state *st, void *cdata);
-int dst_data_send_header(struct socket *sock,
-               void *data, unsigned int size, int more);
-
-int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio);
-
-int dst_process_io(struct dst_state *st);
-int dst_export_crypto(struct dst_node *n, struct bio *bio);
-int dst_export_send_bio(struct bio *bio);
-int dst_start_export(struct dst_node *n);
-
-int __init dst_export_init(void);
-void dst_export_exit(void);
-
-/* Private structure for export block IO requests */
-struct dst_export_priv
-{
-       struct list_head                request_entry;
-       struct dst_state                *state;
-       struct bio                      *bio;
-       struct dst_cmd                  cmd;
-};
-
-static inline void dst_trans_get(struct dst_trans *t)
-{
-       atomic_inc(&t->refcnt);
-}
-
-struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen);
-int dst_trans_remove(struct dst_trans *t);
-int dst_trans_remove_nolock(struct dst_trans *t);
-void dst_trans_put(struct dst_trans *t);
-
-/*
- * Convert bio into network command.
- */
-static inline void dst_bio_to_cmd(struct bio *bio, struct dst_cmd *cmd,
-               u32 command, u64 id)
-{
-       cmd->cmd = command;
-       cmd->flags = (bio->bi_flags << BIO_POOL_BITS) >> BIO_POOL_BITS;
-       cmd->rw = bio->bi_rw;
-       cmd->size = bio->bi_size;
-       cmd->csize = 0;
-       cmd->id = id;
-       cmd->sector = bio->bi_sector;
-};
-
-int dst_trans_send(struct dst_trans *t);
-int dst_trans_crypto(struct dst_trans *t);
-
-int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl);
-void dst_node_crypto_exit(struct dst_node *n);
-
-static inline int dst_need_crypto(struct dst_node *n)
-{
-       struct dst_crypto_ctl *c = &n->crypto;
-       /*
-        * Logical OR is appropriate here, but boolean one produces
-        * more optimal code, so it is used instead.
-        */
-       return (c->hash_algo[0] | c->cipher_algo[0]);
-}
-
-int dst_node_trans_init(struct dst_node *n, unsigned int size);
-void dst_node_trans_exit(struct dst_node *n);
-
-/*
- * Pool of threads.
- * Ready list contains threads currently free to be used,
- * active one contains threads with some work scheduled for them.
- * Caller can wait in given queue when thread is ready.
- */
-struct thread_pool
-{
-       int                     thread_num;
-       struct mutex            thread_lock;
-       struct list_head        ready_list, active_list;
-
-       wait_queue_head_t       wait;
-};
-
-void thread_pool_del_worker(struct thread_pool *p);
-void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id);
-int thread_pool_add_worker(struct thread_pool *p,
-               char *name,
-               unsigned int id,
-               void *(* init)(void *data),
-               void (* cleanup)(void *data),
-               void *data);
-
-void thread_pool_destroy(struct thread_pool *p);
-struct thread_pool *thread_pool_create(int num, char *name,
-               void *(* init)(void *data),
-               void (* cleanup)(void *data),
-               void *data);
-
-int thread_pool_schedule(struct thread_pool *p,
-               int (* setup)(void *stored_private, void *setup_data),
-               int (* action)(void *stored_private, void *setup_data),
-               void *setup_data, long timeout);
-int thread_pool_schedule_private(struct thread_pool *p,
-               int (* setup)(void *private, void *data),
-               int (* action)(void *private, void *data),
-               void *data, long timeout, void *id);
-
-#endif /* __KERNEL__ */
-#endif /* __DST_H */
index f07f34d..258088a 100644 (file)
@@ -72,6 +72,8 @@ struct ext3_sb_info {
        struct inode * s_journal_inode;
        struct journal_s * s_journal;
        struct list_head s_orphan;
+       struct mutex s_orphan_lock;
+       struct mutex s_resize_lock;
        unsigned long s_commit_interval;
        struct block_device *journal_bdev;
 #ifdef CONFIG_JBD_DEBUG
index cf82d51..d7b5ddc 100644 (file)
 
 #define EXT3_DATA_TRANS_BLOCKS(sb)     (EXT3_SINGLEDATA_TRANS_BLOCKS + \
                                         EXT3_XATTR_TRANS_BLOCKS - 2 + \
-                                        2*EXT3_QUOTA_TRANS_BLOCKS(sb))
+                                        EXT3_MAXQUOTAS_TRANS_BLOCKS(sb))
 
 /* Delete operations potentially hit one directory's namespace plus an
  * entire inode, plus arbitrary amounts of bitmap/indirection data.  Be
  * generous.  We can grow the delete transaction later if necessary. */
 
-#define EXT3_DELETE_TRANS_BLOCKS(sb)   (2 * EXT3_DATA_TRANS_BLOCKS(sb) + 64)
+#define EXT3_DELETE_TRANS_BLOCKS(sb)   (EXT3_MAXQUOTAS_TRANS_BLOCKS(sb) + 64)
 
 /* Define an arbitrary limit for the amount of data we will anticipate
  * writing to any given transaction.  For unbounded transactions such as
@@ -86,6 +86,9 @@
 #define EXT3_QUOTA_INIT_BLOCKS(sb) 0
 #define EXT3_QUOTA_DEL_BLOCKS(sb) 0
 #endif
+#define EXT3_MAXQUOTAS_TRANS_BLOCKS(sb) (MAXQUOTAS*EXT3_QUOTA_TRANS_BLOCKS(sb))
+#define EXT3_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT3_QUOTA_INIT_BLOCKS(sb))
+#define EXT3_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT3_QUOTA_DEL_BLOCKS(sb))
 
 int
 ext3_mark_iloc_dirty(handle_t *handle,
index 7e3012e..9147ca8 100644 (file)
@@ -2297,6 +2297,7 @@ extern const struct inode_operations page_symlink_inode_operations;
 extern int generic_readlink(struct dentry *, char __user *, int);
 extern void generic_fillattr(struct inode *, struct kstat *);
 extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+void __inode_add_bytes(struct inode *inode, loff_t bytes);
 void inode_add_bytes(struct inode *inode, loff_t bytes);
 void inode_sub_bytes(struct inode *inode, loff_t bytes);
 loff_t inode_get_bytes(struct inode *inode);
index 486e8ad..3d44e9c 100644 (file)
@@ -69,8 +69,8 @@ struct kfifo {
  * @name: name of the declared kfifo datatype
  * @size: size of the fifo buffer
  *
- * Note: the macro can be used inside struct or union declaration
- * Note: the macro creates two objects:
+ * Note1: the macro can be used inside struct or union declaration
+ * Note2: the macro creates two objects:
  *  A kfifo object with the given name and a buffer for the kfifo
  *  object named name##kfifo_buffer
  */
@@ -83,7 +83,6 @@ union { \
 /**
  * INIT_KFIFO - Initialize a kfifo declared by DECLARED_KFIFO
  * @name: name of the declared kfifo datatype
- * @size: size of the fifo buffer
  */
 #define INIT_KFIFO(name) \
        name = __kfifo_initializer(sizeof(name##kfifo_buffer) - \
@@ -94,8 +93,8 @@ union { \
  * @name: name of the declared kfifo datatype
  * @size: size of the fifo buffer
  *
- * Note: the macro can be used for global and local kfifo data type variables
- * Note: the macro creates two objects:
+ * Note1: the macro can be used for global and local kfifo data type variables
+ * Note2: the macro creates two objects:
  *  A kfifo object with the given name and a buffer for the kfifo
  *  object named name##kfifo_buffer
  */
@@ -249,7 +248,7 @@ extern __must_check unsigned int kfifo_from_user(struct kfifo *fifo,
 extern __must_check unsigned int kfifo_to_user(struct kfifo *fifo,
        void __user *to, unsigned int n);
 
-/**
+/*
  * __kfifo_add_out internal helper function for updating the out offset
  */
 static inline void __kfifo_add_out(struct kfifo *fifo,
@@ -259,7 +258,7 @@ static inline void __kfifo_add_out(struct kfifo *fifo,
        fifo->out += off;
 }
 
-/**
+/*
  * __kfifo_add_in internal helper function for updating the in offset
  */
 static inline void __kfifo_add_in(struct kfifo *fifo,
@@ -269,7 +268,7 @@ static inline void __kfifo_add_in(struct kfifo *fifo,
        fifo->in += off;
 }
 
-/**
+/*
  * __kfifo_off internal helper function for calculating the index of a
  * given offeset
  */
@@ -278,7 +277,7 @@ static inline unsigned int __kfifo_off(struct kfifo *fifo, unsigned int off)
        return off & (fifo->size - 1);
 }
 
-/**
+/*
  * __kfifo_peek_n internal helper function for determinate the length of
  * the next record in the fifo
  */
@@ -299,7 +298,7 @@ static inline unsigned int __kfifo_peek_n(struct kfifo *fifo,
 #undef __KFIFO_GET
 }
 
-/**
+/*
  * __kfifo_poke_n internal helper function for storing the length of
  * the next record into the fifo
  */
@@ -319,7 +318,7 @@ static inline void __kfifo_poke_n(struct kfifo *fifo,
 #undef __KFIFO_PUT
 }
 
-/**
+/*
  * __kfifo_in_... internal functions for put date into the fifo
  * do not call it directly, use kfifo_in_rec() instead
  */
@@ -367,7 +366,7 @@ static inline __must_check unsigned int kfifo_in_rec(struct kfifo *fifo,
        return __kfifo_in_rec(fifo, from, n, recsize);
 }
 
-/**
+/*
  * __kfifo_out_... internal functions for get date from the fifo
  * do not call it directly, use kfifo_out_rec() instead
  */
@@ -425,7 +424,7 @@ static inline __must_check unsigned int kfifo_out_rec(struct kfifo *fifo,
        return __kfifo_out_rec(fifo, to, n, recsize, total);
 }
 
-/**
+/*
  * __kfifo_from_user_... internal functions for transfer from user space into
  * the fifo. do not call it directly, use kfifo_from_user_rec() instead
  */
@@ -474,7 +473,7 @@ static inline __must_check unsigned int kfifo_from_user_rec(struct kfifo *fifo,
        return __kfifo_from_user_rec(fifo, from, n, recsize);
 }
 
-/**
+/*
  * __kfifo_to_user_... internal functions for transfer fifo data into user space
  * do not call it directly, use kfifo_to_user_rec() instead
  */
@@ -533,7 +532,7 @@ static inline __must_check unsigned int kfifo_to_user_rec(struct kfifo *fifo,
        return __kfifo_to_user_rec(fifo, to, n, recsize, total);
 }
 
-/**
+/*
  * __kfifo_peek_... internal functions for peek into the next fifo record
  * do not call it directly, use kfifo_peek_rec() instead
  */
@@ -557,7 +556,7 @@ static inline __must_check unsigned int kfifo_peek_rec(struct kfifo *fifo,
        return __kfifo_peek_n(fifo, recsize);
 }
 
-/**
+/*
  * __kfifo_skip_... internal functions for skip the next fifo record
  * do not call it directly, use kfifo_skip_rec() instead
  */
index e70e621..a6861f1 100644 (file)
@@ -315,8 +315,9 @@ struct dquot_operations {
        int (*claim_space) (struct inode *, qsize_t);
        /* release rsved quota for delayed alloc */
        void (*release_rsv) (struct inode *, qsize_t);
-       /* get reserved quota for delayed alloc */
-       qsize_t (*get_reserved_space) (struct inode *);
+       /* get reserved quota for delayed alloc, value returned is managed by
+        * quota code only */
+       qsize_t *(*get_reserved_space) (struct inode *);
 };
 
 /* Operations handling requests from userspace */
index 9d68fed..cfa8308 100644 (file)
@@ -99,8 +99,9 @@ int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr,
 void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
 
 int __must_check sysfs_create_bin_file(struct kobject *kobj,
-                                      struct bin_attribute *attr);
-void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
+                                      const struct bin_attribute *attr);
+void sysfs_remove_bin_file(struct kobject *kobj,
+                          const struct bin_attribute *attr);
 
 int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target,
                                   const char *name);
@@ -175,13 +176,13 @@ static inline void sysfs_remove_file(struct kobject *kobj,
 }
 
 static inline int sysfs_create_bin_file(struct kobject *kobj,
-                                       struct bin_attribute *attr)
+                                       const struct bin_attribute *attr)
 {
        return 0;
 }
 
 static inline void sysfs_remove_bin_file(struct kobject *kobj,
-                                        struct bin_attribute *attr)
+                                        const struct bin_attribute *attr)
 {
 }
 
index 87f1f47..c535cc4 100644 (file)
@@ -2045,11 +2045,10 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 
        trace_sched_migrate_task(p, new_cpu);
 
-       if (task_cpu(p) == new_cpu)
-               return;
-
-       p->se.nr_migrations++;
-       perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 1, NULL, 0);
+       if (task_cpu(p) != new_cpu) {
+               p->se.nr_migrations++;
+               perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 1, NULL, 0);
+       }
 
        __set_task_cpu(p, new_cpu);
 }
index c15682a..475455c 100644 (file)
@@ -5,6 +5,7 @@ config SND_TIMER
 config SND_PCM
        tristate
        select SND_TIMER
+       select GCD
 
 config SND_HWDEP
        tristate
index ca8068b..b01d948 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <linux/time.h>
+#include <linux/gcd.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/timer.h>
  *  Timer functions
  */
 
-/* Greatest common divisor */
-static unsigned long gcd(unsigned long a, unsigned long b)
-{
-       unsigned long r;
-       if (a < b) {
-               r = a;
-               a = b;
-               b = r;
-       }
-       while ((r = a % b) != 0) {
-               a = b;
-               b = r;
-       }
-       return b;
-}
-
 void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
 {
        unsigned long rate, mult, fsize, l, post;
index 9cfdb77..950ee5c 100644 (file)
@@ -1086,11 +1086,6 @@ int snd_hda_codec_configure(struct hda_codec *codec)
                if (err < 0)
                        return err;
        }
-       /* audio codec should override the mixer name */
-       if (codec->afg || !*codec->bus->card->mixername)
-               snprintf(codec->bus->card->mixername,
-                        sizeof(codec->bus->card->mixername),
-                        "%s %s", codec->vendor_name, codec->chip_name);
 
        if (is_generic_config(codec)) {
                err = snd_hda_parse_generic_codec(codec);
@@ -1109,6 +1104,11 @@ int snd_hda_codec_configure(struct hda_codec *codec)
  patched:
        if (!err && codec->patch_ops.unsol_event)
                err = init_unsol_queue(codec->bus);
+       /* audio codec should override the mixer name */
+       if (!err && (codec->afg || !*codec->bus->card->mixername))
+               snprintf(codec->bus->card->mixername,
+                        sizeof(codec->bus->card->mixername),
+                        "%s %s", codec->vendor_name, codec->chip_name);
        return err;
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
index 9b56f93..ff8ad46 100644 (file)
@@ -2322,6 +2322,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
  * white/black-list for enable_msi
  */
 static struct snd_pci_quirk msi_black_list[] __devinitdata = {
+       SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
        {}
 };
 
index 4b200da..fe0423c 100644 (file)
@@ -66,6 +66,7 @@ struct cs_spec {
 /* available models */
 enum {
        CS420X_MBP55,
+       CS420X_IMAC27,
        CS420X_AUTO,
        CS420X_MODELS
 };
@@ -827,7 +828,8 @@ static void cs_automute(struct hda_codec *codec)
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
                                    hp_present ? 0 : PIN_OUT);
        }
-       if (spec->board_config == CS420X_MBP55) {
+       if (spec->board_config == CS420X_MBP55 ||
+           spec->board_config == CS420X_IMAC27) {
                unsigned int gpio = hp_present ? 0x02 : 0x08;
                snd_hda_codec_write(codec, 0x01, 0,
                                    AC_VERB_SET_GPIO_DATA, gpio);
@@ -1069,12 +1071,14 @@ static int cs_parse_auto_config(struct hda_codec *codec)
 
 static const char *cs420x_models[CS420X_MODELS] = {
        [CS420X_MBP55] = "mbp55",
+       [CS420X_IMAC27] = "imac27",
        [CS420X_AUTO] = "auto",
 };
 
 
 static struct snd_pci_quirk cs420x_cfg_tbl[] = {
        SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
+       SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
        {} /* terminator */
 };
 
@@ -1097,8 +1101,23 @@ static struct cs_pincfg mbp55_pincfgs[] = {
        {} /* terminator */
 };
 
+static struct cs_pincfg imac27_pincfgs[] = {
+       { 0x09, 0x012b4050 },
+       { 0x0a, 0x90100140 },
+       { 0x0b, 0x90100142 },
+       { 0x0c, 0x018b3020 },
+       { 0x0d, 0x90a00110 },
+       { 0x0e, 0x400000f0 },
+       { 0x0f, 0x01cbe030 },
+       { 0x10, 0x014be060 },
+       { 0x12, 0x01ab9070 },
+       { 0x15, 0x400000f0 },
+       {} /* terminator */
+};
+
 static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
        [CS420X_MBP55] = mbp55_pincfgs,
+       [CS420X_IMAC27] = imac27_pincfgs,
 };
 
 static void fix_pincfg(struct hda_codec *codec, int model)
@@ -1128,6 +1147,7 @@ static int patch_cs420x(struct hda_codec *codec)
                fix_pincfg(codec, spec->board_config);
 
        switch (spec->board_config) {
+       case CS420X_IMAC27:
        case CS420X_MBP55:
                /* GPIO1 = headphones */
                /* GPIO3 = speakers */
index 3d59f83..eeda7be 100644 (file)
@@ -2104,6 +2104,7 @@ static unsigned int ref9205_pin_configs[12] = {
     10280204
     1028021F
     10280228 (Dell Vostro 1500)
+    10280229 (Dell Vostro 1700)
 */
 static unsigned int dell_9205_m42_pin_configs[12] = {
        0x0321101F, 0x03A11020, 0x400003FA, 0x90170310,
@@ -2189,6 +2190,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
                      "Dell Inspiron", STAC_9205_DELL_M44),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
                      "Dell Vostro 1500", STAC_9205_DELL_M42),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0229,
+                     "Dell Vostro 1700", STAC_9205_DELL_M42),
        /* Gateway */
        SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD),
        SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
@@ -3779,15 +3782,16 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
                err = snd_hda_attach_beep_device(codec, nid);
                if (err < 0)
                        return err;
-               /* IDT/STAC codecs have linear beep tone parameter */
-               codec->beep->linear_tone = 1;
-               /* if no beep switch is available, make its own one */
-               caps = query_amp_caps(codec, nid, HDA_OUTPUT);
-               if (codec->beep &&
-                   !((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT)) {
-                       err = stac92xx_beep_switch_ctl(codec);
-                       if (err < 0)
-                               return err;
+               if (codec->beep) {
+                       /* IDT/STAC codecs have linear beep tone parameter */
+                       codec->beep->linear_tone = 1;
+                       /* if no beep switch is available, make its own one */
+                       caps = query_amp_caps(codec, nid, HDA_OUTPUT);
+                       if (!(caps & AC_AMPCAP_MUTE)) {
+                               err = stac92xx_beep_switch_ctl(codec);
+                               if (err < 0)
+                                       return err;
+                       }
                }
        }
 #endif
index 0ac1215..e237bf6 100644 (file)
@@ -463,7 +463,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
 {
        u16 *cache = codec->reg_cache;
 
-       soc_ac97_ops.write(codec->ac97, reg, val);
+       if (reg < 0x7c)
+               soc_ac97_ops.write(codec->ac97, reg, val);
        reg = reg >> 1;
        if (reg < (ARRAY_SIZE(wm9712_reg)))
                cache[reg] = val;
index 0267d2d..07d2a24 100644 (file)
@@ -180,7 +180,8 @@ static int mx27vis_hifi_hw_free(struct snd_pcm_substream *substream)
        struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 
        /* disable the PLL */
-       return codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, 0, 0);
+       return codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, IGNORED_ARG,
+                                      0, 0);
 }
 
 /*
index 9c49c11..42813b8 100644 (file)
@@ -876,7 +876,7 @@ static int fsi_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
-       if (!res || !irq) {
+       if (!res || (int)irq <= 0) {
                dev_err(&pdev->dev, "Not enough FSI platform resources.\n");
                ret = -ENODEV;
                goto exit;