mirror of
https://github.com/SCST-project/scst.git
synced 2026-09-04 23:26:57 +00:00
Synchronize with Feral CVS repository:
Go for the gusto and merge multichan_development into the head branch. This will break FreeBSD and NetBSD ports for a while (yawn) and solaris is dubious anyway. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@260 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+167
-148
@@ -1,4 +1,4 @@
|
||||
/* $Id: isp_cb_ops.c,v 1.77 2007/08/29 20:37:08 mjacob Exp $ */
|
||||
/* $Id: isp_cb_ops.c,v 1.78 2007/12/02 22:02:06 mjacob Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2007 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -61,12 +61,6 @@
|
||||
#include "isp_ioctl.h"
|
||||
#include "exioct.h"
|
||||
|
||||
#if __GNUC__ >= 4
|
||||
#define BAD_COMPILER 1
|
||||
#else
|
||||
#define BAD_COMPILER 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
/*
|
||||
@@ -164,7 +158,9 @@ isplinux_proc_info(struct Scsi_Host *shp, char *buf, char **st, off_t off, int l
|
||||
io = len;
|
||||
} else if (strncmp(buf, "rescan", 6) == 0) {
|
||||
if (IS_FC(isp)) {
|
||||
SEND_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, NULL, 1, __FUNCTION__, __LINE__);
|
||||
for (io = 0; io < isp->isp_nchan; io++) {
|
||||
ISP_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, io), 1, __FUNCTION__, __LINE__);
|
||||
}
|
||||
io = len;
|
||||
}
|
||||
} else if (strncmp(buf, "lip", 3) == 0) {
|
||||
@@ -182,7 +178,7 @@ isplinux_proc_info(struct Scsi_Host *shp, char *buf, char **st, off_t off, int l
|
||||
return (-EINVAL);
|
||||
}
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
(void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
|
||||
(void) isp_control(isp, ISPCTL_RESET_BUS, bus);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
io = len;
|
||||
} else if (strncmp(buf, "devreset=", 9) == 0) {
|
||||
@@ -194,30 +190,17 @@ isplinux_proc_info(struct Scsi_Host *shp, char *buf, char **st, off_t off, int l
|
||||
}
|
||||
/* always bus 0 */
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
(void) isp_control(isp, ISPCTL_RESET_DEV, &dev);
|
||||
(void) isp_control(isp, ISPCTL_RESET_DEV, 0, dev);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
io = len;
|
||||
} else if (strncmp(buf, "reset", 5) == 0) {
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
io = isp_drain_reset(isp, "proc_reset");
|
||||
isp_reinit(isp);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
if (io == 0) {
|
||||
io = len;
|
||||
} else {
|
||||
io = -EIO;
|
||||
}
|
||||
} else if (strncmp(buf, "drain", 5) == 0) {
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
io = isp_drain(isp, "proc_reset");
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
if (io == 0) {
|
||||
io = len;
|
||||
} else {
|
||||
io = -EIO;
|
||||
}
|
||||
io = len;
|
||||
} else if (strncmp(buf, "bins", 4) == 0) {
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
memset(isp->isp_osinfo.bins, 0, sizeof (isp->isp_osinfo.bins));
|
||||
MEMZERO(isp->isp_osinfo.bins, sizeof (isp->isp_osinfo.bins));
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
io = len;
|
||||
}
|
||||
@@ -225,7 +208,7 @@ isplinux_proc_info(struct Scsi_Host *shp, char *buf, char **st, off_t off, int l
|
||||
else if (strncmp(buf, "fwcrash", 7) == 0) {
|
||||
if (IS_FC(isp)) {
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
SEND_THREAD_EVENT(isp, ISP_THREAD_FW_CRASH_DUMP, NULL, 0, __FUNCTION__, __LINE__);
|
||||
ISP_THREAD_EVENT(isp, ISP_THREAD_FW_CRASH_DUMP, NULL, 0, __FUNCTION__, __LINE__);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
io = len;
|
||||
}
|
||||
@@ -247,7 +230,7 @@ isplinux_proc_info(struct Scsi_Host *shp, char *buf, char **st, off_t off, int l
|
||||
#ifdef HBA_VERSION
|
||||
copy_info(&info, "\n HBA Version %s, built %s, %s", HBA_VERSION, __DATE__, __TIME__);
|
||||
#endif
|
||||
copy_info(&info, "\n DEVID %x role %d\n", isp->isp_osinfo.device_id, isp->isp_role);
|
||||
copy_info(&info, "\n DEVID %x\n", isp->isp_osinfo.device_id);
|
||||
copy_info(&info,
|
||||
" Interrupt Stats:\n"
|
||||
" total=0x%016llx bogus=0x%016llx\n"
|
||||
@@ -295,7 +278,7 @@ isplinux_proc_info(struct Scsi_Host *shp, char *buf, char **st, off_t off, int l
|
||||
}
|
||||
copy_info(&info, "\n");
|
||||
}
|
||||
copy_info(&info, "blocked %d draining %d qfdelay %d\n", isp->isp_blocked, isp->isp_draining, isp->isp_qfdelay);
|
||||
// copy_info(&info, "blocked %d qfdelay %d\n", isp->isp_blocked, isp->isp_qfdelay);
|
||||
|
||||
copy_info(&info, "\nxfer bins:\n");
|
||||
copy_info(&info, " <=1024 4096 32768 65536 131072 262144 524288 >0.5M\n");
|
||||
@@ -313,24 +296,27 @@ isplinux_proc_info(struct Scsi_Host *shp, char *buf, char **st, off_t off, int l
|
||||
#endif
|
||||
|
||||
if (IS_FC(isp)) {
|
||||
fcparam *fcp = FCPARAM(isp);
|
||||
copy_info(&info,
|
||||
"Self:\nHandle ID 0x%x PortID 0x%06x FW State 0x%x Loop State 0x%x\n",
|
||||
fcp->isp_loopid, fcp->isp_portid, fcp->isp_fwstate, fcp->isp_loopstate);
|
||||
copy_info(&info, "Port WWN 0x%016llx Node WWN 0x%016llx\n\n", ISP_PORTWWN(isp), ISP_NODEWWN(isp));
|
||||
copy_info(&info, "FC devices in port database:\n");
|
||||
for (i = 0; i < MAX_FC_TARG; i++) {
|
||||
if (fcp->portdb[i].state != FC_PORTDB_STATE_VALID) {
|
||||
continue;
|
||||
}
|
||||
if (fcp->portdb[i].ini_map_idx) {
|
||||
copy_info(&info, "\tdbidx %d handle 0x%x PortID 0x%06x role %s (target %d)\n\tPort WWN 0x%016llx Node WWN 0x%016llx\n\n",
|
||||
i, fcp->portdb[i].handle, fcp->portdb[i].portid, class3_roles[fcp->portdb[i].roles],
|
||||
fcp->portdb[i].ini_map_idx - 1, fcp->portdb[i].port_wwn, fcp->portdb[i].node_wwn);
|
||||
} else {
|
||||
copy_info(&info, "\tdbidx %d handle 0x%x PortID 0x%06x role %s\n\tPort WWN 0x%016llx Node WWN 0x%016llx\n\n",
|
||||
i, fcp->portdb[i].handle, fcp->portdb[i].portid, class3_roles[fcp->portdb[i].roles],
|
||||
fcp->portdb[i].port_wwn, fcp->portdb[i].node_wwn);
|
||||
int chan;
|
||||
for (chan = 0; chan < isp->isp_nchan; chan++) {
|
||||
fcparam *fcp = FCPARAM(isp, chan);
|
||||
copy_info(&info,
|
||||
"Self Channel %d:\nHandle ID 0x%x PortID 0x%06x FW State 0x%x Loop State 0x%x\n", chan,
|
||||
fcp->isp_loopid, fcp->isp_portid, fcp->isp_fwstate, fcp->isp_loopstate);
|
||||
copy_info(&info, "Port WWN 0x%016llx Node WWN 0x%016llx\n\n", fcp->isp_wwpn, fcp->isp_wwnn);
|
||||
copy_info(&info, "FC devices in port database:\n");
|
||||
for (i = 0; i < MAX_FC_TARG; i++) {
|
||||
if (fcp->portdb[i].state != FC_PORTDB_STATE_VALID) {
|
||||
continue;
|
||||
}
|
||||
if (fcp->portdb[i].ini_map_idx) {
|
||||
copy_info(&info, "\tdbidx %d handle 0x%x PortID 0x%06x role %s (target %d)\n\tPort WWN 0x%016llx Node WWN 0x%016llx\n\n",
|
||||
i, fcp->portdb[i].handle, fcp->portdb[i].portid, isp_class3_roles[fcp->portdb[i].roles],
|
||||
fcp->portdb[i].ini_map_idx - 1, fcp->portdb[i].port_wwn, fcp->portdb[i].node_wwn);
|
||||
} else {
|
||||
copy_info(&info, "\tdbidx %d handle 0x%x PortID 0x%06x role %s\n\tPort WWN 0x%016llx Node WWN 0x%016llx\n\n",
|
||||
i, fcp->portdb[i].handle, fcp->portdb[i].portid, isp_class3_roles[fcp->portdb[i].roles],
|
||||
fcp->portdb[i].port_wwn, fcp->portdb[i].node_wwn);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -417,9 +403,9 @@ static int
|
||||
isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
{
|
||||
ispsoftc_t *isp = fp->private_data;
|
||||
int rv, inarg, outarg;
|
||||
int i, rv, inarg, outarg;
|
||||
fcparam *fcp;
|
||||
uint16_t loopid;
|
||||
uint16_t loopid, chan;
|
||||
mbreg_t mbs;
|
||||
unsigned long flags;
|
||||
|
||||
@@ -531,24 +517,44 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
case ISP_RESCAN:
|
||||
if (IS_FC(isp)) {
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
SEND_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, NULL, 0, __FUNCTION__, __LINE__)
|
||||
for (i = 0; i < isp->isp_nchan; i++) {
|
||||
ISP_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, i), 1, __FUNCTION__, __LINE__);
|
||||
}
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
}
|
||||
break;
|
||||
|
||||
case ISP_GETROLE:
|
||||
outarg = isp->isp_role;
|
||||
if (COPYIN((void *)arg, &inarg, sizeof (inarg))) {
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
chan = inarg >> 16;
|
||||
if (chan >= isp->isp_nchan) {
|
||||
rv = -ENXIO;
|
||||
break;
|
||||
}
|
||||
if (IS_FC(isp)) {
|
||||
outarg = FCPARAM(isp, chan)->role;
|
||||
} else {
|
||||
outarg = SDPARAM(isp, chan)->role;
|
||||
}
|
||||
if (COPYOUT(&outarg, (void *)arg, sizeof (outarg))) {
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ISP_SETROLE:
|
||||
if (COPYIN((void *)arg, &inarg, sizeof (inarg))) {
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
chan = inarg >> 16;
|
||||
if (chan >= isp->isp_nchan) {
|
||||
rv = -ENXIO;
|
||||
break;
|
||||
}
|
||||
inarg &= 0xffff;
|
||||
if (inarg & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) {
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
@@ -556,37 +562,40 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
/*
|
||||
* Check to see if we're already in that role.
|
||||
*/
|
||||
if (isp->isp_role == inarg) {
|
||||
outarg = isp->isp_role;
|
||||
if (IS_FC(isp)) {
|
||||
if (FCPARAM(isp, chan)->role == inarg) {
|
||||
break;
|
||||
}
|
||||
outarg = FCPARAM(isp, chan)->role;
|
||||
if (COPYOUT(&outarg, (void *)arg, sizeof (outarg))) {
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
FCPARAM(isp, chan)->role = inarg;
|
||||
SET_DEFAULT_ROLE(isp, chan, FCPARAM(isp, chan)->role);
|
||||
} else {
|
||||
if (SDPARAM(isp, chan)->role == inarg) {
|
||||
break;
|
||||
}
|
||||
outarg = SDPARAM(isp, chan)->role;
|
||||
if (COPYOUT(&outarg, (void *)arg, sizeof (outarg))) {
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
SDPARAM(isp, chan)->role = inarg;
|
||||
SET_DEFAULT_ROLE(isp, chan, SDPARAM(isp, chan)->role);
|
||||
}
|
||||
/*FALLTHROUGH*/
|
||||
break;
|
||||
case ISP_RESETHBA:
|
||||
{
|
||||
ISP_LOCK_SOFTC(isp);
|
||||
if (c == ISP_SETROLE) {
|
||||
outarg = isp->isp_role;
|
||||
isp->isp_role = inarg;
|
||||
}
|
||||
if (isp_drain_reset(isp, "isp_ioctl")) {
|
||||
ISP_UNLK_SOFTC(isp);
|
||||
rv = -EIO;
|
||||
break;
|
||||
}
|
||||
isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
|
||||
isp_reset(isp);
|
||||
ISP_UNLK_SOFTC(isp);
|
||||
if (c == ISP_SETROLE && COPYOUT(&outarg, (void *)arg, sizeof (outarg))) {
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ISP_FC_LIP:
|
||||
ISP_LOCK_SOFTC(isp);
|
||||
if (isp_control(isp, ISPCTL_SEND_LIP, NULL)) {
|
||||
if (isp_control(isp, ISPCTL_SEND_LIP, 0)) {
|
||||
rv = -EIO;
|
||||
}
|
||||
ISP_UNLK_SOFTC(isp);
|
||||
@@ -601,29 +610,32 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
if (COPYIN((void *)arg, ifc, sizeof (*ifc))) {
|
||||
rv = EFAULT;
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
if (ifc->loopid < 0 || ifc->loopid >= MAX_FC_TARG) {
|
||||
rv = EINVAL;
|
||||
if (ifc->chan >= isp->isp_nchan) {
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (ifc->loopid >= MAX_FC_TARG) {
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ISP_LOCK_SOFTC(isp);
|
||||
lp = &FCPARAM(isp)->portdb[ifc->loopid];
|
||||
lp = &FCPARAM(isp, ifc->chan)->portdb[ifc->loopid];
|
||||
if (lp->state == FC_PORTDB_STATE_VALID) {
|
||||
ifc->role = lp->roles;
|
||||
ifc->loopid = lp->handle;
|
||||
ifc->portid = lp->portid;
|
||||
ifc->node_wwn = lp->node_wwn;
|
||||
ifc->port_wwn = lp->port_wwn;
|
||||
rv = 0;
|
||||
} else {
|
||||
rv = ENODEV;
|
||||
rv = -ENODEV;
|
||||
}
|
||||
ISP_UNLK_SOFTC(isp);
|
||||
if (rv == 0) {
|
||||
if (COPYOUT((void *)ifc, (void *)arg, sizeof (*ifc))) {
|
||||
rv = EFAULT;
|
||||
rv = -EFAULT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -631,22 +643,31 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
case ISP_FC_GETHINFO:
|
||||
{
|
||||
struct isp_hba_device local, *hba = &local;
|
||||
MEMZERO(hba, sizeof (*hba));
|
||||
if (COPYIN((void *)arg, hba, sizeof (*hba))) {
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
chan = hba->fc_channel;
|
||||
if (chan >= isp->isp_nchan) {
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ISP_LOCK_SOFTC(isp);
|
||||
hba->fc_nchannels = isp->isp_nchan;
|
||||
hba->fc_nports = ISP_CAP_2KLOGIN(isp)? 2048 : 256;
|
||||
hba->fc_fw_major = ISP_FW_MAJORX(isp->isp_fwrev);
|
||||
hba->fc_fw_minor = ISP_FW_MINORX(isp->isp_fwrev);
|
||||
hba->fc_fw_micro = ISP_FW_MICROX(isp->isp_fwrev);
|
||||
hba->fc_speed = FCPARAM(isp)->isp_gbspeed;
|
||||
hba->fc_scsi_supported = 1;
|
||||
hba->fc_topology = FCPARAM(isp)->isp_topo + 1;
|
||||
hba->fc_loopid = FCPARAM(isp)->isp_loopid;
|
||||
hba->nvram_node_wwn = FCPARAM(isp)->isp_wwnn_nvram;
|
||||
hba->nvram_port_wwn = FCPARAM(isp)->isp_wwpn_nvram;
|
||||
hba->active_node_wwn = ISP_NODEWWN(isp);
|
||||
hba->active_port_wwn = ISP_PORTWWN(isp);
|
||||
hba->fc_speed = FCPARAM(isp, chan)->isp_gbspeed;
|
||||
hba->fc_topology = FCPARAM(isp, chan)->isp_topo + 1;
|
||||
hba->fc_loopid = FCPARAM(isp, chan)->isp_loopid;
|
||||
hba->nvram_node_wwn = FCPARAM(isp, chan)->isp_wwnn_nvram;
|
||||
hba->nvram_port_wwn = FCPARAM(isp, chan)->isp_wwpn_nvram;
|
||||
hba->active_node_wwn = FCPARAM(isp, chan)->isp_wwnn;
|
||||
hba->active_port_wwn = FCPARAM(isp, chan)->isp_wwpn;
|
||||
ISP_UNLK_SOFTC(isp);
|
||||
if (COPYOUT(hba, (void *)arg, sizeof (*hba))) {
|
||||
rv = EFAULT;
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -657,19 +678,19 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
struct isp_fc_tsk_mgmt local, *fct = (struct isp_fc_tsk_mgmt *) &local;
|
||||
|
||||
if (IS_SCSI(isp)) {
|
||||
rv = EINVAL;
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (COPYIN((void *)arg, fct, sizeof (*fct))) {
|
||||
rv = EFAULT;
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
MEMZERO(&mbs, sizeof (mbs));
|
||||
needmarker = rv = 0;
|
||||
needmarker = 0;
|
||||
loopid = fct->loopid;
|
||||
if (FCPARAM(isp)->isp_2klogin == 0) {
|
||||
if (ISP_CAP_2KLOGIN(isp) == 0) {
|
||||
loopid <<= 8;
|
||||
}
|
||||
switch (fct->action) {
|
||||
@@ -702,7 +723,7 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
needmarker = 1;
|
||||
break;
|
||||
default:
|
||||
rv = EINVAL;
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (rv == 0) {
|
||||
@@ -710,12 +731,12 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
mbs.timeout = 2000000;
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
if (needmarker) {
|
||||
isp->isp_sendmarker |= 1;
|
||||
ISP_SET_SENDMARKER(isp, 0, 1);
|
||||
}
|
||||
rv = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
if (rv) {
|
||||
rv = EIO;
|
||||
rv = -EIO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -723,11 +744,11 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
case ISP_FC_GETDLIST:
|
||||
{
|
||||
isp_dlist_t *ua;
|
||||
uint16_t nph, nphs, nphe, lim, count;
|
||||
uint16_t nph, nphs, nphe, count, chan, lim;
|
||||
struct wwnpair pair, *uptr;
|
||||
|
||||
if (IS_SCSI(isp)) {
|
||||
rv = EINVAL;
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -735,14 +756,19 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
uptr = &ua->wwns[0];
|
||||
|
||||
if (COPYIN((void *)&ua->count, &lim, sizeof (lim))) {
|
||||
rv = EFAULT;
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FCPARAM(isp)->isp_2klogin == 0) {
|
||||
nphe = NPH_MAX;
|
||||
} else {
|
||||
if (COPYIN((void *)&ua->channel, &chan, sizeof (chan))) {
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ISP_CAP_2KLOGIN(isp)) {
|
||||
nphe = NPH_MAX_2K;
|
||||
} else {
|
||||
nphe = NPH_MAX;
|
||||
}
|
||||
if (IS_24XX(isp)) {
|
||||
nphs = 1;
|
||||
@@ -751,38 +777,30 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
}
|
||||
for (count = 0, nph = nphs; count < lim && nph != nphe; nph++) {
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
pair.wwnn = nph;
|
||||
if (isp_control(isp, ISPCTL_GET_NODENAME, &pair.wwnn)) {
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
continue;
|
||||
}
|
||||
pair.wwpn = nph;
|
||||
if (isp_control(isp, ISPCTL_GET_PORTNAME, &pair.wwpn)) {
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
continue;
|
||||
}
|
||||
rv = isp_control(isp, ISPCTL_GET_NAMES, chan, nph, &pair.wwnn, &pair.wwpn);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
if (pair.wwnn == 0 || pair.wwpn == 0) {
|
||||
if (rv || (pair.wwpn == INI_NONE && pair.wwnn == INI_NONE)) {
|
||||
rv = 0;
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
if (COPYOUT(&pair, (void *)uptr++, sizeof (pair))) {
|
||||
rv = EFAULT;
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (rv == 0) {
|
||||
if (COPYOUT(&count, (void *)&ua->count, sizeof (count))) {
|
||||
rv = EFAULT;
|
||||
rv = -EFAULT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rv = EINVAL;
|
||||
rv = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return(rv? -rv : 0);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -792,21 +810,18 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
|
||||
static int isp_exti_query(EXT_IOCTL *);
|
||||
static int isp_exti_setinstance(EXT_IOCTL *);
|
||||
static int isp_exti_fcct_passthru(EXT_IOCTL *);
|
||||
static int isp_exti_discover_luns(ispsoftc_t *, UINT64, UINT64, UINT16 *);
|
||||
static int isp_exti_discover_luns(ispsoftc_t *, int, UINT64, UINT64, UINT16 *);
|
||||
static void *isp_exti_usrptr(UINT64, UINT16);
|
||||
static int isp_exti_passthru(EXT_IOCTL *);
|
||||
static int isp_run_cmd(ispsoftc_t *, isp_xcmd_t *);
|
||||
|
||||
static int
|
||||
int
|
||||
isp_qlogic_ext_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
EXT_IOCTL ext;
|
||||
EXT_IOCTL *uext = (EXT_IOCTL *) arg;
|
||||
int rval;
|
||||
|
||||
if (BAD_COMPILER) {
|
||||
return (-EINVAL);
|
||||
}
|
||||
rval = 0;
|
||||
|
||||
if (COPYIN(uext, &ext, sizeof (ext))) {
|
||||
@@ -849,7 +864,6 @@ isp_qlogic_ext_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsign
|
||||
ext.Status = EXT_STATUS_UNSUPPORTED_VERSION;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We only count FC adapters.
|
||||
*/
|
||||
@@ -914,6 +928,7 @@ isp_exti_setinstance(EXT_IOCTL *ext)
|
||||
}
|
||||
api_isp = isplist[index];
|
||||
ext->HbaSelect = api_isp->isp_unit;
|
||||
api_channel = 0; /* XXXXXXXXXXXXXXXXXXXXXXX */
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -932,9 +947,9 @@ isp_exti_query(EXT_IOCTL *pext)
|
||||
return (0);
|
||||
}
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
fcp = FCPARAM(isp);
|
||||
fcp = FCPARAM(isp, api_channel);
|
||||
if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_LSCAN_DONE) {
|
||||
if (isp_fc_runstate(isp, 1000000) < 0) {
|
||||
if (isp_fc_runstate(isp, api_channel, 1000000) < 0) {
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
pext->Status = EXT_STATUS_PENDING;
|
||||
return (0);
|
||||
@@ -971,16 +986,16 @@ isp_exti_query(EXT_IOCTL *pext)
|
||||
EXT_HBA_PORT hbp;
|
||||
|
||||
MEMZERO(&hbp, sizeof (hbp));
|
||||
MAKE_NODE_NAME_FROM_WWN(hbp.WWPN, ISP_PORTWWN(isp));
|
||||
MAKE_NODE_NAME_FROM_WWN(hbp.WWPN, FCPARAM(isp, 0)->isp_wwpn);
|
||||
hbp.Id[1] = (fcp->isp_portid >> 16) & 0xff;
|
||||
hbp.Id[2] = (fcp->isp_portid >> 8) & 0xff;
|
||||
hbp.Id[3] = fcp->isp_portid & 0xff;
|
||||
|
||||
if (isp->isp_role & ISP_ROLE_TARGET) {
|
||||
if (FCPARAM(isp, 0)->role & ISP_ROLE_TARGET) {
|
||||
hbp.Type |= EXT_DEF_TARGET_DEV;
|
||||
}
|
||||
|
||||
if (isp->isp_role & ISP_ROLE_INITIATOR) {
|
||||
if (FCPARAM(isp, 0)->role & ISP_ROLE_INITIATOR) {
|
||||
hbp.Type |= EXT_DEF_INITIATOR_DEV;
|
||||
}
|
||||
|
||||
@@ -1015,9 +1030,9 @@ isp_exti_query(EXT_IOCTL *pext)
|
||||
hbp.PortActiveFC4Types = EXT_DEF_FC4_TYPE_SCSI;
|
||||
hbp.PortSupportedSpeed = EXT_DEF_PORTSPEED_1GBIT;
|
||||
if (IS_23XX(isp)) {
|
||||
hbp.PortSupportedSpeed = EXT_DEF_PORTSPEED_2GBIT;
|
||||
hbp.PortSupportedSpeed |= EXT_DEF_PORTSPEED_2GBIT;
|
||||
} else if (IS_24XX(isp)) {
|
||||
hbp.PortSupportedSpeed = EXT_DEF_PORTSPEED_4GBIT;
|
||||
hbp.PortSupportedSpeed |= EXT_DEF_PORTSPEED_2GBIT|EXT_DEF_PORTSPEED_4GBIT;
|
||||
}
|
||||
cl = min(pext->ResponseLen, sizeof (hbp));
|
||||
if (COPYOUT(&hbp, outaddr, cl)) {
|
||||
@@ -1141,7 +1156,7 @@ isp_exti_query(EXT_IOCTL *pext)
|
||||
wwpn = rlp->port_wwn;
|
||||
wwnn = rlp->node_wwn;
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
rval = isp_exti_discover_luns(isp, wwpn, wwnn, &tgt.LunCount);
|
||||
rval = isp_exti_discover_luns(isp, api_channel, wwpn, wwnn, &tgt.LunCount);
|
||||
if (rval) {
|
||||
break;
|
||||
}
|
||||
@@ -1185,16 +1200,16 @@ isp_exti_query(EXT_IOCTL *pext)
|
||||
|
||||
|
||||
#define IGPOFF 0 /* place CT Request itself is put */
|
||||
#define OGPOFF (ISP2100_SCRLEN >> 1) /* place CT Response itself is put */
|
||||
#define ZTXOFF (ISP2100_SCRLEN - (1 * QENTRY_LEN)) /* place where status entry for CT passthru request ends up */
|
||||
#define CTXOFF (ISP2100_SCRLEN - (2 * QENTRY_LEN)) /* place where CT passthru request is put */
|
||||
#define OGPOFF (ISP_FC_SCRLEN >> 1) /* place CT Response itself is put */
|
||||
#define ZTXOFF (ISP_FC_SCRLEN - (1 * QENTRY_LEN)) /* place where status entry for CT passthru request ends up */
|
||||
#define CTXOFF (ISP_FC_SCRLEN - (2 * QENTRY_LEN)) /* place where CT passthru request is put */
|
||||
|
||||
static int
|
||||
isp_exti_fcct_passthru(EXT_IOCTL *pext)
|
||||
{
|
||||
ispsoftc_t *isp = api_isp;
|
||||
isp_plcmd_t p;
|
||||
fcparam *fcp = FCPARAM(isp);
|
||||
fcparam *fcp = FCPARAM(isp, 0);
|
||||
mbreg_t mbs;
|
||||
uint8_t qe[QENTRY_LEN], *scp;
|
||||
uint16_t handle;
|
||||
@@ -1209,11 +1224,11 @@ isp_exti_fcct_passthru(EXT_IOCTL *pext)
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (pext->RequestLen > (ISP2100_SCRLEN >> 1)) {
|
||||
if (pext->RequestLen > (ISP_FC_SCRLEN >> 1)) {
|
||||
pext->Status = EXT_STATUS_NO_MEMORY;
|
||||
return (0);
|
||||
}
|
||||
if (pext->ResponseLen > ((ISP2100_SCRLEN >> 1) - (2 * QENTRY_LEN))) {
|
||||
if (pext->ResponseLen > ((ISP_FC_SCRLEN >> 1) - (2 * QENTRY_LEN))) {
|
||||
pext->Status = EXT_STATUS_NO_MEMORY;
|
||||
return (0);
|
||||
}
|
||||
@@ -1247,6 +1262,7 @@ isp_exti_fcct_passthru(EXT_IOCTL *pext)
|
||||
/*
|
||||
* Login into the Management Server
|
||||
*/
|
||||
p.channel = api_channel;
|
||||
p.handle = NIL_HANDLE;
|
||||
p.portid = MANAGEMENT_PORT_ID;
|
||||
p.flags = PLOGX_FLG_CMD_PLOGI;
|
||||
@@ -1263,7 +1279,7 @@ isp_exti_fcct_passthru(EXT_IOCTL *pext)
|
||||
* Acquire Scratch
|
||||
*/
|
||||
MEMZERO(qe, QENTRY_LEN);
|
||||
FC_SCRATCH_ACQUIRE(isp);
|
||||
FC_SCRATCH_ACQUIRE(isp, 0);
|
||||
scp = fcp->isp_scratch;
|
||||
|
||||
MEMCPY(&scp[IGPOFF], localmem, pext->RequestLen);
|
||||
@@ -1328,7 +1344,7 @@ isp_exti_fcct_passthru(EXT_IOCTL *pext)
|
||||
ms->ms_header.rqs_entry_count = 1;
|
||||
ms->ms_header.rqs_entry_type = RQSTYPE_MS_PASSTHRU;
|
||||
ms->ms_handle = 0xffffffff;
|
||||
if (FCPARAM(isp)->isp_2klogin) {
|
||||
if (ISP_CAP_2KLOGIN(isp)) {
|
||||
ms->ms_nphdl = handle;
|
||||
} else {
|
||||
ms->ms_nphdl = handle << 8;
|
||||
@@ -1376,11 +1392,12 @@ out1:
|
||||
/*
|
||||
* Release Scratch
|
||||
*/
|
||||
FC_SCRATCH_RELEASE(isp);
|
||||
FC_SCRATCH_RELEASE(isp, 0);
|
||||
|
||||
/*
|
||||
* Log out of the Management Server
|
||||
*/
|
||||
p.channel = api_channel;
|
||||
p.handle = handle;
|
||||
p.portid = MANAGEMENT_PORT_ID;
|
||||
p.flags = PLOGX_FLG_CMD_LOGO|PLOGX_FLG_EXPLICIT_LOGO;
|
||||
@@ -1493,7 +1510,7 @@ isp_exti_passthru(EXT_IOCTL *pext)
|
||||
MAKE_WWN_FROM_NODE_NAME(wwnn, fcx.FCScsiAddr.DestAddr.WWNN);
|
||||
} else if (fcx.FCScsiAddr.DestType == EXT_DEF_DESTTYPE_WWPN) {
|
||||
MAKE_WWN_FROM_NODE_NAME(wwpn, fcx.FCScsiAddr.DestAddr.WWPN);
|
||||
} else if (fcx.FCScsiAddr.DestType == EXT_DEF_DESTTYPE_WWNN) {
|
||||
} else if (fcx.FCScsiAddr.DestType == EXT_DEF_DESTTYPE_PORTID) {
|
||||
portid = (fcx.FCScsiAddr.DestAddr.Id[1] << 16) | (fcx.FCScsiAddr.DestAddr.Id[2] << 8) | (fcx.FCScsiAddr.DestAddr.Id[3]);
|
||||
}
|
||||
/*
|
||||
@@ -1501,7 +1518,7 @@ isp_exti_passthru(EXT_IOCTL *pext)
|
||||
* so we know how to send the command.
|
||||
*/
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
for (lp = &FCPARAM(isp)->portdb[0]; lp < &FCPARAM(isp)->portdb[MAX_FC_TARG]; lp++) {
|
||||
for (lp = &FCPARAM(isp, api_channel)->portdb[0]; lp < &FCPARAM(isp, api_channel)->portdb[MAX_FC_TARG]; lp++) {
|
||||
if (lp->state != FC_PORTDB_STATE_VALID) {
|
||||
continue;
|
||||
}
|
||||
@@ -1519,7 +1536,7 @@ isp_exti_passthru(EXT_IOCTL *pext)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lp == &FCPARAM(isp)->portdb[MAX_FC_TARG]) {
|
||||
if (lp == &FCPARAM(isp, api_channel)->portdb[MAX_FC_TARG]) {
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
pext->Status = EXT_STATUS_DEV_NOT_FOUND;
|
||||
if (bufp) {
|
||||
@@ -1531,6 +1548,7 @@ isp_exti_passthru(EXT_IOCTL *pext)
|
||||
wwpn = lp->port_wwn;
|
||||
cmd.handle = lp->handle;
|
||||
cmd.portid = lp->portid;
|
||||
cmd.channel = api_channel;
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
|
||||
MEMCPY(cmd.fcd.beg.cdb, fcx.Cdb, min(EXT_DEF_SCSI_PASSTHRU_CDB_LENGTH, sizeof (cmd.fcd.beg.cdb)));
|
||||
@@ -1572,17 +1590,18 @@ isp_exti_passthru(EXT_IOCTL *pext)
|
||||
#define RPT_LUN_SIZE 1024
|
||||
|
||||
static int
|
||||
isp_exti_discover_luns(ispsoftc_t *isp, UINT64 wwpn, UINT64 wwnn, UINT16 *nluns)
|
||||
isp_exti_discover_luns(ispsoftc_t *isp, int chan, UINT64 wwpn, UINT64 wwnn, UINT16 *nluns)
|
||||
{
|
||||
isp_xcmd_t cmd;
|
||||
int status, nent, i, hilun;
|
||||
unsigned long flags;
|
||||
fcparam *fcp = FCPARAM(isp, chan);
|
||||
fcportdb_t *lp;
|
||||
uint8_t *bufp;
|
||||
|
||||
MEMZERO(&cmd, sizeof (isp_xcmd_t));
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
for (lp = &FCPARAM(isp)->portdb[0]; lp < &FCPARAM(isp)->portdb[MAX_FC_TARG]; lp++) {
|
||||
for (lp = &fcp->portdb[0]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
|
||||
if (lp->state != FC_PORTDB_STATE_VALID) {
|
||||
continue;
|
||||
}
|
||||
@@ -1590,7 +1609,7 @@ isp_exti_discover_luns(ispsoftc_t *isp, UINT64 wwpn, UINT64 wwnn, UINT16 *nluns)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lp == &FCPARAM(isp)->portdb[MAX_FC_TARG]) {
|
||||
if (lp == &fcp->portdb[MAX_FC_TARG]) {
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
return (-ENODEV);
|
||||
}
|
||||
@@ -1731,10 +1750,10 @@ isp_run_cmd(ispsoftc_t *isp, isp_xcmd_t *cmd)
|
||||
reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
|
||||
t2->req_flags = REQFLAG_STAG;
|
||||
|
||||
if (FCPARAM(isp)->isp_2klogin) {
|
||||
if (ISP_CAP_2KLOGIN(isp)) {
|
||||
((ispreqt2e_t *)reqp)->req_target = cmd->handle;
|
||||
((ispreqt2e_t *)reqp)->req_scclun = cmd->lun;
|
||||
} else if (FCPARAM(isp)->isp_sccfw) {
|
||||
} else if (ISP_CAP_SCCFW(isp)) {
|
||||
t2->req_target = cmd->handle;
|
||||
t2->req_scclun = cmd->lun;
|
||||
} else {
|
||||
|
||||
+17
-17
@@ -1,4 +1,4 @@
|
||||
/* $Id: isp_ioctl.h,v 1.23 2007/07/19 01:58:40 mjacob Exp $ */
|
||||
/* $Id: isp_ioctl.h,v 1.24 2007/12/02 22:02:06 mjacob Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2007 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -138,7 +138,8 @@ typedef struct {
|
||||
*/
|
||||
struct isp_fc_device {
|
||||
uint32_t loopid; /* 0..255/2048 */
|
||||
uint32_t : 6,
|
||||
uint32_t
|
||||
chan : 6,
|
||||
role : 2,
|
||||
portid : 24; /* 24 bit Port ID */
|
||||
uint64_t node_wwn;
|
||||
@@ -157,20 +158,17 @@ struct isp_fc_device {
|
||||
* topology and capabilities.
|
||||
*/
|
||||
struct isp_hba_device {
|
||||
uint32_t
|
||||
: 8,
|
||||
: 4,
|
||||
uint32_t : 8,
|
||||
fc_speed : 4, /* Gbps */
|
||||
: 2,
|
||||
fc_class2 : 1,
|
||||
fc_ip_supported : 1,
|
||||
fc_scsi_supported : 1,
|
||||
: 1,
|
||||
fc_topology : 3,
|
||||
fc_loopid : 8;
|
||||
uint8_t fc_fw_major;
|
||||
uint8_t fc_fw_minor;
|
||||
uint8_t fc_fw_micro;
|
||||
uint8_t reserved;
|
||||
fc_channel : 8, /* channel selector */
|
||||
fc_loopid : 16; /* loop id selector */
|
||||
uint8_t fc_fw_major; /* firmware major version */
|
||||
uint8_t fc_fw_minor; /* firmware minor version */
|
||||
uint8_t fc_fw_micro; /* firmware micro version */
|
||||
uint8_t fc_nchannels; /* number of supported channels */
|
||||
uint16_t fc_nports; /* number of supported ports */
|
||||
uint64_t nvram_node_wwn;
|
||||
uint64_t nvram_port_wwn;
|
||||
uint64_t active_node_wwn;
|
||||
@@ -183,7 +181,9 @@ struct isp_hba_device {
|
||||
#define ISP_TOPO_NPORT 3 /* N-port */
|
||||
#define ISP_TOPO_FPORT 4 /* F-port */
|
||||
|
||||
#define ISP_FC_GETHINFO (ISP_IOC|12)
|
||||
/* do not use this one any more */
|
||||
/* #define ISP_FC_GETHINFO (ISP_IOC|12) */
|
||||
#define ISP_FC_GETHINFO (ISP_IOC|13)
|
||||
|
||||
/*
|
||||
* Set Active WWNN/WWPN
|
||||
@@ -217,13 +217,13 @@ struct isp_fc_tsk_mgmt {
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t count;
|
||||
uint16_t reserved;
|
||||
uint16_t channel;
|
||||
struct wwnpair {
|
||||
uint64_t wwnn;
|
||||
uint64_t wwpn;
|
||||
} wwns[1];
|
||||
} isp_dlist_t;
|
||||
/* don't recycle 22 */
|
||||
/* do not recycle 22 */
|
||||
#define ISP_FC_GETDLIST (ISP_IOC | 23)
|
||||
/*
|
||||
* vim:ts=4:sw=4:expandtab
|
||||
|
||||
+1299
-884
File diff suppressed because it is too large
Load Diff
+156
-171
@@ -1,4 +1,4 @@
|
||||
/* $Id: isp_linux.h,v 1.143 2007/11/15 18:41:47 mjacob Exp $ */
|
||||
/* $Id: isp_linux.h,v 1.144 2007/12/02 22:02:06 mjacob Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2007 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -71,8 +71,8 @@
|
||||
#define KERNEL_VERSION(v,p,s) (((v)<<16)+(p<<8)+s)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
#error "Only Linux 2.6 kernels are supported with this driver"
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,7,0)
|
||||
#error "Only Linux 2.5/2.6 kernels are supported with this driver"
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
|
||||
@@ -166,13 +166,13 @@ typedef struct scsi_host_template Scsi_Host_Template;
|
||||
#define ISP_SBUS_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
#define ISP_PLATFORM_VERSION_MAJOR 6
|
||||
#define ISP_PLATFORM_VERSION_MINOR 0
|
||||
|
||||
#ifndef ISP_NAME
|
||||
#define ISP_NAME "isp"
|
||||
#endif
|
||||
|
||||
#define ISP_PLATFORM_VERSION_MAJOR 5
|
||||
#define ISP_PLATFORM_VERSION_MINOR 0
|
||||
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
@@ -220,6 +220,15 @@ typedef struct scsi_host_template Scsi_Host_Template;
|
||||
#define u_char unsigned char
|
||||
typedef u_long vm_offset_t;
|
||||
|
||||
/* bit map using 8 bit arrays */
|
||||
typedef uint8_t isp_bmap_t;
|
||||
#define _ISP_WIX(isp, ix) (ix >> 3)
|
||||
#define _ISP_BIX(isp, ix) (1 << (ix & 0x7))
|
||||
#define ISP_NBPIDX(x) ((x + 7) / 8) /* index width from bits */
|
||||
#define ISP_BTST(map, ix) (((map)[_ISP_WIX(isp, ix)] & _ISP_BIX(isp, ix)) != 0)
|
||||
#define ISP_BSET(map, ix) (map)[_ISP_WIX(isp, ix)] |= _ISP_BIX(isp, ix)
|
||||
#define ISP_BCLR(map, ix) (map)[_ISP_WIX(isp, ix)] &= ~_ISP_BIX(isp, ix)
|
||||
|
||||
#ifdef ISP_TARGET_MODE
|
||||
|
||||
#include "isp_tpublic.h"
|
||||
@@ -231,13 +240,6 @@ typedef u_long vm_offset_t;
|
||||
#define N_NOTIFIES 256
|
||||
#define DEFAULT_INQSIZE 32
|
||||
|
||||
#define WIX(ix) (ix >> 5)
|
||||
#define BIX(ix) (1 << (ix & 0x1f))
|
||||
|
||||
#define LUN_BTST(bmap, ix) ((bmap[WIX(ix)] & BIX(ix)) != 0)
|
||||
#define LUN_BSET(bmap, ix) bmap[WIX(ix)] |= BIX(ix)
|
||||
#define LUN_BCLR(bmap, ix) bmap[WIX(ix)] &= ~BIX(ix)
|
||||
|
||||
typedef struct isp_notify isp_notify_t;
|
||||
|
||||
#define cd_action cd_lreserved[0].shorts[0]
|
||||
@@ -269,6 +271,7 @@ typedef struct {
|
||||
} tgt_auxcmd_t;
|
||||
#define N_TGT_AUX 32
|
||||
|
||||
#define ISP_CT_TIMEOUT 120
|
||||
#endif /* ISP_TARGET_MODE */
|
||||
|
||||
typedef struct {
|
||||
@@ -280,22 +283,27 @@ typedef struct {
|
||||
ISP_THREAD_LOGOUT,
|
||||
ISP_THREAD_FINDIID,
|
||||
ISP_THREAD_TERMINATE,
|
||||
ISP_THREAD_RESTART_AT7,
|
||||
ISP_THREAD_FC_PUTBACK,
|
||||
ISP_THREAD_EXIT=99
|
||||
} thread_action;
|
||||
void * arg;
|
||||
struct semaphore * thread_waiter;
|
||||
int count;
|
||||
} isp_thread_action_t;
|
||||
#define MAX_THREAD_ACTION 32
|
||||
#define MAX_THREAD_ACTION 128
|
||||
#define MAX_FC_CHAN 128
|
||||
|
||||
#define ISP_HOST2ISP(host) (ispsoftc_t *) host->hostdata
|
||||
|
||||
union pstore;
|
||||
struct isposinfo {
|
||||
struct Scsi_Host * host;
|
||||
u32 mcorig; /* original maxcmds */
|
||||
void *device; /* hardware device structure */
|
||||
Scsi_Cmnd *wqnext, *wqtail;
|
||||
Scsi_Cmnd *dqnext, *dqtail;
|
||||
union pstore *storep;
|
||||
void * storep;
|
||||
size_t storep_amt;
|
||||
size_t param_amt;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *pdp;
|
||||
#endif
|
||||
@@ -304,46 +312,41 @@ struct isposinfo {
|
||||
u16 wqcnt;
|
||||
u16 wqhiwater;
|
||||
u16 hiwater;
|
||||
int role;
|
||||
struct timer_list timer;
|
||||
struct timer_list _mbtimer;
|
||||
struct semaphore _mbox_sem;
|
||||
struct semaphore _mbox_c_sem;
|
||||
struct semaphore _fcs_sem;
|
||||
struct timer_list mbtimer;
|
||||
struct semaphore mbox_sem;
|
||||
struct semaphore mbox_c_sem;
|
||||
struct semaphore fcs_sem;
|
||||
spinlock_t slock;
|
||||
unsigned volatile int
|
||||
_downcnt : 8,
|
||||
: 2,
|
||||
_qfdelay : 6,
|
||||
: 5,
|
||||
_isopen : 1,
|
||||
_deadloop : 1,
|
||||
_draining : 1,
|
||||
_blocked : 1,
|
||||
_fcrswdog : 1,
|
||||
_fcrspend : 1,
|
||||
_dogactive : 1,
|
||||
_mboxcmd_done : 1,
|
||||
_mbox_waiting : 1,
|
||||
_mbintsok : 1,
|
||||
_intsok : 1;
|
||||
void * misc[8]; /* private platform variant usage */
|
||||
struct task_struct * task_thread;
|
||||
struct semaphore * task_request;
|
||||
struct semaphore * task_ctl_sem;
|
||||
: 20,
|
||||
dogcnt : 5,
|
||||
isopen : 1,
|
||||
task_active : 1,
|
||||
dogactive : 1,
|
||||
mboxcmd_done : 1,
|
||||
mbox_waiting : 1,
|
||||
mbintsok : 1,
|
||||
intsok : 1;
|
||||
u16 frame_size;
|
||||
u16 exec_throttle;
|
||||
struct semaphore trq;
|
||||
struct semaphore tcs;
|
||||
spinlock_t tlock;
|
||||
unsigned int nt_actions;
|
||||
unsigned int device_id;
|
||||
isp_thread_action_t t_actions[MAX_THREAD_ACTION];
|
||||
#ifdef ISP_TARGET_MODE
|
||||
uint32_t rollinfo : 16,
|
||||
u32 isget : 16,
|
||||
rstatus : 8,
|
||||
: 6,
|
||||
isget : 1,
|
||||
: 7,
|
||||
hcb : 1;
|
||||
struct semaphore tgt_inisem;
|
||||
struct semaphore * rsemap;
|
||||
tgt_enalun_t * luns; /* enabled { lun, port } tuples */
|
||||
struct tmd_cmd * pending_t; /* pending list of commands going upstream */
|
||||
struct tmd_cmd * waiting_t; /* pending list of commands waiting to be fleshed out */
|
||||
struct tmd_cmd * tfreelist; /* freelist head */
|
||||
struct tmd_cmd * bfreelist; /* freelist tail */
|
||||
struct tmd_cmd * pool; /* pool itself */
|
||||
@@ -357,75 +360,56 @@ struct isposinfo {
|
||||
* to manage those commands.
|
||||
*/
|
||||
tgt_auxcmd_t auxinfo[N_TGT_AUX];
|
||||
uint32_t auxbmap[N_TGT_AUX >> 5];
|
||||
uint8_t inqdata[DEFAULT_INQSIZE];
|
||||
isp_bmap_t auxbmap[ISP_NBPIDX(N_TGT_AUX)];
|
||||
u8 inqdata[DEFAULT_INQSIZE];
|
||||
|
||||
uint64_t cmds_started;
|
||||
uint64_t cmds_completed;
|
||||
struct {
|
||||
uint32_t portid;
|
||||
uint32_t nphdl;
|
||||
uint64_t iid;
|
||||
#define TM_CS 256
|
||||
} tgt_cache[TM_CS];
|
||||
u64 cmds_started;
|
||||
u64 cmds_completed;
|
||||
#endif
|
||||
};
|
||||
#define mbtimer isp_osinfo._mbtimer
|
||||
#define dogactive isp_osinfo._dogactive
|
||||
#define mbox_sem isp_osinfo._mbox_sem
|
||||
#define mbox_c_sem isp_osinfo._mbox_c_sem
|
||||
#define fcs_sem isp_osinfo._fcs_sem
|
||||
#define mbintsok isp_osinfo._mbintsok
|
||||
#define intsok isp_osinfo._intsok
|
||||
#define mbox_waiting isp_osinfo._mbox_waiting
|
||||
#define mboxcmd_done isp_osinfo._mboxcmd_done
|
||||
#define isp_pbuf isp_osinfo._pbuf
|
||||
#define isp_fcrspend isp_osinfo._fcrspend
|
||||
#define isp_fcrswdog isp_osinfo._fcrswdog
|
||||
#define isp_qfdelay isp_osinfo._qfdelay
|
||||
#define isp_blocked isp_osinfo._blocked
|
||||
#define isp_draining isp_osinfo._draining
|
||||
#define isp_downcnt isp_osinfo._downcnt
|
||||
#define isp_isopen isp_osinfo._isopen
|
||||
#define isp_deadloop isp_osinfo._deadloop
|
||||
#define mbtimer isp_osinfo.mbtimer
|
||||
#define dogactive isp_osinfo.dogactive
|
||||
#define mbox_sem isp_osinfo.mbox_sem
|
||||
#define mbox_c_sem isp_osinfo.mbox_c_sem
|
||||
#define fcs_sem isp_osinfo.fcs_sem
|
||||
#define mbintsok isp_osinfo.mbintsok
|
||||
#define intsok isp_osinfo.intsok
|
||||
#define mbox_waiting isp_osinfo.mbox_waiting
|
||||
#define mboxcmd_done isp_osinfo.mboxcmd_done
|
||||
#define isp_isopen isp_osinfo.isopen
|
||||
|
||||
#define SEND_THREAD_EVENT(isp, action, a, dowait, file, line) \
|
||||
if (isp->isp_osinfo.task_request) { \
|
||||
unsigned long flags; \
|
||||
spin_lock_irqsave(&isp->isp_osinfo.tlock, flags); \
|
||||
if (isp->isp_osinfo.nt_actions >= MAX_THREAD_ACTION) { \
|
||||
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); \
|
||||
isp_prt(isp, ISP_LOGERR, "thread event overflow"); \
|
||||
} else if (action == ISP_THREAD_FC_RESCAN && isp->isp_fcrspend) { \
|
||||
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); \
|
||||
} else { \
|
||||
DECLARE_MUTEX_LOCKED(sem); \
|
||||
isp_thread_action_t *tap; \
|
||||
tap = &isp->isp_osinfo.t_actions[isp->isp_osinfo.nt_actions++]; \
|
||||
tap->thread_action = action; \
|
||||
tap->arg = a; \
|
||||
if (dowait) { \
|
||||
tap->thread_waiter = &sem; \
|
||||
} else { \
|
||||
tap->thread_waiter = 0; \
|
||||
} \
|
||||
if (action == ISP_THREAD_FC_RESCAN) { \
|
||||
isp->isp_fcrspend = 1; \
|
||||
} \
|
||||
up(isp->isp_osinfo.task_request); \
|
||||
if (dowait) { \
|
||||
isp_prt(isp, ISP_LOGDEBUG1, \
|
||||
"action %d sent from %s:%d and now waiting on %p", action, file, line, &sem); \
|
||||
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); \
|
||||
down(&sem); \
|
||||
isp_prt(isp, ISP_LOGDEBUG1, \
|
||||
"action %d done from %p", action, &sem); \
|
||||
} else { \
|
||||
isp_prt(isp, ISP_LOGDEBUG1, "action %d from %s:%d sent", action, file, line); \
|
||||
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#define ISP_THREAD_EXEC(x) \
|
||||
sema_init(&(x)->isp_osinfo.tcs, 0); \
|
||||
kernel_thread(isp_task_thread, (x), 0); \
|
||||
down(&isp->isp_osinfo.tcs)
|
||||
|
||||
#define ISP_THREAD_IACK(x) \
|
||||
sema_init(&(x)->isp_osinfo.trq, 0); \
|
||||
(x)->isp_osinfo.task_active = 1; \
|
||||
up(&(x)->isp_osinfo.tcs)
|
||||
|
||||
#define ISP_THREAD_WAIT(x) down_interruptible(&(x)->isp_osinfo.trq)
|
||||
|
||||
#define ISP_THREAD_EVENT isp_thread_event
|
||||
|
||||
#define ISP_THREAD_WAKE(x) up(&(x)->isp_osinfo.trq)
|
||||
|
||||
#define ISP_THREAD_KILL(x) \
|
||||
{ \
|
||||
unsigned long _fl; \
|
||||
spin_lock_irqsave(&(x)->isp_osinfo.tlock, _fl); \
|
||||
if ((x)->isp_osinfo.task_active) { \
|
||||
sema_init(&(x)->isp_osinfo.tcs, 0); \
|
||||
(x)->isp_osinfo.task_active = 0; \
|
||||
up(&(x)->isp_osinfo.trq); \
|
||||
spin_unlock_irqrestore(&(x)->isp_osinfo.tlock, _fl); \
|
||||
down(&(x)->isp_osinfo.tcs); \
|
||||
} else { \
|
||||
spin_unlock_irqrestore(&(x)->isp_osinfo.tlock, _fl); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ISP_THREAD_XACK(x) up(&(x)->isp_osinfo.tcs)
|
||||
|
||||
/*
|
||||
* Locking macros...
|
||||
@@ -455,11 +439,11 @@ if (isp->isp_osinfo.task_request) { \
|
||||
* Required Macros/Defines
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_HIGHMEM64G) || defined(CONFIG_X86_64)
|
||||
#if defined(CONFIG_HIGHMEM64G) || defined(CONFIG_X86_64) /* BOGUS */
|
||||
#define ISP_DAC_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
#define ISP2100_SCRLEN 0x1000
|
||||
#define ISP_FC_SCRLEN 0x1000
|
||||
|
||||
#define MEMZERO(b, a) memset(b, 0, a)
|
||||
#define MEMCPY memcpy
|
||||
@@ -499,7 +483,7 @@ if (isp->isp_osinfo.task_request) { \
|
||||
isp->mboxcmd_done = 1
|
||||
#define MBOX_RELEASE(isp) up(&isp->mbox_sem)
|
||||
|
||||
#define FC_SCRATCH_ACQUIRE(isp) \
|
||||
#define FC_SCRATCH_ACQUIRE(isp, chan) \
|
||||
/* \
|
||||
* Try and acquire semaphore the easy way first- \
|
||||
* with our lock already held. \
|
||||
@@ -516,7 +500,7 @@ if (isp->isp_osinfo.task_request) { \
|
||||
ISP_IGET_LK_SOFTC(isp); \
|
||||
}
|
||||
|
||||
#define FC_SCRATCH_RELEASE(isp) up(&isp->fcs_sem)
|
||||
#define FC_SCRATCH_RELEASE(isp, chan) up(&isp->fcs_sem)
|
||||
|
||||
|
||||
#ifndef SCSI_GOOD
|
||||
@@ -591,14 +575,16 @@ if (isp->isp_osinfo.task_request) { \
|
||||
|
||||
#define XS_SET_STATE_STAT(a, b, c)
|
||||
|
||||
#define DEFAULT_IID isplinux_default_id
|
||||
#define DEFAULT_LOOPID isplinux_default_id
|
||||
#define DEFAULT_NODEWWN(isp) (isp)->isp_defwwnn
|
||||
#define DEFAULT_PORTWWN(isp) (isp)->isp_defwwpn
|
||||
#define DEFAULT_FRAME_SIZE(isp) (IS_SCSI(isp)? 0 : isp->isp_osinfo.storep->fibre_scsi.default_frame_size)
|
||||
#define DEFAULT_EXEC_ALLOC(isp) (IS_SCSI(isp)? 0 : isp->isp_osinfo.storep->fibre_scsi.default_exec_alloc)
|
||||
#define ISP_NODEWWN(isp) (isp)->isp_actvwwnn
|
||||
#define ISP_PORTWWN(isp) (isp)->isp_actvwwpn
|
||||
#define GET_DEFAULT_ROLE isplinux_get_default_role
|
||||
#define SET_DEFAULT_ROLE isplinux_set_default_role
|
||||
#define DEFAULT_IID isplinux_get_default_id
|
||||
#define DEFAULT_LOOPID isplinux_get_default_id
|
||||
#define DEFAULT_FRAMESIZE(isp) isp->isp_osinfo.frame_size
|
||||
#define DEFAULT_EXEC_THROTTLE(isp) isp->isp_osinfo.exec_throttle
|
||||
#define DEFAULT_NODEWWN(isp, chan) isplinux_default_wwn(isp, chan, 0, 1)
|
||||
#define DEFAULT_PORTWWN(isp, chan) isplinux_default_wwn(isp, chan, 0, 0)
|
||||
#define ACTIVE_NODEWWN(isp, chan) isplinux_default_wwn(isp, chan, 1, 1)
|
||||
#define ACTIVE_PORTWWN(isp, chan) isplinux_default_wwn(isp, chan, 1, 0)
|
||||
|
||||
#define ISP_IOXPUT_8(isp, s, d) *(d) = s
|
||||
#define ISP_IOXPUT_16(isp, s, d) *(d) = cpu_to_le16(s)
|
||||
@@ -655,34 +641,28 @@ void isp_prt(ispsoftc_t *, int level, const char *, ...);
|
||||
*/
|
||||
|
||||
/*
|
||||
* Parameter storage. The order of tags is important- sdparam && fcp
|
||||
* must come first because isp->isp_params is set to point there...
|
||||
* Parameter and platform per-channel storage.
|
||||
*/
|
||||
union pstore {
|
||||
struct {
|
||||
sdparam _sdp[2]; /* they need to be sequential */
|
||||
u_char psc_opts[2][MAX_TARGETS];
|
||||
u_char dutydone;
|
||||
} parallel_scsi;
|
||||
struct {
|
||||
fcparam fcp;
|
||||
uint64_t def_wwnn;
|
||||
uint64_t def_wwpn;
|
||||
uint64_t actv_wwnn;
|
||||
uint64_t actv_wwpn;
|
||||
uint16_t default_frame_size;
|
||||
uint16_t default_exec_throttle;
|
||||
} fibre_scsi;
|
||||
};
|
||||
typedef struct {
|
||||
uint64_t def_wwnn;
|
||||
uint64_t def_wwpn;
|
||||
uint32_t
|
||||
tgts_tested : 16,
|
||||
: 10,
|
||||
fcrswdog : 1,
|
||||
: 1,
|
||||
blocked : 1,
|
||||
deadloop : 1,
|
||||
role : 2;
|
||||
unsigned int downcount;
|
||||
unsigned int qfdelay;
|
||||
} isp_data;
|
||||
|
||||
#define ISP_DATA(isp, chan) (&((isp_data *)((isp)->isp_osinfo.storep))[chan])
|
||||
|
||||
#define isp_name isp_osinfo.hbaname
|
||||
#define isp_host isp_osinfo.host
|
||||
#define isp_unit isp_osinfo.host->unique_id
|
||||
#define isp_psco isp_osinfo.storep->parallel_scsi.psc_opts
|
||||
#define isp_dutydone isp_osinfo.storep->parallel_scsi.dutydone
|
||||
#define isp_defwwnn isp_osinfo.storep->fibre_scsi.def_wwnn
|
||||
#define isp_defwwpn isp_osinfo.storep->fibre_scsi.def_wwpn
|
||||
#define isp_actvwwnn isp_osinfo.storep->fibre_scsi.actv_wwnn
|
||||
#define isp_actvwwpn isp_osinfo.storep->fibre_scsi.actv_wwpn
|
||||
|
||||
/*
|
||||
* Driver prototypes..
|
||||
@@ -702,22 +682,25 @@ void isplinux_undo_proc(ispsoftc_t *);
|
||||
int isplinux_reinit(ispsoftc_t *);
|
||||
void isplinux_sqd(struct Scsi_Host *, struct scsi_device *);
|
||||
|
||||
int isp_drain_reset(ispsoftc_t *, char *);
|
||||
int isp_drain(ispsoftc_t *, char *);
|
||||
void isp_thread_event(ispsoftc_t *, int, void *, int, const char *, const int line);
|
||||
|
||||
static __inline uint64_t _isp_microtime_sub(struct timeval *, struct timeval *);
|
||||
static __inline void _isp_usec_delay(unsigned int);
|
||||
static __inline unsigned long _usec_to_jiffies(unsigned int);
|
||||
static __inline unsigned long _jiffies_to_usec(unsigned long);
|
||||
static __inline int isplinux_tagtype(Scsi_Cmnd *);
|
||||
static __inline int mbox_acquire(ispsoftc_t *);
|
||||
static __inline void mbox_wait_complete(ispsoftc_t *, mbreg_t *);
|
||||
static inline uint64_t _isp_microtime_sub(struct timeval *, struct timeval *);
|
||||
static inline void _isp_usec_delay(unsigned int);
|
||||
static inline unsigned long _usec_to_jiffies(unsigned int);
|
||||
static inline unsigned long _jiffies_to_usec(unsigned long);
|
||||
static inline int isplinux_tagtype(Scsi_Cmnd *);
|
||||
static inline int mbox_acquire(ispsoftc_t *);
|
||||
static inline void mbox_wait_complete(ispsoftc_t *, mbreg_t *);
|
||||
|
||||
int isplinux_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
|
||||
const char *isplinux_info(struct Scsi_Host *);
|
||||
int isplinux_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
|
||||
int isplinux_biosparam(struct scsi_device *, struct block_device *, sector_t, int[]);
|
||||
int isplinux_default_id(ispsoftc_t *);
|
||||
int isplinux_get_default_id(ispsoftc_t *, int);
|
||||
int isplinux_get_default_role(ispsoftc_t *, int);
|
||||
void isplinux_set_default_role(ispsoftc_t *, int, int);
|
||||
uint64_t isplinux_default_wwn(ispsoftc_t *, int, int, int);
|
||||
|
||||
|
||||
/*
|
||||
* Driver wide data...
|
||||
@@ -731,17 +714,19 @@ extern int isp_fcduplex;
|
||||
extern int isp_maxsectors;
|
||||
extern struct scsi_host_template *isp_template;
|
||||
extern const char *class3_roles[4];
|
||||
extern int isp_vports;
|
||||
extern dev_t isp_dev;
|
||||
extern struct cdev isp_cdev;
|
||||
extern struct file_operations isp_ioctl_operations;
|
||||
extern ISP_CLASS *isp_class;
|
||||
|
||||
/*
|
||||
* This used to be considered bad form, but locking crasp made it more attractive.
|
||||
* This used to be considered bad form, but locking crap made it more attractive.
|
||||
*/
|
||||
#define MAX_ISP 32
|
||||
extern ispsoftc_t *isplist[MAX_ISP];
|
||||
extern ispsoftc_t *api_isp;
|
||||
extern int api_channel;
|
||||
|
||||
/*
|
||||
* Platform private flags
|
||||
@@ -781,7 +766,7 @@ extern ispsoftc_t *api_isp;
|
||||
#define _SBSWAP(a, b, c)
|
||||
#endif
|
||||
|
||||
static __inline uint64_t
|
||||
static inline uint64_t
|
||||
_isp_microtime_sub(struct timeval *b, struct timeval *a)
|
||||
{
|
||||
uint64_t elapsed;
|
||||
@@ -804,7 +789,7 @@ _isp_microtime_sub(struct timeval *b, struct timeval *a)
|
||||
return (elapsed * 1000);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
static inline void
|
||||
_isp_usec_delay(unsigned int usecs)
|
||||
{
|
||||
while (usecs > 1000) {
|
||||
@@ -815,7 +800,7 @@ _isp_usec_delay(unsigned int usecs)
|
||||
udelay(usecs);
|
||||
}
|
||||
|
||||
static __inline unsigned long
|
||||
static inline unsigned long
|
||||
_usec_to_jiffies(unsigned int usecs)
|
||||
{
|
||||
struct timespec lt;
|
||||
@@ -826,7 +811,7 @@ _usec_to_jiffies(unsigned int usecs)
|
||||
return (timespec_to_jiffies(<));
|
||||
}
|
||||
|
||||
static __inline unsigned long
|
||||
static inline unsigned long
|
||||
_jiffies_to_usec(unsigned long jiffies)
|
||||
{
|
||||
unsigned long usecs;
|
||||
@@ -848,7 +833,7 @@ _jiffies_to_usec(unsigned long jiffies)
|
||||
#define MSG_ORDERED_TAG 0x22
|
||||
#endif
|
||||
|
||||
static __inline int
|
||||
static inline int
|
||||
isplinux_tagtype(Scsi_Cmnd *Cmnd)
|
||||
{
|
||||
switch (Cmnd->tag) {
|
||||
@@ -863,7 +848,7 @@ isplinux_tagtype(Scsi_Cmnd *Cmnd)
|
||||
}
|
||||
}
|
||||
|
||||
static __inline int
|
||||
static inline int
|
||||
mbox_acquire(ispsoftc_t *isp)
|
||||
{
|
||||
/*
|
||||
@@ -882,7 +867,7 @@ mbox_acquire(ispsoftc_t *isp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
static inline void
|
||||
mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
|
||||
{
|
||||
uint32_t lim = mbp->timeout;
|
||||
@@ -947,11 +932,11 @@ mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
|
||||
/*
|
||||
* Note that these allocators aren't interrupt safe
|
||||
*/
|
||||
static __inline void * isp_kalloc(size_t, int);
|
||||
static __inline void isp_kfree(void *, size_t);
|
||||
static __inline void * isp_kzalloc(size_t, int);
|
||||
static inline void * isp_kalloc(size_t, int);
|
||||
static inline void isp_kfree(void *, size_t);
|
||||
static inline void * isp_kzalloc(size_t, int);
|
||||
|
||||
static __inline void *
|
||||
static inline void *
|
||||
isp_kalloc(size_t size, int flags)
|
||||
{
|
||||
void *ptr;
|
||||
@@ -963,7 +948,7 @@ isp_kalloc(size_t size, int flags)
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
static inline void
|
||||
isp_kfree(void *ptr, size_t size)
|
||||
{
|
||||
if (size >= PAGE_SIZE) {
|
||||
@@ -973,12 +958,12 @@ isp_kfree(void *ptr, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
static __inline void *
|
||||
static inline void *
|
||||
isp_kzalloc(size_t size, int flags)
|
||||
{
|
||||
void *ptr = isp_kalloc(size, flags);
|
||||
if (ptr != NULL){
|
||||
memset(ptr, 0, size);
|
||||
MEMZERO(ptr, size);
|
||||
}
|
||||
return (ptr);
|
||||
}
|
||||
@@ -1001,8 +986,8 @@ void isp_deinit_target(ispsoftc_t *);
|
||||
void isp_detach_target(ispsoftc_t *);
|
||||
int isp_target_async(ispsoftc_t *, int, int);
|
||||
int isp_target_notify(ispsoftc_t *, void *, uint32_t *);
|
||||
int isp_enable_lun(ispsoftc_t *, uint16_t, uint64_t, uint16_t);
|
||||
int isp_disable_lun(ispsoftc_t *, uint16_t, uint64_t, uint16_t);
|
||||
int isp_enable_lun(ispsoftc_t *, uint16_t, uint16_t);
|
||||
int isp_disable_lun(ispsoftc_t *, uint16_t, uint16_t);
|
||||
|
||||
struct isp_notify {
|
||||
tmd_notify_t notify;
|
||||
|
||||
+124
-83
@@ -1,4 +1,4 @@
|
||||
/* $Id: isp_pci.c,v 1.144 2007/11/27 17:58:04 mjacob Exp $ */
|
||||
/* $Id: isp_pci.c,v 1.145 2007/12/02 22:02:06 mjacob Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2007 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -357,7 +357,7 @@ static struct ispmdvec mdvec_2400 = {
|
||||
/*
|
||||
* Encapsulating softc... Order of elements is important. The tag
|
||||
* pci_isp must come first because of multiple structure punning
|
||||
* (Scsi_Host * == struct isp_pcisoftc * == struct ispsofct *).
|
||||
* (Scsi_Host == struct isp_pcisoftc == ispsoftc_t).
|
||||
*/
|
||||
struct isp_pcisoftc {
|
||||
ispsoftc_t pci_isp;
|
||||
@@ -367,7 +367,6 @@ struct isp_pcisoftc {
|
||||
void * vaddr; /* Mapped Memory Address */
|
||||
vm_offset_t voff;
|
||||
vm_offset_t poff[_NREG_BLKS];
|
||||
union pstore params;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -426,8 +425,8 @@ map_isp_io(struct isp_pcisoftc *isp_pci, u_short cmd, vm_offset_t io_base)
|
||||
void
|
||||
isplinux_pci_release(struct Scsi_Host *host)
|
||||
{
|
||||
ispsoftc_t *isp = (ispsoftc_t *) host->hostdata;
|
||||
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) host->hostdata;
|
||||
ispsoftc_t *isp = ISP_HOST2ISP(host);
|
||||
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
||||
int i;
|
||||
|
||||
pci_disable_device(pcs->pci_dev);
|
||||
@@ -458,13 +457,25 @@ isplinux_pci_release(struct Scsi_Host *host)
|
||||
isp->isp_result = NULL;
|
||||
}
|
||||
if (IS_FC(isp)) {
|
||||
if (FCPARAM(isp)->isp_scratch) {
|
||||
pci_free_consistent(pcs->pci_dev, ISP2100_SCRLEN, FCPARAM(isp)->isp_scratch, FCPARAM(isp)->isp_scdma);
|
||||
FCPARAM(isp)->isp_scratch = NULL;
|
||||
for (i = 0; i < isp->isp_nchan; i++) {
|
||||
fcparam *fcp = FCPARAM(isp, i);
|
||||
if (fcp->isp_scratch) {
|
||||
pci_free_consistent(pcs->pci_dev, ISP_FC_SCRLEN, fcp->isp_scratch, fcp->isp_scdma);
|
||||
fcp->isp_scratch = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
pci_release_regions(pcs->pci_dev);
|
||||
|
||||
if (isp->isp_param) {
|
||||
isp_kfree(isp->isp_param, isp->isp_osinfo.param_amt);
|
||||
isp->isp_param = NULL;
|
||||
}
|
||||
if (isp->isp_osinfo.storep) {
|
||||
isp_kfree(isp->isp_osinfo.storep, isp->isp_osinfo.storep_amt);
|
||||
isp->isp_osinfo.storep = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pull ourselves off the global list
|
||||
*/
|
||||
@@ -512,7 +523,7 @@ isplinux_pci_init_one(struct Scsi_Host *host)
|
||||
struct pci_dev *pdev;
|
||||
ispsoftc_t *isp;
|
||||
|
||||
isp_pci = (struct isp_pcisoftc *) host->hostdata;
|
||||
isp_pci = (struct isp_pcisoftc *) ISP_HOST2ISP(host);
|
||||
pdev = isp_pci->pci_dev;
|
||||
isp = (ispsoftc_t *) isp_pci;
|
||||
|
||||
@@ -544,15 +555,18 @@ isplinux_pci_init_one(struct Scsi_Host *host)
|
||||
isp_pci->poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
|
||||
isp_pci->poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF;
|
||||
isp_pci->poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
|
||||
isp->isp_nchan = 1;
|
||||
|
||||
switch (pdev->device) {
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP1020:
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP1080:
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP12160:
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP1240:
|
||||
isp->isp_nchan = 2;
|
||||
/* FALLTHROUGH */
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP1080:
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP1280:
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP10160:
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP12160:
|
||||
isp_pci->poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2200:
|
||||
@@ -573,6 +587,7 @@ isplinux_pci_init_one(struct Scsi_Host *host)
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2432:
|
||||
isp->isp_port = PCI_FUNC(pdev->devfn);
|
||||
isp_pci->poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF;
|
||||
isp->isp_nchan += isp_vports;
|
||||
break;
|
||||
default:
|
||||
isp_prt(isp, ISP_LOGERR, "Device ID 0x%04x is not a known Qlogic Device", pdev->device);
|
||||
@@ -658,6 +673,7 @@ isplinux_pci_init_one(struct Scsi_Host *host)
|
||||
host->io_port = isp_pci->port;
|
||||
}
|
||||
host->irq = 0;
|
||||
host->max_channel = isp->isp_nchan - 1;
|
||||
isp_pci->pci_isp.isp_revision = rev;
|
||||
#ifndef ISP_DISABLE_1020_SUPPORT
|
||||
if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020) {
|
||||
@@ -736,7 +752,22 @@ isplinux_pci_init_one(struct Scsi_Host *host)
|
||||
}
|
||||
host->irq = pdev->irq;
|
||||
|
||||
isp->isp_param = &isp_pci->params;
|
||||
/*
|
||||
* Get parameter area set up
|
||||
*/
|
||||
isp->isp_osinfo.storep_amt = sizeof (isp_data) * isp->isp_nchan;
|
||||
if (IS_FC(isp)) {
|
||||
isp->isp_osinfo.param_amt = sizeof (fcparam) * isp->isp_nchan;
|
||||
} else {
|
||||
isp->isp_osinfo.param_amt = sizeof (sdparam) * isp->isp_nchan;
|
||||
}
|
||||
isp->isp_param = isp_kzalloc(isp->isp_osinfo.param_amt, GFP_KERNEL);
|
||||
isp->isp_osinfo.storep = isp_kzalloc(isp->isp_osinfo.storep_amt, GFP_KERNEL);
|
||||
if (isp->isp_param == NULL || isp->isp_osinfo.storep == NULL) {
|
||||
isp_prt(isp, ISP_LOGERR, "unable to allocate data structures");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* All PCI QLogic cards really can do full 32 bit PCI transactions,
|
||||
* at least. But the older cards (1020s) have a 24 bit segment limit
|
||||
@@ -780,6 +811,14 @@ isplinux_pci_init_one(struct Scsi_Host *host)
|
||||
CREATE_ISP_DEV(isp);
|
||||
return (0);
|
||||
bad:
|
||||
if (isp->isp_param) {
|
||||
isp_kfree(isp->isp_param, isp->isp_osinfo.param_amt);
|
||||
isp->isp_param = NULL;
|
||||
}
|
||||
if (isp->isp_osinfo.storep) {
|
||||
isp_kfree(isp->isp_osinfo.storep, isp->isp_osinfo.storep_amt);
|
||||
isp->isp_osinfo.storep = NULL;
|
||||
}
|
||||
if (host->irq) {
|
||||
ISP_DISABLE_INTS(isp);
|
||||
free_irq(host->irq, isp_pci);
|
||||
@@ -1006,10 +1045,10 @@ isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff)
|
||||
case BIU2400_REQOUTP:
|
||||
case BIU2400_RSPINP:
|
||||
case BIU2400_RSPOUTP:
|
||||
case BIU2400_PRI_RQINP:
|
||||
case BIU2400_PRI_RSPINP:
|
||||
case BIU2400_PRI_REQINP:
|
||||
case BIU2400_PRI_REQOUTP:
|
||||
case BIU2400_ATIO_RSPINP:
|
||||
case BIU2400_ATIO_REQINP:
|
||||
case BIU2400_ATIO_RSPOUTP:
|
||||
case BIU2400_HCCR:
|
||||
case BIU2400_GPIOD:
|
||||
case BIU2400_GPIOE:
|
||||
@@ -1067,10 +1106,10 @@ isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val)
|
||||
case BIU2400_REQOUTP:
|
||||
case BIU2400_RSPINP:
|
||||
case BIU2400_RSPOUTP:
|
||||
case BIU2400_PRI_RQINP:
|
||||
case BIU2400_PRI_RSPINP:
|
||||
case BIU2400_PRI_REQINP:
|
||||
case BIU2400_PRI_REQOUTP:
|
||||
case BIU2400_ATIO_RSPINP:
|
||||
case BIU2400_ATIO_REQINP:
|
||||
case BIU2400_ATIO_RSPOUTP:
|
||||
case BIU2400_HCCR:
|
||||
case BIU2400_GPIOD:
|
||||
case BIU2400_GPIOE:
|
||||
@@ -1259,6 +1298,8 @@ isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val)
|
||||
static int
|
||||
isp_pci_mbxdma(ispsoftc_t *isp)
|
||||
{
|
||||
fcparam *fcp;
|
||||
int i;
|
||||
struct isp_pcisoftc *pcs;
|
||||
|
||||
if (isp->isp_xflist) {
|
||||
@@ -1332,19 +1373,21 @@ isp_pci_mbxdma(ispsoftc_t *isp)
|
||||
}
|
||||
|
||||
if (IS_FC(isp)) {
|
||||
fcparam *fcp = isp->isp_param;
|
||||
if (fcp->isp_scratch == NULL) {
|
||||
dma_addr_t busaddr;
|
||||
fcp->isp_scratch = pci_alloc_consistent(pcs->pci_dev, ISP2100_SCRLEN, &busaddr);
|
||||
for (i = 0; i < isp->isp_nchan; i++) {
|
||||
fcp = FCPARAM(isp, i);
|
||||
if (fcp->isp_scratch == NULL) {
|
||||
isp_prt(isp, ISP_LOGERR, "unable to allocate scratch space");
|
||||
goto bad;
|
||||
}
|
||||
fcp->isp_scdma = busaddr;
|
||||
MEMZERO(fcp->isp_scratch, ISP2100_SCRLEN);
|
||||
if (fcp->isp_scdma & 0x7) {
|
||||
isp_prt(isp, ISP_LOGERR, "scratch space not 8 byte aligned");
|
||||
goto bad;
|
||||
dma_addr_t busaddr;
|
||||
fcp->isp_scratch = pci_alloc_consistent(pcs->pci_dev, ISP_FC_SCRLEN, &busaddr);
|
||||
if (fcp->isp_scratch == NULL) {
|
||||
isp_prt(isp, ISP_LOGERR, "unable to allocate scratch space");
|
||||
goto bad;
|
||||
}
|
||||
fcp->isp_scdma = busaddr;
|
||||
MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN);
|
||||
if (fcp->isp_scdma & 0x7) {
|
||||
isp_prt(isp, ISP_LOGERR, "scratch space not 8 byte aligned");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1377,10 +1420,15 @@ bad:
|
||||
isp->isp_result = NULL;
|
||||
isp->isp_result_dma = 0;
|
||||
}
|
||||
if (IS_FC(isp) && FCPARAM(isp)->isp_scratch) {
|
||||
pci_free_consistent(pcs->pci_dev, ISP2100_SCRLEN, FCPARAM(isp)->isp_scratch, FCPARAM(isp)->isp_scdma);
|
||||
FCPARAM(isp)->isp_scratch = NULL;
|
||||
FCPARAM(isp)->isp_scdma = 0;
|
||||
if (IS_FC(isp)) {
|
||||
for (i = 0; i < isp->isp_nchan; i++) {
|
||||
fcp = FCPARAM(isp, i);
|
||||
if (fcp->isp_scratch) {
|
||||
pci_free_consistent(pcs->pci_dev, ISP_FC_SCRLEN, fcp->isp_scratch, fcp->isp_scdma);
|
||||
fcp->isp_scratch = NULL;
|
||||
fcp->isp_scdma = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ISP_IGET_LK_SOFTC(isp);
|
||||
return (1);
|
||||
@@ -1441,6 +1489,9 @@ tdma_mk(ispsoftc_t *isp, tmd_xact_t *xact, ct_entry_t *cto, uint32_t *nxtip, uin
|
||||
isp_prt(isp, ISP_LOGTDEBUG1, ctx, cto->ct_fwhandle, L0LUN_TO_FLATLUN(tmd->cd_lun), (int) cto->ct_iid, cto->ct_flags, cto->ct_status,
|
||||
cto->ct_scsi_status, cto->ct_resid, "<END>");
|
||||
isp_put_ctio(isp, cto, qe);
|
||||
if (cto->ct_flags & CT_CCINCR) {
|
||||
tmd->cd_flags &= ~CDFL_RESRC_FILL;
|
||||
}
|
||||
return (CMD_QUEUED);
|
||||
}
|
||||
|
||||
@@ -1662,6 +1713,9 @@ tdma_mk(ispsoftc_t *isp, tmd_xact_t *xact, ct_entry_t *cto, uint32_t *nxtip, uin
|
||||
}
|
||||
*nxtip = nxti;
|
||||
isp_prt(isp, ISP_LOGTDEBUG2, "[%llx]: map %d segments at %p for handle 0x%x", tmd->cd_tagval, new_seg_cnt, xact->td_data, cto->ct_syshandle);
|
||||
if (sflags & CT_CCINCR) {
|
||||
tmd->cd_flags &= ~CDFL_RESRC_FILL;
|
||||
}
|
||||
return (CMD_QUEUED);
|
||||
}
|
||||
|
||||
@@ -1729,11 +1783,13 @@ tdma_mk_2400(ispsoftc_t *isp, tmd_xact_t *xact, ct7_entry_t *cto, uint32_t *nxti
|
||||
if (xact->td_xfrlen == 0) {
|
||||
cto->ct_header.rqs_entry_count = 1;
|
||||
cto->ct_header.rqs_seqno = 1;
|
||||
|
||||
/* ct_syshandle contains the synchronization handle set by caller */
|
||||
isp_put_ctio7(isp, cto, qe);
|
||||
ISP_TDQE(isp, "tdma_mk_2400[no data]", curi, qe);
|
||||
return (CMD_QUEUED);
|
||||
}
|
||||
|
||||
if (xact->td_xfrlen <= 1024) {
|
||||
nseg = 0;
|
||||
} else if (xact->td_xfrlen <= 4096) {
|
||||
@@ -1752,6 +1808,7 @@ tdma_mk_2400(ispsoftc_t *isp, tmd_xact_t *xact, ct7_entry_t *cto, uint32_t *nxti
|
||||
nseg = 7;
|
||||
}
|
||||
isp->isp_osinfo.bins[nseg]++;
|
||||
|
||||
/*
|
||||
* First, count and map all S/G segments
|
||||
*
|
||||
@@ -1818,17 +1875,11 @@ tdma_mk_2400(ispsoftc_t *isp, tmd_xact_t *xact, ct7_entry_t *cto, uint32_t *nxti
|
||||
cto2->ct_flags |= CT7_NO_DATA|CT7_NO_DATA|CT7_FLAG_MODE1;
|
||||
cto2->ct_seg_count = 0;
|
||||
MEMZERO(&cto2->rsp, sizeof (cto2->rsp));
|
||||
cto2->ct_scsi_status = swd;
|
||||
if ((swd & 0xff) == SCSI_CHECK && (xact->td_hflags & TDFH_SNSVALID)) {
|
||||
swd |= CT2_SNSLEN_VALID;
|
||||
cto2->rsp.m1.ct_resplen = min(TMD_SENSELEN, MAXRESPLEN_24XX);
|
||||
MEMCPY(cto2->rsp.m1.ct_resp, tmd->cd_sense, cto2->rsp.m1.ct_resplen);
|
||||
}
|
||||
if (cto2->ct_resid > 0) {
|
||||
swd |= CT2_DATA_UNDER;
|
||||
} else if (cto2->ct_resid < 0) {
|
||||
swd |= CT2_DATA_OVER;
|
||||
}
|
||||
cto2->ct_scsi_status = swd;
|
||||
#else
|
||||
cto->ct_flags &= ~CT7_SENDSTATUS;
|
||||
cto->ct_resid = 0;
|
||||
@@ -1849,35 +1900,27 @@ tdma_mk_2400(ispsoftc_t *isp, tmd_xact_t *xact, ct7_entry_t *cto, uint32_t *nxti
|
||||
last_synthetic_count = 0;
|
||||
last_synthetic_addr = 0;
|
||||
cto->ct_seg_count = 1;
|
||||
seg = 1;
|
||||
|
||||
for (seg = 0; seg < cto->ct_seg_count; seg++) {
|
||||
bc = min(sg_dma_len(sg), xfcnt);
|
||||
addr = sg_dma_address(sg);
|
||||
#ifdef ISP_DAC_SUPPORTED
|
||||
cto->rsp.m0.ds.ds_base = LOWD(addr);
|
||||
cto->rsp.m0.ds.ds_basehi = HIWD(addr);
|
||||
if (!SAME_4G(addr, bc)) {
|
||||
isp_prt(isp, ISP_LOGTDEBUG1, "seg0[%d]%x%08x:%u (TRUNC'd)", seg, (uint32_t) HIWD(addr), (uint32_t)LOWD(addr), bc);
|
||||
cto->rsp.m0.ds.ds_count = (unsigned int) (FOURG_SEG(addr + bc) - addr);
|
||||
addr += cto->rsp.m0.ds.ds_count;
|
||||
bc -= cto->rsp.m0.ds.ds_count;
|
||||
last_synthetic_count = bc;
|
||||
last_synthetic_addr = addr;
|
||||
} else {
|
||||
cto->rsp.m0.ds.ds_count = bc;
|
||||
isp_prt(isp, ISP_LOGTDEBUG1, "%s: seg0[%d]%lx%08lx:%u", __FUNCTION__, seg,
|
||||
(unsigned long)cto->rsp.m0.ds.ds_basehi, (unsigned long)cto->rsp.m0.ds.ds_base, bc);
|
||||
}
|
||||
#else
|
||||
cto->rsp.m0.ds.ds_base = addr;
|
||||
cto->rsp.m0.ds.ds_basehi = 0;
|
||||
bc = min(sg_dma_len(sg), xfcnt);
|
||||
addr = sg_dma_address(sg);
|
||||
cto->rsp.m0.ds.ds_base = LOWD(addr);
|
||||
cto->rsp.m0.ds.ds_basehi = HIWD(addr);
|
||||
if (!SAME_4G(addr, bc)) {
|
||||
isp_prt(isp, ISP_LOGTDEBUG1, "seg0[%d]%x%08x:%u (TRUNC'd)", seg, (uint32_t) HIWD(addr), (uint32_t)LOWD(addr), bc);
|
||||
cto->rsp.m0.ds.ds_count = (unsigned int) (FOURG_SEG(addr + bc) - addr);
|
||||
addr += cto->rsp.m0.ds.ds_count;
|
||||
bc -= cto->rsp.m0.ds.ds_count;
|
||||
last_synthetic_count = bc;
|
||||
last_synthetic_addr = addr;
|
||||
} else {
|
||||
cto->rsp.m0.ds.ds_count = bc;
|
||||
isp_prt(isp, ISP_LOGTDEBUG1, "%s: seg0[%d]%lx:%u", __FUNCTION__, seg, (unsigned long) cto->rsp.m0.ds.ds_base, bc);
|
||||
#endif
|
||||
cto->rsp.m0.ct_xfrlen += bc;
|
||||
xfcnt -= bc;
|
||||
sg++;
|
||||
isp_prt(isp, ISP_LOGTDEBUG1, "%s: seg0[%d]%lx%08lx:%u", __FUNCTION__, seg,
|
||||
(unsigned long)cto->rsp.m0.ds.ds_basehi, (unsigned long)cto->rsp.m0.ds.ds_base, bc);
|
||||
}
|
||||
cto->rsp.m0.ct_xfrlen += bc;
|
||||
xfcnt -= bc;
|
||||
sg++;
|
||||
|
||||
|
||||
if (seg == nseg && last_synthetic_count == 0) {
|
||||
@@ -2008,7 +2051,7 @@ tdma_mkfc(ispsoftc_t *isp, tmd_xact_t *xact, ct2_entry_t *cto, uint32_t *nxtip,
|
||||
uint32_t curi, nxti;
|
||||
uint32_t bc, last_synthetic_count;
|
||||
long xfcnt; /* must be signed */
|
||||
int nseg, seg, ovseg, seglim, new_seg_cnt;
|
||||
int nseg, seg, ovseg, seglim, new_seg_cnt, ccincr = 0;
|
||||
#ifdef ALLOW_SYNTHETIC_CTIO
|
||||
ct2_entry_t *cto2 = NULL, ct2;
|
||||
#endif
|
||||
@@ -2037,6 +2080,9 @@ tdma_mkfc(ispsoftc_t *isp, tmd_xact_t *xact, ct2_entry_t *cto, uint32_t *nxtip,
|
||||
isp_prt(isp, ISP_LOGTDEBUG1, "[%x] faspost (0x%x)", cto->ct_rxid, tmd->cd_cdb[0]);
|
||||
}
|
||||
ISP_TDQE(isp, "tdma_mkfc[no data]", curi, qe);
|
||||
if (cto->ct_flags & CT2_CCINCR) {
|
||||
tmd->cd_flags &= ~CDFL_RESRC_FILL;
|
||||
}
|
||||
return (CMD_QUEUED);
|
||||
}
|
||||
|
||||
@@ -2129,6 +2175,9 @@ tdma_mkfc(ispsoftc_t *isp, tmd_xact_t *xact, ct2_entry_t *cto, uint32_t *nxtip,
|
||||
swd |= CT2_DATA_OVER;
|
||||
}
|
||||
cto2->rsp.m1.ct_scsi_status = swd;
|
||||
if (cto2->ct_flags & CT2_CCINCR) {
|
||||
ccincr = 1;
|
||||
}
|
||||
#else
|
||||
cto->ct_flags &= ~(CT2_SENDSTATUS|CT2_CCINCR|CT2_FASTPOST);
|
||||
cto->ct_resid = 0;
|
||||
@@ -2377,6 +2426,9 @@ mbxsync:
|
||||
}
|
||||
ISP_TDQE(isp, "tdma_mkfc", isp->isp_reqidx, cto);
|
||||
*nxtip = nxti;
|
||||
if (ccincr) {
|
||||
tmd->cd_flags &= ~CDFL_RESRC_FILL;
|
||||
}
|
||||
return (CMD_QUEUED);
|
||||
}
|
||||
#endif
|
||||
@@ -2696,12 +2748,12 @@ mbxsync:
|
||||
}
|
||||
|
||||
if (rq->req_header.rqs_entry_type == RQSTYPE_T3RQS) {
|
||||
if (FCPARAM(isp)->isp_2klogin)
|
||||
if (ISP_CAP_2KLOGIN(isp))
|
||||
isp_put_request_t3e(isp, (ispreqt3e_t *) rq, (ispreqt3e_t *) h);
|
||||
else
|
||||
isp_put_request_t3(isp, (ispreqt3_t *) rq, (ispreqt3_t *) h);
|
||||
} else if (rq->req_header.rqs_entry_type == RQSTYPE_T2RQS) {
|
||||
if (FCPARAM(isp)->isp_2klogin)
|
||||
if (ISP_CAP_2KLOGIN(isp))
|
||||
isp_put_request_t2e(isp, (ispreqt2e_t *) rq, (ispreqt2e_t *) h);
|
||||
else
|
||||
isp_put_request_t2(isp, (ispreqt2_t *) rq, (ispreqt2_t *) h);
|
||||
@@ -3137,12 +3189,11 @@ isplinux_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
pci_disable_device(pdev);
|
||||
return (-ENOMEM);
|
||||
}
|
||||
pci_isp = (struct isp_pcisoftc *) host->hostdata;
|
||||
pci_isp = (struct isp_pcisoftc *) ISP_HOST2ISP(host);
|
||||
pci_set_drvdata(pdev, pci_isp);
|
||||
pci_isp->pci_dev = pdev;
|
||||
isp = (ispsoftc_t *) pci_isp;
|
||||
isp->isp_host = host;
|
||||
isp->isp_osinfo.storep = &pci_isp->params;
|
||||
isp->isp_osinfo.device = pdev;
|
||||
host->unique_id = isp_unit_seed++;
|
||||
sprintf(isp->isp_name, "%s%d", ISP_NAME, isp->isp_unit);
|
||||
@@ -3180,7 +3231,6 @@ isplinux_pci_remove(struct pci_dev *pdev)
|
||||
struct isp_pcisoftc *pci_isp = pci_get_drvdata(pdev);
|
||||
unsigned long flags;
|
||||
ispsoftc_t *isp;
|
||||
int i;
|
||||
struct Scsi_Host *host;
|
||||
|
||||
isp = (ispsoftc_t *) pci_isp;
|
||||
@@ -3190,14 +3240,11 @@ isplinux_pci_remove(struct pci_dev *pdev)
|
||||
#ifdef ISP_TARGET_MODE
|
||||
isp_detach_target(isp);
|
||||
#endif
|
||||
if (isp->isp_osinfo.task_thread) {
|
||||
SEND_THREAD_EVENT(isp, ISP_THREAD_EXIT, NULL, 1, __FUNCTION__, __LINE__);
|
||||
}
|
||||
ISP_THREAD_KILL(isp);
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
isp_shutdown(isp);
|
||||
isp->dogactive = 0;
|
||||
del_timer(&isp->isp_osinfo.timer);
|
||||
isp->isp_role = ISP_ROLE_NONE;
|
||||
ISP_DISABLE_INTS(isp);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
isplinux_pci_release(host);
|
||||
@@ -3219,12 +3266,6 @@ isplinux_pci_remove(struct pci_dev *pdev)
|
||||
#endif
|
||||
scsi_host_put(host);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
for (i = 0; i < MAX_ISP; i++) {
|
||||
if (isplist[i] == isp) {
|
||||
isplist[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct pci_driver isplinux_pci_driver = {
|
||||
|
||||
+102
-60
@@ -1,4 +1,4 @@
|
||||
/* $Id: scsi_target.c,v 1.74 2007/11/27 17:57:26 mjacob Exp $ */
|
||||
/* $Id: scsi_target.c,v 1.75 2007/12/02 22:02:06 mjacob Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2007 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -259,7 +259,7 @@ struct initiator {
|
||||
};
|
||||
|
||||
#define HASH_WIDTH 16
|
||||
#define INI_HASH_LISTP(busp, ini_id) busp->list[ini_id & (HASH_WIDTH - 1)]
|
||||
#define INI_HASH_LISTP(busp, chan, ini_id) busp->bchan[chan].list[ini_id & (HASH_WIDTH - 1)]
|
||||
|
||||
/*
|
||||
* We maintain a reasonable cache of large sized (8MB) scatterlists
|
||||
@@ -303,10 +303,14 @@ typedef struct {
|
||||
} lun_t;
|
||||
#define LUN_BLOCK_SHIFT 9
|
||||
|
||||
struct bus {
|
||||
hba_register_t h; /* must be first */
|
||||
struct bus_chan {
|
||||
ini_t * list[HASH_WIDTH]; /* hash list of known initiators */
|
||||
lun_t luns[MAX_LUN]; /* luns */
|
||||
lun_t luns[MAX_LUN]; /* per-channel lun arrays */
|
||||
};
|
||||
|
||||
struct bus {
|
||||
hba_register_t h; /* must be first */
|
||||
struct bus_chan *bchan;
|
||||
};
|
||||
|
||||
#define SDprintk if (scsi_tdebug) printk
|
||||
@@ -333,12 +337,12 @@ static void scsi_target_read_capacity(tmd_cmd_t *, ini_t *);
|
||||
static void scsi_target_modesense(tmd_cmd_t *, ini_t *);
|
||||
static int scsi_target_rdwr(tmd_cmd_t *, ini_t *, int);
|
||||
static int scsi_target_thread(void *);
|
||||
static int scsi_alloc_disk(bus_t *, int, int, uint64_t);
|
||||
static void scsi_free_disk(bus_t *, int);
|
||||
static int scsi_alloc_disk(bus_t *, int, int, int, uint64_t);
|
||||
static void scsi_free_disk(bus_t *, int, int);
|
||||
static int scsi_target_copydata(struct scatterlist *, void *, uint32_t, int);
|
||||
static int scsi_target_start_user_io(sc_io_t *);
|
||||
static int scsi_target_end_user_io(sc_io_t *);
|
||||
static int scsi_target_endis(char *, uint64_t, int, int);
|
||||
static int scsi_target_endis(char *, uint64_t, int, int, int);
|
||||
|
||||
/*
|
||||
* Local Declarations
|
||||
@@ -423,7 +427,7 @@ scsi_target_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned
|
||||
rv = -EFAULT;
|
||||
break;
|
||||
}
|
||||
rv = scsi_target_endis(sc->hba_name_unit, sc->nbytes, sc->lun, (cmd == SC_ENABLE_LUN)?((sc->flags == SC_EF_OVERCOMMIT)? 2 : 1) : 0);
|
||||
rv = scsi_target_endis(sc->hba_name_unit, sc->nbytes, sc->channel, sc->lun, (cmd == SC_ENABLE_LUN)? ((sc->flags & SC_EF_OVERCOMMIT)? 2 : 1) : 0);
|
||||
break;
|
||||
}
|
||||
case SC_PUT_IO:
|
||||
@@ -512,7 +516,7 @@ bus_from_name(char *name)
|
||||
static __inline ini_t *
|
||||
ini_from_tmd(bus_t *bp, tmd_cmd_t *tmd)
|
||||
{
|
||||
ini_t *ptr = INI_HASH_LISTP(bp, tmd->cd_iid);
|
||||
ini_t *ptr = INI_HASH_LISTP(bp, tmd->cd_channel, tmd->cd_iid);
|
||||
if (ptr) {
|
||||
do {
|
||||
if (ptr->ini_iid == tmd->cd_iid) {
|
||||
@@ -543,9 +547,9 @@ bus_from_notify(tmd_notify_t *np)
|
||||
* Make an initiator structure
|
||||
*/
|
||||
static void
|
||||
add_ini(bus_t *bp, uint64_t iid, ini_t *nptr)
|
||||
add_ini(bus_t *bp, int chan, uint64_t iid, ini_t *nptr)
|
||||
{
|
||||
ini_t **ptrlptr = &INI_HASH_LISTP(bp, iid);
|
||||
ini_t **ptrlptr = &INI_HASH_LISTP(bp, chan, iid);
|
||||
|
||||
nptr->ini_iid = iid;
|
||||
nptr->ini_bus = (struct bus *) bp;
|
||||
@@ -714,7 +718,7 @@ scsi_target_start_cmd(tmd_cmd_t *tmd, int from_intr)
|
||||
(*bp->h.r_action)(QIN_TMD_CONT, xact);
|
||||
return;
|
||||
}
|
||||
add_ini(bp, tmd->cd_iid, nptr);
|
||||
add_ini(bp, tmd->cd_channel, tmd->cd_iid, nptr);
|
||||
spin_unlock_irqrestore(&scsi_target_lock, flags);
|
||||
ini = nptr;
|
||||
/*
|
||||
@@ -784,8 +788,7 @@ scsi_target_start_cmd(tmd_cmd_t *tmd, int from_intr)
|
||||
len = min(sizeof(vp80data), len);
|
||||
if (len) {
|
||||
memcpy(addr, vp80data, len);
|
||||
snprintf(&buf[4], sizeof (vp80data) - 4, "FERAL_%s%d_LUN%06dSER%s", bp->h.r_name, bp->h.r_inst,
|
||||
L0LUN_TO_FLATLUN(tmd->cd_lun), SERNO);
|
||||
snprintf(&buf[4], sizeof (vp80data) - 4, "FERAL0LUN%06dSER%s", L0LUN_TO_FLATLUN(tmd->cd_lun), SERNO);
|
||||
for (j = 0, i = 4; i < sizeof (vp80data); i++) {
|
||||
if (j == 0) {
|
||||
if (buf[i] == 0) {
|
||||
@@ -831,7 +834,7 @@ scsi_target_start_cmd(tmd_cmd_t *tmd, int from_intr)
|
||||
/*
|
||||
* If we're not here, say we aren't here.
|
||||
*/
|
||||
if (L0LUN_TO_FLATLUN(tmd->cd_lun) >= MAX_LUN || bp->luns[L0LUN_TO_FLATLUN(tmd->cd_lun)].enabled == 0) {
|
||||
if (L0LUN_TO_FLATLUN(tmd->cd_lun) >= MAX_LUN || bp->bchan[tmd->cd_channel].luns[L0LUN_TO_FLATLUN(tmd->cd_lun)].enabled == 0) {
|
||||
((u8 *)addr)[0] = 0x7f;
|
||||
}
|
||||
SDprintk2("scsi_target(%s%d): %p (%p) length %d byte0 0x%x\n", bp->h.r_name, bp->h.r_inst, addr, dp, dp->length, ((u8 *)addr)[0]);
|
||||
@@ -901,7 +904,7 @@ scsi_target_start_cmd(tmd_cmd_t *tmd, int from_intr)
|
||||
|
||||
spin_lock_irqsave(&scsi_target_lock, flags);
|
||||
for (nluns = i = 0; i < MAX_LUN; i++) {
|
||||
lun_t *lp = &bp->luns[i];
|
||||
lun_t *lp = &bp->bchan[tmd->cd_channel].luns[i];
|
||||
if (lp->enabled) {
|
||||
uint8_t *ptr = &rpa[8 + (nluns << 3)];
|
||||
if (i >= 256) {
|
||||
@@ -999,7 +1002,7 @@ scsi_target_start_cmd(tmd_cmd_t *tmd, int from_intr)
|
||||
/*
|
||||
* Make sure we have a legal and open lun
|
||||
*/
|
||||
if (L0LUN_TO_FLATLUN(tmd->cd_lun) >= MAX_LUN || bp->luns[L0LUN_TO_FLATLUN(tmd->cd_lun)].enabled == 0) {
|
||||
if (L0LUN_TO_FLATLUN(tmd->cd_lun) >= MAX_LUN || bp->bchan[tmd->cd_channel].luns[L0LUN_TO_FLATLUN(tmd->cd_lun)].enabled == 0) {
|
||||
if (from_intr) {
|
||||
scsi_cmd_sched_restart(tmd, "bad or disabled lun");
|
||||
return;
|
||||
@@ -1081,10 +1084,10 @@ doit:
|
||||
} else {
|
||||
memset(tmd->cd_sense, 0, TMD_SENSELEN);
|
||||
}
|
||||
printk("INI(%#llx)=>LUN %d: [%llx] cdb0=0x%02x tl=%u CHECK (0x%x 0x%x 0x%x)\n", tmd->cd_iid, L0LUN_TO_FLATLUN(tmd->cd_lun),
|
||||
printk("%s%d: INI(%#llx)=>LUN %d: [%llx] cdb0=0x%02x tl=%u CHECK (0x%x 0x%x 0x%x)\n", bp->h.r_name, bp->h.r_inst, tmd->cd_iid, L0LUN_TO_FLATLUN(tmd->cd_lun),
|
||||
tmd->cd_tagval, tmd->cd_cdb[0] & 0xff, tmd->cd_totlen, tmd->cd_sense[2] & 0xf, tmd->cd_sense[12], tmd->cd_sense[13]);
|
||||
} else {
|
||||
SDprintk("INI(%#llx)=>LUN %d: [%llx] cdb0=0x%02x tl=%u ssts=%x hf 0x%x\n", tmd->cd_iid, L0LUN_TO_FLATLUN(tmd->cd_lun),
|
||||
SDprintk("%s%d: INI(%#llx)=>LUN %d: [%llx] cdb0=0x%02x tl=%u ssts=%x hf 0x%x\n", bp->h.r_name, bp->h.r_inst, tmd->cd_iid, L0LUN_TO_FLATLUN(tmd->cd_lun),
|
||||
tmd->cd_tagval, tmd->cd_cdb[0] & 0xff, tmd->cd_totlen, tmd->cd_scsi_status, xact->td_hflags);
|
||||
}
|
||||
(*bp->h.r_action)(QIN_TMD_CONT, xact);
|
||||
@@ -1109,7 +1112,7 @@ scsi_target_read_capacity_16(tmd_cmd_t *tmd, ini_t *ini)
|
||||
return;
|
||||
}
|
||||
|
||||
lp = &bp->luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
lp = &bp->bchan[tmd->cd_channel].luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
|
||||
dp = SGS_SGP(addr);
|
||||
if (tmd->cd_cdb[14] & 0x1) { /* PMI */
|
||||
@@ -1169,7 +1172,7 @@ scsi_target_read_capacity(tmd_cmd_t *tmd, ini_t *ini)
|
||||
return;
|
||||
}
|
||||
|
||||
lp = &bp->luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
lp = &bp->bchan[tmd->cd_channel].luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
|
||||
dp = SGS_SGP(addr);
|
||||
if (tmd->cd_cdb[8] & 0x1) { /* PMI */
|
||||
@@ -1221,7 +1224,7 @@ scsi_target_modesense(tmd_cmd_t *tmd, ini_t *ini)
|
||||
void *addr;
|
||||
|
||||
bp = ini->ini_bus;
|
||||
lp = &bp->luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
lp = &bp->bchan[tmd->cd_channel].luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
pgctl = tmd->cd_cdb[2] & MODE_PGCTL_MASK;
|
||||
page = tmd->cd_cdb[2] & MODE_ALL_PAGES;
|
||||
|
||||
@@ -1392,7 +1395,7 @@ scsi_target_rdwr(tmd_cmd_t *tmd, ini_t *ini, int from_intr)
|
||||
unsigned long flags;
|
||||
|
||||
bp = ini->ini_bus;
|
||||
lp = &bp->luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
lp = &bp->bchan[tmd->cd_channel].luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
iswrite = 0;
|
||||
|
||||
switch (tmd->cd_cdb[0]) {
|
||||
@@ -1693,7 +1696,7 @@ scsi_target_ldfree(bus_t *bp, tmd_xact_t *xact, int from_intr)
|
||||
tmd->cd_flags &= ~CDF_PRIVATE_0;
|
||||
} else if (tmd->cd_flags & CDF_PRIVATE_1) {
|
||||
struct scatterlist *dp = tmd->cd_dp;
|
||||
lun_t *lp = &bp->luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
lun_t *lp = &bp->bchan[tmd->cd_channel].luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
|
||||
if (dp == NULL) {
|
||||
printk(KERN_ERR "scsi_target: LDFREE[%llx] null dp @ line %d\n", tmd->cd_tagval, __LINE__);
|
||||
@@ -1761,7 +1764,11 @@ scsi_target_handler(qact_e action, void *arg)
|
||||
switch (action) {
|
||||
case QOUT_HBA_REG:
|
||||
{
|
||||
hba_register_t *hp;
|
||||
hba_register_t *hp = arg;
|
||||
|
||||
/*
|
||||
* Make sure we can allocate an adequate number of lun structures
|
||||
*/
|
||||
spin_lock_irqsave(&scsi_target_lock, flags);
|
||||
for (bp = busses; bp < &busses[MAX_BUS]; bp++) {
|
||||
if (bp->h.r_action == NULL) {
|
||||
@@ -1773,7 +1780,6 @@ scsi_target_handler(qact_e action, void *arg)
|
||||
printk("scsi_target: cannot register any more SCSI busses\n");
|
||||
break;
|
||||
}
|
||||
hp = arg;
|
||||
if (hp->r_version != QR_VERSION) {
|
||||
spin_unlock_irqrestore(&scsi_target_lock, flags);
|
||||
printk("scsi_target: version mismatch- compiled with %d, got %d\n", QR_VERSION, hp->r_version);
|
||||
@@ -1781,7 +1787,13 @@ scsi_target_handler(qact_e action, void *arg)
|
||||
}
|
||||
bp->h = *hp;
|
||||
spin_unlock_irqrestore(&scsi_target_lock, flags);
|
||||
printk("scsi_target: registering %s%d\n", hp->r_name, hp->r_inst);
|
||||
bp->bchan = scsi_target_kzalloc(bp->h.r_nchannels * sizeof (struct bus_chan), GFP_KERNEL);
|
||||
if (bp->bchan == NULL) {
|
||||
memset(&bp->h, 0, sizeof (hba_register_t));
|
||||
printk("scsi_target: cannot allocate buschan for %s%d\n", hp->r_name, hp->r_inst);
|
||||
} else {
|
||||
printk("scsi_target: registering %s%d\n", hp->r_name, hp->r_inst);
|
||||
}
|
||||
(hp->r_action)(QIN_HBA_REG, arg);
|
||||
break;
|
||||
}
|
||||
@@ -1834,7 +1846,7 @@ scsi_target_handler(qact_e action, void *arg)
|
||||
lun_t *lp;
|
||||
SDprintk("scsi_target: [%llx] data receive done\n", tmd->cd_tagval);
|
||||
spin_lock_irqsave(&scsi_target_lock, flags);
|
||||
lp = &bp->luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
lp = &bp->bchan[tmd->cd_channel].luns[L0LUN_TO_FLATLUN(tmd->cd_lun)];
|
||||
/*
|
||||
* If we're an overcommit disk we don't complete the command here.
|
||||
*
|
||||
@@ -1911,7 +1923,7 @@ scsi_target_handler(qact_e action, void *arg)
|
||||
}
|
||||
if (np->nt_ncode == NT_ABORT_TASK) {
|
||||
tmd_cmd_t *tmd;
|
||||
lun_t *lp = &bp->luns[np->nt_lun];
|
||||
lun_t *lp = &bp->bchan[np->nt_channel].luns[np->nt_lun];
|
||||
int i;
|
||||
|
||||
for (i = 0, tmd = p_front; tmd; tmd = tmd->cd_next, i++) {
|
||||
@@ -1942,7 +1954,7 @@ scsi_target_handler(qact_e action, void *arg)
|
||||
case QOUT_HBA_UNREG:
|
||||
{
|
||||
hba_register_t *hp = arg;
|
||||
int j;
|
||||
int j, k;
|
||||
|
||||
spin_lock_irqsave(&scsi_target_lock, flags);
|
||||
for (bp = busses; bp < &busses[MAX_BUS]; bp++) {
|
||||
@@ -1955,26 +1967,32 @@ scsi_target_handler(qact_e action, void *arg)
|
||||
}
|
||||
if (bp == &busses[MAX_BUS]) {
|
||||
spin_unlock_irqrestore(&scsi_target_lock, flags);
|
||||
printk(KERN_WARNING "%s: HBA_UNREG cannot find busp)\n", __FUNCTION__);
|
||||
printk(KERN_WARNING "%s: HBA_UNREG cannot find bus\n", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&scsi_target_lock, flags);
|
||||
for (j = 0; j < HASH_WIDTH; j++) {
|
||||
ini_t *nptr = bp->list[j];
|
||||
while (nptr) {
|
||||
ini_t *next = nptr->ini_next;
|
||||
free_sdata_chain(nptr->ini_sdata);
|
||||
scsi_target_kfree(nptr, sizeof (ini_t));
|
||||
nptr = next;
|
||||
for (j = 0; j < bp->h.r_nchannels; j++) {
|
||||
for (k = 0; k < HASH_WIDTH; k++) {
|
||||
ini_t *nptr = bp->bchan[j].list[k];
|
||||
while (nptr) {
|
||||
ini_t *next = nptr->ini_next;
|
||||
free_sdata_chain(nptr->ini_sdata);
|
||||
scsi_target_kfree(nptr, sizeof (ini_t));
|
||||
nptr = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < MAX_BUS; j++) {
|
||||
if (bp->luns[j].enabled) {
|
||||
printk("scsi_target: %s%d had lun %d enabled\n", bp->h.r_name, bp->h.r_inst, j);
|
||||
scsi_free_disk(bp, j);
|
||||
for (j = 0; j < bp->h.r_nchannels; j++) {
|
||||
for (k = 0; k < MAX_LUN; k++) {
|
||||
if (bp->bchan[j].luns[k].enabled) {
|
||||
printk("scsi_target: %s%d chan %d had lun %d enabled\n", bp->h.r_name, bp->h.r_inst, j, k);
|
||||
scsi_free_disk(bp, j, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
printk("scsi_target: unregistering %s%d\n", bp->h.r_name, bp->h.r_inst);
|
||||
scsi_target_kfree(bp->bchan, sizeof (struct bus_chan) * bp->h.r_nchannels);
|
||||
memset(bp, 0, sizeof (*bp));
|
||||
printk("scsi_target: unregistering %s%d\n", hp->r_name, hp->r_inst);
|
||||
(hp->r_action)(QIN_HBA_UNREG, arg);
|
||||
break;
|
||||
}
|
||||
@@ -2043,7 +2061,7 @@ scsi_target_thread(void *arg)
|
||||
}
|
||||
|
||||
static int
|
||||
scsi_alloc_disk(bus_t *bp, int lun, int overcommit, uint64_t nbytes)
|
||||
scsi_alloc_disk(bus_t *bp, int chan, int lun, int overcommit, uint64_t nbytes)
|
||||
{
|
||||
int i;
|
||||
lun_t *lp;
|
||||
@@ -2061,7 +2079,7 @@ scsi_alloc_disk(bus_t *bp, int lun, int overcommit, uint64_t nbytes)
|
||||
nbytes = rusz;
|
||||
}
|
||||
|
||||
lp = &bp->luns[lun];
|
||||
lp = &bp->bchan[chan].luns[lun];
|
||||
lp->nbytes = nbytes;
|
||||
|
||||
if (overcommit) {
|
||||
@@ -2117,14 +2135,14 @@ scsi_alloc_disk(bus_t *bp, int lun, int overcommit, uint64_t nbytes)
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
scsi_free_disk(bp, lun);
|
||||
scsi_free_disk(bp, chan, lun);
|
||||
return (-ENOMEM);
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_free_disk(bus_t *bp, int lun)
|
||||
scsi_free_disk(bus_t *bp, int chan, int lun)
|
||||
{
|
||||
lun_t *lp = &bp->luns[lun];
|
||||
lun_t *lp = &bp->bchan[chan].luns[lun];
|
||||
|
||||
if (lp->overcommit) {
|
||||
while (lp->pagelists) {
|
||||
@@ -2207,11 +2225,15 @@ scsi_target_start_user_io(sc_io_t *sc)
|
||||
return (-ENXIO);
|
||||
}
|
||||
|
||||
if (sc->channel >= bp->h.r_nchannels) {
|
||||
SDprintk("%s: bad chan (%d)\n", __FUNCTION__, sc->channel);
|
||||
return (-EINVAL);
|
||||
}
|
||||
if (sc->lun >= MAX_LUN) {
|
||||
SDprintk("%s: bad lun (%d)\n", __FUNCTION__, sc->lun);
|
||||
return (-EINVAL);
|
||||
}
|
||||
lp = &bp->luns[sc->lun];
|
||||
lp = &bp->bchan[sc->channel].luns[sc->lun];
|
||||
|
||||
SDprintk2("%s: waiting for a R/W IO operation\n", __FUNCTION__);
|
||||
if (down_interruptible(&lp->sema)) {
|
||||
@@ -2280,11 +2302,15 @@ scsi_target_end_user_io(sc_io_t *sc)
|
||||
return (-ENXIO);
|
||||
}
|
||||
|
||||
if (sc->channel >= bp->h.r_nchannels) {
|
||||
SDprintk("%s: bad chan (%d)\n", __FUNCTION__, sc->channel);
|
||||
return (-EINVAL);
|
||||
}
|
||||
if (sc->lun >= MAX_LUN) {
|
||||
SDprintk("%s: bad lun (%d)\n", __FUNCTION__, sc->lun);
|
||||
return (-EINVAL);
|
||||
}
|
||||
lp = &bp->luns[sc->lun];
|
||||
lp = &bp->bchan[sc->channel].luns[sc->lun];
|
||||
tmd = sc->tag;
|
||||
xact = &tmd->cd_xact;
|
||||
SDprintk2("scsi_target: USER->KERN [%llx] %p err %d len %u\n", tmd->cd_tagval, tmd, sc->err, sc->len);
|
||||
@@ -2332,11 +2358,12 @@ scsi_target_end_user_io(sc_io_t *sc)
|
||||
}
|
||||
|
||||
static int
|
||||
scsi_target_endis(char *hba_name_unit, uint64_t nbytes, int lun, int en)
|
||||
scsi_target_endis(char *hba_name_unit, uint64_t nbytes, int chan, int lun, int en)
|
||||
{
|
||||
DECLARE_MUTEX_LOCKED(rsem);
|
||||
unsigned long flags;
|
||||
enadis_t ec;
|
||||
info_t info;
|
||||
lun_t *lp;
|
||||
bus_t *bp;
|
||||
int rv, i;
|
||||
@@ -2353,18 +2380,22 @@ scsi_target_endis(char *hba_name_unit, uint64_t nbytes, int lun, int en)
|
||||
return (-ENXIO);
|
||||
}
|
||||
|
||||
if (chan < 0 || chan >= bp->h.r_nchannels) {
|
||||
SDprintk("%s: bad chan (%d)\n", __FUNCTION__, chan);
|
||||
return (-EINVAL);
|
||||
}
|
||||
if (lun < 0 || lun >= MAX_LUN) {
|
||||
SDprintk("%s: bad lun (%d)\n", __FUNCTION__, lun);
|
||||
return (-EINVAL);
|
||||
}
|
||||
lp = &bp->luns[lun];
|
||||
lp = &bp->bchan[chan].luns[lun];
|
||||
|
||||
if (en) {
|
||||
if (bp->luns[lun].enabled) {
|
||||
if (lp->enabled) {
|
||||
printk("%s: lun %d already enabled\n", __FUNCTION__, lun);
|
||||
return (-EBUSY);
|
||||
}
|
||||
rv = scsi_alloc_disk(bp, lun, en == 2, nbytes);
|
||||
rv = scsi_alloc_disk(bp, chan, lun, en == 2, nbytes);
|
||||
if (rv) {
|
||||
return (rv);
|
||||
}
|
||||
@@ -2372,10 +2403,21 @@ scsi_target_endis(char *hba_name_unit, uint64_t nbytes, int lun, int en)
|
||||
lp->enabled = 0;
|
||||
}
|
||||
|
||||
memset(&info, 0, sizeof (info));
|
||||
info.i_identity = bp->h.r_identity;
|
||||
info.i_channel = chan;
|
||||
(*bp->h.r_action)(QIN_GETINFO, &info);
|
||||
if (info.i_error) {
|
||||
return (info.i_error);
|
||||
}
|
||||
memset(&ec, 0, sizeof (ec));
|
||||
ec.en_hba = bp->h.r_identity;
|
||||
ec.en_tgt = TGT_ANY;
|
||||
ec.en_lun = lun;
|
||||
if (bp->h.r_type == R_FC) {
|
||||
ec.en_lun = LUN_ANY;
|
||||
} else {
|
||||
ec.en_lun = lun;
|
||||
}
|
||||
ec.en_chan = chan;
|
||||
ec.en_private = &rsem;
|
||||
|
||||
(*bp->h.r_action)(en? QIN_ENABLE : QIN_DISABLE, &ec);
|
||||
@@ -2383,13 +2425,13 @@ scsi_target_endis(char *hba_name_unit, uint64_t nbytes, int lun, int en)
|
||||
|
||||
if (ec.en_error) {
|
||||
SDprintk("%s: HBA returned %d for %s action\n", __FUNCTION__, ec.en_error, en? "enable" : "disable");
|
||||
scsi_free_disk(bp, lun);
|
||||
scsi_free_disk(bp, chan, lun);
|
||||
return (ec.en_error);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&scsi_target_lock, flags);
|
||||
for (i = 0; i < HASH_WIDTH; i++) {
|
||||
ini_t *ini = bp->list[i];
|
||||
ini_t *ini = bp->bchan[chan].list[i];
|
||||
while (ini) {
|
||||
spin_unlock_irqrestore(&scsi_target_lock, flags);
|
||||
add_sdata(ini, invchg);
|
||||
@@ -2400,7 +2442,7 @@ scsi_target_endis(char *hba_name_unit, uint64_t nbytes, int lun, int en)
|
||||
spin_unlock_irqrestore(&scsi_target_lock, flags);
|
||||
|
||||
if (en == 0) {
|
||||
scsi_free_disk(bp, lun);
|
||||
scsi_free_disk(bp, chan, lun);
|
||||
} else {
|
||||
lp->u_tail = lp->u_front = NULL;
|
||||
sema_init(&lp->sema, 0);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: scsi_target.h,v 1.27 2007/07/07 23:20:56 mjacob Exp $ */
|
||||
/* $Id: scsi_target.h,v 1.28 2007/12/02 22:02:07 mjacob Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2007 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -63,7 +63,7 @@
|
||||
* Ioctl Definitions File.
|
||||
*/
|
||||
|
||||
#define _SI ('e' << 8)
|
||||
#define _SI ('j' << 8)
|
||||
|
||||
/*
|
||||
* Set new debugging level (get previous) (int argument).
|
||||
@@ -74,10 +74,11 @@
|
||||
* Enable/Disable lun
|
||||
*/
|
||||
typedef struct {
|
||||
char hba_name_unit[16]; /* e.g., "isp0" */
|
||||
uint64_t nbytes; /* disk size, in bytes */
|
||||
uint16_t lun; /* lun to map it to */
|
||||
uint16_t flags; /* flags */
|
||||
char hba_name_unit[16]; /* e.g., "isp0" */
|
||||
uint64_t nbytes; /* disk size, in bytes */
|
||||
uint16_t lun; /* lun to map it to */
|
||||
uint8_t channel; /* channel */
|
||||
uint8_t flags;
|
||||
} sc_enable_t;
|
||||
#define SC_EF_OVERCOMMIT 0x01 /* allow overcommit */
|
||||
|
||||
@@ -91,7 +92,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
char hba_name_unit[16]; /* e.g., "isp0" */
|
||||
uint16_t lun; /* lun */
|
||||
uint16_t : 14,
|
||||
uint8_t channel;
|
||||
uint8_t : 6,
|
||||
sync : 1, /* (implied) sync after write */
|
||||
read : 1; /* read (from target to initiator) flag */
|
||||
void * tag; /* id tag for this command */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: scsi_target_ctl.c,v 1.19 2007/07/07 23:20:56 mjacob Exp $ */
|
||||
/* $Id: scsi_target_ctl.c,v 1.20 2007/12/02 22:02:07 mjacob Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2007 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -67,6 +67,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "scsi_target.h"
|
||||
|
||||
@@ -74,8 +75,8 @@
|
||||
|
||||
const char usage[] = "usage: %s\n\
|
||||
scsi_target_ctl debug level\n\
|
||||
scsi_target_ctl enable hba-name-unit nbytes lun [ overcommit-file ]\n\
|
||||
scsi_target_ctl disable hba-name-unit lun\n";
|
||||
scsi_target_ctl enable hba-name-unit channel lun nbytes [ overcommit-file ]\n\
|
||||
scsi_target_ctl disable hba-name-unit channel lun\n";
|
||||
|
||||
static uint64_t szarg(char *);
|
||||
static void ioloop(int, int, char *, uint16_t);
|
||||
@@ -102,7 +103,7 @@ main(int a, char **v)
|
||||
|
||||
debug = getenv("DEBUG") != NULL;
|
||||
|
||||
if (a < 3 || a > 6) {
|
||||
if (a < 3 || a > 7) {
|
||||
usage:
|
||||
fprintf(stderr, usage, progname);
|
||||
return (1);
|
||||
@@ -110,29 +111,31 @@ main(int a, char **v)
|
||||
|
||||
memset(&x, 0, sizeof (x));
|
||||
if (strcmp(v[1], "enable") == 0) {
|
||||
if (a < 5) {
|
||||
if (a < 6) {
|
||||
goto usage;
|
||||
}
|
||||
action = SC_ENABLE_LUN;
|
||||
strncpy(x._x.hba_name_unit, v[2], sizeof (x._x.hba_name_unit));
|
||||
x._x.nbytes = szarg(v[3]);
|
||||
x._x.channel = atoi(v[3]);
|
||||
x._x.lun = atoi(v[4]);
|
||||
if (a == 6) {
|
||||
iofd = open(v[5], O_RDWR);
|
||||
x._x.nbytes = szarg(v[5]);
|
||||
if (a == 7) {
|
||||
iofd = open(v[6], O_RDWR);
|
||||
if (iofd < 0) {
|
||||
perror(v[5]);
|
||||
perror(v[6]);
|
||||
return (1);
|
||||
}
|
||||
dprintf("opened %s to back size 0x%016llx bytes\n", v[5], (unsigned long long) x._x.nbytes);
|
||||
dprintf("opened %s to back size 0x%016llx bytes\n", v[6], (unsigned long long) x._x.nbytes);
|
||||
x._x.flags = SC_EF_OVERCOMMIT;
|
||||
}
|
||||
} else if (strcmp(v[1], "disable") == 0) {
|
||||
if (a != 4) {
|
||||
if (a != 5) {
|
||||
goto usage;
|
||||
}
|
||||
action = SC_DISABLE_LUN;
|
||||
strncpy(x._x.hba_name_unit, v[2], sizeof (x._x.hba_name_unit));
|
||||
x._x.lun = atoi(v[3]);
|
||||
x._x.channel = atoi(v[3]);
|
||||
x._x.lun = atoi(v[4]);
|
||||
} else if (strcmp(v[1], "debug") == 0) {
|
||||
if (a != 3) {
|
||||
goto usage;
|
||||
@@ -154,9 +157,16 @@ main(int a, char **v)
|
||||
return (2);
|
||||
}
|
||||
if (action == SC_ENABLE_LUN && iofd != -1) {
|
||||
ioloop(fd, iofd, x._x.hba_name_unit, x._x.lun);
|
||||
}
|
||||
if (action == SC_DEBUG) {
|
||||
pid_t p = fork();
|
||||
if (p == 0) {
|
||||
(void) close(0);
|
||||
(void) close(1);
|
||||
(void) close(2);
|
||||
ioloop(fd, iofd, x._x.hba_name_unit, x._x.lun);
|
||||
} else if (p < 0) {
|
||||
perror("fork");
|
||||
}
|
||||
} else if (action == SC_DEBUG) {
|
||||
printf("old debug level: %d; new debug level %d\n", x._y, dd);
|
||||
}
|
||||
return (0);
|
||||
@@ -217,6 +227,8 @@ ioloop(int fd, int iofd, char *hba, uint16_t lun)
|
||||
int amt;
|
||||
void *buffer = valloc(4 << 20);
|
||||
|
||||
openlog("scsi_target_ctl", LOG_NDELAY|LOG_PID, LOG_DAEMON);
|
||||
|
||||
for (;;) {
|
||||
memset(&sc, 0, sizeof (sc));
|
||||
strcpy(sc.hba_name_unit, hba);
|
||||
@@ -227,24 +239,24 @@ ioloop(int fd, int iofd, char *hba, uint16_t lun)
|
||||
if (errno == EINTR || errno == ENOENT) {
|
||||
continue;
|
||||
}
|
||||
perror("SC_GET_IO");
|
||||
syslog(LOG_ERR, "SC_GET_IO returned %s", strerror(errno));
|
||||
break;
|
||||
}
|
||||
off = (off_t) sc.off;
|
||||
if (lseek(iofd, off, SEEK_SET) != off) {
|
||||
perror("lseek");
|
||||
syslog(LOG_ERR, "lseek error: %s", strerror(errno));
|
||||
break;
|
||||
}
|
||||
if (sc.read) {
|
||||
amt = read(iofd, sc.addr, sc.amt);
|
||||
dprintf(" read %8u @ offset 0x%016llx returns %d\n", sc.amt, (unsigned long long)sc.off, amt);
|
||||
syslog(LOG_DEBUG, "read %8u @ offset 0x%016llx returns %d\n", sc.amt, (unsigned long long)sc.off, amt);
|
||||
} else {
|
||||
amt = write(iofd, sc.addr, sc.amt);
|
||||
dprintf("write %8u @ offset 0x%016llx returns %d\n", sc.amt, (unsigned long long)sc.off, amt);
|
||||
syslog(LOG_DEBUG, "write %8u @ offset 0x%016llx returns %d\n", sc.amt, (unsigned long long)sc.off, amt);
|
||||
if (sc.sync) {
|
||||
if (fdatasync(iofd) < 0) {
|
||||
sc.err = errno;
|
||||
perror("FDATASYNC");
|
||||
syslog(LOG_ERR, "FDATASYNC: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,7 +268,7 @@ ioloop(int fd, int iofd, char *hba, uint16_t lun)
|
||||
sc.len = amt;
|
||||
}
|
||||
if (ioctl(fd, SC_PUT_IO, &sc) < 0) {
|
||||
perror("SC_PUT_IO");
|
||||
syslog(LOG_ERR, "SC_PUT_IO: %s", strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user