root/drivers/scsi/aacraid/sa.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. aac_sa_intr
  2. aac_sa_disable_interrupt
  3. aac_sa_enable_interrupt
  4. aac_sa_notify_adapter
  5. sa_sync_cmd
  6. aac_sa_interrupt_adapter
  7. aac_sa_start_adapter
  8. aac_sa_restart_adapter
  9. aac_sa_check_health
  10. aac_sa_ioremap
  11. aac_sa_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *      Adaptec AAC series RAID controller driver
   4  *      (c) Copyright 2001 Red Hat Inc.
   5  *
   6  * based on the old aacraid driver that is..
   7  * Adaptec aacraid device driver for Linux.
   8  *
   9  * Copyright (c) 2000-2010 Adaptec, Inc.
  10  *               2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
  11  *               2016-2017 Microsemi Corp. (aacraid@microsemi.com)
  12  *
  13  * Module Name:
  14  *  sa.c
  15  *
  16  * Abstract: Drawbridge specific support functions
  17  */
  18 
  19 #include <linux/kernel.h>
  20 #include <linux/init.h>
  21 #include <linux/types.h>
  22 #include <linux/pci.h>
  23 #include <linux/spinlock.h>
  24 #include <linux/blkdev.h>
  25 #include <linux/delay.h>
  26 #include <linux/completion.h>
  27 #include <linux/time.h>
  28 #include <linux/interrupt.h>
  29 
  30 #include <scsi/scsi_host.h>
  31 
  32 #include "aacraid.h"
  33 
  34 static irqreturn_t aac_sa_intr(int irq, void *dev_id)
  35 {
  36         struct aac_dev *dev = dev_id;
  37         unsigned short intstat, mask;
  38 
  39         intstat = sa_readw(dev, DoorbellReg_p);
  40         /*
  41          *      Read mask and invert because drawbridge is reversed.
  42          *      This allows us to only service interrupts that have been enabled.
  43          */
  44         mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK));
  45 
  46         /* Check to see if this is our interrupt.  If it isn't just return */
  47 
  48         if (intstat & mask) {
  49                 if (intstat & PrintfReady) {
  50                         aac_printf(dev, sa_readl(dev, Mailbox5));
  51                         sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */
  52                         sa_writew(dev, DoorbellReg_s, PrintfDone);
  53                 } else if (intstat & DOORBELL_1) {      // dev -> Host Normal Command Ready
  54                         sa_writew(dev, DoorbellClrReg_p, DOORBELL_1);
  55                         aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
  56                 } else if (intstat & DOORBELL_2) {      // dev -> Host Normal Response Ready
  57                         sa_writew(dev, DoorbellClrReg_p, DOORBELL_2);
  58                         aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
  59                 } else if (intstat & DOORBELL_3) {      // dev -> Host Normal Command Not Full
  60                         sa_writew(dev, DoorbellClrReg_p, DOORBELL_3);
  61                 } else if (intstat & DOORBELL_4) {      // dev -> Host Normal Response Not Full
  62                         sa_writew(dev, DoorbellClrReg_p, DOORBELL_4);
  63                 }
  64                 return IRQ_HANDLED;
  65         }
  66         return IRQ_NONE;
  67 }
  68 
  69 /**
  70  *      aac_sa_disable_interrupt        -       disable interrupt
  71  *      @dev: Which adapter to enable.
  72  */
  73 
  74 static void aac_sa_disable_interrupt (struct aac_dev *dev)
  75 {
  76         sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
  77 }
  78 
  79 /**
  80  *      aac_sa_enable_interrupt -       enable interrupt
  81  *      @dev: Which adapter to enable.
  82  */
  83 
  84 static void aac_sa_enable_interrupt (struct aac_dev *dev)
  85 {
  86         sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
  87                                 DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
  88 }
  89 
  90 /**
  91  *      aac_sa_notify_adapter           -       handle adapter notification
  92  *      @dev:   Adapter that notification is for
  93  *      @event: Event to notidy
  94  *
  95  *      Notify the adapter of an event
  96  */
  97  
  98 static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
  99 {
 100         switch (event) {
 101 
 102         case AdapNormCmdQue:
 103                 sa_writew(dev, DoorbellReg_s,DOORBELL_1);
 104                 break;
 105         case HostNormRespNotFull:
 106                 sa_writew(dev, DoorbellReg_s,DOORBELL_4);
 107                 break;
 108         case AdapNormRespQue:
 109                 sa_writew(dev, DoorbellReg_s,DOORBELL_2);
 110                 break;
 111         case HostNormCmdNotFull:
 112                 sa_writew(dev, DoorbellReg_s,DOORBELL_3);
 113                 break;
 114         case HostShutdown:
 115                 /*
 116                 sa_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
 117                 NULL, NULL, NULL, NULL, NULL);
 118                 */
 119                 break;
 120         case FastIo:
 121                 sa_writew(dev, DoorbellReg_s,DOORBELL_6);
 122                 break;
 123         case AdapPrintfDone:
 124                 sa_writew(dev, DoorbellReg_s,DOORBELL_5);
 125                 break;
 126         default:
 127                 BUG();
 128                 break;
 129         }
 130 }
 131 
 132 
 133 /**
 134  *      sa_sync_cmd     -       send a command and wait
 135  *      @dev: Adapter
 136  *      @command: Command to execute
 137  *      @p1: first parameter
 138  *      @ret: adapter status
 139  *
 140  *      This routine will send a synchronous command to the adapter and wait 
 141  *      for its completion.
 142  */
 143 
 144 static int sa_sync_cmd(struct aac_dev *dev, u32 command, 
 145                 u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
 146                 u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
 147 {
 148         unsigned long start;
 149         int ok;
 150         /*
 151          *      Write the Command into Mailbox 0
 152          */
 153         sa_writel(dev, Mailbox0, command);
 154         /*
 155          *      Write the parameters into Mailboxes 1 - 4
 156          */
 157         sa_writel(dev, Mailbox1, p1);
 158         sa_writel(dev, Mailbox2, p2);
 159         sa_writel(dev, Mailbox3, p3);
 160         sa_writel(dev, Mailbox4, p4);
 161 
 162         /*
 163          *      Clear the synch command doorbell to start on a clean slate.
 164          */
 165         sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
 166         /*
 167          *      Signal that there is a new synch command
 168          */
 169         sa_writew(dev, DoorbellReg_s, DOORBELL_0);
 170 
 171         ok = 0;
 172         start = jiffies;
 173 
 174         while(time_before(jiffies, start+30*HZ))
 175         {
 176                 /*
 177                  *      Delay 5uS so that the monitor gets access
 178                  */
 179                 udelay(5);
 180                 /*
 181                  *      Mon110 will set doorbell0 bit when it has 
 182                  *      completed the command.
 183                  */
 184                 if(sa_readw(dev, DoorbellReg_p) & DOORBELL_0)  {
 185                         ok = 1;
 186                         break;
 187                 }
 188                 msleep(1);
 189         }
 190 
 191         if (ok != 1)
 192                 return -ETIMEDOUT;
 193         /*
 194          *      Clear the synch command doorbell.
 195          */
 196         sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
 197         /*
 198          *      Pull the synch status from Mailbox 0.
 199          */
 200         if (ret)
 201                 *ret = sa_readl(dev, Mailbox0);
 202         if (r1)
 203                 *r1 = sa_readl(dev, Mailbox1);
 204         if (r2)
 205                 *r2 = sa_readl(dev, Mailbox2);
 206         if (r3)
 207                 *r3 = sa_readl(dev, Mailbox3);
 208         if (r4)
 209                 *r4 = sa_readl(dev, Mailbox4);
 210         return 0;
 211 }
 212 
 213 /**
 214  *      aac_sa_interrupt_adapter        -       interrupt an adapter
 215  *      @dev: Which adapter to enable.
 216  *
 217  *      Breakpoint an adapter.
 218  */
 219  
 220 static void aac_sa_interrupt_adapter (struct aac_dev *dev)
 221 {
 222         sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
 223                         NULL, NULL, NULL, NULL, NULL);
 224 }
 225 
 226 /**
 227  *      aac_sa_start_adapter            -       activate adapter
 228  *      @dev:   Adapter
 229  *
 230  *      Start up processing on an ARM based AAC adapter
 231  */
 232 
 233 static void aac_sa_start_adapter(struct aac_dev *dev)
 234 {
 235         union aac_init *init;
 236         /*
 237          * Fill in the remaining pieces of the init.
 238          */
 239         init = dev->init;
 240         init->r7.host_elapsed_seconds = cpu_to_le32(ktime_get_real_seconds());
 241         /* We can only use a 32 bit address here */
 242         sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, 
 243                         (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
 244                         NULL, NULL, NULL, NULL, NULL);
 245 }
 246 
 247 static int aac_sa_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
 248 {
 249         return -EINVAL;
 250 }
 251 
 252 /**
 253  *      aac_sa_check_health
 254  *      @dev: device to check if healthy
 255  *
 256  *      Will attempt to determine if the specified adapter is alive and
 257  *      capable of handling requests, returning 0 if alive.
 258  */
 259 static int aac_sa_check_health(struct aac_dev *dev)
 260 {
 261         long status = sa_readl(dev, Mailbox7);
 262 
 263         /*
 264          *      Check to see if the board failed any self tests.
 265          */
 266         if (status & SELF_TEST_FAILED)
 267                 return -1;
 268         /*
 269          *      Check to see if the board panic'd while booting.
 270          */
 271         if (status & KERNEL_PANIC)
 272                 return -2;
 273         /*
 274          *      Wait for the adapter to be up and running. Wait up to 3 minutes
 275          */
 276         if (!(status & KERNEL_UP_AND_RUNNING))
 277                 return -3;
 278         /*
 279          *      Everything is OK
 280          */
 281         return 0;
 282 }
 283 
 284 /**
 285  *      aac_sa_ioremap
 286  *      @size: mapping resize request
 287  *
 288  */
 289 static int aac_sa_ioremap(struct aac_dev * dev, u32 size)
 290 {
 291         if (!size) {
 292                 iounmap(dev->regs.sa);
 293                 return 0;
 294         }
 295         dev->base = dev->regs.sa = ioremap(dev->base_start, size);
 296         return (dev->base == NULL) ? -1 : 0;
 297 }
 298 
 299 /**
 300  *      aac_sa_init     -       initialize an ARM based AAC card
 301  *      @dev: device to configure
 302  *
 303  *      Allocate and set up resources for the ARM based AAC variants. The 
 304  *      device_interface in the commregion will be allocated and linked 
 305  *      to the comm region.
 306  */
 307 
 308 int aac_sa_init(struct aac_dev *dev)
 309 {
 310         unsigned long start;
 311         unsigned long status;
 312         int instance;
 313         const char *name;
 314 
 315         instance = dev->id;
 316         name     = dev->name;
 317 
 318         /*
 319          *      Fill in the function dispatch table.
 320          */
 321 
 322         dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
 323         dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
 324         dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt;
 325         dev->a_ops.adapter_notify = aac_sa_notify_adapter;
 326         dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
 327         dev->a_ops.adapter_check_health = aac_sa_check_health;
 328         dev->a_ops.adapter_restart = aac_sa_restart_adapter;
 329         dev->a_ops.adapter_start = aac_sa_start_adapter;
 330         dev->a_ops.adapter_intr = aac_sa_intr;
 331         dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
 332         dev->a_ops.adapter_ioremap = aac_sa_ioremap;
 333 
 334         if (aac_sa_ioremap(dev, dev->base_size)) {
 335                 printk(KERN_WARNING "%s: unable to map adapter.\n", name);
 336                 goto error_iounmap;
 337         }
 338 
 339         /*
 340          *      Check to see if the board failed any self tests.
 341          */
 342         if (sa_readl(dev, Mailbox7) & SELF_TEST_FAILED) {
 343                 printk(KERN_WARNING "%s%d: adapter self-test failed.\n", name, instance);
 344                 goto error_iounmap;
 345         }
 346         /*
 347          *      Check to see if the board panic'd while booting.
 348          */
 349         if (sa_readl(dev, Mailbox7) & KERNEL_PANIC) {
 350                 printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n", name, instance);
 351                 goto error_iounmap;
 352         }
 353         start = jiffies;
 354         /*
 355          *      Wait for the adapter to be up and running. Wait up to 3 minutes.
 356          */
 357         while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
 358                 if (time_after(jiffies, start+startup_timeout*HZ)) {
 359                         status = sa_readl(dev, Mailbox7);
 360                         printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n", 
 361                                         name, instance, status);
 362                         goto error_iounmap;
 363                 }
 364                 msleep(1);
 365         }
 366 
 367         /*
 368          *      First clear out all interrupts.  Then enable the one's that 
 369          *      we can handle.
 370          */
 371         aac_adapter_disable_int(dev);
 372         aac_adapter_enable_int(dev);
 373 
 374         if(aac_init_adapter(dev) == NULL)
 375                 goto error_irq;
 376         dev->sync_mode = 0;     /* sync. mode not supported */
 377         if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
 378                         IRQF_SHARED, "aacraid", (void *)dev) < 0) {
 379                 printk(KERN_WARNING "%s%d: Interrupt unavailable.\n",
 380                         name, instance);
 381                 goto error_iounmap;
 382         }
 383         dev->dbg_base = dev->base_start;
 384         dev->dbg_base_mapped = dev->base;
 385         dev->dbg_size = dev->base_size;
 386 
 387         aac_adapter_enable_int(dev);
 388 
 389         /*
 390          *      Tell the adapter that all is configure, and it can start 
 391          *      accepting requests
 392          */
 393         aac_sa_start_adapter(dev);
 394         return 0;
 395 
 396 error_irq:
 397         aac_sa_disable_interrupt(dev);
 398         free_irq(dev->pdev->irq, (void *)dev);
 399 
 400 error_iounmap:
 401 
 402         return -1;
 403 }
 404 

/* [<][>][^][v][top][bottom][index][help] */