0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/device.h>
0010 #include <linux/idr.h>
0011 #include <linux/irq.h>
0012 #include <linux/irqdomain.h>
0013 #include <linux/msi.h>
0014 #include <linux/slab.h>
0015
0016 #define DEV_ID_SHIFT 21
0017 #define MAX_DEV_MSIS (1 << (32 - DEV_ID_SHIFT))
0018
0019
0020
0021
0022
0023 struct platform_msi_priv_data {
0024 struct device *dev;
0025 void *host_data;
0026 msi_alloc_info_t arg;
0027 irq_write_msi_msg_t write_msg;
0028 int devid;
0029 };
0030
0031
0032 static DEFINE_IDA(platform_msi_devid_ida);
0033
0034 #ifdef GENERIC_MSI_DOMAIN_OPS
0035
0036
0037
0038
0039 static irq_hw_number_t platform_msi_calc_hwirq(struct msi_desc *desc)
0040 {
0041 u32 devid = desc->dev->msi.data->platform_data->devid;
0042
0043 return (devid << (32 - DEV_ID_SHIFT)) | desc->msi_index;
0044 }
0045
0046 static void platform_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
0047 {
0048 arg->desc = desc;
0049 arg->hwirq = platform_msi_calc_hwirq(desc);
0050 }
0051
0052 static int platform_msi_init(struct irq_domain *domain,
0053 struct msi_domain_info *info,
0054 unsigned int virq, irq_hw_number_t hwirq,
0055 msi_alloc_info_t *arg)
0056 {
0057 return irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
0058 info->chip, info->chip_data);
0059 }
0060
0061 static void platform_msi_set_proxy_dev(msi_alloc_info_t *arg)
0062 {
0063 arg->flags |= MSI_ALLOC_FLAGS_PROXY_DEVICE;
0064 }
0065 #else
0066 #define platform_msi_set_desc NULL
0067 #define platform_msi_init NULL
0068 #define platform_msi_set_proxy_dev(x) do {} while(0)
0069 #endif
0070
0071 static void platform_msi_update_dom_ops(struct msi_domain_info *info)
0072 {
0073 struct msi_domain_ops *ops = info->ops;
0074
0075 BUG_ON(!ops);
0076
0077 if (ops->msi_init == NULL)
0078 ops->msi_init = platform_msi_init;
0079 if (ops->set_desc == NULL)
0080 ops->set_desc = platform_msi_set_desc;
0081 }
0082
0083 static void platform_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
0084 {
0085 struct msi_desc *desc = irq_data_get_msi_desc(data);
0086
0087 desc->dev->msi.data->platform_data->write_msg(desc, msg);
0088 }
0089
0090 static void platform_msi_update_chip_ops(struct msi_domain_info *info)
0091 {
0092 struct irq_chip *chip = info->chip;
0093
0094 BUG_ON(!chip);
0095 if (!chip->irq_mask)
0096 chip->irq_mask = irq_chip_mask_parent;
0097 if (!chip->irq_unmask)
0098 chip->irq_unmask = irq_chip_unmask_parent;
0099 if (!chip->irq_eoi)
0100 chip->irq_eoi = irq_chip_eoi_parent;
0101 if (!chip->irq_set_affinity)
0102 chip->irq_set_affinity = msi_domain_set_affinity;
0103 if (!chip->irq_write_msi_msg)
0104 chip->irq_write_msi_msg = platform_msi_write_msg;
0105 if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE) &&
0106 !(chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI)))
0107 info->flags &= ~MSI_FLAG_LEVEL_CAPABLE;
0108 }
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
0123 struct msi_domain_info *info,
0124 struct irq_domain *parent)
0125 {
0126 struct irq_domain *domain;
0127
0128 if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
0129 platform_msi_update_dom_ops(info);
0130 if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
0131 platform_msi_update_chip_ops(info);
0132 info->flags |= MSI_FLAG_DEV_SYSFS | MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS |
0133 MSI_FLAG_FREE_MSI_DESCS;
0134
0135 domain = msi_create_irq_domain(fwnode, info, parent);
0136 if (domain)
0137 irq_domain_update_bus_token(domain, DOMAIN_BUS_PLATFORM_MSI);
0138
0139 return domain;
0140 }
0141
0142 static int platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
0143 irq_write_msi_msg_t write_msi_msg)
0144 {
0145 struct platform_msi_priv_data *datap;
0146 int err;
0147
0148
0149
0150
0151
0152
0153
0154 if (!dev->msi.domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
0155 return -EINVAL;
0156
0157 if (dev->msi.domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
0158 dev_err(dev, "Incompatible msi_domain, giving up\n");
0159 return -EINVAL;
0160 }
0161
0162 err = msi_setup_device_data(dev);
0163 if (err)
0164 return err;
0165
0166
0167 if (dev->msi.data->platform_data)
0168 return -EBUSY;
0169
0170 datap = kzalloc(sizeof(*datap), GFP_KERNEL);
0171 if (!datap)
0172 return -ENOMEM;
0173
0174 datap->devid = ida_simple_get(&platform_msi_devid_ida,
0175 0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
0176 if (datap->devid < 0) {
0177 err = datap->devid;
0178 kfree(datap);
0179 return err;
0180 }
0181
0182 datap->write_msg = write_msi_msg;
0183 datap->dev = dev;
0184 dev->msi.data->platform_data = datap;
0185 return 0;
0186 }
0187
0188 static void platform_msi_free_priv_data(struct device *dev)
0189 {
0190 struct platform_msi_priv_data *data = dev->msi.data->platform_data;
0191
0192 dev->msi.data->platform_data = NULL;
0193 ida_simple_remove(&platform_msi_devid_ida, data->devid);
0194 kfree(data);
0195 }
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
0207 irq_write_msi_msg_t write_msi_msg)
0208 {
0209 int err;
0210
0211 err = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
0212 if (err)
0213 return err;
0214
0215 err = msi_domain_alloc_irqs(dev->msi.domain, dev, nvec);
0216 if (err)
0217 platform_msi_free_priv_data(dev);
0218
0219 return err;
0220 }
0221 EXPORT_SYMBOL_GPL(platform_msi_domain_alloc_irqs);
0222
0223
0224
0225
0226
0227 void platform_msi_domain_free_irqs(struct device *dev)
0228 {
0229 msi_domain_free_irqs(dev->msi.domain, dev);
0230 platform_msi_free_priv_data(dev);
0231 }
0232 EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs);
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 void *platform_msi_get_host_data(struct irq_domain *domain)
0243 {
0244 struct platform_msi_priv_data *data = domain->host_data;
0245
0246 return data->host_data;
0247 }
0248
0249 static struct lock_class_key platform_device_msi_lock_class;
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 struct irq_domain *
0268 __platform_msi_create_device_domain(struct device *dev,
0269 unsigned int nvec,
0270 bool is_tree,
0271 irq_write_msi_msg_t write_msi_msg,
0272 const struct irq_domain_ops *ops,
0273 void *host_data)
0274 {
0275 struct platform_msi_priv_data *data;
0276 struct irq_domain *domain;
0277 int err;
0278
0279 err = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
0280 if (err)
0281 return NULL;
0282
0283
0284
0285
0286
0287
0288 lockdep_set_class(&dev->msi.data->mutex, &platform_device_msi_lock_class);
0289
0290 data = dev->msi.data->platform_data;
0291 data->host_data = host_data;
0292 domain = irq_domain_create_hierarchy(dev->msi.domain, 0,
0293 is_tree ? 0 : nvec,
0294 dev->fwnode, ops, data);
0295 if (!domain)
0296 goto free_priv;
0297
0298 platform_msi_set_proxy_dev(&data->arg);
0299 err = msi_domain_prepare_irqs(domain->parent, dev, nvec, &data->arg);
0300 if (err)
0301 goto free_domain;
0302
0303 return domain;
0304
0305 free_domain:
0306 irq_domain_remove(domain);
0307 free_priv:
0308 platform_msi_free_priv_data(dev);
0309 return NULL;
0310 }
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int virq,
0321 unsigned int nr_irqs)
0322 {
0323 struct platform_msi_priv_data *data = domain->host_data;
0324
0325 msi_lock_descs(data->dev);
0326 irq_domain_free_irqs_common(domain, virq, nr_irqs);
0327 msi_free_msi_descs_range(data->dev, MSI_DESC_ALL, virq, virq + nr_irqs - 1);
0328 msi_unlock_descs(data->dev);
0329 }
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343 int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int virq,
0344 unsigned int nr_irqs)
0345 {
0346 struct platform_msi_priv_data *data = domain->host_data;
0347 struct device *dev = data->dev;
0348
0349 return msi_domain_populate_irqs(domain->parent, dev, virq, nr_irqs, &data->arg);
0350 }