Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of https://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / drivers / net / fddi / defxx.c
index caed6ee..7f975a2 100644 (file)
@@ -414,7 +414,7 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
  * ================
  *
  * Overview:
- *   Retrieves the address range used to access control and status
+ *   Retrieves the address ranges used to access control and status
  *   registers.
  *
  * Returns:
@@ -422,8 +422,8 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
  *
  * Arguments:
  *   bdev      - pointer to device information
- *   bar_start - pointer to store the start address
- *   bar_len   - pointer to store the length of the area
+ *   bar_start - pointer to store the start addresses
+ *   bar_len   - pointer to store the lengths of the areas
  *
  * Assumptions:
  *   I am sure there are some.
@@ -442,38 +442,47 @@ static void dfx_get_bars(struct device *bdev,
        if (dfx_bus_pci) {
                int num = dfx_use_mmio ? 0 : 1;
 
-               *bar_start = pci_resource_start(to_pci_dev(bdev), num);
-               *bar_len = pci_resource_len(to_pci_dev(bdev), num);
+               bar_start[0] = pci_resource_start(to_pci_dev(bdev), num);
+               bar_len[0] = pci_resource_len(to_pci_dev(bdev), num);
+               bar_start[2] = bar_start[1] = 0;
+               bar_len[2] = bar_len[1] = 0;
        }
        if (dfx_bus_eisa) {
                unsigned long base_addr = to_eisa_device(bdev)->base_addr;
-               resource_size_t bar;
+               resource_size_t bar_lo;
+               resource_size_t bar_hi;
 
                if (dfx_use_mmio) {
-                       bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2);
-                       bar <<= 8;
-                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1);
-                       bar <<= 8;
-                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0);
-                       bar <<= 16;
-                       *bar_start = bar;
-                       bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2);
-                       bar <<= 8;
-                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1);
-                       bar <<= 8;
-                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0);
-                       bar <<= 16;
-                       *bar_len = (bar | PI_MEM_ADD_MASK_M) + 1;
+                       bar_lo = inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_2);
+                       bar_lo <<= 8;
+                       bar_lo |= inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_1);
+                       bar_lo <<= 8;
+                       bar_lo |= inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_0);
+                       bar_lo <<= 8;
+                       bar_start[0] = bar_lo;
+                       bar_hi = inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_2);
+                       bar_hi <<= 8;
+                       bar_hi |= inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_1);
+                       bar_hi <<= 8;
+                       bar_hi |= inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_0);
+                       bar_hi <<= 8;
+                       bar_len[0] = ((bar_hi - bar_lo) | PI_MEM_ADD_MASK_M) +
+                                    1;
                } else {
-                       *bar_start = base_addr;
-                       *bar_len = PI_ESIC_K_CSR_IO_LEN +
-                                  PI_ESIC_K_BURST_HOLDOFF_LEN;
+                       bar_start[0] = base_addr;
+                       bar_len[0] = PI_ESIC_K_CSR_IO_LEN;
                }
+               bar_start[1] = base_addr + PI_DEFEA_K_BURST_HOLDOFF;
+               bar_len[1] = PI_ESIC_K_BURST_HOLDOFF_LEN;
+               bar_start[2] = base_addr + PI_ESIC_K_ESIC_CSR;
+               bar_len[2] = PI_ESIC_K_ESIC_CSR_LEN;
        }
        if (dfx_bus_tc) {
-               *bar_start = to_tc_dev(bdev)->resource.start +
-                            PI_TC_K_CSR_OFFSET;
-               *bar_len = PI_TC_K_CSR_LEN;
+               bar_start[0] = to_tc_dev(bdev)->resource.start +
+                              PI_TC_K_CSR_OFFSET;
+               bar_len[0] = PI_TC_K_CSR_LEN;
+               bar_start[2] = bar_start[1] = 0;
+               bar_len[2] = bar_len[1] = 0;
        }
 }
 
@@ -518,13 +527,14 @@ static int dfx_register(struct device *bdev)
 {
        static int version_disp;
        int dfx_bus_pci = dev_is_pci(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
        int dfx_bus_tc = DFX_BUS_TC(bdev);
        int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
        const char *print_name = dev_name(bdev);
        struct net_device *dev;
        DFX_board_t       *bp;                  /* board pointer */
-       resource_size_t bar_start = 0;          /* pointer to port */
-       resource_size_t bar_len = 0;            /* resource length */
+       resource_size_t bar_start[3];           /* pointers to ports */
+       resource_size_t bar_len[3];             /* resource length */
        int alloc_size;                         /* total buffer size used */
        struct resource *region;
        int err = 0;
@@ -542,10 +552,13 @@ static int dfx_register(struct device *bdev)
        }
 
        /* Enable PCI device. */
-       if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) {
-               printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n",
-                      print_name);
-               goto err_out;
+       if (dfx_bus_pci) {
+               err = pci_enable_device(to_pci_dev(bdev));
+               if (err) {
+                       pr_err("%s: Cannot enable PCI device, aborting\n",
+                              print_name);
+                       goto err_out;
+               }
        }
 
        SET_NETDEV_DEV(dev, bdev);
