#include <asm/io.h>
#include <asm/system.h>
-#include "scsi.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
#include "BusLogic.h"
#include "FlashPoint.c"
#define FAILURE (-1)
#endif
+static struct scsi_host_template Bus_Logic_template;
+
/*
BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver
Options specifications provided via the Linux Kernel Command Line or via
MODULE_LICENSE("GPL");
#ifdef MODULE
static char *BusLogic;
-MODULE_PARM(BusLogic, "s");
+module_param(BusLogic, charp, 0);
#endif
static struct BusLogic_GlobalOptions BusLogic_GlobalOptions;
-
-/*
- BusLogic_FirstRegisteredHostAdapter and BusLogic_LastRegisteredHostAdapter
- are pointers to the first and last registered BusLogic Host Adapters.
-*/
-
-static struct BusLogic_HostAdapter *BusLogic_FirstRegisteredHostAdapter;
-static struct BusLogic_HostAdapter *BusLogic_LastRegisteredHostAdapter;
-
+static LIST_HEAD(BusLogic_host_list);
/*
BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList.
return HostAdapter->FullModelName;
}
-
-/*
- BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered
- BusLogic Host Adapters.
-*/
-
-static void __init BusLogic_RegisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
-{
- HostAdapter->Next = NULL;
- if (BusLogic_FirstRegisteredHostAdapter == NULL) {
- BusLogic_FirstRegisteredHostAdapter = HostAdapter;
- BusLogic_LastRegisteredHostAdapter = HostAdapter;
- } else {
- BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
- BusLogic_LastRegisteredHostAdapter = HostAdapter;
- }
-}
-
-
-/*
- BusLogic_UnregisterHostAdapter removes Host Adapter from the list of
- registered BusLogic Host Adapters.
-*/
-
-static void BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
-{
- if (HostAdapter == BusLogic_FirstRegisteredHostAdapter) {
- BusLogic_FirstRegisteredHostAdapter = BusLogic_FirstRegisteredHostAdapter->Next;
- if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
- BusLogic_LastRegisteredHostAdapter = NULL;
- } else {
- struct BusLogic_HostAdapter *PreviousHostAdapter = BusLogic_FirstRegisteredHostAdapter;
- while (PreviousHostAdapter != NULL && PreviousHostAdapter->Next != HostAdapter)
- PreviousHostAdapter = PreviousHostAdapter->Next;
- if (PreviousHostAdapter != NULL)
- PreviousHostAdapter->Next = HostAdapter->Next;
- }
- HostAdapter->Next = NULL;
-}
-
-
/*
BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs)
for Host Adapter from the BlockSize bytes located at BlockPointer. The newly
static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
{
struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
- if (CCB->Command->use_sg != 0) {
- pci_unmap_sg(HostAdapter->PCI_Device, (struct scatterlist *) CCB->Command->request_buffer, CCB->Command->use_sg, scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
- } else if (CCB->Command->request_bufflen != 0) {
- pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer, CCB->DataLength, scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
+ struct scsi_cmnd *cmd = CCB->Command;
+
+ if (cmd->use_sg != 0) {
+ pci_unmap_sg(HostAdapter->PCI_Device,
+ (struct scatterlist *)cmd->request_buffer,
+ cmd->use_sg, cmd->sc_data_direction);
+ } else if (cmd->request_bufflen != 0) {
+ pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer,
+ CCB->DataLength, cmd->sc_data_direction);
}
- pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer, CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
+ CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+
CCB->Command = NULL;
CCB->Status = BusLogic_CCB_Free;
CCB->Next = HostAdapter->Free_CCBs;
registered.
*/
-static int __init BusLogic_DetectHostAdapter(struct scsi_host_template *HostTemplate)
+static int __init BusLogic_init(void)
{
int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
struct BusLogic_HostAdapter *PrototypeHostAdapter;
+
+#ifdef MODULE
+ if (BusLogic)
+ BusLogic_Setup(BusLogic);
+#endif
+
if (BusLogic_ProbeOptions.NoProbe)
- return 0;
+ return -ENODEV;
BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *)
kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_ATOMIC);
if (BusLogic_ProbeInfoList == NULL) {
BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
- return 0;
+ return -ENOMEM;
}
memset(BusLogic_ProbeInfoList, 0, BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo));
PrototypeHostAdapter = (struct BusLogic_HostAdapter *)
if (PrototypeHostAdapter == NULL) {
kfree(BusLogic_ProbeInfoList);
BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL);
- return 0;
+ return -ENOMEM;
}
memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
#ifdef MODULE
HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
HostAdapter->Bus = ProbeInfo->Bus;
HostAdapter->Device = ProbeInfo->Device;
+ HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
/*
Register the SCSI Host structure.
*/
- Host = scsi_host_alloc(HostTemplate, sizeof(struct BusLogic_HostAdapter));
+ Host = scsi_host_alloc(&Bus_Logic_template, sizeof(struct BusLogic_HostAdapter));
if (Host == NULL) {
release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
continue;
Add Host Adapter to the end of the list of registered BusLogic
Host Adapters.
*/
- BusLogic_RegisterHostAdapter(HostAdapter);
+ list_add_tail(&HostAdapter->host_list, &BusLogic_host_list);
+
/*
Read the Host Adapter Configuration, Configure the Host Adapter,
Acquire the System Resources necessary to use the Host Adapter, then
printk(KERN_WARNING "BusLogic: Release and re-register of " "port 0x%04lx failed \n", (unsigned long) HostAdapter->IO_Address);
BusLogic_DestroyCCBs(HostAdapter);
BusLogic_ReleaseResources(HostAdapter);
- BusLogic_UnregisterHostAdapter(HostAdapter);
+ list_del(&HostAdapter->host_list);
scsi_host_put(Host);
} else {
BusLogic_InitializeHostStructure(HostAdapter, Host);
- scsi_add_host(Host, NULL);
+ scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL);
scsi_scan_host(Host);
BusLogicHostAdapterCount++;
}
*/
BusLogic_DestroyCCBs(HostAdapter);
BusLogic_ReleaseResources(HostAdapter);
- BusLogic_UnregisterHostAdapter(HostAdapter);
+ list_del(&HostAdapter->host_list);
scsi_host_put(Host);
}
}
kfree(PrototypeHostAdapter);
kfree(BusLogic_ProbeInfoList);
BusLogic_ProbeInfoList = NULL;
- return BusLogicHostAdapterCount;
+ return 0;
}
unregisters the BusLogic Host Adapter.
*/
-static int __exit BusLogic_ReleaseHostAdapter(struct Scsi_Host *Host)
+static int __exit BusLogic_ReleaseHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
{
- struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
+ struct Scsi_Host *Host = HostAdapter->SCSI_Host;
+
+ scsi_remove_host(Host);
+
/*
FlashPoint Host Adapters must first be released by the FlashPoint
SCCB Manager.
/*
Remove Host Adapter from the list of registered BusLogic Host Adapters.
*/
- BusLogic_UnregisterHostAdapter(HostAdapter);
+ list_del(&HostAdapter->host_list);
+
+ scsi_host_put(Host);
return 0;
}
/*
Acquire exclusive access to Host Adapter.
*/
- BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
+ spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, ProcessorFlags);
/*
Handle Interrupts appropriately for each Host Adapter type.
*/
/*
Release exclusive access to Host Adapter.
*/
- BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
+ spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, ProcessorFlags);
return IRQ_HANDLED;
}
/* Error Handling (EH) support */
-static int BusLogic_host_reset(Scsi_Cmnd * SCpnt)
+static int BusLogic_host_reset(struct scsi_cmnd * SCpnt)
{
struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata;
unsigned int id = SCpnt->device->id;
struct BusLogic_TargetStatistics *stats = &HostAdapter->TargetStatistics[id];
+ int rc;
+
+ spin_lock_irq(SCpnt->device->host->host_lock);
+
BusLogic_IncrementErrorCounter(&stats->HostAdapterResetsRequested);
- return BusLogic_ResetHostAdapter(HostAdapter, false);
+ rc = BusLogic_ResetHostAdapter(HostAdapter, false);
+ spin_unlock_irq(SCpnt->device->host->host_lock);
+ return rc;
}
/*
*/
CCB = BusLogic_AllocateCCB(HostAdapter);
if (CCB == NULL) {
- BusLogic_ReleaseHostAdapterLock(HostAdapter);
+ spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
BusLogic_Delay(1);
- BusLogic_AcquireHostAdapterLock(HostAdapter);
+ spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
CCB = BusLogic_AllocateCCB(HostAdapter);
if (CCB == NULL) {
Command->result = DID_ERROR << 16;
if (SegmentCount == 0 && BufferLength != 0) {
CCB->Opcode = BusLogic_InitiatorCCB;
CCB->DataLength = BufferLength;
- CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device, BufferPointer, BufferLength, scsi_to_pci_dma_dir(Command->sc_data_direction));
+ CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device,
+ BufferPointer, BufferLength,
+ Command->sc_data_direction);
} else if (SegmentCount != 0) {
struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer;
int Segment, Count;
- Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount, scsi_to_pci_dma_dir(Command->sc_data_direction));
+ Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount,
+ Command->sc_data_direction);
CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
error as a Host Adapter Hard Reset should be initiated soon.
*/
if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
- BusLogic_ReleaseHostAdapterLock(HostAdapter);
+ spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
BusLogic_Warning("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", HostAdapter);
BusLogic_Delay(1);
- BusLogic_AcquireHostAdapterLock(HostAdapter);
+ spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
BusLogic_Warning("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", HostAdapter);
BusLogic_DeallocateCCB(CCB);
int TargetID = Command->device->id;
struct BusLogic_CCB *CCB;
BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
- /*
- If this Command has already completed, then no Abort is necessary.
- */
- if (Command->serial_number != Command->serial_number_at_timeout) {
- BusLogic_Warning("Unable to Abort Command to Target %d - " "Already Completed\n", HostAdapter, TargetID);
- return SUCCESS;
- }
/*
Attempt to find an Active CCB for this Command. If no Active CCB for this
Command is found, then no Abort is necessary.
*/
if (HardReset) {
- BusLogic_ReleaseHostAdapterLock(HostAdapter);
+ spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
BusLogic_Delay(HostAdapter->BusSettleTime);
- BusLogic_AcquireHostAdapterLock(HostAdapter);
+ spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
}
for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, char **StartPointer, off_t Offset, int BytesAvailable, int WriteFlag)
{
- struct BusLogic_HostAdapter *HostAdapter;
+ struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) shost->hostdata;
struct BusLogic_TargetStatistics *TargetStatistics;
int TargetID, Length;
char *Buffer;
- for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next)
- if (HostAdapter->HostNumber == shost->host_no)
- break;
- if (HostAdapter == NULL) {
- BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n", NULL, shost->host_no);
- return 0;
- }
+
TargetStatistics = HostAdapter->TargetStatistics;
if (WriteFlag) {
HostAdapter->ExternalHostAdapterResets = 0;
Get it all started
*/
-static struct scsi_host_template driver_template = {
+static struct scsi_host_template Bus_Logic_template = {
.module = THIS_MODULE,
.proc_name = "BusLogic",
.proc_info = BusLogic_ProcDirectoryInfo,
return BusLogic_ParseDriverOptions(str);
}
-/*
- * Initialization function
- */
-
-static int __init BusLogic_init(void)
-{
-
-#ifdef MODULE
- if (BusLogic)
- BusLogic_Setup(BusLogic);
-#endif
-
- return BusLogic_DetectHostAdapter(&driver_template) ? 0 : -ENODEV;
-}
-
/*
* Exit function. Deletes all hosts associated with this driver.
*/
static void __exit BusLogic_exit(void)
{
- struct BusLogic_HostAdapter *HostAdapter;
- for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
- struct Scsi_Host *host = HostAdapter->SCSI_Host;
- scsi_remove_host(host);
+ struct BusLogic_HostAdapter *ha, *next;
- }
- for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
- struct Scsi_Host *host = HostAdapter->SCSI_Host;
- BusLogic_ReleaseHostAdapter(host);
- }
+ list_for_each_entry_safe(ha, next, &BusLogic_host_list, host_list)
+ BusLogic_ReleaseHostAdapter(ha);
}
__setup("BusLogic=", BusLogic_Setup);