// SPDX-License-Identifier: GPL-2.0-or-later /* * Adaptec AAC series RAID controller driver * (c) Copyright 2001 Red Hat Inc. * * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * * Copyright (c) 2000-2010 Adaptec, Inc. * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) * * Module Name: * comminit.c * * Abstract: This supports the initialization of the host adapter commuication interface. * This is a platform dependent module for the pci cyclone board.
*/
/* * number of 4k pages of host physical memory. The aacraid fw * needs this number to be less than 4gb worth of pages. New * firmware doesn't have any issues with the mapping system, but * older Firmware did, and had *troubles* dealing with the math * overloading past 32 bits, thus we must limit this field.
*/
aac_max_hostphysmempages =
dma_get_required_mask(&dev->pdev->dev) >> 12; if (aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES)
init->r7.host_phys_mem_pages =
cpu_to_le32(aac_max_hostphysmempages); else
init->r7.host_phys_mem_pages =
cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
/* * Increment the base address by the amount already used
*/
base = base + fibsize + host_rrq_size + aac_init_size;
phys = (dma_addr_t)((ulong)phys + fibsize + host_rrq_size +
aac_init_size);
/* * Align the beginning of Headers to commalign
*/
align = (commalign - ((uintptr_t)(base) & (commalign - 1)));
base = base + align;
phys = phys + align; /* * Fill in addresses of the Comm Area Headers and Queues
*/
*commaddr = base; if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3)
init->r7.comm_header_address = cpu_to_le32((u32)phys); /* * Increment the base address by the size of the CommArea
*/
base = base + commsize;
phys = phys + commsize; /* * Place the Printf buffer area after the Fast I/O comm area.
*/
dev->printfbuf = (void *)base; if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3) {
init->r7.printfbuf = cpu_to_le32(phys);
init->r7.printfbufsiz = cpu_to_le32(printfbufsiz);
}
memset(base, 0, printfbufsiz); return 1;
}
if (aac_priv(cmd)->owner == AAC_OWNER_FIRMWARE)
*active = *active + 1; returntrue;
} staticvoid aac_wait_for_io_completion(struct aac_dev *aac)
{ int i = 0, active;
for (i = 60; i; --i) {
active = 0;
scsi_host_busy_iter(aac->scsi_host_ptr,
wait_for_io_iter, &active); /* * We can exit If all the commands are complete
*/ if (active == 0) break;
dev_info(&aac->pdev->dev, "Wait for %d commands to complete\n", active);
ssleep(1);
} if (active)
dev_err(&aac->pdev->dev, "%d outstanding commands during shutdown\n", active);
}
/** * aac_send_shutdown - shutdown an adapter * @dev: Adapter to shutdown * * This routine will send a VM_CloseAll (shutdown) request to the adapter.
*/
int aac_send_shutdown(struct aac_dev * dev)
{ struct fib * fibctx; struct aac_close *cmd; int status = 0;
if (aac_adapter_check_health(dev)) return status;
if (!dev->adapter_shutdown) {
mutex_lock(&dev->ioctl_mutex);
dev->adapter_shutdown = 1;
mutex_unlock(&dev->ioctl_mutex);
}
aac_wait_for_io_completion(dev);
fibctx = aac_fib_alloc(dev); if (!fibctx) return -ENOMEM;
aac_fib_init(fibctx);
if (status >= 0)
aac_fib_complete(fibctx); /* FIB should be freed only after getting the response from the F/W */ if (status != -ERESTARTSYS)
aac_fib_free(fibctx); if (aac_is_src(dev) &&
dev->msi_enabled)
aac_set_intx_mode(dev); return status;
}
/** * aac_comm_init - Initialise FSA data structures * @dev: Adapter to initialise * * Initializes the data structures that are required for the FSA commuication * interface to operate. * Returns * 1 - if we were able to init the commuication interface. * 0 - If there were errors initing. This is a fatal error.
*/
staticint aac_comm_init(struct aac_dev * dev)
{ unsignedlong hdrsize = (sizeof(u32) * NUMBER_OF_COMM_QUEUES) * 2; unsignedlong queuesize = sizeof(struct aac_entry) * TOTAL_QUEUE_ENTRIES;
u32 *headers; struct aac_entry * queues; unsignedlong size; struct aac_queue_block * comm = dev->queues; /* * Now allocate and initialize the zone structures used as our * pool of FIB context records. The size of the zone is based * on the system memory size. We also initialize the mutex used * to protect the zone.
*/
spin_lock_init(&dev->fib_lock);
/* * Allocate the physically contiguous space for the commuication * queue headers.
*/
size = hdrsize + queuesize;
if (!aac_alloc_comm(dev, (void * *)&headers, size, QUEUE_ALIGNMENT)) return -ENOMEM;
if (aac_is_src(dev))
aac_define_int_mode(dev); /* * Ok now init the communication subsystem
*/
dev->queues = kzalloc(sizeof(struct aac_queue_block), GFP_KERNEL); if (dev->queues == NULL) {
printk(KERN_ERR "Error could not allocate comm region.\n"); return NULL;
}
if (aac_comm_init(dev)<0){
kfree(dev->queues);
dev->queues = NULL; return NULL;
} /* * Initialize the list of fibs
*/ if (aac_fib_setup(dev) < 0) {
kfree(dev->queues);
dev->queues = NULL; return NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.