struct proc_dir_entry *mpt_proc_root_dir;
+DmpServices_t *DmpService;
+
#define WHOINIT_UNKNOWN 0xAA
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
+static int FusionInitCalled = 0;
static int mpt_base_index = -1;
static int last_drv_idx = -1;
*/
static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
-static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
- u32 *req, int replyBytes, u16 *u16reply, int maxwait,
- int sleepFlag);
+
static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
static void mpt_adapter_disable(MPT_ADAPTER *ioc);
ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
- if (ioc->bus_type == FC)
+ if ((int)ioc->chip_type <= (int)FC929)
mpt_fc_log_info(ioc, log_info);
- else if (ioc->bus_type == SCSI)
+ else
mpt_sp_log_info(ioc, log_info);
}
if (ioc_stat & MPI_IOCSTATUS_MASK) {
- if (ioc->bus_type == SCSI)
+ if ((int)ioc->chip_type <= (int)FC929)
+ ;
+ else
mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
}
} else {
}
#ifdef MPT_DEBUG_IRQ
- if (ioc->bus_type == SCSI) {
+ if ((int)ioc->chip_type > (int)FC929) {
/* Verify mf, mr are reasonable.
*/
if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
/* Put Request back on FreeQ! */
spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
+ Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
#ifdef MFCNT
ioc->mfcnt--;
#endif
del_timer(&pCfg->timer);
spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_del(&pCfg->linkage);
+ Q_DEL_ITEM(&pCfg->linkage);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
/*
last_drv_idx = -1;
+#ifndef MODULE
+ /*
+ * Handle possibility of the mptscsih_detect() routine getting
+ * called *before* fusion_init!
+ */
+ if (!FusionInitCalled) {
+ dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n"));
+ /*
+ * NOTE! We'll get recursion here, as fusion_init()
+ * calls mpt_register()!
+ */
+ fusion_init();
+ FusionInitCalled++;
+ }
+#endif
+
/*
* Search for empty callback slot in this order: {N,...,7,6,5,...,1}
* (slot/handle 0 is reserved!)
return NULL;
spin_lock_irqsave(&ioc->FreeQlock, flags);
- if (!list_empty(&ioc->FreeQ)) {
+ if (! Q_IS_EMPTY(&ioc->FreeQ)) {
int req_offset;
- mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
- u.frame.linkage.list);
- list_del(&mf->u.frame.linkage.list);
+ mf = ioc->FreeQ.head;
+ Q_DEL_ITEM(&mf->u.frame.linkage);
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
/* u16! */
/* Put Request back on FreeQ! */
spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
+ Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
#ifdef MFCNT
ioc->mfcnt--;
#endif
}
}
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_add_chain - Place a chain SGE at address pAddr.
+ * @pAddr: virtual address for SGE
+ * @next: nextChainOffset value (u32's)
+ * @length: length of next SGL segment
+ * @dma_addr: Physical address
+ *
+ * This routine places a MPT request frame back on the MPT adapter's
+ * FreeQ.
+ */
+void
+mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
+{
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
+ u32 tmp = dma_addr & 0xFFFFFFFF;
+
+ pChain->Length = cpu_to_le16(length);
+ pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
+
+ pChain->NextChainOffset = next;
+
+ pChain->Address.Low = cpu_to_le32(tmp);
+ tmp = (u32) ((u64)dma_addr >> 32);
+ pChain->Address.High = cpu_to_le32(tmp);
+ } else {
+ SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
+ pChain->Length = cpu_to_le16(length);
+ pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
+ pChain->NextChainOffset = next;
+ pChain->Address = cpu_to_le32(dma_addr);
+ }
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mpt_send_handshake_request - Send MPT request via doorbell
mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
MPT_ADAPTER *ioc;
- u8 __iomem *mem;
+ u8 *mem;
unsigned long mem_phys;
unsigned long port;
u32 msize;
/* Initialize the running configQ head.
*/
- INIT_LIST_HEAD(&ioc->configQ);
+ Q_INIT(&ioc->configQ, Q_ITEM);
/* Find lookup slot. */
INIT_LIST_HEAD(&ioc->list);
&ioc->facts, &ioc->pfacts[0]));
ioc->mem_phys = mem_phys;
- ioc->chip = (SYSIF_REGS __iomem *)mem;
+ ioc->chip = (SYSIF_REGS*)mem;
/* Save Port IO values in case we need to do downloadboot */
{
u8 *pmem = (u8*)port;
ioc->pio_mem_phys = port;
- ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
+ ioc->pio_chip = (SYSIF_REGS*)pmem;
}
+ ioc->chip_type = FCUNK;
if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
+ ioc->chip_type = FC909;
ioc->prod_name = "LSIFC909";
- ioc->bus_type = FC;
}
if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
+ ioc->chip_type = FC929;
ioc->prod_name = "LSIFC929";
- ioc->bus_type = FC;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
+ ioc->chip_type = FC919;
ioc->prod_name = "LSIFC919";
- ioc->bus_type = FC;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
+ ioc->chip_type = FC929X;
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
- ioc->bus_type = FC;
if (revision < XL_929) {
ioc->prod_name = "LSIFC929X";
/* 929X Chip Fix. Set Split transactions level
}
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
+ ioc->chip_type = FC919X;
ioc->prod_name = "LSIFC919X";
- ioc->bus_type = FC;
/* 919X Chip Fix. Set Split transactions level
* for PCIX. Set MOST bits to zero.
*/
pci_write_config_byte(pdev, 0x6a, pcixcmd);
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
+ ioc->chip_type = C1030;
ioc->prod_name = "LSI53C1030";
- ioc->bus_type = SCSI;
/* 1030 Chip Fix. Disable Split transactions
* for PCIX. Set MOST bits to zero if Rev < C0( = 8).
*/
}
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
+ ioc->chip_type = C1035;
ioc->prod_name = "LSI53C1035";
- ioc->bus_type = SCSI;
}
sprintf(ioc->name, "ioc%d", ioc->id);
/* NEW! 20010220 -sralston
* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
*/
- mpt_detect_bound_ports(ioc, pdev);
+ if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030)
+ || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X))
+ mpt_detect_bound_ports(ioc, pdev);
if ((r = mpt_do_ioc_recovery(ioc,
MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
}
}
- pci_save_state(pdev);
+ pci_save_state(pdev, ioc->PciState);
/* put ioc into READY_STATE */
if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
ioc->name, pdev, pci_name(pdev), device_state);
pci_set_power_state(pdev, 0);
- pci_restore_state(pdev);
+ pci_restore_state(pdev, ioc->PciState);
pci_enable_device(pdev);
/* enable interrupts */
* and we try GetLanConfigPages again...
*/
if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
- if (ioc->bus_type == FC) {
+ if ((int)ioc->chip_type <= (int)FC929) {
/*
* Pre-fetch FC port WWN and stuff...
* (FCPortPage0_t stuff)
}
if (ioc->memmap != NULL)
- iounmap(ioc->memmap);
+ iounmap((u8 *) ioc->memmap);
#if defined(CONFIG_MTRR) && 0
if (ioc->mtrr_reg > 0) {
}
/* Is it already READY? */
- if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
- return 0;
+ if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) {
+ if ((int)ioc->chip_type <= (int)FC929)
+ return 0;
+ else {
+ return 0;
+ /* Workaround from broken 1030 FW.
+ * Force a diagnostic reset if fails.
+ */
+/* if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
+ return 0;
+ else
+ statefault = 4; */
+ }
+ }
/*
* Check to see if IOC is in FAULT state.
}
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible(1);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1 * HZ / 1000);
} else {
mdelay (1); /* 1 msec delay */
}
ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
ioc->name, ioc->upload_fw, ioc->facts.Flags));
- if (ioc->bus_type == FC)
+ if ((int)ioc->chip_type <= (int)FC929) {
ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
- else
+ } else {
ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
-
+ }
ioc_init.MaxBuses = MPT_MAX_BUS;
ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
state = mpt_GetIocState(ioc, 1);
while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible(1);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1 * HZ / 1000);
} else {
mdelay(1);
}
/* RAID FW may take a long time to enable
*/
- if (ioc->bus_type == FC) {
+ if ((int)ioc->chip_type <= (int)FC929) {
ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
} else {
/* wait 1 msec */
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible(1);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1 * HZ / 1000);
} else {
mdelay (1);
}
}
/* wait 1 sec */
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible (1000);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1000 * HZ / 1000);
} else {
mdelay (1000);
}
return 0;
}
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible (10);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(10 * HZ / 1000);
} else {
mdelay (10);
}
int cnt,cntdn;
dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
- if (ioc->bus_type == SCSI) {
+ if ((int)ioc->chip_type > (int)FC929) {
/* Always issue a Msg Unit Reset first. This will clear some
* SCSI bus hang conditions.
*/
SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible (1000);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1000 * HZ / 1000);
} else {
mdelay (1000);
}
return hard_reset_done;
}
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible (10);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(10 * HZ / 1000);
} else {
mdelay (10);
}
/* wait 100 msec */
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible (100);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(100 * HZ / 1000);
} else {
mdelay (100);
}
/* wait 1 sec */
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible (1000);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1000 * HZ / 1000);
} else {
mdelay (1000);
}
/* wait 100 msec */
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible (100);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(100 * HZ / 1000);
} else {
mdelay (100);
}
}
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible(1);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1 * HZ / 1000);
} else {
mdelay (1); /* 1 msec delay */
}
dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
ioc->name, numSGE, num_sge, num_chain));
- if (ioc->bus_type == SCSI)
+ if ((int) ioc->chip_type > (int) FC929)
num_chain *= MPT_SCSI_CAN_QUEUE;
else
num_chain *= MPT_FC_CAN_QUEUE;
/* Initialize the free chain Q.
*/
- INIT_LIST_HEAD(&ioc->FreeChainQ);
+ Q_INIT(&ioc->FreeChainQ, MPT_FRAME_HDR);
/* Post the chain buffers to the FreeChainQ.
*/
mem = (u8 *)ioc->ChainBuffer;
for (i=0; i < num_chain; i++) {
mf = (MPT_FRAME_HDR *) mem;
- list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
+ Q_ADD_TAIL(&ioc->FreeChainQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
mem += ioc->req_sz;
}
mem = (u8 *) ioc->req_frames;
spin_lock_irqsave(&ioc->FreeQlock, flags);
- INIT_LIST_HEAD(&ioc->FreeQ);
+ Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
for (i = 0; i < ioc->req_depth; i++) {
mf = (MPT_FRAME_HDR *) mem;
/* Queue REQUESTs *internally*! */
- list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
-
+ Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
mem += ioc->req_sz;
}
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
*
* Returns 0 for success, non-zero for failure.
*/
-static int
+int
mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
{
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
break;
- msleep_interruptible (1);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1 * HZ / 1000);
count++;
}
} else {
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
break;
- msleep_interruptible(1);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1 * HZ / 1000);
count++;
}
} else {
/* Add to end of Q, set timer and then issue this command */
spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_add_tail(&pCfg->linkage, &ioc->configQ);
+ Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
add_timer(&pCfg->timer);
/* Add to end of Q, set timer and then issue this command */
spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_add_tail(&pCfg->linkage, &ioc->configQ);
+ Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
add_timer(&pCfg->timer);
* the FIFO's are primed.
*/
spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_for_each_entry(pCfg, &ioc->configQ, linkage)
- del_timer(&pCfg->timer);
+ if (! Q_IS_EMPTY(&ioc->configQ)){
+ pCfg = (CONFIGPARMS *)ioc->configQ.head;
+ do {
+ del_timer(&pCfg->timer);
+ pCfg = (CONFIGPARMS *) (pCfg->linkage.forw);
+ } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
+ }
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
} else {
* Flush the Q, and wake up all suspended threads.
*/
spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
- list_del(&pCfg->linkage);
+ if (! Q_IS_EMPTY(&ioc->configQ)){
+ pCfg = (CONFIGPARMS *)ioc->configQ.head;
+ do {
+ pNext = (CONFIGPARMS *) pCfg->linkage.forw;
- pCfg->status = MPT_CONFIG_ERROR;
- pCfg->wait_done = 1;
- wake_up(&mpt_waitq);
+ Q_DEL_ITEM(&pCfg->linkage);
+
+ pCfg->status = MPT_CONFIG_ERROR;
+ pCfg->wait_done = 1;
+ wake_up(&mpt_waitq);
+
+ pCfg = pNext;
+ } while (pCfg != (CONFIGPARMS *)&ioc->configQ);
}
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
}
case MPTCTL_DRIVER:
if (!ctl++) drvname = "ioctl";
break;
+ case MPTDMP_DRIVER:
+ if (!dmp++) drvname = "DMP";
+ break;
}
if (drvname)
len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
p+1,
ioc->facts.NumberOfPorts);
- if (ioc->bus_type == FC) {
+ if ((int)ioc->chip_type <= (int)FC929) {
if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
EXPORT_SYMBOL(ioc_list);
EXPORT_SYMBOL(mpt_proc_root_dir);
+EXPORT_SYMBOL(DmpService);
EXPORT_SYMBOL(mpt_register);
EXPORT_SYMBOL(mpt_deregister);
EXPORT_SYMBOL(mpt_event_register);
EXPORT_SYMBOL(mpt_put_msg_frame);
EXPORT_SYMBOL(mpt_free_msg_frame);
EXPORT_SYMBOL(mpt_add_sge);
+EXPORT_SYMBOL(mpt_add_chain);
EXPORT_SYMBOL(mpt_send_handshake_request);
+EXPORT_SYMBOL(mpt_handshake_req_reply_wait);
EXPORT_SYMBOL(mpt_verify_adapter);
EXPORT_SYMBOL(mpt_GetIocState);
EXPORT_SYMBOL(mpt_print_ioc_summary);
int i;
int r;
+ if (FusionInitCalled++) {
+ dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n"));
+ return 0;
+ }
+
show_mptmod_ver(my_NAME, my_VERSION);
printk(KERN_INFO COPYRIGHT "\n");
MptResetHandlers[i] = NULL;
}
+ DmpService = NULL;
+
/* NEW! 20010120 -sralston
* Register ourselves (mptbase) in order to facilitate
* EventNotification handling.