Showing error 592

User: Jiri Slaby
Error type: Double Resource Put
Error type description: There is a try to return some resource to the system twice
File location: drivers/mtd/maps/l440gx.c
Line in file: 109
Project: Linux Kernel
Project version: 2.6.28
Tools: Stanse (1.2)
Entered: 2011-11-07 22:20:28 UTC


Source:

  1/*
  2 * BIOS Flash chip on Intel 440GX board.
  3 *
  4 * Bugs this currently does not work under linuxBIOS.
  5 */
  6
  7#include <linux/module.h>
  8#include <linux/pci.h>
  9#include <linux/kernel.h>
 10#include <linux/init.h>
 11#include <asm/io.h>
 12#include <linux/mtd/mtd.h>
 13#include <linux/mtd/map.h>
 14
 15#define PIIXE_IOBASE_RESOURCE        11
 16
 17#define WINDOW_ADDR 0xfff00000
 18#define WINDOW_SIZE 0x00100000
 19#define BUSWIDTH 1
 20
 21static u32 iobase;
 22#define IOBASE iobase
 23#define TRIBUF_PORT (IOBASE+0x37)
 24#define VPP_PORT (IOBASE+0x28)
 25
 26static struct mtd_info *mymtd;
 27
 28
 29/* Is this really the vpp port? */
 30static void l440gx_set_vpp(struct map_info *map, int vpp)
 31{
 32        unsigned long l;
 33
 34        l = inl(VPP_PORT);
 35        if (vpp) {
 36                l |= 1;
 37        } else {
 38                l &= ~1;
 39        }
 40        outl(l, VPP_PORT);
 41}
 42
 43static struct map_info l440gx_map = {
 44        .name = "L440GX BIOS",
 45        .size = WINDOW_SIZE,
 46        .bankwidth = BUSWIDTH,
 47        .phys = WINDOW_ADDR,
 48#if 0
 49        /* FIXME verify that this is the
 50         * appripriate code for vpp enable/disable
 51         */
 52        .set_vpp = l440gx_set_vpp
 53#endif
 54};
 55
 56static int __init init_l440gx(void)
 57{
 58        struct pci_dev *dev, *pm_dev;
 59        struct resource *pm_iobase;
 60        __u16 word;
 61
 62        dev = pci_get_device(PCI_VENDOR_ID_INTEL,
 63                PCI_DEVICE_ID_INTEL_82371AB_0, NULL);
 64
 65        pm_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
 66                PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
 67
 68        pci_dev_put(dev);
 69
 70        if (!dev || !pm_dev) {
 71                printk(KERN_NOTICE "L440GX flash mapping: failed to find PIIX4 ISA bridge, cannot continue\n");
 72                pci_dev_put(pm_dev);
 73                return -ENODEV;
 74        }
 75
 76        l440gx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
 77
 78        if (!l440gx_map.virt) {
 79                printk(KERN_WARNING "Failed to ioremap L440GX flash region\n");
 80                pci_dev_put(pm_dev);
 81                return -ENOMEM;
 82        }
 83        simple_map_init(&l440gx_map);
 84        printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.virt);
 85
 86        /* Setup the pm iobase resource
 87         * This code should move into some kind of generic bridge
 88         * driver but for the moment I'm content with getting the
 89         * allocation correct.
 90         */
 91        pm_iobase = &pm_dev->resource[PIIXE_IOBASE_RESOURCE];
 92        if (!(pm_iobase->flags & IORESOURCE_IO)) {
 93                pm_iobase->name = "pm iobase";
 94                pm_iobase->start = 0;
 95                pm_iobase->end = 63;
 96                pm_iobase->flags = IORESOURCE_IO;
 97
 98                /* Put the current value in the resource */
 99                pci_read_config_dword(pm_dev, 0x40, &iobase);
100                iobase &= ~1;
101                pm_iobase->start += iobase & ~1;
102                pm_iobase->end += iobase & ~1;
103
104                pci_dev_put(pm_dev);
105
106                /* Allocate the resource region */
107                if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) {
108                        pci_dev_put(dev);
109                        pci_dev_put(pm_dev);
110                        printk(KERN_WARNING "Could not allocate pm iobase resource\n");
111                        iounmap(l440gx_map.virt);
112                        return -ENXIO;
113                }
114        }
115        /* Set the iobase */
116        iobase = pm_iobase->start;
117        pci_write_config_dword(pm_dev, 0x40, iobase | 1);
118
119
120        /* Set XBCS# */
121        pci_read_config_word(dev, 0x4e, &word);
122        word |= 0x4;
123        pci_write_config_word(dev, 0x4e, word);
124
125        /* Supply write voltage to the chip */
126        l440gx_set_vpp(&l440gx_map, 1);
127
128        /* Enable the gate on the WE line */
129        outb(inb(TRIBUF_PORT) & ~1, TRIBUF_PORT);
130
131               printk(KERN_NOTICE "Enabled WE line to L440GX BIOS flash chip.\n");
132
133        mymtd = do_map_probe("jedec_probe", &l440gx_map);
134        if (!mymtd) {
135                printk(KERN_NOTICE "JEDEC probe on BIOS chip failed. Using ROM\n");
136                mymtd = do_map_probe("map_rom", &l440gx_map);
137        }
138        if (mymtd) {
139                mymtd->owner = THIS_MODULE;
140
141                add_mtd_device(mymtd);
142                return 0;
143        }
144
145        iounmap(l440gx_map.virt);
146        return -ENXIO;
147}
148
149static void __exit cleanup_l440gx(void)
150{
151        del_mtd_device(mymtd);
152        map_destroy(mymtd);
153
154        iounmap(l440gx_map.virt);
155}
156
157module_init(init_l440gx);
158module_exit(cleanup_l440gx);
159
160MODULE_LICENSE("GPL");
161MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
162MODULE_DESCRIPTION("MTD map driver for BIOS chips on Intel L440GX motherboards");