linux/drivers/scsi/megaraid/megaraid_mm.c
<<
>>
Prefs
   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
  23static int mraid_mm_open(struct inode *, struct file *);
  24static int mraid_mm_ioctl(struct inode *, struct file *, uint, unsigned long);
  25
  26
  27// routines to convert to and from the old the format
  28static int mimd_to_kioc(mimd_t __user *, mraid_mmadp_t *, uioc_t *);
  29static int kioc_to_mimd(uioc_t *, mimd_t __user *);
  30
  31
  32// Helper functions
  33static int handle_drvrcmd(void __user *, uint8_t, int *);
  34static int lld_ioctl(mraid_mmadp_t *, uioc_t *);
  35static void ioctl_done(uioc_t *);
  36static void lld_timedout(unsigned long);
  37static void hinfo_to_cinfo(mraid_hba_info_t *, mcontroller_t *);
  38static mraid_mmadp_t *mraid_mm_get_adapter(mimd_t __user *, int *);
  39static uioc_t *mraid_mm_alloc_kioc(mraid_mmadp_t *);
  40static void mraid_mm_dealloc_kioc(mraid_mmadp_t *, uioc_t *);
  41static int mraid_mm_attach_buf(mraid_mmadp_t *, uioc_t *, int);
  42static int mraid_mm_setup_dma_pools(mraid_mmadp_t *);
  43static void mraid_mm_free_adp_resources(mraid_mmadp_t *);
  44static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *);
  45
  46#ifdef CONFIG_COMPAT
  47static long mraid_mm_compat_ioctl(struct file *, unsigned int, unsigned long);
  48#endif
  49
  50MODULE_AUTHOR("LSI Logic Corporation");
  51MODULE_DESCRIPTION("LSI Logic Management Module");
  52MODULE_LICENSE("GPL");
  53MODULE_VERSION(LSI_COMMON_MOD_VERSION);
  54
  55static int dbglevel = CL_ANN;
  56module_param_named(dlevel, dbglevel, int, 0);
  57MODULE_PARM_DESC(dlevel, "Debug level (default=0)");
  58
  59EXPORT_SYMBOL(mraid_mm_register_adp);
  60EXPORT_SYMBOL(mraid_mm_unregister_adp);
  61EXPORT_SYMBOL(mraid_mm_adapter_app_handle);
  62
  63static uint32_t drvr_ver        = 0x02200207;
  64
  65static int adapters_count_g;
  66static struct list_head adapters_list_g;
  67
  68static wait_queue_head_t wait_q;
  69
  70static 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
  79static 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 */
  92static int
  93mraid_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 */
 111static int
 112mraid_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 */
 228static mraid_mmadp_t *
 229mraid_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 */
 270static int
 271handle_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
 283new_packet:
 284        return (-ENOTSUPP);
 285
 286old_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
 343static int
 344mimd_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 */
 495static int
 496mraid_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 */
 575static uioc_t *
 576mraid_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 */
 621static void
 622mraid_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 */
 665static int
 666lld_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 */
 716static void
 717ioctl_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 */
 768static void
 769lld_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 */
 787static int
 788kioc_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 */
 864static void
 865hinfo_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 */
 887int
 888mraid_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
 981dma_pool_error:
 982        /* Do nothing */
 983
 984pthru_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
 994memalloc_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 */
1019uint32_t
1020mraid_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 */
1050static int
1051mraid_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
1087dma_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 */
1100int
1101mraid_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 */
1134static void
1135mraid_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 */
1164static void
1165mraid_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 */
1191static int __init
1192mraid_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 */
1221static long
1222mraid_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 */
1236static void __exit
1237mraid_mm_exit(void)
1238{
1239        con_log(CL_DLEVEL1 , ("exiting common mod\n"));
1240
1241        misc_deregister(&megaraid_mm_dev);
1242}
1243
1244module_init(mraid_mm_init);
1245module_exit(mraid_mm_exit);
1246
1247/* vi: set ts=8 sw=8 tw=78: */
1248