@@ -554,31 +567,62 @@ static int dfx_register(struct device *bdev)
        bp->bus_dev = bdev;
        dev_set_drvdata(bdev, dev);
 
-       dfx_get_bars(bdev, &bar_start, &bar_len);
+       dfx_get_bars(bdev, bar_start, bar_len);
+       if (dfx_bus_eisa && dfx_use_mmio && bar_start[0] == 0) {
+               pr_err("%s: Cannot use MMIO, no address set, aborting\n",
+                      print_name);
+               pr_err("%s: Run ECU and set adapter's MMIO location\n",
+                      print_name);
+               pr_err("%s: Or recompile driver with \"CONFIG_DEFXX_MMIO=n\""
+                      "\n", print_name);
+               err = -ENXIO;
+               goto err_out;
+       }
 
        if (dfx_use_mmio)
-               region = request_mem_region(bar_start, bar_len, print_name);
+               region = request_mem_region(bar_start[0], bar_len[0],
+                                           print_name);
        else
-               region = request_region(bar_start, bar_len, print_name);
+               region = request_region(bar_start[0], bar_len[0], print_name);
        if (!region) {
-               printk(KERN_ERR "%s: Cannot reserve I/O resource "
-                      "0x%lx @ 0x%lx, aborting\n",
-                      print_name, (long)bar_len, (long)bar_start);
+               pr_err("%s: Cannot reserve %s resource 0x%lx @ 0x%lx, "
+                      "aborting\n", dfx_use_mmio ? "MMIO" : "I/O", print_name,
+                      (long)bar_len[0], (long)bar_start[0]);
                err = -EBUSY;
                goto err_out_disable;
        }
+       if (bar_start[1] != 0) {
+               region = request_region(bar_start[1], bar_len[1], print_name);
+               if (!region) {
+                       pr_err("%s: Cannot reserve I/O resource "
+                              "0x%lx @ 0x%lx, aborting\n", print_name,
+                              (long)bar_len[1], (long)bar_start[1]);
+                       err = -EBUSY;
+                       goto err_out_csr_region;
+               }
+       }
+       if (bar_start[2] != 0) {
+               region = request_region(bar_start[2], bar_len[2], print_name);
+               if (!region) {
+                       pr_err("%s: Cannot reserve I/O resource "
+                              "0x%lx @ 0x%lx, aborting\n", print_name,
+                              (long)bar_len[2], (long)bar_start[2]);
+                       err = -EBUSY;
+                       goto err_out_bh_region;
+               }
+       }
 
        /* Set up I/O base address. */
        if (dfx_use_mmio) {
-               bp->base.mem = ioremap_nocache(bar_start, bar_len);
+               bp->base.mem = ioremap_nocache(bar_start[0], bar_len[0]);
                if (!bp->base.mem) {
                        printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);
                        err = -ENOMEM;
-                       goto err_out_region;
+                       goto err_out_esic_region;
                }
        } else {
-               bp->base.port = bar_start;
-               dev->base_addr = bar_start;
+               bp->base.port = bar_start[0];
+               dev->base_addr = bar_start[0];
        }
 
        /* Initialize new device structure */
@@ -587,7 +631,7 @@ static int dfx_register(struct device *bdev)
        if (dfx_bus_pci)
                pci_set_master(to_pci_dev(bdev));
 
