blob: 0297931335e158f53ab8c556fdf7cb42190146c7 [file] [log] [blame]
Jan Glauber9a4da8a2012-11-29 13:05:05 +01001/*
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 unsigned int msihash_shift = 6;
22#define msi_hashfn(nr) hash_long(nr, msihash_shift)
23
24static DEFINE_SPINLOCK(msi_map_lock);
25
26struct msi_desc *__irq_get_msi_desc(unsigned int irq)
27{
Jan Glauber9a4da8a2012-11-29 13:05:05 +010028 struct msi_map *map;
29
Sasha Levinb67bfe02013-02-27 17:06:00 -080030 hlist_for_each_entry_rcu(map,
Jan Glauber9a4da8a2012-11-29 13:05:05 +010031 &msi_hash[msi_hashfn(irq)], msi_chain)
32 if (map->irq == irq)
33 return map->msi;
34 return NULL;
35}
36
37int 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
63int 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
100void 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 */
124int __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
137void __init zpci_msihash_exit(void)
138{
139 kfree(msi_hash);
140}