#include <linux/pci.h>
#include <linux/miscdevice.h>
#include <linux/smp_lock.h>
+#include <linux/compat.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <linux/kdev_t.h> /* needed for access to Scsi_Host struct */
-#include <linux/blkdev.h>
-#include "../../scsi/scsi.h"
-#include "../../scsi/hosts.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
#define COPYRIGHT "Copyright (c) 1999-2004 LSI Logic Corporation"
#define MODULEAUTHOR "Steven J. Ralston, Noah Romer, Pamela Delaney"
#define my_VERSION MPT_LINUX_VERSION_COMMON
#define MYNAM "mptctl"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,62)
-EXPORT_NO_SYMBOLS;
-#endif
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static int mptctl_id = -1;
-static struct semaphore mptctl_syscall_sem_ioc[MPT_MAX_ADAPTERS];
static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
static int mptctl_hp_targetinfo(unsigned long arg);
+static int mptctl_probe(struct pci_dev *, const struct pci_device_id *);
+static void mptctl_remove(struct pci_dev *);
+
/*
* Private function calls.
*/
-static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local);
-static int mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen);
+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,
struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
}
if (nonblock) {
- if (down_trylock(&mptctl_syscall_sem_ioc[ioc->id]))
+ if (down_trylock(&ioc->ioctl->sem_ioc))
rc = -EAGAIN;
} else {
- if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id]))
+ if (down_interruptible(&ioc->ioctl->sem_ioc))
rc = -ERESTARTSYS;
}
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
/* Send request
*/
- if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc->id)) == NULL) {
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc)) == NULL) {
dctlprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
ioctl->ioc->name));
ioctl->status |= MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
add_timer(&ioctl->TMtimer);
- retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc->id,
+ retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, NO_SLEEP);
if (retval != 0) {
mptctl_free_tm_flags(ioctl->ioc);
del_timer(&ioctl->TMtimer);
- mpt_free_msg_frame(mptctl_id, ioctl->ioc->id, mf);
+ mpt_free_msg_frame(ioctl->ioc, mf);
ioctl->tmPtr = NULL;
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
- hd->tmState = TM_STATE_ERROR;
+ hd->tmState = TM_STATE_NONE;
hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){
ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
del_timer(&ioctl->TMtimer);
- mpt_free_msg_frame(mptctl_id, ioc->id, ioctl->tmPtr);
+ mpt_free_msg_frame(ioc, ioctl->tmPtr);
}
} else {
return 1;
}
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * struct file_operations functionality.
- * Members:
- * llseek, write, read, ioctl, open, release
- */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9)
-static loff_t
-mptctl_llseek(struct file *file, loff_t offset, int origin)
-{
- return -ESPIPE;
-}
-#define no_llseek mptctl_llseek
-#endif
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static ssize_t
-mptctl_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- printk(KERN_ERR MYNAM ": ioctl WRITE not yet supported\n");
- return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static ssize_t
-mptctl_read(struct file *file, char *buf, size_t count, loff_t *ptr)
-{
- printk(KERN_ERR MYNAM ": ioctl READ not yet supported\n");
- return 0;
-}
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* MPT ioctl handler
static int
mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
- mpt_ioctl_header *uhdr = (mpt_ioctl_header *) arg;
+ mpt_ioctl_header __user *uhdr = (void __user *) arg;
mpt_ioctl_header khdr;
int iocnum;
unsigned iocnumX;
if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
printk(KERN_ERR "%s::mptctl_ioctl() @%d - "
"Unable to copy mpt_ioctl_header data @ %p\n",
- __FILE__, __LINE__, (void*)uhdr);
+ __FILE__, __LINE__, uhdr);
return -EFAULT;
}
ret = -ENXIO; /* (-6) No such device or address */
else
ret = -EINVAL;
-
- up(&mptctl_syscall_sem_ioc[iocp->id]);
+ up(&iocp->ioctl->sem_ioc);
return ret;
}
static int mptctl_do_reset(unsigned long arg)
{
- struct mpt_ioctl_diag_reset *urinfo = (struct mpt_ioctl_diag_reset *) arg;
+ struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
struct mpt_ioctl_diag_reset krinfo;
MPT_ADAPTER *iocp;
if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
printk(KERN_ERR "%s@%d::mptctl_do_reset - "
"Unable to copy mpt_ioctl_diag_reset struct @ %p\n",
- __FILE__, __LINE__, (void*)urinfo);
+ __FILE__, __LINE__, urinfo);
return -EFAULT;
}
return 0;
}
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int mptctl_open(struct inode *inode, struct file *file)
-{
- /*
- * Should support multiple management users
- */
- return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int mptctl_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* MPT FW download function. Cast the arg into the mpt_fw_xfer structure.
static int
mptctl_fw_download(unsigned long arg)
{
- struct mpt_fw_xfer *ufwdl = (struct mpt_fw_xfer *) arg;
+ struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
struct mpt_fw_xfer kfwdl;
dctlprintk((KERN_INFO "mptctl_fwdl called. mptctl_id = %xh\n", mptctl_id)); //tc
if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) {
printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
"Unable to copy mpt_fw_xfer struct @ %p\n",
- __FILE__, __LINE__, (void*)ufwdl);
+ __FILE__, __LINE__, ufwdl);
return -EFAULT;
}
* -ENOMSG if FW upload returned bad status
*/
static int
-mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
+mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
{
FWDownload_t *dlmsg;
MPT_FRAME_HDR *mf;
/* Valid device. Get a message frame and construct the FW download message.
*/
- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
+ if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
return -EAGAIN;
dlmsg = (FWDownload_t*) mf;
ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
"Unable to copy f/w buffer hunk#%d @ %p\n",
- __FILE__, __LINE__, n, (void*)ufwbuf);
+ __FILE__, __LINE__, n, ufwbuf);
goto fwdl_out;
}
fw_bytes_copied += bl->len;
* Finally, perform firmware download.
*/
ReplyMsg = NULL;
- mpt_put_msg_frame(mptctl_id, ioc, mf);
+ mpt_put_msg_frame(mptctl_id, iocp, mf);
/*
* Wait until the reply has been received
static int
mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
{
- struct mpt_ioctl_iocinfo *uarg = (struct mpt_ioctl_iocinfo *) arg;
+ struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
struct mpt_ioctl_iocinfo *karg;
MPT_ADAPTER *ioc;
struct pci_dev *pdev;
if (copy_from_user(karg, uarg, data_size)) {
printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
"Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
kfree(karg);
return -EFAULT;
}
karg->pciId = pdev->device;
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
karg->hwRev = revision;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
karg->subSystemDevice = pdev->subsystem_device;
karg->subSystemVendor = pdev->subsystem_vendor;
-#endif
if (cim_rev == 1) {
/* Get the PCI bus, device, and function numbers for the IOC
/* Copy the data from kernel memory to user memory
*/
- if (copy_to_user((char *)arg, karg, data_size)) {
+ if (copy_to_user((char __user *)arg, karg, data_size)) {
printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
"Unable to write out mpt_ioctl_iocinfo struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
kfree(karg);
return -EFAULT;
}
static int
mptctl_gettargetinfo (unsigned long arg)
{
- struct mpt_ioctl_targetinfo *uarg = (struct mpt_ioctl_targetinfo *) arg;
+ struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
struct mpt_ioctl_targetinfo karg;
MPT_ADAPTER *ioc;
struct Scsi_Host *sh;
char *pmem;
int *pdata;
IOCPage2_t *pIoc2;
+ IOCPage3_t *pIoc3;
int iocnum;
int numDevices = 0;
unsigned int max_id;
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
"Unable to read in mpt_ioctl_targetinfo struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
if (hd && hd->Targets) {
mpt_findImVolumes(ioc);
pIoc2 = ioc->spi_data.pIocPg2;
- for ( id = 0; id <= max_id; id++ ) {
- if ( pIoc2 && pIoc2->NumActiveVolumes &&
- ( id == pIoc2->RaidVolume[0].VolumeID ) ) {
- if (maxWordsLeft <= 0) {
- printk(KERN_ERR "mptctl_gettargetinfo - "
+ for ( id = 0; id <= max_id; ) {
+ if ( pIoc2 && pIoc2->NumActiveVolumes ) {
+ if ( id == pIoc2->RaidVolume[0].VolumeID ) {
+ if (maxWordsLeft <= 0) {
+ printk(KERN_ERR "mptctl_gettargetinfo - "
"buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
- goto data_space_full;
- }
- if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
- devType = 0x80;
- else
- devType = 0xC0;
- bus_id = pIoc2->RaidVolume[0].VolumeBus;
- numDevices++;
- *pdata = ( (devType << 24) | (bus_id << 8) | id );
- dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
+ goto data_space_full;
+ }
+ if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
+ devType = 0x80;
+ else
+ devType = 0xC0;
+ bus_id = pIoc2->RaidVolume[0].VolumeBus;
+ numDevices++;
+ *pdata = ( (devType << 24) | (bus_id << 8) | id );
+ dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
"volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
- pdata++;
- --maxWordsLeft;
- } else {
- vdev = hd->Targets[id];
- if (vdev) {
- for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
- lun_index = (jj >> 5);
- indexed_lun = (jj % 32);
- lun = (1 << indexed_lun);
- if (vdev->luns[lun_index] & lun) {
- if (maxWordsLeft <= 0) {
- printk(KERN_ERR
- "mptctl_gettargetinfo - "
- "buffer is full but more targets are available on ioc %d numDevices=%d\n",
- iocnum, numDevices);
- goto data_space_full;
- }
- bus_id = vdev->bus_id;
- numDevices++;
- *pdata = ( (jj << 16) | (bus_id << 8) | id );
- dctlprintk((KERN_ERR
- "mptctl_gettargetinfo - "
- "target ioc=%d target=%x numDevices=%d pdata=%p\n",
- iocnum, *pdata, numDevices, pdata));
- pdata++;
- --maxWordsLeft;
+ pdata++;
+ --maxWordsLeft;
+ goto next_id;
+ } else {
+ pIoc3 = ioc->spi_data.pIocPg3;
+ for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
+ if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
+ goto next_id;
+ }
+ }
+ }
+ if ( (vdev = hd->Targets[id]) ) {
+ for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
+ lun_index = (jj >> 5);
+ indexed_lun = (jj % 32);
+ lun = (1 << indexed_lun);
+ if (vdev->luns[lun_index] & lun) {
+ if (maxWordsLeft <= 0) {
+ printk(KERN_ERR "mptctl_gettargetinfo - "
+ "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
+ goto data_space_full;
}
+ bus_id = vdev->bus_id;
+ numDevices++;
+ *pdata = ( (jj << 16) | (bus_id << 8) | id );
+ dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
+ "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
+ pdata++;
+ --maxWordsLeft;
}
}
}
+next_id:
+ id++;
}
}
}
/* Copy part of the data from kernel memory to user memory
*/
- if (copy_to_user((char *)arg, &karg,
+ if (copy_to_user((char __user *)arg, &karg,
sizeof(struct mpt_ioctl_targetinfo))) {
printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
kfree(pmem);
return -EFAULT;
}
/* Copy the remaining data from kernel memory to user memory
*/
- if (copy_to_user((char *) uarg->targetInfo, pmem, numBytes)) {
+ if (copy_to_user(uarg->targetInfo, pmem, numBytes)) {
printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
- __FILE__, __LINE__, (void*)pdata);
+ __FILE__, __LINE__, pdata);
kfree(pmem);
return -EFAULT;
}
static int
mptctl_readtest (unsigned long arg)
{
- struct mpt_ioctl_test *uarg = (struct mpt_ioctl_test *) arg;
+ struct mpt_ioctl_test __user *uarg = (void __user *) arg;
struct mpt_ioctl_test karg;
MPT_ADAPTER *ioc;
int iocnum;
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
printk(KERN_ERR "%s@%d::mptctl_readtest - "
"Unable to read in mpt_ioctl_test struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
/* Copy the data from kernel memory to user memory
*/
- if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
+ if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
printk(KERN_ERR "%s@%d::mptctl_readtest - "
"Unable to write out mpt_ioctl_test struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
static int
mptctl_eventquery (unsigned long arg)
{
- struct mpt_ioctl_eventquery *uarg = (struct mpt_ioctl_eventquery *) arg;
+ struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
struct mpt_ioctl_eventquery karg;
MPT_ADAPTER *ioc;
int iocnum;
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
printk(KERN_ERR "%s@%d::mptctl_eventquery - "
"Unable to read in mpt_ioctl_eventquery struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
/* Copy the data from kernel memory to user memory
*/
- if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
+ if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
printk(KERN_ERR "%s@%d::mptctl_eventquery - "
"Unable to write out mpt_ioctl_eventquery struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
return 0;
static int
mptctl_eventenable (unsigned long arg)
{
- struct mpt_ioctl_eventenable *uarg = (struct mpt_ioctl_eventenable *) arg;
+ struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
struct mpt_ioctl_eventenable karg;
MPT_ADAPTER *ioc;
int iocnum;
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
printk(KERN_ERR "%s@%d::mptctl_eventenable - "
"Unable to read in mpt_ioctl_eventenable struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
static int
mptctl_eventreport (unsigned long arg)
{
- struct mpt_ioctl_eventreport *uarg = (struct mpt_ioctl_eventreport *) arg;
+ struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
struct mpt_ioctl_eventreport karg;
MPT_ADAPTER *ioc;
int iocnum;
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
printk(KERN_ERR "%s@%d::mptctl_eventreport - "
"Unable to read in mpt_ioctl_eventreport struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
/* Copy the data from kernel memory to user memory
*/
numBytes = max * sizeof(MPT_IOCTL_EVENTS);
- if (copy_to_user((char *) uarg->eventData, ioc->events, numBytes)) {
+ if (copy_to_user(uarg->eventData, ioc->events, numBytes)) {
printk(KERN_ERR "%s@%d::mptctl_eventreport - "
"Unable to write out mpt_ioctl_eventreport struct @ %p\n",
- __FILE__, __LINE__, (void*)ioc->events);
+ __FILE__, __LINE__, ioc->events);
return -EFAULT;
}
static int
mptctl_replace_fw (unsigned long arg)
{
- struct mpt_ioctl_replace_fw *uarg = (struct mpt_ioctl_replace_fw *) arg;
+ struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
struct mpt_ioctl_replace_fw karg;
MPT_ADAPTER *ioc;
- fw_image_t **fwmem = NULL;
int iocnum;
int newFwSize;
- int num_frags, alloc_sz;
- int ii;
- u32 offset;
dctlprintk(("mptctl_replace_fw called.\n"));
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
"Unable to read in mpt_ioctl_replace_fw struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
return -ENODEV;
}
- /* If not caching FW, return 0
+ /* If caching FW, Free the old FW image
*/
- if ((ioc->cached_fw == NULL) && (ioc->alt_ioc) && (ioc->alt_ioc->cached_fw == NULL))
+ if (ioc->cached_fw == NULL)
return 0;
+ mpt_free_fw_memory(ioc);
+
/* Allocate memory for the new FW image
*/
newFwSize = karg.newImageSize;
- fwmem = mpt_alloc_fw_memory(ioc, newFwSize, &num_frags, &alloc_sz);
- if (fwmem == NULL)
- return -ENOMEM;
- offset = 0;
- for (ii = 0; ii < num_frags; ii++) {
- /* Copy the data from user memory to kernel space
- */
- if (copy_from_user(fwmem[ii]->fw, uarg->newImage + offset, fwmem[ii]->size)) {
- printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
- "Unable to read in mpt_ioctl_replace_fw image @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
-
- mpt_free_fw_memory(ioc, fwmem);
- return -EFAULT;
- }
- offset += fwmem[ii]->size;
- }
+ if (newFwSize & 0x01)
+ newFwSize += 1;
+ if (newFwSize & 0x02)
+ newFwSize += 2;
+ mpt_alloc_fw_memory(ioc, newFwSize);
+ if (ioc->cached_fw == NULL)
+ return -ENOMEM;
- /* Free the old FW image
+ /* Copy the data from user memory to kernel space
*/
- if (ioc->cached_fw) {
- mpt_free_fw_memory(ioc, 0);
- ioc->cached_fw = fwmem;
- ioc->alloc_total += alloc_sz;
- } else if ((ioc->alt_ioc) && (ioc->alt_ioc->cached_fw)) {
- mpt_free_fw_memory(ioc->alt_ioc, 0);
- ioc->alt_ioc->cached_fw = fwmem;
- ioc->alt_ioc->alloc_total += alloc_sz;
+ if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
+ printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
+ "Unable to read in mpt_ioctl_replace_fw image "
+ "@ %p\n", __FILE__, __LINE__, uarg);
+ mpt_free_fw_memory(ioc);
+ return -EFAULT;
}
/* Update IOCFactsReply
*/
ioc->facts.FWImageSize = newFwSize;
- if (ioc->alt_ioc)
- ioc->alt_ioc->facts.FWImageSize = newFwSize;
-
return 0;
}
static int
mptctl_mpt_command (unsigned long arg)
{
- struct mpt_ioctl_command *uarg = (struct mpt_ioctl_command *) arg;
+ struct mpt_ioctl_command __user *uarg = (void __user *) arg;
struct mpt_ioctl_command karg;
MPT_ADAPTER *ioc;
int iocnum;
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) {
printk(KERN_ERR "%s@%d::mptctl_mpt_command - "
"Unable to read in mpt_ioctl_command struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
return -ENODEV;
}
- rc = mptctl_do_mpt_command (karg, (char *) &uarg->MF, 0);
+ rc = mptctl_do_mpt_command (karg, &uarg->MF);
return rc;
}
* -EPERM if SCSI I/O and target is untagged
*/
static int
-mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
+mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
{
MPT_ADAPTER *ioc;
MPT_FRAME_HDR *mf = NULL;
struct buflist bufOut; /* data Out buffer */
dma_addr_t dma_addr_in;
dma_addr_t dma_addr_out;
- int dir; /* PCI data direction */
int sgSize = 0; /* Num SG elements */
int iocnum, flagsLength;
int sz, rc = 0;
/* Get a free request frame and save the message context.
*/
- if ((mf = mpt_get_msg_frame(mptctl_id, ioc->id)) == NULL)
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
return -EAGAIN;
hdr = (MPIHeader_t *) mf;
/* Copy the request frame
* Reset the saved message context.
+ * Request frame in user space
*/
- if (local) {
- /* Request frame in kernel space
- */
- memcpy((char *)mf, (char *) mfPtr, karg.dataSgeOffset * 4);
- } else {
- /* Request frame in user space
- */
- if (copy_from_user((char *)mf, (char *) mfPtr,
- karg.dataSgeOffset * 4)){
- printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
- "Unable to read MF from mpt_ioctl_command struct @ %p\n",
- __FILE__, __LINE__, (void*)mfPtr);
- rc = -EFAULT;
- goto done_free_mem;
- }
- }
+ if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) {
+ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ "Unable to read MF from mpt_ioctl_command struct @ %p\n",
+ __FILE__, __LINE__, mfPtr);
+ rc = -EFAULT;
+ goto done_free_mem;
+ }
hdr->MsgContext = cpu_to_le32(msgContext);
/* Set up the dataOut memory allocation */
if (karg.dataOutSize > 0) {
- dir = PCI_DMA_TODEVICE;
if (karg.dataInSize > 0) {
flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI_SGE_FLAGS_END_OF_BUFFER |
MPI_SGE_FLAGS_DIRECTION |
mpt_addr_size() )
<< MPI_SGE_FLAGS_SHIFT;
"%s@%d::mptctl_do_mpt_command - Unable "
"to read user data "
"struct @ %p\n",
- __FILE__, __LINE__,(void*)karg.dataOutBufPtr);
+ __FILE__, __LINE__,karg.dataOutBufPtr);
rc = -EFAULT;
goto done_free_mem;
}
}
if (karg.dataInSize > 0) {
- dir = PCI_DMA_FROMDEVICE;
flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
flagsLength |= karg.dataInSize;
add_timer(&ioc->ioctl->timer);
if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
- rc = mpt_send_handshake_request(mptctl_id, ioc->id,
+ DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
+ rc = mpt_send_handshake_request(mptctl_id, ioc,
sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
if (rc == 0) {
wait_event(mptctl_wait, ioc->ioctl->wait_done);
del_timer(&ioc->ioctl->timer);
ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED;
- mpt_free_msg_frame(mptctl_id, ioc->id, mf);
+ mpt_free_msg_frame(ioc, mf);
}
} else {
- mpt_put_msg_frame(mptctl_id, ioc->id, mf);
+ mpt_put_msg_frame(mptctl_id, ioc, mf);
wait_event(mptctl_wait, ioc->ioctl->wait_done);
}
}
if (sz > 0) {
- if (copy_to_user((char *)karg.replyFrameBufPtr,
+ if (copy_to_user(karg.replyFrameBufPtr,
&ioc->ioctl->ReplyFrame, sz)){
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
"Unable to write out reply frame %p\n",
- __FILE__, __LINE__, (void*)karg.replyFrameBufPtr);
+ __FILE__, __LINE__, karg.replyFrameBufPtr);
rc = -ENODATA;
goto done_free_mem;
}
if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
if (sz > 0) {
- if (copy_to_user((char *)karg.senseDataPtr, ioc->ioctl->sense, sz)) {
+ if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
"Unable to write sense data to user %p\n",
__FILE__, __LINE__,
- (void*)karg.senseDataPtr);
+ karg.senseDataPtr);
rc = -ENODATA;
goto done_free_mem;
}
if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
(karg.dataInSize > 0) && (bufIn.kptr)) {
- if (copy_to_user((char *)karg.dataInBufPtr,
+ if (copy_to_user(karg.dataInBufPtr,
bufIn.kptr, karg.dataInSize)) {
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
"Unable to write data to user %p\n",
__FILE__, __LINE__,
- (void*)karg.dataInBufPtr);
+ karg.dataInBufPtr);
rc = -ENODATA;
}
}
* otherwise, failure occured after mf acquired.
*/
if (mf)
- mpt_free_msg_frame(mptctl_id, ioc->id, mf);
+ mpt_free_msg_frame(ioc, mf);
return rc;
}
static int
mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
{
- hp_host_info_t *uarg = (hp_host_info_t *) arg;
+ hp_host_info_t __user *uarg = (void __user *) arg;
MPT_ADAPTER *ioc;
struct pci_dev *pdev;
char *pbuf;
if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
printk(KERN_ERR "%s@%d::mptctl_hp_host_info - "
"Unable to read in hp_host_info struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
karg.vendor = pdev->vendor;
karg.device = pdev->device;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
karg.subsystem_id = pdev->subsystem_device;
karg.subsystem_vendor = pdev->subsystem_vendor;
-#endif
karg.devfn = pdev->devfn;
karg.bus = pdev->bus->number;
break;
}
- karg.base_io_addr = pdev->PCI_BASEADDR_START(0);
+ karg.base_io_addr = pci_resource_start(pdev, 0);
if ((int)ioc->chip_type <= (int) FC929)
karg.bus_phys_width = HP_BUS_WIDTH_UNK;
/* Copy the data from kernel memory to user memory
*/
- if (copy_to_user((char *)arg, &karg,
- sizeof(hp_host_info_t))) {
+ if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - "
"Unable to write out hp_host_info @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
static int
mptctl_hp_targetinfo(unsigned long arg)
{
- hp_target_info_t *uarg = (hp_target_info_t *) arg;
+ hp_target_info_t __user *uarg = (void __user *) arg;
SCSIDevicePage0_t *pg0_alloc;
SCSIDevicePage3_t *pg3_alloc;
MPT_ADAPTER *ioc;
if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) {
printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - "
"Unable to read in hp_host_targetinfo struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
/* Copy the data from kernel memory to user memory
*/
- if (copy_to_user((char *)arg, &karg, sizeof(hp_target_info_t))) {
+ if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) {
printk(KERN_ERR "%s@%d::mptctl_hp_target_info - "
"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
- __FILE__, __LINE__, (void*)uarg);
+ __FILE__, __LINE__, uarg);
return -EFAULT;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51)
-#define owner_THIS_MODULE .owner = THIS_MODULE,
-#else
-#define owner_THIS_MODULE
-#endif
-
static struct file_operations mptctl_fops = {
- owner_THIS_MODULE
+ .owner = THIS_MODULE,
.llseek = no_llseek,
- .read = mptctl_read,
- .write = mptctl_write,
.ioctl = mptctl_ioctl,
- .open = mptctl_open,
- .release = mptctl_release,
};
static struct miscdevice mptctl_miscdev = {
dctlprintk((KERN_INFO MYNAM "::compat_mptfwxfer_ioctl() called\n"));
- if (copy_from_user(&kfw32, (char *)arg, sizeof(kfw32)))
+ if (copy_from_user(&kfw32, (char __user *)arg, sizeof(kfw32)))
return -EFAULT;
/* Verify intended MPT adapter */
kfw.iocnum = iocnum;
kfw.fwlen = kfw32.fwlen;
- kfw.bufp = (void *)(unsigned long)kfw32.bufp;
+ kfw.bufp = compat_ptr(kfw32.bufp);
ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
- up(&mptctl_syscall_sem_ioc[iocp->id]);
+ up(&iocp->ioctl->sem_ioc);
return ret;
}
unsigned long arg, struct file *filp)
{
struct mpt_ioctl_command32 karg32;
- struct mpt_ioctl_command32 *uarg = (struct mpt_ioctl_command32 *) arg;
+ struct mpt_ioctl_command32 __user *uarg = (struct mpt_ioctl_command32 __user *) arg;
struct mpt_ioctl_command karg;
MPT_ADAPTER *iocp = NULL;
int iocnum, iocnumX;
dctlprintk((KERN_INFO MYNAM "::compat_mpt_command() called\n"));
- if (copy_from_user(&karg32, (char *)arg, sizeof(karg32)))
+ if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32)))
return -EFAULT;
/* Verify intended MPT adapter */
karg.maxSenseBytes = karg32.maxSenseBytes;
karg.dataSgeOffset = karg32.dataSgeOffset;
- karg.replyFrameBufPtr = (char *)(unsigned long)karg32.replyFrameBufPtr;
- karg.dataInBufPtr = (char *)(unsigned long)karg32.dataInBufPtr;
- karg.dataOutBufPtr = (char *)(unsigned long)karg32.dataOutBufPtr;
- karg.senseDataPtr = (char *)(unsigned long)karg32.senseDataPtr;
+ karg.replyFrameBufPtr = (char __user *)(unsigned long)karg32.replyFrameBufPtr;
+ karg.dataInBufPtr = (char __user *)(unsigned long)karg32.dataInBufPtr;
+ karg.dataOutBufPtr = (char __user *)(unsigned long)karg32.dataOutBufPtr;
+ karg.senseDataPtr = (char __user *)(unsigned long)karg32.senseDataPtr;
/* Pass new structure to do_mpt_command
*/
- ret = mptctl_do_mpt_command (karg, (char *) &uarg->MF, 0);
+ ret = mptctl_do_mpt_command (karg, &uarg->MF);
- up(&mptctl_syscall_sem_ioc[iocp->id]);
+ up(&iocp->ioctl->sem_ioc);
return ret;
}
#endif
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-int __init mptctl_init(void)
+/*
+ * mptctl_probe - Installs ioctl devices per bus.
+ * @pdev: Pointer to pci_dev structure
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+
+static int
+mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int err;
- int i;
- int where = 1;
int sz;
u8 *mem;
- MPT_ADAPTER *ioc = NULL;
- int iocnum;
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
- show_mptmod_ver(my_NAME, my_VERSION);
+ /*
+ * Allocate and inite a MPT_IOCTL structure
+ */
+ sz = sizeof (MPT_IOCTL);
+ mem = kmalloc(sz, GFP_KERNEL);
+ if (mem == NULL) {
+ err = -ENOMEM;
+ goto out_fail;
+ }
- for (i=0; i<MPT_MAX_ADAPTERS; i++) {
- sema_init(&mptctl_syscall_sem_ioc[i], 1);
+ memset(mem, 0, sz);
+ ioc->ioctl = (MPT_IOCTL *) mem;
+ ioc->ioctl->ioc = ioc;
+ init_timer (&ioc->ioctl->timer);
+ ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
+ ioc->ioctl->timer.function = mptctl_timer_expired;
+ init_timer (&ioc->ioctl->TMtimer);
+ ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
+ ioc->ioctl->TMtimer.function = mptctl_timer_expired;
+ sema_init(&ioc->ioctl->sem_ioc, 1);
+ return 0;
- ioc = NULL;
- if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
- (ioc == NULL)) {
- continue;
- }
- else {
- /* This adapter instance is found.
- * Allocate and inite a MPT_IOCTL structure
- */
- sz = sizeof (MPT_IOCTL);
- mem = kmalloc(sz, GFP_KERNEL);
- if (mem == NULL) {
- err = -ENOMEM;
- goto out_fail;
- }
+out_fail:
- memset(mem, 0, sz);
- ioc->ioctl = (MPT_IOCTL *) mem;
- ioc->ioctl->ioc = ioc;
- init_timer (&ioc->ioctl->timer);
- ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
- ioc->ioctl->timer.function = mptctl_timer_expired;
- init_timer (&ioc->ioctl->TMtimer);
- ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
- ioc->ioctl->TMtimer.function = mptctl_timer_expired;
- }
+ mptctl_remove(pdev);
+ return err;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptctl_remove - Removed ioctl devices
+ * @pdev: Pointer to pci_dev structure
+ *
+ *
+ */
+static void
+mptctl_remove(struct pci_dev *pdev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+
+ kfree ( ioc->ioctl );
+}
+
+static struct mpt_pci_driver mptctl_driver = {
+ .probe = mptctl_probe,
+ .remove = mptctl_remove,
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int __init mptctl_init(void)
+{
+ int err;
+ int where = 1;
+
+ show_mptmod_ver(my_NAME, my_VERSION);
+
+ if(mpt_device_driver_register(&mptctl_driver,
+ MPTCTL_DRIVER) != 0 ) {
+ dprintk((KERN_INFO MYNAM
+ ": failed to register dd callbacks\n"));
}
#ifdef CONFIG_COMPAT
unregister_ioctl32_conversion(HP_GETTARGETINFO);
#endif
- for (i=0; i<MPT_MAX_ADAPTERS; i++) {
- ioc = NULL;
- if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
- (ioc == NULL)) {
- continue;
- }
- else {
- if (ioc->ioctl) {
- kfree ( ioc->ioctl );
- ioc->ioctl = NULL;
- }
- }
- }
+ mpt_device_driver_deregister(MPTCTL_DRIVER);
+
return err;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-void mptctl_exit(void)
+static void mptctl_exit(void)
{
- int i;
- MPT_ADAPTER *ioc;
- int iocnum;
-
misc_deregister(&mptctl_miscdev);
printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",
mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
mpt_deregister(mptctl_id);
printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n");
+ mpt_device_driver_deregister(MPTCTL_DRIVER);
+
#ifdef CONFIG_COMPAT
unregister_ioctl32_conversion(MPTIOCINFO);
unregister_ioctl32_conversion(MPTIOCINFO1);
unregister_ioctl32_conversion(HP_GETTARGETINFO);
#endif
- /* Free allocated memory */
- for (i=0; i<MPT_MAX_ADAPTERS; i++) {
- ioc = NULL;
- if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
- (ioc == NULL)) {
- continue;
- }
- else {
- if (ioc->ioctl) {
- kfree ( ioc->ioctl );
- ioc->ioctl = NULL;
- }
- }
- }
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/