]> Pileus Git - ~andy/linux/blob - arch/s390/pci/pci_msi.c
hlist: drop the node parameter from iterators
[~andy/linux] / arch / s390 / pci / pci_msi.c
1 /*
2  * Copyright IBM Corp. 2012
3  *
4  * Author(s):
5  *   Jan Glauber <jang@linux.vnet.ibm.com>
6  */
7
8 #define COMPONENT "zPCI"
9 #define pr_fmt(fmt) COMPONENT ": " fmt
10
11 #include <linux/kernel.h>
12 #include <linux/err.h>
13 #include <linux/rculist.h>
14 #include <linux/hash.h>
15 #include <linux/pci.h>
16 #include <linux/msi.h>
17 #include <asm/hw_irq.h>
18
19 /* mapping of irq numbers to msi_desc */
20 static struct hlist_head *msi_hash;
21 static unsigned int msihash_shift = 6;
22 #define msi_hashfn(nr)  hash_long(nr, msihash_shift)
23
24 static DEFINE_SPINLOCK(msi_map_lock);
25
26 struct msi_desc *__irq_get_msi_desc(unsigned int irq)
27 {
28         struct msi_map *map;
29
30         hlist_for_each_entry_rcu(map,
31                         &msi_hash[msi_hashfn(irq)], msi_chain)
32                 if (map->irq == irq)
33                         return map->msi;
34         return NULL;
35 }
36
37 int zpci_msi_set_mask_bits(struct msi_desc *msi, u32 mask, u32 flag)
38 {
39         if (msi->msi_attrib.is_msix) {
40                 int offset = msi->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
41                         PCI_MSIX_ENTRY_VECTOR_CTRL;
42                 msi->masked = readl(msi->mask_base + offset);
43                 writel(flag, msi->mask_base + offset);
44         } else {
45                 if (msi->msi_attrib.maskbit) {
46                         int pos;
47                         u32 mask_bits;
48
49                         pos = (long) msi->mask_base;
50                         pci_read_config_dword(msi->dev, pos, &mask_bits);
51                         mask_bits &= ~(mask);
52                         mask_bits |= flag & mask;
53                         pci_write_config_dword(msi->dev, pos, mask_bits);
54                 } else {
55                         return 0;
56                 }
57         }
58
59         msi->msi_attrib.maskbit = !!flag;
60         return 1;
61 }
62
63 int zpci_setup_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi,
64                         unsigned int nr, int offset)
65 {
66         struct msi_map *map;
67         struct msi_msg msg;
68         int rc;
69
70         map = kmalloc(sizeof(*map), GFP_KERNEL);
71         if (map == NULL)
72                 return -ENOMEM;
73
74         map->irq = nr;
75         map->msi = msi;
76         zdev->msi_map[nr & ZPCI_MSI_MASK] = map;
77
78         pr_debug("%s hashing irq: %u  to bucket nr: %llu\n",
79                 __func__, nr, msi_hashfn(nr));
80         hlist_add_head_rcu(&map->msi_chain, &msi_hash[msi_hashfn(nr)]);
81
82         spin_lock(&msi_map_lock);
83         rc = irq_set_msi_desc(nr, msi);
84         if (rc) {
85                 spin_unlock(&msi_map_lock);
86                 hlist_del_rcu(&map->msi_chain);
87                 kfree(map);
88                 zdev->msi_map[nr & ZPCI_MSI_MASK] = NULL;
89                 return rc;
90         }
91         spin_unlock(&msi_map_lock);
92
93         msg.data = nr - offset;
94         msg.address_lo = zdev->msi_addr & 0xffffffff;
95         msg.address_hi = zdev->msi_addr >> 32;
96         write_msi_msg(nr, &msg);
97         return 0;
98 }
99
100 void zpci_teardown_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi)
101 {
102         int irq = msi->irq & ZPCI_MSI_MASK;
103         struct msi_map *map;
104
105         msi->msg.address_lo = 0;
106         msi->msg.address_hi = 0;
107         msi->msg.data = 0;
108         msi->irq = 0;
109         zpci_msi_set_mask_bits(msi, 1, 1);
110
111         spin_lock(&msi_map_lock);
112         map = zdev->msi_map[irq];
113         hlist_del_rcu(&map->msi_chain);
114         kfree(map);
115         zdev->msi_map[irq] = NULL;
116         spin_unlock(&msi_map_lock);
117 }
118
119 /*
120  * The msi hash table has 256 entries which is good for 4..20
121  * devices (a typical device allocates 10 + CPUs MSI's). Maybe make
122  * the hash table size adjustable later.
123  */
124 int __init zpci_msihash_init(void)
125 {
126         unsigned int i;
127
128         msi_hash = kmalloc(256 * sizeof(*msi_hash), GFP_KERNEL);
129         if (!msi_hash)
130                 return -ENOMEM;
131
132         for (i = 0; i < (1U << msihash_shift); i++)
133                 INIT_HLIST_HEAD(&msi_hash[i]);
134         return 0;
135 }
136
137 void __init zpci_msihash_exit(void)
138 {
139         kfree(msi_hash);
140 }