fmvj18x_cs: write interrupt ack bit for lan and modem to work simultaneously.
authorKomuro <komurojun-mbn@nifty.com>
Mon, 3 Nov 2008 01:56:04 +0000 (10:56 +0900)
committerJeff Garzik <jgarzik@redhat.com>
Fri, 7 Nov 2008 08:21:10 +0000 (03:21 -0500)
Write interrupt ack bit in fjn_interrupt for lan and modem to work
simultaneously.

Signed-off-by: Komuro <komurojun-mbn@nifty.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/net/pcmcia/fmvj18x_cs.c

index e4f8fe3c5dae52574a8a1904637c92cb683773c3..69dcfbbabe825229ca4f709315b9e29c9049cd76 100644 (file)
@@ -125,6 +125,7 @@ typedef struct local_info_t {
     u_short tx_queue_len;
     cardtype_t cardtype;
     u_short sent;
+    u_char __iomem *base;
 } local_info_t;
 
 #define MC_FILTERBREAK 64
@@ -242,6 +243,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
     lp = netdev_priv(dev);
     link->priv = dev;
     lp->p_dev = link;
+    lp->base = NULL;
 
     /* The io structure describes IO port mapping */
     link->io.NumPorts1 = 32;
@@ -442,8 +444,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
 
-    if (link->io.BasePort2 != 0)
-       fmvj18x_setup_mfc(link);
+    if (link->io.BasePort2 != 0) {
+       ret = fmvj18x_setup_mfc(link);
+       if (ret != 0) goto failed;
+    }
 
     ioaddr = dev->base_addr;
 
@@ -610,10 +614,10 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 {
     win_req_t req;
     memreq_t mem;
-    u_char __iomem *base;
-    int i, j;
+    int i;
     struct net_device *dev = link->priv;
     unsigned int ioaddr;
+    local_info_t *lp = netdev_priv(dev);
 
     /* Allocate a small memory window */
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
@@ -625,25 +629,32 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
        return -1;
     }
 
-    base = ioremap(req.Base, req.Size);
+    lp->base = ioremap(req.Base, req.Size);
+    if (lp->base == NULL) {
+       printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n");
+       return -1;
+    }
+
     mem.Page = 0;
     mem.CardOffset = 0;
-    pcmcia_map_mem_page(link->win, &mem);
-
+    i = pcmcia_map_mem_page(link->win, &mem);
+    if (i != 0) {
+       iounmap(lp->base);
+       lp->base = NULL;
+       cs_error(link, MapMemPage, i);
+       return -1;
+    }
+    
     ioaddr = dev->base_addr;
-    writeb(0x47, base+0x800);  /* Config Option Register of LAN */
-    writeb(0x0, base+0x802);   /* Config and Status Register */
+    writeb(0x47, lp->base+0x800);      /* Config Option Register of LAN */
+    writeb(0x0,  lp->base+0x802);      /* Config and Status Register */
 
-    writeb(ioaddr & 0xff, base+0x80a);         /* I/O Base(Low) of LAN */
-    writeb((ioaddr >> 8) & 0xff, base+0x80c);  /* I/O Base(High) of LAN */
+    writeb(ioaddr & 0xff, lp->base+0x80a);       /* I/O Base(Low) of LAN */
+    writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */
    
-    writeb(0x45, base+0x820);  /* Config Option Register of Modem */
-    writeb(0x8, base+0x822);   /* Config and Status Register */
+    writeb(0x45, lp->base+0x820);      /* Config Option Register of Modem */
+    writeb(0x8,  lp->base+0x822);      /* Config and Status Register */
 
-    iounmap(base);
-    j = pcmcia_release_window(link->win);
-    if (j != 0)
-       cs_error(link, ReleaseWindow, j);
     return 0;
 
 }
@@ -651,8 +662,25 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 
 static void fmvj18x_release(struct pcmcia_device *link)
 {
-       DEBUG(0, "fmvj18x_release(0x%p)\n", link);
-       pcmcia_disable_device(link);
+
+    struct net_device *dev = link->priv;
+    local_info_t *lp = netdev_priv(dev);
+    u_char __iomem *tmp;
+    int j;
+
+    DEBUG(0, "fmvj18x_release(0x%p)\n", link);
+
+    if (lp->base != NULL) {
+       tmp = lp->base;
+       lp->base = NULL;    /* set NULL before iounmap */
+       iounmap(tmp);
+       j = pcmcia_release_window(link->win);
+       if (j != 0)
+           cs_error(link, ReleaseWindow, j);
+    }
+
+    pcmcia_disable_device(link);
+
 }
 
 static int fmvj18x_suspend(struct pcmcia_device *link)
@@ -783,6 +811,13 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
 
     outb(D_TX_INTR, ioaddr + TX_INTR);
     outb(D_RX_INTR, ioaddr + RX_INTR);
+
+    if (lp->base != NULL) {
+       /* Ack interrupt for multifunction card */
+       writeb(0x01, lp->base+0x802);
+       writeb(0x09, lp->base+0x822);
+    }
+
     return IRQ_HANDLED;
 
 } /* fjn_interrupt */