/*
* linux/drivers/message/fusion/mptctl.c
- * Fusion MPT misc device (ioctl) driver.
- * For use with PCI chip/adapter(s):
- * LSIFC9xx/LSI409xx Fibre Channel
+ * mpt Ioctl driver.
+ * For use with LSI Logic PCI chip/adapters
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Credits:
- * This driver would not exist if not for Alan Cox's development
- * of the linux i2o driver.
- *
- * A special thanks to Pamela Delaney (LSI Logic) for tons of work
- * and countless enhancements while adding support for the 1030
- * chip family. Pam has been instrumental in the development of
- * of the 2.xx.xx series fusion drivers, and her contributions are
- * far too numerous to hope to list in one place.
- *
- * A huge debt of gratitude is owed to David S. Miller (DaveM)
- * for fixing much of the stupid and broken stuff in the early
- * driver while porting to sparc64 platform. THANK YOU!
- *
- * A big THANKS to Eddie C. Dost for fixing the ioctl path
- * and most importantly f/w download on sparc64 platform!
- * (plus Eddie's other helpful hints and insights)
- *
- * Thanks to Arnaldo Carvalho de Melo for finding and patching
- * a potential memory leak in mptctl_do_fw_download(),
- * and for some kmalloc insight:-)
- *
- * (see also mptbase.c)
- *
- * Copyright (c) 1999-2004 LSI Logic Corporation
- * Originally By: Steven J. Ralston, Noah Romer
- * (mailto:sjralston1@netscape.net)
+ * Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
- * $Id: mptctl.c,v 1.63 2002/12/03 21:26:33 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-#define COPYRIGHT "Copyright (c) 1999-2004 LSI Logic Corporation"
-#define MODULEAUTHOR "Steven J. Ralston, Noah Romer, Pamela Delaney"
+#define COPYRIGHT "Copyright (c) 1999-2005 LSI Logic Corporation"
+#define MODULEAUTHOR "LSI Logic Corporation"
#include "mptbase.h"
#include "mptctl.h"
* arg contents specific to function.
*/
static int mptctl_fw_download(unsigned long arg);
-static int mptctl_getiocinfo (unsigned long arg, unsigned int cmd);
-static int mptctl_gettargetinfo (unsigned long arg);
-static int mptctl_readtest (unsigned long arg);
-static int mptctl_mpt_command (unsigned long arg);
-static int mptctl_eventquery (unsigned long arg);
-static int mptctl_eventenable (unsigned long arg);
-static int mptctl_eventreport (unsigned long arg);
-static int mptctl_replace_fw (unsigned long arg);
+static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
+static int mptctl_gettargetinfo(unsigned long arg);
+static int mptctl_readtest(unsigned long arg);
+static int mptctl_mpt_command(unsigned long arg);
+static int mptctl_eventquery(unsigned long arg);
+static int mptctl_eventenable(unsigned long arg);
+static int mptctl_eventreport(unsigned long arg);
+static int mptctl_replace_fw(unsigned long arg);
static int mptctl_do_reset(unsigned long arg);
static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
/*
* Private function calls.
*/
-static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr);
+static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
-static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frags,
+static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
-static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
+static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
struct buflist *buflist, MPT_ADAPTER *ioc);
static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
static int mptctl_bus_reset(MPT_IOCTL *ioctl);
*/
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);
+static struct fasync_struct *async_queue=NULL;
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Scatter gather list (SGL) sizes and limits...
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
if (nonblock) {
- if (down_trylock(&ioc->ioctl->sem_ioc))
+ if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
rc = -EAGAIN;
} else {
- if (down_interruptible(&ioc->ioctl->sem_ioc))
+ if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
rc = -ERESTARTSYS;
}
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
/* Set the command status to GOOD if IOC Status is GOOD
* OR if SCSI I/O cmd and data underrun or recovered error.
*/
- iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
+ iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK;
if (iocStatus == MPI_IOCSTATUS_SUCCESS)
ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
}
/* 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;
}
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"));
+ devtverboseprintk(("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"));
+ devtverboseprintk(("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
else
ret = -EINVAL;
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
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);
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.
*/
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,
/*
* 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);
int numDevices = 0;
unsigned int max_id;
int ii;
- int port;
+ unsigned int port;
int cim_rev;
u8 revision;
return -ENODEV;
}
- /* Verify the data transfer size is correct.
- * Ignore the port setting.
- */
+ /* Verify the data transfer size is correct. */
if (karg->hdr.maxDataSize != data_size) {
printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
"Structure size mismatch. Command not completed.\n",
/* 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;
+ if (karg->hdr.port > 1)
+ return -EINVAL;
port = karg->hdr.port;
karg->port = port;
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);
}
MPT_ADAPTER *ioc;
struct Scsi_Host *sh;
MPT_SCSI_HOST *hd;
- VirtDevice *vdev;
+ VirtTarget *vdev;
char *pmem;
int *pdata;
IOCPage2_t *pIoc2;
*/
if (hd && hd->Targets) {
mpt_findImVolumes(ioc);
- pIoc2 = ioc->spi_data.pIocPg2;
+ pIoc2 = ioc->raid_data.pIocPg2;
for ( id = 0; id <= max_id; ) {
if ( pIoc2 && pIoc2->NumActiveVolumes ) {
if ( id == pIoc2->RaidVolume[0].VolumeID ) {
--maxWordsLeft;
goto next_id;
} else {
- pIoc3 = ioc->spi_data.pIocPg3;
+ pIoc3 = ioc->raid_data.pIocPg3;
for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
goto next_id;
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
memset(ioc->events, 0, sz);
ioc->alloc_total += sz;
- ioc->eventLogSize = MPTCTL_EVENT_LOG_SIZE;
ioc->eventContext = 0;
}
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.
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);
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:
if (ioc->sh) {
SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
- VirtDevice *pTarget = NULL;
+ VirtTarget *pTarget = NULL;
MPT_SCSI_HOST *hd = NULL;
int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
int scsidir = 0;
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
}
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
*/
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
/* 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);
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
hdr.PageLength = 0;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
strncpy(karg.serial_number, " ", 24);
if (mpt_config(ioc, &cfg) == 0) {
- if (cfg.hdr->PageLength > 0) {
+ if (cfg.cfghdr.hdr->PageLength > 0) {
/* Issue the second config page request */
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
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;
}
}
- cfg.pageAddr = 0;
- cfg.action = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
- cfg.dir = MPI_TB_ISTWI_FLAGS_READ;
- cfg.timeout = 10;
+ /*
+ * 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) {
- 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;
+ 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))) {
/* 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))
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
cfg.dir = 0;
cfg.timeout = 0;
hdr.PageNumber = 3;
hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
cfg.timeout = 0;
cfg.physAddr = -1;
- if ((mpt_config(ioc, &cfg) == 0) && (cfg.hdr->PageLength > 0)) {
+ if ((mpt_config(ioc, &cfg) == 0) && (cfg.cfghdr.hdr->PageLength > 0)) {
/* Issue the second config page request */
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
- data_sz = (int) cfg.hdr->PageLength * 4;
+ data_sz = (int) cfg.cfghdr.hdr->PageLength * 4;
pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent(
ioc->pcidev, data_sz, &page_dma);
if (pg3_alloc) {
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,
#ifdef CONFIG_COMPAT
-#include <linux/ioctl32.h>
-
static int
compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
*/
ret = mptctl_do_mpt_command (karg, &uarg->MF);
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
memset(mem, 0, sz);
ioc->ioctl = (MPT_IOCTL *) mem;
ioc->ioctl->ioc = ioc;
- sema_init(&ioc->ioctl->sem_ioc, 1);
+ mutex_init(&ioc->ioctl->ioctl_mutex);
return 0;
out_fail:
/* FIXME! */
}
+ if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
+ devtverboseprintk((KERN_INFO MYNAM
+ ": Registered for IOC event notifications\n"));
+ }
+
return 0;
out_fail: