1c88aa867a1c90c2b07825d83935d6e73223c0ab
[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 #include <linux/device.h>
26 #include <linux/module.h>
27 #include <linux/pci.h>
28 #include <linux/uio_driver.h>
29 #include <linux/io.h>
30 #include <linux/msi.h>
31 #include <linux/version.h>
32
33 #ifdef CONFIG_XEN_DOM0 
34 #include <xen/xen.h>
35 #endif
36
37 /**
38  * MSI-X related macros, copy from linux/pci_regs.h in kernel 2.6.39,
39  * but none of them in kernel 2.6.35.
40  */
41 #ifndef PCI_MSIX_ENTRY_SIZE
42 #define PCI_MSIX_ENTRY_SIZE             16
43 #define PCI_MSIX_ENTRY_LOWER_ADDR       0
44 #define PCI_MSIX_ENTRY_UPPER_ADDR       4
45 #define PCI_MSIX_ENTRY_DATA             8
46 #define PCI_MSIX_ENTRY_VECTOR_CTRL      12
47 #define PCI_MSIX_ENTRY_CTRL_MASKBIT     1
48 #endif
49
50 #define IGBUIO_NUM_MSI_VECTORS 1
51
52 /* interrupt mode */
53 enum igbuio_intr_mode {
54         IGBUIO_LEGACY_INTR_MODE = 0,
55         IGBUIO_MSI_INTR_MODE,
56         IGBUIO_MSIX_INTR_MODE,
57         IGBUIO_INTR_MODE_MAX
58 };
59
60 /**
61  * A structure describing the private information for a uio device.
62  */
63 struct rte_uio_pci_dev {
64         struct uio_info info;
65         struct pci_dev *pdev;
66         spinlock_t lock; /* spinlock for accessing PCI config space or msix data in multi tasks/isr */
67         enum igbuio_intr_mode mode;
68         struct msix_entry \
69                 msix_entries[IGBUIO_NUM_MSI_VECTORS]; /* pointer to the msix vectors to be allocated later */
70 };
71
72 static char *intr_mode = NULL;
73 static enum igbuio_intr_mode igbuio_intr_mode_preferred = IGBUIO_MSIX_INTR_MODE;
74
75 /* PCI device id table */
76 static struct pci_device_id igbuio_pci_ids[] = {
77 #define RTE_PCI_DEV_ID_DECL_EM(vend, dev) {PCI_DEVICE(vend, dev)},
78 #define RTE_PCI_DEV_ID_DECL_IGB(vend, dev) {PCI_DEVICE(vend, dev)},
79 #define RTE_PCI_DEV_ID_DECL_IGBVF(vend, dev) {PCI_DEVICE(vend, dev)},
80 #define RTE_PCI_DEV_ID_DECL_IXGBE(vend, dev) {PCI_DEVICE(vend, dev)},
81 #define RTE_PCI_DEV_ID_DECL_IXGBEVF(vend, dev) {PCI_DEVICE(vend, dev)},
82 #define RTE_PCI_DEV_ID_DECL_VIRTIO(vend, dev) {PCI_DEVICE(vend, dev)},
83 #define RTE_PCI_DEV_ID_DECL_VMXNET3(vend, dev) {PCI_DEVICE(vend, dev)},
84 #include <rte_pci_dev_ids.h>
85 { 0, },
86 };
87
88 MODULE_DEVICE_TABLE(pci, igbuio_pci_ids);
89
90 static inline struct rte_uio_pci_dev *
91 igbuio_get_uio_pci_dev(struct uio_info *info)
92 {
93         return container_of(info, struct rte_uio_pci_dev, info);
94 }
95
96 /* sriov sysfs */
97 int local_pci_num_vf(struct pci_dev *dev)
98 {
99 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
100         struct iov {
101                 int pos;
102                 int nres;
103                 u32 cap;
104                 u16 ctrl;
105                 u16 total;
106                 u16 initial;
107                 u16 nr_virtfn;
108         } *iov = (struct iov*)dev->sriov;
109
110         if (!dev->is_physfn)
111                 return 0;
112         
113         return iov->nr_virtfn;
114 #else
115         return pci_num_vf(dev);
116 #endif
117 }
118
119 static ssize_t
120 show_max_vfs(struct device *dev, struct device_attribute *attr,
121              char *buf)
122 {
123         return snprintf(buf, 10, "%u\n", local_pci_num_vf(
124                                 container_of(dev, struct pci_dev, dev)));
125 }
126
127 static ssize_t
128 store_max_vfs(struct device *dev, struct device_attribute *attr,
129               const char *buf, size_t count)
130 {
131         int err = 0;
132         unsigned long max_vfs;
133         struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
134
135         if (0 != strict_strtoul(buf, 0, &max_vfs))
136                 return -EINVAL;
137
138         if (0 == max_vfs)
139                 pci_disable_sriov(pdev);
140         else if (0 == local_pci_num_vf(pdev))
141                 err = pci_enable_sriov(pdev, max_vfs);
142         else /* do nothing if change max_vfs number */
143                 err = -EINVAL;
144
145         return err ? err : count;                                                       
146 }
147
148 static DEVICE_ATTR(max_vfs, S_IRUGO | S_IWUSR, show_max_vfs, store_max_vfs);
149 static struct attribute *dev_attrs[] = {
150         &dev_attr_max_vfs.attr,
151         NULL,
152 };
153
154 static const struct attribute_group dev_attr_grp = {
155         .attrs = dev_attrs,
156 };
157
158 static inline int
159 pci_lock(struct pci_dev * pdev)
160 {
161         /* Some function names changes between 3.2.0 and 3.3.0... */
162 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
163         pci_block_user_cfg_access(pdev);
164         return 1;
165 #else
166         return pci_cfg_access_trylock(pdev);
167 #endif
168 }
169
170 static inline void
171 pci_unlock(struct pci_dev * pdev)
172 {
173         /* Some function names changes between 3.2.0 and 3.3.0... */
174 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
175         pci_unblock_user_cfg_access(pdev);
176 #else
177         pci_cfg_access_unlock(pdev);
178 #endif
179 }
180
181 /**
182  * It masks the msix on/off of generating MSI-X messages.
183  */
184 static int
185 igbuio_msix_mask_irq(struct msi_desc *desc, int32_t state)
186 {
187         uint32_t mask_bits = desc->masked;
188         unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
189                                                 PCI_MSIX_ENTRY_VECTOR_CTRL;
190
191         if (state != 0)
192                 mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
193         else
194                 mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
195
196         if (mask_bits != desc->masked) {
197                 writel(mask_bits, desc->mask_base + offset);
198                 readl(desc->mask_base);
199                 desc->masked = mask_bits;
200         }
201
202         return 0;
203 }
204
205 /**
206  * This function sets/clears the masks for generating LSC interrupts.
207  *
208  * @param info
209  *   The pointer to struct uio_info.
210  * @param on
211  *   The on/off flag of masking LSC.
212  * @return
213  *   -On success, zero value.
214  *   -On failure, a negative value.
215  */
216 static int
217 igbuio_set_interrupt_mask(struct rte_uio_pci_dev *udev, int32_t state)
218 {
219         struct pci_dev *pdev = udev->pdev;
220
221         if (udev->mode == IGBUIO_MSIX_INTR_MODE) {
222                 struct msi_desc *desc;
223
224                 list_for_each_entry(desc, &pdev->msi_list, list) {
225                         igbuio_msix_mask_irq(desc, state);
226                 }
227         }
228         else if (udev->mode == IGBUIO_LEGACY_INTR_MODE) {
229                 uint32_t status;
230                 uint16_t old, new;
231
232                 pci_read_config_dword(pdev, PCI_COMMAND, &status);
233                 old = status;
234                 if (state != 0)
235                         new = old & (~PCI_COMMAND_INTX_DISABLE);
236                 else
237                         new = old | PCI_COMMAND_INTX_DISABLE;
238
239                 if (old != new)
240                         pci_write_config_word(pdev, PCI_COMMAND, new);
241         }
242
243         return 0;
244 }
245
246 /**
247  * This is the irqcontrol callback to be registered to uio_info.
248  * It can be used to disable/enable interrupt from user space processes.
249  *
250  * @param info
251  *  pointer to uio_info.
252  * @param irq_state
253  *  state value. 1 to enable interrupt, 0 to disable interrupt.
254  *
255  * @return
256  *  - On success, 0.
257  *  - On failure, a negative value.
258  */
259 static int
260 igbuio_pci_irqcontrol(struct uio_info *info, s32 irq_state)
261 {
262         unsigned long flags;
263         struct rte_uio_pci_dev *udev = igbuio_get_uio_pci_dev(info);
264         struct pci_dev *pdev = udev->pdev;
265
266         spin_lock_irqsave(&udev->lock, flags);
267         if (!pci_lock(pdev)) {
268                 spin_unlock_irqrestore(&udev->lock, flags);
269                 return -1;
270         }
271
272         igbuio_set_interrupt_mask(udev, irq_state);
273
274         pci_unlock(pdev);
275         spin_unlock_irqrestore(&udev->lock, flags);
276
277         return 0;
278 }
279
280 /**
281  * This is interrupt handler which will check if the interrupt is for the right device.
282  * If yes, disable it here and will be enable later.
283  */
284 static irqreturn_t
285 igbuio_pci_irqhandler(int irq, struct uio_info *info)
286 {
287         irqreturn_t ret = IRQ_NONE;
288         unsigned long flags;
289         struct rte_uio_pci_dev *udev = igbuio_get_uio_pci_dev(info);
290         struct pci_dev *pdev = udev->pdev;
291         uint32_t cmd_status_dword;
292         uint16_t status;
293
294         spin_lock_irqsave(&udev->lock, flags);
295         /* block userspace PCI config reads/writes */
296         if (!pci_lock(pdev))
297                 goto spin_unlock;
298
299         /* for legacy mode, interrupt maybe shared */
300         if (udev->mode == IGBUIO_LEGACY_INTR_MODE) {
301                 pci_read_config_dword(pdev, PCI_COMMAND, &cmd_status_dword);
302                 status = cmd_status_dword >> 16;
303                 /* interrupt is not ours, goes to out */
304                 if (!(status & PCI_STATUS_INTERRUPT))
305                         goto done;
306         }
307
308         igbuio_set_interrupt_mask(udev, 0);
309         ret = IRQ_HANDLED;
310 done:
311         /* unblock userspace PCI config reads/writes */
312         pci_unlock(pdev);
313 spin_unlock:
314         spin_unlock_irqrestore(&udev->lock, flags);
315         printk(KERN_INFO "irq 0x%x %s\n", irq, (ret == IRQ_HANDLED) ? "handled" : "not handled");
316
317         return ret;
318 }
319
320 #ifdef CONFIG_XEN_DOM0
321 static int
322 igbuio_dom0_mmap_phys(struct uio_info *info, struct vm_area_struct *vma)
323 {
324         int idx;
325         idx = (int)vma->vm_pgoff;
326         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
327         vma->vm_page_prot.pgprot |= _PAGE_IOMAP;
328
329         return remap_pfn_range(vma,
330                         vma->vm_start,
331                         info->mem[idx].addr >> PAGE_SHIFT,
332                         vma->vm_end - vma->vm_start,
333                         vma->vm_page_prot);
334 }
335
336 /**
337  * This is uio device mmap method which will use igbuio mmap for Xen 
338  * Dom0 enviroment.
339  */
340 static int
341 igbuio_dom0_pci_mmap(struct uio_info *info, struct vm_area_struct *vma)
342 {
343         int idx;
344
345         if (vma->vm_pgoff >= MAX_UIO_MAPS) 
346                 return -EINVAL;
347         if(info->mem[vma->vm_pgoff].size == 0)
348                 return  -EINVAL;
349
350         idx = (int)vma->vm_pgoff;
351         switch (info->mem[idx].memtype) {
352         case UIO_MEM_PHYS:
353                 return igbuio_dom0_mmap_phys(info, vma);
354         case UIO_MEM_LOGICAL:
355         case UIO_MEM_VIRTUAL:
356         default:
357                 return -EINVAL;
358         }
359 }       
360 #endif
361
362 /* Remap pci resources described by bar #pci_bar in uio resource n. */
363 static int
364 igbuio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info,
365                        int n, int pci_bar, const char *name)
366 {
367         unsigned long addr, len;
368         void *internal_addr;
369
370         if (sizeof(info->mem) / sizeof (info->mem[0]) <= n)  
371                 return (EINVAL);
372
373         addr = pci_resource_start(dev, pci_bar);
374         len = pci_resource_len(dev, pci_bar);
375         if (addr == 0 || len == 0)
376                 return -1;
377         internal_addr = ioremap(addr, len);
378         if (internal_addr == NULL)
379                 return -1;
380         info->mem[n].name = name;
381         info->mem[n].addr = addr;
382         info->mem[n].internal_addr = internal_addr;
383         info->mem[n].size = len;
384         info->mem[n].memtype = UIO_MEM_PHYS;
385         return 0;
386 }
387
388 /* Get pci port io resources described by bar #pci_bar in uio resource n. */
389 static int
390 igbuio_pci_setup_ioport(struct pci_dev *dev, struct uio_info *info,
391                 int n, int pci_bar, const char *name)
392 {
393         unsigned long addr, len;
394
395         if (sizeof(info->port) / sizeof (info->port[0]) <= n)  
396                 return (EINVAL);
397
398         addr = pci_resource_start(dev, pci_bar);
399         len = pci_resource_len(dev, pci_bar);
400         if (addr == 0 || len == 0)
401                 return (-1);
402
403         info->port[n].name = name;
404         info->port[n].start = addr;
405         info->port[n].size = len;
406         info->port[n].porttype = UIO_PORT_X86;
407
408         return (0);
409 }
410
411 /* Unmap previously ioremap'd resources */
412 static void
413 igbuio_pci_release_iomem(struct uio_info *info)
414 {
415         int i;
416         for (i = 0; i < MAX_UIO_MAPS; i++) {
417                 if (info->mem[i].internal_addr)
418                         iounmap(info->mem[i].internal_addr);
419         }
420 }
421
422 static int
423 igbuio_setup_bars(struct pci_dev *dev, struct uio_info *info)
424 {
425         int i, iom, iop, ret;
426         unsigned long flags;
427         static const char *bar_names[PCI_STD_RESOURCE_END + 1]  = {
428                 "BAR0",
429                 "BAR1",
430                 "BAR2",
431                 "BAR3",
432                 "BAR4",
433                 "BAR5",
434         };
435
436         iom = 0;
437         iop = 0;
438
439         for (i = 0; i != sizeof(bar_names) / sizeof(bar_names[0]); i++) {
440                 if (pci_resource_len(dev, i) != 0 &&
441                                 pci_resource_start(dev, i) != 0) {
442                         flags = pci_resource_flags(dev, i);
443                         if (flags & IORESOURCE_MEM) {
444                                 if ((ret = igbuio_pci_setup_iomem(dev, info,
445                                                 iom, i, bar_names[i])) != 0)
446                                         return (ret);
447                                 iom++;
448                         } else if (flags & IORESOURCE_IO) {
449                                 if ((ret = igbuio_pci_setup_ioport(dev, info,
450                                                 iop, i, bar_names[i])) != 0)
451                                         return (ret);
452                                 iop++;
453                         }
454                 }
455         }
456
457         return ((iom != 0) ? ret : ENOENT);
458 }
459
460 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
461 static int __devinit
462 #else
463 static int
464 #endif
465 igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
466 {
467         struct rte_uio_pci_dev *udev;
468
469         udev = kzalloc(sizeof(struct rte_uio_pci_dev), GFP_KERNEL);
470         if (!udev)
471                 return -ENOMEM;
472
473         /*
474          * enable device: ask low-level code to enable I/O and
475          * memory
476          */
477         if (pci_enable_device(dev)) {
478                 printk(KERN_ERR "Cannot enable PCI device\n");
479                 goto fail_free;
480         }
481
482         /*
483          * reserve device's PCI memory regions for use by this
484          * module
485          */
486         if (pci_request_regions(dev, "igb_uio")) {
487                 printk(KERN_ERR "Cannot request regions\n");
488                 goto fail_disable;
489         }
490
491         /* enable bus mastering on the device */
492         pci_set_master(dev);
493
494         /* remap IO memory */
495         if (igbuio_setup_bars(dev, &udev->info))
496                 goto fail_release_iomem;
497
498         /* set 64-bit DMA mask */
499         if (pci_set_dma_mask(dev,  DMA_BIT_MASK(64))) {
500                 printk(KERN_ERR "Cannot set DMA mask\n");
501                 goto fail_release_iomem;
502         } else if (pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64))) {
503                 printk(KERN_ERR "Cannot set consistent DMA mask\n");
504                 goto fail_release_iomem;
505         }
506
507         /* fill uio infos */
508         udev->info.name = "Intel IGB UIO";
509         udev->info.version = "0.1";
510         udev->info.handler = igbuio_pci_irqhandler;
511         udev->info.irqcontrol = igbuio_pci_irqcontrol;
512 #ifdef CONFIG_XEN_DOM0
513         /* check if the driver run on Xen Dom0 */
514         if (xen_initial_domain())
515                 udev->info.mmap = igbuio_dom0_pci_mmap;
516 #endif
517         udev->info.priv = udev;
518         udev->pdev = dev;
519         udev->mode = 0; /* set the default value for interrupt mode */
520         spin_lock_init(&udev->lock);
521
522         /* check if it need to try msix first */
523         if (igbuio_intr_mode_preferred == IGBUIO_MSIX_INTR_MODE) {
524                 int vector;
525
526                 for (vector = 0; vector < IGBUIO_NUM_MSI_VECTORS; vector ++)
527                         udev->msix_entries[vector].entry = vector;
528
529                 if (pci_enable_msix(udev->pdev, udev->msix_entries, IGBUIO_NUM_MSI_VECTORS) == 0) {
530                         udev->mode = IGBUIO_MSIX_INTR_MODE;
531                 }
532                 else {
533                         pci_disable_msix(udev->pdev);
534                         printk(KERN_INFO "fail to enable pci msix, or not enough msix entries\n");
535                 }
536         }
537         switch (udev->mode) {
538         case IGBUIO_MSIX_INTR_MODE:
539                 udev->info.irq_flags = 0;
540                 udev->info.irq = udev->msix_entries[0].vector;
541                 break;
542         case IGBUIO_MSI_INTR_MODE:
543                 break;
544         case IGBUIO_LEGACY_INTR_MODE:
545                 udev->info.irq_flags = IRQF_SHARED;
546                 udev->info.irq = dev->irq;
547                 break;
548         default:
549                 break;
550         }
551
552         pci_set_drvdata(dev, udev);
553         igbuio_pci_irqcontrol(&udev->info, 0);
554
555         if (sysfs_create_group(&dev->dev.kobj, &dev_attr_grp))
556                 goto fail_release_iomem;
557
558         /* register uio driver */
559         if (uio_register_device(&dev->dev, &udev->info))
560                 goto fail_release_iomem;
561
562         printk(KERN_INFO "uio device registered with irq %lx\n", udev->info.irq);
563
564         return 0;
565
566 fail_release_iomem:
567         sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp);
568         igbuio_pci_release_iomem(&udev->info);
569         if (udev->mode == IGBUIO_MSIX_INTR_MODE)
570                 pci_disable_msix(udev->pdev);
571         pci_release_regions(dev);
572 fail_disable:
573         pci_disable_device(dev);
574 fail_free:
575         kfree(udev);
576
577         return -ENODEV;
578 }
579
580 static void
581 igbuio_pci_remove(struct pci_dev *dev)
582 {
583         struct uio_info *info = pci_get_drvdata(dev);
584
585         if (info->priv == NULL) {
586                 printk(KERN_DEBUG "Not igbuio device\n");
587                 return;
588         }
589
590         sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp);
591         uio_unregister_device(info);
592         igbuio_pci_release_iomem(info);
593         if (((struct rte_uio_pci_dev *)info->priv)->mode ==
594                                         IGBUIO_MSIX_INTR_MODE)
595                 pci_disable_msix(dev);
596         pci_release_regions(dev);
597         pci_disable_device(dev);
598         pci_set_drvdata(dev, NULL);
599         kfree(info);
600 }
601
602 static int
603 igbuio_config_intr_mode(char *intr_str)
604 {
605         if (!intr_str) {
606                 printk(KERN_INFO "Use MSIX interrupt by default\n");
607                 return 0;
608         }
609
610         if (!strcmp(intr_str, "msix")) {
611                 igbuio_intr_mode_preferred = IGBUIO_MSIX_INTR_MODE;
612                 printk(KERN_INFO "Use MSIX interrupt\n");
613         } else if (!strcmp(intr_str, "legacy")) {
614                 igbuio_intr_mode_preferred = IGBUIO_LEGACY_INTR_MODE;
615                 printk(KERN_INFO "Use legacy interrupt\n");
616         } else {
617                 printk(KERN_INFO "Error: bad parameter - %s\n", intr_str);
618                 return -EINVAL;
619         }
620
621         return 0;
622 }
623
624 static struct pci_driver igbuio_pci_driver = {
625         .name = "igb_uio",
626         .id_table = igbuio_pci_ids,
627         .probe = igbuio_pci_probe,
628         .remove = igbuio_pci_remove,
629 };
630
631 static int __init
632 igbuio_pci_init_module(void)
633 {
634         int ret;
635
636         ret = igbuio_config_intr_mode(intr_mode);
637         if (ret < 0)
638                 return ret;
639
640         return pci_register_driver(&igbuio_pci_driver);
641 }
642
643 static void __exit
644 igbuio_pci_exit_module(void)
645 {
646         pci_unregister_driver(&igbuio_pci_driver);
647 }
648
649 module_init(igbuio_pci_init_module);
650 module_exit(igbuio_pci_exit_module);
651
652 module_param(intr_mode, charp, S_IRUGO | S_IWUSR);
653 MODULE_PARM_DESC(intr_mode,
654 "igb_uio interrupt mode (default=msix):\n"
655 "    msix       Use MSIX interrupt\n"
656 "    legacy     Use Legacy interrupt\n"
657 "\n");
658
659 MODULE_DESCRIPTION("UIO driver for Intel IGB PCI cards");
660 MODULE_LICENSE("GPL");
661 MODULE_AUTHOR("Intel Corporation");