forked from Minki/linux
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
This commit is contained in:
commit
26d451b603
@ -1,3 +1,26 @@
|
||||
1 Release Date : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
|
||||
2 Current Version : 00.00.02.04
|
||||
3 Older Version : 00.00.02.04
|
||||
|
||||
i. Support for 1078 type (ppc IOP) controller, device id : 0x60 added.
|
||||
During initialization, depending on the device id, the template members
|
||||
are initialized with function pointers specific to the ppc or
|
||||
xscale controllers.
|
||||
|
||||
-Sumant Patro <Sumant.Patro@lsil.com>
|
||||
|
||||
1 Release Date : Fri Feb 03 14:16:25 PST 2006 - Sumant Patro
|
||||
<Sumant.Patro@lsil.com>
|
||||
2 Current Version : 00.00.02.04
|
||||
3 Older Version : 00.00.02.02
|
||||
i. Register 16 byte CDB capability with scsi midlayer
|
||||
|
||||
"Ths patch properly registers the 16 byte command length capability of the
|
||||
megaraid_sas controlled hardware with the scsi midlayer. All megaraid_sas
|
||||
hardware supports 16 byte CDB's."
|
||||
|
||||
-Joshua Giles <joshua_giles@dell.com>
|
||||
|
||||
1 Release Date : Mon Jan 23 14:09:01 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
|
||||
2 Current Version : 00.00.02.02
|
||||
3 Older Version : 00.00.02.01
|
||||
|
@ -452,8 +452,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
|
||||
} else if (func == MPI_FUNCTION_EVENT_ACK) {
|
||||
dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
|
||||
ioc->name));
|
||||
} else if (func == MPI_FUNCTION_CONFIG ||
|
||||
func == MPI_FUNCTION_TOOLBOX) {
|
||||
} else if (func == MPI_FUNCTION_CONFIG) {
|
||||
CONFIGPARMS *pCfg;
|
||||
unsigned long flags;
|
||||
|
||||
@ -5326,115 +5325,6 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/**
|
||||
* mpt_toolbox - Generic function to issue toolbox message
|
||||
* @ioc - Pointer to an adapter structure
|
||||
* @cfg - Pointer to a toolbox structure. Struct contains
|
||||
* action, page address, direction, physical address
|
||||
* and pointer to a configuration page header
|
||||
* Page header is updated.
|
||||
*
|
||||
* Returns 0 for success
|
||||
* -EPERM if not allowed due to ISR context
|
||||
* -EAGAIN if no msg frames currently available
|
||||
* -EFAULT for non-successful reply or no reply (timeout)
|
||||
*/
|
||||
int
|
||||
mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
|
||||
{
|
||||
ToolboxIstwiReadWriteRequest_t *pReq;
|
||||
MPT_FRAME_HDR *mf;
|
||||
struct pci_dev *pdev;
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
u32 flagsLength;
|
||||
int in_isr;
|
||||
|
||||
/* Prevent calling wait_event() (below), if caller happens
|
||||
* to be in ISR context, because that is fatal!
|
||||
*/
|
||||
in_isr = in_interrupt();
|
||||
if (in_isr) {
|
||||
dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
|
||||
ioc->name));
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* Get and Populate a free Frame
|
||||
*/
|
||||
if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
|
||||
dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
|
||||
ioc->name));
|
||||
return -EAGAIN;
|
||||
}
|
||||
pReq = (ToolboxIstwiReadWriteRequest_t *)mf;
|
||||
pReq->Tool = pCfg->action;
|
||||
pReq->Reserved = 0;
|
||||
pReq->ChainOffset = 0;
|
||||
pReq->Function = MPI_FUNCTION_TOOLBOX;
|
||||
pReq->Reserved1 = 0;
|
||||
pReq->Reserved2 = 0;
|
||||
pReq->MsgFlags = 0;
|
||||
pReq->Flags = pCfg->dir;
|
||||
pReq->BusNum = 0;
|
||||
pReq->Reserved3 = 0;
|
||||
pReq->NumAddressBytes = 0x01;
|
||||
pReq->Reserved4 = 0;
|
||||
pReq->DataLength = cpu_to_le16(0x04);
|
||||
pdev = ioc->pcidev;
|
||||
if (pdev->devfn & 1)
|
||||
pReq->DeviceAddr = 0xB2;
|
||||
else
|
||||
pReq->DeviceAddr = 0xB0;
|
||||
pReq->Addr1 = 0;
|
||||
pReq->Addr2 = 0;
|
||||
pReq->Addr3 = 0;
|
||||
pReq->Reserved5 = 0;
|
||||
|
||||
/* Add a SGE to the config request.
|
||||
*/
|
||||
|
||||
flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
|
||||
|
||||
mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
|
||||
|
||||
dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
|
||||
ioc->name, pReq->Tool));
|
||||
|
||||
/* Append pCfg pointer to end of mf
|
||||
*/
|
||||
*((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
|
||||
|
||||
/* Initalize the timer
|
||||
*/
|
||||
init_timer(&pCfg->timer);
|
||||
pCfg->timer.data = (unsigned long) ioc;
|
||||
pCfg->timer.function = mpt_timer_expired;
|
||||
pCfg->wait_done = 0;
|
||||
|
||||
/* Set the timer; ensure 10 second minimum */
|
||||
if (pCfg->timeout < 10)
|
||||
pCfg->timer.expires = jiffies + HZ*10;
|
||||
else
|
||||
pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
|
||||
|
||||
/* 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);
|
||||
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
|
||||
|
||||
add_timer(&pCfg->timer);
|
||||
mpt_put_msg_frame(mpt_base_index, ioc, mf);
|
||||
wait_event(mpt_waitq, pCfg->wait_done);
|
||||
|
||||
/* mf has been freed - do not access */
|
||||
|
||||
rc = pCfg->status;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* mpt_timer_expired - Call back for timer process.
|
||||
@ -6142,7 +6032,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
|
||||
if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
|
||||
int idx;
|
||||
|
||||
idx = ioc->eventContext % ioc->eventLogSize;
|
||||
idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
|
||||
|
||||
ioc->events[idx].event = event;
|
||||
ioc->events[idx].eventContext = ioc->eventContext;
|
||||
@ -6540,7 +6430,6 @@ EXPORT_SYMBOL(mpt_lan_index);
|
||||
EXPORT_SYMBOL(mpt_stm_index);
|
||||
EXPORT_SYMBOL(mpt_HardResetHandler);
|
||||
EXPORT_SYMBOL(mpt_config);
|
||||
EXPORT_SYMBOL(mpt_toolbox);
|
||||
EXPORT_SYMBOL(mpt_findImVolumes);
|
||||
EXPORT_SYMBOL(mpt_read_ioc_pg_3);
|
||||
EXPORT_SYMBOL(mpt_alloc_fw_memory);
|
||||
|
@ -616,6 +616,7 @@ typedef struct _MPT_ADAPTER
|
||||
* increments by 32 bytes
|
||||
*/
|
||||
int errata_flag_1064;
|
||||
int aen_event_read_flag; /* flag to indicate event log was read*/
|
||||
u8 FirstWhoInit;
|
||||
u8 upload_fw; /* If set, do a fw upload */
|
||||
u8 reload_fw; /* Force a FW Reload on next reset */
|
||||
@ -1026,7 +1027,6 @@ extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
|
||||
extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
|
||||
extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
|
||||
extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
|
||||
extern int mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
|
||||
extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
|
||||
extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
|
||||
extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
|
||||
|
@ -136,6 +136,12 @@ static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
|
||||
*/
|
||||
static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
|
||||
|
||||
/*
|
||||
* Event Handler function
|
||||
*/
|
||||
static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
|
||||
struct fasync_struct *async_queue=NULL;
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* Scatter gather list (SGL) sizes and limits...
|
||||
@ -385,18 +391,18 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
|
||||
}
|
||||
|
||||
/* Now wait for the command to complete */
|
||||
ii = wait_event_interruptible_timeout(mptctl_wait,
|
||||
ii = wait_event_timeout(mptctl_wait,
|
||||
ioctl->wait_done == 1,
|
||||
HZ*5 /* 5 second timeout */);
|
||||
|
||||
if(ii <=0 && (ioctl->wait_done != 1 )) {
|
||||
mpt_free_msg_frame(hd->ioc, mf);
|
||||
ioctl->wait_done = 0;
|
||||
retval = -1; /* return failure */
|
||||
}
|
||||
|
||||
mptctl_bus_reset_done:
|
||||
|
||||
mpt_free_msg_frame(hd->ioc, mf);
|
||||
mptctl_free_tm_flags(ioctl->ioc);
|
||||
return retval;
|
||||
}
|
||||
@ -471,6 +477,69 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/* ASYNC Event Notification Support */
|
||||
static int
|
||||
mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
|
||||
{
|
||||
u8 event;
|
||||
|
||||
event = le32_to_cpu(pEvReply->Event) & 0xFF;
|
||||
|
||||
dctlprintk(("%s() called\n", __FUNCTION__));
|
||||
if(async_queue == NULL)
|
||||
return 1;
|
||||
|
||||
/* Raise SIGIO for persistent events.
|
||||
* TODO - this define is not in MPI spec yet,
|
||||
* but they plan to set it to 0x21
|
||||
*/
|
||||
if (event == 0x21 ) {
|
||||
ioc->aen_event_read_flag=1;
|
||||
dctlprintk(("Raised SIGIO to application\n"));
|
||||
devtprintk(("Raised SIGIO to application\n"));
|
||||
kill_fasync(&async_queue, SIGIO, POLL_IN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This flag is set after SIGIO was raised, and
|
||||
* remains set until the application has read
|
||||
* the event log via ioctl=MPTEVENTREPORT
|
||||
*/
|
||||
if(ioc->aen_event_read_flag)
|
||||
return 1;
|
||||
|
||||
/* Signal only for the events that are
|
||||
* requested for by the application
|
||||
*/
|
||||
if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
|
||||
ioc->aen_event_read_flag=1;
|
||||
dctlprintk(("Raised SIGIO to application\n"));
|
||||
devtprintk(("Raised SIGIO to application\n"));
|
||||
kill_fasync(&async_queue, SIGIO, POLL_IN);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
mptctl_fasync(int fd, struct file *filep, int mode)
|
||||
{
|
||||
MPT_ADAPTER *ioc;
|
||||
|
||||
list_for_each_entry(ioc, &ioc_list, list)
|
||||
ioc->aen_event_read_flag=0;
|
||||
|
||||
dctlprintk(("%s() called\n", __FUNCTION__));
|
||||
return fasync_helper(fd, filep, mode, &async_queue);
|
||||
}
|
||||
|
||||
static int
|
||||
mptctl_release(struct inode *inode, struct file *filep)
|
||||
{
|
||||
dctlprintk(("%s() called\n", __FUNCTION__));
|
||||
return fasync_helper(-1, filep, 0, &async_queue);
|
||||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* MPT ioctl handler
|
||||
@ -674,22 +743,23 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
|
||||
u16 iocstat;
|
||||
pFWDownloadReply_t ReplyMsg = NULL;
|
||||
|
||||
dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
|
||||
dctlprintk(("mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
|
||||
|
||||
dctlprintk((KERN_INFO "DbG: kfwdl.bufp = %p\n", ufwbuf));
|
||||
dctlprintk((KERN_INFO "DbG: kfwdl.fwlen = %d\n", (int)fwlen));
|
||||
dctlprintk((KERN_INFO "DbG: kfwdl.ioc = %04xh\n", ioc));
|
||||
dctlprintk(("DbG: kfwdl.bufp = %p\n", ufwbuf));
|
||||
dctlprintk(("DbG: kfwdl.fwlen = %d\n", (int)fwlen));
|
||||
dctlprintk(("DbG: kfwdl.ioc = %04xh\n", ioc));
|
||||
|
||||
if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) {
|
||||
dctlprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n",
|
||||
__FILE__, __LINE__, ioc));
|
||||
if (mpt_verify_adapter(ioc, &iocp) < 0) {
|
||||
dctlprintk(("ioctl_fwdl - ioc%d not found!\n",
|
||||
ioc));
|
||||
return -ENODEV; /* (-6) No such device or address */
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Valid device. Get a message frame and construct the FW download message.
|
||||
*/
|
||||
if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
|
||||
return -EAGAIN;
|
||||
/* Valid device. Get a message frame and construct the FW download message.
|
||||
*/
|
||||
if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
|
||||
return -EAGAIN;
|
||||
}
|
||||
dlmsg = (FWDownload_t*) mf;
|
||||
ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
|
||||
sgOut = (char *) (ptsge + 1);
|
||||
@ -702,7 +772,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
|
||||
dlmsg->ChainOffset = 0;
|
||||
dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD;
|
||||
dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0;
|
||||
dlmsg->MsgFlags = 0;
|
||||
if (iocp->facts.MsgVersion >= MPI_VERSION_01_05)
|
||||
dlmsg->MsgFlags = MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT;
|
||||
else
|
||||
dlmsg->MsgFlags = 0;
|
||||
|
||||
|
||||
/* Set up the Transaction SGE.
|
||||
*/
|
||||
@ -754,7 +828,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
|
||||
goto fwdl_out;
|
||||
}
|
||||
|
||||
dctlprintk((KERN_INFO "DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags));
|
||||
dctlprintk(("DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags));
|
||||
|
||||
/*
|
||||
* Parse SG list, copying sgl itself,
|
||||
@ -803,11 +877,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
|
||||
/*
|
||||
* Finally, perform firmware download.
|
||||
*/
|
||||
iocp->ioctl->wait_done = 0;
|
||||
ReplyMsg = NULL;
|
||||
mpt_put_msg_frame(mptctl_id, iocp, mf);
|
||||
|
||||
/* Now wait for the command to complete */
|
||||
ret = wait_event_interruptible_timeout(mptctl_wait,
|
||||
ret = wait_event_timeout(mptctl_wait,
|
||||
iocp->ioctl->wait_done == 1,
|
||||
HZ*60);
|
||||
|
||||
@ -1145,7 +1219,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
|
||||
/* Fill in the data and return the structure to the calling
|
||||
* program
|
||||
*/
|
||||
if (ioc->bus_type == FC)
|
||||
if (ioc->bus_type == SAS)
|
||||
karg->adapterType = MPT_IOCTL_INTERFACE_SAS;
|
||||
else if (ioc->bus_type == FC)
|
||||
karg->adapterType = MPT_IOCTL_INTERFACE_FC;
|
||||
else
|
||||
karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
|
||||
@ -1170,12 +1246,11 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
|
||||
karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
|
||||
karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
|
||||
} else if (cim_rev == 2) {
|
||||
/* Get the PCI bus, device, function and segment ID numbers
|
||||
/* Get the PCI bus, device, function and segment ID numbers
|
||||
for the IOC */
|
||||
karg->pciInfo.u.bits.busNumber = pdev->bus->number;
|
||||
karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
|
||||
karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
|
||||
karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
|
||||
karg->pciInfo.segmentID = pci_domain_nr(pdev->bus);
|
||||
}
|
||||
|
||||
@ -1500,7 +1575,7 @@ mptctl_eventquery (unsigned long arg)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
karg.eventEntries = ioc->eventLogSize;
|
||||
karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
|
||||
karg.eventTypes = ioc->eventTypes;
|
||||
|
||||
/* Copy the data from kernel memory to user memory
|
||||
@ -1550,7 +1625,6 @@ mptctl_eventenable (unsigned long arg)
|
||||
memset(ioc->events, 0, sz);
|
||||
ioc->alloc_total += sz;
|
||||
|
||||
ioc->eventLogSize = MPTCTL_EVENT_LOG_SIZE;
|
||||
ioc->eventContext = 0;
|
||||
}
|
||||
|
||||
@ -1590,7 +1664,7 @@ mptctl_eventreport (unsigned long arg)
|
||||
maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS);
|
||||
|
||||
|
||||
max = ioc->eventLogSize < maxEvents ? ioc->eventLogSize : maxEvents;
|
||||
max = MPTCTL_EVENT_LOG_SIZE < maxEvents ? MPTCTL_EVENT_LOG_SIZE : maxEvents;
|
||||
|
||||
/* If fewer than 1 event is requested, there must have
|
||||
* been some type of error.
|
||||
@ -1598,6 +1672,9 @@ mptctl_eventreport (unsigned long arg)
|
||||
if ((max < 1) || !ioc->events)
|
||||
return -ENODATA;
|
||||
|
||||
/* reset this flag so SIGIO can restart */
|
||||
ioc->aen_event_read_flag=0;
|
||||
|
||||
/* Copy the data from kernel memory to user memory
|
||||
*/
|
||||
numBytes = max * sizeof(MPT_IOCTL_EVENTS);
|
||||
@ -1817,6 +1894,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
|
||||
case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
|
||||
case MPI_FUNCTION_FW_DOWNLOAD:
|
||||
case MPI_FUNCTION_FC_PRIMITIVE_SEND:
|
||||
case MPI_FUNCTION_TOOLBOX:
|
||||
case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
|
||||
break;
|
||||
|
||||
case MPI_FUNCTION_SCSI_IO_REQUEST:
|
||||
@ -1837,7 +1916,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
|
||||
goto done_free_mem;
|
||||
}
|
||||
|
||||
pScsiReq->MsgFlags = mpt_msg_flags();
|
||||
pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
|
||||
pScsiReq->MsgFlags |= mpt_msg_flags();
|
||||
|
||||
|
||||
/* verify that app has not requested
|
||||
* more sense data than driver
|
||||
@ -1888,6 +1969,25 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
|
||||
}
|
||||
break;
|
||||
|
||||
case MPI_FUNCTION_SMP_PASSTHROUGH:
|
||||
/* Check mf->PassthruFlags to determine if
|
||||
* transfer is ImmediateMode or not.
|
||||
* Immediate mode returns data in the ReplyFrame.
|
||||
* Else, we are sending request and response data
|
||||
* in two SGLs at the end of the mf.
|
||||
*/
|
||||
break;
|
||||
|
||||
case MPI_FUNCTION_SATA_PASSTHROUGH:
|
||||
if (!ioc->sh) {
|
||||
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
|
||||
"SCSI driver is not loaded. \n",
|
||||
__FILE__, __LINE__);
|
||||
rc = -EFAULT;
|
||||
goto done_free_mem;
|
||||
}
|
||||
break;
|
||||
|
||||
case MPI_FUNCTION_RAID_ACTION:
|
||||
/* Just add a SGE
|
||||
*/
|
||||
@ -1900,7 +2000,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
|
||||
int scsidir = MPI_SCSIIO_CONTROL_READ;
|
||||
int dataSize;
|
||||
|
||||
pScsiReq->MsgFlags = mpt_msg_flags();
|
||||
pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
|
||||
pScsiReq->MsgFlags |= mpt_msg_flags();
|
||||
|
||||
|
||||
/* verify that app has not requested
|
||||
* more sense data than driver
|
||||
@ -2130,7 +2232,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
|
||||
|
||||
/* Now wait for the command to complete */
|
||||
timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
|
||||
timeout = wait_event_interruptible_timeout(mptctl_wait,
|
||||
timeout = wait_event_timeout(mptctl_wait,
|
||||
ioc->ioctl->wait_done == 1,
|
||||
HZ*timeout);
|
||||
|
||||
@ -2246,13 +2348,16 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
|
||||
hp_host_info_t __user *uarg = (void __user *) arg;
|
||||
MPT_ADAPTER *ioc;
|
||||
struct pci_dev *pdev;
|
||||
char *pbuf;
|
||||
char *pbuf=NULL;
|
||||
dma_addr_t buf_dma;
|
||||
hp_host_info_t karg;
|
||||
CONFIGPARMS cfg;
|
||||
ConfigPageHeader_t hdr;
|
||||
int iocnum;
|
||||
int rc, cim_rev;
|
||||
ToolboxIstwiReadWriteRequest_t *IstwiRWRequest;
|
||||
MPT_FRAME_HDR *mf = NULL;
|
||||
MPIHeader_t *mpi_hdr;
|
||||
|
||||
dctlprintk((": mptctl_hp_hostinfo called.\n"));
|
||||
/* Reset long to int. Should affect IA64 and SPARC only
|
||||
@ -2370,7 +2475,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
|
||||
|
||||
karg.base_io_addr = pci_resource_start(pdev, 0);
|
||||
|
||||
if (ioc->bus_type == FC)
|
||||
if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
|
||||
karg.bus_phys_width = HP_BUS_WIDTH_UNK;
|
||||
else
|
||||
karg.bus_phys_width = HP_BUS_WIDTH_16;
|
||||
@ -2388,20 +2493,67 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
|
||||
}
|
||||
}
|
||||
|
||||
cfg.pageAddr = 0;
|
||||
cfg.action = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
|
||||
cfg.dir = MPI_TB_ISTWI_FLAGS_READ;
|
||||
cfg.timeout = 10;
|
||||
pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
|
||||
if (pbuf) {
|
||||
cfg.physAddr = buf_dma;
|
||||
if ((mpt_toolbox(ioc, &cfg)) == 0) {
|
||||
karg.rsvd = *(u32 *)pbuf;
|
||||
}
|
||||
pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
|
||||
pbuf = NULL;
|
||||
/*
|
||||
* Gather ISTWI(Industry Standard Two Wire Interface) Data
|
||||
*/
|
||||
if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
|
||||
dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
|
||||
ioc->name,__FUNCTION__));
|
||||
goto out;
|
||||
}
|
||||
|
||||
IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf;
|
||||
mpi_hdr = (MPIHeader_t *) mf;
|
||||
memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t));
|
||||
IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX;
|
||||
IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
|
||||
IstwiRWRequest->MsgContext = mpi_hdr->MsgContext;
|
||||
IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ;
|
||||
IstwiRWRequest->NumAddressBytes = 0x01;
|
||||
IstwiRWRequest->DataLength = cpu_to_le16(0x04);
|
||||
if (pdev->devfn & 1)
|
||||
IstwiRWRequest->DeviceAddr = 0xB2;
|
||||
else
|
||||
IstwiRWRequest->DeviceAddr = 0xB0;
|
||||
|
||||
pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
|
||||
if (!pbuf)
|
||||
goto out;
|
||||
mpt_add_sge((char *)&IstwiRWRequest->SGL,
|
||||
(MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
|
||||
|
||||
ioc->ioctl->wait_done = 0;
|
||||
mpt_put_msg_frame(mptctl_id, ioc, mf);
|
||||
|
||||
rc = wait_event_timeout(mptctl_wait,
|
||||
ioc->ioctl->wait_done == 1,
|
||||
HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
|
||||
|
||||
if(rc <=0 && (ioc->ioctl->wait_done != 1 )) {
|
||||
/*
|
||||
* Now we need to reset the board
|
||||
*/
|
||||
mpt_free_msg_frame(ioc, mf);
|
||||
mptctl_timeout_expired(ioc->ioctl);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
*ISTWI Data Definition
|
||||
* pbuf[0] = FW_VERSION = 0x4
|
||||
* pbuf[1] = Bay Count = 6 or 4 or 2, depending on
|
||||
* the config, you should be seeing one out of these three values
|
||||
* pbuf[2] = Drive Installed Map = bit pattern depend on which
|
||||
* bays have drives in them
|
||||
* pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3)
|
||||
*/
|
||||
if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID)
|
||||
karg.rsvd = *(u32 *)pbuf;
|
||||
|
||||
out:
|
||||
if (pbuf)
|
||||
pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
|
||||
|
||||
/* Copy the data from kernel memory to user memory
|
||||
*/
|
||||
if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
|
||||
@ -2459,7 +2611,7 @@ mptctl_hp_targetinfo(unsigned long arg)
|
||||
|
||||
/* There is nothing to do for FCP parts.
|
||||
*/
|
||||
if (ioc->bus_type == FC)
|
||||
if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
|
||||
return 0;
|
||||
|
||||
if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL))
|
||||
@ -2569,6 +2721,8 @@ mptctl_hp_targetinfo(unsigned long arg)
|
||||
static struct file_operations mptctl_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.release = mptctl_release,
|
||||
.fasync = mptctl_fasync,
|
||||
.unlocked_ioctl = mptctl_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = compat_mpctl_ioctl,
|
||||
@ -2813,6 +2967,11 @@ static int __init mptctl_init(void)
|
||||
/* FIXME! */
|
||||
}
|
||||
|
||||
if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
|
||||
devtprintk((KERN_INFO MYNAM
|
||||
": Registered for IOC event notifications\n"));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_fail:
|
||||
|
@ -169,8 +169,10 @@ struct mpt_ioctl_pci_info2 {
|
||||
* Read only.
|
||||
* Data starts at offset 0xC
|
||||
*/
|
||||
#define MPT_IOCTL_INTERFACE_FC (0x01)
|
||||
#define MPT_IOCTL_INTERFACE_SCSI (0x00)
|
||||
#define MPT_IOCTL_INTERFACE_FC (0x01)
|
||||
#define MPT_IOCTL_INTERFACE_FC_IP (0x02)
|
||||
#define MPT_IOCTL_INTERFACE_SAS (0x03)
|
||||
#define MPT_IOCTL_VERSION_LENGTH (32)
|
||||
|
||||
struct mpt_ioctl_iocinfo {
|
||||
|
@ -2489,7 +2489,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
|
||||
int idx;
|
||||
MPT_ADAPTER *ioc = hd->ioc;
|
||||
|
||||
idx = ioc->eventContext % ioc->eventLogSize;
|
||||
idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
|
||||
ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
|
||||
ioc->events[idx].eventContext = ioc->eventContext;
|
||||
|
||||
|
@ -710,10 +710,9 @@ static inline void
|
||||
_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
|
||||
struct zfcp_adapter *adapter,
|
||||
struct scsi_cmnd *scsi_cmnd,
|
||||
struct zfcp_fsf_req *new_fsf_req)
|
||||
struct zfcp_fsf_req *fsf_req,
|
||||
struct zfcp_fsf_req *old_fsf_req)
|
||||
{
|
||||
struct zfcp_fsf_req *fsf_req =
|
||||
(struct zfcp_fsf_req *)scsi_cmnd->host_scribble;
|
||||
struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
|
||||
struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
|
||||
unsigned long flags;
|
||||
@ -727,19 +726,20 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
|
||||
if (offset == 0) {
|
||||
strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
|
||||
strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
|
||||
if (scsi_cmnd->device) {
|
||||
rec->scsi_id = scsi_cmnd->device->id;
|
||||
rec->scsi_lun = scsi_cmnd->device->lun;
|
||||
if (scsi_cmnd != NULL) {
|
||||
if (scsi_cmnd->device) {
|
||||
rec->scsi_id = scsi_cmnd->device->id;
|
||||
rec->scsi_lun = scsi_cmnd->device->lun;
|
||||
}
|
||||
rec->scsi_result = scsi_cmnd->result;
|
||||
rec->scsi_cmnd = (unsigned long)scsi_cmnd;
|
||||
rec->scsi_serial = scsi_cmnd->serial_number;
|
||||
memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
|
||||
min((int)scsi_cmnd->cmd_len,
|
||||
ZFCP_DBF_SCSI_OPCODE));
|
||||
rec->scsi_retries = scsi_cmnd->retries;
|
||||
rec->scsi_allowed = scsi_cmnd->allowed;
|
||||
}
|
||||
rec->scsi_result = scsi_cmnd->result;
|
||||
rec->scsi_cmnd = (unsigned long)scsi_cmnd;
|
||||
rec->scsi_serial = scsi_cmnd->serial_number;
|
||||
memcpy(rec->scsi_opcode,
|
||||
&scsi_cmnd->cmnd,
|
||||
min((int)scsi_cmnd->cmd_len,
|
||||
ZFCP_DBF_SCSI_OPCODE));
|
||||
rec->scsi_retries = scsi_cmnd->retries;
|
||||
rec->scsi_allowed = scsi_cmnd->allowed;
|
||||
if (fsf_req != NULL) {
|
||||
fcp_rsp = (struct fcp_rsp_iu *)
|
||||
&(fsf_req->qtcb->bottom.io.fcp_rsp);
|
||||
@ -772,15 +772,8 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
|
||||
rec->fsf_seqno = fsf_req->seq_no;
|
||||
rec->fsf_issued = fsf_req->issued;
|
||||
}
|
||||
if (new_fsf_req != NULL) {
|
||||
rec->type.new_fsf_req.fsf_reqid =
|
||||
(unsigned long)
|
||||
new_fsf_req;
|
||||
rec->type.new_fsf_req.fsf_seqno =
|
||||
new_fsf_req->seq_no;
|
||||
rec->type.new_fsf_req.fsf_issued =
|
||||
new_fsf_req->issued;
|
||||
}
|
||||
rec->type.old_fsf_reqid =
|
||||
(unsigned long) old_fsf_req;
|
||||
} else {
|
||||
strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
|
||||
dump->total_size = buflen;
|
||||
@ -801,19 +794,21 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
|
||||
inline void
|
||||
zfcp_scsi_dbf_event_result(const char *tag, int level,
|
||||
struct zfcp_adapter *adapter,
|
||||
struct scsi_cmnd *scsi_cmnd)
|
||||
struct scsi_cmnd *scsi_cmnd,
|
||||
struct zfcp_fsf_req *fsf_req)
|
||||
{
|
||||
_zfcp_scsi_dbf_event_common("rslt",
|
||||
tag, level, adapter, scsi_cmnd, NULL);
|
||||
_zfcp_scsi_dbf_event_common("rslt", tag, level,
|
||||
adapter, scsi_cmnd, fsf_req, NULL);
|
||||
}
|
||||
|
||||
inline void
|
||||
zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
|
||||
struct scsi_cmnd *scsi_cmnd,
|
||||
struct zfcp_fsf_req *new_fsf_req)
|
||||
struct zfcp_fsf_req *new_fsf_req,
|
||||
struct zfcp_fsf_req *old_fsf_req)
|
||||
{
|
||||
_zfcp_scsi_dbf_event_common("abrt",
|
||||
tag, 1, adapter, scsi_cmnd, new_fsf_req);
|
||||
_zfcp_scsi_dbf_event_common("abrt", tag, 1,
|
||||
adapter, scsi_cmnd, new_fsf_req, old_fsf_req);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -823,7 +818,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
|
||||
struct zfcp_adapter *adapter = unit->port->adapter;
|
||||
|
||||
_zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
|
||||
tag, 1, adapter, scsi_cmnd, NULL);
|
||||
tag, 1, adapter, scsi_cmnd, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -856,6 +851,10 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
|
||||
rec->scsi_retries);
|
||||
len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
|
||||
rec->scsi_allowed);
|
||||
if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
|
||||
len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx",
|
||||
rec->type.old_fsf_reqid);
|
||||
}
|
||||
len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
|
||||
rec->fsf_reqid);
|
||||
len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
|
||||
@ -883,21 +882,6 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
|
||||
min((int)rec->type.fcp.sns_info_len,
|
||||
ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
|
||||
rec->type.fcp.sns_info_len);
|
||||
} else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
|
||||
len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx",
|
||||
rec->type.new_fsf_req.fsf_reqid);
|
||||
len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x",
|
||||
rec->type.new_fsf_req.fsf_seqno);
|
||||
len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
|
||||
rec->type.new_fsf_req.fsf_issued);
|
||||
} else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) ||
|
||||
(strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) {
|
||||
len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx",
|
||||
rec->type.new_fsf_req.fsf_reqid);
|
||||
len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x",
|
||||
rec->type.new_fsf_req.fsf_seqno);
|
||||
len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
|
||||
rec->type.new_fsf_req.fsf_issued);
|
||||
}
|
||||
|
||||
len += sprintf(out_buf + len, "\n");
|
||||
|
@ -152,11 +152,6 @@ typedef u32 scsi_lun_t;
|
||||
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
|
||||
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
|
||||
|
||||
/* Retry 5 times every 2 second, then every minute */
|
||||
#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5
|
||||
#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200
|
||||
#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000
|
||||
|
||||
/* timeout value for "default timer" for fsf requests */
|
||||
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
|
||||
|
||||
@ -429,11 +424,7 @@ struct zfcp_scsi_dbf_record {
|
||||
u32 fsf_seqno;
|
||||
u64 fsf_issued;
|
||||
union {
|
||||
struct {
|
||||
u64 fsf_reqid;
|
||||
u32 fsf_seqno;
|
||||
u64 fsf_issued;
|
||||
} new_fsf_req;
|
||||
u64 old_fsf_reqid;
|
||||
struct {
|
||||
u8 rsp_validity;
|
||||
u8 rsp_scsi_status;
|
||||
@ -915,8 +906,6 @@ struct zfcp_adapter {
|
||||
wwn_t peer_wwnn; /* P2P peer WWNN */
|
||||
wwn_t peer_wwpn; /* P2P peer WWPN */
|
||||
u32 peer_d_id; /* P2P peer D_ID */
|
||||
wwn_t physical_wwpn; /* WWPN of physical port */
|
||||
u32 physical_s_id; /* local FC port ID */
|
||||
struct ccw_device *ccw_device; /* S/390 ccw device */
|
||||
u8 fc_service_class;
|
||||
u32 hydra_version; /* Hydra version */
|
||||
|
@ -2246,15 +2246,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
|
||||
&erp_action->adapter->status)) &&
|
||||
(erp_action->adapter->adapter_features &
|
||||
FSF_FEATURE_HBAAPI_MANAGEMENT)) {
|
||||
zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
|
||||
atomic_set(&erp_action->adapter->erp_counter, 0);
|
||||
return ZFCP_ERP_FAILED;
|
||||
}
|
||||
|
||||
retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
|
||||
if (retval == ZFCP_ERP_FAILED)
|
||||
return ZFCP_ERP_FAILED;
|
||||
@ -2266,13 +2257,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
|
||||
return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
|
||||
}
|
||||
|
||||
/*
|
||||
* function:
|
||||
*
|
||||
* purpose:
|
||||
*
|
||||
* returns:
|
||||
*/
|
||||
static int
|
||||
zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
|
||||
{
|
||||
@ -2350,48 +2334,40 @@ static int
|
||||
zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
|
||||
{
|
||||
int ret;
|
||||
int retries;
|
||||
int sleep;
|
||||
struct zfcp_adapter *adapter = erp_action->adapter;
|
||||
struct zfcp_adapter *adapter;
|
||||
|
||||
adapter = erp_action->adapter;
|
||||
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
|
||||
|
||||
retries = 0;
|
||||
do {
|
||||
write_lock(&adapter->erp_lock);
|
||||
zfcp_erp_action_to_running(erp_action);
|
||||
write_unlock(&adapter->erp_lock);
|
||||
zfcp_erp_timeout_init(erp_action);
|
||||
ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
|
||||
if (ret == -EOPNOTSUPP) {
|
||||
debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
|
||||
return ZFCP_ERP_SUCCEEDED;
|
||||
} else if (ret) {
|
||||
debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
|
||||
return ZFCP_ERP_FAILED;
|
||||
}
|
||||
debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
|
||||
write_lock(&adapter->erp_lock);
|
||||
zfcp_erp_action_to_running(erp_action);
|
||||
write_unlock(&adapter->erp_lock);
|
||||
|
||||
down(&adapter->erp_ready_sem);
|
||||
if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
|
||||
ZFCP_LOG_INFO("error: exchange of port data "
|
||||
"for adapter %s timed out\n",
|
||||
zfcp_get_busid_by_adapter(adapter));
|
||||
break;
|
||||
}
|
||||
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
|
||||
&adapter->status))
|
||||
break;
|
||||
zfcp_erp_timeout_init(erp_action);
|
||||
ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
|
||||
if (ret == -EOPNOTSUPP) {
|
||||
debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
|
||||
return ZFCP_ERP_SUCCEEDED;
|
||||
} else if (ret) {
|
||||
debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
|
||||
return ZFCP_ERP_FAILED;
|
||||
}
|
||||
debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
|
||||
|
||||
if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) {
|
||||
sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP;
|
||||
retries++;
|
||||
} else
|
||||
sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
|
||||
schedule_timeout(sleep);
|
||||
} while (1);
|
||||
ret = ZFCP_ERP_SUCCEEDED;
|
||||
down(&adapter->erp_ready_sem);
|
||||
if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
|
||||
ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
|
||||
"%s)\n", zfcp_get_busid_by_adapter(adapter));
|
||||
ret = ZFCP_ERP_FAILED;
|
||||
}
|
||||
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) {
|
||||
ZFCP_LOG_INFO("error: exchange port data failed (adapter "
|
||||
"%s\n", zfcp_get_busid_by_adapter(adapter));
|
||||
ret = ZFCP_ERP_FAILED;
|
||||
}
|
||||
|
||||
return ZFCP_ERP_SUCCEEDED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3439,6 +3415,8 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
|
||||
"(adapter %s, wwpn=0x%016Lx)\n",
|
||||
zfcp_get_busid_by_port(port),
|
||||
port->wwpn);
|
||||
else
|
||||
scsi_flush_work(adapter->scsi_host);
|
||||
}
|
||||
zfcp_port_put(port);
|
||||
break;
|
||||
|
@ -194,9 +194,10 @@ extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *);
|
||||
extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *);
|
||||
|
||||
extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
|
||||
struct scsi_cmnd *);
|
||||
struct scsi_cmnd *,
|
||||
struct zfcp_fsf_req *);
|
||||
extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
|
||||
struct scsi_cmnd *,
|
||||
struct scsi_cmnd *, struct zfcp_fsf_req *,
|
||||
struct zfcp_fsf_req *);
|
||||
extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
|
||||
struct scsi_cmnd *);
|
||||
|
@ -388,6 +388,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
|
||||
case FSF_PROT_LINK_DOWN:
|
||||
zfcp_fsf_link_down_info_eval(adapter,
|
||||
&prot_status_qual->link_down_info);
|
||||
zfcp_erp_adapter_reopen(adapter, 0);
|
||||
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
|
||||
break;
|
||||
|
||||
@ -558,10 +559,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
|
||||
|
||||
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
|
||||
|
||||
if (link_down == NULL) {
|
||||
zfcp_erp_adapter_reopen(adapter, 0);
|
||||
return;
|
||||
}
|
||||
if (link_down == NULL)
|
||||
goto out;
|
||||
|
||||
switch (link_down->error_code) {
|
||||
case FSF_PSQ_LINK_NO_LIGHT:
|
||||
@ -643,16 +642,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
|
||||
link_down->explanation_code,
|
||||
link_down->vendor_specific_code);
|
||||
|
||||
switch (link_down->error_code) {
|
||||
case FSF_PSQ_LINK_NO_LIGHT:
|
||||
case FSF_PSQ_LINK_WRAP_PLUG:
|
||||
case FSF_PSQ_LINK_NO_FCP:
|
||||
case FSF_PSQ_LINK_FIRMWARE_UPDATE:
|
||||
zfcp_erp_adapter_reopen(adapter, 0);
|
||||
break;
|
||||
default:
|
||||
zfcp_erp_adapter_failed(adapter);
|
||||
}
|
||||
out:
|
||||
zfcp_erp_adapter_failed(adapter);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2304,6 +2295,35 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_fsf_exchange_port_evaluate
|
||||
* @fsf_req: fsf_req which belongs to xchg port data request
|
||||
* @xchg_ok: specifies if xchg port data was incomplete or complete (0/1)
|
||||
*/
|
||||
static void
|
||||
zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
|
||||
{
|
||||
struct zfcp_adapter *adapter;
|
||||
struct fsf_qtcb *qtcb;
|
||||
struct fsf_qtcb_bottom_port *bottom, *data;
|
||||
struct Scsi_Host *shost;
|
||||
|
||||
adapter = fsf_req->adapter;
|
||||
qtcb = fsf_req->qtcb;
|
||||
bottom = &qtcb->bottom.port;
|
||||
shost = adapter->scsi_host;
|
||||
|
||||
data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
|
||||
if (data)
|
||||
memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
|
||||
|
||||
if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
|
||||
fc_host_permanent_port_name(shost) = bottom->wwpn;
|
||||
else
|
||||
fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
|
||||
fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
|
||||
fc_host_supported_speeds(shost) = bottom->supported_speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
|
||||
@ -2312,38 +2332,26 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
|
||||
static void
|
||||
zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
|
||||
{
|
||||
struct zfcp_adapter *adapter = fsf_req->adapter;
|
||||
struct Scsi_Host *shost = adapter->scsi_host;
|
||||
struct fsf_qtcb *qtcb = fsf_req->qtcb;
|
||||
struct fsf_qtcb_bottom_port *bottom, *data;
|
||||
struct zfcp_adapter *adapter;
|
||||
struct fsf_qtcb *qtcb;
|
||||
|
||||
adapter = fsf_req->adapter;
|
||||
qtcb = fsf_req->qtcb;
|
||||
|
||||
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
|
||||
return;
|
||||
|
||||
switch (qtcb->header.fsf_status) {
|
||||
case FSF_GOOD:
|
||||
zfcp_fsf_exchange_port_evaluate(fsf_req, 1);
|
||||
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
|
||||
|
||||
bottom = &qtcb->bottom.port;
|
||||
data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
|
||||
if (data)
|
||||
memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
|
||||
if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
|
||||
fc_host_permanent_port_name(shost) = bottom->wwpn;
|
||||
else
|
||||
fc_host_permanent_port_name(shost) =
|
||||
fc_host_port_name(shost);
|
||||
fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
|
||||
fc_host_supported_speeds(shost) = bottom->supported_speed;
|
||||
break;
|
||||
|
||||
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
|
||||
zfcp_fsf_exchange_port_evaluate(fsf_req, 0);
|
||||
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
|
||||
|
||||
zfcp_fsf_link_down_info_eval(adapter,
|
||||
&qtcb->header.fsf_status_qual.link_down_info);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
|
||||
debug_event(adapter->erp_dbf, 0,
|
||||
@ -4203,11 +4211,11 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
|
||||
ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
|
||||
|
||||
if (scpnt->result != 0)
|
||||
zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt);
|
||||
zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt, fsf_req);
|
||||
else if (scpnt->retries > 0)
|
||||
zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt);
|
||||
zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt, fsf_req);
|
||||
else
|
||||
zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt);
|
||||
zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt, fsf_req);
|
||||
|
||||
/* cleanup pointer (need this especially for abort) */
|
||||
scpnt->host_scribble = NULL;
|
||||
|
@ -242,7 +242,7 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
|
||||
if ((scpnt->device != NULL) && (scpnt->device->host != NULL))
|
||||
zfcp_scsi_dbf_event_result("fail", 4,
|
||||
(struct zfcp_adapter*) scpnt->device->host->hostdata[0],
|
||||
scpnt);
|
||||
scpnt, NULL);
|
||||
/* return directly */
|
||||
scpnt->scsi_done(scpnt);
|
||||
}
|
||||
@ -446,7 +446,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
|
||||
old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
|
||||
if (!old_fsf_req) {
|
||||
write_unlock_irqrestore(&adapter->abort_lock, flags);
|
||||
zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req);
|
||||
zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL);
|
||||
retval = SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
@ -460,6 +460,8 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
|
||||
adapter, unit, 0);
|
||||
if (!new_fsf_req) {
|
||||
ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
|
||||
zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
|
||||
old_fsf_req);
|
||||
retval = FAILED;
|
||||
goto out;
|
||||
}
|
||||
@ -470,13 +472,16 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
|
||||
|
||||
/* status should be valid since signals were not permitted */
|
||||
if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
|
||||
zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req);
|
||||
zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,
|
||||
NULL);
|
||||
retval = SUCCESS;
|
||||
} else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
|
||||
zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req);
|
||||
zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req,
|
||||
NULL);
|
||||
retval = SUCCESS;
|
||||
} else {
|
||||
zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req);
|
||||
zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req,
|
||||
NULL);
|
||||
retval = FAILED;
|
||||
}
|
||||
zfcp_fsf_req_free(new_fsf_req);
|
||||
|
@ -55,8 +55,6 @@ ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
|
||||
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn);
|
||||
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn);
|
||||
ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
|
||||
ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
|
||||
ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
|
||||
ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
|
||||
ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
|
||||
ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
|
||||
@ -241,8 +239,6 @@ static struct attribute *zfcp_adapter_attrs[] = {
|
||||
&dev_attr_peer_wwnn.attr,
|
||||
&dev_attr_peer_wwpn.attr,
|
||||
&dev_attr_peer_d_id.attr,
|
||||
&dev_attr_physical_wwpn.attr,
|
||||
&dev_attr_physical_s_id.attr,
|
||||
&dev_attr_card_version.attr,
|
||||
&dev_attr_lic_version.attr,
|
||||
&dev_attr_status.attr,
|
||||
|
@ -61,6 +61,7 @@
|
||||
Add support for embedded firmware error strings.
|
||||
2.26.02.003 - Correctly handle single sgl's with use_sg=1.
|
||||
2.26.02.004 - Add support for 9550SX controllers.
|
||||
2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -84,7 +85,7 @@
|
||||
#include "3w-9xxx.h"
|
||||
|
||||
/* Globals */
|
||||
#define TW_DRIVER_VERSION "2.26.02.004"
|
||||
#define TW_DRIVER_VERSION "2.26.02.005"
|
||||
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
|
||||
static unsigned int twa_device_extension_count;
|
||||
static int twa_major = -1;
|
||||
@ -1408,7 +1409,7 @@ static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int requ
|
||||
dma_addr_t mapping;
|
||||
struct scsi_cmnd *cmd = tw_dev->srb[request_id];
|
||||
struct pci_dev *pdev = tw_dev->tw_pci_dev;
|
||||
int retval = 0;
|
||||
dma_addr_t retval = 0;
|
||||
|
||||
if (cmd->request_bufflen == 0) {
|
||||
retval = 0;
|
||||
@ -1798,7 +1799,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
|
||||
int i, sg_count;
|
||||
struct scsi_cmnd *srb = NULL;
|
||||
struct scatterlist *sglist = NULL;
|
||||
u32 buffaddr = 0x0;
|
||||
dma_addr_t buffaddr = 0x0;
|
||||
int retval = 1;
|
||||
|
||||
if (tw_dev->srb[request_id]) {
|
||||
|
@ -173,10 +173,10 @@ int aac_get_config_status(struct aac_dev *dev)
|
||||
int status = 0;
|
||||
struct fib * fibptr;
|
||||
|
||||
if (!(fibptr = fib_alloc(dev)))
|
||||
if (!(fibptr = aac_fib_alloc(dev)))
|
||||
return -ENOMEM;
|
||||
|
||||
fib_init(fibptr);
|
||||
aac_fib_init(fibptr);
|
||||
{
|
||||
struct aac_get_config_status *dinfo;
|
||||
dinfo = (struct aac_get_config_status *) fib_data(fibptr);
|
||||
@ -186,7 +186,7 @@ int aac_get_config_status(struct aac_dev *dev)
|
||||
dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data));
|
||||
}
|
||||
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
fibptr,
|
||||
sizeof (struct aac_get_config_status),
|
||||
FsaNormal,
|
||||
@ -209,30 +209,30 @@ int aac_get_config_status(struct aac_dev *dev)
|
||||
status = -EINVAL;
|
||||
}
|
||||
}
|
||||
fib_complete(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
/* Send a CT_COMMIT_CONFIG to enable discovery of devices */
|
||||
if (status >= 0) {
|
||||
if (commit == 1) {
|
||||
struct aac_commit_config * dinfo;
|
||||
fib_init(fibptr);
|
||||
aac_fib_init(fibptr);
|
||||
dinfo = (struct aac_commit_config *) fib_data(fibptr);
|
||||
|
||||
dinfo->command = cpu_to_le32(VM_ContainerConfig);
|
||||
dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG);
|
||||
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
fibptr,
|
||||
sizeof (struct aac_commit_config),
|
||||
FsaNormal,
|
||||
1, 1,
|
||||
NULL, NULL);
|
||||
fib_complete(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
} else if (commit == 0) {
|
||||
printk(KERN_WARNING
|
||||
"aac_get_config_status: Foreign device configurations are being ignored\n");
|
||||
}
|
||||
}
|
||||
fib_free(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -255,15 +255,15 @@ int aac_get_containers(struct aac_dev *dev)
|
||||
|
||||
instance = dev->scsi_host_ptr->unique_id;
|
||||
|
||||
if (!(fibptr = fib_alloc(dev)))
|
||||
if (!(fibptr = aac_fib_alloc(dev)))
|
||||
return -ENOMEM;
|
||||
|
||||
fib_init(fibptr);
|
||||
aac_fib_init(fibptr);
|
||||
dinfo = (struct aac_get_container_count *) fib_data(fibptr);
|
||||
dinfo->command = cpu_to_le32(VM_ContainerConfig);
|
||||
dinfo->type = cpu_to_le32(CT_GET_CONTAINER_COUNT);
|
||||
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
fibptr,
|
||||
sizeof (struct aac_get_container_count),
|
||||
FsaNormal,
|
||||
@ -272,7 +272,7 @@ int aac_get_containers(struct aac_dev *dev)
|
||||
if (status >= 0) {
|
||||
dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);
|
||||
maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
|
||||
fib_complete(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
}
|
||||
|
||||
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
|
||||
@ -280,7 +280,7 @@ int aac_get_containers(struct aac_dev *dev)
|
||||
fsa_dev_ptr = (struct fsa_dev_info *) kmalloc(
|
||||
sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
|
||||
if (!fsa_dev_ptr) {
|
||||
fib_free(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
|
||||
@ -294,14 +294,14 @@ int aac_get_containers(struct aac_dev *dev)
|
||||
|
||||
fsa_dev_ptr[index].devname[0] = '\0';
|
||||
|
||||
fib_init(fibptr);
|
||||
aac_fib_init(fibptr);
|
||||
dinfo = (struct aac_query_mount *) fib_data(fibptr);
|
||||
|
||||
dinfo->command = cpu_to_le32(VM_NameServe);
|
||||
dinfo->count = cpu_to_le32(index);
|
||||
dinfo->type = cpu_to_le32(FT_FILESYS);
|
||||
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
fibptr,
|
||||
sizeof (struct aac_query_mount),
|
||||
FsaNormal,
|
||||
@ -319,7 +319,7 @@ int aac_get_containers(struct aac_dev *dev)
|
||||
dinfo->count = cpu_to_le32(index);
|
||||
dinfo->type = cpu_to_le32(FT_FILESYS);
|
||||
|
||||
if (fib_send(ContainerCommand,
|
||||
if (aac_fib_send(ContainerCommand,
|
||||
fibptr,
|
||||
sizeof(struct aac_query_mount),
|
||||
FsaNormal,
|
||||
@ -347,7 +347,7 @@ int aac_get_containers(struct aac_dev *dev)
|
||||
if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
|
||||
fsa_dev_ptr[index].ro = 1;
|
||||
}
|
||||
fib_complete(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
/*
|
||||
* If there are no more containers, then stop asking.
|
||||
*/
|
||||
@ -355,7 +355,7 @@ int aac_get_containers(struct aac_dev *dev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
fib_free(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -413,8 +413,8 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
|
||||
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
|
||||
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
}
|
||||
|
||||
@ -430,10 +430,10 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
|
||||
|
||||
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
|
||||
|
||||
if (!(cmd_fibcontext = fib_alloc(dev)))
|
||||
if (!(cmd_fibcontext = aac_fib_alloc(dev)))
|
||||
return -ENOMEM;
|
||||
|
||||
fib_init(cmd_fibcontext);
|
||||
aac_fib_init(cmd_fibcontext);
|
||||
dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext);
|
||||
|
||||
dinfo->command = cpu_to_le32(VM_ContainerConfig);
|
||||
@ -441,7 +441,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
|
||||
dinfo->cid = cpu_to_le32(cid);
|
||||
dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data));
|
||||
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
cmd_fibcontext,
|
||||
sizeof (struct aac_get_name),
|
||||
FsaNormal,
|
||||
@ -455,14 +455,14 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
|
||||
if (status == -EINPROGRESS)
|
||||
return 0;
|
||||
|
||||
printk(KERN_WARNING "aac_get_container_name: fib_send failed with status: %d.\n", status);
|
||||
fib_complete(cmd_fibcontext);
|
||||
fib_free(cmd_fibcontext);
|
||||
printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
|
||||
aac_fib_complete(cmd_fibcontext);
|
||||
aac_fib_free(cmd_fibcontext);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* probe_container - query a logical volume
|
||||
* aac_probe_container - query a logical volume
|
||||
* @dev: device to query
|
||||
* @cid: container identifier
|
||||
*
|
||||
@ -470,7 +470,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
|
||||
* is updated in the struct fsa_dev_info structure rather than returned.
|
||||
*/
|
||||
|
||||
int probe_container(struct aac_dev *dev, int cid)
|
||||
int aac_probe_container(struct aac_dev *dev, int cid)
|
||||
{
|
||||
struct fsa_dev_info *fsa_dev_ptr;
|
||||
int status;
|
||||
@ -482,10 +482,10 @@ int probe_container(struct aac_dev *dev, int cid)
|
||||
fsa_dev_ptr = dev->fsa_dev;
|
||||
instance = dev->scsi_host_ptr->unique_id;
|
||||
|
||||
if (!(fibptr = fib_alloc(dev)))
|
||||
if (!(fibptr = aac_fib_alloc(dev)))
|
||||
return -ENOMEM;
|
||||
|
||||
fib_init(fibptr);
|
||||
aac_fib_init(fibptr);
|
||||
|
||||
dinfo = (struct aac_query_mount *)fib_data(fibptr);
|
||||
|
||||
@ -493,14 +493,14 @@ int probe_container(struct aac_dev *dev, int cid)
|
||||
dinfo->count = cpu_to_le32(cid);
|
||||
dinfo->type = cpu_to_le32(FT_FILESYS);
|
||||
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
fibptr,
|
||||
sizeof(struct aac_query_mount),
|
||||
FsaNormal,
|
||||
1, 1,
|
||||
NULL, NULL);
|
||||
if (status < 0) {
|
||||
printk(KERN_WARNING "aacraid: probe_container query failed.\n");
|
||||
printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -512,7 +512,7 @@ int probe_container(struct aac_dev *dev, int cid)
|
||||
dinfo->count = cpu_to_le32(cid);
|
||||
dinfo->type = cpu_to_le32(FT_FILESYS);
|
||||
|
||||
if (fib_send(ContainerCommand,
|
||||
if (aac_fib_send(ContainerCommand,
|
||||
fibptr,
|
||||
sizeof(struct aac_query_mount),
|
||||
FsaNormal,
|
||||
@ -535,8 +535,8 @@ int probe_container(struct aac_dev *dev, int cid)
|
||||
}
|
||||
|
||||
error:
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -700,14 +700,14 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
||||
struct aac_bus_info *command;
|
||||
struct aac_bus_info_response *bus_info;
|
||||
|
||||
if (!(fibptr = fib_alloc(dev)))
|
||||
if (!(fibptr = aac_fib_alloc(dev)))
|
||||
return -ENOMEM;
|
||||
|
||||
fib_init(fibptr);
|
||||
aac_fib_init(fibptr);
|
||||
info = (struct aac_adapter_info *) fib_data(fibptr);
|
||||
memset(info,0,sizeof(*info));
|
||||
|
||||
rcode = fib_send(RequestAdapterInfo,
|
||||
rcode = aac_fib_send(RequestAdapterInfo,
|
||||
fibptr,
|
||||
sizeof(*info),
|
||||
FsaNormal,
|
||||
@ -716,8 +716,8 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
||||
NULL);
|
||||
|
||||
if (rcode < 0) {
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
return rcode;
|
||||
}
|
||||
memcpy(&dev->adapter_info, info, sizeof(*info));
|
||||
@ -725,13 +725,13 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
||||
if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
|
||||
struct aac_supplement_adapter_info * info;
|
||||
|
||||
fib_init(fibptr);
|
||||
aac_fib_init(fibptr);
|
||||
|
||||
info = (struct aac_supplement_adapter_info *) fib_data(fibptr);
|
||||
|
||||
memset(info,0,sizeof(*info));
|
||||
|
||||
rcode = fib_send(RequestSupplementAdapterInfo,
|
||||
rcode = aac_fib_send(RequestSupplementAdapterInfo,
|
||||
fibptr,
|
||||
sizeof(*info),
|
||||
FsaNormal,
|
||||
@ -748,7 +748,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
||||
* GetBusInfo
|
||||
*/
|
||||
|
||||
fib_init(fibptr);
|
||||
aac_fib_init(fibptr);
|
||||
|
||||
bus_info = (struct aac_bus_info_response *) fib_data(fibptr);
|
||||
|
||||
@ -761,7 +761,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
||||
command->MethodId = cpu_to_le32(1);
|
||||
command->CtlCmd = cpu_to_le32(GetBusInfo);
|
||||
|
||||
rcode = fib_send(ContainerCommand,
|
||||
rcode = aac_fib_send(ContainerCommand,
|
||||
fibptr,
|
||||
sizeof (*bus_info),
|
||||
FsaNormal,
|
||||
@ -891,8 +891,8 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
||||
}
|
||||
}
|
||||
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
|
||||
return rcode;
|
||||
}
|
||||
@ -976,8 +976,8 @@ static void io_callback(void *context, struct fib * fibptr)
|
||||
? sizeof(scsicmd->sense_buffer)
|
||||
: sizeof(dev->fsa_dev[cid].sense_data));
|
||||
}
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
}
|
||||
@ -1062,11 +1062,11 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
||||
/*
|
||||
* Alocate and initialize a Fib
|
||||
*/
|
||||
if (!(cmd_fibcontext = fib_alloc(dev))) {
|
||||
if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fib_init(cmd_fibcontext);
|
||||
aac_fib_init(cmd_fibcontext);
|
||||
|
||||
if (dev->raw_io_interface) {
|
||||
struct aac_raw_io *readcmd;
|
||||
@ -1086,7 +1086,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ContainerRawIo,
|
||||
status = aac_fib_send(ContainerRawIo,
|
||||
cmd_fibcontext,
|
||||
fibsize,
|
||||
FsaNormal,
|
||||
@ -1112,7 +1112,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ContainerCommand64,
|
||||
status = aac_fib_send(ContainerCommand64,
|
||||
cmd_fibcontext,
|
||||
fibsize,
|
||||
FsaNormal,
|
||||
@ -1136,7 +1136,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
cmd_fibcontext,
|
||||
fibsize,
|
||||
FsaNormal,
|
||||
@ -1153,14 +1153,14 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
||||
if (status == -EINPROGRESS)
|
||||
return 0;
|
||||
|
||||
printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status);
|
||||
printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
|
||||
/*
|
||||
* For some reason, the Fib didn't queue, return QUEUE_FULL
|
||||
*/
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
fib_complete(cmd_fibcontext);
|
||||
fib_free(cmd_fibcontext);
|
||||
aac_fib_complete(cmd_fibcontext);
|
||||
aac_fib_free(cmd_fibcontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1228,12 +1228,12 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
||||
/*
|
||||
* Allocate and initialize a Fib then setup a BlockWrite command
|
||||
*/
|
||||
if (!(cmd_fibcontext = fib_alloc(dev))) {
|
||||
if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
|
||||
scsicmd->result = DID_ERROR << 16;
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
return 0;
|
||||
}
|
||||
fib_init(cmd_fibcontext);
|
||||
aac_fib_init(cmd_fibcontext);
|
||||
|
||||
if (dev->raw_io_interface) {
|
||||
struct aac_raw_io *writecmd;
|
||||
@ -1253,7 +1253,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ContainerRawIo,
|
||||
status = aac_fib_send(ContainerRawIo,
|
||||
cmd_fibcontext,
|
||||
fibsize,
|
||||
FsaNormal,
|
||||
@ -1279,7 +1279,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ContainerCommand64,
|
||||
status = aac_fib_send(ContainerCommand64,
|
||||
cmd_fibcontext,
|
||||
fibsize,
|
||||
FsaNormal,
|
||||
@ -1305,7 +1305,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
cmd_fibcontext,
|
||||
fibsize,
|
||||
FsaNormal,
|
||||
@ -1322,15 +1322,15 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status);
|
||||
printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d\n", status);
|
||||
/*
|
||||
* For some reason, the Fib didn't queue, return QUEUE_FULL
|
||||
*/
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
|
||||
fib_complete(cmd_fibcontext);
|
||||
fib_free(cmd_fibcontext);
|
||||
aac_fib_complete(cmd_fibcontext);
|
||||
aac_fib_free(cmd_fibcontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1369,8 +1369,8 @@ static void synchronize_callback(void *context, struct fib *fibptr)
|
||||
sizeof(cmd->sense_buffer)));
|
||||
}
|
||||
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
@ -1407,10 +1407,10 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
|
||||
* Allocate and initialize a Fib
|
||||
*/
|
||||
if (!(cmd_fibcontext =
|
||||
fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
|
||||
aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
||||
fib_init(cmd_fibcontext);
|
||||
aac_fib_init(cmd_fibcontext);
|
||||
|
||||
synchronizecmd = fib_data(cmd_fibcontext);
|
||||
synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
|
||||
@ -1422,7 +1422,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
cmd_fibcontext,
|
||||
sizeof(struct aac_synchronize),
|
||||
FsaNormal,
|
||||
@ -1437,9 +1437,9 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
|
||||
return 0;
|
||||
|
||||
printk(KERN_WARNING
|
||||
"aac_synchronize: fib_send failed with status: %d.\n", status);
|
||||
fib_complete(cmd_fibcontext);
|
||||
fib_free(cmd_fibcontext);
|
||||
"aac_synchronize: aac_fib_send failed with status: %d.\n", status);
|
||||
aac_fib_complete(cmd_fibcontext);
|
||||
aac_fib_free(cmd_fibcontext);
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
}
|
||||
|
||||
@ -1465,7 +1465,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
|
||||
* itself.
|
||||
*/
|
||||
if (scmd_id(scsicmd) != host->this_id) {
|
||||
if ((scsicmd->device->channel == 0) ){
|
||||
if ((scsicmd->device->channel == CONTAINER_CHANNEL)) {
|
||||
if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){
|
||||
scsicmd->result = DID_NO_CONNECT << 16;
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
@ -1488,7 +1488,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
|
||||
case READ_CAPACITY:
|
||||
case TEST_UNIT_READY:
|
||||
spin_unlock_irq(host->host_lock);
|
||||
probe_container(dev, cid);
|
||||
aac_probe_container(dev, cid);
|
||||
if ((fsa_dev_ptr[cid].valid & 1) == 0)
|
||||
fsa_dev_ptr[cid].valid = 0;
|
||||
spin_lock_irq(host->host_lock);
|
||||
@ -1935,33 +1935,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
|
||||
case SRB_STATUS_ERROR_RECOVERY:
|
||||
case SRB_STATUS_PENDING:
|
||||
case SRB_STATUS_SUCCESS:
|
||||
if(scsicmd->cmnd[0] == INQUIRY ){
|
||||
u8 b;
|
||||
u8 b1;
|
||||
/* We can't expose disk devices because we can't tell whether they
|
||||
* are the raw container drives or stand alone drives. If they have
|
||||
* the removable bit set then we should expose them though.
|
||||
*/
|
||||
b = (*(u8*)scsicmd->buffer)&0x1f;
|
||||
b1 = ((u8*)scsicmd->buffer)[1];
|
||||
if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER
|
||||
|| (b==TYPE_DISK && (b1&0x80)) ){
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
|
||||
/*
|
||||
* We will allow disk devices if in RAID/SCSI mode and
|
||||
* the channel is 2
|
||||
*/
|
||||
} else if ((dev->raid_scsi_mode) &&
|
||||
(scmd_channel(scsicmd) == 2)) {
|
||||
scsicmd->result = DID_OK << 16 |
|
||||
COMMAND_COMPLETE << 8;
|
||||
} else {
|
||||
scsicmd->result = DID_NO_CONNECT << 16 |
|
||||
COMMAND_COMPLETE << 8;
|
||||
}
|
||||
} else {
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
|
||||
}
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
case SRB_STATUS_DATA_OVERRUN:
|
||||
switch(scsicmd->cmnd[0]){
|
||||
@ -1981,28 +1955,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
|
||||
scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
case INQUIRY: {
|
||||
u8 b;
|
||||
u8 b1;
|
||||
/* We can't expose disk devices because we can't tell whether they
|
||||
* are the raw container drives or stand alone drives
|
||||
*/
|
||||
b = (*(u8*)scsicmd->buffer)&0x0f;
|
||||
b1 = ((u8*)scsicmd->buffer)[1];
|
||||
if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER
|
||||
|| (b==TYPE_DISK && (b1&0x80)) ){
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
|
||||
/*
|
||||
* We will allow disk devices if in RAID/SCSI mode and
|
||||
* the channel is 2
|
||||
*/
|
||||
} else if ((dev->raid_scsi_mode) &&
|
||||
(scmd_channel(scsicmd) == 2)) {
|
||||
scsicmd->result = DID_OK << 16 |
|
||||
COMMAND_COMPLETE << 8;
|
||||
} else {
|
||||
scsicmd->result = DID_NO_CONNECT << 16 |
|
||||
COMMAND_COMPLETE << 8;
|
||||
}
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -2089,8 +2042,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
|
||||
*/
|
||||
scsicmd->result |= le32_to_cpu(srbreply->scsi_status);
|
||||
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_fib_complete(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
}
|
||||
|
||||
@ -2142,10 +2095,10 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
|
||||
/*
|
||||
* Allocate and initialize a Fib then setup a BlockWrite command
|
||||
*/
|
||||
if (!(cmd_fibcontext = fib_alloc(dev))) {
|
||||
if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
|
||||
return -1;
|
||||
}
|
||||
fib_init(cmd_fibcontext);
|
||||
aac_fib_init(cmd_fibcontext);
|
||||
|
||||
srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
|
||||
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
|
||||
@ -2179,7 +2132,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ScsiPortCommand64, cmd_fibcontext,
|
||||
status = aac_fib_send(ScsiPortCommand64, cmd_fibcontext,
|
||||
fibsize, FsaNormal, 0, 1,
|
||||
(fib_callback) aac_srb_callback,
|
||||
(void *) scsicmd);
|
||||
@ -2201,7 +2154,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
|
||||
/*
|
||||
* Now send the Fib to the adapter
|
||||
*/
|
||||
status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
|
||||
status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
|
||||
(fib_callback) aac_srb_callback, (void *) scsicmd);
|
||||
}
|
||||
/*
|
||||
@ -2211,9 +2164,9 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status);
|
||||
fib_complete(cmd_fibcontext);
|
||||
fib_free(cmd_fibcontext);
|
||||
printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);
|
||||
aac_fib_complete(cmd_fibcontext);
|
||||
aac_fib_free(cmd_fibcontext);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -1774,16 +1774,16 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor)
|
||||
struct scsi_cmnd;
|
||||
|
||||
const char *aac_driverinfo(struct Scsi_Host *);
|
||||
struct fib *fib_alloc(struct aac_dev *dev);
|
||||
int fib_setup(struct aac_dev *dev);
|
||||
void fib_map_free(struct aac_dev *dev);
|
||||
void fib_free(struct fib * context);
|
||||
void fib_init(struct fib * context);
|
||||
struct fib *aac_fib_alloc(struct aac_dev *dev);
|
||||
int aac_fib_setup(struct aac_dev *dev);
|
||||
void aac_fib_map_free(struct aac_dev *dev);
|
||||
void aac_fib_free(struct fib * context);
|
||||
void aac_fib_init(struct fib * context);
|
||||
void aac_printf(struct aac_dev *dev, u32 val);
|
||||
int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
|
||||
int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
|
||||
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
|
||||
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
|
||||
int fib_complete(struct fib * context);
|
||||
int aac_fib_complete(struct fib * context);
|
||||
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data)
|
||||
struct aac_dev *aac_init_adapter(struct aac_dev *dev);
|
||||
int aac_get_config_status(struct aac_dev *dev);
|
||||
@ -1799,11 +1799,11 @@ unsigned int aac_command_normal(struct aac_queue * q);
|
||||
unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
|
||||
int aac_command_thread(struct aac_dev * dev);
|
||||
int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
|
||||
int fib_adapter_complete(struct fib * fibptr, unsigned short size);
|
||||
int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size);
|
||||
struct aac_driver_ident* aac_get_driver_ident(int devtype);
|
||||
int aac_get_adapter_info(struct aac_dev* dev);
|
||||
int aac_send_shutdown(struct aac_dev *dev);
|
||||
int probe_container(struct aac_dev *dev, int cid);
|
||||
int aac_probe_container(struct aac_dev *dev, int cid);
|
||||
extern int numacb;
|
||||
extern int acbsize;
|
||||
extern char aac_driver_version[];
|
||||
|
@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
|
||||
unsigned size;
|
||||
int retval;
|
||||
|
||||
fibptr = fib_alloc(dev);
|
||||
fibptr = aac_fib_alloc(dev);
|
||||
if(fibptr == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -73,7 +73,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
|
||||
* First copy in the header so that we can check the size field.
|
||||
*/
|
||||
if (copy_from_user((void *)kfib, arg, sizeof(struct aac_fibhdr))) {
|
||||
fib_free(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
return -EFAULT;
|
||||
}
|
||||
/*
|
||||
@ -110,13 +110,13 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
|
||||
*/
|
||||
kfib->header.XferState = 0;
|
||||
} else {
|
||||
retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
|
||||
retval = aac_fib_send(le16_to_cpu(kfib->header.Command), fibptr,
|
||||
le16_to_cpu(kfib->header.Size) , FsaNormal,
|
||||
1, 1, NULL, NULL);
|
||||
if (retval) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (fib_complete(fibptr) != 0) {
|
||||
if (aac_fib_complete(fibptr) != 0) {
|
||||
retval = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -138,7 +138,7 @@ cleanup:
|
||||
fibptr->hw_fib_pa = hw_fib_pa;
|
||||
fibptr->hw_fib = hw_fib;
|
||||
}
|
||||
fib_free(fibptr);
|
||||
aac_fib_free(fibptr);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -464,10 +464,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
|
||||
/*
|
||||
* Allocate and initialize a Fib then setup a BlockWrite command
|
||||
*/
|
||||
if (!(srbfib = fib_alloc(dev))) {
|
||||
if (!(srbfib = aac_fib_alloc(dev))) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
fib_init(srbfib);
|
||||
aac_fib_init(srbfib);
|
||||
|
||||
srbcmd = (struct aac_srb*) fib_data(srbfib);
|
||||
|
||||
@ -601,7 +601,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
|
||||
|
||||
srbcmd->count = cpu_to_le32(byte_count);
|
||||
psg->count = cpu_to_le32(sg_indx+1);
|
||||
status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
|
||||
status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
|
||||
} else {
|
||||
struct user_sgmap* upsg = &user_srbcmd->sg;
|
||||
struct sgmap* psg = &srbcmd->sg;
|
||||
@ -649,7 +649,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
|
||||
}
|
||||
srbcmd->count = cpu_to_le32(byte_count);
|
||||
psg->count = cpu_to_le32(sg_indx+1);
|
||||
status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
|
||||
status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
|
||||
}
|
||||
|
||||
if (status != 0){
|
||||
@ -684,8 +684,8 @@ cleanup:
|
||||
for(i=0; i <= sg_indx; i++){
|
||||
kfree(sg_list[i]);
|
||||
}
|
||||
fib_complete(srbfib);
|
||||
fib_free(srbfib);
|
||||
aac_fib_complete(srbfib);
|
||||
aac_fib_free(srbfib);
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
@ -185,17 +185,17 @@ int aac_send_shutdown(struct aac_dev * dev)
|
||||
struct aac_close *cmd;
|
||||
int status;
|
||||
|
||||
fibctx = fib_alloc(dev);
|
||||
fibctx = aac_fib_alloc(dev);
|
||||
if (!fibctx)
|
||||
return -ENOMEM;
|
||||
fib_init(fibctx);
|
||||
aac_fib_init(fibctx);
|
||||
|
||||
cmd = (struct aac_close *) fib_data(fibctx);
|
||||
|
||||
cmd->command = cpu_to_le32(VM_CloseAll);
|
||||
cmd->cid = cpu_to_le32(0xffffffff);
|
||||
|
||||
status = fib_send(ContainerCommand,
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
fibctx,
|
||||
sizeof(struct aac_close),
|
||||
FsaNormal,
|
||||
@ -203,8 +203,8 @@ int aac_send_shutdown(struct aac_dev * dev)
|
||||
NULL, NULL);
|
||||
|
||||
if (status == 0)
|
||||
fib_complete(fibctx);
|
||||
fib_free(fibctx);
|
||||
aac_fib_complete(fibctx);
|
||||
aac_fib_free(fibctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -427,7 +427,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
||||
/*
|
||||
* Initialize the list of fibs
|
||||
*/
|
||||
if(fib_setup(dev)<0){
|
||||
if (aac_fib_setup(dev) < 0) {
|
||||
kfree(dev->queues);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -67,27 +67,27 @@ static int fib_map_alloc(struct aac_dev *dev)
|
||||
}
|
||||
|
||||
/**
|
||||
* fib_map_free - free the fib objects
|
||||
* aac_fib_map_free - free the fib objects
|
||||
* @dev: Adapter to free
|
||||
*
|
||||
* Free the PCI mappings and the memory allocated for FIB blocks
|
||||
* on this adapter.
|
||||
*/
|
||||
|
||||
void fib_map_free(struct aac_dev *dev)
|
||||
void aac_fib_map_free(struct aac_dev *dev)
|
||||
{
|
||||
pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa);
|
||||
}
|
||||
|
||||
/**
|
||||
* fib_setup - setup the fibs
|
||||
* aac_fib_setup - setup the fibs
|
||||
* @dev: Adapter to set up
|
||||
*
|
||||
* Allocate the PCI space for the fibs, map it and then intialise the
|
||||
* fib area, the unmapped fib data and also the free list
|
||||
*/
|
||||
|
||||
int fib_setup(struct aac_dev * dev)
|
||||
int aac_fib_setup(struct aac_dev * dev)
|
||||
{
|
||||
struct fib *fibptr;
|
||||
struct hw_fib *hw_fib_va;
|
||||
@ -134,14 +134,14 @@ int fib_setup(struct aac_dev * dev)
|
||||
}
|
||||
|
||||
/**
|
||||
* fib_alloc - allocate a fib
|
||||
* aac_fib_alloc - allocate a fib
|
||||
* @dev: Adapter to allocate the fib for
|
||||
*
|
||||
* Allocate a fib from the adapter fib pool. If the pool is empty we
|
||||
* return NULL.
|
||||
*/
|
||||
|
||||
struct fib * fib_alloc(struct aac_dev *dev)
|
||||
struct fib *aac_fib_alloc(struct aac_dev *dev)
|
||||
{
|
||||
struct fib * fibptr;
|
||||
unsigned long flags;
|
||||
@ -170,14 +170,14 @@ struct fib * fib_alloc(struct aac_dev *dev)
|
||||
}
|
||||
|
||||
/**
|
||||
* fib_free - free a fib
|
||||
* aac_fib_free - free a fib
|
||||
* @fibptr: fib to free up
|
||||
*
|
||||
* Frees up a fib and places it on the appropriate queue
|
||||
* (either free or timed out)
|
||||
*/
|
||||
|
||||
void fib_free(struct fib * fibptr)
|
||||
void aac_fib_free(struct fib *fibptr)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@ -188,7 +188,7 @@ void fib_free(struct fib * fibptr)
|
||||
fibptr->dev->timeout_fib = fibptr;
|
||||
} else {
|
||||
if (fibptr->hw_fib->header.XferState != 0) {
|
||||
printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
|
||||
printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
|
||||
(void*)fibptr,
|
||||
le32_to_cpu(fibptr->hw_fib->header.XferState));
|
||||
}
|
||||
@ -199,13 +199,13 @@ void fib_free(struct fib * fibptr)
|
||||
}
|
||||
|
||||
/**
|
||||
* fib_init - initialise a fib
|
||||
* aac_fib_init - initialise a fib
|
||||
* @fibptr: The fib to initialize
|
||||
*
|
||||
* Set up the generic fib fields ready for use
|
||||
*/
|
||||
|
||||
void fib_init(struct fib *fibptr)
|
||||
void aac_fib_init(struct fib *fibptr)
|
||||
{
|
||||
struct hw_fib *hw_fib = fibptr->hw_fib;
|
||||
|
||||
@ -362,7 +362,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
|
||||
*/
|
||||
|
||||
/**
|
||||
* fib_send - send a fib to the adapter
|
||||
* aac_fib_send - send a fib to the adapter
|
||||
* @command: Command to send
|
||||
* @fibptr: The fib
|
||||
* @size: Size of fib data area
|
||||
@ -378,7 +378,9 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
|
||||
* response FIB is received from the adapter.
|
||||
*/
|
||||
|
||||
int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data)
|
||||
int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
|
||||
int priority, int wait, int reply, fib_callback callback,
|
||||
void *callback_data)
|
||||
{
|
||||
struct aac_dev * dev = fibptr->dev;
|
||||
struct hw_fib * hw_fib = fibptr->hw_fib;
|
||||
@ -493,7 +495,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
|
||||
q->numpending++;
|
||||
*(q->headers.producer) = cpu_to_le32(index + 1);
|
||||
spin_unlock_irqrestore(q->lock, qflags);
|
||||
dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
|
||||
dprintk((KERN_DEBUG "aac_fib_send: inserting a queue entry at index %d.\n",index));
|
||||
if (!(nointr & aac_config.irq_mod))
|
||||
aac_adapter_notify(dev, AdapNormCmdQueue);
|
||||
}
|
||||
@ -520,7 +522,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
|
||||
list_del(&fibptr->queue);
|
||||
spin_unlock_irqrestore(q->lock, qflags);
|
||||
if (wait == -1) {
|
||||
printk(KERN_ERR "aacraid: fib_send: first asynchronous command timed out.\n"
|
||||
printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n"
|
||||
"Usually a result of a PCI interrupt routing problem;\n"
|
||||
"update mother board BIOS or consider utilizing one of\n"
|
||||
"the SAFE mode kernel options (acpi, apic etc)\n");
|
||||
@ -624,7 +626,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
|
||||
}
|
||||
|
||||
/**
|
||||
* fib_adapter_complete - complete adapter issued fib
|
||||
* aac_fib_adapter_complete - complete adapter issued fib
|
||||
* @fibptr: fib to complete
|
||||
* @size: size of fib
|
||||
*
|
||||
@ -632,7 +634,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
|
||||
* the adapter.
|
||||
*/
|
||||
|
||||
int fib_adapter_complete(struct fib * fibptr, unsigned short size)
|
||||
int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
|
||||
{
|
||||
struct hw_fib * hw_fib = fibptr->hw_fib;
|
||||
struct aac_dev * dev = fibptr->dev;
|
||||
@ -683,20 +685,20 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_WARNING "fib_adapter_complete: Unknown xferstate detected.\n");
|
||||
printk(KERN_WARNING "aac_fib_adapter_complete: Unknown xferstate detected.\n");
|
||||
BUG();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fib_complete - fib completion handler
|
||||
* aac_fib_complete - fib completion handler
|
||||
* @fib: FIB to complete
|
||||
*
|
||||
* Will do all necessary work to complete a FIB.
|
||||
*/
|
||||
|
||||
int fib_complete(struct fib * fibptr)
|
||||
int aac_fib_complete(struct fib *fibptr)
|
||||
{
|
||||
struct hw_fib * hw_fib = fibptr->hw_fib;
|
||||
|
||||
@ -995,14 +997,14 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
|
||||
if (!dev || !dev->scsi_host_ptr)
|
||||
return;
|
||||
/*
|
||||
* force reload of disk info via probe_container
|
||||
* force reload of disk info via aac_probe_container
|
||||
*/
|
||||
if ((device_config_needed == CHANGE)
|
||||
&& (dev->fsa_dev[container].valid == 1))
|
||||
dev->fsa_dev[container].valid = 2;
|
||||
if ((device_config_needed == CHANGE) ||
|
||||
(device_config_needed == ADD))
|
||||
probe_container(dev, container);
|
||||
aac_probe_container(dev, container);
|
||||
device = scsi_device_lookup(dev->scsi_host_ptr,
|
||||
CONTAINER_TO_CHANNEL(container),
|
||||
CONTAINER_TO_ID(container),
|
||||
@ -1104,7 +1106,7 @@ int aac_command_thread(struct aac_dev * dev)
|
||||
/* Handle Driver Notify Events */
|
||||
aac_handle_aif(dev, fib);
|
||||
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
|
||||
fib_adapter_complete(fib, (u16)sizeof(u32));
|
||||
aac_fib_adapter_complete(fib, (u16)sizeof(u32));
|
||||
} else {
|
||||
struct list_head *entry;
|
||||
/* The u32 here is important and intended. We are using
|
||||
@ -1241,7 +1243,7 @@ int aac_command_thread(struct aac_dev * dev)
|
||||
* Set the status of this FIB
|
||||
*/
|
||||
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
|
||||
fib_adapter_complete(fib, sizeof(u32));
|
||||
aac_fib_adapter_complete(fib, sizeof(u32));
|
||||
spin_unlock_irqrestore(&dev->fib_lock, flagv);
|
||||
/* Free up the remaining resources */
|
||||
hw_fib_p = hw_fib_pool;
|
||||
|
@ -206,7 +206,7 @@ unsigned int aac_command_normal(struct aac_queue *q)
|
||||
* Set the status of this FIB
|
||||
*/
|
||||
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
|
||||
fib_adapter_complete(fib, sizeof(u32));
|
||||
aac_fib_adapter_complete(fib, sizeof(u32));
|
||||
spin_lock_irqsave(q->lock, flags);
|
||||
}
|
||||
}
|
||||
|
@ -385,17 +385,45 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
|
||||
|
||||
static int aac_slave_configure(struct scsi_device *sdev)
|
||||
{
|
||||
struct Scsi_Host *host = sdev->host;
|
||||
if (sdev_channel(sdev) == CONTAINER_CHANNEL) {
|
||||
sdev->skip_ms_page_8 = 1;
|
||||
sdev->skip_ms_page_3f = 1;
|
||||
}
|
||||
if ((sdev->type == TYPE_DISK) &&
|
||||
(sdev_channel(sdev) != CONTAINER_CHANNEL)) {
|
||||
struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
|
||||
if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
|
||||
sdev->no_uld_attach = 1;
|
||||
}
|
||||
if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
|
||||
(sdev_channel(sdev) == CONTAINER_CHANNEL)) {
|
||||
struct scsi_device * dev;
|
||||
struct Scsi_Host *host = sdev->host;
|
||||
unsigned num_lsu = 0;
|
||||
unsigned num_one = 0;
|
||||
unsigned depth;
|
||||
|
||||
if (sdev->tagged_supported)
|
||||
scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128);
|
||||
else
|
||||
__shost_for_each_device(dev, host) {
|
||||
if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
|
||||
(sdev_channel(dev) == CONTAINER_CHANNEL))
|
||||
++num_lsu;
|
||||
else
|
||||
++num_one;
|
||||
}
|
||||
if (num_lsu == 0)
|
||||
++num_lsu;
|
||||
depth = (host->can_queue - num_one) / num_lsu;
|
||||
if (depth > 256)
|
||||
depth = 256;
|
||||
else if (depth < 2)
|
||||
depth = 2;
|
||||
scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
|
||||
if (!(((struct aac_dev *)host->hostdata)->adapter_info.options &
|
||||
AAC_OPT_NEW_COMM))
|
||||
blk_queue_max_segment_size(sdev->request_queue, 65536);
|
||||
} else
|
||||
scsi_adjust_queue_depth(sdev, 0, 1);
|
||||
|
||||
if (!(((struct aac_dev *)host->hostdata)->adapter_info.options
|
||||
& AAC_OPT_NEW_COMM))
|
||||
blk_queue_max_segment_size(sdev->request_queue, 65536);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -870,7 +898,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
|
||||
|
||||
/*
|
||||
* max channel will be the physical channels plus 1 virtual channel
|
||||
* all containers are on the virtual channel 0
|
||||
* all containers are on the virtual channel 0 (CONTAINER_CHANNEL)
|
||||
* physical channels are address by their actual physical number+1
|
||||
*/
|
||||
if (aac->nondasd_support == 1)
|
||||
@ -913,7 +941,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
|
||||
aac_adapter_disable_int(aac);
|
||||
free_irq(pdev->irq, aac);
|
||||
out_unmap:
|
||||
fib_map_free(aac);
|
||||
aac_fib_map_free(aac);
|
||||
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
|
||||
kfree(aac->queues);
|
||||
iounmap(aac->regs.sa);
|
||||
@ -947,7 +975,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
|
||||
|
||||
aac_send_shutdown(aac);
|
||||
aac_adapter_disable_int(aac);
|
||||
fib_map_free(aac);
|
||||
aac_fib_map_free(aac);
|
||||
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
|
||||
aac->comm_phys);
|
||||
kfree(aac->queues);
|
||||
|
@ -2816,7 +2816,7 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
} else if (scp->request_bufflen) {
|
||||
scp->SCp.Status = GDTH_MAP_SINGLE;
|
||||
scp->SCp.Message = (read_write == 1 ?
|
||||
PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
|
||||
|
@ -4235,35 +4235,6 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
|
||||
ipr_erp_start(ioa_cfg, ipr_cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_save_ioafp_mode_select - Save adapters mode select data
|
||||
* @ioa_cfg: ioa config struct
|
||||
* @scsi_cmd: scsi command struct
|
||||
*
|
||||
* This function saves mode select data for the adapter to
|
||||
* use following an adapter reset.
|
||||
*
|
||||
* Return value:
|
||||
* 0 on success / SCSI_MLQUEUE_HOST_BUSY on failure
|
||||
**/
|
||||
static int ipr_save_ioafp_mode_select(struct ipr_ioa_cfg *ioa_cfg,
|
||||
struct scsi_cmnd *scsi_cmd)
|
||||
{
|
||||
if (!ioa_cfg->saved_mode_pages) {
|
||||
ioa_cfg->saved_mode_pages = kmalloc(sizeof(struct ipr_mode_pages),
|
||||
GFP_ATOMIC);
|
||||
if (!ioa_cfg->saved_mode_pages) {
|
||||
dev_err(&ioa_cfg->pdev->dev,
|
||||
"IOA mode select buffer allocation failed\n");
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(ioa_cfg->saved_mode_pages, scsi_cmd->buffer, scsi_cmd->cmnd[4]);
|
||||
ioa_cfg->saved_mode_page_len = scsi_cmd->cmnd[4];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_queuecommand - Queue a mid-layer request
|
||||
* @scsi_cmd: scsi command struct
|
||||
@ -4338,9 +4309,6 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
|
||||
(!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE))
|
||||
ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
|
||||
|
||||
if (ipr_is_ioa_resource(res) && scsi_cmd->cmnd[0] == MODE_SELECT)
|
||||
rc = ipr_save_ioafp_mode_select(ioa_cfg, scsi_cmd);
|
||||
|
||||
if (likely(rc == 0))
|
||||
rc = ipr_build_ioadl(ioa_cfg, ipr_cmd);
|
||||
|
||||
@ -4829,17 +4797,11 @@ static int ipr_ioafp_mode_select_page28(struct ipr_cmnd *ipr_cmd)
|
||||
int length;
|
||||
|
||||
ENTER;
|
||||
if (ioa_cfg->saved_mode_pages) {
|
||||
memcpy(mode_pages, ioa_cfg->saved_mode_pages,
|
||||
ioa_cfg->saved_mode_page_len);
|
||||
length = ioa_cfg->saved_mode_page_len;
|
||||
} else {
|
||||
ipr_scsi_bus_speed_limit(ioa_cfg);
|
||||
ipr_check_term_power(ioa_cfg, mode_pages);
|
||||
ipr_modify_ioafp_mode_page_28(ioa_cfg, mode_pages);
|
||||
length = mode_pages->hdr.length + 1;
|
||||
mode_pages->hdr.length = 0;
|
||||
}
|
||||
ipr_scsi_bus_speed_limit(ioa_cfg);
|
||||
ipr_check_term_power(ioa_cfg, mode_pages);
|
||||
ipr_modify_ioafp_mode_page_28(ioa_cfg, mode_pages);
|
||||
length = mode_pages->hdr.length + 1;
|
||||
mode_pages->hdr.length = 0;
|
||||
|
||||
ipr_build_mode_select(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), 0x11,
|
||||
ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, mode_pages),
|
||||
@ -5969,7 +5931,6 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
|
||||
}
|
||||
|
||||
ipr_free_dump(ioa_cfg);
|
||||
kfree(ioa_cfg->saved_mode_pages);
|
||||
kfree(ioa_cfg->trace);
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,8 @@
|
||||
/*
|
||||
* Literals
|
||||
*/
|
||||
#define IPR_DRIVER_VERSION "2.1.1"
|
||||
#define IPR_DRIVER_DATE "(November 15, 2005)"
|
||||
#define IPR_DRIVER_VERSION "2.1.2"
|
||||
#define IPR_DRIVER_DATE "(February 8, 2006)"
|
||||
|
||||
/*
|
||||
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
|
||||
@ -1000,7 +1000,6 @@ struct ipr_ioa_cfg {
|
||||
struct Scsi_Host *host;
|
||||
struct pci_dev *pdev;
|
||||
struct ipr_sglist *ucode_sglist;
|
||||
struct ipr_mode_pages *saved_mode_pages;
|
||||
u8 saved_mode_page_len;
|
||||
|
||||
struct work_struct work_q;
|
||||
|
@ -146,7 +146,7 @@ iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
|
||||
spin_unlock_irqrestore(&session->lock, flags);
|
||||
set_bit(SUSPEND_BIT, &conn->suspend_tx);
|
||||
set_bit(SUSPEND_BIT, &conn->suspend_rx);
|
||||
iscsi_conn_error(iscsi_handle(conn), err);
|
||||
iscsi_conn_error(conn->cls_conn, err);
|
||||
}
|
||||
|
||||
static inline int
|
||||
@ -244,12 +244,10 @@ iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
|
||||
if (sc->sc_data_direction == DMA_TO_DEVICE) {
|
||||
struct iscsi_data_task *dtask, *n;
|
||||
/* WRITE: cleanup Data-Out's if any */
|
||||
spin_lock(&conn->lock);
|
||||
list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) {
|
||||
list_del(&dtask->item);
|
||||
mempool_free(dtask, ctask->datapool);
|
||||
}
|
||||
spin_unlock(&conn->lock);
|
||||
}
|
||||
ctask->xmstate = XMSTATE_IDLE;
|
||||
ctask->r2t = NULL;
|
||||
@ -689,7 +687,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
|
||||
break;
|
||||
|
||||
if (!conn->in.datalen) {
|
||||
rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
|
||||
rc = iscsi_recv_pdu(conn->cls_conn, hdr,
|
||||
NULL, 0);
|
||||
if (conn->login_mtask != mtask) {
|
||||
spin_lock(&session->lock);
|
||||
@ -737,7 +735,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
|
||||
if (!conn->in.datalen) {
|
||||
struct iscsi_mgmt_task *mtask;
|
||||
|
||||
rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
|
||||
rc = iscsi_recv_pdu(conn->cls_conn, hdr,
|
||||
NULL, 0);
|
||||
mtask = (struct iscsi_mgmt_task *)
|
||||
session->mgmt_cmds[conn->in.itt -
|
||||
@ -761,7 +759,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
|
||||
rc = iscsi_check_assign_cmdsn(session,
|
||||
(struct iscsi_nopin*)hdr);
|
||||
if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
|
||||
rc = iscsi_recv_pdu(iscsi_handle(conn),
|
||||
rc = iscsi_recv_pdu(conn->cls_conn,
|
||||
hdr, NULL, 0);
|
||||
} else
|
||||
rc = ISCSI_ERR_PROTO;
|
||||
@ -1044,7 +1042,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
|
||||
rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr,
|
||||
conn->data, conn->in.datalen);
|
||||
|
||||
if (!rc && conn->datadgst_en &&
|
||||
@ -2428,19 +2426,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
|
||||
}
|
||||
|
||||
static struct iscsi_cls_conn *
|
||||
iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
|
||||
iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
|
||||
{
|
||||
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
||||
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
|
||||
struct iscsi_conn *conn;
|
||||
struct iscsi_cls_conn *cls_conn;
|
||||
|
||||
cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
|
||||
conn_idx);
|
||||
cls_conn = iscsi_create_conn(cls_session, conn_idx);
|
||||
if (!cls_conn)
|
||||
return NULL;
|
||||
conn = cls_conn->dd_data;
|
||||
memset(conn, 0, sizeof(*conn));
|
||||
|
||||
memset(conn, 0, sizeof(struct iscsi_conn));
|
||||
conn->cls_conn = cls_conn;
|
||||
conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
|
||||
conn->in_progress = IN_PROGRESS_WAIT_HEADER;
|
||||
conn->id = conn_idx;
|
||||
@ -2452,8 +2451,6 @@ iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
|
||||
conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||
conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||
|
||||
spin_lock_init(&conn->lock);
|
||||
|
||||
/* initialize general xmit PDU commands queue */
|
||||
conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
|
||||
GFP_KERNEL, NULL);
|
||||
@ -2625,11 +2622,13 @@ iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
|
||||
uint32_t transport_fd, int is_leading)
|
||||
iscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
struct iscsi_cls_conn *cls_conn, uint32_t transport_fd,
|
||||
int is_leading)
|
||||
{
|
||||
struct iscsi_session *session = iscsi_ptr(sessionh);
|
||||
struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = iscsi_ptr(connh);
|
||||
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
||||
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
|
||||
struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
|
||||
struct sock *sk;
|
||||
struct socket *sock;
|
||||
int err;
|
||||
@ -2703,9 +2702,9 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_conn_start(iscsi_connh_t connh)
|
||||
iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
|
||||
{
|
||||
struct iscsi_conn *conn = iscsi_ptr(connh);
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct sock *sk;
|
||||
|
||||
@ -2754,9 +2753,9 @@ iscsi_conn_start(iscsi_connh_t connh)
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_conn_stop(iscsi_connh_t connh, int flag)
|
||||
iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
|
||||
{
|
||||
struct iscsi_conn *conn = iscsi_ptr(connh);
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct sock *sk;
|
||||
unsigned long flags;
|
||||
@ -3253,9 +3252,9 @@ static struct scsi_host_template iscsi_sht = {
|
||||
|
||||
static struct iscsi_transport iscsi_tcp_transport;
|
||||
|
||||
static struct Scsi_Host *
|
||||
static struct iscsi_cls_session *
|
||||
iscsi_session_create(struct scsi_transport_template *scsit,
|
||||
uint32_t initial_cmdsn)
|
||||
uint32_t initial_cmdsn, uint32_t *sid)
|
||||
{
|
||||
struct Scsi_Host *shost;
|
||||
struct iscsi_session *session;
|
||||
@ -3268,13 +3267,14 @@ iscsi_session_create(struct scsi_transport_template *scsit,
|
||||
session = iscsi_hostdata(shost->hostdata);
|
||||
memset(session, 0, sizeof(struct iscsi_session));
|
||||
session->host = shost;
|
||||
session->state = ISCSI_STATE_LOGGED_IN;
|
||||
session->state = ISCSI_STATE_FREE;
|
||||
session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
|
||||
session->cmds_max = ISCSI_XMIT_CMDS_MAX;
|
||||
session->cmdsn = initial_cmdsn;
|
||||
session->exp_cmdsn = initial_cmdsn + 1;
|
||||
session->max_cmdsn = initial_cmdsn + 1;
|
||||
session->max_r2t = 1;
|
||||
*sid = shost->host_no;
|
||||
|
||||
/* initialize SCSI PDU commands pool */
|
||||
if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
|
||||
@ -3311,22 +3311,24 @@ iscsi_session_create(struct scsi_transport_template *scsit,
|
||||
if (iscsi_r2tpool_alloc(session))
|
||||
goto r2tpool_alloc_fail;
|
||||
|
||||
return shost;
|
||||
return hostdata_session(shost->hostdata);
|
||||
|
||||
r2tpool_alloc_fail:
|
||||
for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
|
||||
kfree(session->mgmt_cmds[cmd_i]->data);
|
||||
iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
|
||||
immdata_alloc_fail:
|
||||
iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
|
||||
mgmtpool_alloc_fail:
|
||||
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
|
||||
cmdpool_alloc_fail:
|
||||
iscsi_transport_destroy_session(shost);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_session_destroy(struct Scsi_Host *shost)
|
||||
iscsi_session_destroy(struct iscsi_cls_session *cls_session)
|
||||
{
|
||||
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
||||
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
|
||||
int cmd_i;
|
||||
struct iscsi_data_task *dtask, *n;
|
||||
@ -3350,10 +3352,10 @@ iscsi_session_destroy(struct Scsi_Host *shost)
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
|
||||
iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
|
||||
uint32_t value)
|
||||
{
|
||||
struct iscsi_conn *conn = iscsi_ptr(connh);
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
struct iscsi_session *session = conn->session;
|
||||
|
||||
spin_lock_bh(&session->lock);
|
||||
@ -3495,9 +3497,10 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_session_get_param(struct Scsi_Host *shost,
|
||||
iscsi_session_get_param(struct iscsi_cls_session *cls_session,
|
||||
enum iscsi_param param, uint32_t *value)
|
||||
{
|
||||
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
||||
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
|
||||
|
||||
switch(param) {
|
||||
@ -3539,9 +3542,10 @@ iscsi_session_get_param(struct Scsi_Host *shost,
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
|
||||
iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
|
||||
enum iscsi_param param, uint32_t *value)
|
||||
{
|
||||
struct iscsi_conn *conn = data;
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
|
||||
switch(param) {
|
||||
case ISCSI_PARAM_MAX_RECV_DLENGTH:
|
||||
@ -3564,9 +3568,9 @@ iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
|
||||
iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
|
||||
{
|
||||
struct iscsi_conn *conn = iscsi_ptr(connh);
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
|
||||
stats->txdata_octets = conn->txdata_octets;
|
||||
stats->rxdata_octets = conn->rxdata_octets;
|
||||
@ -3587,10 +3591,10 @@ iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data,
|
||||
uint32_t data_size)
|
||||
iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
|
||||
char *data, uint32_t data_size)
|
||||
{
|
||||
struct iscsi_conn *conn = iscsi_ptr(connh);
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
int rc;
|
||||
|
||||
mutex_lock(&conn->xmitmutex);
|
||||
|
@ -113,7 +113,10 @@ struct iscsi_tcp_recv {
|
||||
int datadgst;
|
||||
};
|
||||
|
||||
struct iscsi_cls_conn;
|
||||
|
||||
struct iscsi_conn {
|
||||
struct iscsi_cls_conn *cls_conn; /* ptr to class connection */
|
||||
struct iscsi_hdr hdr; /* header placeholder */
|
||||
char hdrext[4*sizeof(__u16) +
|
||||
sizeof(__u32)];
|
||||
@ -143,7 +146,6 @@ struct iscsi_conn {
|
||||
struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */
|
||||
struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */
|
||||
struct iscsi_cmd_task *ctask; /* xmit ctask in progress */
|
||||
spinlock_t lock; /* FIXME: to be removed */
|
||||
|
||||
/* old values for socket callbacks */
|
||||
void (*old_data_ready)(struct sock *, int);
|
||||
|
@ -5049,7 +5049,7 @@ static struct pci_device_id megaraid_pci_tbl[] = {
|
||||
MODULE_DEVICE_TABLE(pci, megaraid_pci_tbl);
|
||||
|
||||
static struct pci_driver megaraid_pci_driver = {
|
||||
.name = "megaraid",
|
||||
.name = "megaraid_legacy",
|
||||
.id_table = megaraid_pci_tbl,
|
||||
.probe = megaraid_probe_one,
|
||||
.remove = __devexit_p(megaraid_remove_one),
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#define MEGARAID_VERSION \
|
||||
"v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n"
|
||||
"v2.00.4 (Release Date: Thu Feb 9 08:51:30 EST 2006)\n"
|
||||
|
||||
/*
|
||||
* Driver features - change the values to enable or disable features in the
|
||||
|
@ -10,7 +10,7 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FILE : megaraid_sas.c
|
||||
* Version : v00.00.02.02
|
||||
* Version : v00.00.02.04
|
||||
*
|
||||
* Authors:
|
||||
* Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
|
||||
@ -59,6 +59,12 @@ static struct pci_device_id megasas_pci_table[] = {
|
||||
PCI_ANY_ID,
|
||||
PCI_ANY_ID,
|
||||
},
|
||||
{
|
||||
PCI_VENDOR_ID_LSI_LOGIC,
|
||||
PCI_DEVICE_ID_LSI_SAS1078R, // ppc IOP
|
||||
PCI_ANY_ID,
|
||||
PCI_ANY_ID,
|
||||
},
|
||||
{
|
||||
PCI_VENDOR_ID_DELL,
|
||||
PCI_DEVICE_ID_DELL_PERC5, // xscale IOP
|
||||
@ -198,6 +204,86 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
|
||||
* to xscale (deviceid : 1064R, PERC5) controllers
|
||||
*/
|
||||
|
||||
/**
|
||||
* The following functions are defined for ppc (deviceid : 0x60)
|
||||
* controllers
|
||||
*/
|
||||
|
||||
/**
|
||||
* megasas_enable_intr_ppc - Enables interrupts
|
||||
* @regs: MFI register set
|
||||
*/
|
||||
static inline void
|
||||
megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
|
||||
{
|
||||
writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
|
||||
|
||||
writel(~0x80000004, &(regs)->outbound_intr_mask);
|
||||
|
||||
/* Dummy readl to force pci flush */
|
||||
readl(®s->outbound_intr_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* megasas_read_fw_status_reg_ppc - returns the current FW status value
|
||||
* @regs: MFI register set
|
||||
*/
|
||||
static u32
|
||||
megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
|
||||
{
|
||||
return readl(&(regs)->outbound_scratch_pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* megasas_clear_interrupt_ppc - Check & clear interrupt
|
||||
* @regs: MFI register set
|
||||
*/
|
||||
static int
|
||||
megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
|
||||
{
|
||||
u32 status;
|
||||
/*
|
||||
* Check if it is our interrupt
|
||||
*/
|
||||
status = readl(®s->outbound_intr_status);
|
||||
|
||||
if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the interrupt by writing back the same value
|
||||
*/
|
||||
writel(status, ®s->outbound_doorbell_clear);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* megasas_fire_cmd_ppc - Sends command to the FW
|
||||
* @frame_phys_addr : Physical address of cmd
|
||||
* @frame_count : Number of frames for the command
|
||||
* @regs : MFI register set
|
||||
*/
|
||||
static inline void
|
||||
megasas_fire_cmd_ppc(dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs)
|
||||
{
|
||||
writel((frame_phys_addr | (frame_count<<1))|1,
|
||||
&(regs)->inbound_queue_port);
|
||||
}
|
||||
|
||||
static struct megasas_instance_template megasas_instance_template_ppc = {
|
||||
|
||||
.fire_cmd = megasas_fire_cmd_ppc,
|
||||
.enable_intr = megasas_enable_intr_ppc,
|
||||
.clear_intr = megasas_clear_intr_ppc,
|
||||
.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the end of set of functions & definitions
|
||||
* specific to ppc (deviceid : 0x60) controllers
|
||||
*/
|
||||
|
||||
/**
|
||||
* megasas_disable_intr - Disables interrupts
|
||||
* @regs: MFI register set
|
||||
@ -1607,7 +1693,17 @@ static int megasas_init_mfi(struct megasas_instance *instance)
|
||||
|
||||
reg_set = instance->reg_set;
|
||||
|
||||
instance->instancet = &megasas_instance_template_xscale;
|
||||
switch(instance->pdev->device)
|
||||
{
|
||||
case PCI_DEVICE_ID_LSI_SAS1078R:
|
||||
instance->instancet = &megasas_instance_template_ppc;
|
||||
break;
|
||||
case PCI_DEVICE_ID_LSI_SAS1064R:
|
||||
case PCI_DEVICE_ID_DELL_PERC5:
|
||||
default:
|
||||
instance->instancet = &megasas_instance_template_xscale;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We expect the FW state to be READY
|
||||
@ -1983,6 +2079,7 @@ static int megasas_io_attach(struct megasas_instance *instance)
|
||||
host->max_channel = MEGASAS_MAX_CHANNELS - 1;
|
||||
host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
|
||||
host->max_lun = MEGASAS_MAX_LUN;
|
||||
host->max_cmd_len = 16;
|
||||
|
||||
/*
|
||||
* Notify the mid-layer about the new controller
|
||||
|
@ -18,9 +18,9 @@
|
||||
/**
|
||||
* MegaRAID SAS Driver meta data
|
||||
*/
|
||||
#define MEGASAS_VERSION "00.00.02.02"
|
||||
#define MEGASAS_RELDATE "Jan 23, 2006"
|
||||
#define MEGASAS_EXT_VERSION "Mon Jan 23 14:09:01 PST 2006"
|
||||
#define MEGASAS_VERSION "00.00.02.04"
|
||||
#define MEGASAS_RELDATE "Feb 03, 2006"
|
||||
#define MEGASAS_EXT_VERSION "Fri Feb 03 14:31:44 PST 2006"
|
||||
/*
|
||||
* =====================================
|
||||
* MegaRAID SAS MFI firmware definitions
|
||||
@ -553,31 +553,46 @@ struct megasas_ctrl_info {
|
||||
#define MFI_OB_INTR_STATUS_MASK 0x00000002
|
||||
#define MFI_POLL_TIMEOUT_SECS 10
|
||||
|
||||
#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
|
||||
#define PCI_DEVICE_ID_LSI_SAS1078R 0x00000060
|
||||
|
||||
struct megasas_register_set {
|
||||
u32 reserved_0[4]; /*0000h*/
|
||||
|
||||
u32 reserved_0[4]; /*0000h */
|
||||
u32 inbound_msg_0; /*0010h*/
|
||||
u32 inbound_msg_1; /*0014h*/
|
||||
u32 outbound_msg_0; /*0018h*/
|
||||
u32 outbound_msg_1; /*001Ch*/
|
||||
|
||||
u32 inbound_msg_0; /*0010h */
|
||||
u32 inbound_msg_1; /*0014h */
|
||||
u32 outbound_msg_0; /*0018h */
|
||||
u32 outbound_msg_1; /*001Ch */
|
||||
u32 inbound_doorbell; /*0020h*/
|
||||
u32 inbound_intr_status; /*0024h*/
|
||||
u32 inbound_intr_mask; /*0028h*/
|
||||
|
||||
u32 inbound_doorbell; /*0020h */
|
||||
u32 inbound_intr_status; /*0024h */
|
||||
u32 inbound_intr_mask; /*0028h */
|
||||
u32 outbound_doorbell; /*002Ch*/
|
||||
u32 outbound_intr_status; /*0030h*/
|
||||
u32 outbound_intr_mask; /*0034h*/
|
||||
|
||||
u32 outbound_doorbell; /*002Ch */
|
||||
u32 outbound_intr_status; /*0030h */
|
||||
u32 outbound_intr_mask; /*0034h */
|
||||
u32 reserved_1[2]; /*0038h*/
|
||||
|
||||
u32 reserved_1[2]; /*0038h */
|
||||
u32 inbound_queue_port; /*0040h*/
|
||||
u32 outbound_queue_port; /*0044h*/
|
||||
|
||||
u32 inbound_queue_port; /*0040h */
|
||||
u32 outbound_queue_port; /*0044h */
|
||||
u32 reserved_2[22]; /*0048h*/
|
||||
|
||||
u32 reserved_2; /*004Ch */
|
||||
u32 outbound_doorbell_clear; /*00A0h*/
|
||||
|
||||
u32 index_registers[1004]; /*0050h */
|
||||
u32 reserved_3[3]; /*00A4h*/
|
||||
|
||||
u32 outbound_scratch_pad ; /*00B0h*/
|
||||
|
||||
u32 reserved_4[3]; /*00B4h*/
|
||||
|
||||
u32 inbound_low_queue_port ; /*00C0h*/
|
||||
|
||||
u32 inbound_high_queue_port ; /*00C4h*/
|
||||
|
||||
u32 reserved_5; /*00C8h*/
|
||||
u32 index_registers[820]; /*00CCh*/
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "qla_def.h"
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
/* SYSFS attributes --------------------------------------------------------- */
|
||||
|
||||
@ -114,7 +113,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
|
||||
struct device, kobj)));
|
||||
unsigned long flags;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
|
||||
if (!capable(CAP_SYS_ADMIN) || off != 0)
|
||||
return 0;
|
||||
|
||||
/* Read NVRAM. */
|
||||
@ -123,7 +122,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
|
||||
ha->nvram_size);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
return (count);
|
||||
return ha->nvram_size;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@ -175,19 +174,150 @@ static struct bin_attribute sysfs_nvram_attr = {
|
||||
.mode = S_IRUSR | S_IWUSR,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.size = 0,
|
||||
.size = 512,
|
||||
.read = qla2x00_sysfs_read_nvram,
|
||||
.write = qla2x00_sysfs_write_nvram,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
|
||||
size_t count)
|
||||
{
|
||||
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
|
||||
struct device, kobj)));
|
||||
|
||||
if (ha->optrom_state != QLA_SREADING)
|
||||
return 0;
|
||||
if (off > ha->optrom_size)
|
||||
return 0;
|
||||
if (off + count > ha->optrom_size)
|
||||
count = ha->optrom_size - off;
|
||||
|
||||
memcpy(buf, &ha->optrom_buffer[off], count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
|
||||
size_t count)
|
||||
{
|
||||
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
|
||||
struct device, kobj)));
|
||||
|
||||
if (ha->optrom_state != QLA_SWRITING)
|
||||
return -EINVAL;
|
||||
if (off > ha->optrom_size)
|
||||
return -ERANGE;
|
||||
if (off + count > ha->optrom_size)
|
||||
count = ha->optrom_size - off;
|
||||
|
||||
memcpy(&ha->optrom_buffer[off], buf, count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute sysfs_optrom_attr = {
|
||||
.attr = {
|
||||
.name = "optrom",
|
||||
.mode = S_IRUSR | S_IWUSR,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.size = OPTROM_SIZE_24XX,
|
||||
.read = qla2x00_sysfs_read_optrom,
|
||||
.write = qla2x00_sysfs_write_optrom,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
|
||||
size_t count)
|
||||
{
|
||||
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
|
||||
struct device, kobj)));
|
||||
int val;
|
||||
|
||||
if (off)
|
||||
return 0;
|
||||
|
||||
if (sscanf(buf, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
switch (val) {
|
||||
case 0:
|
||||
if (ha->optrom_state != QLA_SREADING &&
|
||||
ha->optrom_state != QLA_SWRITING)
|
||||
break;
|
||||
|
||||
ha->optrom_state = QLA_SWAITING;
|
||||
vfree(ha->optrom_buffer);
|
||||
ha->optrom_buffer = NULL;
|
||||
break;
|
||||
case 1:
|
||||
if (ha->optrom_state != QLA_SWAITING)
|
||||
break;
|
||||
|
||||
ha->optrom_state = QLA_SREADING;
|
||||
ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
|
||||
if (ha->optrom_buffer == NULL) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Unable to allocate memory for optrom retrieval "
|
||||
"(%x).\n", ha->optrom_size);
|
||||
|
||||
ha->optrom_state = QLA_SWAITING;
|
||||
return count;
|
||||
}
|
||||
|
||||
memset(ha->optrom_buffer, 0, ha->optrom_size);
|
||||
ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0,
|
||||
ha->optrom_size);
|
||||
break;
|
||||
case 2:
|
||||
if (ha->optrom_state != QLA_SWAITING)
|
||||
break;
|
||||
|
||||
ha->optrom_state = QLA_SWRITING;
|
||||
ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
|
||||
if (ha->optrom_buffer == NULL) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Unable to allocate memory for optrom update "
|
||||
"(%x).\n", ha->optrom_size);
|
||||
|
||||
ha->optrom_state = QLA_SWAITING;
|
||||
return count;
|
||||
}
|
||||
memset(ha->optrom_buffer, 0, ha->optrom_size);
|
||||
break;
|
||||
case 3:
|
||||
if (ha->optrom_state != QLA_SWRITING)
|
||||
break;
|
||||
|
||||
ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0,
|
||||
ha->optrom_size);
|
||||
break;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute sysfs_optrom_ctl_attr = {
|
||||
.attr = {
|
||||
.name = "optrom_ctl",
|
||||
.mode = S_IWUSR,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.size = 0,
|
||||
.write = qla2x00_sysfs_write_optrom_ctl,
|
||||
};
|
||||
|
||||
void
|
||||
qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
|
||||
{
|
||||
struct Scsi_Host *host = ha->host;
|
||||
|
||||
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
|
||||
sysfs_nvram_attr.size = ha->nvram_size;
|
||||
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
|
||||
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
|
||||
sysfs_create_bin_file(&host->shost_gendev.kobj,
|
||||
&sysfs_optrom_ctl_attr);
|
||||
}
|
||||
|
||||
void
|
||||
@ -197,6 +327,12 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
|
||||
|
||||
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
|
||||
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
|
||||
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
|
||||
sysfs_remove_bin_file(&host->shost_gendev.kobj,
|
||||
&sysfs_optrom_ctl_attr);
|
||||
|
||||
if (ha->beacon_blink_led == 1)
|
||||
ha->isp_ops.beacon_off(ha);
|
||||
}
|
||||
|
||||
/* Scsi_Host attributes. */
|
||||
@ -384,6 +520,50 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
qla2x00_beacon_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
|
||||
int len = 0;
|
||||
|
||||
if (ha->beacon_blink_led)
|
||||
len += snprintf(buf + len, PAGE_SIZE-len, "Enabled\n");
|
||||
else
|
||||
len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
qla2x00_beacon_store(struct class_device *cdev, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
|
||||
int val = 0;
|
||||
int rval;
|
||||
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||
return -EPERM;
|
||||
|
||||
if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Abort ISP active -- ignoring beacon request.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (sscanf(buf, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (val)
|
||||
rval = ha->isp_ops.beacon_on(ha);
|
||||
else
|
||||
rval = ha->isp_ops.beacon_off(ha);
|
||||
|
||||
if (rval != QLA_SUCCESS)
|
||||
count = 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
|
||||
NULL);
|
||||
static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
|
||||
@ -398,6 +578,8 @@ static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show,
|
||||
qla2x00_zio_store);
|
||||
static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
|
||||
qla2x00_zio_timer_store);
|
||||
static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
|
||||
qla2x00_beacon_store);
|
||||
|
||||
struct class_device_attribute *qla2x00_host_attrs[] = {
|
||||
&class_device_attr_driver_version,
|
||||
@ -411,6 +593,7 @@ struct class_device_attribute *qla2x00_host_attrs[] = {
|
||||
&class_device_attr_state,
|
||||
&class_device_attr_zio,
|
||||
&class_device_attr_zio_timer,
|
||||
&class_device_attr_beacon,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@ -425,6 +608,49 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost)
|
||||
ha->d_id.b.area << 8 | ha->d_id.b.al_pa;
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_get_host_speed(struct Scsi_Host *shost)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(shost);
|
||||
uint32_t speed = 0;
|
||||
|
||||
switch (ha->link_data_rate) {
|
||||
case LDR_1GB:
|
||||
speed = 1;
|
||||
break;
|
||||
case LDR_2GB:
|
||||
speed = 2;
|
||||
break;
|
||||
case LDR_4GB:
|
||||
speed = 4;
|
||||
break;
|
||||
}
|
||||
fc_host_speed(shost) = speed;
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_get_host_port_type(struct Scsi_Host *shost)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(shost);
|
||||
uint32_t port_type = FC_PORTTYPE_UNKNOWN;
|
||||
|
||||
switch (ha->current_topology) {
|
||||
case ISP_CFG_NL:
|
||||
port_type = FC_PORTTYPE_LPORT;
|
||||
break;
|
||||
case ISP_CFG_FL:
|
||||
port_type = FC_PORTTYPE_NLPORT;
|
||||
break;
|
||||
case ISP_CFG_N:
|
||||
port_type = FC_PORTTYPE_PTP;
|
||||
break;
|
||||
case ISP_CFG_F:
|
||||
port_type = FC_PORTTYPE_NPORT;
|
||||
break;
|
||||
}
|
||||
fc_host_port_type(shost) = port_type;
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_get_starget_node_name(struct scsi_target *starget)
|
||||
{
|
||||
@ -512,6 +738,41 @@ qla2x00_issue_lip(struct Scsi_Host *shost)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fc_host_statistics *
|
||||
qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(shost);
|
||||
int rval;
|
||||
uint16_t mb_stat[1];
|
||||
link_stat_t stat_buf;
|
||||
struct fc_host_statistics *pfc_host_stat;
|
||||
|
||||
pfc_host_stat = &ha->fc_host_stat;
|
||||
memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
|
||||
|
||||
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
|
||||
rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf,
|
||||
sizeof(stat_buf) / 4, mb_stat);
|
||||
} else {
|
||||
rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf,
|
||||
mb_stat);
|
||||
}
|
||||
if (rval != 0) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Unable to retrieve host statistics (%d).\n", mb_stat[0]);
|
||||
return pfc_host_stat;
|
||||
}
|
||||
|
||||
pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt;
|
||||
pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt;
|
||||
pfc_host_stat->loss_of_signal_count = stat_buf.loss_sig_cnt;
|
||||
pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt;
|
||||
pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt;
|
||||
pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt;
|
||||
|
||||
return pfc_host_stat;
|
||||
}
|
||||
|
||||
struct fc_function_template qla2xxx_transport_functions = {
|
||||
|
||||
.show_host_node_name = 1,
|
||||
@ -520,6 +781,10 @@ struct fc_function_template qla2xxx_transport_functions = {
|
||||
|
||||
.get_host_port_id = qla2x00_get_host_port_id,
|
||||
.show_host_port_id = 1,
|
||||
.get_host_speed = qla2x00_get_host_speed,
|
||||
.show_host_speed = 1,
|
||||
.get_host_port_type = qla2x00_get_host_port_type,
|
||||
.show_host_port_type = 1,
|
||||
|
||||
.dd_fcrport_size = sizeof(struct fc_port *),
|
||||
.show_rport_supported_classes = 1,
|
||||
@ -536,6 +801,7 @@ struct fc_function_template qla2xxx_transport_functions = {
|
||||
.show_rport_dev_loss_tmo = 1,
|
||||
|
||||
.issue_fc_host_lip = qla2x00_issue_lip,
|
||||
.get_fc_host_stats = qla2x00_get_fc_host_stats,
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
|
||||
#if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE)
|
||||
@ -180,6 +181,13 @@
|
||||
#define WRT_REG_WORD(addr, data) writew(data,addr)
|
||||
#define WRT_REG_DWORD(addr, data) writel(data,addr)
|
||||
|
||||
/*
|
||||
* The ISP2312 v2 chip cannot access the FLASH/GPIO registers via MMIO in an
|
||||
* 133Mhz slot.
|
||||
*/
|
||||
#define RD_REG_WORD_PIO(addr) (inw((unsigned long)addr))
|
||||
#define WRT_REG_WORD_PIO(addr, data) (outw(data,(unsigned long)addr))
|
||||
|
||||
/*
|
||||
* Fibre Channel device definitions.
|
||||
*/
|
||||
@ -432,6 +440,9 @@ struct device_reg_2xxx {
|
||||
#define GPIO_LED_GREEN_ON_AMBER_OFF 0x0040
|
||||
#define GPIO_LED_GREEN_OFF_AMBER_ON 0x0080
|
||||
#define GPIO_LED_GREEN_ON_AMBER_ON 0x00C0
|
||||
#define GPIO_LED_ALL_OFF 0x0000
|
||||
#define GPIO_LED_RED_ON_OTHER_OFF 0x0001 /* isp2322 */
|
||||
#define GPIO_LED_RGA_ON 0x00C1 /* isp2322: red green amber */
|
||||
|
||||
union {
|
||||
struct {
|
||||
@ -2199,6 +2210,15 @@ struct isp_operations {
|
||||
|
||||
void (*fw_dump) (struct scsi_qla_host *, int);
|
||||
void (*ascii_fw_dump) (struct scsi_qla_host *);
|
||||
|
||||
int (*beacon_on) (struct scsi_qla_host *);
|
||||
int (*beacon_off) (struct scsi_qla_host *);
|
||||
void (*beacon_blink) (struct scsi_qla_host *);
|
||||
|
||||
uint8_t * (*read_optrom) (struct scsi_qla_host *, uint8_t *,
|
||||
uint32_t, uint32_t);
|
||||
int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t,
|
||||
uint32_t);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -2331,6 +2351,10 @@ typedef struct scsi_qla_host {
|
||||
uint16_t min_external_loopid; /* First external loop Id */
|
||||
|
||||
uint16_t link_data_rate; /* F/W operating speed */
|
||||
#define LDR_1GB 0
|
||||
#define LDR_2GB 1
|
||||
#define LDR_4GB 3
|
||||
#define LDR_UNKNOWN 0xFFFF
|
||||
|
||||
uint8_t current_topology;
|
||||
uint8_t prev_topology;
|
||||
@ -2486,12 +2510,26 @@ typedef struct scsi_qla_host {
|
||||
uint8_t *port_name;
|
||||
uint32_t isp_abort_cnt;
|
||||
|
||||
/* Option ROM information. */
|
||||
char *optrom_buffer;
|
||||
uint32_t optrom_size;
|
||||
int optrom_state;
|
||||
#define QLA_SWAITING 0
|
||||
#define QLA_SREADING 1
|
||||
#define QLA_SWRITING 2
|
||||
|
||||
/* Needed for BEACON */
|
||||
uint16_t beacon_blink_led;
|
||||
uint16_t beacon_green_on;
|
||||
uint8_t beacon_color_state;
|
||||
#define QLA_LED_GRN_ON 0x01
|
||||
#define QLA_LED_YLW_ON 0x02
|
||||
#define QLA_LED_ABR_ON 0x04
|
||||
#define QLA_LED_ALL_ON 0x07 /* yellow, green, amber. */
|
||||
/* ISP2322: red, green, amber. */
|
||||
|
||||
uint16_t zio_mode;
|
||||
uint16_t zio_timer;
|
||||
struct fc_host_statistics fc_host_stat;
|
||||
} scsi_qla_host_t;
|
||||
|
||||
|
||||
@ -2557,7 +2595,9 @@ struct _qla2x00stats {
|
||||
/*
|
||||
* Flash support definitions
|
||||
*/
|
||||
#define FLASH_IMAGE_SIZE 131072
|
||||
#define OPTROM_SIZE_2300 0x20000
|
||||
#define OPTROM_SIZE_2322 0x100000
|
||||
#define OPTROM_SIZE_24XX 0x100000
|
||||
|
||||
#include "qla_gbl.h"
|
||||
#include "qla_dbg.h"
|
||||
|
@ -75,12 +75,12 @@ extern void qla2x00_cmd_timeout(srb_t *);
|
||||
extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
|
||||
extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
|
||||
|
||||
extern void qla2x00_blink_led(scsi_qla_host_t *);
|
||||
|
||||
extern int qla2x00_down_timeout(struct semaphore *, unsigned long);
|
||||
|
||||
extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
|
||||
|
||||
extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
|
||||
|
||||
/*
|
||||
* Global Function Prototypes in qla_iocb.c source file.
|
||||
*/
|
||||
@ -185,6 +185,13 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *,
|
||||
extern int
|
||||
qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
|
||||
|
||||
extern int
|
||||
qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, link_stat_t *,
|
||||
uint16_t *);
|
||||
|
||||
extern int
|
||||
qla24xx_get_isp_stats(scsi_qla_host_t *, uint32_t *, uint32_t, uint16_t *);
|
||||
|
||||
extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *);
|
||||
extern int qla24xx_abort_target(fc_port_t *);
|
||||
|
||||
@ -228,6 +235,22 @@ extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
|
||||
extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
|
||||
uint32_t);
|
||||
|
||||
extern int qla2x00_beacon_on(struct scsi_qla_host *);
|
||||
extern int qla2x00_beacon_off(struct scsi_qla_host *);
|
||||
extern void qla2x00_beacon_blink(struct scsi_qla_host *);
|
||||
extern int qla24xx_beacon_on(struct scsi_qla_host *);
|
||||
extern int qla24xx_beacon_off(struct scsi_qla_host *);
|
||||
extern void qla24xx_beacon_blink(struct scsi_qla_host *);
|
||||
|
||||
extern uint8_t *qla2x00_read_optrom_data(struct scsi_qla_host *, uint8_t *,
|
||||
uint32_t, uint32_t);
|
||||
extern int qla2x00_write_optrom_data(struct scsi_qla_host *, uint8_t *,
|
||||
uint32_t, uint32_t);
|
||||
extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
|
||||
uint32_t, uint32_t);
|
||||
extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
|
||||
uint32_t, uint32_t);
|
||||
|
||||
/*
|
||||
* Global Function Prototypes in qla_dbg.c source file.
|
||||
*/
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "qla_devtbl.h"
|
||||
|
||||
|
@ -814,6 +814,7 @@ qla24xx_start_scsi(srb_t *sp)
|
||||
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
|
||||
|
||||
int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
|
||||
host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
|
||||
|
||||
/* Load SCSI command packet. */
|
||||
memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
|
||||
|
@ -402,9 +402,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
|
||||
break;
|
||||
|
||||
case MBA_LOOP_UP: /* Loop Up Event */
|
||||
ha->link_data_rate = 0;
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
|
||||
link_speed = link_speeds[0];
|
||||
ha->link_data_rate = LDR_1GB;
|
||||
} else {
|
||||
link_speed = link_speeds[LS_UNKNOWN];
|
||||
if (mb[1] < 5)
|
||||
@ -436,7 +436,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
|
||||
}
|
||||
|
||||
ha->flags.management_server_logged_in = 0;
|
||||
ha->link_data_rate = 0;
|
||||
ha->link_data_rate = LDR_UNKNOWN;
|
||||
if (ql2xfdmienable)
|
||||
set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "qla_def.h"
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
static void
|
||||
qla2x00_mbx_sem_timeout(unsigned long data)
|
||||
@ -1874,7 +1873,8 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
|
||||
mcp->mb[3] = LSW(id_list_dma);
|
||||
mcp->mb[6] = MSW(MSD(id_list_dma));
|
||||
mcp->mb[7] = LSW(MSD(id_list_dma));
|
||||
mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2;
|
||||
mcp->mb[8] = 0;
|
||||
mcp->out_mb |= MBX_8|MBX_7|MBX_6|MBX_3|MBX_2;
|
||||
} else {
|
||||
mcp->mb[1] = MSW(id_list_dma);
|
||||
mcp->mb[2] = LSW(id_list_dma);
|
||||
@ -2017,8 +2017,109 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map)
|
||||
|
||||
return rval;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t
|
||||
/*
|
||||
* qla2x00_get_link_status
|
||||
*
|
||||
* Input:
|
||||
* ha = adapter block pointer.
|
||||
* loop_id = device loop ID.
|
||||
* ret_buf = pointer to link status return buffer.
|
||||
*
|
||||
* Returns:
|
||||
* 0 = success.
|
||||
* BIT_0 = mem alloc error.
|
||||
* BIT_1 = mailbox error.
|
||||
*/
|
||||
int
|
||||
qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
|
||||
link_stat_t *ret_buf, uint16_t *status)
|
||||
{
|
||||
int rval;
|
||||
mbx_cmd_t mc;
|
||||
mbx_cmd_t *mcp = &mc;
|
||||
link_stat_t *stat_buf;
|
||||
dma_addr_t stat_buf_dma;
|
||||
|
||||
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
|
||||
|
||||
stat_buf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &stat_buf_dma);
|
||||
if (stat_buf == NULL) {
|
||||
DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
|
||||
__func__, ha->host_no));
|
||||
return BIT_0;
|
||||
}
|
||||
memset(stat_buf, 0, sizeof(link_stat_t));
|
||||
|
||||
mcp->mb[0] = MBC_GET_LINK_STATUS;
|
||||
mcp->mb[2] = MSW(stat_buf_dma);
|
||||
mcp->mb[3] = LSW(stat_buf_dma);
|
||||
mcp->mb[6] = MSW(MSD(stat_buf_dma));
|
||||
mcp->mb[7] = LSW(MSD(stat_buf_dma));
|
||||
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
|
||||
mcp->in_mb = MBX_0;
|
||||
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
|
||||
mcp->mb[1] = loop_id;
|
||||
mcp->mb[4] = 0;
|
||||
mcp->mb[10] = 0;
|
||||
mcp->out_mb |= MBX_10|MBX_4|MBX_1;
|
||||
mcp->in_mb |= MBX_1;
|
||||
} else if (HAS_EXTENDED_IDS(ha)) {
|
||||
mcp->mb[1] = loop_id;
|
||||
mcp->mb[10] = 0;
|
||||
mcp->out_mb |= MBX_10|MBX_1;
|
||||
} else {
|
||||
mcp->mb[1] = loop_id << 8;
|
||||
mcp->out_mb |= MBX_1;
|
||||
}
|
||||
mcp->tov = 30;
|
||||
mcp->flags = IOCTL_CMD;
|
||||
rval = qla2x00_mailbox_command(ha, mcp);
|
||||
|
||||
if (rval == QLA_SUCCESS) {
|
||||
if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
|
||||
DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
|
||||
__func__, ha->host_no, mcp->mb[0]);)
|
||||
status[0] = mcp->mb[0];
|
||||
rval = BIT_1;
|
||||
} else {
|
||||
/* copy over data -- firmware data is LE. */
|
||||
ret_buf->link_fail_cnt =
|
||||
le32_to_cpu(stat_buf->link_fail_cnt);
|
||||
ret_buf->loss_sync_cnt =
|
||||
le32_to_cpu(stat_buf->loss_sync_cnt);
|
||||
ret_buf->loss_sig_cnt =
|
||||
le32_to_cpu(stat_buf->loss_sig_cnt);
|
||||
ret_buf->prim_seq_err_cnt =
|
||||
le32_to_cpu(stat_buf->prim_seq_err_cnt);
|
||||
ret_buf->inval_xmit_word_cnt =
|
||||
le32_to_cpu(stat_buf->inval_xmit_word_cnt);
|
||||
ret_buf->inval_crc_cnt =
|
||||
le32_to_cpu(stat_buf->inval_crc_cnt);
|
||||
|
||||
DEBUG11(printk("%s(%ld): stat dump: fail_cnt=%d "
|
||||
"loss_sync=%d loss_sig=%d seq_err=%d "
|
||||
"inval_xmt_word=%d inval_crc=%d.\n", __func__,
|
||||
ha->host_no, stat_buf->link_fail_cnt,
|
||||
stat_buf->loss_sync_cnt, stat_buf->loss_sig_cnt,
|
||||
stat_buf->prim_seq_err_cnt,
|
||||
stat_buf->inval_xmit_word_cnt,
|
||||
stat_buf->inval_crc_cnt);)
|
||||
}
|
||||
} else {
|
||||
/* Failed. */
|
||||
DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
|
||||
ha->host_no, rval);)
|
||||
rval = BIT_1;
|
||||
}
|
||||
|
||||
dma_pool_free(ha->s_dma_pool, stat_buf, stat_buf_dma);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
int
|
||||
qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
|
||||
uint16_t *status)
|
||||
{
|
||||
@ -2080,7 +2181,6 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
|
||||
|
||||
return rval;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
|
||||
|
@ -366,6 +366,12 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
|
||||
goto qc_fail_command;
|
||||
}
|
||||
|
||||
/* Close window on fcport/rport state-transitioning. */
|
||||
if (!*(fc_port_t **)rport->dd_data) {
|
||||
cmd->result = DID_IMM_RETRY << 16;
|
||||
goto qc_fail_command;
|
||||
}
|
||||
|
||||
if (atomic_read(&fcport->state) != FCS_ONLINE) {
|
||||
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
|
||||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
|
||||
@ -421,6 +427,12 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
|
||||
goto qc24_fail_command;
|
||||
}
|
||||
|
||||
/* Close window on fcport/rport state-transitioning. */
|
||||
if (!*(fc_port_t **)rport->dd_data) {
|
||||
cmd->result = DID_IMM_RETRY << 16;
|
||||
goto qc24_fail_command;
|
||||
}
|
||||
|
||||
if (atomic_read(&fcport->state) != FCS_ONLINE) {
|
||||
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
|
||||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
|
||||
@ -513,7 +525,7 @@ qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
|
||||
* Success (Adapter is online) : 0
|
||||
* Failed (Adapter is offline/disabled) : 1
|
||||
*/
|
||||
static int
|
||||
int
|
||||
qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
|
||||
{
|
||||
int return_status;
|
||||
@ -1312,6 +1324,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
|
||||
ha->ports = MAX_BUSES;
|
||||
ha->init_cb_size = sizeof(init_cb_t);
|
||||
ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
|
||||
ha->link_data_rate = LDR_UNKNOWN;
|
||||
ha->optrom_size = OPTROM_SIZE_2300;
|
||||
|
||||
/* Assign ISP specific operations. */
|
||||
ha->isp_ops.pci_config = qla2100_pci_config;
|
||||
@ -1339,6 +1353,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
|
||||
ha->isp_ops.write_nvram = qla2x00_write_nvram_data;
|
||||
ha->isp_ops.fw_dump = qla2100_fw_dump;
|
||||
ha->isp_ops.ascii_fw_dump = qla2100_ascii_fw_dump;
|
||||
ha->isp_ops.read_optrom = qla2x00_read_optrom_data;
|
||||
ha->isp_ops.write_optrom = qla2x00_write_optrom_data;
|
||||
if (IS_QLA2100(ha)) {
|
||||
host->max_id = MAX_TARGETS_2100;
|
||||
ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
|
||||
@ -1364,7 +1380,12 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
|
||||
ha->isp_ops.intr_handler = qla2300_intr_handler;
|
||||
ha->isp_ops.fw_dump = qla2300_fw_dump;
|
||||
ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump;
|
||||
ha->isp_ops.beacon_on = qla2x00_beacon_on;
|
||||
ha->isp_ops.beacon_off = qla2x00_beacon_off;
|
||||
ha->isp_ops.beacon_blink = qla2x00_beacon_blink;
|
||||
ha->gid_list_info_size = 6;
|
||||
if (IS_QLA2322(ha) || IS_QLA6322(ha))
|
||||
ha->optrom_size = OPTROM_SIZE_2322;
|
||||
} else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
|
||||
host->max_id = MAX_TARGETS_2200;
|
||||
ha->mbx_count = MAILBOX_REGISTER_COUNT;
|
||||
@ -1400,7 +1421,13 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
|
||||
ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
|
||||
ha->isp_ops.fw_dump = qla24xx_fw_dump;
|
||||
ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump;
|
||||
ha->isp_ops.read_optrom = qla24xx_read_optrom_data;
|
||||
ha->isp_ops.write_optrom = qla24xx_write_optrom_data;
|
||||
ha->isp_ops.beacon_on = qla24xx_beacon_on;
|
||||
ha->isp_ops.beacon_off = qla24xx_beacon_off;
|
||||
ha->isp_ops.beacon_blink = qla24xx_beacon_blink;
|
||||
ha->gid_list_info_size = 8;
|
||||
ha->optrom_size = OPTROM_SIZE_24XX;
|
||||
}
|
||||
host->can_queue = ha->request_q_length + 128;
|
||||
|
||||
@ -1657,11 +1684,13 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
|
||||
spin_lock_irqsave(&fcport->rport_lock, flags);
|
||||
fcport->drport = rport;
|
||||
fcport->rport = NULL;
|
||||
*(fc_port_t **)rport->dd_data = NULL;
|
||||
spin_unlock_irqrestore(&fcport->rport_lock, flags);
|
||||
set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
|
||||
} else {
|
||||
spin_lock_irqsave(&fcport->rport_lock, flags);
|
||||
fcport->rport = NULL;
|
||||
*(fc_port_t **)rport->dd_data = NULL;
|
||||
spin_unlock_irqrestore(&fcport->rport_lock, flags);
|
||||
fc_remote_port_delete(rport);
|
||||
}
|
||||
@ -2066,6 +2095,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
|
||||
ha->fw_dumped = 0;
|
||||
ha->fw_dump_reading = 0;
|
||||
ha->fw_dump_buffer = NULL;
|
||||
|
||||
vfree(ha->optrom_buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2314,6 +2345,9 @@ qla2x00_do_dpc(void *data)
|
||||
if (!ha->interrupts_on)
|
||||
ha->isp_ops.enable_intrs(ha);
|
||||
|
||||
if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags))
|
||||
ha->isp_ops.beacon_blink(ha);
|
||||
|
||||
ha->dpc_active = 0;
|
||||
} /* End of while(1) */
|
||||
|
||||
@ -2491,6 +2525,12 @@ qla2x00_timer(scsi_qla_host_t *ha)
|
||||
atomic_read(&ha->loop_down_timer)));
|
||||
}
|
||||
|
||||
/* Check if beacon LED needs to be blinked */
|
||||
if (ha->beacon_blink_led == 1) {
|
||||
set_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags);
|
||||
start_dpc++;
|
||||
}
|
||||
|
||||
/* Schedule the DPC routine if needed */
|
||||
if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
|
||||
test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
|
||||
@ -2499,6 +2539,7 @@ qla2x00_timer(scsi_qla_host_t *ha)
|
||||
start_dpc ||
|
||||
test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
|
||||
test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
|
||||
test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
|
||||
test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) &&
|
||||
ha->dpc_wait && !ha->dpc_active) {
|
||||
|
||||
|
@ -6,8 +6,6 @@
|
||||
*/
|
||||
#include "qla_def.h"
|
||||
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
/**
|
||||
* IO descriptor handle definitions.
|
||||
*
|
||||
|
@ -695,3 +695,966 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags)
|
||||
{
|
||||
if (IS_QLA2322(ha)) {
|
||||
/* Flip all colors. */
|
||||
if (ha->beacon_color_state == QLA_LED_ALL_ON) {
|
||||
/* Turn off. */
|
||||
ha->beacon_color_state = 0;
|
||||
*pflags = GPIO_LED_ALL_OFF;
|
||||
} else {
|
||||
/* Turn on. */
|
||||
ha->beacon_color_state = QLA_LED_ALL_ON;
|
||||
*pflags = GPIO_LED_RGA_ON;
|
||||
}
|
||||
} else {
|
||||
/* Flip green led only. */
|
||||
if (ha->beacon_color_state == QLA_LED_GRN_ON) {
|
||||
/* Turn off. */
|
||||
ha->beacon_color_state = 0;
|
||||
*pflags = GPIO_LED_GREEN_OFF_AMBER_OFF;
|
||||
} else {
|
||||
/* Turn on. */
|
||||
ha->beacon_color_state = QLA_LED_GRN_ON;
|
||||
*pflags = GPIO_LED_GREEN_ON_AMBER_OFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
qla2x00_beacon_blink(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint16_t gpio_enable;
|
||||
uint16_t gpio_data;
|
||||
uint16_t led_color = 0;
|
||||
unsigned long flags;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
if (ha->pio_address)
|
||||
reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
|
||||
/* Save the Original GPIOE. */
|
||||
if (ha->pio_address) {
|
||||
gpio_enable = RD_REG_WORD_PIO(®->gpioe);
|
||||
gpio_data = RD_REG_WORD_PIO(®->gpiod);
|
||||
} else {
|
||||
gpio_enable = RD_REG_WORD(®->gpioe);
|
||||
gpio_data = RD_REG_WORD(®->gpiod);
|
||||
}
|
||||
|
||||
/* Set the modified gpio_enable values */
|
||||
gpio_enable |= GPIO_LED_MASK;
|
||||
|
||||
if (ha->pio_address) {
|
||||
WRT_REG_WORD_PIO(®->gpioe, gpio_enable);
|
||||
} else {
|
||||
WRT_REG_WORD(®->gpioe, gpio_enable);
|
||||
RD_REG_WORD(®->gpioe);
|
||||
}
|
||||
|
||||
qla2x00_flip_colors(ha, &led_color);
|
||||
|
||||
/* Clear out any previously set LED color. */
|
||||
gpio_data &= ~GPIO_LED_MASK;
|
||||
|
||||
/* Set the new input LED color to GPIOD. */
|
||||
gpio_data |= led_color;
|
||||
|
||||
/* Set the modified gpio_data values */
|
||||
if (ha->pio_address) {
|
||||
WRT_REG_WORD_PIO(®->gpiod, gpio_data);
|
||||
} else {
|
||||
WRT_REG_WORD(®->gpiod, gpio_data);
|
||||
RD_REG_WORD(®->gpiod);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
}
|
||||
|
||||
int
|
||||
qla2x00_beacon_on(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint16_t gpio_enable;
|
||||
uint16_t gpio_data;
|
||||
unsigned long flags;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
|
||||
ha->fw_options[1] |= FO1_DISABLE_GPIO6_7;
|
||||
|
||||
if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Unable to update fw options (beacon on).\n");
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
if (ha->pio_address)
|
||||
reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
|
||||
|
||||
/* Turn off LEDs. */
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
if (ha->pio_address) {
|
||||
gpio_enable = RD_REG_WORD_PIO(®->gpioe);
|
||||
gpio_data = RD_REG_WORD_PIO(®->gpiod);
|
||||
} else {
|
||||
gpio_enable = RD_REG_WORD(®->gpioe);
|
||||
gpio_data = RD_REG_WORD(®->gpiod);
|
||||
}
|
||||
gpio_enable |= GPIO_LED_MASK;
|
||||
|
||||
/* Set the modified gpio_enable values. */
|
||||
if (ha->pio_address) {
|
||||
WRT_REG_WORD_PIO(®->gpioe, gpio_enable);
|
||||
} else {
|
||||
WRT_REG_WORD(®->gpioe, gpio_enable);
|
||||
RD_REG_WORD(®->gpioe);
|
||||
}
|
||||
|
||||
/* Clear out previously set LED colour. */
|
||||
gpio_data &= ~GPIO_LED_MASK;
|
||||
if (ha->pio_address) {
|
||||
WRT_REG_WORD_PIO(®->gpiod, gpio_data);
|
||||
} else {
|
||||
WRT_REG_WORD(®->gpiod, gpio_data);
|
||||
RD_REG_WORD(®->gpiod);
|
||||
}
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
/*
|
||||
* Let the per HBA timer kick off the blinking process based on
|
||||
* the following flags. No need to do anything else now.
|
||||
*/
|
||||
ha->beacon_blink_led = 1;
|
||||
ha->beacon_color_state = 0;
|
||||
|
||||
return QLA_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
qla2x00_beacon_off(struct scsi_qla_host *ha)
|
||||
{
|
||||
int rval = QLA_SUCCESS;
|
||||
|
||||
ha->beacon_blink_led = 0;
|
||||
|
||||
/* Set the on flag so when it gets flipped it will be off. */
|
||||
if (IS_QLA2322(ha))
|
||||
ha->beacon_color_state = QLA_LED_ALL_ON;
|
||||
else
|
||||
ha->beacon_color_state = QLA_LED_GRN_ON;
|
||||
|
||||
ha->isp_ops.beacon_blink(ha); /* This turns green LED off */
|
||||
|
||||
ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
|
||||
ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7;
|
||||
|
||||
rval = qla2x00_set_fw_options(ha, ha->fw_options);
|
||||
if (rval != QLA_SUCCESS)
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Unable to update fw options (beacon off).\n");
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
qla24xx_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags)
|
||||
{
|
||||
/* Flip all colors. */
|
||||
if (ha->beacon_color_state == QLA_LED_ALL_ON) {
|
||||
/* Turn off. */
|
||||
ha->beacon_color_state = 0;
|
||||
*pflags = 0;
|
||||
} else {
|
||||
/* Turn on. */
|
||||
ha->beacon_color_state = QLA_LED_ALL_ON;
|
||||
*pflags = GPDX_LED_YELLOW_ON | GPDX_LED_AMBER_ON;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
qla24xx_beacon_blink(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint16_t led_color = 0;
|
||||
uint32_t gpio_data;
|
||||
unsigned long flags;
|
||||
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
||||
|
||||
/* Save the Original GPIOD. */
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
gpio_data = RD_REG_DWORD(®->gpiod);
|
||||
|
||||
/* Enable the gpio_data reg for update. */
|
||||
gpio_data |= GPDX_LED_UPDATE_MASK;
|
||||
|
||||
WRT_REG_DWORD(®->gpiod, gpio_data);
|
||||
gpio_data = RD_REG_DWORD(®->gpiod);
|
||||
|
||||
/* Set the color bits. */
|
||||
qla24xx_flip_colors(ha, &led_color);
|
||||
|
||||
/* Clear out any previously set LED color. */
|
||||
gpio_data &= ~GPDX_LED_COLOR_MASK;
|
||||
|
||||
/* Set the new input LED color to GPIOD. */
|
||||
gpio_data |= led_color;
|
||||
|
||||
/* Set the modified gpio_data values. */
|
||||
WRT_REG_DWORD(®->gpiod, gpio_data);
|
||||
gpio_data = RD_REG_DWORD(®->gpiod);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
}
|
||||
|
||||
int
|
||||
qla24xx_beacon_on(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t gpio_data;
|
||||
unsigned long flags;
|
||||
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
||||
|
||||
if (ha->beacon_blink_led == 0) {
|
||||
/* Enable firmware for update */
|
||||
ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL;
|
||||
|
||||
if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
if (qla2x00_get_fw_options(ha, ha->fw_options) !=
|
||||
QLA_SUCCESS) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Unable to update fw options (beacon on).\n");
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
gpio_data = RD_REG_DWORD(®->gpiod);
|
||||
|
||||
/* Enable the gpio_data reg for update. */
|
||||
gpio_data |= GPDX_LED_UPDATE_MASK;
|
||||
WRT_REG_DWORD(®->gpiod, gpio_data);
|
||||
RD_REG_DWORD(®->gpiod);
|
||||
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
}
|
||||
|
||||
/* So all colors blink together. */
|
||||
ha->beacon_color_state = 0;
|
||||
|
||||
/* Let the per HBA timer kick off the blinking process. */
|
||||
ha->beacon_blink_led = 1;
|
||||
|
||||
return QLA_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
qla24xx_beacon_off(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t gpio_data;
|
||||
unsigned long flags;
|
||||
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
||||
|
||||
ha->beacon_blink_led = 0;
|
||||
ha->beacon_color_state = QLA_LED_ALL_ON;
|
||||
|
||||
ha->isp_ops.beacon_blink(ha); /* Will flip to all off. */
|
||||
|
||||
/* Give control back to firmware. */
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
gpio_data = RD_REG_DWORD(®->gpiod);
|
||||
|
||||
/* Disable the gpio_data reg for update. */
|
||||
gpio_data &= ~GPDX_LED_UPDATE_MASK;
|
||||
WRT_REG_DWORD(®->gpiod, gpio_data);
|
||||
RD_REG_DWORD(®->gpiod);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
ha->fw_options[1] &= ~ADD_FO1_DISABLE_GPIO_LED_CTRL;
|
||||
|
||||
if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Unable to update fw options (beacon off).\n");
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
if (qla2x00_get_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Unable to get fw options (beacon off).\n");
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
return QLA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Flash support routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* qla2x00_flash_enable() - Setup flash for reading and writing.
|
||||
* @ha: HA context
|
||||
*/
|
||||
static void
|
||||
qla2x00_flash_enable(scsi_qla_host_t *ha)
|
||||
{
|
||||
uint16_t data;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
data = RD_REG_WORD(®->ctrl_status);
|
||||
data |= CSR_FLASH_ENABLE;
|
||||
WRT_REG_WORD(®->ctrl_status, data);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
}
|
||||
|
||||
/**
|
||||
* qla2x00_flash_disable() - Disable flash and allow RISC to run.
|
||||
* @ha: HA context
|
||||
*/
|
||||
static void
|
||||
qla2x00_flash_disable(scsi_qla_host_t *ha)
|
||||
{
|
||||
uint16_t data;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
data = RD_REG_WORD(®->ctrl_status);
|
||||
data &= ~(CSR_FLASH_ENABLE);
|
||||
WRT_REG_WORD(®->ctrl_status, data);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
}
|
||||
|
||||
/**
|
||||
* qla2x00_read_flash_byte() - Reads a byte from flash
|
||||
* @ha: HA context
|
||||
* @addr: Address in flash to read
|
||||
*
|
||||
* A word is read from the chip, but, only the lower byte is valid.
|
||||
*
|
||||
* Returns the byte read from flash @addr.
|
||||
*/
|
||||
static uint8_t
|
||||
qla2x00_read_flash_byte(scsi_qla_host_t *ha, uint32_t addr)
|
||||
{
|
||||
uint16_t data;
|
||||
uint16_t bank_select;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
bank_select = RD_REG_WORD(®->ctrl_status);
|
||||
|
||||
if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
|
||||
/* Specify 64K address range: */
|
||||
/* clear out Module Select and Flash Address bits [19:16]. */
|
||||
bank_select &= ~0xf8;
|
||||
bank_select |= addr >> 12 & 0xf0;
|
||||
bank_select |= CSR_FLASH_64K_BANK;
|
||||
WRT_REG_WORD(®->ctrl_status, bank_select);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
|
||||
WRT_REG_WORD(®->flash_address, (uint16_t)addr);
|
||||
data = RD_REG_WORD(®->flash_data);
|
||||
|
||||
return (uint8_t)data;
|
||||
}
|
||||
|
||||
/* Setup bit 16 of flash address. */
|
||||
if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
|
||||
bank_select |= CSR_FLASH_64K_BANK;
|
||||
WRT_REG_WORD(®->ctrl_status, bank_select);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
} else if (((addr & BIT_16) == 0) &&
|
||||
(bank_select & CSR_FLASH_64K_BANK)) {
|
||||
bank_select &= ~(CSR_FLASH_64K_BANK);
|
||||
WRT_REG_WORD(®->ctrl_status, bank_select);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
}
|
||||
|
||||
/* Always perform IO mapped accesses to the FLASH registers. */
|
||||
if (ha->pio_address) {
|
||||
uint16_t data2;
|
||||
|
||||
reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
|
||||
WRT_REG_WORD_PIO(®->flash_address, (uint16_t)addr);
|
||||
do {
|
||||
data = RD_REG_WORD_PIO(®->flash_data);
|
||||
barrier();
|
||||
cpu_relax();
|
||||
data2 = RD_REG_WORD_PIO(®->flash_data);
|
||||
} while (data != data2);
|
||||
} else {
|
||||
WRT_REG_WORD(®->flash_address, (uint16_t)addr);
|
||||
data = qla2x00_debounce_register(®->flash_data);
|
||||
}
|
||||
|
||||
return (uint8_t)data;
|
||||
}
|
||||
|
||||
/**
|
||||
* qla2x00_write_flash_byte() - Write a byte to flash
|
||||
* @ha: HA context
|
||||
* @addr: Address in flash to write
|
||||
* @data: Data to write
|
||||
*/
|
||||
static void
|
||||
qla2x00_write_flash_byte(scsi_qla_host_t *ha, uint32_t addr, uint8_t data)
|
||||
{
|
||||
uint16_t bank_select;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
bank_select = RD_REG_WORD(®->ctrl_status);
|
||||
if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
|
||||
/* Specify 64K address range: */
|
||||
/* clear out Module Select and Flash Address bits [19:16]. */
|
||||
bank_select &= ~0xf8;
|
||||
bank_select |= addr >> 12 & 0xf0;
|
||||
bank_select |= CSR_FLASH_64K_BANK;
|
||||
WRT_REG_WORD(®->ctrl_status, bank_select);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
|
||||
WRT_REG_WORD(®->flash_address, (uint16_t)addr);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
WRT_REG_WORD(®->flash_data, (uint16_t)data);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Setup bit 16 of flash address. */
|
||||
if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
|
||||
bank_select |= CSR_FLASH_64K_BANK;
|
||||
WRT_REG_WORD(®->ctrl_status, bank_select);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
} else if (((addr & BIT_16) == 0) &&
|
||||
(bank_select & CSR_FLASH_64K_BANK)) {
|
||||
bank_select &= ~(CSR_FLASH_64K_BANK);
|
||||
WRT_REG_WORD(®->ctrl_status, bank_select);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
}
|
||||
|
||||
/* Always perform IO mapped accesses to the FLASH registers. */
|
||||
if (ha->pio_address) {
|
||||
reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
|
||||
WRT_REG_WORD_PIO(®->flash_address, (uint16_t)addr);
|
||||
WRT_REG_WORD_PIO(®->flash_data, (uint16_t)data);
|
||||
} else {
|
||||
WRT_REG_WORD(®->flash_address, (uint16_t)addr);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
WRT_REG_WORD(®->flash_data, (uint16_t)data);
|
||||
RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* qla2x00_poll_flash() - Polls flash for completion.
|
||||
* @ha: HA context
|
||||
* @addr: Address in flash to poll
|
||||
* @poll_data: Data to be polled
|
||||
* @man_id: Flash manufacturer ID
|
||||
* @flash_id: Flash ID
|
||||
*
|
||||
* This function polls the device until bit 7 of what is read matches data
|
||||
* bit 7 or until data bit 5 becomes a 1. If that hapens, the flash ROM timed
|
||||
* out (a fatal error). The flash book recommeds reading bit 7 again after
|
||||
* reading bit 5 as a 1.
|
||||
*
|
||||
* Returns 0 on success, else non-zero.
|
||||
*/
|
||||
static int
|
||||
qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data,
|
||||
uint8_t man_id, uint8_t flash_id)
|
||||
{
|
||||
int status;
|
||||
uint8_t flash_data;
|
||||
uint32_t cnt;
|
||||
|
||||
status = 1;
|
||||
|
||||
/* Wait for 30 seconds for command to finish. */
|
||||
poll_data &= BIT_7;
|
||||
for (cnt = 3000000; cnt; cnt--) {
|
||||
flash_data = qla2x00_read_flash_byte(ha, addr);
|
||||
if ((flash_data & BIT_7) == poll_data) {
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (man_id != 0x40 && man_id != 0xda) {
|
||||
if ((flash_data & BIT_5) && cnt > 2)
|
||||
cnt = 2;
|
||||
}
|
||||
udelay(10);
|
||||
barrier();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#define IS_OEM_001(ha) \
|
||||
((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322 && \
|
||||
(ha)->pdev->subsystem_vendor == 0x1028 && \
|
||||
(ha)->pdev->subsystem_device == 0x0170)
|
||||
|
||||
/**
|
||||
* qla2x00_program_flash_address() - Programs a flash address
|
||||
* @ha: HA context
|
||||
* @addr: Address in flash to program
|
||||
* @data: Data to be written in flash
|
||||
* @man_id: Flash manufacturer ID
|
||||
* @flash_id: Flash ID
|
||||
*
|
||||
* Returns 0 on success, else non-zero.
|
||||
*/
|
||||
static int
|
||||
qla2x00_program_flash_address(scsi_qla_host_t *ha, uint32_t addr, uint8_t data,
|
||||
uint8_t man_id, uint8_t flash_id)
|
||||
{
|
||||
/* Write Program Command Sequence. */
|
||||
if (IS_OEM_001(ha)) {
|
||||
qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x555, 0x55);
|
||||
qla2x00_write_flash_byte(ha, 0xaaa, 0xa0);
|
||||
qla2x00_write_flash_byte(ha, addr, data);
|
||||
} else {
|
||||
if (man_id == 0xda && flash_id == 0xc1) {
|
||||
qla2x00_write_flash_byte(ha, addr, data);
|
||||
if (addr & 0x7e)
|
||||
return 0;
|
||||
} else {
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0xa0);
|
||||
qla2x00_write_flash_byte(ha, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
udelay(150);
|
||||
|
||||
/* Wait for write to complete. */
|
||||
return qla2x00_poll_flash(ha, addr, data, man_id, flash_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* qla2x00_erase_flash() - Erase the flash.
|
||||
* @ha: HA context
|
||||
* @man_id: Flash manufacturer ID
|
||||
* @flash_id: Flash ID
|
||||
*
|
||||
* Returns 0 on success, else non-zero.
|
||||
*/
|
||||
static int
|
||||
qla2x00_erase_flash(scsi_qla_host_t *ha, uint8_t man_id, uint8_t flash_id)
|
||||
{
|
||||
/* Individual Sector Erase Command Sequence */
|
||||
if (IS_OEM_001(ha)) {
|
||||
qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x555, 0x55);
|
||||
qla2x00_write_flash_byte(ha, 0xaaa, 0x80);
|
||||
qla2x00_write_flash_byte(ha, 0xaaa, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x555, 0x55);
|
||||
qla2x00_write_flash_byte(ha, 0xaaa, 0x10);
|
||||
} else {
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0x80);
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0x10);
|
||||
}
|
||||
|
||||
udelay(150);
|
||||
|
||||
/* Wait for erase to complete. */
|
||||
return qla2x00_poll_flash(ha, 0x00, 0x80, man_id, flash_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* qla2x00_erase_flash_sector() - Erase a flash sector.
|
||||
* @ha: HA context
|
||||
* @addr: Flash sector to erase
|
||||
* @sec_mask: Sector address mask
|
||||
* @man_id: Flash manufacturer ID
|
||||
* @flash_id: Flash ID
|
||||
*
|
||||
* Returns 0 on success, else non-zero.
|
||||
*/
|
||||
static int
|
||||
qla2x00_erase_flash_sector(scsi_qla_host_t *ha, uint32_t addr,
|
||||
uint32_t sec_mask, uint8_t man_id, uint8_t flash_id)
|
||||
{
|
||||
/* Individual Sector Erase Command Sequence */
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0x80);
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
|
||||
if (man_id == 0x1f && flash_id == 0x13)
|
||||
qla2x00_write_flash_byte(ha, addr & sec_mask, 0x10);
|
||||
else
|
||||
qla2x00_write_flash_byte(ha, addr & sec_mask, 0x30);
|
||||
|
||||
udelay(150);
|
||||
|
||||
/* Wait for erase to complete. */
|
||||
return qla2x00_poll_flash(ha, addr, 0x80, man_id, flash_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip.
|
||||
* @man_id: Flash manufacturer ID
|
||||
* @flash_id: Flash ID
|
||||
*/
|
||||
static void
|
||||
qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
|
||||
uint8_t *flash_id)
|
||||
{
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0x90);
|
||||
*man_id = qla2x00_read_flash_byte(ha, 0x0000);
|
||||
*flash_id = qla2x00_read_flash_byte(ha, 0x0001);
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x2aaa, 0x55);
|
||||
qla2x00_write_flash_byte(ha, 0x5555, 0xf0);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
qla2x00_suspend_hba(struct scsi_qla_host *ha)
|
||||
{
|
||||
int cnt;
|
||||
unsigned long flags;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
/* Suspend HBA. */
|
||||
scsi_block_requests(ha->host);
|
||||
ha->isp_ops.disable_intrs(ha);
|
||||
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
|
||||
|
||||
/* Pause RISC. */
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
|
||||
RD_REG_WORD(®->hccr);
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
|
||||
for (cnt = 0; cnt < 30000; cnt++) {
|
||||
if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) != 0)
|
||||
break;
|
||||
udelay(100);
|
||||
}
|
||||
} else {
|
||||
udelay(10);
|
||||
}
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
qla2x00_resume_hba(struct scsi_qla_host *ha)
|
||||
{
|
||||
/* Resume HBA. */
|
||||
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
|
||||
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
|
||||
up(ha->dpc_wait);
|
||||
qla2x00_wait_for_hba_online(ha);
|
||||
scsi_unblock_requests(ha->host);
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
|
||||
uint32_t offset, uint32_t length)
|
||||
{
|
||||
unsigned long flags;
|
||||
uint32_t addr, midpoint;
|
||||
uint8_t *data;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
/* Suspend HBA. */
|
||||
qla2x00_suspend_hba(ha);
|
||||
|
||||
/* Go with read. */
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
midpoint = ha->optrom_size / 2;
|
||||
|
||||
qla2x00_flash_enable(ha);
|
||||
WRT_REG_WORD(®->nvram, 0);
|
||||
RD_REG_WORD(®->nvram); /* PCI Posting. */
|
||||
for (addr = offset, data = buf; addr < length; addr++, data++) {
|
||||
if (addr == midpoint) {
|
||||
WRT_REG_WORD(®->nvram, NVR_SELECT);
|
||||
RD_REG_WORD(®->nvram); /* PCI Posting. */
|
||||
}
|
||||
|
||||
*data = qla2x00_read_flash_byte(ha, addr);
|
||||
}
|
||||
qla2x00_flash_disable(ha);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
/* Resume HBA. */
|
||||
qla2x00_resume_hba(ha);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
|
||||
uint32_t offset, uint32_t length)
|
||||
{
|
||||
|
||||
int rval;
|
||||
unsigned long flags;
|
||||
uint8_t man_id, flash_id, sec_number, data;
|
||||
uint16_t wd;
|
||||
uint32_t addr, liter, sec_mask, rest_addr;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
/* Suspend HBA. */
|
||||
qla2x00_suspend_hba(ha);
|
||||
|
||||
rval = QLA_SUCCESS;
|
||||
sec_number = 0;
|
||||
|
||||
/* Reset ISP chip. */
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET);
|
||||
pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
|
||||
|
||||
/* Go with write. */
|
||||
qla2x00_flash_enable(ha);
|
||||
do { /* Loop once to provide quick error exit */
|
||||
/* Structure of flash memory based on manufacturer */
|
||||
if (IS_OEM_001(ha)) {
|
||||
/* OEM variant with special flash part. */
|
||||
man_id = flash_id = 0;
|
||||
rest_addr = 0xffff;
|
||||
sec_mask = 0x10000;
|
||||
goto update_flash;
|
||||
}
|
||||
qla2x00_get_flash_manufacturer(ha, &man_id, &flash_id);
|
||||
switch (man_id) {
|
||||
case 0x20: /* ST flash. */
|
||||
if (flash_id == 0xd2 || flash_id == 0xe3) {
|
||||
/*
|
||||
* ST m29w008at part - 64kb sector size with
|
||||
* 32kb,8kb,8kb,16kb sectors at memory address
|
||||
* 0xf0000.
|
||||
*/
|
||||
rest_addr = 0xffff;
|
||||
sec_mask = 0x10000;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* ST m29w010b part - 16kb sector size
|
||||
* Default to 16kb sectors
|
||||
*/
|
||||
rest_addr = 0x3fff;
|
||||
sec_mask = 0x1c000;
|
||||
break;
|
||||
case 0x40: /* Mostel flash. */
|
||||
/* Mostel v29c51001 part - 512 byte sector size. */
|
||||
rest_addr = 0x1ff;
|
||||
sec_mask = 0x1fe00;
|
||||
break;
|
||||
case 0xbf: /* SST flash. */
|
||||
/* SST39sf10 part - 4kb sector size. */
|
||||
rest_addr = 0xfff;
|
||||
sec_mask = 0x1f000;
|
||||
break;
|
||||
case 0xda: /* Winbond flash. */
|
||||
/* Winbond W29EE011 part - 256 byte sector size. */
|
||||
rest_addr = 0x7f;
|
||||
sec_mask = 0x1ff80;
|
||||
break;
|
||||
case 0xc2: /* Macronix flash. */
|
||||
/* 64k sector size. */
|
||||
if (flash_id == 0x38 || flash_id == 0x4f) {
|
||||
rest_addr = 0xffff;
|
||||
sec_mask = 0x10000;
|
||||
break;
|
||||
}
|
||||
/* Fall through... */
|
||||
|
||||
case 0x1f: /* Atmel flash. */
|
||||
/* 512k sector size. */
|
||||
if (flash_id == 0x13) {
|
||||
rest_addr = 0x7fffffff;
|
||||
sec_mask = 0x80000000;
|
||||
break;
|
||||
}
|
||||
/* Fall through... */
|
||||
|
||||
case 0x01: /* AMD flash. */
|
||||
if (flash_id == 0x38 || flash_id == 0x40 ||
|
||||
flash_id == 0x4f) {
|
||||
/* Am29LV081 part - 64kb sector size. */
|
||||
/* Am29LV002BT part - 64kb sector size. */
|
||||
rest_addr = 0xffff;
|
||||
sec_mask = 0x10000;
|
||||
break;
|
||||
} else if (flash_id == 0x3e) {
|
||||
/*
|
||||
* Am29LV008b part - 64kb sector size with
|
||||
* 32kb,8kb,8kb,16kb sector at memory address
|
||||
* h0xf0000.
|
||||
*/
|
||||
rest_addr = 0xffff;
|
||||
sec_mask = 0x10000;
|
||||
break;
|
||||
} else if (flash_id == 0x20 || flash_id == 0x6e) {
|
||||
/*
|
||||
* Am29LV010 part or AM29f010 - 16kb sector
|
||||
* size.
|
||||
*/
|
||||
rest_addr = 0x3fff;
|
||||
sec_mask = 0x1c000;
|
||||
break;
|
||||
} else if (flash_id == 0x6d) {
|
||||
/* Am29LV001 part - 8kb sector size. */
|
||||
rest_addr = 0x1fff;
|
||||
sec_mask = 0x1e000;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Default to 16 kb sector size. */
|
||||
rest_addr = 0x3fff;
|
||||
sec_mask = 0x1c000;
|
||||
break;
|
||||
}
|
||||
|
||||
update_flash:
|
||||
if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
|
||||
if (qla2x00_erase_flash(ha, man_id, flash_id)) {
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (addr = offset, liter = 0; liter < length; liter++,
|
||||
addr++) {
|
||||
data = buf[liter];
|
||||
/* Are we at the beginning of a sector? */
|
||||
if ((addr & rest_addr) == 0) {
|
||||
if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
|
||||
if (addr >= 0x10000UL) {
|
||||
if (((addr >> 12) & 0xf0) &&
|
||||
((man_id == 0x01 &&
|
||||
flash_id == 0x3e) ||
|
||||
(man_id == 0x20 &&
|
||||
flash_id == 0xd2))) {
|
||||
sec_number++;
|
||||
if (sec_number == 1) {
|
||||
rest_addr =
|
||||
0x7fff;
|
||||
sec_mask =
|
||||
0x18000;
|
||||
} else if (
|
||||
sec_number == 2 ||
|
||||
sec_number == 3) {
|
||||
rest_addr =
|
||||
0x1fff;
|
||||
sec_mask =
|
||||
0x1e000;
|
||||
} else if (
|
||||
sec_number == 4) {
|
||||
rest_addr =
|
||||
0x3fff;
|
||||
sec_mask =
|
||||
0x1c000;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (addr == ha->optrom_size / 2) {
|
||||
WRT_REG_WORD(®->nvram, NVR_SELECT);
|
||||
RD_REG_WORD(®->nvram);
|
||||
}
|
||||
|
||||
if (flash_id == 0xda && man_id == 0xc1) {
|
||||
qla2x00_write_flash_byte(ha, 0x5555,
|
||||
0xaa);
|
||||
qla2x00_write_flash_byte(ha, 0x2aaa,
|
||||
0x55);
|
||||
qla2x00_write_flash_byte(ha, 0x5555,
|
||||
0xa0);
|
||||
} else if (!IS_QLA2322(ha) && !IS_QLA6322(ha)) {
|
||||
/* Then erase it */
|
||||
if (qla2x00_erase_flash_sector(ha,
|
||||
addr, sec_mask, man_id,
|
||||
flash_id)) {
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
break;
|
||||
}
|
||||
if (man_id == 0x01 && flash_id == 0x6d)
|
||||
sec_number++;
|
||||
}
|
||||
}
|
||||
|
||||
if (man_id == 0x01 && flash_id == 0x6d) {
|
||||
if (sec_number == 1 &&
|
||||
addr == (rest_addr - 1)) {
|
||||
rest_addr = 0x0fff;
|
||||
sec_mask = 0x1f000;
|
||||
} else if (sec_number == 3 && (addr & 0x7ffe)) {
|
||||
rest_addr = 0x3fff;
|
||||
sec_mask = 0x1c000;
|
||||
}
|
||||
}
|
||||
|
||||
if (qla2x00_program_flash_address(ha, addr, data,
|
||||
man_id, flash_id)) {
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
qla2x00_flash_disable(ha);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
/* Resume HBA. */
|
||||
qla2x00_resume_hba(ha);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
|
||||
uint32_t offset, uint32_t length)
|
||||
{
|
||||
/* Suspend HBA. */
|
||||
scsi_block_requests(ha->host);
|
||||
ha->isp_ops.disable_intrs(ha);
|
||||
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
|
||||
|
||||
/* Go with read. */
|
||||
qla24xx_read_flash_data(ha, (uint32_t *)buf, offset >> 2, length >> 2);
|
||||
|
||||
/* Resume HBA. */
|
||||
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
|
||||
ha->isp_ops.enable_intrs(ha);
|
||||
scsi_unblock_requests(ha->host);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
|
||||
uint32_t offset, uint32_t length)
|
||||
{
|
||||
int rval;
|
||||
|
||||
/* Suspend HBA. */
|
||||
scsi_block_requests(ha->host);
|
||||
ha->isp_ops.disable_intrs(ha);
|
||||
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
|
||||
|
||||
/* Go with write. */
|
||||
rval = qla24xx_write_flash_data(ha, (uint32_t *)buf, offset >> 2,
|
||||
length >> 2);
|
||||
|
||||
/* Resume HBA -- RISC reset needed. */
|
||||
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
|
||||
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
|
||||
up(ha->dpc_wait);
|
||||
qla2x00_wait_for_hba_online(ha);
|
||||
scsi_unblock_requests(ha->host);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/hardirq.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_dbg.h>
|
||||
@ -2248,3 +2249,61 @@ scsi_target_unblock(struct device *dev)
|
||||
device_for_each_child(dev, NULL, target_unblock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(scsi_target_unblock);
|
||||
|
||||
|
||||
struct work_queue_work {
|
||||
struct work_struct work;
|
||||
void (*fn)(void *);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static void execute_in_process_context_work(void *data)
|
||||
{
|
||||
void (*fn)(void *data);
|
||||
struct work_queue_work *wqw = data;
|
||||
|
||||
fn = wqw->fn;
|
||||
data = wqw->data;
|
||||
|
||||
kfree(wqw);
|
||||
|
||||
fn(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_execute_in_process_context - reliably execute the routine with user context
|
||||
* @fn: the function to execute
|
||||
* @data: data to pass to the function
|
||||
*
|
||||
* Executes the function immediately if process context is available,
|
||||
* otherwise schedules the function for delayed execution.
|
||||
*
|
||||
* Returns: 0 - function was executed
|
||||
* 1 - function was scheduled for execution
|
||||
* <0 - error
|
||||
*/
|
||||
int scsi_execute_in_process_context(void (*fn)(void *data), void *data)
|
||||
{
|
||||
struct work_queue_work *wqw;
|
||||
|
||||
if (!in_interrupt()) {
|
||||
fn(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wqw = kmalloc(sizeof(struct work_queue_work), GFP_ATOMIC);
|
||||
|
||||
if (unlikely(!wqw)) {
|
||||
printk(KERN_ERR "Failed to allocate memory\n");
|
||||
WARN_ON(1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_WORK(&wqw->work, execute_in_process_context_work, wqw);
|
||||
wqw->fn = fn;
|
||||
wqw->data = data;
|
||||
schedule_work(&wqw->work);
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(scsi_execute_in_process_context);
|
||||
|
@ -387,19 +387,12 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
|
||||
return found_target;
|
||||
}
|
||||
|
||||
struct work_queue_wrapper {
|
||||
struct work_struct work;
|
||||
struct scsi_target *starget;
|
||||
};
|
||||
|
||||
static void scsi_target_reap_work(void *data) {
|
||||
struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
|
||||
struct scsi_target *starget = wqw->starget;
|
||||
static void scsi_target_reap_usercontext(void *data)
|
||||
{
|
||||
struct scsi_target *starget = data;
|
||||
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
|
||||
unsigned long flags;
|
||||
|
||||
kfree(wqw);
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
|
||||
if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
|
||||
@ -428,18 +421,7 @@ static void scsi_target_reap_work(void *data) {
|
||||
*/
|
||||
void scsi_target_reap(struct scsi_target *starget)
|
||||
{
|
||||
struct work_queue_wrapper *wqw =
|
||||
kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
|
||||
|
||||
if (!wqw) {
|
||||
starget_printk(KERN_ERR, starget,
|
||||
"Failed to allocate memory in scsi_reap_target()\n");
|
||||
return;
|
||||
}
|
||||
|
||||
INIT_WORK(&wqw->work, scsi_target_reap_work, wqw);
|
||||
wqw->starget = starget;
|
||||
schedule_work(&wqw->work);
|
||||
scsi_execute_in_process_context(scsi_target_reap_usercontext, starget);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -217,8 +217,9 @@ static void scsi_device_cls_release(struct class_device *class_dev)
|
||||
put_device(&sdev->sdev_gendev);
|
||||
}
|
||||
|
||||
static void scsi_device_dev_release(struct device *dev)
|
||||
static void scsi_device_dev_release_usercontext(void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
struct scsi_device *sdev;
|
||||
struct device *parent;
|
||||
struct scsi_target *starget;
|
||||
@ -237,6 +238,7 @@ static void scsi_device_dev_release(struct device *dev)
|
||||
|
||||
if (sdev->request_queue) {
|
||||
sdev->request_queue->queuedata = NULL;
|
||||
/* user context needed to free queue */
|
||||
scsi_free_queue(sdev->request_queue);
|
||||
/* temporary expedient, try to catch use of queue lock
|
||||
* after free of sdev */
|
||||
@ -252,6 +254,11 @@ static void scsi_device_dev_release(struct device *dev)
|
||||
put_device(parent);
|
||||
}
|
||||
|
||||
static void scsi_device_dev_release(struct device *dev)
|
||||
{
|
||||
scsi_execute_in_process_context(scsi_device_dev_release_usercontext, dev);
|
||||
}
|
||||
|
||||
static struct class sdev_class = {
|
||||
.name = "scsi_device",
|
||||
.release = scsi_device_cls_release,
|
||||
|
@ -38,10 +38,6 @@ struct iscsi_internal {
|
||||
struct scsi_transport_template t;
|
||||
struct iscsi_transport *iscsi_transport;
|
||||
struct list_head list;
|
||||
/*
|
||||
* List of sessions for this transport
|
||||
*/
|
||||
struct list_head sessions;
|
||||
/*
|
||||
* based on transport capabilities, at register time we set these
|
||||
* bits to tell the transport class it wants attributes displayed
|
||||
@ -164,9 +160,43 @@ static struct mempool_zone *z_reply;
|
||||
#define Z_MAX_ERROR 16
|
||||
#define Z_HIWAT_ERROR 12
|
||||
|
||||
static LIST_HEAD(sesslist);
|
||||
static DEFINE_SPINLOCK(sesslock);
|
||||
static LIST_HEAD(connlist);
|
||||
static DEFINE_SPINLOCK(connlock);
|
||||
|
||||
static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iscsi_cls_session *sess;
|
||||
|
||||
spin_lock_irqsave(&sesslock, flags);
|
||||
list_for_each_entry(sess, &sesslist, sess_list) {
|
||||
if (sess == iscsi_ptr(handle)) {
|
||||
spin_unlock_irqrestore(&sesslock, flags);
|
||||
return sess;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&sesslock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iscsi_cls_conn *conn;
|
||||
|
||||
spin_lock_irqsave(&connlock, flags);
|
||||
list_for_each_entry(conn, &connlist, conn_list) {
|
||||
if (conn == iscsi_ptr(handle)) {
|
||||
spin_unlock_irqrestore(&connlock, flags);
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&connlock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following functions can be used by LLDs that allocate
|
||||
* their own scsi_hosts or by software iscsi LLDs
|
||||
@ -365,6 +395,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
|
||||
{
|
||||
struct iscsi_cls_session *session;
|
||||
struct Scsi_Host *shost;
|
||||
unsigned long flags;
|
||||
|
||||
shost = scsi_host_alloc(transport->host_template,
|
||||
hostdata_privsize(transport));
|
||||
@ -389,6 +420,9 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
|
||||
goto remove_host;
|
||||
|
||||
*(unsigned long*)shost->hostdata = (unsigned long)session;
|
||||
spin_lock_irqsave(&sesslock, flags);
|
||||
list_add(&session->sess_list, &sesslist);
|
||||
spin_unlock_irqrestore(&sesslock, flags);
|
||||
return shost;
|
||||
|
||||
remove_host:
|
||||
@ -410,9 +444,13 @@ EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
|
||||
int iscsi_transport_destroy_session(struct Scsi_Host *shost)
|
||||
{
|
||||
struct iscsi_cls_session *session;
|
||||
unsigned long flags;
|
||||
|
||||
scsi_remove_host(shost);
|
||||
session = hostdata_session(shost->hostdata);
|
||||
spin_lock_irqsave(&sesslock, flags);
|
||||
list_del(&session->sess_list);
|
||||
spin_unlock_irqrestore(&sesslock, flags);
|
||||
iscsi_destroy_session(session);
|
||||
/* ref from host alloc */
|
||||
scsi_host_put(shost);
|
||||
@ -424,22 +462,6 @@ EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
|
||||
/*
|
||||
* iscsi interface functions
|
||||
*/
|
||||
static struct iscsi_cls_conn*
|
||||
iscsi_if_find_conn(uint64_t key)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iscsi_cls_conn *conn;
|
||||
|
||||
spin_lock_irqsave(&connlock, flags);
|
||||
list_for_each_entry(conn, &connlist, conn_list)
|
||||
if (conn->connh == key) {
|
||||
spin_unlock_irqrestore(&connlock, flags);
|
||||
return conn;
|
||||
}
|
||||
spin_unlock_irqrestore(&connlock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct iscsi_internal *
|
||||
iscsi_if_transport_lookup(struct iscsi_transport *tt)
|
||||
{
|
||||
@ -504,6 +526,12 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
|
||||
if (!zp)
|
||||
return NULL;
|
||||
|
||||
zp->size = size;
|
||||
zp->hiwat = hiwat;
|
||||
INIT_LIST_HEAD(&zp->freequeue);
|
||||
spin_lock_init(&zp->freelock);
|
||||
atomic_set(&zp->allocated, 0);
|
||||
|
||||
zp->pool = mempool_create(max, mempool_zone_alloc_skb,
|
||||
mempool_zone_free_skb, zp);
|
||||
if (!zp->pool) {
|
||||
@ -511,13 +539,6 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zp->size = size;
|
||||
zp->hiwat = hiwat;
|
||||
|
||||
INIT_LIST_HEAD(&zp->freequeue);
|
||||
spin_lock_init(&zp->freelock);
|
||||
atomic_set(&zp->allocated, 0);
|
||||
|
||||
return zp;
|
||||
}
|
||||
|
||||
@ -559,25 +580,21 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
|
||||
int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
|
||||
char *data, uint32_t data_size)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct sk_buff *skb;
|
||||
struct iscsi_uevent *ev;
|
||||
struct iscsi_cls_conn *conn;
|
||||
char *pdu;
|
||||
int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
|
||||
data_size);
|
||||
|
||||
conn = iscsi_if_find_conn(connh);
|
||||
BUG_ON(!conn);
|
||||
|
||||
mempool_zone_complete(conn->z_pdu);
|
||||
|
||||
skb = mempool_zone_get_skb(conn->z_pdu);
|
||||
if (!skb) {
|
||||
iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
|
||||
iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
|
||||
dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
|
||||
"control PDU: OOM\n");
|
||||
return -ENOMEM;
|
||||
@ -590,7 +607,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
|
||||
ev->type = ISCSI_KEVENT_RECV_PDU;
|
||||
if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
|
||||
ev->iferror = -ENOMEM;
|
||||
ev->r.recv_req.conn_handle = connh;
|
||||
ev->r.recv_req.conn_handle = iscsi_handle(conn);
|
||||
pdu = (char*)ev + sizeof(*ev);
|
||||
memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
|
||||
memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
|
||||
@ -599,17 +616,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
|
||||
|
||||
void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
|
||||
void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct sk_buff *skb;
|
||||
struct iscsi_uevent *ev;
|
||||
struct iscsi_cls_conn *conn;
|
||||
int len = NLMSG_SPACE(sizeof(*ev));
|
||||
|
||||
conn = iscsi_if_find_conn(connh);
|
||||
BUG_ON(!conn);
|
||||
|
||||
mempool_zone_complete(conn->z_error);
|
||||
|
||||
skb = mempool_zone_get_skb(conn->z_error);
|
||||
@ -626,7 +639,7 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
|
||||
if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
|
||||
ev->iferror = -ENOMEM;
|
||||
ev->r.connerror.error = error;
|
||||
ev->r.connerror.conn_handle = connh;
|
||||
ev->r.connerror.conn_handle = iscsi_handle(conn);
|
||||
|
||||
iscsi_unicast_skb(conn->z_error, skb);
|
||||
|
||||
@ -662,8 +675,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
|
||||
struct nlmsghdr *nlh)
|
||||
iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
|
||||
{
|
||||
struct iscsi_uevent *ev = NLMSG_DATA(nlh);
|
||||
struct iscsi_stats *stats;
|
||||
@ -677,7 +689,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
|
||||
ISCSI_STATS_CUSTOM_MAX);
|
||||
int err = 0;
|
||||
|
||||
conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
|
||||
conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle);
|
||||
if (!conn)
|
||||
return -EEXIST;
|
||||
|
||||
@ -707,14 +719,14 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
|
||||
((char*)evstat + sizeof(*evstat));
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
|
||||
transport->get_stats(ev->u.get_stats.conn_handle, stats);
|
||||
transport->get_stats(conn, stats);
|
||||
actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
|
||||
sizeof(struct iscsi_stats) +
|
||||
sizeof(struct iscsi_stats_custom) *
|
||||
stats->custom_length);
|
||||
actual_size -= sizeof(*nlhstat);
|
||||
actual_size = NLMSG_LENGTH(actual_size);
|
||||
skb_trim(skb, NLMSG_ALIGN(actual_size));
|
||||
skb_trim(skbstat, NLMSG_ALIGN(actual_size));
|
||||
nlhstat->nlmsg_len = actual_size;
|
||||
|
||||
err = iscsi_unicast_skb(conn->z_pdu, skbstat);
|
||||
@ -727,58 +739,34 @@ static int
|
||||
iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
|
||||
{
|
||||
struct iscsi_transport *transport = priv->iscsi_transport;
|
||||
struct Scsi_Host *shost;
|
||||
struct iscsi_cls_session *session;
|
||||
uint32_t sid;
|
||||
|
||||
if (!transport->create_session)
|
||||
return -EINVAL;
|
||||
|
||||
shost = transport->create_session(&priv->t,
|
||||
ev->u.c_session.initial_cmdsn);
|
||||
if (!shost)
|
||||
session = transport->create_session(&priv->t,
|
||||
ev->u.c_session.initial_cmdsn,
|
||||
&sid);
|
||||
if (!session)
|
||||
return -ENOMEM;
|
||||
|
||||
ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
|
||||
ev->r.c_session_ret.sid = shost->host_no;
|
||||
ev->r.c_session_ret.session_handle = iscsi_handle(session);
|
||||
ev->r.c_session_ret.sid = sid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
|
||||
iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
|
||||
{
|
||||
struct iscsi_transport *transport = priv->iscsi_transport;
|
||||
|
||||
struct Scsi_Host *shost;
|
||||
|
||||
if (!transport->destroy_session)
|
||||
return -EINVAL;
|
||||
|
||||
shost = scsi_host_lookup(ev->u.d_session.sid);
|
||||
if (shost == ERR_PTR(-ENXIO))
|
||||
return -EEXIST;
|
||||
|
||||
if (transport->destroy_session)
|
||||
transport->destroy_session(shost);
|
||||
/* ref from host lookup */
|
||||
scsi_host_put(shost);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
|
||||
struct Scsi_Host *shost;
|
||||
struct iscsi_cls_conn *conn;
|
||||
struct iscsi_cls_session *session;
|
||||
unsigned long flags;
|
||||
|
||||
if (!transport->create_conn)
|
||||
session = iscsi_session_lookup(ev->u.c_conn.session_handle);
|
||||
if (!session)
|
||||
return -EINVAL;
|
||||
|
||||
shost = scsi_host_lookup(ev->u.c_conn.sid);
|
||||
if (shost == ERR_PTR(-ENXIO))
|
||||
return -EEXIST;
|
||||
|
||||
conn = transport->create_conn(shost, ev->u.c_conn.cid);
|
||||
conn = transport->create_conn(session, ev->u.c_conn.cid);
|
||||
if (!conn)
|
||||
goto release_ref;
|
||||
return -ENOMEM;
|
||||
|
||||
conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
|
||||
NLMSG_SPACE(sizeof(struct iscsi_uevent) +
|
||||
@ -800,14 +788,13 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
|
||||
goto free_pdu_pool;
|
||||
}
|
||||
|
||||
ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
|
||||
ev->r.handle = iscsi_handle(conn);
|
||||
|
||||
spin_lock_irqsave(&connlock, flags);
|
||||
list_add(&conn->conn_list, &connlist);
|
||||
conn->active = 1;
|
||||
spin_unlock_irqrestore(&connlock, flags);
|
||||
|
||||
scsi_host_put(shost);
|
||||
return 0;
|
||||
|
||||
free_pdu_pool:
|
||||
@ -815,8 +802,6 @@ free_pdu_pool:
|
||||
destroy_conn:
|
||||
if (transport->destroy_conn)
|
||||
transport->destroy_conn(conn->dd_data);
|
||||
release_ref:
|
||||
scsi_host_put(shost);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -827,13 +812,9 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
|
||||
struct iscsi_cls_conn *conn;
|
||||
struct mempool_zone *z_error, *z_pdu;
|
||||
|
||||
conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
|
||||
conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle);
|
||||
if (!conn)
|
||||
return -EEXIST;
|
||||
|
||||
if (!transport->destroy_conn)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&connlock, flags);
|
||||
conn->active = 0;
|
||||
list_del(&conn->conn_list);
|
||||
@ -858,23 +839,27 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
struct iscsi_uevent *ev = NLMSG_DATA(nlh);
|
||||
struct iscsi_transport *transport = NULL;
|
||||
struct iscsi_internal *priv;
|
||||
|
||||
if (NETLINK_CREDS(skb)->uid)
|
||||
return -EPERM;
|
||||
struct iscsi_cls_session *session;
|
||||
struct iscsi_cls_conn *conn;
|
||||
|
||||
priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
transport = priv->iscsi_transport;
|
||||
|
||||
daemon_pid = NETLINK_CREDS(skb)->pid;
|
||||
if (!try_module_get(transport->owner))
|
||||
return -EINVAL;
|
||||
|
||||
switch (nlh->nlmsg_type) {
|
||||
case ISCSI_UEVENT_CREATE_SESSION:
|
||||
err = iscsi_if_create_session(priv, ev);
|
||||
break;
|
||||
case ISCSI_UEVENT_DESTROY_SESSION:
|
||||
err = iscsi_if_destroy_session(priv, ev);
|
||||
session = iscsi_session_lookup(ev->u.d_session.session_handle);
|
||||
if (session)
|
||||
transport->destroy_session(session);
|
||||
else
|
||||
err = -EINVAL;
|
||||
break;
|
||||
case ISCSI_UEVENT_CREATE_CONN:
|
||||
err = iscsi_if_create_conn(transport, ev);
|
||||
@ -883,56 +868,64 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
err = iscsi_if_destroy_conn(transport, ev);
|
||||
break;
|
||||
case ISCSI_UEVENT_BIND_CONN:
|
||||
if (!iscsi_if_find_conn(ev->u.b_conn.conn_handle))
|
||||
return -EEXIST;
|
||||
ev->r.retcode = transport->bind_conn(
|
||||
ev->u.b_conn.session_handle,
|
||||
ev->u.b_conn.conn_handle,
|
||||
ev->u.b_conn.transport_fd,
|
||||
ev->u.b_conn.is_leading);
|
||||
session = iscsi_session_lookup(ev->u.b_conn.session_handle);
|
||||
conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle);
|
||||
|
||||
if (session && conn)
|
||||
ev->r.retcode = transport->bind_conn(session, conn,
|
||||
ev->u.b_conn.transport_fd,
|
||||
ev->u.b_conn.is_leading);
|
||||
else
|
||||
err = -EINVAL;
|
||||
break;
|
||||
case ISCSI_UEVENT_SET_PARAM:
|
||||
if (!iscsi_if_find_conn(ev->u.set_param.conn_handle))
|
||||
return -EEXIST;
|
||||
ev->r.retcode = transport->set_param(
|
||||
ev->u.set_param.conn_handle,
|
||||
ev->u.set_param.param, ev->u.set_param.value);
|
||||
conn = iscsi_conn_lookup(ev->u.set_param.conn_handle);
|
||||
if (conn)
|
||||
ev->r.retcode = transport->set_param(conn,
|
||||
ev->u.set_param.param, ev->u.set_param.value);
|
||||
else
|
||||
err = -EINVAL;
|
||||
break;
|
||||
case ISCSI_UEVENT_START_CONN:
|
||||
if (!iscsi_if_find_conn(ev->u.start_conn.conn_handle))
|
||||
return -EEXIST;
|
||||
ev->r.retcode = transport->start_conn(
|
||||
ev->u.start_conn.conn_handle);
|
||||
conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle);
|
||||
if (conn)
|
||||
ev->r.retcode = transport->start_conn(conn);
|
||||
else
|
||||
err = -EINVAL;
|
||||
|
||||
break;
|
||||
case ISCSI_UEVENT_STOP_CONN:
|
||||
if (!iscsi_if_find_conn(ev->u.stop_conn.conn_handle))
|
||||
return -EEXIST;
|
||||
transport->stop_conn(ev->u.stop_conn.conn_handle,
|
||||
ev->u.stop_conn.flag);
|
||||
conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle);
|
||||
if (conn)
|
||||
transport->stop_conn(conn, ev->u.stop_conn.flag);
|
||||
else
|
||||
err = -EINVAL;
|
||||
break;
|
||||
case ISCSI_UEVENT_SEND_PDU:
|
||||
if (!iscsi_if_find_conn(ev->u.send_pdu.conn_handle))
|
||||
return -EEXIST;
|
||||
ev->r.retcode = transport->send_pdu(
|
||||
ev->u.send_pdu.conn_handle,
|
||||
(struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
|
||||
(char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
|
||||
ev->u.send_pdu.data_size);
|
||||
conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle);
|
||||
if (conn)
|
||||
ev->r.retcode = transport->send_pdu(conn,
|
||||
(struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
|
||||
(char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
|
||||
ev->u.send_pdu.data_size);
|
||||
else
|
||||
err = -EINVAL;
|
||||
break;
|
||||
case ISCSI_UEVENT_GET_STATS:
|
||||
err = iscsi_if_get_stats(transport, skb, nlh);
|
||||
err = iscsi_if_get_stats(transport, nlh);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
module_put(transport->owner);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Get message from skb (based on rtnetlink_rcv_skb). Each message is
|
||||
* processed by iscsi_if_recv_msg. Malformed skbs with wrong length are
|
||||
* discarded silently. */
|
||||
* or invalid creds discarded silently. */
|
||||
static void
|
||||
iscsi_if_rx(struct sock *sk, int len)
|
||||
{
|
||||
@ -940,6 +933,12 @@ iscsi_if_rx(struct sock *sk, int len)
|
||||
|
||||
mutex_lock(&rx_queue_mutex);
|
||||
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
|
||||
if (NETLINK_CREDS(skb)->uid) {
|
||||
skb_pull(skb, skb->len);
|
||||
goto free_skb;
|
||||
}
|
||||
daemon_pid = NETLINK_CREDS(skb)->pid;
|
||||
|
||||
while (skb->len >= NLMSG_SPACE(0)) {
|
||||
int err;
|
||||
uint32_t rlen;
|
||||
@ -951,10 +950,12 @@ iscsi_if_rx(struct sock *sk, int len)
|
||||
skb->len < nlh->nlmsg_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
ev = NLMSG_DATA(nlh);
|
||||
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
|
||||
if (rlen > skb->len)
|
||||
rlen = skb->len;
|
||||
|
||||
err = iscsi_if_recv_msg(skb, nlh);
|
||||
if (err) {
|
||||
ev->type = ISCSI_KEVENT_IF_ERROR;
|
||||
@ -978,6 +979,7 @@ iscsi_if_rx(struct sock *sk, int len)
|
||||
} while (err < 0 && err != -ECONNREFUSED);
|
||||
skb_pull(skb, rlen);
|
||||
}
|
||||
free_skb:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
mutex_unlock(&rx_queue_mutex);
|
||||
@ -997,7 +999,7 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf) \
|
||||
struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
|
||||
struct iscsi_transport *t = conn->transport; \
|
||||
\
|
||||
t->get_conn_param(conn->dd_data, param, &value); \
|
||||
t->get_conn_param(conn, param, &value); \
|
||||
return snprintf(buf, 20, format"\n", value); \
|
||||
}
|
||||
|
||||
@ -1024,10 +1026,9 @@ show_session_int_param_##param(struct class_device *cdev, char *buf) \
|
||||
{ \
|
||||
uint32_t value = 0; \
|
||||
struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
|
||||
struct Scsi_Host *shost = iscsi_session_to_shost(session); \
|
||||
struct iscsi_transport *t = session->transport; \
|
||||
\
|
||||
t->get_session_param(shost, param, &value); \
|
||||
t->get_session_param(session, param, &value); \
|
||||
return snprintf(buf, 20, format"\n", value); \
|
||||
}
|
||||
|
||||
@ -1121,7 +1122,6 @@ iscsi_register_transport(struct iscsi_transport *tt)
|
||||
return NULL;
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
INIT_LIST_HEAD(&priv->list);
|
||||
INIT_LIST_HEAD(&priv->sessions);
|
||||
priv->iscsi_transport = tt;
|
||||
|
||||
priv->cdev.class = &iscsi_transport_class;
|
||||
|
@ -3588,7 +3588,7 @@ static int sym_evaluate_dp(struct sym_hcb *np, struct sym_ccb *cp, u32 scr, int
|
||||
|
||||
if (pm) {
|
||||
dp_scr = scr_to_cpu(pm->ret);
|
||||
dp_ofs -= scr_to_cpu(pm->sg.size);
|
||||
dp_ofs -= scr_to_cpu(pm->sg.size) & 0x00ffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -163,9 +163,6 @@ enum iscsi_param {
|
||||
};
|
||||
#define ISCSI_PARAM_MAX 14
|
||||
|
||||
typedef uint64_t iscsi_sessionh_t; /* iSCSI Data-Path session handle */
|
||||
typedef uint64_t iscsi_connh_t; /* iSCSI Data-Path connection handle */
|
||||
|
||||
#define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
|
||||
#define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
|
||||
#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
|
||||
|
@ -433,4 +433,6 @@ struct scsi_lun {
|
||||
/* Used to obtain the PCI location of a device */
|
||||
#define SCSI_IOCTL_GET_PCI 0x5387
|
||||
|
||||
int scsi_execute_in_process_context(void (*fn)(void *data), void *data);
|
||||
|
||||
#endif /* _SCSI_SCSI_H */
|
||||
|
@ -63,25 +63,28 @@ struct iscsi_transport {
|
||||
int max_lun;
|
||||
unsigned int max_conn;
|
||||
unsigned int max_cmd_len;
|
||||
struct Scsi_Host *(*create_session) (struct scsi_transport_template *t,
|
||||
uint32_t initial_cmdsn);
|
||||
void (*destroy_session) (struct Scsi_Host *shost);
|
||||
struct iscsi_cls_conn *(*create_conn) (struct Scsi_Host *shost,
|
||||
struct iscsi_cls_session *(*create_session)
|
||||
(struct scsi_transport_template *t, uint32_t sn, uint32_t *sid);
|
||||
void (*destroy_session) (struct iscsi_cls_session *session);
|
||||
struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
|
||||
uint32_t cid);
|
||||
int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn,
|
||||
int (*bind_conn) (struct iscsi_cls_session *session,
|
||||
struct iscsi_cls_conn *cls_conn,
|
||||
uint32_t transport_fd, int is_leading);
|
||||
int (*start_conn) (iscsi_connh_t conn);
|
||||
void (*stop_conn) (iscsi_connh_t conn, int flag);
|
||||
int (*start_conn) (struct iscsi_cls_conn *conn);
|
||||
void (*stop_conn) (struct iscsi_cls_conn *conn, int flag);
|
||||
void (*destroy_conn) (struct iscsi_cls_conn *conn);
|
||||
int (*set_param) (iscsi_connh_t conn, enum iscsi_param param,
|
||||
int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param,
|
||||
uint32_t value);
|
||||
int (*get_conn_param) (void *conndata, enum iscsi_param param,
|
||||
int (*get_conn_param) (struct iscsi_cls_conn *conn,
|
||||
enum iscsi_param param,
|
||||
uint32_t *value);
|
||||
int (*get_session_param) (struct Scsi_Host *shost,
|
||||
int (*get_session_param) (struct iscsi_cls_session *session,
|
||||
enum iscsi_param param, uint32_t *value);
|
||||
int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr,
|
||||
int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
|
||||
char *data, uint32_t data_size);
|
||||
void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats);
|
||||
void (*get_stats) (struct iscsi_cls_conn *conn,
|
||||
struct iscsi_stats *stats);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -93,15 +96,14 @@ extern int iscsi_unregister_transport(struct iscsi_transport *tt);
|
||||
/*
|
||||
* control plane upcalls
|
||||
*/
|
||||
extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error);
|
||||
extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr,
|
||||
extern void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error);
|
||||
extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
|
||||
char *data, uint32_t data_size);
|
||||
|
||||
struct iscsi_cls_conn {
|
||||
struct list_head conn_list; /* item in connlist */
|
||||
void *dd_data; /* LLD private data */
|
||||
struct iscsi_transport *transport;
|
||||
iscsi_connh_t connh;
|
||||
int active; /* must be accessed with the connlock */
|
||||
struct device dev; /* sysfs transport/container device */
|
||||
struct mempool_zone *z_error;
|
||||
@ -113,7 +115,7 @@ struct iscsi_cls_conn {
|
||||
container_of(_dev, struct iscsi_cls_conn, dev)
|
||||
|
||||
struct iscsi_cls_session {
|
||||
struct list_head list; /* item in session_list */
|
||||
struct list_head sess_list; /* item in session_list */
|
||||
struct iscsi_transport *transport;
|
||||
struct device dev; /* sysfs transport/container device */
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user