Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6

This commit is contained in:
Linus Torvalds 2006-02-16 12:47:44 -08:00
commit 26d451b603
48 changed files with 2389 additions and 813 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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:

View file

@ -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 {

View file

@ -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;

View file

@ -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");

View file

@ -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 */

View file

@ -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;

View file

@ -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 *);

View file

@ -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;

View file

@ -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);

View file

@ -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,

View file

@ -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]) {

View file

@ -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;
}

View file

@ -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[];

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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),

View file

@ -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

View file

@ -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(&regs->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(&regs->outbound_intr_status);
if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
return 1;
}
/*
* Clear the interrupt by writing back the same value
*/
writel(status, &regs->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

View file

@ -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));

View file

@ -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

View file

@ -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"

View file

@ -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.
*/

View file

@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/vmalloc.h>
#include <scsi/scsi_transport_fc.h>
#include "qla_devtbl.h"

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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) {

View file

@ -6,8 +6,6 @@
*/
#include "qla_def.h"
#include <scsi/scsi_transport_fc.h>
/**
* IO descriptor handle definitions.
*

View file

@ -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(&reg->gpioe);
gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
} else {
gpio_enable = RD_REG_WORD(&reg->gpioe);
gpio_data = RD_REG_WORD(&reg->gpiod);
}
/* Set the modified gpio_enable values */
gpio_enable |= GPIO_LED_MASK;
if (ha->pio_address) {
WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
} else {
WRT_REG_WORD(&reg->gpioe, gpio_enable);
RD_REG_WORD(&reg->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(&reg->gpiod, gpio_data);
} else {
WRT_REG_WORD(&reg->gpiod, gpio_data);
RD_REG_WORD(&reg->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(&reg->gpioe);
gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
} else {
gpio_enable = RD_REG_WORD(&reg->gpioe);
gpio_data = RD_REG_WORD(&reg->gpiod);
}
gpio_enable |= GPIO_LED_MASK;
/* Set the modified gpio_enable values. */
if (ha->pio_address) {
WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
} else {
WRT_REG_WORD(&reg->gpioe, gpio_enable);
RD_REG_WORD(&reg->gpioe);
}
/* Clear out previously set LED colour. */
gpio_data &= ~GPIO_LED_MASK;
if (ha->pio_address) {
WRT_REG_WORD_PIO(&reg->gpiod, gpio_data);
} else {
WRT_REG_WORD(&reg->gpiod, gpio_data);
RD_REG_WORD(&reg->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(&reg->gpiod);
/* Enable the gpio_data reg for update. */
gpio_data |= GPDX_LED_UPDATE_MASK;
WRT_REG_DWORD(&reg->gpiod, gpio_data);
gpio_data = RD_REG_DWORD(&reg->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(&reg->gpiod, gpio_data);
gpio_data = RD_REG_DWORD(&reg->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(&reg->gpiod);
/* Enable the gpio_data reg for update. */
gpio_data |= GPDX_LED_UPDATE_MASK;
WRT_REG_DWORD(&reg->gpiod, gpio_data);
RD_REG_DWORD(&reg->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(&reg->gpiod);
/* Disable the gpio_data reg for update. */
gpio_data &= ~GPDX_LED_UPDATE_MASK;
WRT_REG_DWORD(&reg->gpiod, gpio_data);
RD_REG_DWORD(&reg->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(&reg->ctrl_status);
data |= CSR_FLASH_ENABLE;
WRT_REG_WORD(&reg->ctrl_status, data);
RD_REG_WORD(&reg->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(&reg->ctrl_status);
data &= ~(CSR_FLASH_ENABLE);
WRT_REG_WORD(&reg->ctrl_status, data);
RD_REG_WORD(&reg->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(&reg->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(&reg->ctrl_status, bank_select);
RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
data = RD_REG_WORD(&reg->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(&reg->ctrl_status, bank_select);
RD_REG_WORD(&reg->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(&reg->ctrl_status, bank_select);
RD_REG_WORD(&reg->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(&reg->flash_address, (uint16_t)addr);
do {
data = RD_REG_WORD_PIO(&reg->flash_data);
barrier();
cpu_relax();
data2 = RD_REG_WORD_PIO(&reg->flash_data);
} while (data != data2);
} else {
WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
data = qla2x00_debounce_register(&reg->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(&reg->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(&reg->ctrl_status, bank_select);
RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
WRT_REG_WORD(&reg->flash_data, (uint16_t)data);
RD_REG_WORD(&reg->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(&reg->ctrl_status, bank_select);
RD_REG_WORD(&reg->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(&reg->ctrl_status, bank_select);
RD_REG_WORD(&reg->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(&reg->flash_address, (uint16_t)addr);
WRT_REG_WORD_PIO(&reg->flash_data, (uint16_t)data);
} else {
WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
WRT_REG_WORD(&reg->flash_data, (uint16_t)data);
RD_REG_WORD(&reg->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(&reg->hccr, HCCR_PAUSE_RISC);
RD_REG_WORD(&reg->hccr);
if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
for (cnt = 0; cnt < 30000; cnt++) {
if ((RD_REG_WORD(&reg->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(&reg->nvram, 0);
RD_REG_WORD(&reg->nvram); /* PCI Posting. */
for (addr = offset, data = buf; addr < length; addr++, data++) {
if (addr == midpoint) {
WRT_REG_WORD(&reg->nvram, NVR_SELECT);
RD_REG_WORD(&reg->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(&reg->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(&reg->nvram, NVR_SELECT);
RD_REG_WORD(&reg->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;
}

View file

@ -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);

View file

@ -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);
}
/**

View file

@ -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,

View file

@ -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;

View file

@ -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;
}
/*

View file

@ -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))

View file

@ -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 */

View file

@ -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 */
};