11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adaptec AAC series RAID controller driver 3fa195afe4ad3f6d85a9b7cc236ae85c05ca8db03Alan Cox * (c) Copyright 2001 Red Hat Inc. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * based on the old aacraid driver that is.. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adaptec aacraid device driver for Linux. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara * Copyright (c) 2000-2010 Adaptec, Inc. 9e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * any later version. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; see the file COPYING. If not, write to 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Module Name: 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * commsup.c 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Abstract: Contain all routines that are required for FSA host/adapter 297c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp * communication. 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/completion.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 42164006da316a22eaaa9fbe36f835a01606436c66Al Viro#include <linux/delay.h> 43fe27381d16c6683c55e618360d0d11bd43647e43Christoph Hellwig#include <linux/kthread.h> 446a3670c4f1b97373425340ab2dc0a66c25983d46Al Viro#include <linux/interrupt.h> 456188e10d38b8d7244ee7776d5f1f88c837b4b93fMatthew Wilcox#include <linux/semaphore.h> 468c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp#include <scsi/scsi.h> 477c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp#include <scsi/scsi_host.h> 48131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp#include <scsi/scsi_device.h> 498c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp#include <scsi/scsi_cmnd.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "aacraid.h" 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fib_map_alloc - allocate the fib objects 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter to allocate for 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate and map the shared PCI space for the FIB blocks used to 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * talk to the Adaptec firmware. 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 608ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fib_map_alloc(struct aac_dev *dev) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 637c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp dprintk((KERN_INFO 647c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n", 657c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue, 667c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp AAC_NUM_MGT_FIB, &dev->hw_fib_pa)); 67e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara dev->hw_fib_va = pci_alloc_consistent(dev->pdev, 68e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara (dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) 69e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) + (ALIGN32 - 1), 70e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara &dev->hw_fib_pa); 71e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara if (dev->hw_fib_va == NULL) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 77bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp * aac_fib_map_free - free the fib objects 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter to free 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free the PCI mappings and the memory allocated for FIB blocks 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * on this adapter. 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 84bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkampvoid aac_fib_map_free(struct aac_dev *dev) 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 869ad5204d68a3b48b92907d88d1c28d33fde6ba2aSalyzyn, Mark pci_free_consistent(dev->pdev, 879ad5204d68a3b48b92907d88d1c28d33fde6ba2aSalyzyn, Mark dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), 889ad5204d68a3b48b92907d88d1c28d33fde6ba2aSalyzyn, Mark dev->hw_fib_va, dev->hw_fib_pa); 899ad5204d68a3b48b92907d88d1c28d33fde6ba2aSalyzyn, Mark dev->hw_fib_va = NULL; 909ad5204d68a3b48b92907d88d1c28d33fde6ba2aSalyzyn, Mark dev->hw_fib_pa = 0; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 94bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp * aac_fib_setup - setup the fibs 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter to set up 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 97b595076a180a56d1bb170e6eceda6eb9d76f4cd3Uwe Kleine-König * Allocate the PCI space for the fibs, map it and then initialise the 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fib area, the unmapped fib data and also the free list 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkampint aac_fib_setup(struct aac_dev * dev) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fib *fibptr; 104a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp struct hw_fib *hw_fib; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t hw_fib_pa; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1077c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp 1087c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp while (((i = fib_map_alloc(dev)) == -ENOMEM) 1097c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp && (dev->scsi_host_ptr->can_queue > (64 - AAC_NUM_MGT_FIB))) { 1107c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp dev->init->MaxIoCommands = cpu_to_le32((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) >> 1); 1117c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp dev->scsi_host_ptr->can_queue = le32_to_cpu(dev->init->MaxIoCommands) - AAC_NUM_MGT_FIB; 1127c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp } 1137c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp if (i<0) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1158ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 116e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara /* 32 byte alignment for PMC */ 117e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara hw_fib_pa = (dev->hw_fib_pa + (ALIGN32 - 1)) & ~(ALIGN32 - 1); 118e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va + 119e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara (hw_fib_pa - dev->hw_fib_pa)); 120e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara dev->hw_fib_pa = hw_fib_pa; 121e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara memset(dev->hw_fib_va, 0, 122e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara (dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) * 123e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)); 124e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara 125e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara /* add Xport header */ 126e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va + 127e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara sizeof(struct aac_fib_xporthdr)); 128e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara dev->hw_fib_pa += sizeof(struct aac_fib_xporthdr); 129e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara 130a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp hw_fib = dev->hw_fib_va; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib_pa = dev->hw_fib_pa; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialise the fibs 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1358ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark for (i = 0, fibptr = &dev->fibs[i]; 1368ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); 1378ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark i++, fibptr++) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->dev = dev; 140a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp fibptr->hw_fib_va = hw_fib; 141a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp fibptr->data = (void *) fibptr->hw_fib_va->data; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->next = fibptr+1; /* Forward chain the fibs */ 1436de76cfc7db8844bc26ab9a60b20f50ad7851833Thomas Gleixner sema_init(&fibptr->event_wait, 0); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&fibptr->event_lock); 145a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp hw_fib->header.XferState = cpu_to_le32(0xffffffff); 146a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->hw_fib_pa = hw_fib_pa; 148e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + 149e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara dev->max_fib_size + sizeof(struct aac_fib_xporthdr)); 150e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara hw_fib_pa = hw_fib_pa + 151e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara dev->max_fib_size + sizeof(struct aac_fib_xporthdr); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add the fib chain to the free list 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1567c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp dev->fibs[dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1].next = NULL; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Enable this to debug out of queue space 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->free_fib = &dev->fibs[0]; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 165bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp * aac_fib_alloc - allocate a fib 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter to allocate the fib for 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate a fib from the adapter fib pool. If the pool is empty we 1697c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp * return NULL. 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1718ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 172bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkampstruct fib *aac_fib_alloc(struct aac_dev *dev) 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fib * fibptr; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&dev->fib_lock, flags); 1778ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark fibptr = dev->free_fib; 1787c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp if(!fibptr){ 1797c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp spin_unlock_irqrestore(&dev->fib_lock, flags); 1807c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp return fibptr; 1817c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp } 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->free_fib = fibptr->next; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&dev->fib_lock, flags); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the proper node type code and node byte size 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->type = FSAFS_NTC_FIB_CONTEXT; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->size = sizeof(struct fib); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Null out fields that depend on being zero at the start of 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * each I/O 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 193a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp fibptr->hw_fib_va->header.XferState = 0; 194b6ef70f33ca2a3084b4fea12414550724a9114dcSalyzyn, Mark fibptr->flags = 0; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->callback = NULL; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->callback_data = NULL; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fibptr; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 202bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp * aac_fib_free - free a fib 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fibptr: fib to free up 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Frees up a fib and places it on the appropriate queue 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2078ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 208bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkampvoid aac_fib_free(struct fib *fibptr) 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 210cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech unsigned long flags, flagsv; 211cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech 212cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_lock_irqsave(&fibptr->event_lock, flagsv); 213cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (fibptr->done == 2) { 214cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_unlock_irqrestore(&fibptr->event_lock, flagsv); 215cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech return; 216cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech } 217cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_unlock_irqrestore(&fibptr->event_lock, flagsv); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&fibptr->dev->fib_lock, flags); 22003d4433721880bf1972c924b168e4e1dd3c59d53Mark Haverkamp if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aac_config.fib_timeouts++; 22203d4433721880bf1972c924b168e4e1dd3c59d53Mark Haverkamp if (fibptr->hw_fib_va->header.XferState != 0) { 22303d4433721880bf1972c924b168e4e1dd3c59d53Mark Haverkamp printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", 22403d4433721880bf1972c924b168e4e1dd3c59d53Mark Haverkamp (void*)fibptr, 22503d4433721880bf1972c924b168e4e1dd3c59d53Mark Haverkamp le32_to_cpu(fibptr->hw_fib_va->header.XferState)); 22603d4433721880bf1972c924b168e4e1dd3c59d53Mark Haverkamp } 22703d4433721880bf1972c924b168e4e1dd3c59d53Mark Haverkamp fibptr->next = fibptr->dev->free_fib; 22803d4433721880bf1972c924b168e4e1dd3c59d53Mark Haverkamp fibptr->dev->free_fib = fibptr; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 233bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp * aac_fib_init - initialise a fib 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fibptr: The fib to initialize 2358ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set up the generic fib fields ready for use 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2388ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 239bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkampvoid aac_fib_init(struct fib *fibptr) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 241a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp struct hw_fib *hw_fib = fibptr->hw_fib_va; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.StructType = FIB_MAGIC; 2447c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size); 2457c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); 2468e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp hw_fib->header.SenderFibAddress = 0; /* Filled in later if needed */ 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa); 2487c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fib_deallocate - deallocate a fib 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fibptr: fib to deallocate 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Will deallocate and return to the free pool the FIB pointed to by the 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * caller. 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2588ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 2594833869e6e6c2315e301c256e393dfb949c10076Adrian Bunkstatic void fib_dealloc(struct fib * fibptr) 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 261a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp struct hw_fib *hw_fib = fibptr->hw_fib_va; 262125e18745f16685f69a34fd6130d47598fc4bf54Eric Sesterhenn BUG_ON(hw_fib->header.StructType != FIB_MAGIC); 2638ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark hw_fib->header.XferState = 0; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Commuication primitives define and support the queuing method we use to 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * support host to adapter commuication. All queue accesses happen through 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these routines and are the only routines which have a knowledge of the 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * how these queues are implemented. 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2728ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aac_get_entry - get a queue entry 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @qid: Queue Number 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @entry: Entry return 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @index: Index return 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @nonotify: notification control 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * With a priority the routine returns a queue entry if the queue has free entries. If the queue 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is full(no free entries) than no entry is returned and the function returns 0 otherwise 1 is 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returned. 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2858ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aac_queue * q; 289bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp unsigned long idx; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All of the queues wrap when they reach the end, so we check 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to see if they have reached the end and if they have we just 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set the index back to zero. This is a wrap. You could or off 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the high bits in all updates but this is a bit faster I think. 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = &dev->queues->queue[qid]; 299bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp 300bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp idx = *index = le32_to_cpu(*(q->headers.producer)); 301bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp /* Interrupt Moderation, only interrupt for first two entries */ 302bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp if (idx != le32_to_cpu(*(q->headers.consumer))) { 303bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp if (--idx == 0) { 3041640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp if (qid == AdapNormCmdQueue) 305bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp idx = ADAP_NORM_CMD_ENTRIES; 3061640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp else 307bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp idx = ADAP_NORM_RESP_ENTRIES; 308bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp } 309bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp if (idx != le32_to_cpu(*(q->headers.consumer))) 3108ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark *nonotify = 1; 311bed30de47b034b5f28fb7db2fae4860b9d9c0622Mark Haverkamp } 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3131640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp if (qid == AdapNormCmdQueue) { 3148ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark if (*index >= ADAP_NORM_CMD_ENTRIES) 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *index = 0; /* Wrap to front of the Producer Queue. */ 3161640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp } else { 3178ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark if (*index >= ADAP_NORM_RESP_ENTRIES) 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *index = 0; /* Wrap to front of the Producer Queue. */ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3218ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark /* Queue is full */ 3228ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { 3237c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp printk(KERN_WARNING "Queue %d full, %u outstanding.\n", 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qid, q->numpending); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3278ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark *entry = q->base + *index; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3308ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark} 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aac_queue_get - get the next free QE 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @index: Returned index 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @priority: Priority of fib 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fib: Fib to associate with the queue entry 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @wait: Wait if queue full 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fibptr: Driver fib object to go with fib 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @nonotify: Don't notify the adapter 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Gets the next free QE off the requested priorty adapter command 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * queue and associates the Fib with the QE. The QE represented by 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * index is ready to insert on the queue when this routine returns 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * success. 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkampint aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aac_entry * entry = NULL; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int map = 0; 3528ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 3531640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp if (qid == AdapNormCmdQueue) { 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if no entries wait for some if caller wants to */ 3558ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark while (!aac_get_entry(dev, qid, &entry, index, nonotify)) { 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "GetEntries failed\n"); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3588ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark /* 3598ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * Setup queue entry with a command, status and fib mapped 3608ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark */ 3618ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); 3628ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark map = 1; 3631640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp } else { 3648ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark while (!aac_get_entry(dev, qid, &entry, index, nonotify)) { 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if no entries wait for some if caller wants to */ 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3678ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark /* 3688ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * Setup queue entry with command, status and fib mapped 3698ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark */ 3708ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); 3718ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark entry->addr = hw_fib->header.SenderFibAddress; 3728ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark /* Restore adapters pointer to the FIB */ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.ReceiverFibAddress = hw_fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ 3748ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark map = 0; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If MapFib is true than we need to map the Fib and put pointers 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in the queue entry. 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (map) 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->addr = cpu_to_le32(fibptr->hw_fib_pa); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3868ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * Define the highest level of host to adapter communication routines. 3878ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * These routines will support host to adapter FS commuication. These 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routines have no knowledge of the commuication method used. This level 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sends and receives FIBs. This level has no knowledge of how these FIBs 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get passed back and forth. 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 394bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp * aac_fib_send - send a fib to the adapter 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @command: Command to send 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fibptr: The fib 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @size: Size of fib data area 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @priority: Priority of Fib 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @wait: Async/sync select 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @reply: True if a reply is wanted 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @callback: Called with reply 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @callback_data: Passed to callback 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sends the requested FIB to the adapter and optionally will wait for a 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response FIB. If the caller does not wish to wait for a response than 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * an event to wait on must be supplied. This event will be set when a 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response FIB is received from the adapter. 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4098ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 410bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkampint aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, 411bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp int priority, int wait, int reply, fib_callback callback, 412bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp void *callback_data) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aac_dev * dev = fibptr->dev; 415a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp struct hw_fib * hw_fib = fibptr->hw_fib_va; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags = 0; 4171640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp unsigned long qflags; 418cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech unsigned long mflags = 0; 419116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara unsigned long sflags = 0; 420cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech 4211640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned))) 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 42525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * There are 5 cases with the wait and response requested flags. 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The only invalid cases are if the caller requests to wait and 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * does not request a response and if the caller does not want a 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response and the Fib is not allocated from pool. If a response 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is not requesed the Fib will just be deallocaed by the DPC 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine when the response comes back from the adapter. No 4318ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * further processing will be done besides deleting the Fib. We 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will have a debug mode where the adapter can notify the host 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it had a problem and the host can log that fact. 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 435b6ef70f33ca2a3084b4fea12414550724a9114dcSalyzyn, Mark fibptr->flags = 0; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (wait && !reply) { 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!wait && reply) { 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.XferState |= cpu_to_le32(Async | ResponseExpected); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIB_COUNTER_INCREMENT(aac_config.AsyncSent); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!wait && !reply) { 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.XferState |= cpu_to_le32(NoResponseExpected); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIB_COUNTER_INCREMENT(aac_config.NoResponseSent); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (wait && reply) { 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.XferState |= cpu_to_le32(ResponseExpected); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIB_COUNTER_INCREMENT(aac_config.NormalSent); 4478ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark } 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Map the fib into 32bits by using the fib number 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4528e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2); 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set FIB state to indicate where it came from and if we want a 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response from the adapter. Also load the command from the 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * caller. 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Map the hw fib pointer as a 32bit value 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.Command = cpu_to_le16(command); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.XferState |= cpu_to_le32(SentFromHost); 463a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp fibptr->hw_fib_va->header.Flags = 0; /* 0 the flags field - internal only*/ 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the size of the Fib we want to send to the adapter 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size); 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (le16_to_cpu(hw_fib->header.Size) > le16_to_cpu(hw_fib->header.SenderSize)) { 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EMSGSIZE; 4708ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark } 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get a queue entry connect the FIB to it and send an notify 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the adapter a command is ready. 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4751640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp hw_fib->header.XferState |= cpu_to_le32(NormalPriority); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fill in the Callback and CallbackContext if we are not 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * going to wait. 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!wait) { 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->callback = callback; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->callback_data = callback_data; 484b6ef70f33ca2a3084b4fea12414550724a9114dcSalyzyn, Mark fibptr->flags = FIB_CONTEXT_FLAG; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibptr->done = 0; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp FIB_COUNTER_INCREMENT(aac_config.FibsSent); 4901640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp 4911640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp dprintk((KERN_DEBUG "Fib contents:.\n")); 4928e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command))); 4938e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp dprintk((KERN_DEBUG " SubCommand = %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command))); 4948e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(hw_fib->header.XferState))); 495a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib_va)); 4961640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); 4971640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); 4981640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp 499c8f7b073e0e81499474a84ee2a90f77f7805c7f8Mark Haverkamp if (!dev->queues) 50065101355450df2d935f8d56ac3abef279f28a0e2Mark Haverkamp return -EBUSY; 5011640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp 502cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (wait) { 503cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech 504cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_lock_irqsave(&dev->manage_lock, mflags); 505cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (dev->management_fib_count >= AAC_NUM_MGT_FIB) { 506cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech printk(KERN_INFO "No management Fibs Available:%d\n", 507cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech dev->management_fib_count); 508cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_unlock_irqrestore(&dev->manage_lock, mflags); 509cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech return -EBUSY; 510cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech } 511cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech dev->management_fib_count++; 512cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_unlock_irqrestore(&dev->manage_lock, mflags); 5131640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp spin_lock_irqsave(&fibptr->event_lock, flags); 514cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech } 515cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech 516116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara if (dev->sync_mode) { 517116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara if (wait) 518116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara spin_unlock_irqrestore(&fibptr->event_lock, flags); 519116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara spin_lock_irqsave(&dev->sync_lock, sflags); 520116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara if (dev->sync_fib) { 521116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara list_add_tail(&fibptr->fiblink, &dev->sync_fib_list); 522116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara spin_unlock_irqrestore(&dev->sync_lock, sflags); 523116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara } else { 524116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara dev->sync_fib = fibptr; 525116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara spin_unlock_irqrestore(&dev->sync_lock, sflags); 526116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, 527116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara (u32)fibptr->hw_fib_pa, 0, 0, 0, 0, 0, 528116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara NULL, NULL, NULL, NULL, NULL); 529116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara } 530116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara if (wait) { 531116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara fibptr->flags |= FIB_CONTEXT_FLAG_WAIT; 532116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara if (down_interruptible(&fibptr->event_wait)) { 533116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara fibptr->flags &= ~FIB_CONTEXT_FLAG_WAIT; 534116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara return -EFAULT; 535116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara } 536116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara return 0; 537116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara } 538116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara return -EINPROGRESS; 539116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara } 540116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara 541cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (aac_adapter_deliver(fibptr) != 0) { 542cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech printk(KERN_ERR "aac_fib_send: returned -EBUSY\n"); 543cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (wait) { 544cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_unlock_irqrestore(&fibptr->event_lock, flags); 545cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_lock_irqsave(&dev->manage_lock, mflags); 546cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech dev->management_fib_count--; 547cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_unlock_irqrestore(&dev->manage_lock, mflags); 548cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech } 549cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech return -EBUSY; 550cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech } 551cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech 5528e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5548ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * If the caller wanted us to wait for response wait now. 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5568ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (wait) { 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&fibptr->event_lock, flags); 5599203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp /* Only set for first known interruptable command */ 5609203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp if (wait < 0) { 5619203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp /* 5629203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp * *VERY* Dangerous to time out a command, the 5639203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp * assumption is made that we have no hope of 5649203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp * functioning because an interrupt routing or other 5659203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp * hardware failure has occurred. 5669203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp */ 5679203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp unsigned long count = 36000000L; /* 3 minutes */ 5689203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp while (down_trylock(&fibptr->event_wait)) { 56933524b70e8f3dd55a4ba78ad81742c7814e7b0edMark Haverkamp int blink; 5709203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp if (--count == 0) { 57128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue]; 5729203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp spin_lock_irqsave(q->lock, qflags); 5739203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp q->numpending--; 5749203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp spin_unlock_irqrestore(q->lock, qflags); 5759203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp if (wait == -1) { 576bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n" 5779203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp "Usually a result of a PCI interrupt routing problem;\n" 5789203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp "update mother board BIOS or consider utilizing one of\n" 5799203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp "the SAFE mode kernel options (acpi, apic etc)\n"); 5809203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp } 5819203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp return -ETIMEDOUT; 5829203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp } 58333524b70e8f3dd55a4ba78ad81742c7814e7b0edMark Haverkamp if ((blink = aac_adapter_check_health(dev)) > 0) { 58433524b70e8f3dd55a4ba78ad81742c7814e7b0edMark Haverkamp if (wait == -1) { 58533524b70e8f3dd55a4ba78ad81742c7814e7b0edMark Haverkamp printk(KERN_ERR "aacraid: aac_fib_send: adapter blinkLED 0x%x.\n" 58633524b70e8f3dd55a4ba78ad81742c7814e7b0edMark Haverkamp "Usually a result of a serious unrecoverable hardware problem\n", 58733524b70e8f3dd55a4ba78ad81742c7814e7b0edMark Haverkamp blink); 58833524b70e8f3dd55a4ba78ad81742c7814e7b0edMark Haverkamp } 58933524b70e8f3dd55a4ba78ad81742c7814e7b0edMark Haverkamp return -EFAULT; 59033524b70e8f3dd55a4ba78ad81742c7814e7b0edMark Haverkamp } 5919203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp udelay(5); 5929203344cb8ecc554a1d36eae6661235ed422cf59Mark Haverkamp } 5930462590efe9a562dd2aa976ae2dc9cd2e6f5a0c6Mark Salyzyn } else if (down_interruptible(&fibptr->event_wait)) { 594cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech /* Do nothing ... satisfy 595cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech * down_interruptible must_check */ 596e6990c6448ca9359b6d4ad027c0a6efbf4379e64Mark Salyzyn } 597cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech 59833bb3b296207ff4f9e3b8dddb623e645ee1b8809Mark Haverkamp spin_lock_irqsave(&fibptr->event_lock, flags); 599cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (fibptr->done == 0) { 60033bb3b296207ff4f9e3b8dddb623e645ee1b8809Mark Haverkamp fibptr->done = 2; /* Tell interrupt we aborted */ 601c8f7b073e0e81499474a84ee2a90f77f7805c7f8Mark Haverkamp spin_unlock_irqrestore(&fibptr->event_lock, flags); 602cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech return -ERESTARTSYS; 603c8f7b073e0e81499474a84ee2a90f77f7805c7f8Mark Haverkamp } 60433bb3b296207ff4f9e3b8dddb623e645ee1b8809Mark Haverkamp spin_unlock_irqrestore(&fibptr->event_lock, flags); 605125e18745f16685f69a34fd6130d47598fc4bf54Eric Sesterhenn BUG_ON(fibptr->done == 0); 6068ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 607912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark if(unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ETIMEDOUT; 609912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark return 0; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the user does not want a response than return success otherwise 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return pending 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reply) 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINPROGRESS; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6218ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark/** 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aac_consumer_get - get the top of the queue 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @q: Queue 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @entry: Return entry 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Will return a pointer to the entry on the top of the queue requested that 6288ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * we are a consumer of, and return the address of the queue entry. It does 6298ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * not change the state of the queue. 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry) 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 index; 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (le32_to_cpu(*q->headers.producer) == le32_to_cpu(*q->headers.consumer)) { 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = 0; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The consumer index must be wrapped if we have reached 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the end of the queue, else we just use the entry 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pointed to by the header index 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6448ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark if (le32_to_cpu(*q->headers.consumer) >= q->entries) 6458ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark index = 0; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6478ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark index = le32_to_cpu(*q->headers.consumer); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *entry = q->base + index; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = 1; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(status); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aac_consumer_free - free consumer entry 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @q: Queue 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @qid: Queue ident 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Frees up the current top of the queue we are a consumer of. If the 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * queue was full notify the producer that the queue is no longer full. 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int wasfull = 0; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 notify; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((le32_to_cpu(*q->headers.producer)+1) == le32_to_cpu(*q->headers.consumer)) 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wasfull = 1; 6718ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (le32_to_cpu(*q->headers.consumer) >= q->entries) 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *q->headers.consumer = cpu_to_le32(1); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 67536b8dd1bf787512e33efa7ce88eff437404ab22dMarcin Slusarz le32_add_cpu(q->headers.consumer, 1); 6768ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (wasfull) { 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (qid) { 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HostNormCmdQueue: 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds notify = HostNormCmdNotFull; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HostNormRespQueue: 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds notify = HostNormRespNotFull; 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG(); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aac_adapter_notify(dev, notify); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6928ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark} 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 695bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp * aac_fib_adapter_complete - complete adapter issued fib 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fibptr: fib to complete 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @size: size of fib 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Will do all necessary work to complete a FIB that was sent from 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the adapter. 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 703bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkampint aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 705a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp struct hw_fib * hw_fib = fibptr->hw_fib_va; 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aac_dev * dev = fibptr->dev; 7071640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp struct aac_queue * q; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long nointr = 0; 7091640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp unsigned long qflags; 7101640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp 711e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { 712e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara kfree(hw_fib); 713e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara return 0; 714e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara } 715e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara 7161640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp if (hw_fib->header.XferState == 0) { 71728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp if (dev->comm_interface == AAC_COMM_MESSAGE) 718e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara kfree(hw_fib); 7198ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark return 0; 7201640a2c385a860ef25be4a8d18a528c4b6f02bd6Mark Haverkamp } 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we plan to do anything check the structure type first. 7238ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark */ 7248ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark if (hw_fib->header.StructType != FIB_MAGIC) { 72528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp if (dev->comm_interface == AAC_COMM_MESSAGE) 726e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara kfree(hw_fib); 7278ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark return -EINVAL; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This block handles the case where the adapter had sent us a 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command and we have finished processing the command. We 7328ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * call completeFib when we are done processing the command 7338ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * and want to send a response back to the adapter. This will 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * send the completed cdb to the adapter. 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { 73728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp if (dev->comm_interface == AAC_COMM_MESSAGE) { 7388e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp kfree (hw_fib); 7398e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp } else { 7408ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark u32 index; 7418ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark hw_fib->header.XferState |= cpu_to_le32(HostProcessed); 7428e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp if (size) { 7438e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp size += sizeof(struct aac_fibhdr); 7448ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark if (size > le16_to_cpu(hw_fib->header.SenderSize)) 7458e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp return -EMSGSIZE; 7468e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp hw_fib->header.Size = cpu_to_le16(size); 7478e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp } 7488e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp q = &dev->queues->queue[AdapNormRespQueue]; 7498e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp spin_lock_irqsave(q->lock, qflags); 7508e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr); 7518e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp *(q->headers.producer) = cpu_to_le32(index + 1); 7528e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp spin_unlock_irqrestore(q->lock, qflags); 7538e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp if (!(nointr & (int)aac_config.irq_mod)) 7548e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp aac_adapter_notify(dev, AdapNormRespQueue); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7568ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark } else { 7578ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark printk(KERN_WARNING "aac_fib_adapter_complete: " 7588ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark "Unknown xferstate detected.\n"); 7598ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark BUG(); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 765bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp * aac_fib_complete - fib completion handler 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @fib: FIB to complete 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Will do all necessary work to complete a FIB. 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7708ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 771bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkampint aac_fib_complete(struct fib *fibptr) 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 773cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech unsigned long flags; 774a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp struct hw_fib * hw_fib = fibptr->hw_fib_va; 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check for a fib which has already been completed 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hw_fib->header.XferState == 0) 7818ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark return 0; 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we plan to do anything check the structure type first. 7848ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark */ 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hw_fib->header.StructType != FIB_MAGIC) 7878ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark return -EINVAL; 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7898ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * This block completes a cdb which orginated on the host and we 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * just need to deallocate the cdb or reinit it. At this point the 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command is complete that we had sent to the adapter and this 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cdb could be reused. 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 794cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_lock_irqsave(&fibptr->event_lock, flags); 795cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (fibptr->done == 2) { 796cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_unlock_irqrestore(&fibptr->event_lock, flags); 797cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech return 0; 798cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech } 799cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech spin_unlock_irqrestore(&fibptr->event_lock, flags); 800cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fib_dealloc(fibptr); 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if(hw_fib->header.XferState & cpu_to_le32(SentFromHost)) 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This handles the case when the host has aborted the I/O 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the adapter because the adapter is not responding 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fib_dealloc(fibptr); 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if(hw_fib->header.XferState & cpu_to_le32(HostOwned)) { 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fib_dealloc(fibptr); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG(); 8178ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark } 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aac_printf - handle printf from firmware 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @val: Message info 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Print a message passed to us by the controller firmware on the 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adaptec board 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid aac_printf(struct aac_dev *dev, u32 val) 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *cp = dev->printfbuf; 8337c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp if (dev->printf_enabled) 8347c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp { 8357c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp int length = val & 0xffff; 8367c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp int level = (val >> 16) & 0xffff; 8378ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 8387c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp /* 8397c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp * The size of the printfbuf is set in port.c 8407c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp * There is no variable or define for it 8417c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp */ 8427c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp if (length > 255) 8437c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp length = 255; 8447c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp if (cp[length] != 0) 8457c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp cp[length] = 0; 8467c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp if (level == LOG_AAC_HIGH_ERROR) 8471241f3593a8857fab4259b6aa9d17f26e7de3a86Mark Haverkamp printk(KERN_WARNING "%s:%s", dev->name, cp); 8487c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp else 8491241f3593a8857fab4259b6aa9d17f26e7de3a86Mark Haverkamp printk(KERN_INFO "%s:%s", dev->name, cp); 8507c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp } 8518ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark memset(cp, 0, 256); 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 854131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 855131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp/** 856131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * aac_handle_aif - Handle a message from the firmware 857131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * @dev: Which adapter this fib is from 858131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * @fibptr: Pointer to fibptr from adapter 859131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * 860131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * This routine handles a driver notify fib from the adapter and 861131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * dispatches it to the appropriate routine for handling. 862131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 863131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 86431876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp#define AIF_SNIFF_TIMEOUT (30*HZ) 865131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkampstatic void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) 866131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp{ 867a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp struct hw_fib * hw_fib = fibptr->hw_fib_va; 868131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; 8690995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark u32 channel, id, lun, container; 870131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp struct scsi_device *device; 871131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp enum { 872131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp NOTHING, 873131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp DELETE, 874131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp ADD, 875131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp CHANGE 8760995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark } device_config_needed = NOTHING; 877131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 878131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* Sniff for container changes */ 879131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 880c8f7b073e0e81499474a84ee2a90f77f7805c7f8Mark Haverkamp if (!dev || !dev->fsa_dev) 881131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp return; 8820995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark container = channel = id = lun = (u32)-1; 883131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 884131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 885131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * We have set this up to try and minimize the number of 886131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * re-configures that take place. As a result of this when 887131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * certain AIF's come in we will set a flag waiting for another 888131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * type of AIF before setting the re-config flag. 889131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 890131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp switch (le32_to_cpu(aifcmd->command)) { 891131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case AifCmdDriverNotify: 892f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig switch (le32_to_cpu(((__le32 *)aifcmd->data)[0])) { 893131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 894131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * Morph or Expand complete 895131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 896131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case AifDenMorphComplete: 897131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case AifDenVolumeExtendComplete: 898f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); 899131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (container >= dev->maximum_num_containers) 900131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 901131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 902131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 903f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * Find the scsi_device associated with the SCSI 904131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * address. Make sure we have the right array, and if 905131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * so set the flag to initiate a new re-config once we 906131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * see an AifEnConfigChange AIF come through. 907131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 908131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 909131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if ((dev != NULL) && (dev->scsi_host_ptr != NULL)) { 9108ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark device = scsi_device_lookup(dev->scsi_host_ptr, 9118ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark CONTAINER_TO_CHANNEL(container), 9128ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark CONTAINER_TO_ID(container), 913131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp CONTAINER_TO_LUN(container)); 914131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (device) { 915131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_needed = CHANGE; 916131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = AifEnConfigChange; 91731876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp dev->fsa_dev[container].config_waiting_stamp = jiffies; 918131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp scsi_device_put(device); 919131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 920131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 921131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 922131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 923131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 924131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * If we are waiting on something and this happens to be 925131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * that thing then set the re-configure flag. 926131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 927131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (container != (u32)-1) { 928131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (container >= dev->maximum_num_containers) 929131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 93031876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp if ((dev->fsa_dev[container].config_waiting_on == 931f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig le32_to_cpu(*(__le32 *)aifcmd->data)) && 93231876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) 933131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = 0; 934131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } else for (container = 0; 935131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp container < dev->maximum_num_containers; ++container) { 93631876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp if ((dev->fsa_dev[container].config_waiting_on == 937f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig le32_to_cpu(*(__le32 *)aifcmd->data)) && 93831876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) 939131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = 0; 940131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 941131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 942131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 943131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case AifCmdEventNotify: 944f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig switch (le32_to_cpu(((__le32 *)aifcmd->data)[0])) { 94595e852e1ef165560e85d3012127068c8f08b19a1Salyzyn, Mark case AifEnBatteryEvent: 94695e852e1ef165560e85d3012127068c8f08b19a1Salyzyn, Mark dev->cache_protected = 94795e852e1ef165560e85d3012127068c8f08b19a1Salyzyn, Mark (((__le32 *)aifcmd->data)[1] == cpu_to_le32(3)); 94895e852e1ef165560e85d3012127068c8f08b19a1Salyzyn, Mark break; 949131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 950131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * Add an Array. 951131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 952131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case AifEnAddContainer: 953f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); 954131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (container >= dev->maximum_num_containers) 955131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 956131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_needed = ADD; 957131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = 958131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp AifEnConfigChange; 95931876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp dev->fsa_dev[container].config_waiting_stamp = jiffies; 960131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 961131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 962131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 963131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * Delete an Array. 964131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 965131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case AifEnDeleteContainer: 966f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); 967131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (container >= dev->maximum_num_containers) 968131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 969131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_needed = DELETE; 970131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = 971131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp AifEnConfigChange; 97231876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp dev->fsa_dev[container].config_waiting_stamp = jiffies; 973131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 974131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 975131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 976131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * Container change detected. If we currently are not 977131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * waiting on something else, setup to wait on a Config Change. 978131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 979131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case AifEnContainerChange: 980f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); 981131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (container >= dev->maximum_num_containers) 982131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 98331876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp if (dev->fsa_dev[container].config_waiting_on && 98431876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) 985131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 986131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_needed = CHANGE; 987131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = 988131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp AifEnConfigChange; 98931876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp dev->fsa_dev[container].config_waiting_stamp = jiffies; 990131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 991131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 992131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case AifEnConfigChange: 993131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 994131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 995cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark case AifEnAddJBOD: 996cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark case AifEnDeleteJBOD: 997cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); 998a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn if ((container >> 28)) { 999a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn container = (u32)-1; 1000cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark break; 1001a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn } 1002cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark channel = (container >> 24) & 0xF; 1003a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn if (channel >= dev->maximum_num_channels) { 1004a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn container = (u32)-1; 1005cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark break; 1006a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn } 1007cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark id = container & 0xFFFF; 1008a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn if (id >= dev->maximum_num_physicals) { 1009a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn container = (u32)-1; 1010cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark break; 1011a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn } 1012cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark lun = (container >> 16) & 0xFF; 1013a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn container = (u32)-1; 1014cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark channel = aac_phys_to_logical(channel); 1015cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark device_config_needed = 1016cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark (((__le32 *)aifcmd->data)[0] == 1017cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark cpu_to_le32(AifEnAddJBOD)) ? ADD : DELETE; 10185ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh if (device_config_needed == ADD) { 10195ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh device = scsi_device_lookup(dev->scsi_host_ptr, 10205ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh channel, 10215ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh id, 10225ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh lun); 10235ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh if (device) { 10245ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh scsi_remove_device(device); 10255ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh scsi_device_put(device); 10265ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh } 10275ca05594097438f81337e53ad50c2d17ffc28238Rajashekhara, Mahesh } 1028cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark break; 1029cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark 10300995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark case AifEnEnclosureManagement: 1031cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark /* 1032cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark * If in JBOD mode, automatic exposure of new 1033cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark * physical target to be suppressed until configured. 1034cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark */ 1035cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark if (dev->jbod) 1036cb1042f285c2168bd8cf10aca0e24802e682252bSalyzyn, Mark break; 10370995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark switch (le32_to_cpu(((__le32 *)aifcmd->data)[3])) { 10380995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark case EM_DRIVE_INSERTION: 10390995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark case EM_DRIVE_REMOVAL: 10400995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark container = le32_to_cpu( 10410995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark ((__le32 *)aifcmd->data)[2]); 1042a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn if ((container >> 28)) { 1043a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn container = (u32)-1; 10440995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark break; 1045a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn } 10460995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark channel = (container >> 24) & 0xF; 1047a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn if (channel >= dev->maximum_num_channels) { 1048a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn container = (u32)-1; 10490995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark break; 1050a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn } 10510995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark id = container & 0xFFFF; 10520995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark lun = (container >> 16) & 0xFF; 1053a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn container = (u32)-1; 10540995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if (id >= dev->maximum_num_physicals) { 10550995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark /* legacy dev_t ? */ 10560995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if ((0x2000 <= id) || lun || channel || 10570995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark ((channel = (id >> 7) & 0x3F) >= 10580995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark dev->maximum_num_channels)) 10590995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark break; 10600995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark lun = (id >> 4) & 7; 10610995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark id &= 0xF; 10620995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark } 10630995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark channel = aac_phys_to_logical(channel); 10640995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark device_config_needed = 10650995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark (((__le32 *)aifcmd->data)[3] 10660995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark == cpu_to_le32(EM_DRIVE_INSERTION)) ? 10670995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark ADD : DELETE; 10680995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark break; 10690995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark } 10700995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark break; 1071131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1072131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 1073131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 1074131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * If we are waiting on something and this happens to be 1075131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * that thing then set the re-configure flag. 1076131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 1077131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (container != (u32)-1) { 1078131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (container >= dev->maximum_num_containers) 1079131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 108031876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp if ((dev->fsa_dev[container].config_waiting_on == 1081f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig le32_to_cpu(*(__le32 *)aifcmd->data)) && 108231876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) 1083131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = 0; 1084131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } else for (container = 0; 1085131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp container < dev->maximum_num_containers; ++container) { 108631876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp if ((dev->fsa_dev[container].config_waiting_on == 1087f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig le32_to_cpu(*(__le32 *)aifcmd->data)) && 108831876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) 1089131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = 0; 1090131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1091131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 1092131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 1093131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case AifCmdJobProgress: 1094131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 1095131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * These are job progress AIF's. When a Clear is being 1096131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * done on a container it is initially created then hidden from 1097131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * the OS. When the clear completes we don't get a config 1098131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * change so we monitor the job status complete on a clear then 1099131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * wait for a container change. 1100131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 1101131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 1102f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig if (((__le32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero) && 1103f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig (((__le32 *)aifcmd->data)[6] == ((__le32 *)aifcmd->data)[5] || 1104f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig ((__le32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsSuccess))) { 1105131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp for (container = 0; 1106131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp container < dev->maximum_num_containers; 1107131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp ++container) { 1108131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 1109131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * Stomp on all config sequencing for all 1110131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * containers? 1111131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 1112131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = 1113131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp AifEnContainerChange; 1114131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_needed = ADD; 111531876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp dev->fsa_dev[container].config_waiting_stamp = 111631876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp jiffies; 1117131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1118131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1119f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig if (((__le32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero) && 1120f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig ((__le32 *)aifcmd->data)[6] == 0 && 1121f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig ((__le32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsRunning)) { 1122131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp for (container = 0; 1123131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp container < dev->maximum_num_containers; 1124131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp ++container) { 1125131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 1126131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * Stomp on all config sequencing for all 1127131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * containers? 1128131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 1129131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_waiting_on = 1130131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp AifEnContainerChange; 1131131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_needed = DELETE; 113231876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp dev->fsa_dev[container].config_waiting_stamp = 113331876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp jiffies; 1134131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1135131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1136131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 1137131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1138131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 1139a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn container = 0; 1140a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzynretry_next: 11410995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if (device_config_needed == NOTHING) 1142a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn for (; container < dev->maximum_num_containers; ++container) { 114331876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp if ((dev->fsa_dev[container].config_waiting_on == 0) && 114431876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp (dev->fsa_dev[container].config_needed != NOTHING) && 114531876f328f22435c21cfc27f0c871a4a4b22f9dbMark Haverkamp time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) { 1146131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp device_config_needed = 1147131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_needed; 1148131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp dev->fsa_dev[container].config_needed = NOTHING; 11490995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark channel = CONTAINER_TO_CHANNEL(container); 11500995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark id = CONTAINER_TO_ID(container); 11510995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark lun = CONTAINER_TO_LUN(container); 1152131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 1153131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1154131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1155131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (device_config_needed == NOTHING) 1156131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp return; 1157131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 1158131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 1159131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * If we decided that a re-configuration needs to be done, 1160131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * schedule it here on the way out the door, please close the door 1161131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * behind you. 1162131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 1163131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 1164131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 1165f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * Find the scsi_device associated with the SCSI address, 1166131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * and mark it as changed, invalidating the cache. This deals 1167131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp * with changes to existing device IDs. 1168131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 1169131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 1170131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (!dev || !dev->scsi_host_ptr) 1171131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp return; 1172131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* 1173bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp * force reload of disk info via aac_probe_container 1174131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp */ 11750995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if ((channel == CONTAINER_CHANNEL) && 11760995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark (device_config_needed != NOTHING)) { 11770995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if (dev->fsa_dev[container].valid == 1) 11780995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark dev->fsa_dev[container].valid = 2; 1179bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp aac_probe_container(dev, container); 11800995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark } 11810995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark device = scsi_device_lookup(dev->scsi_host_ptr, channel, id, lun); 1182131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp if (device) { 1183131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp switch (device_config_needed) { 1184131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case DELETE: 11859cccde93fed1ca988eb2fb17ab9194bf7b5ed1b0Rajashekhara, Mahesh#if (defined(AAC_DEBUG_INSTRUMENT_AIF_DELETE)) 11869cccde93fed1ca988eb2fb17ab9194bf7b5ed1b0Rajashekhara, Mahesh scsi_remove_device(device); 11879cccde93fed1ca988eb2fb17ab9194bf7b5ed1b0Rajashekhara, Mahesh#else 11880995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if (scsi_device_online(device)) { 11890995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark scsi_device_set_state(device, SDEV_OFFLINE); 11900995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark sdev_printk(KERN_INFO, device, 11910995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark "Device offlined - %s\n", 11920995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark (channel == CONTAINER_CHANNEL) ? 11930995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark "array deleted" : 11940995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark "enclosure services event"); 11950995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark } 11969cccde93fed1ca988eb2fb17ab9194bf7b5ed1b0Rajashekhara, Mahesh#endif 11970995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark break; 11980995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark case ADD: 11990995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if (!scsi_device_online(device)) { 12000995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark sdev_printk(KERN_INFO, device, 12010995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark "Device online - %s\n", 12020995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark (channel == CONTAINER_CHANNEL) ? 12030995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark "array created" : 12040995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark "enclosure services event"); 12050995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark scsi_device_set_state(device, SDEV_RUNNING); 12060995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark } 12070995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark /* FALLTHRU */ 1208131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp case CHANGE: 12090995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if ((channel == CONTAINER_CHANNEL) 12100995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark && (!dev->fsa_dev[container].valid)) { 12119cccde93fed1ca988eb2fb17ab9194bf7b5ed1b0Rajashekhara, Mahesh#if (defined(AAC_DEBUG_INSTRUMENT_AIF_DELETE)) 12129cccde93fed1ca988eb2fb17ab9194bf7b5ed1b0Rajashekhara, Mahesh scsi_remove_device(device); 12139cccde93fed1ca988eb2fb17ab9194bf7b5ed1b0Rajashekhara, Mahesh#else 12140995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if (!scsi_device_online(device)) 12150995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark break; 12160995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark scsi_device_set_state(device, SDEV_OFFLINE); 12170995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark sdev_printk(KERN_INFO, device, 12180995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark "Device offlined - %s\n", 12190995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark "array failed"); 12209cccde93fed1ca988eb2fb17ab9194bf7b5ed1b0Rajashekhara, Mahesh#endif 12210995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark break; 12220995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark } 1223131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp scsi_rescan_device(&device->sdev_gendev); 1224131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 1225131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp default: 1226131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp break; 1227131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 1228131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp scsi_device_put(device); 12290995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark device_config_needed = NOTHING; 1230131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 12310995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark if (device_config_needed == ADD) 12320995ad382df77b438d0c1e4f93ff349aa2eb9cafSalyzyn, Mark scsi_add_device(dev->scsi_host_ptr, channel, id, lun); 1233a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn if (channel == CONTAINER_CHANNEL) { 1234a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn container++; 1235a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn device_config_needed = NOTHING; 1236a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn goto retry_next; 1237a4576b5da671563187ac388e36e1d077bd20e43aMark Salyzyn } 1238131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp} 1239131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp 124029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Markstatic int _aac_reset_adapter(struct aac_dev *aac, int forced) 12418c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp{ 12428c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp int index, quirks; 12438c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp int retval; 12448c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct Scsi_Host *host; 12458c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct scsi_device *dev; 12468c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct scsi_cmnd *command; 12478c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct scsi_cmnd *command_list; 124829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark int jafo = 0; 12498c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 12508c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 12518c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * Assumptions: 125229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * - host is locked, unless called by the aacraid thread. 125329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * (a matter of convenience, due to legacy issues surrounding 125429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * eh_host_adapter_reset). 12558c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * - in_reset is asserted, so no new i/o is getting to the 12568c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * card. 125729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * - The card is dead, or will be very shortly ;-/ so no new 125829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * commands are completing in the interrupt service. 12598c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 12608c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp host = aac->scsi_host_ptr; 12618c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp scsi_block_requests(host); 12628c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac_adapter_disable_int(aac); 126329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (aac->thread->pid != current->pid) { 126429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_unlock_irq(host->host_lock); 126529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark kthread_stop(aac->thread); 126629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark jafo = 1; 126729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 12688c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 12698c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 12708c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * If a positive health, means in a known DEAD PANIC 12718c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * state and the adapter could be reset to `try again'. 12728c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 127329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark retval = aac_adapter_restart(aac, forced ? 0 : aac_adapter_check_health(aac)); 12748c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 12758c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if (retval) 12768c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp goto out; 12778c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 1278d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp /* 1279d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp * Loop through the fibs, close the synchronous FIBS 1280d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp */ 128133bb3b296207ff4f9e3b8dddb623e645ee1b8809Mark Haverkamp for (retval = 1, index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) { 1282d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp struct fib *fib = &aac->fibs[index]; 1283a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && 1284a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) { 1285d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp unsigned long flagv; 1286d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp spin_lock_irqsave(&fib->event_lock, flagv); 1287d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp up(&fib->event_wait); 1288d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp spin_unlock_irqrestore(&fib->event_lock, flagv); 1289d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp schedule(); 129033bb3b296207ff4f9e3b8dddb623e645ee1b8809Mark Haverkamp retval = 0; 1291d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp } 1292d18b448fc2caf0d719bd4bd34fb1856be89c8ef7Mark Haverkamp } 129333bb3b296207ff4f9e3b8dddb623e645ee1b8809Mark Haverkamp /* Give some extra time for ioctls to complete. */ 129433bb3b296207ff4f9e3b8dddb623e645ee1b8809Mark Haverkamp if (retval == 0) 129533bb3b296207ff4f9e3b8dddb623e645ee1b8809Mark Haverkamp ssleep(2); 12968c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp index = aac->cardtype; 12978c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 12988c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 12998c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * Re-initialize the adapter, first free resources, then carefully 13008c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * apply the initialization sequence to come back again. Only risk 13018c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * is a change in Firmware dropping cache, it is assumed the caller 13028c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * will ensure that i/o is queisced and the card is flushed in that 13038c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * case. 13048c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 13058c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac_fib_map_free(aac); 13068c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); 13078c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac->comm_addr = NULL; 13088c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac->comm_phys = 0; 13098c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp kfree(aac->queues); 13108c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac->queues = NULL; 13118c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp free_irq(aac->pdev->irq, aac); 1312d0efab26f89506387a1bde898556660e06d7eb15Vasily Averin if (aac->msi) 1313d0efab26f89506387a1bde898556660e06d7eb15Vasily Averin pci_disable_msi(aac->pdev); 13148c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp kfree(aac->fsa_dev); 13158c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac->fsa_dev = NULL; 131694cf6ba11b068b8a8f68a1e88bffb6827e92124bSalyzyn, Mark quirks = aac_get_driver_ident(index)->quirks; 131794cf6ba11b068b8a8f68a1e88bffb6827e92124bSalyzyn, Mark if (quirks & AAC_QUIRK_31BIT) { 1318929a22a558429bd22001d6b41cf31c233c68a5e2Yang Hongyang if (((retval = pci_set_dma_mask(aac->pdev, DMA_BIT_MASK(31)))) || 1319929a22a558429bd22001d6b41cf31c233c68a5e2Yang Hongyang ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_BIT_MASK(31))))) 13208c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp goto out; 13218c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } else { 1322284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang if (((retval = pci_set_dma_mask(aac->pdev, DMA_BIT_MASK(32)))) || 1323284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_BIT_MASK(32))))) 13248c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp goto out; 13258c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 13268c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if ((retval = (*(aac_get_driver_ident(index)->init))(aac))) 13278c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp goto out; 132894cf6ba11b068b8a8f68a1e88bffb6827e92124bSalyzyn, Mark if (quirks & AAC_QUIRK_31BIT) 1329284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang if ((retval = pci_set_dma_mask(aac->pdev, DMA_BIT_MASK(32)))) 13308c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp goto out; 133129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (jafo) { 133229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark aac->thread = kthread_run(aac_command_thread, aac, aac->name); 133329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (IS_ERR(aac->thread)) { 133429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark retval = PTR_ERR(aac->thread); 133529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark goto out; 133629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 13378c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 13388c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp (void)aac_get_adapter_info(aac); 13398c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if ((quirks & AAC_QUIRK_34SG) && (host->sg_tablesize > 34)) { 13408ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark host->sg_tablesize = 34; 13418ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark host->max_sectors = (host->sg_tablesize * 8) + 112; 13428ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark } 13438ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark if ((quirks & AAC_QUIRK_17SG) && (host->sg_tablesize > 17)) { 13448ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark host->sg_tablesize = 17; 13458ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark host->max_sectors = (host->sg_tablesize * 8) + 112; 13468ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark } 13478c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac_get_config_status(aac, 1); 13488c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac_get_containers(aac); 13498c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 13508c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * This is where the assumption that the Adapter is quiesced 13518c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * is important. 13528c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 13538c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp command_list = NULL; 13548c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp __shost_for_each_device(dev, host) { 13558c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp unsigned long flags; 13568c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp spin_lock_irqsave(&dev->list_lock, flags); 13578c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp list_for_each_entry(command, &dev->cmd_list, list) 13588c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if (command->SCp.phase == AAC_OWNER_FIRMWARE) { 13598c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp command->SCp.buffer = (struct scatterlist *)command_list; 13608c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp command_list = command; 13618c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 13628c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp spin_unlock_irqrestore(&dev->list_lock, flags); 13638c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 13648c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp while ((command = command_list)) { 13658c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp command_list = (struct scsi_cmnd *)command->SCp.buffer; 13668c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp command->SCp.buffer = NULL; 13678c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp command->result = DID_OK << 16 13688c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp | COMMAND_COMPLETE << 8 13698c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp | SAM_STAT_TASK_SET_FULL; 13708c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp command->SCp.phase = AAC_OWNER_ERROR_HANDLER; 13718c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp command->scsi_done(command); 13728c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 13738c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp retval = 0; 13748c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 13758c867b257d159ca04602d7087fa29f846785f9eaMark Haverkampout: 13768c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac->in_reset = 0; 13778c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp scsi_unblock_requests(host); 137829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (jafo) { 137929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_lock_irq(host->host_lock); 138029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 138129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark return retval; 138229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark} 138329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 138429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Markint aac_reset_adapter(struct aac_dev * aac, int forced) 138529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark{ 138629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark unsigned long flagv = 0; 138729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark int retval; 138829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark struct Scsi_Host * host; 138929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 139029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0) 139129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark return -EBUSY; 139229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 139329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (aac->in_reset) { 139429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_unlock_irqrestore(&aac->fib_lock, flagv); 139529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark return -EBUSY; 139629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 139729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark aac->in_reset = 1; 139829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_unlock_irqrestore(&aac->fib_lock, flagv); 139929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 140029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark /* 140129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * Wait for all commands to complete to this specific 140229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * target (block maximum 60 seconds). Although not necessary, 140329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * it does make us a good storage citizen. 140429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark */ 140529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark host = aac->scsi_host_ptr; 140629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark scsi_block_requests(host); 140729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (forced < 2) for (retval = 60; retval; --retval) { 140829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark struct scsi_device * dev; 140929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark struct scsi_cmnd * command; 141029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark int active = 0; 141129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 141229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark __shost_for_each_device(dev, host) { 141329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_lock_irqsave(&dev->list_lock, flagv); 141429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark list_for_each_entry(command, &dev->cmd_list, list) { 141529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (command->SCp.phase == AAC_OWNER_FIRMWARE) { 141629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark active++; 141729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark break; 141829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 141929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 142029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_unlock_irqrestore(&dev->list_lock, flagv); 142129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (active) 142229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark break; 142329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 142429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 142529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark /* 142629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * We can exit If all the commands are complete 142729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark */ 142829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (active == 0) 142929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark break; 143029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark ssleep(1); 143129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 143229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 143329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark /* Quiesce build, flush cache, write through mode */ 1434f858317d894a22eb2c26edcd26c7060fc4f40a15Salyzyn, Mark if (forced < 2) 1435f858317d894a22eb2c26edcd26c7060fc4f40a15Salyzyn, Mark aac_send_shutdown(aac); 143629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_lock_irqsave(host->host_lock, flagv); 1437f858317d894a22eb2c26edcd26c7060fc4f40a15Salyzyn, Mark retval = _aac_reset_adapter(aac, forced ? forced : ((aac_check_reset != 0) && (aac_check_reset != 1))); 143829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_unlock_irqrestore(host->host_lock, flagv); 143929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 1440f858317d894a22eb2c26edcd26c7060fc4f40a15Salyzyn, Mark if ((forced < 2) && (retval == -ENODEV)) { 144129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark /* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */ 144229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark struct fib * fibctx = aac_fib_alloc(aac); 144329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (fibctx) { 144429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark struct aac_pause *cmd; 144529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark int status; 144629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 144729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark aac_fib_init(fibctx); 144829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 144929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark cmd = (struct aac_pause *) fib_data(fibctx); 145029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 145129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark cmd->command = cpu_to_le32(VM_ContainerConfig); 145229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark cmd->type = cpu_to_le32(CT_PAUSE_IO); 145329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark cmd->timeout = cpu_to_le32(1); 145429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark cmd->min = cpu_to_le32(1); 145529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark cmd->noRescan = cpu_to_le32(1); 145629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark cmd->count = cpu_to_le32(0); 145729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 145829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark status = aac_fib_send(ContainerCommand, 145929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark fibctx, 146029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark sizeof(struct aac_pause), 146129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark FsaNormal, 146229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark -2 /* Timeout silently */, 1, 146329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark NULL, NULL); 146429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 146529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (status >= 0) 146629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark aac_fib_complete(fibctx); 1467cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech /* FIB should be freed only after getting 1468cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech * the response from the F/W */ 1469cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (status != -ERESTARTSYS) 1470cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech aac_fib_free(fibctx); 147129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 147229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 147329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 14748c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp return retval; 14758c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp} 14768c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 14778c867b257d159ca04602d7087fa29f846785f9eaMark Haverkampint aac_check_health(struct aac_dev * aac) 14788c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp{ 14798c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp int BlinkLED; 14808c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp unsigned long time_now, flagv = 0; 14818c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct list_head * entry; 14828c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct Scsi_Host * host; 14838c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 14848c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* Extending the scope of fib_lock slightly to protect aac->in_reset */ 14858c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0) 14868c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp return 0; 14878c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 14888c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if (aac->in_reset || !(BlinkLED = aac_adapter_check_health(aac))) { 14898c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp spin_unlock_irqrestore(&aac->fib_lock, flagv); 14908c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp return 0; /* OK */ 14918c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 14928c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 14938c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac->in_reset = 1; 14948c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 14958c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* Fake up an AIF: 14968c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * aac_aifcmd.command = AifCmdEventNotify = 1 14978c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * aac_aifcmd.seqnum = 0xFFFFFFFF 14988c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * aac_aifcmd.data[0] = AifEnExpEvent = 23 14998c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * aac_aifcmd.data[1] = AifExeFirmwarePanic = 3 15008c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * aac.aifcmd.data[2] = AifHighPriority = 3 15018c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * aac.aifcmd.data[3] = BlinkLED 15028c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 15038c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 15048c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp time_now = jiffies/HZ; 15058c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp entry = aac->fib_list.next; 15068c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 15078c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 15088c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * For each Context that is on the 15098c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * fibctxList, make a copy of the 15108c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * fib, and then set the event to wake up the 15118c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * thread that is waiting for it. 15128c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 15138c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp while (entry != &aac->fib_list) { 15148c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 15158c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * Extract the fibctx 15168c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 15178c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct aac_fib_context *fibctx = list_entry(entry, struct aac_fib_context, next); 15188c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct hw_fib * hw_fib; 15198c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct fib * fib; 15208c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 15218c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * Check if the queue is getting 15228c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * backlogged 15238c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 15248c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if (fibctx->count > 20) { 15258c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 15268c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * It's *not* jiffies folks, 15278c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * but jiffies / HZ, so do not 15288c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * panic ... 15298c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 15308c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp u32 time_last = fibctx->jiffies; 15318c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 15328c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * Has it been > 2 minutes 15338c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * since the last read off 15348c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * the queue? 15358c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 15368c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if ((time_now - time_last) > aif_timeout) { 15378c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp entry = entry->next; 15388c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac_close_fib_context(aac, fibctx); 15398c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp continue; 15408c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 15418c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 15428c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 15438c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * Warning: no sleep allowed while 15448c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * holding spinlock 15458c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 15464dbc22d7a9644088266a579433a3d621142a01e9Salyzyn, Mark hw_fib = kzalloc(sizeof(struct hw_fib), GFP_ATOMIC); 15474dbc22d7a9644088266a579433a3d621142a01e9Salyzyn, Mark fib = kzalloc(sizeof(struct fib), GFP_ATOMIC); 15488c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if (fib && hw_fib) { 15498c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp struct aac_aifcmd * aif; 15508c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 1551a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp fib->hw_fib_va = hw_fib; 15528c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp fib->dev = aac; 15538c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac_fib_init(fib); 15548c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp fib->type = FSAFS_NTC_FIB_CONTEXT; 15558c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp fib->size = sizeof (struct fib); 15568c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp fib->data = hw_fib->data; 15578c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aif = (struct aac_aifcmd *)hw_fib->data; 15588c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aif->command = cpu_to_le32(AifCmdEventNotify); 1559a3940da5e6fe8b833eecdbca3fac9456b4204d6eSalyzyn, Mark aif->seqnum = cpu_to_le32(0xFFFFFFFF); 1560a3940da5e6fe8b833eecdbca3fac9456b4204d6eSalyzyn, Mark ((__le32 *)aif->data)[0] = cpu_to_le32(AifEnExpEvent); 1561a3940da5e6fe8b833eecdbca3fac9456b4204d6eSalyzyn, Mark ((__le32 *)aif->data)[1] = cpu_to_le32(AifExeFirmwarePanic); 1562a3940da5e6fe8b833eecdbca3fac9456b4204d6eSalyzyn, Mark ((__le32 *)aif->data)[2] = cpu_to_le32(AifHighPriority); 1563a3940da5e6fe8b833eecdbca3fac9456b4204d6eSalyzyn, Mark ((__le32 *)aif->data)[3] = cpu_to_le32(BlinkLED); 15648c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 15658c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 15668c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * Put the FIB onto the 15678c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * fibctx's fibs 15688c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 15698c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp list_add_tail(&fib->fiblink, &fibctx->fib_list); 15708c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp fibctx->count++; 15718c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp /* 15728c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * Set the event to wake up the 15738c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp * thread that will waiting. 15748c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp */ 15758c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp up(&fibctx->wait_sem); 15768c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } else { 15778c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); 15788c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp kfree(fib); 15798c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp kfree(hw_fib); 15808c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 15818c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp entry = entry->next; 15828c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 15838c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 15848c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp spin_unlock_irqrestore(&aac->fib_lock, flagv); 15858c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 15868c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp if (BlinkLED < 0) { 15878c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp printk(KERN_ERR "%s: Host adapter dead %d\n", aac->name, BlinkLED); 15888c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp goto out; 15898c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp } 15908c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 15918c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED); 15928c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 15932f7ecc55b37ef9f0208360e64d8b9d2313df8ce6Salyzyn, Mark if (!aac_check_reset || ((aac_check_reset == 1) && 1594a3940da5e6fe8b833eecdbca3fac9456b4204d6eSalyzyn, Mark (aac->supplement_adapter_info.SupportedOptions2 & 1595a3940da5e6fe8b833eecdbca3fac9456b4204d6eSalyzyn, Mark AAC_OPTION_IGNORE_RESET))) 159629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark goto out; 15978c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp host = aac->scsi_host_ptr; 159829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (aac->thread->pid != current->pid) 159929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_lock_irqsave(host->host_lock, flagv); 1600f858317d894a22eb2c26edcd26c7060fc4f40a15Salyzyn, Mark BlinkLED = _aac_reset_adapter(aac, aac_check_reset != 1); 160129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (aac->thread->pid != current->pid) 160229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark spin_unlock_irqrestore(host->host_lock, flagv); 16038c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp return BlinkLED; 16048c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 16058c867b257d159ca04602d7087fa29f846785f9eaMark Haverkampout: 16068c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp aac->in_reset = 0; 16078c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp return BlinkLED; 16088c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp} 16098c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 16108c867b257d159ca04602d7087fa29f846785f9eaMark Haverkamp 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aac_command_thread - command processing thread 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Adapter to monitor 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Waits on the commandready event in it's queue. When the event gets set 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it will pull FIBs off it's queue. It will continue to pull FIBs off 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * until the queue is empty. When the queue is empty it will wait for 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * more FIBs. 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16208ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 1621fe27381d16c6683c55e618360d0d11bd43647e43Christoph Hellwigint aac_command_thread(void *data) 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1623fe27381d16c6683c55e618360d0d11bd43647e43Christoph Hellwig struct aac_dev *dev = data; 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hw_fib *hw_fib, *hw_newfib; 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fib *fib, *newfib; 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aac_fib_context *fibctx; 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DECLARE_WAITQUEUE(wait, current); 162929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark unsigned long next_jiffies = jiffies + HZ; 163029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark unsigned long next_check_jiffies = next_jiffies; 163129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark long difference = HZ; 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We can only have one thread per adapter for AIF's. 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->aif_thread) 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1638fe27381d16c6683c55e618360d0d11bd43647e43Christoph Hellwig 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Let the DPC know it has a place to send the AIF's to. 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->aif_thread = 1; 16432f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp add_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_INTERRUPTIBLE); 16452f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp dprintk ((KERN_INFO "aac_command_thread start\n")); 16468ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark while (1) { 16472f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); 16482f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp while(!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) { 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *entry; 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aac_aifcmd * aifcmd; 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_RUNNING); 16538ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 16542f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp entry = dev->queues->queue[HostNormCmdQueue].cmdq.next; 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(entry); 16568ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 16572f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fib = list_entry(entry, struct fib, fiblink); 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16608ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * We will process the FIB here or pass it to a 16618ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * worker thread that is TBD. We Really can't 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * do anything at this point since we don't have 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * anything defined for this thread to do. 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1665a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp hw_fib = fib->hw_fib_va; 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(fib, 0, sizeof(struct fib)); 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fib->type = FSAFS_NTC_FIB_CONTEXT; 16688ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark fib->size = sizeof(struct fib); 1669a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp fib->hw_fib_va = hw_fib; 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fib->data = hw_fib->data; 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fib->dev = dev; 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We only handle AifRequest fibs from the adapter. 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aifcmd = (struct aac_aifcmd *) hw_fib->data; 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Handle Driver Notify Events */ 1678131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp aac_handle_aif(dev, fib); 167956b5871223f66d4a34e6e1069f241077e9f0a154Mark Haverkamp *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); 1680bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp aac_fib_adapter_complete(fib, (u16)sizeof(u32)); 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The u32 here is important and intended. We are using 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32bit wrapping time to fit the adapter field */ 16848ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 time_now, time_last; 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flagv; 16872f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp unsigned num; 16882f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp struct hw_fib ** hw_fib_pool, ** hw_fib_p; 16892f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp struct fib ** fib_pool, ** fib_p; 16908ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark 1691131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp /* Sniff events */ 16928ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark if ((aifcmd->command == 1693131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp cpu_to_le32(AifCmdEventNotify)) || 16948ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark (aifcmd->command == 1695131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp cpu_to_le32(AifCmdJobProgress))) { 1696131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp aac_handle_aif(dev, fib); 1697131256cf203d0df62014dda8453a70cb6af0d0bbMark Haverkamp } 169829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds time_now = jiffies/HZ; 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17012f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp /* 17022f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp * Warning: no sleep allowed while 17032f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp * holding spinlock. We take the estimate 17042f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp * and pre-allocate a set of fibs outside the 17052f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp * lock. 17062f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp */ 17072f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp num = le32_to_cpu(dev->init->AdapterFibsSize) 17082f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp / sizeof(struct hw_fib); /* some extra */ 17092f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp spin_lock_irqsave(&dev->fib_lock, flagv); 17102f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp entry = dev->fib_list.next; 17112f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp while (entry != &dev->fib_list) { 17122f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp entry = entry->next; 17132f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp ++num; 17142f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp } 17152f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp spin_unlock_irqrestore(&dev->fib_lock, flagv); 17162f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp hw_fib_pool = NULL; 17172f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp fib_pool = NULL; 17182f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp if (num 17192f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp && ((hw_fib_pool = kmalloc(sizeof(struct hw_fib *) * num, GFP_KERNEL))) 17202f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp && ((fib_pool = kmalloc(sizeof(struct fib *) * num, GFP_KERNEL)))) { 17212f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp hw_fib_p = hw_fib_pool; 17222f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp fib_p = fib_pool; 17232f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp while (hw_fib_p < &hw_fib_pool[num]) { 17242f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp if (!(*(hw_fib_p++) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL))) { 17252f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp --hw_fib_p; 17262f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp break; 17272f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp } 17282f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp if (!(*(fib_p++) = kmalloc(sizeof(struct fib), GFP_KERNEL))) { 17292f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp kfree(*(--hw_fib_p)); 17302f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp break; 17312f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp } 17322f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp } 17332f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp if ((num = hw_fib_p - hw_fib_pool) == 0) { 17342f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp kfree(fib_pool); 17352f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp fib_pool = NULL; 17362f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp kfree(hw_fib_pool); 17372f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp hw_fib_pool = NULL; 17382f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp } 1739c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl } else { 17402f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp kfree(hw_fib_pool); 17412f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp hw_fib_pool = NULL; 17422f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp } 17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&dev->fib_lock, flagv); 17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = dev->fib_list.next; 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 17468ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * For each Context that is on the 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fibctxList, make a copy of the 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fib, and then set the event to wake up the 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * thread that is waiting for it. 17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17512f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp hw_fib_p = hw_fib_pool; 17522f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp fib_p = fib_pool; 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (entry != &dev->fib_list) { 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Extract the fibctx 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibctx = list_entry(entry, struct aac_fib_context, next); 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check if the queue is getting 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * backlogged 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fibctx->count > 20) 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It's *not* jiffies folks, 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but jiffies / HZ so do not 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * panic ... 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds time_last = fibctx->jiffies; 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 17718ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark * Has it been > 2 minutes 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * since the last read off 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the queue? 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1775404d9a900b5bc83a3780ec337ca6fdcb04b766c0Mark Haverkamp if ((time_now - time_last) > aif_timeout) { 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = entry->next; 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aac_close_fib_context(dev, fibctx); 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Warning: no sleep allowed while 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * holding spinlock 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17852f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp if (hw_fib_p < &hw_fib_pool[num]) { 17862f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp hw_newfib = *hw_fib_p; 17872f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp *(hw_fib_p++) = NULL; 17882f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp newfib = *fib_p; 17892f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp *(fib_p++) = NULL; 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Make the copy of the FIB 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(newfib, fib, sizeof(struct fib)); 1795a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp newfib->hw_fib_va = hw_newfib; 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Put the FIB onto the 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fibctx's fibs 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&newfib->fiblink, &fibctx->fib_list); 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fibctx->count++; 18028ce3eca4dc8161e030a055bde94cde28476e0894Salyzyn, Mark /* 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the event to wake up the 18042f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp * thread that is waiting. 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&fibctx->wait_sem); 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = entry->next; 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the status of this FIB 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 181556b5871223f66d4a34e6e1069f241077e9f0a154Mark Haverkamp *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); 1816bfb35aa85057da4336af56a7f26e08031f4e3468Mark Haverkamp aac_fib_adapter_complete(fib, sizeof(u32)); 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&dev->fib_lock, flagv); 18182f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp /* Free up the remaining resources */ 18192f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp hw_fib_p = hw_fib_pool; 18202f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp fib_p = fib_pool; 18212f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp while (hw_fib_p < &hw_fib_pool[num]) { 1822c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl kfree(*hw_fib_p); 1823c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl kfree(*fib_p); 18242f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp ++fib_p; 18252f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp ++hw_fib_p; 18262f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp } 1827c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl kfree(hw_fib_pool); 1828c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl kfree(fib_pool); 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(fib); 18312f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There are no more AIF's 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18362f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); 183729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 183829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark /* 183929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * Background activity 184029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark */ 184129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if ((time_before(next_check_jiffies,next_jiffies)) 184229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark && ((difference = next_check_jiffies - jiffies) <= 0)) { 184329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark next_check_jiffies = next_jiffies; 184429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (aac_check_health(dev) == 0) { 184529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark difference = ((long)(unsigned)check_interval) 184629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * HZ; 184729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark next_check_jiffies = jiffies + difference; 184829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } else if (!dev->queues) 184929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark break; 185029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 185129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (!time_before(next_check_jiffies,next_jiffies) 185229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark && ((difference = next_jiffies - jiffies) <= 0)) { 185329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark struct timeval now; 185429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark int ret; 185529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 185629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark /* Don't even try to talk to adapter if its sick */ 185729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark ret = aac_check_health(dev); 185829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (!ret && !dev->queues) 185929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark break; 186029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark next_check_jiffies = jiffies 186129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark + ((long)(unsigned)check_interval) 186229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark * HZ; 186329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark do_gettimeofday(&now); 186429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 186529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark /* Synchronize our watches */ 186629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (((1000000 - (1000000 / HZ)) > now.tv_usec) 186729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark && (now.tv_usec > (1000000 / HZ))) 186829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark difference = (((1000000 - now.tv_usec) * HZ) 186929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark + 500000) / 1000000; 187029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark else if (ret == 0) { 187129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark struct fib *fibptr; 187229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 187329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if ((fibptr = aac_fib_alloc(dev))) { 1874cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech int status; 1875f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig __le32 *info; 187629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 187729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark aac_fib_init(fibptr); 187829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 1879f3307f7276067e2f8f29a20e3ebe52887e8f9f00Christoph Hellwig info = (__le32 *) fib_data(fibptr); 188029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (now.tv_usec > 500000) 188129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark ++now.tv_sec; 188229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 188329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark *info = cpu_to_le32(now.tv_sec); 188429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 1885cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech status = aac_fib_send(SendHostTime, 188629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark fibptr, 188729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark sizeof(*info), 188829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark FsaNormal, 188929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark 1, 1, 189029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark NULL, 189129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark NULL); 1892cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech /* Do not set XferState to zero unless 1893cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech * receives a response from F/W */ 1894cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (status >= 0) 1895cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech aac_fib_complete(fibptr); 1896cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech /* FIB should be freed only after 1897cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech * getting the response from the F/W */ 1898cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech if (status != -ERESTARTSYS) 1899cacb6dc3d7fea751879a225c15e48228415e6359Penchala Narasimha Reddy Chilakala, ERS-HCLTech aac_fib_free(fibptr); 190029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 190129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark difference = (long)(unsigned)update_interval*HZ; 190229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } else { 190329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark /* retry shortly */ 190429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark difference = 10 * HZ; 190529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 190629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark next_jiffies = jiffies + difference; 190729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (time_before(next_check_jiffies,next_jiffies)) 190829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark difference = next_check_jiffies - jiffies; 190929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark } 191029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark if (difference <= 0) 191129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark difference = 1; 191229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark set_current_state(TASK_INTERRUPTIBLE); 191329c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark schedule_timeout(difference); 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1915fe27381d16c6683c55e618360d0d11bd43647e43Christoph Hellwig if (kthread_should_stop()) 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19182f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp if (dev->queues) 19192f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->aif_thread = 0; 19212f130980d14cb938226011875ca5224cd46dc1f9Mark Haverkamp return 0; 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1923