aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/pci/pci_msi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/pci/pci_msi.c')
-rw-r--r--arch/s390/pci/pci_msi.c134
1 files changed, 0 insertions, 134 deletions
diff --git a/arch/s390/pci/pci_msi.c b/arch/s390/pci/pci_msi.c
deleted file mode 100644
index d4b480a18b0f..000000000000
--- a/arch/s390/pci/pci_msi.c
+++ /dev/null
@@ -1,134 +0,0 @@
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 */
20static struct hlist_head *msi_hash;
21static const unsigned int msi_hash_bits = 8;
22#define MSI_HASH_BUCKETS (1U << msi_hash_bits)
23#define msi_hashfn(nr) hash_long(nr, msi_hash_bits)
24
25static DEFINE_SPINLOCK(msi_map_lock);
26
27struct msi_desc *__irq_get_msi_desc(unsigned int irq)
28{
29 struct msi_map *map;
30
31 hlist_for_each_entry_rcu(map,
32 &msi_hash[msi_hashfn(irq)], msi_chain)
33 if (map->irq == irq)
34 return map->msi;
35 return NULL;
36}
37
38int zpci_msi_set_mask_bits(struct msi_desc *msi, u32 mask, u32 flag)
39{
40 if (msi->msi_attrib.is_msix) {
41 int offset = msi->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
42 PCI_MSIX_ENTRY_VECTOR_CTRL;
43 msi->masked = readl(msi->mask_base + offset);
44 writel(flag, msi->mask_base + offset);
45 } else {
46 if (msi->msi_attrib.maskbit) {
47 int pos;
48 u32 mask_bits;
49
50 pos = (long) msi->mask_base;
51 pci_read_config_dword(msi->dev, pos, &mask_bits);
52 mask_bits &= ~(mask);
53 mask_bits |= flag & mask;
54 pci_write_config_dword(msi->dev, pos, mask_bits);
55 } else {
56 return 0;
57 }
58 }
59
60 msi->msi_attrib.maskbit = !!flag;
61 return 1;
62}
63
64int zpci_setup_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi,
65 unsigned int nr, int offset)
66{
67 struct msi_map *map;
68 struct msi_msg msg;
69 int rc;
70
71 map = zdev->msi_map + (nr & ZPCI_MSI_VEC_MASK);
72 map->irq = nr;
73 map->msi = msi;
74 INIT_HLIST_NODE(&map->msi_chain);
75
76 pr_debug("%s hashing irq: %u to bucket nr: %llu\n",
77 __func__, nr, msi_hashfn(nr));
78 hlist_add_head_rcu(&map->msi_chain, &msi_hash[msi_hashfn(nr)]);
79
80 spin_lock(&msi_map_lock);
81 rc = irq_set_msi_desc(nr, msi);
82 if (rc) {
83 spin_unlock(&msi_map_lock);
84 hlist_del_rcu(&map->msi_chain);
85 return rc;
86 }
87 spin_unlock(&msi_map_lock);
88
89 msg.data = nr - offset;
90 msg.address_lo = zdev->msi_addr & 0xffffffff;
91 msg.address_hi = zdev->msi_addr >> 32;
92 write_msi_msg(nr, &msg);
93 return 0;
94}
95
96void zpci_teardown_msi_irq(struct zpci_dev *zdev, struct msi_desc *msi)
97{
98 int nr = msi->irq & ZPCI_MSI_VEC_MASK;
99 struct msi_map *map;
100
101 zpci_msi_set_mask_bits(msi, 1, 1);
102 msi->msg.address_lo = 0;
103 msi->msg.address_hi = 0;
104 msi->msg.data = 0;
105 msi->irq = 0;
106
107 spin_lock(&msi_map_lock);
108 map = zdev->msi_map + nr;
109 hlist_del_rcu(&map->msi_chain);
110 spin_unlock(&msi_map_lock);
111}
112
113/*
114 * The msi hash table has 256 entries which is good for 4..20
115 * devices (a typical device allocates 10 + CPUs MSI's). Maybe make
116 * the hash table size adjustable later.
117 */
118int __init zpci_msihash_init(void)
119{
120 unsigned int i;
121
122 msi_hash = kmalloc(MSI_HASH_BUCKETS * sizeof(*msi_hash), GFP_KERNEL);
123 if (!msi_hash)
124 return -ENOMEM;
125
126 for (i = 0; i < MSI_HASH_BUCKETS; i++)
127 INIT_HLIST_HEAD(&msi_hash[i]);
128 return 0;
129}
130
131void __init zpci_msihash_exit(void)
132{
133 kfree(msi_hash);
134}