diff options
author | Marcin Chrzanowski <marcin.j.chrzanowski@gmail.com> | 2018-05-04 21:06:13 +0200 |
---|---|---|
committer | Marcin Chrzanowski <marcin.j.chrzanowski@gmail.com> | 2018-05-04 21:06:13 +0200 |
commit | 66d048ece86d238c0712a0a205479ce8842f3053 (patch) | |
tree | b2304c35b16ec0295f85c68c2c4e87cab2d92e49 | |
parent | 2eaa35293d31075348fe606bef5a58885d8e09a9 (diff) |
Perform basic PCI initialization
-rw-r--r-- | char.c | 20 | ||||
-rw-r--r-- | char.h | 4 | ||||
-rw-r--r-- | pci.c | 38 | ||||
-rw-r--r-- | pci.h | 1 |
4 files changed, 45 insertions, 18 deletions
@@ -44,11 +44,7 @@ int new_doomdev(struct pci_dev *dev) return -ENOMEM; } - doom_data = kmalloc(sizeof(*doom_data), GFP_KERNEL); - if (doom_data == NULL) { - err = -ENOMEM; - goto error_kmalloc; - } + doom_data = pci_get_drvdata(dev); doom_data->cdev = cdev_alloc(); if (doom_data->cdev == NULL) { @@ -63,8 +59,6 @@ int new_doomdev(struct pci_dev *dev) doom_data->device = device_create(doom_class, &dev->dev, devt, NULL, "doom%d", minor), ORFAIL_PTR(doom_data->device, error_create); - - pci_set_drvdata(dev, doom_data); return 0; @@ -72,19 +66,13 @@ error_create: cdev_del(doom_data->cdev); error_add: error_cdev: - kfree(doom_data); -error_kmalloc: return err; } -void destroy_doomdev(struct pci_dev *dev) +void destroy_doomdev(struct doom_data *doom_data) { - struct doom_data *data; - - data = pci_get_drvdata(dev); - device_destroy(doom_class, data->device->devt); - cdev_del(data->cdev); - kfree(data); + device_destroy(doom_class, doom_data->device->devt); + cdev_del(doom_data->cdev); } int char_init(void) @@ -3,8 +3,10 @@ #include <linux/pci.h> +#include "pci.h" + int new_doomdev(struct pci_dev *dev); -void destroy_doomdev(struct pci_dev *dev); +void destroy_doomdev(struct doom_data *doom_data); int char_init(void); void char_cleanup(void); @@ -10,16 +10,52 @@ int doom_probe(struct pci_dev *dev, const struct pci_device_id *id) { + struct doom_data *doom_data; int err = 0; + + ORFAIL(pci_enable_device(dev), error_enable); + ORFAIL(pci_request_regions(dev, "harddoom"), error_regions); + + doom_data = kmalloc(sizeof(*doom_data), GFP_KERNEL); + if (doom_data == NULL) { + err = -ENOMEM; + goto error_kmalloc; + } + pci_set_drvdata(dev, doom_data); + doom_data->iomem = pci_iomap(dev, 0, 0); + + pci_set_master(dev); + pci_set_dma_mask(dev, DMA_BIT_MASK(32)); + pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(32)); + ORFAIL(new_doomdev(dev), error_doomdev); + return 0; + error_doomdev: + pci_clear_master(dev); + pci_iounmap(dev, doom_data->iomem); + kfree(doom_data); +error_kmalloc: + pci_release_regions(dev); +error_regions: + pci_disable_device(dev); +error_enable: return err; } void doom_remove (struct pci_dev *dev) { - destroy_doomdev(dev); + struct doom_data *doom_data; + + doom_data = pci_get_drvdata(dev); + + destroy_doomdev(doom_data); + pci_clear_master(dev); + pci_iounmap(dev, doom_data->iomem); + kfree(doom_data); + pci_release_regions(dev); + pci_disable_device(dev); } int doom_suspend (struct pci_dev *dev, pm_message_t state) @@ -6,6 +6,7 @@ struct doom_data { struct cdev *cdev; struct device *device; + void __iomem *iomem; }; int pci_init(void); |