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