-       if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) {
+       if (dfx_driver_init(dev, print_name, bar_start[0]) != DFX_K_SUCCESS) {
                err = -ENODEV;
                goto err_out_unmap;
        }
@@ -615,11 +659,19 @@ err_out_unmap:
        if (dfx_use_mmio)
                iounmap(bp->base.mem);
 
-err_out_region:
+err_out_esic_region:
+       if (bar_start[2] != 0)
+               release_region(bar_start[2], bar_len[2]);
+
+err_out_bh_region:
+       if (bar_start[1] != 0)
+               release_region(bar_start[1], bar_len[1]);
+
+err_out_csr_region:
        if (dfx_use_mmio)
-               release_mem_region(bar_start, bar_len);
+               release_mem_region(bar_start[0], bar_len[0]);
        else
-               release_region(bar_start, bar_len);
+               release_region(bar_start[0], bar_len[0]);
 
 err_out_disable:
        if (dfx_bus_pci)
@@ -711,13 +763,14 @@ static void dfx_bus_init(struct net_device *dev)
                }
 
                /*
-                * Enable memory decoding (MEMCS0) and/or port decoding
+                * Enable memory decoding (MEMCS1) and/or port decoding
                 * (IOCS1/IOCS0) as appropriate in Function Control
-                * Register.  IOCS0 is used for PDQ registers, taking 16
-                * 32-bit words, while IOCS1 is used for the Burst Holdoff
-                * register, taking a single 32-bit word only.  We use the
-                * slot-specific I/O range as per the ESIC spec, that is
-                * set bits 15:12 in the mask registers to mask them out.
+                * Register.  MEMCS1 or IOCS0 is used for PDQ registers,
+                * taking 16 32-bit words, while IOCS1 is used for the
+                * Burst Holdoff register, taking a single 32-bit word
+                * only.  We use the slot-specific I/O range as per the
+                * ESIC spec, that is set bits 15:12 in the mask registers
+                * to mask them out.
                 */
 
                /* Set the decode range of the board.  */
@@ -742,9 +795,11 @@ static void dfx_bus_init(struct net_device *dev)
                outb(val, base_addr + PI_ESIC_K_IO_ADD_MASK_1_0);
 
                /* Enable the decoders.  */
-               val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0;
+               val = PI_FUNCTION_CNTRL_M_IOCS1;
                if (dfx_use_mmio)
-                       val |= PI_FUNCTION_CNTRL_M_MEMCS0;
+                       val |= PI_FUNCTION_CNTRL_M_MEMCS1;
+               else
+                       val |= PI_FUNCTION_CNTRL_M_IOCS0;
                outb(val, base_addr + PI_ESIC_K_FUNCTION_CNTRL);
 
                /*
@@ -838,6 +893,12 @@ static void dfx_bus_uninit(struct net_device *dev)
                val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
                val &= ~PI_CONFIG_STAT_0_M_INT_ENB;
                outb(val, base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+
+               /* Disable the board.  */
+               outb(0, base_addr + PI_ESIC_K_SLOT_CNTRL);
+
+               /* Disable memory and port decoders.  */
+               outb(0, base_addr + PI_ESIC_K_FUNCTION_CNTRL);
        }
        if (dfx_bus_pci) {
                /* Disable interrupts at PCI bus interface chip (PFI) */
@@ -1061,8 +1122,8 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
                board_name = "DEFEA";
        if (dfx_bus_pci)
                board_name = "DEFPA";
-       pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n",
-               print_name, board_name, dfx_use_mmio ? "" : "I/O ",
+       pr_info("%s: %s at %s addr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n",
+               print_name, board_name, dfx_use_mmio ? "MMIO" : "I/O",
                (long long)bar_start, dev->irq, dev->dev_addr);
 
        /*
@@ -3636,8 +3697,8 @@ static void dfx_unregister(struct device *bdev)
        int dfx_bus_pci = dev_is_pci(bdev);
        int dfx_bus_tc = DFX_BUS_TC(bdev);
        int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-       resource_size_t bar_start = 0;          /* pointer to port */
-       resource_size_t bar_len = 0;            /* resource length */
+       resource_size_t bar_start[3];           /* pointers to ports */
+       resource_size_t bar_len[3];             /* resource lengths */
        int             alloc_size;             /* total buffer size used */
 
        unregister_netdev(dev);
@@ -3655,12 +3716,16 @@ static void dfx_unregister(struct device *bdev)
 
        dfx_bus_uninit(dev);
 
-       dfx_get_bars(bdev, &bar_start, &bar_len);
+       dfx_get_bars(bdev, bar_start, bar_len);
+       if (bar_start[2] != 0)
+               release_region(bar_start[2], bar_len[2]);
+       if (bar_start[1] != 0)
+               release_region(bar_start[1], bar_len[1]);
        if (dfx_use_mmio) {
                iounmap(bp->base.mem);
-               release_mem_region(bar_start, bar_len);
+               release_mem_region(bar_start[0], bar_len[0]);
        } else
-               release_region(bar_start, bar_len);
+               release_region(bar_start[0], bar_len[0]);
 
        if (dfx_bus_pci)
                pci_disable_device(to_pci_dev(bdev));