Merge branch 'llseek' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/bkl
[linux-2.6.git] / drivers / serial / mfd.c
index f5e7569..dc0967f 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/slab.h>
 #include <linux/serial_reg.h>
 #include <linux/circ_buf.h>
 #include <linux/delay.h>
@@ -227,12 +228,14 @@ static const struct file_operations port_regs_ops = {
        .owner          = THIS_MODULE,
        .open           = hsu_show_regs_open,
        .read           = port_show_regs,
+       .llseek         = default_llseek,
 };
 
 static const struct file_operations dma_regs_ops = {
        .owner          = THIS_MODULE,
        .open           = hsu_show_regs_open,
        .read           = dma_show_regs,
+       .llseek         = default_llseek,
 };
 
 static int hsu_debugfs_init(struct hsu_port *hsu)
@@ -1217,25 +1220,38 @@ static struct uart_driver serial_hsu_reg = {
 #ifdef CONFIG_PM
 static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state)
 {
+       void *priv = pci_get_drvdata(pdev);
        struct uart_hsu_port *up;
 
-       up = pci_get_drvdata(pdev);
-       if (!up)
-               return 0;
-
-       uart_suspend_port(&serial_hsu_reg, &up->port);
+       /* Make sure this is not the internal dma controller */
+       if (priv && (pdev->device != 0x081E)) {
+               up = priv;
+               uart_suspend_port(&serial_hsu_reg, &up->port);
+       }
 
+       pci_save_state(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
         return 0;
 }
 
 static int serial_hsu_resume(struct pci_dev *pdev)
 {
+       void *priv = pci_get_drvdata(pdev);
        struct uart_hsu_port *up;
+       int ret;
 
-       up = pci_get_drvdata(pdev);
-       if (!up)
-               return 0;
-       uart_resume_port(&serial_hsu_reg, &up->port);
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               dev_warn(&pdev->dev,
+                       "HSU: can't re-enable device, try to continue\n");
+
+       if (priv && (pdev->device != 0x081E)) {
+               up = priv;
+               uart_resume_port(&serial_hsu_reg, &up->port);
+       }
        return 0;
 }
 #else
@@ -1410,7 +1426,6 @@ static void hsu_global_init(void)
        }
 
        phsu = hsu;
-
        hsu_debugfs_init(hsu);
        return;
 
@@ -1422,18 +1437,20 @@ err_free_region:
 
 static void serial_hsu_remove(struct pci_dev *pdev)
 {
-       struct hsu_port *hsu;
-       int i;
+       void *priv = pci_get_drvdata(pdev);
+       struct uart_hsu_port *up;
 
-       hsu = pci_get_drvdata(pdev);
-       if (!hsu)
+       if (!priv)
                return;
 
-       for (i = 0; i < 3; i++)
-               uart_remove_one_port(&serial_hsu_reg, &hsu->port[i].port);
+       /* For port 0/1/2, priv is the address of uart_hsu_port */
+       if (pdev->device != 0x081E) {
+               up = priv;
+               uart_remove_one_port(&serial_hsu_reg, &up->port);
+       }
 
        pci_set_drvdata(pdev, NULL);
-       free_irq(hsu->irq, hsu);
+       free_irq(pdev->irq, priv);
        pci_disable_device(pdev);
 }