Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.17-rc5 653 lines 18 kB view raw
1/* 2 * Intel MIC Platform Software Stack (MPSS) 3 * 4 * Copyright(c) 2013 Intel Corporation. 5 * 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. 9 * 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. 14 * 15 * The full GNU General Public License is included in this distribution in 16 * the file called "COPYING". 17 * 18 * Intel MIC Host driver. 19 * 20 */ 21#include <linux/pci.h> 22#include <linux/interrupt.h> 23 24#include "../common/mic_dev.h" 25#include "mic_device.h" 26 27static irqreturn_t mic_thread_fn(int irq, void *dev) 28{ 29 struct mic_device *mdev = dev; 30 struct mic_intr_info *intr_info = mdev->intr_info; 31 struct mic_irq_info *irq_info = &mdev->irq_info; 32 struct mic_intr_cb *intr_cb; 33 struct pci_dev *pdev = container_of(mdev->sdev->parent, 34 struct pci_dev, dev); 35 int i; 36 37 spin_lock(&irq_info->mic_thread_lock); 38 for (i = intr_info->intr_start_idx[MIC_INTR_DB]; 39 i < intr_info->intr_len[MIC_INTR_DB]; i++) 40 if (test_and_clear_bit(i, &irq_info->mask)) { 41 list_for_each_entry(intr_cb, &irq_info->cb_list[i], 42 list) 43 if (intr_cb->thread_fn) 44 intr_cb->thread_fn(pdev->irq, 45 intr_cb->data); 46 } 47 spin_unlock(&irq_info->mic_thread_lock); 48 return IRQ_HANDLED; 49} 50/** 51 * mic_interrupt - Generic interrupt handler for 52 * MSI and INTx based interrupts. 53 */ 54static irqreturn_t mic_interrupt(int irq, void *dev) 55{ 56 struct mic_device *mdev = dev; 57 struct mic_intr_info *intr_info = mdev->intr_info; 58 struct mic_irq_info *irq_info = &mdev->irq_info; 59 struct mic_intr_cb *intr_cb; 60 struct pci_dev *pdev = container_of(mdev->sdev->parent, 61 struct pci_dev, dev); 62 u32 mask; 63 int i; 64 65 mask = mdev->ops->ack_interrupt(mdev); 66 if (!mask) 67 return IRQ_NONE; 68 69 spin_lock(&irq_info->mic_intr_lock); 70 for (i = intr_info->intr_start_idx[MIC_INTR_DB]; 71 i < intr_info->intr_len[MIC_INTR_DB]; i++) 72 if (mask & BIT(i)) { 73 list_for_each_entry(intr_cb, &irq_info->cb_list[i], 74 list) 75 if (intr_cb->handler) 76 intr_cb->handler(pdev->irq, 77 intr_cb->data); 78 set_bit(i, &irq_info->mask); 79 } 80 spin_unlock(&irq_info->mic_intr_lock); 81 return IRQ_WAKE_THREAD; 82} 83 84/* Return the interrupt offset from the index. Index is 0 based. */ 85static u16 mic_map_src_to_offset(struct mic_device *mdev, 86 int intr_src, enum mic_intr_type type) 87{ 88 if (type >= MIC_NUM_INTR_TYPES) 89 return MIC_NUM_OFFSETS; 90 if (intr_src >= mdev->intr_info->intr_len[type]) 91 return MIC_NUM_OFFSETS; 92 93 return mdev->intr_info->intr_start_idx[type] + intr_src; 94} 95 96/* Return next available msix_entry. */ 97static struct msix_entry *mic_get_available_vector(struct mic_device *mdev) 98{ 99 int i; 100 struct mic_irq_info *info = &mdev->irq_info; 101 102 for (i = 0; i < info->num_vectors; i++) 103 if (!info->mic_msi_map[i]) 104 return &info->msix_entries[i]; 105 return NULL; 106} 107 108/** 109 * mic_register_intr_callback - Register a callback handler for the 110 * given source id. 111 * 112 * @mdev: pointer to the mic_device instance 113 * @idx: The source id to be registered. 114 * @handler: The function to be called when the source id receives 115 * the interrupt. 116 * @thread_fn: thread fn. corresponding to the handler 117 * @data: Private data of the requester. 118 * Return the callback structure that was registered or an 119 * appropriate error on failure. 120 */ 121static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev, 122 u8 idx, irq_handler_t handler, irq_handler_t thread_fn, 123 void *data) 124{ 125 struct mic_intr_cb *intr_cb; 126 unsigned long flags; 127 int rc; 128 intr_cb = kmalloc(sizeof(*intr_cb), GFP_KERNEL); 129 130 if (!intr_cb) 131 return ERR_PTR(-ENOMEM); 132 133 intr_cb->handler = handler; 134 intr_cb->thread_fn = thread_fn; 135 intr_cb->data = data; 136 intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida, 137 0, 0, GFP_KERNEL); 138 if (intr_cb->cb_id < 0) { 139 rc = intr_cb->cb_id; 140 goto ida_fail; 141 } 142 143 spin_lock(&mdev->irq_info.mic_thread_lock); 144 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags); 145 list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]); 146 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags); 147 spin_unlock(&mdev->irq_info.mic_thread_lock); 148 149 return intr_cb; 150ida_fail: 151 kfree(intr_cb); 152 return ERR_PTR(rc); 153} 154 155/** 156 * mic_unregister_intr_callback - Unregister the callback handler 157 * identified by its callback id. 158 * 159 * @mdev: pointer to the mic_device instance 160 * @idx: The callback structure id to be unregistered. 161 * Return the source id that was unregistered or MIC_NUM_OFFSETS if no 162 * such callback handler was found. 163 */ 164static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx) 165{ 166 struct list_head *pos, *tmp; 167 struct mic_intr_cb *intr_cb; 168 unsigned long flags; 169 int i; 170 171 spin_lock(&mdev->irq_info.mic_thread_lock); 172 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags); 173 for (i = 0; i < MIC_NUM_OFFSETS; i++) { 174 list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) { 175 intr_cb = list_entry(pos, struct mic_intr_cb, list); 176 if (intr_cb->cb_id == idx) { 177 list_del(pos); 178 ida_simple_remove(&mdev->irq_info.cb_ida, 179 intr_cb->cb_id); 180 kfree(intr_cb); 181 spin_unlock_irqrestore( 182 &mdev->irq_info.mic_intr_lock, flags); 183 spin_unlock(&mdev->irq_info.mic_thread_lock); 184 return i; 185 } 186 } 187 } 188 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags); 189 spin_unlock(&mdev->irq_info.mic_thread_lock); 190 return MIC_NUM_OFFSETS; 191} 192 193/** 194 * mic_setup_msix - Initializes MSIx interrupts. 195 * 196 * @mdev: pointer to mic_device instance 197 * 198 * 199 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 200 */ 201static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev) 202{ 203 int rc, i; 204 int entry_size = sizeof(*mdev->irq_info.msix_entries); 205 206 mdev->irq_info.msix_entries = kmalloc_array(MIC_MIN_MSIX, 207 entry_size, GFP_KERNEL); 208 if (!mdev->irq_info.msix_entries) { 209 rc = -ENOMEM; 210 goto err_nomem1; 211 } 212 213 for (i = 0; i < MIC_MIN_MSIX; i++) 214 mdev->irq_info.msix_entries[i].entry = i; 215 216 rc = pci_enable_msix_exact(pdev, mdev->irq_info.msix_entries, 217 MIC_MIN_MSIX); 218 if (rc) { 219 dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc); 220 goto err_enable_msix; 221 } 222 223 mdev->irq_info.num_vectors = MIC_MIN_MSIX; 224 mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) * 225 mdev->irq_info.num_vectors), GFP_KERNEL); 226 227 if (!mdev->irq_info.mic_msi_map) { 228 rc = -ENOMEM; 229 goto err_nomem2; 230 } 231 232 dev_dbg(mdev->sdev->parent, 233 "%d MSIx irqs setup\n", mdev->irq_info.num_vectors); 234 return 0; 235err_nomem2: 236 pci_disable_msix(pdev); 237err_enable_msix: 238 kfree(mdev->irq_info.msix_entries); 239err_nomem1: 240 mdev->irq_info.num_vectors = 0; 241 return rc; 242} 243 244/** 245 * mic_setup_callbacks - Initialize data structures needed 246 * to handle callbacks. 247 * 248 * @mdev: pointer to mic_device instance 249 */ 250static int mic_setup_callbacks(struct mic_device *mdev) 251{ 252 int i; 253 254 mdev->irq_info.cb_list = kmalloc_array(MIC_NUM_OFFSETS, 255 sizeof(*mdev->irq_info.cb_list), 256 GFP_KERNEL); 257 if (!mdev->irq_info.cb_list) 258 return -ENOMEM; 259 260 for (i = 0; i < MIC_NUM_OFFSETS; i++) 261 INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]); 262 ida_init(&mdev->irq_info.cb_ida); 263 spin_lock_init(&mdev->irq_info.mic_intr_lock); 264 spin_lock_init(&mdev->irq_info.mic_thread_lock); 265 return 0; 266} 267 268/** 269 * mic_release_callbacks - Uninitialize data structures needed 270 * to handle callbacks. 271 * 272 * @mdev: pointer to mic_device instance 273 */ 274static void mic_release_callbacks(struct mic_device *mdev) 275{ 276 unsigned long flags; 277 struct list_head *pos, *tmp; 278 struct mic_intr_cb *intr_cb; 279 int i; 280 281 spin_lock(&mdev->irq_info.mic_thread_lock); 282 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags); 283 for (i = 0; i < MIC_NUM_OFFSETS; i++) { 284 285 if (list_empty(&mdev->irq_info.cb_list[i])) 286 break; 287 288 list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) { 289 intr_cb = list_entry(pos, struct mic_intr_cb, list); 290 list_del(pos); 291 ida_simple_remove(&mdev->irq_info.cb_ida, 292 intr_cb->cb_id); 293 kfree(intr_cb); 294 } 295 } 296 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags); 297 spin_unlock(&mdev->irq_info.mic_thread_lock); 298 ida_destroy(&mdev->irq_info.cb_ida); 299 kfree(mdev->irq_info.cb_list); 300} 301 302/** 303 * mic_setup_msi - Initializes MSI interrupts. 304 * 305 * @mdev: pointer to mic_device instance 306 * @pdev: PCI device structure 307 * 308 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 309 */ 310static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev) 311{ 312 int rc; 313 314 rc = pci_enable_msi(pdev); 315 if (rc) { 316 dev_dbg(&pdev->dev, "Error enabling MSI. rc = %d\n", rc); 317 return rc; 318 } 319 320 mdev->irq_info.num_vectors = 1; 321 mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) * 322 mdev->irq_info.num_vectors), GFP_KERNEL); 323 324 if (!mdev->irq_info.mic_msi_map) { 325 rc = -ENOMEM; 326 goto err_nomem1; 327 } 328 329 rc = mic_setup_callbacks(mdev); 330 if (rc) { 331 dev_err(&pdev->dev, "Error setting up callbacks\n"); 332 goto err_nomem2; 333 } 334 335 rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn, 336 0, "mic-msi", mdev); 337 if (rc) { 338 dev_err(&pdev->dev, "Error allocating MSI interrupt\n"); 339 goto err_irq_req_fail; 340 } 341 342 dev_dbg(&pdev->dev, "%d MSI irqs setup\n", mdev->irq_info.num_vectors); 343 return 0; 344err_irq_req_fail: 345 mic_release_callbacks(mdev); 346err_nomem2: 347 kfree(mdev->irq_info.mic_msi_map); 348err_nomem1: 349 pci_disable_msi(pdev); 350 mdev->irq_info.num_vectors = 0; 351 return rc; 352} 353 354/** 355 * mic_setup_intx - Initializes legacy interrupts. 356 * 357 * @mdev: pointer to mic_device instance 358 * @pdev: PCI device structure 359 * 360 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 361 */ 362static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev) 363{ 364 int rc; 365 366 pci_msi_off(pdev); 367 368 /* Enable intx */ 369 pci_intx(pdev, 1); 370 rc = mic_setup_callbacks(mdev); 371 if (rc) { 372 dev_err(&pdev->dev, "Error setting up callbacks\n"); 373 goto err_nomem; 374 } 375 376 rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn, 377 IRQF_SHARED, "mic-intx", mdev); 378 if (rc) 379 goto err; 380 381 dev_dbg(&pdev->dev, "intx irq setup\n"); 382 return 0; 383err: 384 mic_release_callbacks(mdev); 385err_nomem: 386 return rc; 387} 388 389/** 390 * mic_next_db - Retrieve the next doorbell interrupt source id. 391 * The id is picked sequentially from the available pool of 392 * doorlbell ids. 393 * 394 * @mdev: pointer to the mic_device instance. 395 * 396 * Returns the next doorbell interrupt source. 397 */ 398int mic_next_db(struct mic_device *mdev) 399{ 400 int next_db; 401 402 next_db = mdev->irq_info.next_avail_src % 403 mdev->intr_info->intr_len[MIC_INTR_DB]; 404 mdev->irq_info.next_avail_src++; 405 return next_db; 406} 407 408#define COOKIE_ID_SHIFT 16 409#define GET_ENTRY(cookie) ((cookie) & 0xFFFF) 410#define GET_OFFSET(cookie) ((cookie) >> COOKIE_ID_SHIFT) 411#define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT) 412 413/** 414 * mic_request_threaded_irq - request an irq. mic_mutex needs 415 * to be held before calling this function. 416 * 417 * @mdev: pointer to mic_device instance 418 * @handler: The callback function that handles the interrupt. 419 * The function needs to call ack_interrupts 420 * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts. 421 * @thread_fn: thread fn required by request_threaded_irq. 422 * @name: The ASCII name of the callee requesting the irq. 423 * @data: private data that is returned back when calling the 424 * function handler. 425 * @intr_src: The source id of the requester. Its the doorbell id 426 * for Doorbell interrupts and DMA channel id for DMA interrupts. 427 * @type: The type of interrupt. Values defined in mic_intr_type 428 * 429 * returns: The cookie that is transparent to the caller. Passed 430 * back when calling mic_free_irq. An appropriate error code 431 * is returned on failure. Caller needs to use IS_ERR(return_val) 432 * to check for failure and PTR_ERR(return_val) to obtained the 433 * error code. 434 * 435 */ 436struct mic_irq * 437mic_request_threaded_irq(struct mic_device *mdev, 438 irq_handler_t handler, irq_handler_t thread_fn, 439 const char *name, void *data, int intr_src, 440 enum mic_intr_type type) 441{ 442 u16 offset; 443 int rc = 0; 444 struct msix_entry *msix = NULL; 445 unsigned long cookie = 0; 446 u16 entry; 447 struct mic_intr_cb *intr_cb; 448 struct pci_dev *pdev = container_of(mdev->sdev->parent, 449 struct pci_dev, dev); 450 451 offset = mic_map_src_to_offset(mdev, intr_src, type); 452 if (offset >= MIC_NUM_OFFSETS) { 453 dev_err(mdev->sdev->parent, 454 "Error mapping index %d to a valid source id.\n", 455 intr_src); 456 rc = -EINVAL; 457 goto err; 458 } 459 460 if (mdev->irq_info.num_vectors > 1) { 461 msix = mic_get_available_vector(mdev); 462 if (!msix) { 463 dev_err(mdev->sdev->parent, 464 "No MSIx vectors available for use.\n"); 465 rc = -ENOSPC; 466 goto err; 467 } 468 469 rc = request_threaded_irq(msix->vector, handler, thread_fn, 470 0, name, data); 471 if (rc) { 472 dev_dbg(mdev->sdev->parent, 473 "request irq failed rc = %d\n", rc); 474 goto err; 475 } 476 entry = msix->entry; 477 mdev->irq_info.mic_msi_map[entry] |= BIT(offset); 478 mdev->intr_ops->program_msi_to_src_map(mdev, 479 entry, offset, true); 480 cookie = MK_COOKIE(entry, offset); 481 dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n", 482 msix->vector, intr_src); 483 } else { 484 intr_cb = mic_register_intr_callback(mdev, offset, handler, 485 thread_fn, data); 486 if (IS_ERR(intr_cb)) { 487 dev_err(mdev->sdev->parent, 488 "No available callback entries for use\n"); 489 rc = PTR_ERR(intr_cb); 490 goto err; 491 } 492 493 entry = 0; 494 if (pci_dev_msi_enabled(pdev)) { 495 mdev->irq_info.mic_msi_map[entry] |= (1 << offset); 496 mdev->intr_ops->program_msi_to_src_map(mdev, 497 entry, offset, true); 498 } 499 cookie = MK_COOKIE(entry, intr_cb->cb_id); 500 dev_dbg(mdev->sdev->parent, "callback %d registered for src: %d\n", 501 intr_cb->cb_id, intr_src); 502 } 503 return (struct mic_irq *)cookie; 504err: 505 return ERR_PTR(rc); 506} 507 508/** 509 * mic_free_irq - free irq. mic_mutex 510 * needs to be held before calling this function. 511 * 512 * @mdev: pointer to mic_device instance 513 * @cookie: cookie obtained during a successful call to mic_request_threaded_irq 514 * @data: private data specified by the calling function during the 515 * mic_request_threaded_irq 516 * 517 * returns: none. 518 */ 519void mic_free_irq(struct mic_device *mdev, 520 struct mic_irq *cookie, void *data) 521{ 522 u32 offset; 523 u32 entry; 524 u8 src_id; 525 unsigned int irq; 526 struct pci_dev *pdev = container_of(mdev->sdev->parent, 527 struct pci_dev, dev); 528 529 entry = GET_ENTRY((unsigned long)cookie); 530 offset = GET_OFFSET((unsigned long)cookie); 531 if (mdev->irq_info.num_vectors > 1) { 532 if (entry >= mdev->irq_info.num_vectors) { 533 dev_warn(mdev->sdev->parent, 534 "entry %d should be < num_irq %d\n", 535 entry, mdev->irq_info.num_vectors); 536 return; 537 } 538 irq = mdev->irq_info.msix_entries[entry].vector; 539 free_irq(irq, data); 540 mdev->irq_info.mic_msi_map[entry] &= ~(BIT(offset)); 541 mdev->intr_ops->program_msi_to_src_map(mdev, 542 entry, offset, false); 543 544 dev_dbg(mdev->sdev->parent, "irq: %d freed\n", irq); 545 } else { 546 irq = pdev->irq; 547 src_id = mic_unregister_intr_callback(mdev, offset); 548 if (src_id >= MIC_NUM_OFFSETS) { 549 dev_warn(mdev->sdev->parent, "Error unregistering callback\n"); 550 return; 551 } 552 if (pci_dev_msi_enabled(pdev)) { 553 mdev->irq_info.mic_msi_map[entry] &= ~(BIT(src_id)); 554 mdev->intr_ops->program_msi_to_src_map(mdev, 555 entry, src_id, false); 556 } 557 dev_dbg(mdev->sdev->parent, "callback %d unregistered for src: %d\n", 558 offset, src_id); 559 } 560} 561 562/** 563 * mic_setup_interrupts - Initializes interrupts. 564 * 565 * @mdev: pointer to mic_device instance 566 * @pdev: PCI device structure 567 * 568 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 569 */ 570int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev) 571{ 572 int rc; 573 574 rc = mic_setup_msix(mdev, pdev); 575 if (!rc) 576 goto done; 577 578 rc = mic_setup_msi(mdev, pdev); 579 if (!rc) 580 goto done; 581 582 rc = mic_setup_intx(mdev, pdev); 583 if (rc) { 584 dev_err(mdev->sdev->parent, "no usable interrupts\n"); 585 return rc; 586 } 587done: 588 mdev->intr_ops->enable_interrupts(mdev); 589 return 0; 590} 591 592/** 593 * mic_free_interrupts - Frees interrupts setup by mic_setup_interrupts 594 * 595 * @mdev: pointer to mic_device instance 596 * @pdev: PCI device structure 597 * 598 * returns none. 599 */ 600void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev) 601{ 602 int i; 603 604 mdev->intr_ops->disable_interrupts(mdev); 605 if (mdev->irq_info.num_vectors > 1) { 606 for (i = 0; i < mdev->irq_info.num_vectors; i++) { 607 if (mdev->irq_info.mic_msi_map[i]) 608 dev_warn(&pdev->dev, "irq %d may still be in use.\n", 609 mdev->irq_info.msix_entries[i].vector); 610 } 611 kfree(mdev->irq_info.mic_msi_map); 612 kfree(mdev->irq_info.msix_entries); 613 pci_disable_msix(pdev); 614 } else { 615 if (pci_dev_msi_enabled(pdev)) { 616 free_irq(pdev->irq, mdev); 617 kfree(mdev->irq_info.mic_msi_map); 618 pci_disable_msi(pdev); 619 } else { 620 free_irq(pdev->irq, mdev); 621 } 622 mic_release_callbacks(mdev); 623 } 624} 625 626/** 627 * mic_intr_restore - Restore MIC interrupt registers. 628 * 629 * @mdev: pointer to mic_device instance. 630 * 631 * Restore the interrupt registers to values previously 632 * stored in the SW data structures. mic_mutex needs to 633 * be held before calling this function. 634 * 635 * returns None. 636 */ 637void mic_intr_restore(struct mic_device *mdev) 638{ 639 int entry, offset; 640 struct pci_dev *pdev = container_of(mdev->sdev->parent, 641 struct pci_dev, dev); 642 643 if (!pci_dev_msi_enabled(pdev)) 644 return; 645 646 for (entry = 0; entry < mdev->irq_info.num_vectors; entry++) { 647 for (offset = 0; offset < MIC_NUM_OFFSETS; offset++) { 648 if (mdev->irq_info.mic_msi_map[entry] & BIT(offset)) 649 mdev->intr_ops->program_msi_to_src_map(mdev, 650 entry, offset, true); 651 } 652 } 653}