linux/drivers/scsi/aacraid/comminit.c
<<
>>
Prefs
   1/*
   2 *      Adaptec AAC series RAID controller driver
   3 *      (c) Copyright 2001 Red Hat Inc.
   4 *
   5 * based on the old aacraid driver that is..
   6 * Adaptec aacraid device driver for Linux.
   7 *
   8 * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2, or (at your option)
  13 * any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU 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; see the file COPYING.  If not, write to
  22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  23 *
  24 * Module Name:
  25 *  comminit.c
  26 *
  27 * Abstract: This supports the initialization of the host adapter commuication interface.
  28 *    This is a platform dependent module for the pci cyclone board.
  29 *
  30 */
  31
  32#include <linux/kernel.h>
  33#include <linux/init.h>
  34#include <linux/types.h>
  35#include <linux/pci.h>
  36#include <linux/spinlock.h>
  37#include <linux/slab.h>
  38#include <linux/blkdev.h>
  39#include <linux/completion.h>
  40#include <linux/mm.h>
  41#include <scsi/scsi_host.h>
  42
  43#include "aacraid.h"
  44
  45struct aac_common aac_config = {
  46        .irq_mod = 1
  47};
  48
  49static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign)
  50{
  51        unsigned char *base;
  52        unsigned long size, align;
  53        const unsigned long fibsize = 4096;
  54        const unsigned long printfbufsiz = 256;
  55        struct aac_init *init;
  56        dma_addr_t phys;
  57        unsigned long aac_max_hostphysmempages;
  58
  59        size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz;
  60
  61 
  62        base = pci_alloc_consistent(dev->pdev, size, &phys);
  63
  64        if(base == NULL)
  65        {
  66                printk(KERN_ERR "aacraid: unable to create mapping.\n");
  67                return 0;
  68        }
  69        dev->comm_addr = (void *)base;
  70        dev->comm_phys = phys;
  71        dev->comm_size = size;
  72        
  73        dev->init = (struct aac_init *)(base + fibsize);
  74        dev->init_pa = phys + fibsize;
  75
  76        init = dev->init;
  77
  78        init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
  79        if (dev->max_fib_size != sizeof(struct hw_fib))
  80                init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4);
  81        init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION);
  82        init->fsrev = cpu_to_le32(dev->fsrev);
  83
  84        /*
  85         *      Adapter Fibs are the first thing allocated so that they
  86         *      start page aligned
  87         */
  88        dev->aif_base_va = (struct hw_fib *)base;
  89        
  90        init->AdapterFibsVirtualAddress = 0;
  91        init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys);
  92        init->AdapterFibsSize = cpu_to_le32(fibsize);
  93        init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
  94        /*
  95         * number of 4k pages of host physical memory. The aacraid fw needs
  96         * this number to be less than 4gb worth of pages. New firmware doesn't
  97         * have any issues with the mapping system, but older Firmware did, and
  98         * had *troubles* dealing with the math overloading past 32 bits, thus
  99         * we must limit this field.
 100         */
 101        aac_max_hostphysmempages = dma_get_required_mask(&dev->pdev->dev) >> 12;
 102        if (aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES)
 103                init->HostPhysMemPages = cpu_to_le32(aac_max_hostphysmempages);
 104        else
 105                init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
 106
 107        init->InitFlags = 0;
 108        if (dev->comm_interface == AAC_COMM_MESSAGE) {
 109                init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
 110                dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
 111        }
 112        init->InitFlags |= cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME |
 113                                       INITFLAGS_DRIVER_SUPPORTS_PM);
 114        init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
 115        init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
 116        init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
 117
 118        /*
 119         * Increment the base address by the amount already used
 120         */
 121        base = base + fibsize + sizeof(struct aac_init);
 122        phys = (dma_addr_t)((ulong)phys + fibsize + sizeof(struct aac_init));
 123        /*
 124         *      Align the beginning of Headers to commalign
 125         */
 126        align = (commalign - ((uintptr_t)(base) & (commalign - 1)));
 127        base = base + align;
 128        phys = phys + align;
 129        /*
 130         *      Fill in addresses of the Comm Area Headers and Queues
 131         */
 132        *commaddr = base;
 133        init->CommHeaderAddress = cpu_to_le32((u32)phys);
 134        /*
 135         *      Increment the base address by the size of the CommArea
 136         */
 137        base = base + commsize;
 138        phys = phys + commsize;
 139        /*
 140         *       Place the Printf buffer area after the Fast I/O comm area.
 141         */
 142        dev->printfbuf = (void *)base;
 143        init->printfbuf = cpu_to_le32(phys);
 144        init->printfbufsiz = cpu_to_le32(printfbufsiz);
 145        memset(base, 0, printfbufsiz);
 146        return 1;
 147}
 148    
 149static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize)
 150{
 151        q->numpending = 0;
 152        q->dev = dev;
 153        init_waitqueue_head(&q->cmdready);
 154        INIT_LIST_HEAD(&q->cmdq);
 155        init_waitqueue_head(&q->qfull);
 156        spin_lock_init(&q->lockdata);
 157        q->lock = &q->lockdata;
 158        q->headers.producer = (__le32 *)mem;
 159        q->headers.consumer = (__le32 *)(mem+1);
 160        *(q->headers.producer) = cpu_to_le32(qsize);
 161        *(q->headers.consumer) = cpu_to_le32(qsize);
 162        q->entries = qsize;
 163}
 164
 165/**
 166 *      aac_send_shutdown               -       shutdown an adapter
 167 *      @dev: Adapter to shutdown
 168 *
 169 *      This routine will send a VM_CloseAll (shutdown) request to the adapter.
 170 */
 171
 172int aac_send_shutdown(struct aac_dev * dev)
 173{
 174        struct fib * fibctx;
 175        struct aac_close *cmd;
 176        int status;
 177
 178        fibctx = aac_fib_alloc(dev);
 179        if (!fibctx)
 180                return -ENOMEM;
 181        aac_fib_init(fibctx);
 182
 183        cmd = (struct aac_close *) fib_data(fibctx);
 184
 185        cmd->command = cpu_to_le32(VM_CloseAll);
 186        cmd->cid = cpu_to_le32(0xffffffff);
 187
 188        status = aac_fib_send(ContainerCommand,
 189                          fibctx,
 190                          sizeof(struct aac_close),
 191                          FsaNormal,
 192                          -2 /* Timeout silently */, 1,
 193                          NULL, NULL);
 194
 195        if (status >= 0)
 196                aac_fib_complete(fibctx);
 197        aac_fib_free(fibctx);
 198        return status;
 199}
 200
 201/**
 202 *      aac_comm_init   -       Initialise FSA data structures
 203 *      @dev:   Adapter to initialise
 204 *
 205 *      Initializes the data structures that are required for the FSA commuication
 206 *      interface to operate. 
 207 *      Returns
 208 *              1 - if we were able to init the commuication interface.
 209 *              0 - If there were errors initing. This is a fatal error.
 210 */
 211 
 212static int aac_comm_init(struct aac_dev * dev)
 213{
 214        unsigned long hdrsize = (sizeof(u32) * NUMBER_OF_COMM_QUEUES) * 2;
 215        unsigned long queuesize = sizeof(struct aac_entry) * TOTAL_QUEUE_ENTRIES;
 216        u32 *headers;
 217        struct aac_entry * queues;
 218        unsigned long size;
 219        struct aac_queue_block * comm = dev->queues;
 220        /*
 221         *      Now allocate and initialize the zone structures used as our 
 222         *      pool of FIB context records.  The size of the zone is based
 223         *      on the system memory size.  We also initialize the mutex used
 224         *      to protect the zone.
 225         */
 226        spin_lock_init(&dev->fib_lock);
 227
 228        /*
 229         *      Allocate the physically contigous space for the commuication
 230         *      queue headers. 
 231         */
 232
 233        size = hdrsize + queuesize;
 234
 235        if (!aac_alloc_comm(dev, (void * *)&headers, size, QUEUE_ALIGNMENT))
 236                return -ENOMEM;
 237
 238        queues = (struct aac_entry *)(((ulong)headers) + hdrsize);
 239
 240        /* Adapter to Host normal priority Command queue */ 
 241        comm->queue[HostNormCmdQueue].base = queues;
 242        aac_queue_init(dev, &comm->queue[HostNormCmdQueue], headers, HOST_NORM_CMD_ENTRIES);
 243        queues += HOST_NORM_CMD_ENTRIES;
 244        headers += 2;
 245
 246        /* Adapter to Host high priority command queue */
 247        comm->queue[HostHighCmdQueue].base = queues;
 248        aac_queue_init(dev, &comm->queue[HostHighCmdQueue], headers, HOST_HIGH_CMD_ENTRIES);
 249    
 250        queues += HOST_HIGH_CMD_ENTRIES;
 251        headers +=2;
 252
 253        /* Host to adapter normal priority command queue */
 254        comm->queue[AdapNormCmdQueue].base = queues;
 255        aac_queue_init(dev, &comm->queue[AdapNormCmdQueue], headers, ADAP_NORM_CMD_ENTRIES);
 256    
 257        queues += ADAP_NORM_CMD_ENTRIES;
 258        headers += 2;
 259
 260        /* host to adapter high priority command queue */
 261        comm->queue[AdapHighCmdQueue].base = queues;
 262        aac_queue_init(dev, &comm->queue[AdapHighCmdQueue], headers, ADAP_HIGH_CMD_ENTRIES);
 263    
 264        queues += ADAP_HIGH_CMD_ENTRIES;
 265        headers += 2;
 266
 267        /* adapter to host normal priority response queue */
 268        comm->queue[HostNormRespQueue].base = queues;
 269        aac_queue_init(dev, &comm->queue[HostNormRespQueue], headers, HOST_NORM_RESP_ENTRIES);
 270        queues += HOST_NORM_RESP_ENTRIES;
 271        headers += 2;
 272
 273        /* adapter to host high priority response queue */
 274        comm->queue[HostHighRespQueue].base = queues;
 275        aac_queue_init(dev, &comm->queue[HostHighRespQueue], headers, HOST_HIGH_RESP_ENTRIES);
 276   
 277        queues += HOST_HIGH_RESP_ENTRIES;
 278        headers += 2;
 279
 280        /* host to adapter normal priority response queue */
 281        comm->queue[AdapNormRespQueue].base = queues;
 282        aac_queue_init(dev, &comm->queue[AdapNormRespQueue], headers, ADAP_NORM_RESP_ENTRIES);
 283
 284        queues += ADAP_NORM_RESP_ENTRIES;
 285        headers += 2;
 286        
 287        /* host to adapter high priority response queue */ 
 288        comm->queue[AdapHighRespQueue].base = queues;
 289        aac_queue_init(dev, &comm->queue[AdapHighRespQueue], headers, ADAP_HIGH_RESP_ENTRIES);
 290
 291        comm->queue[AdapNormCmdQueue].lock = comm->queue[HostNormRespQueue].lock;
 292        comm->queue[AdapHighCmdQueue].lock = comm->queue[HostHighRespQueue].lock;
 293        comm->queue[AdapNormRespQueue].lock = comm->queue[HostNormCmdQueue].lock;
 294        comm->queue[AdapHighRespQueue].lock = comm->queue[HostHighCmdQueue].lock;
 295
 296        return 0;
 297}
 298
 299struct aac_dev *aac_init_adapter(struct aac_dev *dev)
 300{
 301        u32 status[5];
 302        struct Scsi_Host * host = dev->scsi_host_ptr;
 303
 304        /*
 305         *      Check the preferred comm settings, defaults from template.
 306         */
 307        dev->max_fib_size = sizeof(struct hw_fib);
 308        dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
 309                - sizeof(struct aac_fibhdr)
 310                - sizeof(struct aac_write) + sizeof(struct sgentry))
 311                        / sizeof(struct sgentry);
 312        dev->comm_interface = AAC_COMM_PRODUCER;
 313        dev->raw_io_64 = 0;
 314        if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
 315                0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
 316                        (status[0] == 0x00000001)) {
 317                if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64))
 318                        dev->raw_io_64 = 1;
 319                if (dev->a_ops.adapter_comm &&
 320                    (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM)))
 321                        dev->comm_interface = AAC_COMM_MESSAGE;
 322                if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
 323                    (status[2] > dev->base_size)) {
 324                        aac_adapter_ioremap(dev, 0);
 325                        dev->base_size = status[2];
 326                        if (aac_adapter_ioremap(dev, status[2])) {
 327                                /* remap failed, go back ... */
 328                                dev->comm_interface = AAC_COMM_PRODUCER;
 329                                if (aac_adapter_ioremap(dev, AAC_MIN_FOOTPRINT_SIZE)) {
 330                                        printk(KERN_WARNING
 331                                          "aacraid: unable to map adapter.\n");
 332                                        return NULL;
 333                                }
 334                        }
 335                }
 336        }
 337        if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
 338          0, 0, 0, 0, 0, 0,
 339          status+0, status+1, status+2, status+3, status+4))
 340         && (status[0] == 0x00000001)) {
 341                /*
 342                 *      status[1] >> 16         maximum command size in KB
 343                 *      status[1] & 0xFFFF      maximum FIB size
 344                 *      status[2] >> 16         maximum SG elements to driver
 345                 *      status[2] & 0xFFFF      maximum SG elements from driver
 346                 *      status[3] & 0xFFFF      maximum number FIBs outstanding
 347                 */
 348                host->max_sectors = (status[1] >> 16) << 1;
 349                dev->max_fib_size = status[1] & 0xFFFF;
 350                host->sg_tablesize = status[2] >> 16;
 351                dev->sg_tablesize = status[2] & 0xFFFF;
 352                host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
 353                /*
 354                 *      NOTE:
 355                 *      All these overrides are based on a fixed internal
 356                 *      knowledge and understanding of existing adapters,
 357                 *      acbsize should be set with caution.
 358                 */
 359                if (acbsize == 512) {
 360                        host->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
 361                        dev->max_fib_size = 512;
 362                        dev->sg_tablesize = host->sg_tablesize
 363                          = (512 - sizeof(struct aac_fibhdr)
 364                            - sizeof(struct aac_write) + sizeof(struct sgentry))
 365                             / sizeof(struct sgentry);
 366                        host->can_queue = AAC_NUM_IO_FIB;
 367                } else if (acbsize == 2048) {
 368                        host->max_sectors = 512;
 369                        dev->max_fib_size = 2048;
 370                        host->sg_tablesize = 65;
 371                        dev->sg_tablesize = 81;
 372                        host->can_queue = 512 - AAC_NUM_MGT_FIB;
 373                } else if (acbsize == 4096) {
 374                        host->max_sectors = 1024;
 375                        dev->max_fib_size = 4096;
 376                        host->sg_tablesize = 129;
 377                        dev->sg_tablesize = 166;
 378                        host->can_queue = 256 - AAC_NUM_MGT_FIB;
 379                } else if (acbsize == 8192) {
 380                        host->max_sectors = 2048;
 381                        dev->max_fib_size = 8192;
 382                        host->sg_tablesize = 257;
 383                        dev->sg_tablesize = 337;
 384                        host->can_queue = 128 - AAC_NUM_MGT_FIB;
 385                } else if (acbsize > 0) {
 386                        printk("Illegal acbsize=%d ignored\n", acbsize);
 387                }
 388        }
 389        {
 390
 391                if (numacb > 0) {
 392                        if (numacb < host->can_queue)
 393                                host->can_queue = numacb;
 394                        else
 395                                printk("numacb=%d ignored\n", numacb);
 396                }
 397        }
 398
 399        /*
 400         *      Ok now init the communication subsystem
 401         */
 402
 403        dev->queues = kzalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
 404        if (dev->queues == NULL) {
 405                printk(KERN_ERR "Error could not allocate comm region.\n");
 406                return NULL;
 407        }
 408
 409        if (aac_comm_init(dev)<0){
 410                kfree(dev->queues);
 411                return NULL;
 412        }
 413        /*
 414         *      Initialize the list of fibs
 415         */
 416        if (aac_fib_setup(dev) < 0) {
 417                kfree(dev->queues);
 418                return NULL;
 419        }
 420                
 421        INIT_LIST_HEAD(&dev->fib_list);
 422
 423        return dev;
 424}
 425
 426    
 427