Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Adaptec AAC series RAID controller driver
0004  *  (c) Copyright 2001 Red Hat Inc.
0005  *
0006  * based on the old aacraid driver that is..
0007  * Adaptec aacraid device driver for Linux.
0008  *
0009  * Copyright (c) 2000-2010 Adaptec, Inc.
0010  *               2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
0011  *       2016-2017 Microsemi Corp. (aacraid@microsemi.com)
0012  *
0013  * Module Name:
0014  *  sa.c
0015  *
0016  * Abstract: Drawbridge specific support functions
0017  */
0018 
0019 #include <linux/kernel.h>
0020 #include <linux/init.h>
0021 #include <linux/types.h>
0022 #include <linux/pci.h>
0023 #include <linux/spinlock.h>
0024 #include <linux/blkdev.h>
0025 #include <linux/delay.h>
0026 #include <linux/completion.h>
0027 #include <linux/time.h>
0028 #include <linux/interrupt.h>
0029 
0030 #include <scsi/scsi_host.h>
0031 
0032 #include "aacraid.h"
0033 
0034 static irqreturn_t aac_sa_intr(int irq, void *dev_id)
0035 {
0036     struct aac_dev *dev = dev_id;
0037     unsigned short intstat, mask;
0038 
0039     intstat = sa_readw(dev, DoorbellReg_p);
0040     /*
0041      *  Read mask and invert because drawbridge is reversed.
0042      *  This allows us to only service interrupts that have been enabled.
0043      */
0044     mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK));
0045 
0046     /* Check to see if this is our interrupt.  If it isn't just return */
0047 
0048     if (intstat & mask) {
0049         if (intstat & PrintfReady) {
0050             aac_printf(dev, sa_readl(dev, Mailbox5));
0051             sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */
0052             sa_writew(dev, DoorbellReg_s, PrintfDone);
0053         } else if (intstat & DOORBELL_1) {  // dev -> Host Normal Command Ready
0054             sa_writew(dev, DoorbellClrReg_p, DOORBELL_1);
0055             aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
0056         } else if (intstat & DOORBELL_2) {  // dev -> Host Normal Response Ready
0057             sa_writew(dev, DoorbellClrReg_p, DOORBELL_2);
0058             aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
0059         } else if (intstat & DOORBELL_3) {  // dev -> Host Normal Command Not Full
0060             sa_writew(dev, DoorbellClrReg_p, DOORBELL_3);
0061         } else if (intstat & DOORBELL_4) {  // dev -> Host Normal Response Not Full
0062             sa_writew(dev, DoorbellClrReg_p, DOORBELL_4);
0063         }
0064         return IRQ_HANDLED;
0065     }
0066     return IRQ_NONE;
0067 }
0068 
0069 /**
0070  *  aac_sa_disable_interrupt    -   disable interrupt
0071  *  @dev: Which adapter to enable.
0072  */
0073 
0074 static void aac_sa_disable_interrupt (struct aac_dev *dev)
0075 {
0076     sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
0077 }
0078 
0079 /**
0080  *  aac_sa_enable_interrupt -   enable interrupt
0081  *  @dev: Which adapter to enable.
0082  */
0083 
0084 static void aac_sa_enable_interrupt (struct aac_dev *dev)
0085 {
0086     sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
0087                 DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
0088 }
0089 
0090 /**
0091  *  aac_sa_notify_adapter       -   handle adapter notification
0092  *  @dev:   Adapter that notification is for
0093  *  @event: Event to notidy
0094  *
0095  *  Notify the adapter of an event
0096  */
0097  
0098 static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
0099 {
0100     switch (event) {
0101 
0102     case AdapNormCmdQue:
0103         sa_writew(dev, DoorbellReg_s,DOORBELL_1);
0104         break;
0105     case HostNormRespNotFull:
0106         sa_writew(dev, DoorbellReg_s,DOORBELL_4);
0107         break;
0108     case AdapNormRespQue:
0109         sa_writew(dev, DoorbellReg_s,DOORBELL_2);
0110         break;
0111     case HostNormCmdNotFull:
0112         sa_writew(dev, DoorbellReg_s,DOORBELL_3);
0113         break;
0114     case HostShutdown:
0115         /*
0116         sa_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
0117         NULL, NULL, NULL, NULL, NULL);
0118         */
0119         break;
0120     case FastIo:
0121         sa_writew(dev, DoorbellReg_s,DOORBELL_6);
0122         break;
0123     case AdapPrintfDone:
0124         sa_writew(dev, DoorbellReg_s,DOORBELL_5);
0125         break;
0126     default:
0127         BUG();
0128         break;
0129     }
0130 }
0131 
0132 
0133 /**
0134  *  sa_sync_cmd -   send a command and wait
0135  *  @dev: Adapter
0136  *  @command: Command to execute
0137  *  @p1: first parameter
0138  *  @p2: second parameter
0139  *  @p3: third parameter
0140  *  @p4: forth parameter
0141  *  @p5: fifth parameter
0142  *  @p6: sixth parameter
0143  *  @ret: adapter status
0144  *  @r1: first return value
0145  *  @r2: second return value
0146  *  @r3: third return value
0147  *  @r4: forth return value
0148  *
0149  *  This routine will send a synchronous command to the adapter and wait
0150  *  for its completion.
0151  */
0152 static int sa_sync_cmd(struct aac_dev *dev, u32 command,
0153         u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
0154         u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
0155 {
0156     unsigned long start;
0157     int ok;
0158     /*
0159      *  Write the Command into Mailbox 0
0160      */
0161     sa_writel(dev, Mailbox0, command);
0162     /*
0163      *  Write the parameters into Mailboxes 1 - 4
0164      */
0165     sa_writel(dev, Mailbox1, p1);
0166     sa_writel(dev, Mailbox2, p2);
0167     sa_writel(dev, Mailbox3, p3);
0168     sa_writel(dev, Mailbox4, p4);
0169 
0170     /*
0171      *  Clear the synch command doorbell to start on a clean slate.
0172      */
0173     sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
0174     /*
0175      *  Signal that there is a new synch command
0176      */
0177     sa_writew(dev, DoorbellReg_s, DOORBELL_0);
0178 
0179     ok = 0;
0180     start = jiffies;
0181 
0182     while(time_before(jiffies, start+30*HZ))
0183     {
0184         /*
0185          *  Delay 5uS so that the monitor gets access
0186          */
0187         udelay(5);
0188         /*
0189          *  Mon110 will set doorbell0 bit when it has 
0190          *  completed the command.
0191          */
0192         if(sa_readw(dev, DoorbellReg_p) & DOORBELL_0)  {
0193             ok = 1;
0194             break;
0195         }
0196         msleep(1);
0197     }
0198 
0199     if (ok != 1)
0200         return -ETIMEDOUT;
0201     /*
0202      *  Clear the synch command doorbell.
0203      */
0204     sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
0205     /*
0206      *  Pull the synch status from Mailbox 0.
0207      */
0208     if (ret)
0209         *ret = sa_readl(dev, Mailbox0);
0210     if (r1)
0211         *r1 = sa_readl(dev, Mailbox1);
0212     if (r2)
0213         *r2 = sa_readl(dev, Mailbox2);
0214     if (r3)
0215         *r3 = sa_readl(dev, Mailbox3);
0216     if (r4)
0217         *r4 = sa_readl(dev, Mailbox4);
0218     return 0;
0219 }
0220 
0221 /**
0222  *  aac_sa_interrupt_adapter    -   interrupt an adapter
0223  *  @dev: Which adapter to enable.
0224  *
0225  *  Breakpoint an adapter.
0226  */
0227  
0228 static void aac_sa_interrupt_adapter (struct aac_dev *dev)
0229 {
0230     sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
0231             NULL, NULL, NULL, NULL, NULL);
0232 }
0233 
0234 /**
0235  *  aac_sa_start_adapter        -   activate adapter
0236  *  @dev:   Adapter
0237  *
0238  *  Start up processing on an ARM based AAC adapter
0239  */
0240 
0241 static void aac_sa_start_adapter(struct aac_dev *dev)
0242 {
0243     union aac_init *init;
0244     /*
0245      * Fill in the remaining pieces of the init.
0246      */
0247     init = dev->init;
0248     init->r7.host_elapsed_seconds = cpu_to_le32(ktime_get_real_seconds());
0249     /* We can only use a 32 bit address here */
0250     sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, 
0251             (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
0252             NULL, NULL, NULL, NULL, NULL);
0253 }
0254 
0255 static int aac_sa_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
0256 {
0257     return -EINVAL;
0258 }
0259 
0260 /**
0261  *  aac_sa_check_health
0262  *  @dev: device to check if healthy
0263  *
0264  *  Will attempt to determine if the specified adapter is alive and
0265  *  capable of handling requests, returning 0 if alive.
0266  */
0267 static int aac_sa_check_health(struct aac_dev *dev)
0268 {
0269     long status = sa_readl(dev, Mailbox7);
0270 
0271     /*
0272      *  Check to see if the board failed any self tests.
0273      */
0274     if (status & SELF_TEST_FAILED)
0275         return -1;
0276     /*
0277      *  Check to see if the board panic'd while booting.
0278      */
0279     if (status & KERNEL_PANIC)
0280         return -2;
0281     /*
0282      *  Wait for the adapter to be up and running. Wait up to 3 minutes
0283      */
0284     if (!(status & KERNEL_UP_AND_RUNNING))
0285         return -3;
0286     /*
0287      *  Everything is OK
0288      */
0289     return 0;
0290 }
0291 
0292 /**
0293  *  aac_sa_ioremap
0294  *  @dev: device to ioremap
0295  *  @size: mapping resize request
0296  *
0297  */
0298 static int aac_sa_ioremap(struct aac_dev * dev, u32 size)
0299 {
0300     if (!size) {
0301         iounmap(dev->regs.sa);
0302         return 0;
0303     }
0304     dev->base = dev->regs.sa = ioremap(dev->base_start, size);
0305     return (dev->base == NULL) ? -1 : 0;
0306 }
0307 
0308 /**
0309  *  aac_sa_init -   initialize an ARM based AAC card
0310  *  @dev: device to configure
0311  *
0312  *  Allocate and set up resources for the ARM based AAC variants. The
0313  *  device_interface in the commregion will be allocated and linked
0314  *  to the comm region.
0315  */
0316 
0317 int aac_sa_init(struct aac_dev *dev)
0318 {
0319     unsigned long start;
0320     unsigned long status;
0321     int instance;
0322     const char *name;
0323 
0324     instance = dev->id;
0325     name     = dev->name;
0326 
0327     /*
0328      *  Fill in the function dispatch table.
0329      */
0330 
0331     dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
0332     dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
0333     dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt;
0334     dev->a_ops.adapter_notify = aac_sa_notify_adapter;
0335     dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
0336     dev->a_ops.adapter_check_health = aac_sa_check_health;
0337     dev->a_ops.adapter_restart = aac_sa_restart_adapter;
0338     dev->a_ops.adapter_start = aac_sa_start_adapter;
0339     dev->a_ops.adapter_intr = aac_sa_intr;
0340     dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
0341     dev->a_ops.adapter_ioremap = aac_sa_ioremap;
0342 
0343     if (aac_sa_ioremap(dev, dev->base_size)) {
0344         printk(KERN_WARNING "%s: unable to map adapter.\n", name);
0345         goto error_iounmap;
0346     }
0347 
0348     /*
0349      *  Check to see if the board failed any self tests.
0350      */
0351     if (sa_readl(dev, Mailbox7) & SELF_TEST_FAILED) {
0352         printk(KERN_WARNING "%s%d: adapter self-test failed.\n", name, instance);
0353         goto error_iounmap;
0354     }
0355     /*
0356      *  Check to see if the board panic'd while booting.
0357      */
0358     if (sa_readl(dev, Mailbox7) & KERNEL_PANIC) {
0359         printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n", name, instance);
0360         goto error_iounmap;
0361     }
0362     start = jiffies;
0363     /*
0364      *  Wait for the adapter to be up and running. Wait up to 3 minutes.
0365      */
0366     while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
0367         if (time_after(jiffies, start+startup_timeout*HZ)) {
0368             status = sa_readl(dev, Mailbox7);
0369             printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n", 
0370                     name, instance, status);
0371             goto error_iounmap;
0372         }
0373         msleep(1);
0374     }
0375 
0376     /*
0377      *  First clear out all interrupts.  Then enable the one's that 
0378      *  we can handle.
0379      */
0380     aac_adapter_disable_int(dev);
0381     aac_adapter_enable_int(dev);
0382 
0383     if(aac_init_adapter(dev) == NULL)
0384         goto error_irq;
0385     dev->sync_mode = 0; /* sync. mode not supported */
0386     if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
0387             IRQF_SHARED, "aacraid", (void *)dev) < 0) {
0388         printk(KERN_WARNING "%s%d: Interrupt unavailable.\n",
0389             name, instance);
0390         goto error_iounmap;
0391     }
0392     dev->dbg_base = dev->base_start;
0393     dev->dbg_base_mapped = dev->base;
0394     dev->dbg_size = dev->base_size;
0395 
0396     aac_adapter_enable_int(dev);
0397 
0398     /*
0399      *  Tell the adapter that all is configure, and it can start 
0400      *  accepting requests
0401      */
0402     aac_sa_start_adapter(dev);
0403     return 0;
0404 
0405 error_irq:
0406     aac_sa_disable_interrupt(dev);
0407     free_irq(dev->pdev->irq, (void *)dev);
0408 
0409 error_iounmap:
0410 
0411     return -1;
0412 }
0413