2 * Intel MIC Platform Software Stack (MPSS)
4 * Copyright(c) 2013 Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
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.
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
18 * Intel MIC Host driver.
21 #include <linux/pci.h>
22 #include <linux/interrupt.h>
24 #include "../common/mic_dev.h"
25 #include "mic_device.h"
28 * mic_invoke_callback - Invoke callback functions registered for
29 * the corresponding source id.
31 * @mdev: pointer to the mic_device instance
32 * @idx: The interrupt source id.
36 static inline void mic_invoke_callback(struct mic_device *mdev, int idx)
38 struct mic_intr_cb *intr_cb;
39 struct pci_dev *pdev = container_of(mdev->sdev->parent,
42 spin_lock(&mdev->irq_info.mic_intr_lock);
43 list_for_each_entry(intr_cb, &mdev->irq_info.cb_list[idx], list)
45 intr_cb->func(pdev->irq, intr_cb->data);
46 spin_unlock(&mdev->irq_info.mic_intr_lock);
50 * mic_interrupt - Generic interrupt handler for
51 * MSI and INTx based interrupts.
53 static irqreturn_t mic_interrupt(int irq, void *dev)
55 struct mic_device *mdev = dev;
56 struct mic_intr_info *info = mdev->intr_info;
60 mask = mdev->ops->ack_interrupt(mdev);
64 for (i = info->intr_start_idx[MIC_INTR_DB];
65 i < info->intr_len[MIC_INTR_DB]; i++)
67 mic_invoke_callback(mdev, i);
72 /* Return the interrupt offset from the index. Index is 0 based. */
73 static u16 mic_map_src_to_offset(struct mic_device *mdev,
74 int intr_src, enum mic_intr_type type)
76 if (type >= MIC_NUM_INTR_TYPES)
77 return MIC_NUM_OFFSETS;
78 if (intr_src >= mdev->intr_info->intr_len[type])
79 return MIC_NUM_OFFSETS;
81 return mdev->intr_info->intr_start_idx[type] + intr_src;
84 /* Return next available msix_entry. */
85 static struct msix_entry *mic_get_available_vector(struct mic_device *mdev)
88 struct mic_irq_info *info = &mdev->irq_info;
90 for (i = 0; i < info->num_vectors; i++)
91 if (!info->mic_msi_map[i])
92 return &info->msix_entries[i];
97 * mic_register_intr_callback - Register a callback handler for the
100 * @mdev: pointer to the mic_device instance
101 * @idx: The source id to be registered.
102 * @func: The function to be called when the source id receives
104 * @data: Private data of the requester.
105 * Return the callback structure that was registered or an
106 * appropriate error on failure.
108 static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
109 u8 idx, irqreturn_t (*func) (int irq, void *dev),
112 struct mic_intr_cb *intr_cb;
115 intr_cb = kmalloc(sizeof(*intr_cb), GFP_KERNEL);
118 return ERR_PTR(-ENOMEM);
120 intr_cb->func = func;
121 intr_cb->data = data;
122 intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
124 if (intr_cb->cb_id < 0) {
129 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
130 list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
131 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
140 * mic_unregister_intr_callback - Unregister the callback handler
141 * identified by its callback id.
143 * @mdev: pointer to the mic_device instance
144 * @idx: The callback structure id to be unregistered.
145 * Return the source id that was unregistered or MIC_NUM_OFFSETS if no
146 * such callback handler was found.
148 static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
150 struct list_head *pos, *tmp;
151 struct mic_intr_cb *intr_cb;
155 for (i = 0; i < MIC_NUM_OFFSETS; i++) {
156 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
157 list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
158 intr_cb = list_entry(pos, struct mic_intr_cb, list);
159 if (intr_cb->cb_id == idx) {
161 ida_simple_remove(&mdev->irq_info.cb_ida,
164 spin_unlock_irqrestore(
165 &mdev->irq_info.mic_intr_lock, flags);
169 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
171 return MIC_NUM_OFFSETS;
175 * mic_setup_msix - Initializes MSIx interrupts.
177 * @mdev: pointer to mic_device instance
180 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
182 static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
185 int entry_size = sizeof(*mdev->irq_info.msix_entries);
187 mdev->irq_info.msix_entries = kmalloc_array(MIC_MIN_MSIX,
188 entry_size, GFP_KERNEL);
189 if (!mdev->irq_info.msix_entries) {
194 for (i = 0; i < MIC_MIN_MSIX; i++)
195 mdev->irq_info.msix_entries[i].entry = i;
197 rc = pci_enable_msix(pdev, mdev->irq_info.msix_entries,
200 dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
201 goto err_enable_msix;
204 mdev->irq_info.num_vectors = MIC_MIN_MSIX;
205 mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
206 mdev->irq_info.num_vectors), GFP_KERNEL);
208 if (!mdev->irq_info.mic_msi_map) {
213 dev_dbg(mdev->sdev->parent,
214 "%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
217 pci_disable_msix(pdev);
219 kfree(mdev->irq_info.msix_entries);
221 mdev->irq_info.num_vectors = 0;
226 * mic_setup_callbacks - Initialize data structures needed
227 * to handle callbacks.
229 * @mdev: pointer to mic_device instance
231 static int mic_setup_callbacks(struct mic_device *mdev)
235 mdev->irq_info.cb_list = kmalloc_array(MIC_NUM_OFFSETS,
236 sizeof(*mdev->irq_info.cb_list),
238 if (!mdev->irq_info.cb_list)
241 for (i = 0; i < MIC_NUM_OFFSETS; i++)
242 INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
243 ida_init(&mdev->irq_info.cb_ida);
244 spin_lock_init(&mdev->irq_info.mic_intr_lock);
249 * mic_release_callbacks - Uninitialize data structures needed
250 * to handle callbacks.
252 * @mdev: pointer to mic_device instance
254 static void mic_release_callbacks(struct mic_device *mdev)
257 struct list_head *pos, *tmp;
258 struct mic_intr_cb *intr_cb;
261 for (i = 0; i < MIC_NUM_OFFSETS; i++) {
262 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
264 if (list_empty(&mdev->irq_info.cb_list[i])) {
265 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock,
270 list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
271 intr_cb = list_entry(pos, struct mic_intr_cb, list);
273 ida_simple_remove(&mdev->irq_info.cb_ida,
277 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
279 ida_destroy(&mdev->irq_info.cb_ida);
280 kfree(mdev->irq_info.cb_list);
284 * mic_setup_msi - Initializes MSI interrupts.
286 * @mdev: pointer to mic_device instance
287 * @pdev: PCI device structure
289 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
291 static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev)
295 rc = pci_enable_msi(pdev);
297 dev_dbg(&pdev->dev, "Error enabling MSI. rc = %d\n", rc);
301 mdev->irq_info.num_vectors = 1;
302 mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
303 mdev->irq_info.num_vectors), GFP_KERNEL);
305 if (!mdev->irq_info.mic_msi_map) {
310 rc = mic_setup_callbacks(mdev);
312 dev_err(&pdev->dev, "Error setting up callbacks\n");
316 rc = request_irq(pdev->irq, mic_interrupt, 0 , "mic-msi", mdev);
318 dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
319 goto err_irq_req_fail;
322 dev_dbg(&pdev->dev, "%d MSI irqs setup\n", mdev->irq_info.num_vectors);
325 mic_release_callbacks(mdev);
327 kfree(mdev->irq_info.mic_msi_map);
329 pci_disable_msi(pdev);
330 mdev->irq_info.num_vectors = 0;
335 * mic_setup_intx - Initializes legacy interrupts.
337 * @mdev: pointer to mic_device instance
338 * @pdev: PCI device structure
340 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
342 static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
350 rc = mic_setup_callbacks(mdev);
352 dev_err(&pdev->dev, "Error setting up callbacks\n");
356 rc = request_irq(pdev->irq, mic_interrupt,
357 IRQF_SHARED, "mic-intx", mdev);
361 dev_dbg(&pdev->dev, "intx irq setup\n");
364 mic_release_callbacks(mdev);
370 * mic_next_db - Retrieve the next doorbell interrupt source id.
371 * The id is picked sequentially from the available pool of
374 * @mdev: pointer to the mic_device instance.
376 * Returns the next doorbell interrupt source.
378 int mic_next_db(struct mic_device *mdev)
382 next_db = mdev->irq_info.next_avail_src %
383 mdev->intr_info->intr_len[MIC_INTR_DB];
384 mdev->irq_info.next_avail_src++;
388 #define COOKIE_ID_SHIFT 16
389 #define GET_ENTRY(cookie) ((cookie) & 0xFFFF)
390 #define GET_OFFSET(cookie) ((cookie) >> COOKIE_ID_SHIFT)
391 #define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
394 * mic_request_irq - request an irq. mic_mutex needs
395 * to be held before calling this function.
397 * @mdev: pointer to mic_device instance
398 * @func: The callback function that handles the interrupt.
399 * The function needs to call ack_interrupts
400 * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
401 * @name: The ASCII name of the callee requesting the irq.
402 * @data: private data that is returned back when calling the
404 * @intr_src: The source id of the requester. Its the doorbell id
405 * for Doorbell interrupts and DMA channel id for DMA interrupts.
406 * @type: The type of interrupt. Values defined in mic_intr_type
408 * returns: The cookie that is transparent to the caller. Passed
409 * back when calling mic_free_irq. An appropriate error code
410 * is returned on failure. Caller needs to use IS_ERR(return_val)
411 * to check for failure and PTR_ERR(return_val) to obtained the
415 struct mic_irq *mic_request_irq(struct mic_device *mdev,
416 irqreturn_t (*func)(int irq, void *dev),
417 const char *name, void *data, int intr_src,
418 enum mic_intr_type type)
422 struct msix_entry *msix = NULL;
423 unsigned long cookie = 0;
425 struct mic_intr_cb *intr_cb;
426 struct pci_dev *pdev = container_of(mdev->sdev->parent,
427 struct pci_dev, dev);
429 offset = mic_map_src_to_offset(mdev, intr_src, type);
430 if (offset >= MIC_NUM_OFFSETS) {
431 dev_err(mdev->sdev->parent,
432 "Error mapping index %d to a valid source id.\n",
438 if (mdev->irq_info.num_vectors > 1) {
439 msix = mic_get_available_vector(mdev);
441 dev_err(mdev->sdev->parent,
442 "No MSIx vectors available for use.\n");
447 rc = request_irq(msix->vector, func, 0, name, data);
449 dev_dbg(mdev->sdev->parent,
450 "request irq failed rc = %d\n", rc);
454 mdev->irq_info.mic_msi_map[entry] |= BIT(offset);
455 mdev->intr_ops->program_msi_to_src_map(mdev,
456 entry, offset, true);
457 cookie = MK_COOKIE(entry, offset);
458 dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n",
459 msix->vector, intr_src);
461 intr_cb = mic_register_intr_callback(mdev,
463 if (IS_ERR(intr_cb)) {
464 dev_err(mdev->sdev->parent,
465 "No available callback entries for use\n");
466 rc = PTR_ERR(intr_cb);
471 if (pci_dev_msi_enabled(pdev)) {
472 mdev->irq_info.mic_msi_map[entry] |= (1 << offset);
473 mdev->intr_ops->program_msi_to_src_map(mdev,
474 entry, offset, true);
476 cookie = MK_COOKIE(entry, intr_cb->cb_id);
477 dev_dbg(mdev->sdev->parent, "callback %d registered for src: %d\n",
478 intr_cb->cb_id, intr_src);
480 return (struct mic_irq *)cookie;
486 * mic_free_irq - free irq. mic_mutex
487 * needs to be held before calling this function.
489 * @mdev: pointer to mic_device instance
490 * @cookie: cookie obtained during a successful call to mic_request_irq
491 * @data: private data specified by the calling function during the
496 void mic_free_irq(struct mic_device *mdev,
497 struct mic_irq *cookie, void *data)
503 struct pci_dev *pdev = container_of(mdev->sdev->parent,
504 struct pci_dev, dev);
506 entry = GET_ENTRY((unsigned long)cookie);
507 offset = GET_OFFSET((unsigned long)cookie);
508 if (mdev->irq_info.num_vectors > 1) {
509 if (entry >= mdev->irq_info.num_vectors) {
510 dev_warn(mdev->sdev->parent,
511 "entry %d should be < num_irq %d\n",
512 entry, mdev->irq_info.num_vectors);
515 irq = mdev->irq_info.msix_entries[entry].vector;
517 mdev->irq_info.mic_msi_map[entry] &= ~(BIT(offset));
518 mdev->intr_ops->program_msi_to_src_map(mdev,
519 entry, offset, false);
521 dev_dbg(mdev->sdev->parent, "irq: %d freed\n", irq);
524 src_id = mic_unregister_intr_callback(mdev, offset);
525 if (src_id >= MIC_NUM_OFFSETS) {
526 dev_warn(mdev->sdev->parent, "Error unregistering callback\n");
529 if (pci_dev_msi_enabled(pdev)) {
530 mdev->irq_info.mic_msi_map[entry] &= ~(BIT(src_id));
531 mdev->intr_ops->program_msi_to_src_map(mdev,
532 entry, src_id, false);
534 dev_dbg(mdev->sdev->parent, "callback %d unregistered for src: %d\n",
540 * mic_setup_interrupts - Initializes interrupts.
542 * @mdev: pointer to mic_device instance
543 * @pdev: PCI device structure
545 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
547 int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
551 rc = mic_setup_msix(mdev, pdev);
555 rc = mic_setup_msi(mdev, pdev);
559 rc = mic_setup_intx(mdev, pdev);
561 dev_err(mdev->sdev->parent, "no usable interrupts\n");
565 mdev->intr_ops->enable_interrupts(mdev);
570 * mic_free_interrupts - Frees interrupts setup by mic_setup_interrupts
572 * @mdev: pointer to mic_device instance
573 * @pdev: PCI device structure
577 void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
581 mdev->intr_ops->disable_interrupts(mdev);
582 if (mdev->irq_info.num_vectors > 1) {
583 for (i = 0; i < mdev->irq_info.num_vectors; i++) {
584 if (mdev->irq_info.mic_msi_map[i])
585 dev_warn(&pdev->dev, "irq %d may still be in use.\n",
586 mdev->irq_info.msix_entries[i].vector);
588 kfree(mdev->irq_info.mic_msi_map);
589 kfree(mdev->irq_info.msix_entries);
590 pci_disable_msix(pdev);
592 if (pci_dev_msi_enabled(pdev)) {
593 free_irq(pdev->irq, mdev);
594 kfree(mdev->irq_info.mic_msi_map);
595 pci_disable_msi(pdev);
597 free_irq(pdev->irq, mdev);
599 mic_release_callbacks(mdev);
604 * mic_intr_restore - Restore MIC interrupt registers.
606 * @mdev: pointer to mic_device instance.
608 * Restore the interrupt registers to values previously
609 * stored in the SW data structures. mic_mutex needs to
610 * be held before calling this function.
614 void mic_intr_restore(struct mic_device *mdev)
617 struct pci_dev *pdev = container_of(mdev->sdev->parent,
618 struct pci_dev, dev);
620 if (!pci_dev_msi_enabled(pdev))
623 for (entry = 0; entry < mdev->irq_info.num_vectors; entry++) {
624 for (offset = 0; offset < MIC_NUM_OFFSETS; offset++) {
625 if (mdev->irq_info.mic_msi_map[entry] & BIT(offset))
626 mdev->intr_ops->program_msi_to_src_map(mdev,
627 entry, offset, true);