igb_uio: fix IRQ mode handling
[dpdk.git] / lib / librte_eal / linuxapp / igb_uio / igb_uio.c
1 /*-
2  * GPL LICENSE SUMMARY
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of version 2 of the GNU General Public License as
8  *   published by the Free Software Foundation.
9  *
10  *   This program is distributed in the hope that it will be useful, but
11  *   WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *   General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18  *   The full GNU General Public License is included in this distribution
19  *   in the file called LICENSE.GPL.
20  *
21  *   Contact Information:
22  *   Intel Corporation
23  */
24
25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27 #include <linux/device.h>
28 #include <linux/module.h>
29 #include <linux/pci.h>
30 #include <linux/uio_driver.h>
31 #include <linux/io.h>
32 #include <linux/msi.h>
33 #include <linux/version.h>
34
35 #ifdef CONFIG_XEN_DOM0
36 #include <xen/xen.h>
37 #endif
38 #include <rte_pci_dev_features.h>
39
40 #ifdef RTE_PCI_CONFIG
41 #define PCI_SYS_FILE_BUF_SIZE      10
42 #define PCI_DEV_CAP_REG            0xA4
43 #define PCI_DEV_CTRL_REG           0xA8
44 #define PCI_DEV_CAP_EXT_TAG_MASK   0x20
45 #define PCI_DEV_CTRL_EXT_TAG_SHIFT 8
46 #define PCI_DEV_CTRL_EXT_TAG_MASK  (1 << PCI_DEV_CTRL_EXT_TAG_SHIFT)
47 #endif
48
49 /**
50  * A structure describing the private information for a uio device.
51  */
52 struct rte_uio_pci_dev {
53         struct uio_info info;
54         struct pci_dev *pdev;
55         enum rte_intr_mode mode;
56 };
57
58 static char *intr_mode = NULL;
59 static enum rte_intr_mode igbuio_intr_mode_preferred = RTE_INTR_MODE_MSIX;
60
61 static inline struct rte_uio_pci_dev *
62 igbuio_get_uio_pci_dev(struct uio_info *info)
63 {
64         return container_of(info, struct rte_uio_pci_dev, info);
65 }
66
67 /* sriov sysfs */
68 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
69 static int pci_num_vf(struct pci_dev *dev)
70         struct iov {
71                 int pos;
72                 int nres;
73                 u32 cap;
74                 u16 ctrl;
75                 u16 total;
76                 u16 initial;
77                 u16 nr_virtfn;
78         } *iov = (struct iov *)dev->sriov;
79
80         if (!dev->is_physfn)
81                 return 0;
82
83         return iov->nr_virtfn;
84 }
85 #endif
86
87 static ssize_t
88 show_max_vfs(struct device *dev, struct device_attribute *attr,
89              char *buf)
90 {
91         return snprintf(buf, 10, "%u\n",
92                         pci_num_vf(container_of(dev, struct pci_dev, dev)));
93 }
94
95 static ssize_t
96 store_max_vfs(struct device *dev, struct device_attribute *attr,
97               const char *buf, size_t count)
98 {
99         int err = 0;
100         unsigned long max_vfs;
101         struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
102
103         if (0 != strict_strtoul(buf, 0, &max_vfs))
104                 return -EINVAL;
105
106         if (0 == max_vfs)
107                 pci_disable_sriov(pdev);
108         else if (0 == pci_num_vf(pdev))
109                 err = pci_enable_sriov(pdev, max_vfs);
110         else /* do nothing if change max_vfs number */
111                 err = -EINVAL;
112
113         return err ? err : count;
114 }
115
116 #ifdef RTE_PCI_CONFIG
117 static ssize_t
118 show_extended_tag(struct device *dev, struct device_attribute *attr, char *buf)
119 {
120         struct pci_dev *pci_dev = container_of(dev, struct pci_dev, dev);
121         uint32_t val = 0;
122
123         pci_read_config_dword(pci_dev, PCI_DEV_CAP_REG, &val);
124         if (!(val & PCI_DEV_CAP_EXT_TAG_MASK)) /* Not supported */
125                 return snprintf(buf, PCI_SYS_FILE_BUF_SIZE, "%s\n", "invalid");
126
127         val = 0;
128         pci_bus_read_config_dword(pci_dev->bus, pci_dev->devfn,
129                                         PCI_DEV_CTRL_REG, &val);
130
131         return snprintf(buf, PCI_SYS_FILE_BUF_SIZE, "%s\n",
132                 (val & PCI_DEV_CTRL_EXT_TAG_MASK) ? "on" : "off");
133 }
134
135 static ssize_t
136 store_extended_tag(struct device *dev,
137                    struct device_attribute *attr,
138                    const char *buf,
139                    size_t count)
140 {
141         struct pci_dev *pci_dev = container_of(dev, struct pci_dev, dev);
142         uint32_t val = 0, enable;
143
144         if (strncmp(buf, "on", 2) == 0)
145                 enable = 1;
146         else if (strncmp(buf, "off", 3) == 0)
147                 enable = 0;
148         else
149                 return -EINVAL;
150
151         pci_cfg_access_lock(pci_dev);
152         pci_bus_read_config_dword(pci_dev->bus, pci_dev->devfn,
153                                         PCI_DEV_CAP_REG, &val);
154         if (!(val & PCI_DEV_CAP_EXT_TAG_MASK)) { /* Not supported */
155                 pci_cfg_access_unlock(pci_dev);
156                 return -EPERM;
157         }
158
159         val = 0;
160         pci_bus_read_config_dword(pci_dev->bus, pci_dev->devfn,
161                                         PCI_DEV_CTRL_REG, &val);
162         if (enable)
163                 val |= PCI_DEV_CTRL_EXT_TAG_MASK;
164         else
165                 val &= ~PCI_DEV_CTRL_EXT_TAG_MASK;
166         pci_bus_write_config_dword(pci_dev->bus, pci_dev->devfn,
167                                         PCI_DEV_CTRL_REG, val);
168         pci_cfg_access_unlock(pci_dev);
169
170         return count;
171 }
172
173 static ssize_t
174 show_max_read_request_size(struct device *dev,
175                            struct device_attribute *attr,
176                            char *buf)
177 {
178         struct pci_dev *pci_dev = container_of(dev, struct pci_dev, dev);
179         int val = pcie_get_readrq(pci_dev);
180
181         return snprintf(buf, PCI_SYS_FILE_BUF_SIZE, "%d\n", val);
182 }
183
184 static ssize_t
185 store_max_read_request_size(struct device *dev,
186                             struct device_attribute *attr,
187                             const char *buf,
188                             size_t count)
189 {
190         struct pci_dev *pci_dev = container_of(dev, struct pci_dev, dev);
191         unsigned long size = 0;
192         int ret;
193
194         if (strict_strtoul(buf, 0, &size) != 0)
195                 return -EINVAL;
196
197         ret = pcie_set_readrq(pci_dev, (int)size);
198         if (ret < 0)
199                 return ret;
200
201         return count;
202 }
203 #endif
204
205 static DEVICE_ATTR(max_vfs, S_IRUGO | S_IWUSR, show_max_vfs, store_max_vfs);
206 #ifdef RTE_PCI_CONFIG
207 static DEVICE_ATTR(extended_tag, S_IRUGO | S_IWUSR, show_extended_tag,
208         store_extended_tag);
209 static DEVICE_ATTR(max_read_request_size, S_IRUGO | S_IWUSR,
210         show_max_read_request_size, store_max_read_request_size);
211 #endif
212
213 static struct attribute *dev_attrs[] = {
214         &dev_attr_max_vfs.attr,
215 #ifdef RTE_PCI_CONFIG
216         &dev_attr_extended_tag.attr,
217         &dev_attr_max_read_request_size.attr,
218 #endif
219         NULL,
220 };
221
222 static const struct attribute_group dev_attr_grp = {
223         .attrs = dev_attrs,
224 };
225
226 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
227 /* Check if INTX works to control irq's.
228  * Set's INTX_DISABLE flag and reads it back
229  */
230 static bool pci_intx_mask_supported(struct pci_dev *dev)
231 {
232         bool mask_supported = false;
233         uint16_t orig, new
234
235         pci_block_user_cfg_access(dev);
236         pci_read_config_word(pdev, PCI_COMMAND, &orig);
237         pci_write_config_word(dev, PCI_COMMAND,
238                               orig ^ PCI_COMMAND_INTX_DISABLE);
239         pci_read_config_word(dev, PCI_COMMAND, &new);
240
241         if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
242                 dev_err(&dev->dev, "Command register changed from "
243                         "0x%x to 0x%x: driver or hardware bug?\n", orig, new);
244         } else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) {
245                 mask_supported = true;
246                 pci_write_config_word(dev, PCI_COMMAND, orig);
247         }
248         pci_unblock_user_cfg_access(dev);
249 }
250
251 static bool pci_check_and_mask_intx(struct pci_dev *pdev)
252 {
253         bool pending;
254         uint32_t status;
255
256         pci_block_user_cfg_access(dev);
257         pci_read_config_dword(pdev, PCI_COMMAND, &status);
258
259         /* interrupt is not ours, goes to out */
260         pending = (((status >> 16) & PCI_STATUS_INTERRUPT) != 0);
261         if (pending) {
262                 uint16_t old, new;
263
264                 old = status;
265                 if (state != 0)
266                         new = old & (~PCI_COMMAND_INTX_DISABLE);
267                 else
268                         new = old | PCI_COMMAND_INTX_DISABLE;
269
270                 if (old != new)
271                         pci_write_config_word(pdev, PCI_COMMAND, new);
272         }
273         pci_unblock_user_cfg_access(dev);
274
275         return pending;
276 }
277 #endif
278
279 /*
280  * It masks the msix on/off of generating MSI-X messages.
281  */
282 static void
283 igbuio_msix_mask_irq(struct msi_desc *desc, int32_t state)
284 {
285         u32 mask_bits = desc->masked;
286         unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
287                                                 PCI_MSIX_ENTRY_VECTOR_CTRL;
288
289         if (state != 0)
290                 mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
291         else
292                 mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
293
294         if (mask_bits != desc->masked) {
295                 writel(mask_bits, desc->mask_base + offset);
296                 readl(desc->mask_base);
297                 desc->masked = mask_bits;
298         }
299 }
300
301 /**
302  * This is the irqcontrol callback to be registered to uio_info.
303  * It can be used to disable/enable interrupt from user space processes.
304  *
305  * @param info
306  *  pointer to uio_info.
307  * @param irq_state
308  *  state value. 1 to enable interrupt, 0 to disable interrupt.
309  *
310  * @return
311  *  - On success, 0.
312  *  - On failure, a negative value.
313  */
314 static int
315 igbuio_pci_irqcontrol(struct uio_info *info, s32 irq_state)
316 {
317         struct rte_uio_pci_dev *udev = igbuio_get_uio_pci_dev(info);
318         struct pci_dev *pdev = udev->pdev;
319
320         pci_cfg_access_lock(pdev);
321         if (udev->mode == RTE_INTR_MODE_LEGACY)
322                 pci_intx(pdev, !!irq_state);
323
324         else if (udev->mode == RTE_INTR_MODE_MSIX) {
325                 struct msi_desc *desc;
326
327                 list_for_each_entry(desc, &pdev->msi_list, list)
328                         igbuio_msix_mask_irq(desc, irq_state);
329         }
330         pci_cfg_access_unlock(pdev);
331
332         return 0;
333 }
334
335 /**
336  * This is interrupt handler which will check if the interrupt is for the right device.
337  * If yes, disable it here and will be enable later.
338  */
339 static irqreturn_t
340 igbuio_pci_irqhandler(int irq, struct uio_info *info)
341 {
342         struct rte_uio_pci_dev *udev = igbuio_get_uio_pci_dev(info);
343
344         /* Legacy mode need to mask in hardware */
345         if (udev->mode == RTE_INTR_MODE_LEGACY &&
346             !pci_check_and_mask_intx(udev->pdev))
347                 return IRQ_NONE;
348
349         /* Message signal mode, no share IRQ and automasked */
350         return IRQ_HANDLED;
351 }
352
353 #ifdef CONFIG_XEN_DOM0
354 static int
355 igbuio_dom0_mmap_phys(struct uio_info *info, struct vm_area_struct *vma)
356 {
357         int idx;
358
359         idx = (int)vma->vm_pgoff;
360         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
361         vma->vm_page_prot.pgprot |= _PAGE_IOMAP;
362
363         return remap_pfn_range(vma,
364                         vma->vm_start,
365                         info->mem[idx].addr >> PAGE_SHIFT,
366                         vma->vm_end - vma->vm_start,
367                         vma->vm_page_prot);
368 }
369
370 /**
371  * This is uio device mmap method which will use igbuio mmap for Xen
372  * Dom0 environment.
373  */
374 static int
375 igbuio_dom0_pci_mmap(struct uio_info *info, struct vm_area_struct *vma)
376 {
377         int idx;
378
379         if (vma->vm_pgoff >= MAX_UIO_MAPS)
380                 return -EINVAL;
381
382         if (info->mem[vma->vm_pgoff].size == 0)
383                 return -EINVAL;
384
385         idx = (int)vma->vm_pgoff;
386         switch (info->mem[idx].memtype) {
387         case UIO_MEM_PHYS:
388                 return igbuio_dom0_mmap_phys(info, vma);
389         case UIO_MEM_LOGICAL:
390         case UIO_MEM_VIRTUAL:
391         default:
392                 return -EINVAL;
393         }
394 }
395 #endif
396
397 /* Remap pci resources described by bar #pci_bar in uio resource n. */
398 static int
399 igbuio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info,
400                        int n, int pci_bar, const char *name)
401 {
402         unsigned long addr, len;
403         void *internal_addr;
404
405         if (sizeof(info->mem) / sizeof(info->mem[0]) <= n)
406                 return -EINVAL;
407
408         addr = pci_resource_start(dev, pci_bar);
409         len = pci_resource_len(dev, pci_bar);
410         if (addr == 0 || len == 0)
411                 return -1;
412         internal_addr = ioremap(addr, len);
413         if (internal_addr == NULL)
414                 return -1;
415         info->mem[n].name = name;
416         info->mem[n].addr = addr;
417         info->mem[n].internal_addr = internal_addr;
418         info->mem[n].size = len;
419         info->mem[n].memtype = UIO_MEM_PHYS;
420         return 0;
421 }
422
423 /* Get pci port io resources described by bar #pci_bar in uio resource n. */
424 static int
425 igbuio_pci_setup_ioport(struct pci_dev *dev, struct uio_info *info,
426                 int n, int pci_bar, const char *name)
427 {
428         unsigned long addr, len;
429
430         if (sizeof(info->port) / sizeof(info->port[0]) <= n)
431                 return -EINVAL;
432
433         addr = pci_resource_start(dev, pci_bar);
434         len = pci_resource_len(dev, pci_bar);
435         if (addr == 0 || len == 0)
436                 return -EINVAL;
437
438         info->port[n].name = name;
439         info->port[n].start = addr;
440         info->port[n].size = len;
441         info->port[n].porttype = UIO_PORT_X86;
442
443         return 0;
444 }
445
446 /* Unmap previously ioremap'd resources */
447 static void
448 igbuio_pci_release_iomem(struct uio_info *info)
449 {
450         int i;
451
452         for (i = 0; i < MAX_UIO_MAPS; i++) {
453                 if (info->mem[i].internal_addr)
454                         iounmap(info->mem[i].internal_addr);
455         }
456 }
457
458 static int
459 igbuio_setup_bars(struct pci_dev *dev, struct uio_info *info)
460 {
461         int i, iom, iop, ret;
462         unsigned long flags;
463         static const char *bar_names[PCI_STD_RESOURCE_END + 1]  = {
464                 "BAR0",
465                 "BAR1",
466                 "BAR2",
467                 "BAR3",
468                 "BAR4",
469                 "BAR5",
470         };
471
472         iom = 0;
473         iop = 0;
474
475         for (i = 0; i != sizeof(bar_names) / sizeof(bar_names[0]); i++) {
476                 if (pci_resource_len(dev, i) != 0 &&
477                                 pci_resource_start(dev, i) != 0) {
478                         flags = pci_resource_flags(dev, i);
479                         if (flags & IORESOURCE_MEM) {
480                                 ret = igbuio_pci_setup_iomem(dev, info, iom,
481                                                              i, bar_names[i]);
482                                 if (ret != 0)
483                                         return ret;
484                                 iom++;
485                         } else if (flags & IORESOURCE_IO) {
486                                 ret = igbuio_pci_setup_ioport(dev, info, iop,
487                                                               i, bar_names[i]);
488                                 if (ret != 0)
489                                         return ret;
490                                 iop++;
491                         }
492                 }
493         }
494
495         return (iom != 0) ? ret : -ENOENT;
496 }
497
498 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
499 static int __devinit
500 #else
501 static int
502 #endif
503 igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
504 {
505         struct rte_uio_pci_dev *udev;
506         struct msix_entry msix_entry;
507         int err;
508
509         udev = kzalloc(sizeof(struct rte_uio_pci_dev), GFP_KERNEL);
510         if (!udev)
511                 return -ENOMEM;
512
513         /*
514          * enable device: ask low-level code to enable I/O and
515          * memory
516          */
517         err = pci_enable_device(dev);
518         if (err != 0) {
519                 dev_err(&dev->dev, "Cannot enable PCI device\n");
520                 goto fail_free;
521         }
522
523         /*
524          * reserve device's PCI memory regions for use by this
525          * module
526          */
527         err = pci_request_regions(dev, "igb_uio");
528         if (err != 0) {
529                 dev_err(&dev->dev, "Cannot request regions\n");
530                 goto fail_disable;
531         }
532
533         /* enable bus mastering on the device */
534         pci_set_master(dev);
535
536         /* remap IO memory */
537         err = igbuio_setup_bars(dev, &udev->info);
538         if (err != 0)
539                 goto fail_release_iomem;
540
541         /* set 64-bit DMA mask */
542         err = pci_set_dma_mask(dev,  DMA_BIT_MASK(64));
543         if (err != 0) {
544                 dev_err(&dev->dev, "Cannot set DMA mask\n");
545                 goto fail_release_iomem;
546         }
547
548         err = pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64));
549         if (err != 0) {
550                 dev_err(&dev->dev, "Cannot set consistent DMA mask\n");
551                 goto fail_release_iomem;
552         }
553
554         /* fill uio infos */
555         udev->info.name = "igb_uio";
556         udev->info.version = "0.1";
557         udev->info.handler = igbuio_pci_irqhandler;
558         udev->info.irqcontrol = igbuio_pci_irqcontrol;
559         udev->info.irq = dev->irq;
560 #ifdef CONFIG_XEN_DOM0
561         /* check if the driver run on Xen Dom0 */
562         if (xen_initial_domain())
563                 udev->info.mmap = igbuio_dom0_pci_mmap;
564 #endif
565         udev->info.priv = udev;
566         udev->pdev = dev;
567
568         switch (igbuio_intr_mode_preferred) {
569         case RTE_INTR_MODE_NONE:
570                 udev->info.irq = 0;
571                 break;
572         case RTE_INTR_MODE_MSIX:
573                 /* Only 1 msi-x vector needed */
574                 msix_entry.entry = 0;
575                 if (pci_enable_msix(dev, &msix_entry, 1) == 0) {
576                         dev_dbg(&dev->dev, "using MSI-X");
577                         udev->info.irq = msix_entry.vector;
578                         udev->mode = RTE_INTR_MODE_MSIX;
579                         break;
580                 }
581                 /* fall back to INTX */
582         case RTE_INTR_MODE_LEGACY:
583                 if (pci_intx_mask_supported(dev)) {
584                         dev_dbg(&dev->dev, "using INTX");
585                         udev->info.irq_flags = IRQF_SHARED;
586                         udev->mode = RTE_INTR_MODE_LEGACY;
587                 } else {
588                         dev_err(&dev->dev, "PCI INTX mask not supported\n");
589                         err = -EIO;
590                         goto fail_release_iomem;
591                 }
592                 break;
593         default:
594                 dev_err(&dev->dev, "invalid IRQ mode %u",
595                         igbuio_intr_mode_preferred);
596                 err = -EINVAL;
597                 goto fail_release_iomem;
598         }
599
600         err = sysfs_create_group(&dev->dev.kobj, &dev_attr_grp);
601         if (err != 0)
602                 goto fail_release_iomem;
603
604         /* register uio driver */
605         err = uio_register_device(&dev->dev, &udev->info);
606         if (err != 0)
607                 goto fail_remove_group;
608
609         pci_set_drvdata(dev, udev);
610
611         dev_info(&dev->dev, "uio device registered with irq %lx\n",
612                  udev->info.irq);
613
614         return 0;
615
616 fail_remove_group:
617         sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp);
618 fail_release_iomem:
619         igbuio_pci_release_iomem(&udev->info);
620         if (udev->mode == RTE_INTR_MODE_MSIX)
621                 pci_disable_msix(udev->pdev);
622         pci_release_regions(dev);
623 fail_disable:
624         pci_disable_device(dev);
625 fail_free:
626         kfree(udev);
627
628         return err;
629 }
630
631 static void
632 igbuio_pci_remove(struct pci_dev *dev)
633 {
634         struct uio_info *info = pci_get_drvdata(dev);
635         struct rte_uio_pci_dev *udev = igbuio_get_uio_pci_dev(info);
636
637         if (info->priv == NULL) {
638                 pr_notice("Not igbuio device\n");
639                 return;
640         }
641
642         sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp);
643         uio_unregister_device(info);
644         igbuio_pci_release_iomem(info);
645         if (udev->mode == RTE_INTR_MODE_MSIX)
646                 pci_disable_msix(dev);
647         pci_release_regions(dev);
648         pci_disable_device(dev);
649         pci_set_drvdata(dev, NULL);
650         kfree(info);
651 }
652
653 static int
654 igbuio_config_intr_mode(char *intr_str)
655 {
656         if (!intr_str) {
657                 pr_info("Use MSIX interrupt by default\n");
658                 return 0;
659         }
660
661         if (!strcmp(intr_str, RTE_INTR_MODE_MSIX_NAME)) {
662                 igbuio_intr_mode_preferred = RTE_INTR_MODE_MSIX;
663                 pr_info("Use MSIX interrupt\n");
664         } else if (!strcmp(intr_str, RTE_INTR_MODE_LEGACY_NAME)) {
665                 igbuio_intr_mode_preferred = RTE_INTR_MODE_LEGACY;
666                 pr_info("Use legacy interrupt\n");
667         } else {
668                 pr_info("Error: bad parameter - %s\n", intr_str);
669                 return -EINVAL;
670         }
671
672         return 0;
673 }
674
675 static struct pci_driver igbuio_pci_driver = {
676         .name = "igb_uio",
677         .id_table = NULL,
678         .probe = igbuio_pci_probe,
679         .remove = igbuio_pci_remove,
680 };
681
682 static int __init
683 igbuio_pci_init_module(void)
684 {
685         int ret;
686
687         ret = igbuio_config_intr_mode(intr_mode);
688         if (ret < 0)
689                 return ret;
690
691         return pci_register_driver(&igbuio_pci_driver);
692 }
693
694 static void __exit
695 igbuio_pci_exit_module(void)
696 {
697         pci_unregister_driver(&igbuio_pci_driver);
698 }
699
700 module_init(igbuio_pci_init_module);
701 module_exit(igbuio_pci_exit_module);
702
703 module_param(intr_mode, charp, S_IRUGO);
704 MODULE_PARM_DESC(intr_mode,
705 "igb_uio interrupt mode (default=msix):\n"
706 "    " RTE_INTR_MODE_MSIX_NAME "       Use MSIX interrupt\n"
707 "    " RTE_INTR_MODE_LEGACY_NAME "     Use Legacy interrupt\n"
708 "\n");
709
710 MODULE_DESCRIPTION("UIO driver for Intel IGB PCI cards");
711 MODULE_LICENSE("GPL");
712 MODULE_AUTHOR("Intel Corporation");