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 v4.2 804 lines 19 kB view raw
1/* 2* Filename: cregs.c 3* 4* 5* Authors: Joshua Morris <josh.h.morris@us.ibm.com> 6* Philip Kelleher <pjk1939@linux.vnet.ibm.com> 7* 8* (C) Copyright 2013 IBM Corporation 9* 10* This program is free software; you can redistribute it and/or 11* modify it under the terms of the GNU General Public License as 12* published by the Free Software Foundation; either version 2 of the 13* License, or (at your option) any later version. 14* 15* This program is distributed in the hope that it will be useful, but 16* WITHOUT ANY WARRANTY; without even the implied warranty of 17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18* General Public License for more details. 19* 20* You should have received a copy of the GNU General Public License 21* along with this program; if not, write to the Free Software Foundation, 22* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23*/ 24 25#include <linux/completion.h> 26#include <linux/slab.h> 27 28#include "rsxx_priv.h" 29 30#define CREG_TIMEOUT_MSEC 10000 31 32typedef void (*creg_cmd_cb)(struct rsxx_cardinfo *card, 33 struct creg_cmd *cmd, 34 int st); 35 36struct creg_cmd { 37 struct list_head list; 38 creg_cmd_cb cb; 39 void *cb_private; 40 unsigned int op; 41 unsigned int addr; 42 int cnt8; 43 void *buf; 44 unsigned int stream; 45 unsigned int status; 46}; 47 48static struct kmem_cache *creg_cmd_pool; 49 50 51/*------------ Private Functions --------------*/ 52 53#if defined(__LITTLE_ENDIAN) 54#define LITTLE_ENDIAN 1 55#elif defined(__BIG_ENDIAN) 56#define LITTLE_ENDIAN 0 57#else 58#error Unknown endianess!!! Aborting... 59#endif 60 61static int copy_to_creg_data(struct rsxx_cardinfo *card, 62 int cnt8, 63 void *buf, 64 unsigned int stream) 65{ 66 int i = 0; 67 u32 *data = buf; 68 69 if (unlikely(card->eeh_state)) 70 return -EIO; 71 72 for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { 73 /* 74 * Firmware implementation makes it necessary to byte swap on 75 * little endian processors. 76 */ 77 if (LITTLE_ENDIAN && stream) 78 iowrite32be(data[i], card->regmap + CREG_DATA(i)); 79 else 80 iowrite32(data[i], card->regmap + CREG_DATA(i)); 81 } 82 83 return 0; 84} 85 86 87static int copy_from_creg_data(struct rsxx_cardinfo *card, 88 int cnt8, 89 void *buf, 90 unsigned int stream) 91{ 92 int i = 0; 93 u32 *data = buf; 94 95 if (unlikely(card->eeh_state)) 96 return -EIO; 97 98 for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { 99 /* 100 * Firmware implementation makes it necessary to byte swap on 101 * little endian processors. 102 */ 103 if (LITTLE_ENDIAN && stream) 104 data[i] = ioread32be(card->regmap + CREG_DATA(i)); 105 else 106 data[i] = ioread32(card->regmap + CREG_DATA(i)); 107 } 108 109 return 0; 110} 111 112static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) 113{ 114 int st; 115 116 if (unlikely(card->eeh_state)) 117 return; 118 119 iowrite32(cmd->addr, card->regmap + CREG_ADD); 120 iowrite32(cmd->cnt8, card->regmap + CREG_CNT); 121 122 if (cmd->op == CREG_OP_WRITE) { 123 if (cmd->buf) { 124 st = copy_to_creg_data(card, cmd->cnt8, 125 cmd->buf, cmd->stream); 126 if (st) 127 return; 128 } 129 } 130 131 if (unlikely(card->eeh_state)) 132 return; 133 134 /* Setting the valid bit will kick off the command. */ 135 iowrite32(cmd->op, card->regmap + CREG_CMD); 136} 137 138static void creg_kick_queue(struct rsxx_cardinfo *card) 139{ 140 if (card->creg_ctrl.active || list_empty(&card->creg_ctrl.queue)) 141 return; 142 143 card->creg_ctrl.active = 1; 144 card->creg_ctrl.active_cmd = list_first_entry(&card->creg_ctrl.queue, 145 struct creg_cmd, list); 146 list_del(&card->creg_ctrl.active_cmd->list); 147 card->creg_ctrl.q_depth--; 148 149 /* 150 * We have to set the timer before we push the new command. Otherwise, 151 * we could create a race condition that would occur if the timer 152 * was not canceled, and expired after the new command was pushed, 153 * but before the command was issued to hardware. 154 */ 155 mod_timer(&card->creg_ctrl.cmd_timer, 156 jiffies + msecs_to_jiffies(CREG_TIMEOUT_MSEC)); 157 158 creg_issue_cmd(card, card->creg_ctrl.active_cmd); 159} 160 161static int creg_queue_cmd(struct rsxx_cardinfo *card, 162 unsigned int op, 163 unsigned int addr, 164 unsigned int cnt8, 165 void *buf, 166 int stream, 167 creg_cmd_cb callback, 168 void *cb_private) 169{ 170 struct creg_cmd *cmd; 171 172 /* Don't queue stuff up if we're halted. */ 173 if (unlikely(card->halt)) 174 return -EINVAL; 175 176 if (card->creg_ctrl.reset) 177 return -EAGAIN; 178 179 if (cnt8 > MAX_CREG_DATA8) 180 return -EINVAL; 181 182 cmd = kmem_cache_alloc(creg_cmd_pool, GFP_KERNEL); 183 if (!cmd) 184 return -ENOMEM; 185 186 INIT_LIST_HEAD(&cmd->list); 187 188 cmd->op = op; 189 cmd->addr = addr; 190 cmd->cnt8 = cnt8; 191 cmd->buf = buf; 192 cmd->stream = stream; 193 cmd->cb = callback; 194 cmd->cb_private = cb_private; 195 cmd->status = 0; 196 197 spin_lock_bh(&card->creg_ctrl.lock); 198 list_add_tail(&cmd->list, &card->creg_ctrl.queue); 199 card->creg_ctrl.q_depth++; 200 creg_kick_queue(card); 201 spin_unlock_bh(&card->creg_ctrl.lock); 202 203 return 0; 204} 205 206static void creg_cmd_timed_out(unsigned long data) 207{ 208 struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data; 209 struct creg_cmd *cmd; 210 211 spin_lock(&card->creg_ctrl.lock); 212 cmd = card->creg_ctrl.active_cmd; 213 card->creg_ctrl.active_cmd = NULL; 214 spin_unlock(&card->creg_ctrl.lock); 215 216 if (cmd == NULL) { 217 card->creg_ctrl.creg_stats.creg_timeout++; 218 dev_warn(CARD_TO_DEV(card), 219 "No active command associated with timeout!\n"); 220 return; 221 } 222 223 if (cmd->cb) 224 cmd->cb(card, cmd, -ETIMEDOUT); 225 226 kmem_cache_free(creg_cmd_pool, cmd); 227 228 229 spin_lock(&card->creg_ctrl.lock); 230 card->creg_ctrl.active = 0; 231 creg_kick_queue(card); 232 spin_unlock(&card->creg_ctrl.lock); 233} 234 235 236static void creg_cmd_done(struct work_struct *work) 237{ 238 struct rsxx_cardinfo *card; 239 struct creg_cmd *cmd; 240 int st = 0; 241 242 card = container_of(work, struct rsxx_cardinfo, 243 creg_ctrl.done_work); 244 245 /* 246 * The timer could not be cancelled for some reason, 247 * race to pop the active command. 248 */ 249 if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0) 250 card->creg_ctrl.creg_stats.failed_cancel_timer++; 251 252 spin_lock_bh(&card->creg_ctrl.lock); 253 cmd = card->creg_ctrl.active_cmd; 254 card->creg_ctrl.active_cmd = NULL; 255 spin_unlock_bh(&card->creg_ctrl.lock); 256 257 if (cmd == NULL) { 258 dev_err(CARD_TO_DEV(card), 259 "Spurious creg interrupt!\n"); 260 return; 261 } 262 263 card->creg_ctrl.creg_stats.stat = ioread32(card->regmap + CREG_STAT); 264 cmd->status = card->creg_ctrl.creg_stats.stat; 265 if ((cmd->status & CREG_STAT_STATUS_MASK) == 0) { 266 dev_err(CARD_TO_DEV(card), 267 "Invalid status on creg command\n"); 268 /* 269 * At this point we're probably reading garbage from HW. Don't 270 * do anything else that could mess up the system and let 271 * the sync function return an error. 272 */ 273 st = -EIO; 274 goto creg_done; 275 } else if (cmd->status & CREG_STAT_ERROR) { 276 st = -EIO; 277 } 278 279 if ((cmd->op == CREG_OP_READ)) { 280 unsigned int cnt8 = ioread32(card->regmap + CREG_CNT); 281 282 /* Paranoid Sanity Checks */ 283 if (!cmd->buf) { 284 dev_err(CARD_TO_DEV(card), 285 "Buffer not given for read.\n"); 286 st = -EIO; 287 goto creg_done; 288 } 289 if (cnt8 != cmd->cnt8) { 290 dev_err(CARD_TO_DEV(card), 291 "count mismatch\n"); 292 st = -EIO; 293 goto creg_done; 294 } 295 296 st = copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream); 297 } 298 299creg_done: 300 if (cmd->cb) 301 cmd->cb(card, cmd, st); 302 303 kmem_cache_free(creg_cmd_pool, cmd); 304 305 spin_lock_bh(&card->creg_ctrl.lock); 306 card->creg_ctrl.active = 0; 307 creg_kick_queue(card); 308 spin_unlock_bh(&card->creg_ctrl.lock); 309} 310 311static void creg_reset(struct rsxx_cardinfo *card) 312{ 313 struct creg_cmd *cmd = NULL; 314 struct creg_cmd *tmp; 315 unsigned long flags; 316 317 /* 318 * mutex_trylock is used here because if reset_lock is taken then a 319 * reset is already happening. So, we can just go ahead and return. 320 */ 321 if (!mutex_trylock(&card->creg_ctrl.reset_lock)) 322 return; 323 324 card->creg_ctrl.reset = 1; 325 spin_lock_irqsave(&card->irq_lock, flags); 326 rsxx_disable_ier_and_isr(card, CR_INTR_CREG | CR_INTR_EVENT); 327 spin_unlock_irqrestore(&card->irq_lock, flags); 328 329 dev_warn(CARD_TO_DEV(card), 330 "Resetting creg interface for recovery\n"); 331 332 /* Cancel outstanding commands */ 333 spin_lock_bh(&card->creg_ctrl.lock); 334 list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { 335 list_del(&cmd->list); 336 card->creg_ctrl.q_depth--; 337 if (cmd->cb) 338 cmd->cb(card, cmd, -ECANCELED); 339 kmem_cache_free(creg_cmd_pool, cmd); 340 } 341 342 cmd = card->creg_ctrl.active_cmd; 343 card->creg_ctrl.active_cmd = NULL; 344 if (cmd) { 345 if (timer_pending(&card->creg_ctrl.cmd_timer)) 346 del_timer_sync(&card->creg_ctrl.cmd_timer); 347 348 if (cmd->cb) 349 cmd->cb(card, cmd, -ECANCELED); 350 kmem_cache_free(creg_cmd_pool, cmd); 351 352 card->creg_ctrl.active = 0; 353 } 354 spin_unlock_bh(&card->creg_ctrl.lock); 355 356 card->creg_ctrl.reset = 0; 357 spin_lock_irqsave(&card->irq_lock, flags); 358 rsxx_enable_ier_and_isr(card, CR_INTR_CREG | CR_INTR_EVENT); 359 spin_unlock_irqrestore(&card->irq_lock, flags); 360 361 mutex_unlock(&card->creg_ctrl.reset_lock); 362} 363 364/* Used for synchronous accesses */ 365struct creg_completion { 366 struct completion *cmd_done; 367 int st; 368 u32 creg_status; 369}; 370 371static void creg_cmd_done_cb(struct rsxx_cardinfo *card, 372 struct creg_cmd *cmd, 373 int st) 374{ 375 struct creg_completion *cmd_completion; 376 377 cmd_completion = cmd->cb_private; 378 BUG_ON(!cmd_completion); 379 380 cmd_completion->st = st; 381 cmd_completion->creg_status = cmd->status; 382 complete(cmd_completion->cmd_done); 383} 384 385static int __issue_creg_rw(struct rsxx_cardinfo *card, 386 unsigned int op, 387 unsigned int addr, 388 unsigned int cnt8, 389 void *buf, 390 int stream, 391 unsigned int *hw_stat) 392{ 393 DECLARE_COMPLETION_ONSTACK(cmd_done); 394 struct creg_completion completion; 395 unsigned long timeout; 396 int st; 397 398 completion.cmd_done = &cmd_done; 399 completion.st = 0; 400 completion.creg_status = 0; 401 402 st = creg_queue_cmd(card, op, addr, cnt8, buf, stream, creg_cmd_done_cb, 403 &completion); 404 if (st) 405 return st; 406 407 /* 408 * This timeout is necessary for unresponsive hardware. The additional 409 * 20 seconds to used to guarantee that each cregs requests has time to 410 * complete. 411 */ 412 timeout = msecs_to_jiffies(CREG_TIMEOUT_MSEC * 413 card->creg_ctrl.q_depth + 20000); 414 415 /* 416 * The creg interface is guaranteed to complete. It has a timeout 417 * mechanism that will kick in if hardware does not respond. 418 */ 419 st = wait_for_completion_timeout(completion.cmd_done, timeout); 420 if (st == 0) { 421 /* 422 * This is really bad, because the kernel timer did not 423 * expire and notify us of a timeout! 424 */ 425 dev_crit(CARD_TO_DEV(card), 426 "cregs timer failed\n"); 427 creg_reset(card); 428 return -EIO; 429 } 430 431 *hw_stat = completion.creg_status; 432 433 if (completion.st) { 434 /* 435 * This read is needed to verify that there has not been any 436 * extreme errors that might have occurred, i.e. EEH. The 437 * function iowrite32 will not detect EEH errors, so it is 438 * necessary that we recover if such an error is the reason 439 * for the timeout. This is a dummy read. 440 */ 441 ioread32(card->regmap + SCRATCH); 442 443 dev_warn(CARD_TO_DEV(card), 444 "creg command failed(%d x%08x)\n", 445 completion.st, addr); 446 return completion.st; 447 } 448 449 return 0; 450} 451 452static int issue_creg_rw(struct rsxx_cardinfo *card, 453 u32 addr, 454 unsigned int size8, 455 void *data, 456 int stream, 457 int read) 458{ 459 unsigned int hw_stat; 460 unsigned int xfer; 461 unsigned int op; 462 int st; 463 464 op = read ? CREG_OP_READ : CREG_OP_WRITE; 465 466 do { 467 xfer = min_t(unsigned int, size8, MAX_CREG_DATA8); 468 469 st = __issue_creg_rw(card, op, addr, xfer, 470 data, stream, &hw_stat); 471 if (st) 472 return st; 473 474 data = (char *)data + xfer; 475 addr += xfer; 476 size8 -= xfer; 477 } while (size8); 478 479 return 0; 480} 481 482/* ---------------------------- Public API ---------------------------------- */ 483int rsxx_creg_write(struct rsxx_cardinfo *card, 484 u32 addr, 485 unsigned int size8, 486 void *data, 487 int byte_stream) 488{ 489 return issue_creg_rw(card, addr, size8, data, byte_stream, 0); 490} 491 492int rsxx_creg_read(struct rsxx_cardinfo *card, 493 u32 addr, 494 unsigned int size8, 495 void *data, 496 int byte_stream) 497{ 498 return issue_creg_rw(card, addr, size8, data, byte_stream, 1); 499} 500 501int rsxx_get_card_state(struct rsxx_cardinfo *card, unsigned int *state) 502{ 503 return rsxx_creg_read(card, CREG_ADD_CARD_STATE, 504 sizeof(*state), state, 0); 505} 506 507int rsxx_get_card_size8(struct rsxx_cardinfo *card, u64 *size8) 508{ 509 unsigned int size; 510 int st; 511 512 st = rsxx_creg_read(card, CREG_ADD_CARD_SIZE, 513 sizeof(size), &size, 0); 514 if (st) 515 return st; 516 517 *size8 = (u64)size * RSXX_HW_BLK_SIZE; 518 return 0; 519} 520 521int rsxx_get_num_targets(struct rsxx_cardinfo *card, 522 unsigned int *n_targets) 523{ 524 return rsxx_creg_read(card, CREG_ADD_NUM_TARGETS, 525 sizeof(*n_targets), n_targets, 0); 526} 527 528int rsxx_get_card_capabilities(struct rsxx_cardinfo *card, 529 u32 *capabilities) 530{ 531 return rsxx_creg_read(card, CREG_ADD_CAPABILITIES, 532 sizeof(*capabilities), capabilities, 0); 533} 534 535int rsxx_issue_card_cmd(struct rsxx_cardinfo *card, u32 cmd) 536{ 537 return rsxx_creg_write(card, CREG_ADD_CARD_CMD, 538 sizeof(cmd), &cmd, 0); 539} 540 541 542/*----------------- HW Log Functions -------------------*/ 543static void hw_log_msg(struct rsxx_cardinfo *card, const char *str, int len) 544{ 545 static char level; 546 547 /* 548 * New messages start with "<#>", where # is the log level. Messages 549 * that extend past the log buffer will use the previous level 550 */ 551 if ((len > 3) && (str[0] == '<') && (str[2] == '>')) { 552 level = str[1]; 553 str += 3; /* Skip past the log level. */ 554 len -= 3; 555 } 556 557 switch (level) { 558 case '0': 559 dev_emerg(CARD_TO_DEV(card), "HW: %.*s", len, str); 560 break; 561 case '1': 562 dev_alert(CARD_TO_DEV(card), "HW: %.*s", len, str); 563 break; 564 case '2': 565 dev_crit(CARD_TO_DEV(card), "HW: %.*s", len, str); 566 break; 567 case '3': 568 dev_err(CARD_TO_DEV(card), "HW: %.*s", len, str); 569 break; 570 case '4': 571 dev_warn(CARD_TO_DEV(card), "HW: %.*s", len, str); 572 break; 573 case '5': 574 dev_notice(CARD_TO_DEV(card), "HW: %.*s", len, str); 575 break; 576 case '6': 577 dev_info(CARD_TO_DEV(card), "HW: %.*s", len, str); 578 break; 579 case '7': 580 dev_dbg(CARD_TO_DEV(card), "HW: %.*s", len, str); 581 break; 582 default: 583 dev_info(CARD_TO_DEV(card), "HW: %.*s", len, str); 584 break; 585 } 586} 587 588/* 589 * The substrncpy function copies the src string (which includes the 590 * terminating '\0' character), up to the count into the dest pointer. 591 * Returns the number of bytes copied to dest. 592 */ 593static int substrncpy(char *dest, const char *src, int count) 594{ 595 int max_cnt = count; 596 597 while (count) { 598 count--; 599 *dest = *src; 600 if (*dest == '\0') 601 break; 602 src++; 603 dest++; 604 } 605 return max_cnt - count; 606} 607 608 609static void read_hw_log_done(struct rsxx_cardinfo *card, 610 struct creg_cmd *cmd, 611 int st) 612{ 613 char *buf; 614 char *log_str; 615 int cnt; 616 int len; 617 int off; 618 619 buf = cmd->buf; 620 off = 0; 621 622 /* Failed getting the log message */ 623 if (st) 624 return; 625 626 while (off < cmd->cnt8) { 627 log_str = &card->log.buf[card->log.buf_len]; 628 cnt = min(cmd->cnt8 - off, LOG_BUF_SIZE8 - card->log.buf_len); 629 len = substrncpy(log_str, &buf[off], cnt); 630 631 off += len; 632 card->log.buf_len += len; 633 634 /* 635 * Flush the log if we've hit the end of a message or if we've 636 * run out of buffer space. 637 */ 638 if ((log_str[len - 1] == '\0') || 639 (card->log.buf_len == LOG_BUF_SIZE8)) { 640 if (card->log.buf_len != 1) /* Don't log blank lines. */ 641 hw_log_msg(card, card->log.buf, 642 card->log.buf_len); 643 card->log.buf_len = 0; 644 } 645 646 } 647 648 if (cmd->status & CREG_STAT_LOG_PENDING) 649 rsxx_read_hw_log(card); 650} 651 652int rsxx_read_hw_log(struct rsxx_cardinfo *card) 653{ 654 int st; 655 656 st = creg_queue_cmd(card, CREG_OP_READ, CREG_ADD_LOG, 657 sizeof(card->log.tmp), card->log.tmp, 658 1, read_hw_log_done, NULL); 659 if (st) 660 dev_err(CARD_TO_DEV(card), 661 "Failed getting log text\n"); 662 663 return st; 664} 665 666/*-------------- IOCTL REG Access ------------------*/ 667static int issue_reg_cmd(struct rsxx_cardinfo *card, 668 struct rsxx_reg_access *cmd, 669 int read) 670{ 671 unsigned int op = read ? CREG_OP_READ : CREG_OP_WRITE; 672 673 return __issue_creg_rw(card, op, cmd->addr, cmd->cnt, cmd->data, 674 cmd->stream, &cmd->stat); 675} 676 677int rsxx_reg_access(struct rsxx_cardinfo *card, 678 struct rsxx_reg_access __user *ucmd, 679 int read) 680{ 681 struct rsxx_reg_access cmd; 682 int st; 683 684 st = copy_from_user(&cmd, ucmd, sizeof(cmd)); 685 if (st) 686 return -EFAULT; 687 688 if (cmd.cnt > RSXX_MAX_REG_CNT) 689 return -EFAULT; 690 691 st = issue_reg_cmd(card, &cmd, read); 692 if (st) 693 return st; 694 695 st = put_user(cmd.stat, &ucmd->stat); 696 if (st) 697 return -EFAULT; 698 699 if (read) { 700 st = copy_to_user(ucmd->data, cmd.data, cmd.cnt); 701 if (st) 702 return -EFAULT; 703 } 704 705 return 0; 706} 707 708void rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card) 709{ 710 struct creg_cmd *cmd = NULL; 711 712 cmd = card->creg_ctrl.active_cmd; 713 card->creg_ctrl.active_cmd = NULL; 714 715 if (cmd) { 716 del_timer_sync(&card->creg_ctrl.cmd_timer); 717 718 spin_lock_bh(&card->creg_ctrl.lock); 719 list_add(&cmd->list, &card->creg_ctrl.queue); 720 card->creg_ctrl.q_depth++; 721 card->creg_ctrl.active = 0; 722 spin_unlock_bh(&card->creg_ctrl.lock); 723 } 724} 725 726void rsxx_kick_creg_queue(struct rsxx_cardinfo *card) 727{ 728 spin_lock_bh(&card->creg_ctrl.lock); 729 if (!list_empty(&card->creg_ctrl.queue)) 730 creg_kick_queue(card); 731 spin_unlock_bh(&card->creg_ctrl.lock); 732} 733 734/*------------ Initialization & Setup --------------*/ 735int rsxx_creg_setup(struct rsxx_cardinfo *card) 736{ 737 card->creg_ctrl.active_cmd = NULL; 738 739 card->creg_ctrl.creg_wq = 740 create_singlethread_workqueue(DRIVER_NAME"_creg"); 741 if (!card->creg_ctrl.creg_wq) 742 return -ENOMEM; 743 744 INIT_WORK(&card->creg_ctrl.done_work, creg_cmd_done); 745 mutex_init(&card->creg_ctrl.reset_lock); 746 INIT_LIST_HEAD(&card->creg_ctrl.queue); 747 spin_lock_init(&card->creg_ctrl.lock); 748 setup_timer(&card->creg_ctrl.cmd_timer, creg_cmd_timed_out, 749 (unsigned long) card); 750 751 return 0; 752} 753 754void rsxx_creg_destroy(struct rsxx_cardinfo *card) 755{ 756 struct creg_cmd *cmd; 757 struct creg_cmd *tmp; 758 int cnt = 0; 759 760 /* Cancel outstanding commands */ 761 spin_lock_bh(&card->creg_ctrl.lock); 762 list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { 763 list_del(&cmd->list); 764 if (cmd->cb) 765 cmd->cb(card, cmd, -ECANCELED); 766 kmem_cache_free(creg_cmd_pool, cmd); 767 cnt++; 768 } 769 770 if (cnt) 771 dev_info(CARD_TO_DEV(card), 772 "Canceled %d queue creg commands\n", cnt); 773 774 cmd = card->creg_ctrl.active_cmd; 775 card->creg_ctrl.active_cmd = NULL; 776 if (cmd) { 777 if (timer_pending(&card->creg_ctrl.cmd_timer)) 778 del_timer_sync(&card->creg_ctrl.cmd_timer); 779 780 if (cmd->cb) 781 cmd->cb(card, cmd, -ECANCELED); 782 dev_info(CARD_TO_DEV(card), 783 "Canceled active creg command\n"); 784 kmem_cache_free(creg_cmd_pool, cmd); 785 } 786 spin_unlock_bh(&card->creg_ctrl.lock); 787 788 cancel_work_sync(&card->creg_ctrl.done_work); 789} 790 791 792int rsxx_creg_init(void) 793{ 794 creg_cmd_pool = KMEM_CACHE(creg_cmd, SLAB_HWCACHE_ALIGN); 795 if (!creg_cmd_pool) 796 return -ENOMEM; 797 798 return 0; 799} 800 801void rsxx_creg_cleanup(void) 802{ 803 kmem_cache_destroy(creg_cmd_pool); 804}