Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[linux-2.6] / drivers / scsi / megaraid / megaraid_mm.c
1 /*
2  *
3  *                      Linux MegaRAID device driver
4  *
5  * Copyright (c) 2003-2004  LSI Logic Corporation.
6  *
7  *         This program is free software; you can redistribute it and/or
8  *         modify it under the terms of the GNU General Public License
9  *         as published by the Free Software Foundation; either version
10  *         2 of the License, or (at your option) any later version.
11  *
12  * FILE         : megaraid_mm.c
13  * Version      : v2.20.2.7 (Jul 16 2006)
14  *
15  * Common management module
16  */
17 #include <linux/sched.h>
18 #include <linux/smp_lock.h>
19 #include "megaraid_mm.h"
20
21
22 // Entry points for char node driver
23 static int mraid_mm_open(struct inode *, struct file *);
24 static int mraid_mm_ioctl(struct inode *, struct file *, uint, unsigned long);
25
26
27 // routines to convert to and from the old the format
28 static int mimd_to_kioc(mimd_t __user *, mraid_mmadp_t *, uioc_t *);
29 static int kioc_to_mimd(uioc_t *, mimd_t __user *);
30
31
32 // Helper functions
33 static int handle_drvrcmd(void __user *, uint8_t, int *);
34 static int lld_ioctl(mraid_mmadp_t *, uioc_t *);
35 static void ioctl_done(uioc_t *);
36 static void lld_timedout(unsigned long);
37 static void hinfo_to_cinfo(mraid_hba_info_t *, mcontroller_t *);
38 static mraid_mmadp_t *mraid_mm_get_adapter(mimd_t __user *, int *);
39 static uioc_t *mraid_mm_alloc_kioc(mraid_mmadp_t *);
40 static void mraid_mm_dealloc_kioc(mraid_mmadp_t *, uioc_t *);
41 static int mraid_mm_attach_buf(mraid_mmadp_t *, uioc_t *, int);
42 static int mraid_mm_setup_dma_pools(mraid_mmadp_t *);
43 static void mraid_mm_free_adp_resources(mraid_mmadp_t *);
44 static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *);
45
46 #ifdef CONFIG_COMPAT
47 static long mraid_mm_compat_ioctl(struct file *, unsigned int, unsigned long);
48 #endif
49
50 MODULE_AUTHOR("LSI Logic Corporation");
51 MODULE_DESCRIPTION("LSI Logic Management Module");
52 MODULE_LICENSE("GPL");
53 MODULE_VERSION(LSI_COMMON_MOD_VERSION);
54
55 static int dbglevel = CL_ANN;
56 module_param_named(dlevel, dbglevel, int, 0);
57 MODULE_PARM_DESC(dlevel, "Debug level (default=0)");
58
59 EXPORT_SYMBOL(mraid_mm_register_adp);
60 EXPORT_SYMBOL(mraid_mm_unregister_adp);
61 EXPORT_SYMBOL(mraid_mm_adapter_app_handle);
62
63 static uint32_t drvr_ver        = 0x02200207;
64
65 static int adapters_count_g;
66 static struct list_head adapters_list_g;
67
68 static wait_queue_head_t wait_q;
69
70 static const struct file_operations lsi_fops = {
71         .open   = mraid_mm_open,
72         .ioctl  = mraid_mm_ioctl,
73 #ifdef CONFIG_COMPAT
74         .compat_ioctl = mraid_mm_compat_ioctl,
75 #endif
76         .owner  = THIS_MODULE,
77 };
78
79 static struct miscdevice megaraid_mm_dev = {
80         .minor  = MISC_DYNAMIC_MINOR,
81         .name   = "megadev0",
82         .fops   = &lsi_fops,
83 };
84
85 /**
86  * mraid_mm_open - open routine for char node interface
87  * @inode       : unused
88  * @filep       : unused
89  *
90  * Allow ioctl operations by apps only if they have superuser privilege.
91  */
92 static int
93 mraid_mm_open(struct inode *inode, struct file *filep)
94 {
95         /*
96          * Only allow superuser to access private ioctl interface
97          */
98         if (!capable(CAP_SYS_ADMIN)) return (-EACCES);
99
100         cycle_kernel_lock();
101         return 0;
102 }
103
104 /**
105  * mraid_mm_ioctl - module entry-point for ioctls
106  * @inode       : inode (ignored)
107  * @filep       : file operations pointer (ignored)
108  * @cmd         : ioctl command
109  * @arg         : user ioctl packet
110  */
111 static int
112 mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
113                                                         unsigned long arg)
114 {
115         uioc_t          *kioc;
116         char            signature[EXT_IOCTL_SIGN_SZ]    = {0};
117         int             rval;
118         mraid_mmadp_t   *adp;
119         uint8_t         old_ioctl;
120         int             drvrcmd_rval;
121         void __user *argp = (void __user *)arg;
122
123         /*
124          * Make sure only USCSICMD are issued through this interface.
125          * MIMD application would still fire different command.
126          */
127
128         if ((_IOC_TYPE(cmd) != MEGAIOC_MAGIC) && (cmd != USCSICMD)) {
129                 return (-EINVAL);
130         }
131
132         /*
133          * Look for signature to see if this is the new or old ioctl format.
134          */
135         if (copy_from_user(signature, argp, EXT_IOCTL_SIGN_SZ)) {
136                 con_log(CL_ANN, (KERN_WARNING
137                         "megaraid cmm: copy from usr addr failed\n"));
138                 return (-EFAULT);
139         }
140
141         if (memcmp(signature, EXT_IOCTL_SIGN, EXT_IOCTL_SIGN_SZ) == 0)
142                 old_ioctl = 0;
143         else
144                 old_ioctl = 1;
145
146         /*
147          * At present, we don't support the new ioctl packet
148          */
149         if (!old_ioctl )
150                 return (-EINVAL);
151
152         /*
153          * If it is a driver ioctl (as opposed to fw ioctls), then we can
154          * handle the command locally. rval > 0 means it is not a drvr cmd
155          */
156         rval = handle_drvrcmd(argp, old_ioctl, &drvrcmd_rval);
157
158         if (rval < 0)
159                 return rval;
160         else if (rval == 0)
161                 return drvrcmd_rval;
162
163         rval = 0;
164         if ((adp = mraid_mm_get_adapter(argp, &rval)) == NULL) {
165                 return rval;
166         }
167
168         /*
169          * Check if adapter can accept ioctl. We may have marked it offline
170          * if any previous kioc had timedout on this controller.
171          */
172         if (!adp->quiescent) {
173                 con_log(CL_ANN, (KERN_WARNING
174                         "megaraid cmm: controller cannot accept cmds due to "
175                         "earlier errors\n" ));
176                 return -EFAULT;
177         }
178
179         /*
180          * The following call will block till a kioc is available
181          */
182         kioc = mraid_mm_alloc_kioc(adp);
183
184         /*
185          * User sent the old mimd_t ioctl packet. Convert it to uioc_t.
186          */
187         if ((rval = mimd_to_kioc(argp, adp, kioc))) {
188                 mraid_mm_dealloc_kioc(adp, kioc);
189                 return rval;
190         }
191
192         kioc->done = ioctl_done;
193
194         /*
195          * Issue the IOCTL to the low level driver. After the IOCTL completes
196          * release the kioc if and only if it was _not_ timedout. If it was
197          * timedout, that means that resources are still with low level driver.
198          */
199         if ((rval = lld_ioctl(adp, kioc))) {
200
201                 if (!kioc->timedout)
202                         mraid_mm_dealloc_kioc(adp, kioc);
203
204                 return rval;
205         }
206
207         /*
208          * Convert the kioc back to user space
209          */
210         rval = kioc_to_mimd(kioc, argp);
211
212         /*
213          * Return the kioc to free pool
214          */
215         mraid_mm_dealloc_kioc(adp, kioc);
216
217         return rval;
218 }
219
220
221 /**
222  * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet
223  * @umimd       : User space mimd_t ioctl packet
224  * @rval        : returned success/error status
225  *
226  * The function return value is a pointer to the located @adapter.
227  */
228 static mraid_mmadp_t *
229 mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)
230 {
231         mraid_mmadp_t   *adapter;
232         mimd_t          mimd;
233         uint32_t        adapno;
234         int             iterator;
235
236
237         if (copy_from_user(&mimd, umimd, sizeof(mimd_t))) {
238                 *rval = -EFAULT;
239                 return NULL;
240         }
241
242         adapno = GETADAP(mimd.ui.fcs.adapno);
243
244         if (adapno >= adapters_count_g) {
245                 *rval = -ENODEV;
246                 return NULL;
247         }
248
249         adapter = NULL;
250         iterator = 0;
251
252         list_for_each_entry(adapter, &adapters_list_g, list) {
253                 if (iterator++ == adapno) break;
254         }
255
256         if (!adapter) {
257                 *rval = -ENODEV;
258                 return NULL;
259         }
260
261         return adapter;
262 }
263
264 /**
265  * handle_drvrcmd - Checks if the opcode is a driver cmd and if it is, handles it.
266  * @arg         : packet sent by the user app
267  * @old_ioctl   : mimd if 1; uioc otherwise
268  * @rval        : pointer for command's returned value (not function status)
269  */
270 static int
271 handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval)
272 {
273         mimd_t          __user *umimd;
274         mimd_t          kmimd;
275         uint8_t         opcode;
276         uint8_t         subopcode;
277
278         if (old_ioctl)
279                 goto old_packet;
280         else
281                 goto new_packet;
282
283 new_packet:
284         return (-ENOTSUPP);
285
286 old_packet:
287         *rval = 0;
288         umimd = arg;
289
290         if (copy_from_user(&kmimd, umimd, sizeof(mimd_t)))
291                 return (-EFAULT);
292
293         opcode          = kmimd.ui.fcs.opcode;
294         subopcode       = kmimd.ui.fcs.subopcode;
295
296         /*
297          * If the opcode is 0x82 and the subopcode is either GET_DRVRVER or
298          * GET_NUMADP, then we can handle. Otherwise we should return 1 to
299          * indicate that we cannot handle this.
300          */
301         if (opcode != 0x82)
302                 return 1;
303
304         switch (subopcode) {
305
306         case MEGAIOC_QDRVRVER:
307
308                 if (copy_to_user(kmimd.data, &drvr_ver, sizeof(uint32_t)))
309                         return (-EFAULT);
310
311                 return 0;
312
313         case MEGAIOC_QNADAP:
314
315                 *rval = adapters_count_g;
316
317                 if (copy_to_user(kmimd.data, &adapters_count_g,
318                                 sizeof(uint32_t)))
319                         return (-EFAULT);
320
321                 return 0;
322
323         default:
324                 /* cannot handle */
325                 return 1;
326         }
327
328         return 0;
329 }
330
331
332 /**
333  * mimd_to_kioc - Converter from old to new ioctl format
334  * @umimd       : user space old MIMD IOCTL
335  * @adp         : adapter softstate
336  * @kioc        : kernel space new format IOCTL
337  *
338  * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The
339  * new packet is in kernel space so that driver can perform operations on it
340  * freely.
341  */
342
343 static int
344 mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc)
345 {
346         mbox64_t                *mbox64;
347         mbox_t                  *mbox;
348         mraid_passthru_t        *pthru32;
349         uint32_t                adapno;
350         uint8_t                 opcode;
351         uint8_t                 subopcode;
352         mimd_t                  mimd;
353
354         if (copy_from_user(&mimd, umimd, sizeof(mimd_t)))
355                 return (-EFAULT);
356
357         /*
358          * Applications are not allowed to send extd pthru
359          */
360         if ((mimd.mbox[0] == MBOXCMD_PASSTHRU64) ||
361                         (mimd.mbox[0] == MBOXCMD_EXTPTHRU))
362                 return (-EINVAL);
363
364         opcode          = mimd.ui.fcs.opcode;
365         subopcode       = mimd.ui.fcs.subopcode;
366         adapno          = GETADAP(mimd.ui.fcs.adapno);
367
368         if (adapno >= adapters_count_g)
369                 return (-ENODEV);
370
371         kioc->adapno    = adapno;
372         kioc->mb_type   = MBOX_LEGACY;
373         kioc->app_type  = APPTYPE_MIMD;
374
375         switch (opcode) {
376
377         case 0x82:
378
379                 if (subopcode == MEGAIOC_QADAPINFO) {
380
381                         kioc->opcode    = GET_ADAP_INFO;
382                         kioc->data_dir  = UIOC_RD;
383                         kioc->xferlen   = sizeof(mraid_hba_info_t);
384
385                         if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen))
386                                 return (-ENOMEM);
387                 }
388                 else {
389                         con_log(CL_ANN, (KERN_WARNING
390                                         "megaraid cmm: Invalid subop\n"));
391                         return (-EINVAL);
392                 }
393
394                 break;
395
396         case 0x81:
397
398                 kioc->opcode            = MBOX_CMD;
399                 kioc->xferlen           = mimd.ui.fcs.length;
400                 kioc->user_data_len     = kioc->xferlen;
401                 kioc->user_data         = mimd.ui.fcs.buffer;
402
403                 if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen))
404                         return (-ENOMEM);
405
406                 if (mimd.outlen) kioc->data_dir  = UIOC_RD;
407                 if (mimd.inlen) kioc->data_dir |= UIOC_WR;
408
409                 break;
410
411         case 0x80:
412
413                 kioc->opcode            = MBOX_CMD;
414                 kioc->xferlen           = (mimd.outlen > mimd.inlen) ?
415                                                 mimd.outlen : mimd.inlen;
416                 kioc->user_data_len     = kioc->xferlen;
417                 kioc->user_data         = mimd.data;
418
419                 if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen))
420                         return (-ENOMEM);
421
422                 if (mimd.outlen) kioc->data_dir  = UIOC_RD;
423                 if (mimd.inlen) kioc->data_dir |= UIOC_WR;
424
425                 break;
426
427         default:
428                 return (-EINVAL);
429         }
430
431         /*
432          * If driver command, nothing else to do
433          */
434         if (opcode == 0x82)
435                 return 0;
436
437         /*
438          * This is a mailbox cmd; copy the mailbox from mimd
439          */
440         mbox64  = (mbox64_t *)((unsigned long)kioc->cmdbuf);
441         mbox    = &mbox64->mbox32;
442         memcpy(mbox, mimd.mbox, 14);
443
444         if (mbox->cmd != MBOXCMD_PASSTHRU) {    // regular DCMD
445
446                 mbox->xferaddr  = (uint32_t)kioc->buf_paddr;
447
448                 if (kioc->data_dir & UIOC_WR) {
449                         if (copy_from_user(kioc->buf_vaddr, kioc->user_data,
450                                                         kioc->xferlen)) {
451                                 return (-EFAULT);
452                         }
453                 }
454
455                 return 0;
456         }
457
458         /*
459          * This is a regular 32-bit pthru cmd; mbox points to pthru struct.
460          * Just like in above case, the beginning for memblk is treated as
461          * a mailbox. The passthru will begin at next 1K boundary. And the
462          * data will start 1K after that.
463          */
464         pthru32                 = kioc->pthru32;
465         kioc->user_pthru        = &umimd->pthru;
466         mbox->xferaddr          = (uint32_t)kioc->pthru32_h;
467
468         if (copy_from_user(pthru32, kioc->user_pthru,
469                         sizeof(mraid_passthru_t))) {
470                 return (-EFAULT);
471         }
472
473         pthru32->dataxferaddr   = kioc->buf_paddr;
474         if (kioc->data_dir & UIOC_WR) {
475                 if (copy_from_user(kioc->buf_vaddr, kioc->user_data,
476                                                 pthru32->dataxferlen)) {
477                         return (-EFAULT);
478                 }
479         }
480
481         return 0;
482 }
483
484 /**
485  * mraid_mm_attch_buf - Attach a free dma buffer for required size
486  * @adp         : Adapter softstate
487  * @kioc        : kioc that the buffer needs to be attached to
488  * @xferlen     : required length for buffer
489  *
490  * First we search for a pool with smallest buffer that is >= @xferlen. If
491  * that pool has no free buffer, we will try for the next bigger size. If none
492  * is available, we will try to allocate the smallest buffer that is >=
493  * @xferlen and attach it the pool.
494  */
495 static int
496 mraid_mm_attach_buf(mraid_mmadp_t *adp, uioc_t *kioc, int xferlen)
497 {
498         mm_dmapool_t    *pool;
499         int             right_pool = -1;
500         unsigned long   flags;
501         int             i;
502
503         kioc->pool_index        = -1;
504         kioc->buf_vaddr         = NULL;
505         kioc->buf_paddr         = 0;
506         kioc->free_buf          = 0;
507
508         /*
509          * We need xferlen amount of memory. See if we can get it from our
510          * dma pools. If we don't get exact size, we will try bigger buffer
511          */
512
513         for (i = 0; i < MAX_DMA_POOLS; i++) {
514
515                 pool = &adp->dma_pool_list[i];
516
517                 if (xferlen > pool->buf_size)
518                         continue;
519
520                 if (right_pool == -1)
521                         right_pool = i;
522
523                 spin_lock_irqsave(&pool->lock, flags);
524
525                 if (!pool->in_use) {
526
527                         pool->in_use            = 1;
528                         kioc->pool_index        = i;
529                         kioc->buf_vaddr         = pool->vaddr;
530                         kioc->buf_paddr         = pool->paddr;
531
532                         spin_unlock_irqrestore(&pool->lock, flags);
533                         return 0;
534                 }
535                 else {
536                         spin_unlock_irqrestore(&pool->lock, flags);
537                         continue;
538                 }
539         }
540
541         /*
542          * If xferlen doesn't match any of our pools, return error
543          */
544         if (right_pool == -1)
545                 return -EINVAL;
546
547         /*
548          * We did not get any buffer from the preallocated pool. Let us try
549          * to allocate one new buffer. NOTE: This is a blocking call.
550          */
551         pool = &adp->dma_pool_list[right_pool];
552
553         spin_lock_irqsave(&pool->lock, flags);
554
555         kioc->pool_index        = right_pool;
556         kioc->free_buf          = 1;
557         kioc->buf_vaddr         = pci_pool_alloc(pool->handle, GFP_KERNEL,
558                                                         &kioc->buf_paddr);
559         spin_unlock_irqrestore(&pool->lock, flags);
560
561         if (!kioc->buf_vaddr)
562                 return -ENOMEM;
563
564         return 0;
565 }
566
567 /**
568  * mraid_mm_alloc_kioc - Returns a uioc_t from free list
569  * @adp : Adapter softstate for this module
570  *
571  * The kioc_semaphore is initialized with number of kioc nodes in the
572  * free kioc pool. If the kioc pool is empty, this function blocks till
573  * a kioc becomes free.
574  */
575 static uioc_t *
576 mraid_mm_alloc_kioc(mraid_mmadp_t *adp)
577 {
578         uioc_t                  *kioc;
579         struct list_head*       head;
580         unsigned long           flags;
581
582         down(&adp->kioc_semaphore);
583
584         spin_lock_irqsave(&adp->kioc_pool_lock, flags);
585
586         head = &adp->kioc_pool;
587
588         if (list_empty(head)) {
589                 up(&adp->kioc_semaphore);
590                 spin_unlock_irqrestore(&adp->kioc_pool_lock, flags);
591
592                 con_log(CL_ANN, ("megaraid cmm: kioc list empty!\n"));
593                 return NULL;
594         }
595
596         kioc = list_entry(head->next, uioc_t, list);
597         list_del_init(&kioc->list);
598
599         spin_unlock_irqrestore(&adp->kioc_pool_lock, flags);
600
601         memset((caddr_t)(unsigned long)kioc->cmdbuf, 0, sizeof(mbox64_t));
602         memset((caddr_t) kioc->pthru32, 0, sizeof(mraid_passthru_t));
603
604         kioc->buf_vaddr         = NULL;
605         kioc->buf_paddr         = 0;
606         kioc->pool_index        =-1;
607         kioc->free_buf          = 0;
608         kioc->user_data         = NULL;
609         kioc->user_data_len     = 0;
610         kioc->user_pthru        = NULL;
611         kioc->timedout          = 0;
612
613         return kioc;
614 }
615
616 /**
617  * mraid_mm_dealloc_kioc - Return kioc to free pool
618  * @adp         : Adapter softstate
619  * @kioc        : uioc_t node to be returned to free pool
620  */
621 static void
622 mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc)
623 {
624         mm_dmapool_t    *pool;
625         unsigned long   flags;
626
627         if (kioc->pool_index != -1) {
628                 pool = &adp->dma_pool_list[kioc->pool_index];
629
630                 /* This routine may be called in non-isr context also */
631                 spin_lock_irqsave(&pool->lock, flags);
632
633                 /*
634                  * While attaching the dma buffer, if we didn't get the 
635                  * required buffer from the pool, we would have allocated 
636                  * it at the run time and set the free_buf flag. We must 
637                  * free that buffer. Otherwise, just mark that the buffer is 
638                  * not in use
639                  */
640                 if (kioc->free_buf == 1)
641                         pci_pool_free(pool->handle, kioc->buf_vaddr, 
642                                                         kioc->buf_paddr);
643                 else
644                         pool->in_use = 0;
645
646                 spin_unlock_irqrestore(&pool->lock, flags);
647         }
648
649         /* Return the kioc to the free pool */
650         spin_lock_irqsave(&adp->kioc_pool_lock, flags);
651         list_add(&kioc->list, &adp->kioc_pool);
652         spin_unlock_irqrestore(&adp->kioc_pool_lock, flags);
653
654         /* increment the free kioc count */
655         up(&adp->kioc_semaphore);
656
657         return;
658 }
659
660 /**
661  * lld_ioctl - Routine to issue ioctl to low level drvr
662  * @adp         : The adapter handle
663  * @kioc        : The ioctl packet with kernel addresses
664  */
665 static int
666 lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc)
667 {
668         int                     rval;
669         struct timer_list       timer;
670         struct timer_list       *tp = NULL;
671
672         kioc->status    = -ENODATA;
673         rval            = adp->issue_uioc(adp->drvr_data, kioc, IOCTL_ISSUE);
674
675         if (rval) return rval;
676
677         /*
678          * Start the timer
679          */
680         if (adp->timeout > 0) {
681                 tp              = &timer;
682                 init_timer(tp);
683
684                 tp->function    = lld_timedout;
685                 tp->data        = (unsigned long)kioc;
686                 tp->expires     = jiffies + adp->timeout * HZ;
687
688                 add_timer(tp);
689         }
690
691         /*
692          * Wait till the low level driver completes the ioctl. After this
693          * call, the ioctl either completed successfully or timedout.
694          */
695         wait_event(wait_q, (kioc->status != -ENODATA));
696         if (tp) {
697                 del_timer_sync(tp);
698         }
699
700         /*
701          * If the command had timedout, we mark the controller offline
702          * before returning
703          */
704         if (kioc->timedout) {
705                 adp->quiescent = 0;
706         }
707
708         return kioc->status;
709 }
710
711
712 /**
713  * ioctl_done - callback from the low level driver
714  * @kioc        : completed ioctl packet
715  */
716 static void
717 ioctl_done(uioc_t *kioc)
718 {
719         uint32_t        adapno;
720         int             iterator;
721         mraid_mmadp_t*  adapter;
722
723         /*
724          * When the kioc returns from driver, make sure it still doesn't
725          * have ENODATA in status. Otherwise, driver will hang on wait_event
726          * forever
727          */
728         if (kioc->status == -ENODATA) {
729                 con_log(CL_ANN, (KERN_WARNING
730                         "megaraid cmm: lld didn't change status!\n"));
731
732                 kioc->status = -EINVAL;
733         }
734
735         /*
736          * Check if this kioc was timedout before. If so, nobody is waiting
737          * on this kioc. We don't have to wake up anybody. Instead, we just
738          * have to free the kioc
739          */
740         if (kioc->timedout) {
741                 iterator        = 0;
742                 adapter         = NULL;
743                 adapno          = kioc->adapno;
744
745                 con_log(CL_ANN, ( KERN_WARNING "megaraid cmm: completed "
746                                         "ioctl that was timedout before\n"));
747
748                 list_for_each_entry(adapter, &adapters_list_g, list) {
749                         if (iterator++ == adapno) break;
750                 }
751
752                 kioc->timedout = 0;
753
754                 if (adapter) {
755                         mraid_mm_dealloc_kioc( adapter, kioc );
756                 }
757         }
758         else {
759                 wake_up(&wait_q);
760         }
761 }
762
763
764 /**
765  * lld_timedout - callback from the expired timer
766  * @ptr         : ioctl packet that timed out
767  */
768 static void
769 lld_timedout(unsigned long ptr)
770 {
771         uioc_t *kioc    = (uioc_t *)ptr;
772
773         kioc->status    = -ETIME;
774         kioc->timedout  = 1;
775
776         con_log(CL_ANN, (KERN_WARNING "megaraid cmm: ioctl timed out\n"));
777
778         wake_up(&wait_q);
779 }
780
781
782 /**
783  * kioc_to_mimd - Converter from new back to old format
784  * @kioc        : Kernel space IOCTL packet (successfully issued)
785  * @mimd        : User space MIMD packet
786  */
787 static int
788 kioc_to_mimd(uioc_t *kioc, mimd_t __user *mimd)
789 {
790         mimd_t                  kmimd;
791         uint8_t                 opcode;
792         uint8_t                 subopcode;
793
794         mbox64_t                *mbox64;
795         mraid_passthru_t        __user *upthru32;
796         mraid_passthru_t        *kpthru32;
797         mcontroller_t           cinfo;
798         mraid_hba_info_t        *hinfo;
799
800
801         if (copy_from_user(&kmimd, mimd, sizeof(mimd_t)))
802                 return (-EFAULT);
803
804         opcode          = kmimd.ui.fcs.opcode;
805         subopcode       = kmimd.ui.fcs.subopcode;
806
807         if (opcode == 0x82) {
808                 switch (subopcode) {
809
810                 case MEGAIOC_QADAPINFO:
811
812                         hinfo = (mraid_hba_info_t *)(unsigned long)
813                                         kioc->buf_vaddr;
814
815                         hinfo_to_cinfo(hinfo, &cinfo);
816
817                         if (copy_to_user(kmimd.data, &cinfo, sizeof(cinfo)))
818                                 return (-EFAULT);
819
820                         return 0;
821
822                 default:
823                         return (-EINVAL);
824                 }
825
826                 return 0;
827         }
828
829         mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf;
830
831         if (kioc->user_pthru) {
832
833                 upthru32 = kioc->user_pthru;
834                 kpthru32 = kioc->pthru32;
835
836                 if (copy_to_user(&upthru32->scsistatus,
837                                         &kpthru32->scsistatus,
838                                         sizeof(uint8_t))) {
839                         return (-EFAULT);
840                 }
841         }
842
843         if (kioc->user_data) {
844                 if (copy_to_user(kioc->user_data, kioc->buf_vaddr,
845                                         kioc->user_data_len)) {
846                         return (-EFAULT);
847                 }
848         }
849
850         if (copy_to_user(&mimd->mbox[17],
851                         &mbox64->mbox32.status, sizeof(uint8_t))) {
852                 return (-EFAULT);
853         }
854
855         return 0;
856 }
857
858
859 /**
860  * hinfo_to_cinfo - Convert new format hba info into old format
861  * @hinfo       : New format, more comprehensive adapter info
862  * @cinfo       : Old format adapter info to support mimd_t apps
863  */
864 static void
865 hinfo_to_cinfo(mraid_hba_info_t *hinfo, mcontroller_t *cinfo)
866 {
867         if (!hinfo || !cinfo)
868                 return;
869
870         cinfo->base             = hinfo->baseport;
871         cinfo->irq              = hinfo->irq;
872         cinfo->numldrv          = hinfo->num_ldrv;
873         cinfo->pcibus           = hinfo->pci_bus;
874         cinfo->pcidev           = hinfo->pci_slot;
875         cinfo->pcifun           = PCI_FUNC(hinfo->pci_dev_fn);
876         cinfo->pciid            = hinfo->pci_device_id;
877         cinfo->pcivendor        = hinfo->pci_vendor_id;
878         cinfo->pcislot          = hinfo->pci_slot;
879         cinfo->uid              = hinfo->unique_id;
880 }
881
882
883 /**
884  * mraid_mm_register_adp - Registration routine for low level drivers
885  * @lld_adp     : Adapter objejct
886  */
887 int
888 mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
889 {
890         mraid_mmadp_t   *adapter;
891         mbox64_t        *mbox_list;
892         uioc_t          *kioc;
893         uint32_t        rval;
894         int             i;
895
896
897         if (lld_adp->drvr_type != DRVRTYPE_MBOX)
898                 return (-EINVAL);
899
900         adapter = kzalloc(sizeof(mraid_mmadp_t), GFP_KERNEL);
901
902         if (!adapter)
903                 return -ENOMEM;
904
905
906         adapter->unique_id      = lld_adp->unique_id;
907         adapter->drvr_type      = lld_adp->drvr_type;
908         adapter->drvr_data      = lld_adp->drvr_data;
909         adapter->pdev           = lld_adp->pdev;
910         adapter->issue_uioc     = lld_adp->issue_uioc;
911         adapter->timeout        = lld_adp->timeout;
912         adapter->max_kioc       = lld_adp->max_kioc;
913         adapter->quiescent      = 1;
914
915         /*
916          * Allocate single blocks of memory for all required kiocs,
917          * mailboxes and passthru structures.
918          */
919         adapter->kioc_list      = kmalloc(sizeof(uioc_t) * lld_adp->max_kioc,
920                                                 GFP_KERNEL);
921         adapter->mbox_list      = kmalloc(sizeof(mbox64_t) * lld_adp->max_kioc,
922                                                 GFP_KERNEL);
923         adapter->pthru_dma_pool = pci_pool_create("megaraid mm pthru pool",
924                                                 adapter->pdev,
925                                                 sizeof(mraid_passthru_t),
926                                                 16, 0);
927
928         if (!adapter->kioc_list || !adapter->mbox_list ||
929                         !adapter->pthru_dma_pool) {
930
931                 con_log(CL_ANN, (KERN_WARNING
932                         "megaraid cmm: out of memory, %s %d\n", __func__,
933                         __LINE__));
934
935                 rval = (-ENOMEM);
936
937                 goto memalloc_error;
938         }
939
940         /*
941          * Slice kioc_list and make a kioc_pool with the individiual kiocs
942          */
943         INIT_LIST_HEAD(&adapter->kioc_pool);
944         spin_lock_init(&adapter->kioc_pool_lock);
945         sema_init(&adapter->kioc_semaphore, lld_adp->max_kioc);
946
947         mbox_list       = (mbox64_t *)adapter->mbox_list;
948
949         for (i = 0; i < lld_adp->max_kioc; i++) {
950
951                 kioc            = adapter->kioc_list + i;
952                 kioc->cmdbuf    = (uint64_t)(unsigned long)(mbox_list + i);
953                 kioc->pthru32   = pci_pool_alloc(adapter->pthru_dma_pool,
954                                                 GFP_KERNEL, &kioc->pthru32_h);
955
956                 if (!kioc->pthru32) {
957
958                         con_log(CL_ANN, (KERN_WARNING
959                                 "megaraid cmm: out of memory, %s %d\n",
960                                         __func__, __LINE__));
961
962                         rval = (-ENOMEM);
963
964                         goto pthru_dma_pool_error;
965                 }
966
967                 list_add_tail(&kioc->list, &adapter->kioc_pool);
968         }
969
970         // Setup the dma pools for data buffers
971         if ((rval = mraid_mm_setup_dma_pools(adapter)) != 0) {
972                 goto dma_pool_error;
973         }
974
975         list_add_tail(&adapter->list, &adapters_list_g);
976
977         adapters_count_g++;
978
979         return 0;
980
981 dma_pool_error:
982         /* Do nothing */
983
984 pthru_dma_pool_error:
985
986         for (i = 0; i < lld_adp->max_kioc; i++) {
987                 kioc = adapter->kioc_list + i;
988                 if (kioc->pthru32) {
989                         pci_pool_free(adapter->pthru_dma_pool, kioc->pthru32,
990                                 kioc->pthru32_h);
991                 }
992         }
993
994 memalloc_error:
995
996         kfree(adapter->kioc_list);
997         kfree(adapter->mbox_list);
998
999         if (adapter->pthru_dma_pool)
1000                 pci_pool_destroy(adapter->pthru_dma_pool);
1001
1002         kfree(adapter);
1003
1004         return rval;
1005 }
1006
1007
1008 /**
1009  * mraid_mm_adapter_app_handle - return the application handle for this adapter
1010  * @unique_id   : adapter unique identifier
1011  *
1012  * For the given driver data, locate the adapter in our global list and
1013  * return the corresponding handle, which is also used by applications to
1014  * uniquely identify an adapter.
1015  *
1016  * Return adapter handle if found in the list.
1017  * Return 0 if adapter could not be located, should never happen though.
1018  */
1019 uint32_t
1020 mraid_mm_adapter_app_handle(uint32_t unique_id)
1021 {
1022         mraid_mmadp_t   *adapter;
1023         mraid_mmadp_t   *tmp;
1024         int             index = 0;
1025
1026         list_for_each_entry_safe(adapter, tmp, &adapters_list_g, list) {
1027
1028                 if (adapter->unique_id == unique_id) {
1029
1030                         return MKADAP(index);
1031                 }
1032
1033                 index++;
1034         }
1035
1036         return 0;
1037 }
1038
1039
1040 /**
1041  * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter
1042  * @adp : Adapter softstate
1043  *
1044  * We maintain a pool of dma buffers per each adapter. Each pool has one
1045  * buffer. E.g, we may have 5 dma pools - one each for 4k, 8k ... 64k buffers.
1046  * We have just one 4k buffer in 4k pool, one 8k buffer in 8k pool etc. We
1047  * dont' want to waste too much memory by allocating more buffers per each
1048  * pool.
1049  */
1050 static int
1051 mraid_mm_setup_dma_pools(mraid_mmadp_t *adp)
1052 {
1053         mm_dmapool_t    *pool;
1054         int             bufsize;
1055         int             i;
1056
1057         /*
1058          * Create MAX_DMA_POOLS number of pools
1059          */
1060         bufsize = MRAID_MM_INIT_BUFF_SIZE;
1061
1062         for (i = 0; i < MAX_DMA_POOLS; i++){
1063
1064                 pool = &adp->dma_pool_list[i];
1065
1066                 pool->buf_size = bufsize;
1067                 spin_lock_init(&pool->lock);
1068
1069                 pool->handle = pci_pool_create("megaraid mm data buffer",
1070                                                 adp->pdev, bufsize, 16, 0);
1071
1072                 if (!pool->handle) {
1073                         goto dma_pool_setup_error;
1074                 }
1075
1076                 pool->vaddr = pci_pool_alloc(pool->handle, GFP_KERNEL,
1077                                                         &pool->paddr);
1078
1079                 if (!pool->vaddr)
1080                         goto dma_pool_setup_error;
1081
1082                 bufsize = bufsize * 2;
1083         }
1084
1085         return 0;
1086
1087 dma_pool_setup_error:
1088
1089         mraid_mm_teardown_dma_pools(adp);
1090         return (-ENOMEM);
1091 }
1092
1093
1094 /**
1095  * mraid_mm_unregister_adp - Unregister routine for low level drivers
1096  * @unique_id   : UID of the adpater
1097  *
1098  * Assumes no outstanding ioctls to llds.
1099  */
1100 int
1101 mraid_mm_unregister_adp(uint32_t unique_id)
1102 {
1103         mraid_mmadp_t   *adapter;
1104         mraid_mmadp_t   *tmp;
1105
1106         list_for_each_entry_safe(adapter, tmp, &adapters_list_g, list) {
1107
1108
1109                 if (adapter->unique_id == unique_id) {
1110
1111                         adapters_count_g--;
1112
1113                         list_del_init(&adapter->list);
1114
1115                         mraid_mm_free_adp_resources(adapter);
1116
1117                         kfree(adapter);
1118
1119                         con_log(CL_ANN, (
1120                                 "megaraid cmm: Unregistered one adapter:%#x\n",
1121                                 unique_id));
1122
1123                         return 0;
1124                 }
1125         }
1126
1127         return (-ENODEV);
1128 }
1129
1130 /**
1131  * mraid_mm_free_adp_resources - Free adapter softstate
1132  * @adp : Adapter softstate
1133  */
1134 static void
1135 mraid_mm_free_adp_resources(mraid_mmadp_t *adp)
1136 {
1137         uioc_t  *kioc;
1138         int     i;
1139
1140         mraid_mm_teardown_dma_pools(adp);
1141
1142         for (i = 0; i < adp->max_kioc; i++) {
1143
1144                 kioc = adp->kioc_list + i;
1145
1146                 pci_pool_free(adp->pthru_dma_pool, kioc->pthru32,
1147                                 kioc->pthru32_h);
1148         }
1149
1150         kfree(adp->kioc_list);
1151         kfree(adp->mbox_list);
1152
1153         pci_pool_destroy(adp->pthru_dma_pool);
1154
1155
1156         return;
1157 }
1158
1159
1160 /**
1161  * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers
1162  * @adp : Adapter softstate
1163  */
1164 static void
1165 mraid_mm_teardown_dma_pools(mraid_mmadp_t *adp)
1166 {
1167         int             i;
1168         mm_dmapool_t    *pool;
1169
1170         for (i = 0; i < MAX_DMA_POOLS; i++) {
1171
1172                 pool = &adp->dma_pool_list[i];
1173
1174                 if (pool->handle) {
1175
1176                         if (pool->vaddr)
1177                                 pci_pool_free(pool->handle, pool->vaddr,
1178                                                         pool->paddr);
1179
1180                         pci_pool_destroy(pool->handle);
1181                         pool->handle = NULL;
1182                 }
1183         }
1184
1185         return;
1186 }
1187
1188 /**
1189  * mraid_mm_init        - Module entry point
1190  */
1191 static int __init
1192 mraid_mm_init(void)
1193 {
1194         int err;
1195
1196         // Announce the driver version
1197         con_log(CL_ANN, (KERN_INFO "megaraid cmm: %s %s\n",
1198                 LSI_COMMON_MOD_VERSION, LSI_COMMON_MOD_EXT_VERSION));
1199
1200         err = misc_register(&megaraid_mm_dev);
1201         if (err < 0) {
1202                 con_log(CL_ANN, ("megaraid cmm: cannot register misc device\n"));
1203                 return err;
1204         }
1205
1206         init_waitqueue_head(&wait_q);
1207
1208         INIT_LIST_HEAD(&adapters_list_g);
1209
1210         return 0;
1211 }
1212
1213
1214 #ifdef CONFIG_COMPAT
1215 /**
1216  * mraid_mm_compat_ioctl        - 32bit to 64bit ioctl conversion routine
1217  * @filep       : file operations pointer (ignored)
1218  * @cmd         : ioctl command
1219  * @arg         : user ioctl packet
1220  */
1221 static long
1222 mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd,
1223                       unsigned long arg)
1224 {
1225         int err;
1226
1227         err = mraid_mm_ioctl(NULL, filep, cmd, arg);
1228
1229         return err;
1230 }
1231 #endif
1232
1233 /**
1234  * mraid_mm_exit        - Module exit point
1235  */
1236 static void __exit
1237 mraid_mm_exit(void)
1238 {
1239         con_log(CL_DLEVEL1 , ("exiting common mod\n"));
1240
1241         misc_deregister(&megaraid_mm_dev);
1242 }
1243
1244 module_init(mraid_mm_init);
1245 module_exit(mraid_mm_exit);
1246
1247 /* vi: set ts=8 sw=8 tw=78: */