Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-for-linus-2.6

This commit is contained in:
Linus Torvalds 2005-07-26 13:28:47 -07:00
commit 2d986010ad
106 changed files with 35019 additions and 30487 deletions

View file

@ -388,7 +388,6 @@ Summary:
scsi_remove_device - detach and remove a SCSI device
scsi_remove_host - detach and remove all SCSI devices owned by host
scsi_report_bus_reset - report scsi _bus_ reset observed
scsi_set_device - place device reference in host structure
scsi_track_queue_full - track successive QUEUE_FULL events
scsi_unblock_requests - allow further commands to be queued to given host
scsi_unregister - [calls scsi_host_put()]
@ -740,20 +739,6 @@ int scsi_remove_host(struct Scsi_Host *shost)
void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)
/**
* scsi_set_device - place device reference in host structure
* @shost: a pointer to a scsi host instance
* @pdev: pointer to device instance to assign
*
* Returns nothing
*
* Might block: no
*
* Defined in: include/scsi/scsi_host.h .
**/
void scsi_set_device(struct Scsi_Host * shost, struct device * dev)
/**
* scsi_track_queue_full - track successive QUEUE_FULL events on given
* device to determine if and when there is a need

View file

@ -365,6 +365,7 @@ void fcp_register(fc_channel *fc, u8 type, int unregister)
kfree (fc->scsi_bitmap);
kfree (fc->cmd_slots);
FCND(("Unregistering\n"));
#if 0
if (fc->rst_pkt) {
if (fc->rst_pkt->eh_state == SCSI_STATE_UNUSED)
kfree(fc->rst_pkt);
@ -373,6 +374,7 @@ void fcp_register(fc_channel *fc, u8 type, int unregister)
printk("FC: Reset in progress. Now?!");
}
}
#endif
FCND(("Unregistered\n"));
}
} else
@ -915,6 +917,7 @@ int fcp_scsi_abort(Scsi_Cmnd *SCpnt)
}
}
#if 0
void fcp_scsi_reset_done(Scsi_Cmnd *SCpnt)
{
fc_channel *fc = FC_SCMND(SCpnt);
@ -922,11 +925,13 @@ void fcp_scsi_reset_done(Scsi_Cmnd *SCpnt)
fc->rst_pkt->eh_state = SCSI_STATE_FINISHED;
up(fc->rst_pkt->device->host->eh_action);
}
#endif
#define FCP_RESET_TIMEOUT (2*HZ)
int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
{
#if 0 /* broken junk, but if davem wants to compile this driver, let him.. */
unsigned long flags;
fcp_cmd *cmd;
fcp_cmnd *fcmd;
@ -1000,6 +1005,7 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
}
fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
return SUCCESS;
#endif
}
static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)

View file

@ -83,19 +83,6 @@ static int mptfcDoneCtx = -1;
static int mptfcTaskCtx = -1;
static int mptfcInternalCtx = -1; /* Used only for internal commands */
static struct device_attribute mptfc_queue_depth_attr = {
.attr = {
.name = "queue_depth",
.mode = S_IWUSR,
},
.store = mptscsih_store_queue_depth,
};
static struct device_attribute *mptfc_dev_attrs[] = {
&mptfc_queue_depth_attr,
NULL,
};
static struct scsi_host_template mptfc_driver_template = {
.proc_name = "mptfc",
.proc_info = mptscsih_proc_info,
@ -105,6 +92,7 @@ static struct scsi_host_template mptfc_driver_template = {
.slave_alloc = mptscsih_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
.eh_bus_reset_handler = mptscsih_bus_reset,
@ -116,7 +104,6 @@ static struct scsi_host_template mptfc_driver_template = {
.max_sectors = 8192,
.cmd_per_lun = 7,
.use_clustering = ENABLE_CLUSTERING,
.sdev_attrs = mptfc_dev_attrs,
};
/****************************************************************************
@ -267,10 +254,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->sg_tablesize = numSGE;
}
/* Set the pci device pointer in Scsi_Host structure.
*/
scsi_set_device(sh, &ioc->pcidev->dev);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
hd = (MPT_SCSI_HOST *) sh->hostdata;

View file

@ -2234,13 +2234,27 @@ mptscsih_slave_destroy(struct scsi_device *device)
}
}
static void
mptscsih_set_queue_depth(struct scsi_device *device, MPT_SCSI_HOST *hd,
VirtDevice *pTarget, int qdepth)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptscsih_change_queue_depth - This function will set a devices queue depth
* @sdev: per scsi_device pointer
* @qdepth: requested queue depth
*
* Adding support for new 'change_queue_depth' api.
*/
int
mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
VirtDevice *pTarget;
int max_depth;
int tagged;
if (hd == NULL)
return 0;
if (!(pTarget = hd->Targets[sdev->id]))
return 0;
if (hd->ioc->bus_type == SCSI) {
if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
@ -2264,10 +2278,10 @@ mptscsih_set_queue_depth(struct scsi_device *device, MPT_SCSI_HOST *hd,
else
tagged = MSG_SIMPLE_TAG;
scsi_adjust_queue_depth(device, tagged, qdepth);
scsi_adjust_queue_depth(sdev, tagged, qdepth);
return sdev->queue_depth;
}
/*
* OS entry point to adjust the queue_depths on a per-device basis.
* Called once per device the bus scan. Use it to force the queue_depth
@ -2317,7 +2331,7 @@ mptscsih_slave_configure(struct scsi_device *device)
mptscsih_initTarget(hd, device->channel, device->id, device->lun,
device->inquiry, device->inquiry_len );
mptscsih_set_queue_depth(device, hd, pTarget, MPT_SCSI_CMD_PER_DEV_HIGH);
mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH);
dsprintk((MYIOC_s_INFO_FMT
"Queue depth=%d, tflags=%x\n",
@ -2337,25 +2351,6 @@ slave_configure_exit:
return 0;
}
ssize_t
mptscsih_store_queue_depth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int depth;
struct scsi_device *sdev = to_scsi_device(dev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) sdev->host->hostdata;
VirtDevice *pTarget;
depth = simple_strtoul(buf, NULL, 0);
if (depth == 0)
return -EINVAL;
pTarget = hd->Targets[sdev->id];
if (pTarget == NULL)
return -EINVAL;
mptscsih_set_queue_depth(sdev, (MPT_SCSI_HOST *) sdev->host->hostdata,
pTarget, depth);
return count;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Private routines...
@ -5586,7 +5581,7 @@ EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
EXPORT_SYMBOL(mptscsih_scandv_complete);
EXPORT_SYMBOL(mptscsih_event_process);
EXPORT_SYMBOL(mptscsih_ioc_reset);
EXPORT_SYMBOL(mptscsih_store_queue_depth);
EXPORT_SYMBOL(mptscsih_change_queue_depth);
EXPORT_SYMBOL(mptscsih_timer_expired);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

View file

@ -103,5 +103,5 @@ extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_F
extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
extern ssize_t mptscsih_store_queue_depth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
extern void mptscsih_timer_expired(unsigned long data);

View file

@ -102,19 +102,6 @@ static int mptspiDoneCtx = -1;
static int mptspiTaskCtx = -1;
static int mptspiInternalCtx = -1; /* Used only for internal commands */
static struct device_attribute mptspi_queue_depth_attr = {
.attr = {
.name = "queue_depth",
.mode = S_IWUSR,
},
.store = mptscsih_store_queue_depth,
};
static struct device_attribute *mptspi_dev_attrs[] = {
&mptspi_queue_depth_attr,
NULL,
};
static struct scsi_host_template mptspi_driver_template = {
.proc_name = "mptspi",
.proc_info = mptscsih_proc_info,
@ -124,6 +111,7 @@ static struct scsi_host_template mptspi_driver_template = {
.slave_alloc = mptscsih_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
.eh_bus_reset_handler = mptscsih_bus_reset,
@ -135,7 +123,6 @@ static struct scsi_host_template mptspi_driver_template = {
.max_sectors = 8192,
.cmd_per_lun = 7,
.use_clustering = ENABLE_CLUSTERING,
.sdev_attrs = mptspi_dev_attrs,
};
@ -287,10 +274,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->sg_tablesize = numSGE;
}
/* Set the pci device pointer in Scsi_Host structure.
*/
scsi_set_device(sh, &ioc->pcidev->dev);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
hd = (MPT_SCSI_HOST *) sh->hostdata;

View file

@ -13,6 +13,7 @@ Supported Cards/Chipsets
Adaptec 2020S
Adaptec 2025S
Adaptec 2120S
Adaptec 2130S
Adaptec 2200S
Adaptec 2230S
Adaptec 2240S
@ -35,6 +36,13 @@ Supported Cards/Chipsets
HP NetRAID-4M
Legend S220
Legend S230
IBM ServeRAID 8i
ICP 9014R0
ICP 9024R0
ICP 9047MA
ICP 9087MA
ICP 9085LI
ICP 5085AU
People
-------------------------

View file

@ -1,6 +1,4 @@
o Testing
o More testing
o Feature request: display the firmware/bios/etc revisions in the
/proc info
o Drop irq_mask, basically unused
o I/O size increase

View file

@ -276,7 +276,6 @@ int aac_get_containers(struct aac_dev *dev)
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
fsa_dev_ptr = (struct fsa_dev_info *) kmalloc(
sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
if (!fsa_dev_ptr) {
@ -527,6 +526,11 @@ static char *container_types[] = {
"V-MIRRORS",
"PSEUDO R4",
"RAID50",
"RAID5D",
"RAID5D0",
"RAID1E",
"RAID6",
"RAID60",
"Unknown"
};
@ -610,7 +614,9 @@ int aac_get_adapter_info(struct aac_dev* dev)
struct fib* fibptr;
int rcode;
u32 tmp;
struct aac_adapter_info * info;
struct aac_adapter_info *info;
struct aac_bus_info *command;
struct aac_bus_info_response *bus_info;
if (!(fibptr = fib_alloc(dev)))
return -ENOMEM;
@ -655,6 +661,36 @@ int aac_get_adapter_info(struct aac_dev* dev)
memcpy(&dev->supplement_adapter_info, info, sizeof(*info));
}
/*
* GetBusInfo
*/
fib_init(fibptr);
bus_info = (struct aac_bus_info_response *) fib_data(fibptr);
memset(bus_info, 0, sizeof(*bus_info));
command = (struct aac_bus_info *)bus_info;
command->Command = cpu_to_le32(VM_Ioctl);
command->ObjType = cpu_to_le32(FT_DRIVE);
command->MethodId = cpu_to_le32(1);
command->CtlCmd = cpu_to_le32(GetBusInfo);
rcode = fib_send(ContainerCommand,
fibptr,
sizeof (*bus_info),
FsaNormal,
1, 1,
NULL, NULL);
if (rcode >= 0 && le32_to_cpu(bus_info->Status) == ST_OK) {
dev->maximum_num_physicals = le32_to_cpu(bus_info->TargetsPerBus);
dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount);
}
tmp = le32_to_cpu(dev->adapter_info.kernelrev);
printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n",
dev->name,
@ -1818,7 +1854,9 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
u32 flag;
u32 timeout;
if( scsicmd->device->id > 15 || scsicmd->device->lun > 7) {
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
if (scsicmd->device->id >= dev->maximum_num_physicals ||
scsicmd->device->lun > 7) {
scsicmd->result = DID_NO_CONNECT << 16;
scsicmd->scsi_done(scsicmd);
return 0;

View file

@ -845,6 +845,28 @@ struct aac_supplement_adapter_info
#define AAC_SIS_VERSION_V3 3
#define AAC_SIS_SLOT_UNKNOWN 0xFF
#define GetBusInfo 0x00000009
struct aac_bus_info {
__le32 Command; /* VM_Ioctl */
__le32 ObjType; /* FT_DRIVE */
__le32 MethodId; /* 1 = SCSI Layer */
__le32 ObjectId; /* Handle */
__le32 CtlCmd; /* GetBusInfo */
};
struct aac_bus_info_response {
__le32 Status; /* ST_OK */
__le32 ObjType;
__le32 MethodId; /* unused */
__le32 ObjectId; /* unused */
__le32 CtlCmd; /* unused */
__le32 ProbeComplete;
__le32 BusCount;
__le32 TargetsPerBus;
u8 InitiatorBusId[10];
u8 BusValid[10];
};
/*
* Battery platforms
*/
@ -934,6 +956,8 @@ struct aac_dev
struct Scsi_Host *scsi_host_ptr;
int maximum_num_containers;
int maximum_num_physicals;
int maximum_num_channels;
struct fsa_dev_info *fsa_dev;
pid_t thread_pid;
int cardtype;

View file

@ -517,7 +517,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
if (dev->dac_support == 1) {
struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
struct sgmap64* psg = (struct sgmap64*)&user_srbcmd->sg;
struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
struct user_sgmap* usg;
byte_count = 0;

View file

@ -102,32 +102,43 @@ static struct pci_device_id aac_pci_tbl[] = {
{ 0x9005, 0x0286, 0x9005, 0x029b, 0, 0, 22 }, /* AAR-2820SA (Intruder) */
{ 0x9005, 0x0286, 0x9005, 0x029c, 0, 0, 23 }, /* AAR-2620SA (Intruder) */
{ 0x9005, 0x0286, 0x9005, 0x029d, 0, 0, 24 }, /* AAR-2420SA (Intruder) */
{ 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 25 }, /* Callisto Jupiter Platform */
{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 26 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 27 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 28 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
{ 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 29 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
{ 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 30 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
{ 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 31 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 32 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
{ 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 33 }, /* AAR-2610SA PCI SATA 6ch */
{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 34 }, /* ASR-2240S (SabreExpress) */
{ 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 35 }, /* ASR-4005SAS */
{ 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 36 }, /* IBM 8i (AvonPark) */
{ 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 37 }, /* ASR-4000SAS (BlackBird) */
{ 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 38 }, /* ASR-4800SAS (Marauder-X) */
{ 0x9005, 0x0285, 0x9005, 0x029A, 0, 0, 39 }, /* ASR-4805SAS (Marauder-E) */
{ 0x9005, 0x0286, 0x9005, 0x029e, 0, 0, 25 }, /* ICP9024R0 (Lancer) */
{ 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014R0 (Lancer) */
{ 0x9005, 0x0286, 0x9005, 0x02a0, 0, 0, 27 }, /* ICP9047MA (Lancer) */
{ 0x9005, 0x0286, 0x9005, 0x02a1, 0, 0, 28 }, /* ICP9087MA (Lancer) */
{ 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */
{ 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */
{ 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */
{ 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 32 }, /* Themisto Jupiter Platform */
{ 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 32 }, /* Themisto Jupiter Platform */
{ 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 33 }, /* Callisto Jupiter Platform */
{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 34 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 35 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 36 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
{ 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 37 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
{ 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 38 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
{ 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 39 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 40 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
{ 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 41 }, /* AAR-2610SA PCI SATA 6ch */
{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 42 }, /* ASR-2240S (SabreExpress) */
{ 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 43 }, /* ASR-4005SAS */
{ 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 44 }, /* IBM 8i (AvonPark) */
{ 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 44 }, /* IBM 8i (AvonPark Lite) */
{ 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 45 }, /* ASR-4000SAS (BlackBird) */
{ 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 46 }, /* ASR-4800SAS (Marauder-X) */
{ 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 47 }, /* ASR-4805SAS (Marauder-E) */
{ 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 48 }, /* ASR-4810SAS (Hurricane */
{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 40 }, /* Perc 320/DC*/
{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 41 }, /* Adaptec 5400S (Mustang)*/
{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 42 }, /* Adaptec 5400S (Mustang)*/
{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 43 }, /* Dell PERC2/QC */
{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 44 }, /* HP NetRAID-4M */
{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 49 }, /* Perc 320/DC*/
{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 50 }, /* Adaptec 5400S (Mustang)*/
{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 51 }, /* Adaptec 5400S (Mustang)*/
{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 52 }, /* Dell PERC2/QC */
{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 53 }, /* HP NetRAID-4M */
{ 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 45 }, /* Dell Catchall */
{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 46 }, /* Legend Catchall */
{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 47 }, /* Adaptec Catch All */
{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 48 }, /* Adaptec Rocket Catch All */
{ 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 54 }, /* Dell Catchall */
{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 55 }, /* Legend Catchall */
{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 56 }, /* Adaptec Catch All */
{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 57 }, /* Adaptec Rocket Catch All */
{ 0,}
};
MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@ -164,6 +175,14 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rkt_init, "aacraid", "ADAPTEC ", "AAR-2820SA ", 1 }, /* AAR-2820SA (Intruder) */
{ aac_rkt_init, "aacraid", "ADAPTEC ", "AAR-2620SA ", 1 }, /* AAR-2620SA (Intruder) */
{ aac_rkt_init, "aacraid", "ADAPTEC ", "AAR-2420SA ", 1 }, /* AAR-2420SA (Intruder) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP9024R0 ", 2 }, /* ICP9024R0 (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP9014R0 ", 1 }, /* ICP9014R0 (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP5085AU ", 1 }, /* ICP5085AU (Hurricane) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */
{ NULL , "aacraid", "ADAPTEC ", "Themisto ", 0, AAC_QUIRK_SLAVE }, /* Jupiter Platform */
{ aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
@ -175,10 +194,11 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005SAS ", 1 }, /* ASR-4005SAS */
{ aac_rx_init, "aacraid", "IBM ", "ServeRAID 8i ", 1 }, /* IBM 8i (AvonPark) */
{ aac_rx_init, "ServeRAID","IBM ", "ServeRAID 8i ", 1 }, /* IBM 8i (AvonPark) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */
{ aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
{ aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
@ -681,7 +701,7 @@ static struct scsi_host_template aac_driver_template = {
.slave_configure = aac_slave_configure,
.eh_host_reset_handler = aac_eh_reset,
.can_queue = AAC_NUM_IO_FIB,
.this_id = 16,
.this_id = MAXIMUM_NUM_CONTAINERS,
.sg_tablesize = 16,
.max_sectors = 128,
#if (AAC_NUM_IO_FIB > 256)
@ -760,6 +780,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
if (pci_set_dma_mask(pdev, 0xFFFFFFFFULL))
goto out_free_fibs;
aac->maximum_num_channels = aac_drivers[index].channels;
aac_get_adapter_info(aac);
/*
@ -786,7 +807,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
* physical channels are address by their actual physical number+1
*/
if (aac->nondasd_support == 1)
shost->max_channel = aac_drivers[index].channels+1;
shost->max_channel = aac->maximum_num_channels + 1;
else
shost->max_channel = 1;
@ -795,6 +816,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
list_add(&aac->entry, insert);
shost->max_id = aac->maximum_num_containers;
if (shost->max_id < aac->maximum_num_physicals)
shost->max_id = aac->maximum_num_physicals;
if (shost->max_id < MAXIMUM_NUM_CONTAINERS)
shost->max_id = MAXIMUM_NUM_CONTAINERS;
else

View file

@ -4556,8 +4556,6 @@ advansys_detect(struct scsi_host_template *tpnt)
continue;
}
scsi_set_device(shp, dev);
/* Save a pointer to the Scsi_Host of each board found. */
asc_host[asc_board_count++] = shp;
@ -9194,8 +9192,8 @@ asc_prt_scsi_cmnd(struct scsi_cmnd *s)
s->sc_data_direction, s->resid);
printk(
" use_sg %u, sglist_len %u, abort_reason 0x%x\n",
s->use_sg, s->sglist_len, s->abort_reason);
" use_sg %u, sglist_len %u\n",
s->use_sg, s->sglist_len);
printk(
" serial_number 0x%x, retries %d, allowed %d\n",

View file

@ -254,19 +254,12 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
if (error != 0)
return (error);
ahc_list_lock(&l);
/*
* Link this softc in with all other ahc instances.
*/
ahc_softc_insert(ahc);
ahc->init_level++;
/*
* Enable the board's BUS drivers
*/
ahc_outb(ahc, BCTL, ENABLE);
ahc_list_unlock(&l);
return (0);
}

View file

@ -102,7 +102,6 @@ aic7770_probe(struct device *dev)
dev_set_drvdata(dev, ahc);
if (aic7xxx_detect_complete)
error = ahc_linux_register_host(ahc, &aic7xxx_driver_template);
return (error);
}

View file

@ -1553,7 +1553,7 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
ahd_queue_scb(ahd, scb);
scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
spin_unlock_irq(&ahd->platform_data->spin_lock);
ahd_unlock(ahd, &s);
init_timer(&timer);
timer.data = (u_long)scb;
timer.expires = jiffies + (5 * HZ);
@ -1567,7 +1567,7 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
printf("Timer Expired\n");
retval = FAILED;
}
spin_lock_irq(&ahd->platform_data->spin_lock);
ahd_lock(ahd, &s);
ahd_schedule_runq(ahd);
ahd_linux_run_complete_queue(ahd);
ahd_unlock(ahd, &s);

View file

@ -1023,9 +1023,6 @@ struct ahc_softc {
struct cs *critical_sections;
u_int num_critical_sections;
/* Links for chaining softcs */
TAILQ_ENTRY(ahc_softc) links;
/* Channel Names ('A', 'B', etc.) */
char channel;
char channel_b;
@ -1110,9 +1107,6 @@ struct ahc_softc {
uint16_t user_tagenable;/* Tagged Queuing allowed */
};
TAILQ_HEAD(ahc_softc_tailq, ahc_softc);
extern struct ahc_softc_tailq ahc_tailq;
/************************ Active Device Information ***************************/
typedef enum {
ROLE_UNKNOWN,
@ -1198,7 +1192,6 @@ void ahc_intr_enable(struct ahc_softc *ahc, int enable);
void ahc_pause_and_flushwork(struct ahc_softc *ahc);
int ahc_suspend(struct ahc_softc *ahc);
int ahc_resume(struct ahc_softc *ahc);
void ahc_softc_insert(struct ahc_softc *);
void ahc_set_unit(struct ahc_softc *, int);
void ahc_set_name(struct ahc_softc *, char *);
void ahc_alloc_scbs(struct ahc_softc *ahc);

View file

@ -52,9 +52,6 @@
#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
#endif
/****************************** Softc Data ************************************/
struct ahc_softc_tailq ahc_tailq = TAILQ_HEAD_INITIALIZER(ahc_tailq);
/***************************** Lookup Tables **********************************/
char *ahc_chip_names[] =
{
@ -3878,62 +3875,6 @@ ahc_softc_init(struct ahc_softc *ahc)
return (0);
}
void
ahc_softc_insert(struct ahc_softc *ahc)
{
struct ahc_softc *list_ahc;
#if AHC_PCI_CONFIG > 0
/*
* Second Function PCI devices need to inherit some
* settings from function 0.
*/
if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI
&& (ahc->features & AHC_MULTI_FUNC) != 0) {
TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
ahc_dev_softc_t list_pci;
ahc_dev_softc_t pci;
list_pci = list_ahc->dev_softc;
pci = ahc->dev_softc;
if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci)
&& ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) {
struct ahc_softc *master;
struct ahc_softc *slave;
if (ahc_get_pci_function(list_pci) == 0) {
master = list_ahc;
slave = ahc;
} else {
master = ahc;
slave = list_ahc;
}
slave->flags &= ~AHC_BIOS_ENABLED;
slave->flags |=
master->flags & AHC_BIOS_ENABLED;
slave->flags &= ~AHC_PRIMARY_CHANNEL;
slave->flags |=
master->flags & AHC_PRIMARY_CHANNEL;
break;
}
}
}
#endif
/*
* Insertion sort into our list of softcs.
*/
list_ahc = TAILQ_FIRST(&ahc_tailq);
while (list_ahc != NULL
&& ahc_softc_comp(ahc, list_ahc) <= 0)
list_ahc = TAILQ_NEXT(list_ahc, links);
if (list_ahc != NULL)
TAILQ_INSERT_BEFORE(list_ahc, ahc, links);
else
TAILQ_INSERT_TAIL(&ahc_tailq, ahc, links);
ahc->init_level++;
}
void
ahc_set_unit(struct ahc_softc *ahc, int unit)
{

View file

@ -136,10 +136,6 @@ static struct scsi_transport_template *ahc_linux_transport_template = NULL;
#include <linux/blkdev.h> /* For block_size() */
#include <linux/delay.h> /* For ssleep/msleep */
/*
* Lock protecting manipulation of the ahc softc list.
*/
spinlock_t ahc_list_spinlock;
/*
* Set this to the delay in seconds after SCSI bus reset.
@ -291,25 +287,6 @@ ahc_print_path(struct ahc_softc *ahc, struct scb *scb)
*/
static uint32_t aic7xxx_no_reset;
/*
* Certain PCI motherboards will scan PCI devices from highest to lowest,
* others scan from lowest to highest, and they tend to do all kinds of
* strange things when they come into contact with PCI bridge chips. The
* net result of all this is that the PCI card that is actually used to boot
* the machine is very hard to detect. Most motherboards go from lowest
* PCI slot number to highest, and the first SCSI controller found is the
* one you boot from. The only exceptions to this are when a controller
* has its BIOS disabled. So, we by default sort all of our SCSI controllers
* from lowest PCI slot number to highest PCI slot number. We also force
* all controllers with their BIOS disabled to the end of the list. This
* works on *almost* all computers. Where it doesn't work, we have this
* option. Setting this option to non-0 will reverse the order of the sort
* to highest first, then lowest, but will still leave cards with their BIOS
* disabled at the very end. That should fix everyone up unless there are
* really strange cirumstances.
*/
static uint32_t aic7xxx_reverse_scan;
/*
* Should we force EXTENDED translation on a controller.
* 0 == Use whatever is in the SEEPROM or default to off
@ -337,13 +314,6 @@ static uint32_t aic7xxx_pci_parity = ~0;
*/
uint32_t aic7xxx_allow_memio = ~0;
/*
* aic7xxx_detect() has been run, so register all device arrivals
* immediately with the system rather than deferring to the sorted
* attachment performed by aic7xxx_detect().
*/
int aic7xxx_detect_complete;
/*
* So that we can set how long each device is given as a selection timeout.
* The table of values goes like this:
@ -423,7 +393,9 @@ static int ahc_linux_run_command(struct ahc_softc*,
static void ahc_linux_setup_tag_info_global(char *p);
static aic_option_callback_t ahc_linux_setup_tag_info;
static int aic7xxx_setup(char *s);
static int ahc_linux_next_unit(void);
static int ahc_linux_unit;
/********************************* Inlines ************************************/
static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
@ -475,48 +447,6 @@ ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
return (consumed);
}
/*
* Try to detect an Adaptec 7XXX controller.
*/
static int
ahc_linux_detect(struct scsi_host_template *template)
{
struct ahc_softc *ahc;
int found = 0;
/*
* If we've been passed any parameters, process them now.
*/
if (aic7xxx)
aic7xxx_setup(aic7xxx);
template->proc_name = "aic7xxx";
/*
* Initialize our softc list lock prior to
* probing for any adapters.
*/
ahc_list_lockinit();
found = ahc_linux_pci_init();
if (!ahc_linux_eisa_init())
found++;
/*
* Register with the SCSI layer all
* controllers we've found.
*/
TAILQ_FOREACH(ahc, &ahc_tailq, links) {
if (ahc_linux_register_host(ahc, template) == 0)
found++;
}
aic7xxx_detect_complete++;
return (found);
}
/*
* Return a string describing the driver.
*/
@ -848,6 +778,7 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd)
struct scsi_host_template aic7xxx_driver_template = {
.module = THIS_MODULE,
.name = "aic7xxx",
.proc_name = "aic7xxx",
.proc_info = ahc_linux_proc_info,
.info = ahc_linux_info,
.queuecommand = ahc_linux_queue,
@ -959,99 +890,6 @@ ahc_dmamap_unload(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map)
return (0);
}
/********************* Platform Dependent Functions ***************************/
/*
* Compare "left hand" softc with "right hand" softc, returning:
* < 0 - lahc has a lower priority than rahc
* 0 - Softcs are equal
* > 0 - lahc has a higher priority than rahc
*/
int
ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc)
{
int value;
int rvalue;
int lvalue;
/*
* Under Linux, cards are ordered as follows:
* 1) VLB/EISA BIOS enabled devices sorted by BIOS address.
* 2) PCI devices with BIOS enabled sorted by bus/slot/func.
* 3) All remaining VLB/EISA devices sorted by ioport.
* 4) All remaining PCI devices sorted by bus/slot/func.
*/
value = (lahc->flags & AHC_BIOS_ENABLED)
- (rahc->flags & AHC_BIOS_ENABLED);
if (value != 0)
/* Controllers with BIOS enabled have a *higher* priority */
return (value);
/*
* Same BIOS setting, now sort based on bus type.
* EISA and VL controllers sort together. EISA/VL
* have higher priority than PCI.
*/
rvalue = (rahc->chip & AHC_BUS_MASK);
if (rvalue == AHC_VL)
rvalue = AHC_EISA;
lvalue = (lahc->chip & AHC_BUS_MASK);
if (lvalue == AHC_VL)
lvalue = AHC_EISA;
value = rvalue - lvalue;
if (value != 0)
return (value);
/* Still equal. Sort by BIOS address, ioport, or bus/slot/func. */
switch (rvalue) {
#ifdef CONFIG_PCI
case AHC_PCI:
{
char primary_channel;
if (aic7xxx_reverse_scan != 0)
value = ahc_get_pci_bus(lahc->dev_softc)
- ahc_get_pci_bus(rahc->dev_softc);
else
value = ahc_get_pci_bus(rahc->dev_softc)
- ahc_get_pci_bus(lahc->dev_softc);
if (value != 0)
break;
if (aic7xxx_reverse_scan != 0)
value = ahc_get_pci_slot(lahc->dev_softc)
- ahc_get_pci_slot(rahc->dev_softc);
else
value = ahc_get_pci_slot(rahc->dev_softc)
- ahc_get_pci_slot(lahc->dev_softc);
if (value != 0)
break;
/*
* On multi-function devices, the user can choose
* to have function 1 probed before function 0.
* Give whichever channel is the primary channel
* the highest priority.
*/
primary_channel = (lahc->flags & AHC_PRIMARY_CHANNEL) + 'A';
value = -1;
if (lahc->channel == primary_channel)
value = 1;
break;
}
#endif
case AHC_EISA:
if ((rahc->flags & AHC_BIOS_ENABLED) != 0) {
value = rahc->platform_data->bios_address
- lahc->platform_data->bios_address;
} else {
value = rahc->bsh.ioport
- lahc->bsh.ioport;
}
break;
default:
panic("ahc_softc_sort: invalid bus type");
}
return (value);
}
static void
ahc_linux_setup_tag_info_global(char *p)
{
@ -1103,7 +941,6 @@ aic7xxx_setup(char *s)
#ifdef AHC_DEBUG
{ "debug", &ahc_debug },
#endif
{ "reverse_scan", &aic7xxx_reverse_scan },
{ "periodic_otag", &aic7xxx_periodic_otag },
{ "pci_parity", &aic7xxx_pci_parity },
{ "seltime", &aic7xxx_seltime },
@ -1178,7 +1015,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
host->max_lun = AHC_NUM_LUNS;
host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;
host->sg_tablesize = AHC_NSEG;
ahc_set_unit(ahc, ahc_linux_next_unit());
ahc_set_unit(ahc, ahc_linux_unit++);
sprintf(buf, "scsi%d", host->host_no);
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
if (new_name != NULL) {
@ -1206,29 +1043,6 @@ ahc_linux_get_memsize(void)
return ((uint64_t)si.totalram << PAGE_SHIFT);
}
/*
* Find the smallest available unit number to use
* for a new device. We don't just use a static
* count to handle the "repeated hot-(un)plug"
* scenario.
*/
static int
ahc_linux_next_unit(void)
{
struct ahc_softc *ahc;
int unit;
unit = 0;
retry:
TAILQ_FOREACH(ahc, &ahc_tailq, links) {
if (ahc->unit == unit) {
unit++;
goto retry;
}
}
return (unit);
}
/*
* Place the SCSI bus into a known state by either resetting it,
* or forcing transfer negotiations on the next command to any
@ -2633,6 +2447,11 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
ahc_unlock(ahc, &flags);
}
#if 0
/* FIXME: This code claims to support IU and QAS. However, the actual
* sequencer code and aic7xxx_core have no support for these parameters and
* will get into a bad state if they're negotiated. Do not enable this
* unless you know what you're doing */
static void ahc_linux_set_qas(struct scsi_target *starget, int qas)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@ -2688,6 +2507,7 @@ static void ahc_linux_set_iu(struct scsi_target *starget, int iu)
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
#endif
static struct spi_function_template ahc_linux_transport_functions = {
.set_offset = ahc_linux_set_offset,
@ -2698,10 +2518,12 @@ static struct spi_function_template ahc_linux_transport_functions = {
.show_width = 1,
.set_dt = ahc_linux_set_dt,
.show_dt = 1,
#if 0
.set_iu = ahc_linux_set_iu,
.show_iu = 1,
.set_qas = ahc_linux_set_qas,
.show_qas = 1,
#endif
};
@ -2709,18 +2531,25 @@ static struct spi_function_template ahc_linux_transport_functions = {
static int __init
ahc_linux_init(void)
{
ahc_linux_transport_template = spi_attach_transport(&ahc_linux_transport_functions);
/*
* If we've been passed any parameters, process them now.
*/
if (aic7xxx)
aic7xxx_setup(aic7xxx);
ahc_linux_transport_template =
spi_attach_transport(&ahc_linux_transport_functions);
if (!ahc_linux_transport_template)
return -ENODEV;
scsi_transport_reserve_target(ahc_linux_transport_template,
sizeof(struct ahc_linux_target));
scsi_transport_reserve_device(ahc_linux_transport_template,
sizeof(struct ahc_linux_device));
if (ahc_linux_detect(&aic7xxx_driver_template))
ahc_linux_pci_init();
ahc_linux_eisa_init();
return 0;
spi_release_transport(ahc_linux_transport_template);
ahc_linux_exit();
return -ENODEV;
}
static void

View file

@ -132,7 +132,6 @@ typedef struct scsi_cmnd *ahc_io_ctx_t;
/************************* Configuration Data *********************************/
extern u_int aic7xxx_no_probe;
extern u_int aic7xxx_allow_memio;
extern int aic7xxx_detect_complete;
extern struct scsi_host_template aic7xxx_driver_template;
/***************************** Bus Space/DMA **********************************/
@ -510,15 +509,6 @@ void ahc_format_transinfo(struct info_str *info,
/******************************** Locking *************************************/
/* Lock protecting internal data structures */
static __inline void ahc_lockinit(struct ahc_softc *);
static __inline void ahc_lock(struct ahc_softc *, unsigned long *flags);
static __inline void ahc_unlock(struct ahc_softc *, unsigned long *flags);
/* Lock held during ahc_list manipulation and ahc softc frees */
extern spinlock_t ahc_list_spinlock;
static __inline void ahc_list_lockinit(void);
static __inline void ahc_list_lock(unsigned long *flags);
static __inline void ahc_list_unlock(unsigned long *flags);
static __inline void
ahc_lockinit(struct ahc_softc *ahc)
@ -538,24 +528,6 @@ ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
spin_unlock_irqrestore(&ahc->platform_data->spin_lock, *flags);
}
static __inline void
ahc_list_lockinit(void)
{
spin_lock_init(&ahc_list_spinlock);
}
static __inline void
ahc_list_lock(unsigned long *flags)
{
spin_lock_irqsave(&ahc_list_spinlock, *flags);
}
static __inline void
ahc_list_unlock(unsigned long *flags)
{
spin_unlock_irqrestore(&ahc_list_spinlock, *flags);
}
/******************************* PCI Definitions ******************************/
/*
* PCIM_xxx: mask to locate subfield in register
@ -892,7 +864,6 @@ int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target,
irqreturn_t
ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
void ahc_platform_flushwork(struct ahc_softc *ahc);
int ahc_softc_comp(struct ahc_softc *, struct ahc_softc *);
void ahc_done(struct ahc_softc*, struct scb*);
void ahc_send_async(struct ahc_softc *, char channel,
u_int target, u_int lun, ac_code, void *);

View file

@ -143,10 +143,6 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
struct ahc_softc *ahc = pci_get_drvdata(pdev);
u_long s;
ahc_list_lock(&s);
TAILQ_REMOVE(&ahc_tailq, ahc, links);
ahc_list_unlock(&s);
ahc_lock(ahc, &s);
ahc_intr_enable(ahc, FALSE);
ahc_unlock(ahc, &s);
@ -208,7 +204,6 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return (-error);
}
pci_set_drvdata(pdev, ahc);
if (aic7xxx_detect_complete)
ahc_linux_register_host(ahc, &aic7xxx_driver_template);
return (0);
}

View file

@ -704,7 +704,6 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
int
ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
{
u_long l;
u_int command;
u_int our_id;
u_int sxfrctl1;
@ -964,12 +963,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
if (error != 0)
return (error);
ahc_list_lock(&l);
/*
* Link this softc in with all other ahc instances.
*/
ahc_softc_insert(ahc);
ahc_list_unlock(&l);
ahc->init_level++;
return (0);
}

View file

@ -155,9 +155,9 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
copy_info(info, "\tUser: ");
ahc_format_transinfo(info, &tinfo->user);
starget = ahc->platform_data->starget[target_offset];
targ = scsi_transport_target_data(starget);
if (targ == NULL)
if (!starget)
return;
targ = scsi_transport_target_data(starget);
copy_info(info, "\tGoal: ");
ahc_format_transinfo(info, &tinfo->goal);

View file

@ -8448,7 +8448,6 @@ aic7xxx_alloc(Scsi_Host_Template *sht, struct aic7xxx_host *temp)
}
p->host_no = host->host_no;
}
scsi_set_device(host, &p->pdev->dev);
return (p);
}

View file

@ -336,7 +336,6 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
DEBUG_PCI(printk(" PciDev->baseaddress[3]= %lx\n",
PciDev->resource[3].start));
scsi_set_device(HostAdapter, &PciDev->dev);
HostAdapter->irq = PciDev->irq; // copy for Scsi layers
// HP Tachlite uses two (255-byte) ranges of Port I/O (lower & upper),

View file

@ -382,7 +382,6 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
{
adpt_hba* pHba = NULL;
struct adpt_device* pDev = NULL; /* dpt per device information */
ulong timeout = jiffies + (TMOUT_SCSI*HZ);
cmd->scsi_done = done;
/*
@ -418,11 +417,6 @@ static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
return 1;
}
if(cmd->eh_state != SCSI_STATE_QUEUED){
// If we are not doing error recovery
mod_timer(&cmd->eh_timeout, timeout);
}
// TODO if the cmd->device if offline then I may need to issue a bus rescan
// followed by a get_lct to see if the device is there anymore
if((pDev = (struct adpt_device*) (cmd->device->hostdata)) == NULL) {

View file

@ -1899,16 +1899,6 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg)
printk("%s: abort, mbox %d, interrupt pending.\n",
ha->board_name, i);
if (SCarg->eh_state == SCSI_STATE_TIMEOUT) {
unmap_dma(i, ha);
SCarg->host_scribble = NULL;
ha->cp_stat[i] = FREE;
printk
("%s, abort, mbox %d, eh_state timeout, pid %ld.\n",
ha->board_name, i, SCarg->pid);
return SUCCESS;
}
return FAILED;
}

View file

@ -449,7 +449,7 @@ static int eata_pio_abort(struct scsi_cmnd *cmd)
{
uint loop = HZ;
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_abort called pid: %ld " "target: %x lun: %x reason %x\n", cmd->pid, cmd->device->id, cmd->device->lun, cmd->abort_reason));
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_abort called pid: %ld " "target: %x lun: %x\n", cmd->pid, cmd->device->id, cmd->device->lun));
while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY)
@ -484,7 +484,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd)
struct scsi_cmnd *sp;
struct Scsi_Host *host = cmd->device->host;
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" " %x lun: %x reason %x\n", cmd->pid, cmd->device->id, cmd->device->lun, cmd->abort_reason));
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" " %x lun: %x\n", cmd->pid, cmd->device->id, cmd->device->lun));
spin_lock_irq(host->host_lock);

View file

@ -938,7 +938,6 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
}
shpnt->irq = interrupt_level;
shpnt->io_port = port_base;
scsi_set_device(shpnt, &pdev->dev);
shpnt->n_io_port = 0x10;
print_banner( shpnt );

View file

@ -4521,9 +4521,7 @@ static int __init gdth_detect(Scsi_Host_Template *shtp)
ha->virt_bus = hdr_channel;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_set_device(shp, &pcistr[ctr].pdev->dev);
#else
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
scsi_set_pci_device(shp, pcistr[ctr].pdev);
#endif
if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)||

View file

@ -180,11 +180,6 @@ static void scsi_host_dev_release(struct device *dev)
scsi_destroy_command_freelist(shost);
kfree(shost->shost_data);
/*
* Some drivers (eg aha1542) do scsi_register()/scsi_unregister()
* during probing without performing a scsi_set_device() in between.
* In this case dev->parent is NULL.
*/
if (parent)
put_device(parent);
kfree(shost);

View file

@ -87,7 +87,7 @@ static int max_channel = 3;
static int init_timeout = 5;
static int max_requests = 50;
#define IBMVSCSI_VERSION "1.5.5"
#define IBMVSCSI_VERSION "1.5.6"
MODULE_DESCRIPTION("IBM Virtual SCSI");
MODULE_AUTHOR("Dave Boutcher");
@ -675,8 +675,6 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
struct viosrp_adapter_info *req;
struct srp_event_struct *evt_struct;
memset(&hostdata->madapter_info, 0x00, sizeof(hostdata->madapter_info));
evt_struct = get_event_struct(&hostdata->pool);
if (!evt_struct) {
printk(KERN_ERR "ibmvscsi: couldn't allocate an event "

View file

@ -33,6 +33,10 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include "ibmvscsi.h"
#include "srp.h"
static char partition_name[97] = "UNKNOWN";
static unsigned int partition_number = -1;
/* ------------------------------------------------------------
* Routines for managing the command/response queue
@ -148,6 +152,48 @@ static void ibmvscsi_task(void *data)
}
}
static void gather_partition_info(void)
{
struct device_node *rootdn;
char *ppartition_name;
unsigned int *p_number_ptr;
/* Retrieve information about this partition */
rootdn = find_path_device("/");
if (!rootdn) {
return;
}
ppartition_name =
get_property(rootdn, "ibm,partition-name", NULL);
if (ppartition_name)
strncpy(partition_name, ppartition_name,
sizeof(partition_name));
p_number_ptr =
(unsigned int *)get_property(rootdn, "ibm,partition-no",
NULL);
if (p_number_ptr)
partition_number = *p_number_ptr;
}
static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
{
memset(&hostdata->madapter_info, 0x00,
sizeof(hostdata->madapter_info));
printk(KERN_INFO "rpa_vscsi: SPR_VERSION: %s\n", SRP_VERSION);
strcpy(hostdata->madapter_info.srp_version, SRP_VERSION);
strncpy(hostdata->madapter_info.partition_name, partition_name,
sizeof(hostdata->madapter_info.partition_name));
hostdata->madapter_info.partition_number = partition_number;
hostdata->madapter_info.mad_version = 1;
hostdata->madapter_info.os_type = 2;
}
/**
* initialize_crq_queue: - Initializes and registers CRQ with hypervisor
* @queue: crq_queue to initialize and register
@ -177,6 +223,9 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
if (dma_mapping_error(queue->msg_token))
goto map_failed;
gather_partition_info();
set_adapter_info(hostdata);
rc = plpar_hcall_norets(H_REG_CRQ,
vdev->unit_address,
queue->msg_token, PAGE_SIZE);
@ -246,6 +295,8 @@ void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
memset(queue->msgs, 0x00, PAGE_SIZE);
queue->cur = 0;
set_adapter_info(hostdata);
/* And re-open it again */
rc = plpar_hcall_norets(H_REG_CRQ,
vdev->unit_address,

View file

@ -28,6 +28,8 @@
#ifndef SRP_H
#define SRP_H
#define SRP_VERSION "16.a"
#define PACKED __attribute__((packed))
enum srp_types {

View file

@ -111,7 +111,7 @@
#define IPS_UNREGISTER_HOSTS(SHT)
#define IPS_ADD_HOST(shost,device) do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0)
#define IPS_REMOVE_HOST(shost) scsi_remove_host(shost)
#define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_device(sh, &(ha)->pcidev->dev)
#define IPS_SCSI_SET_DEVICE(sh,ha) do { } while (0)
#define IPS_PRINTK(level, pcidev, format, arg...) \
dev_printk(level , &((pcidev)->dev) , format , ## arg)
#endif

View file

@ -2866,7 +2866,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
if (qc->dev->class == ATA_DEV_ATAPI && qc->scsicmd) {
struct scsi_cmnd *cmd = qc->scsicmd;
if (!scsi_eh_eflags_chk(cmd, SCSI_EH_CANCEL_CMD)) {
if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) {
/* finish completing original command */
__ata_qc_complete(qc);
@ -3750,7 +3750,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
host->max_channel = 1;
host->unique_id = ata_unique_id++;
host->max_cmd_len = 12;
scsi_set_device(host, ent->dev);
scsi_assign_lock(host, &host_set->lock);
ap->flags = ATA_FLAG_PORT_DISABLED;

View file

@ -1,26 +1,24 @@
#/*******************************************************************
# * This file is part of the Emulex Linux Device Driver for *
# * Enterprise Fibre Channel Host Bus Adapters. *
# * Refer to the README file included with this package for *
# * driver version and adapter support. *
# * Copyright (C) 2004 Emulex Corporation. *
# * Fibre Channel Host Bus Adapters. *
# * Copyright (C) 2004-2005 Emulex. All rights reserved. *
# * EMULEX and SLI are trademarks of Emulex. *
# * www.emulex.com *
# * *
# * This program is free software; you can redistribute it and/or *
# * modify it under the terms of the GNU General Public License *
# * as published by the Free Software Foundation; either version 2 *
# * of the License, or (at your option) any later version. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU General Public License for more details, a copy of which *
# * can be found in the file COPYING included with this package. *
# * modify it under the terms of version 2 of the GNU General *
# * Public License as published by the Free Software Foundation. *
# * This program is distributed in the hope that it will be useful. *
# * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
# * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
# * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
# * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
# * TO BE LEGALLY INVALID. See the GNU General Public License for *
# * more details, a copy of which can be found in the file COPYING *
# * included with this package. *
# *******************************************************************/
######################################################################
#$Id: Makefile 1.58 2005/01/23 19:00:32EST sf_support Exp $
ifneq ($(GCOV),)
EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage
EXTRA_CFLAGS += -O0

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc.h 1.167 2005/04/07 08:47:05EDT sf_support Exp $
*/
struct lpfc_sli2_slim;
#define LPFC_MAX_TARGET 256 /* max targets supported */

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_attr.c 1.24 2005/04/13 11:58:55EDT sf_support Exp $
*/
#include <linux/ctype.h>
#include <linux/pci.h>
#include <linux/interrupt.h>

View file

@ -1,26 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_compat.h 1.32 2005/01/25 17:51:45EST sf_support Exp $
*
* This file provides macros to aid compilation in the Linux 2.4 kernel
* over various platform architectures.
*/

View file

@ -1,27 +1,23 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_crtn.h 1.166 2005/04/07 08:46:47EDT sf_support Exp $
*/
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
@ -195,6 +191,9 @@ int lpfc_sli_issue_iocb_wait_high_priority(struct lpfc_hba * phba,
void lpfc_sli_wake_iocb_high_priority(struct lpfc_hba * phba,
struct lpfc_iocbq * queue1,
struct lpfc_iocbq * queue2);
void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba,
struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb);
void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);

View file

@ -1,26 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_ct.c 1.161 2005/04/13 11:59:01EDT sf_support Exp $
*
* Fibre Channel SCSI LAN Device Driver CT support
*/

View file

@ -1,27 +1,23 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_disc.h 1.61 2005/04/07 08:46:52EDT sf_support Exp $
*/
#define FC_MAX_HOLD_RSCN 32 /* max number of deferred RSCNs */
#define FC_MAX_NS_RSP 65536 /* max size NameServer rsp */
#define FC_MAXLOOP 126 /* max devices supported on a fc loop */

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_els.c 1.186 2005/04/13 14:26:55EDT sf_support Exp $
*/
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
@ -3139,7 +3136,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
case ELS_CMD_PLOGI:
phba->fc_stat.elsRcvPLOGI++;
if (phba->hba_state < LPFC_DISC_AUTH) {
rjt_err = LSEXP_NOTHING_MORE;
rjt_err = 1;
break;
}
lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
@ -3154,7 +3151,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
case ELS_CMD_LOGO:
phba->fc_stat.elsRcvLOGO++;
if (phba->hba_state < LPFC_DISC_AUTH) {
rjt_err = LSEXP_NOTHING_MORE;
rjt_err = 1;
break;
}
lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
@ -3162,7 +3159,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
case ELS_CMD_PRLO:
phba->fc_stat.elsRcvPRLO++;
if (phba->hba_state < LPFC_DISC_AUTH) {
rjt_err = LSEXP_NOTHING_MORE;
rjt_err = 1;
break;
}
lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
@ -3177,7 +3174,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
case ELS_CMD_ADISC:
phba->fc_stat.elsRcvADISC++;
if (phba->hba_state < LPFC_DISC_AUTH) {
rjt_err = LSEXP_NOTHING_MORE;
rjt_err = 1;
break;
}
lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_ADISC);
@ -3185,7 +3182,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
case ELS_CMD_PDISC:
phba->fc_stat.elsRcvPDISC++;
if (phba->hba_state < LPFC_DISC_AUTH) {
rjt_err = LSEXP_NOTHING_MORE;
rjt_err = 1;
break;
}
lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PDISC);
@ -3209,7 +3206,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
case ELS_CMD_PRLI:
phba->fc_stat.elsRcvPRLI++;
if (phba->hba_state < LPFC_DISC_AUTH) {
rjt_err = LSEXP_NOTHING_MORE;
rjt_err = 1;
break;
}
lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
@ -3220,7 +3217,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
break;
default:
/* Unsupported ELS command, reject */
rjt_err = LSEXP_NOTHING_MORE;
rjt_err = 1;
/* Unknown ELS command <elsCmd> received from NPORT <did> */
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
@ -3236,7 +3233,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
if (rjt_err) {
stat.un.b.lsRjtRsvd0 = 0;
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = rjt_err;
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
stat.un.b.vendorUnique = 0;
lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp);
}

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_hbadisc.c 1.266 2005/04/13 11:59:06EDT sf_support Exp $
*/
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/kthread.h>
@ -61,14 +58,7 @@ static void lpfc_disc_timeout_handler(struct lpfc_hba *);
static void
lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
if (!(ndlp->nlp_type & NLP_FABRIC)) {
/* Nodev timeout on NPort <nlp_DID> */
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
"%d:0203 Nodev timeout on NPort x%x "
"Data: x%x x%x x%x\n",
phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, ndlp->nlp_rpi);
}
int warn_on = 0;
spin_lock_irq(phba->host->host_lock);
if (!(ndlp->nlp_flag & NLP_NODEV_TMO)) {
@ -79,12 +69,27 @@ lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
ndlp->nlp_flag &= ~NLP_NODEV_TMO;
if (ndlp->nlp_sid != NLP_NO_SID) {
warn_on = 1;
/* flush the target */
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
}
spin_unlock_irq(phba->host->host_lock);
if (warn_on) {
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
"%d:0203 Nodev timeout on NPort x%x "
"Data: x%x x%x x%x\n",
phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, ndlp->nlp_rpi);
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
"%d:0204 Nodev timeout on NPort x%x "
"Data: x%x x%x x%x\n",
phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, ndlp->nlp_rpi);
}
lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM);
return;
}

View file

@ -1,27 +1,23 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_hw.h 1.37 2005/03/29 19:51:45EST sf_support Exp $
*/
#define FDMI_DID 0xfffffaU
#define NameServer_DID 0xfffffcU
#define SCR_DID 0xfffffdU
@ -2214,20 +2210,20 @@ typedef union {
* SLI-2 specific structures
*/
typedef struct {
uint32_t cmdPutInx;
uint32_t rspGetInx;
} HGP;
struct lpfc_hgp {
__le32 cmdPutInx;
__le32 rspGetInx;
};
typedef struct {
uint32_t cmdGetInx;
uint32_t rspPutInx;
} PGP;
struct lpfc_pgp {
__le32 cmdGetInx;
__le32 rspPutInx;
};
typedef struct _SLI2_DESC {
HGP host[MAX_RINGS];
struct lpfc_hgp host[MAX_RINGS];
uint32_t unused1[16];
PGP port[MAX_RINGS];
struct lpfc_pgp port[MAX_RINGS];
} SLI2_DESC;
typedef union {

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_init.c 1.233 2005/04/13 11:59:09EDT sf_support Exp $
*/
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
@ -780,6 +777,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
pci_read_config_dword(phba->pcidev, PCI_VENDOR_ID, &id);
switch ((id >> 16) & 0xffff) {
case PCI_DEVICE_ID_FIREFLY:
strcpy(str, "LP6000 1");
break;
case PCI_DEVICE_ID_SUPERFLY:
if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)
strcpy(str, "LP7000 1");
@ -837,6 +837,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
case PCI_DEVICE_ID_LP10000S:
strcpy(str, "LP10000-S 2");
break;
default:
memset(str, 0, 16);
break;
}
if (mdp)
sscanf(str, "%s", mdp);
@ -1662,6 +1665,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
static struct pci_device_id lpfc_id_table[] = {
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FIREFLY,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_THOR,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PEGASUS,
@ -1712,6 +1717,7 @@ lpfc_init(void)
int error = 0;
printk(LPFC_MODULE_DESC "\n");
printk(LPFC_COPYRIGHT "\n");
lpfc_transport_template =
fc_attach_transport(&lpfc_transport_functions);

View file

@ -1,27 +1,23 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_logmsg.h 1.32 2005/01/25 17:52:01EST sf_support Exp $
*/
#define LOG_ELS 0x1 /* ELS events */
#define LOG_DISCOVERY 0x2 /* Link discovery events */
#define LOG_MBOX 0x4 /* Mailbox events */

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_mbox.c 1.85 2005/04/13 11:59:11EDT sf_support Exp $
*/
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
@ -422,7 +419,6 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
uint32_t iocbCnt;
int i;
psli->MBhostaddr = (uint32_t *)&phba->slim2p->mbx;
pcbp->maxRing = (psli->num_rings - 1);
iocbCnt = 0;
@ -528,7 +524,7 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
dma_addr_t pdma_addr;
uint32_t bar_low, bar_high;
size_t offset;
HGP hgp;
struct lpfc_hgp hgp;
void __iomem *to_slim;
memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
@ -584,9 +580,9 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
else
phba->slim2p->pcb.hgpAddrHigh = 0;
/* write HGP data to SLIM at the required longword offset */
memset(&hgp, 0, sizeof(HGP));
memset(&hgp, 0, sizeof(struct lpfc_hgp));
to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
lpfc_memcpy_to_slim(to_slim, &hgp, sizeof (HGP));
lpfc_memcpy_to_slim(to_slim, &hgp, sizeof(struct lpfc_hgp));
/* Setup Port Group ring pointer */
offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_mem.c 1.79 2005/04/13 14:25:50EDT sf_support Exp $
*/
#include <linux/mempool.h>
#include <linux/pci.h>
#include <linux/interrupt.h>

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_nportdisc.c 1.179 2005/04/13 11:59:13EDT sf_support Exp $
*/
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
@ -950,8 +947,13 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba,
lpfc_unreg_rpi(phba, ndlp);
return (ndlp->nlp_state);
}
if (ndlp->nlp_type & NLP_FCP_TARGET) {
ndlp->nlp_state = NLP_STE_MAPPED_NODE;
lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST);
} else {
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
}
return (ndlp->nlp_state);
}

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_scsi.c 1.37 2005/04/13 14:27:09EDT sf_support Exp $
*/
#include <linux/pci.h>
#include <linux/interrupt.h>
@ -874,6 +871,7 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
else
icmd->ulpCommand = CMD_CLOSE_XRI_CN;
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) ==
IOCB_ERROR) {
list_add_tail(&abtsiocb->list, lpfc_iocb_list);
@ -1273,4 +1271,5 @@ struct scsi_host_template lpfc_template = {
.cmd_per_lun = LPFC_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = lpfc_host_attrs,
.max_sectors = 0xFFFF,
};

View file

@ -1,27 +1,23 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_scsi.h 1.83 2005/04/07 08:47:43EDT sf_support Exp $
*/
struct lpfc_hba;
#define list_remove_head(list, entry, type, member) \

View file

@ -1,27 +1,24 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_sli.c 1.232 2005/04/13 11:59:16EDT sf_support Exp $
*/
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
@ -225,8 +222,7 @@ lpfc_sli_ringtx_get(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
static IOCB_t *
lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
MAILBOX_t *mbox = (MAILBOX_t *)phba->sli.MBhostaddr;
PGP *pgp = (PGP *)&mbox->us.s2.port[pring->ringno];
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
uint32_t max_cmd_idx = pring->numCiocb;
IOCB_t *iocb = NULL;
@ -411,9 +407,7 @@ lpfc_sli_resume_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
static void
lpfc_sli_turn_on_ring(struct lpfc_hba * phba, int ringno)
{
PGP *pgp =
((PGP *) &
(((MAILBOX_t *)phba->sli.MBhostaddr)->us.s2.port[ringno]));
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[ringno];
/* If the ring is active, flag it */
if (phba->sli.ring[ringno].cmdringaddr) {
@ -537,7 +531,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
/* Get a Mailbox buffer to setup mailbox commands for callback */
if ((pmb = phba->sli.mbox_active)) {
pmbox = &pmb->mb;
mbox = (MAILBOX_t *) phba->sli.MBhostaddr;
mbox = &phba->slim2p->mbx;
/* First check out the status word */
lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof (uint32_t));
@ -905,10 +899,11 @@ static int
lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring, uint32_t mask)
{
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
IOCB_t *irsp = NULL;
IOCB_t *entry = NULL;
struct lpfc_iocbq *cmdiocbq = NULL;
struct lpfc_iocbq rspiocbq;
PGP *pgp;
uint32_t status;
uint32_t portRspPut, portRspMax;
int rc = 1;
@ -920,10 +915,6 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
spin_lock_irqsave(phba->host->host_lock, iflag);
pring->stats.iocb_event++;
/* The driver assumes SLI-2 mode */
pgp = (PGP *) &((MAILBOX_t *) phba->sli.MBhostaddr)
->us.s2.port[pring->ringno];
/*
* The next available response entry should never exceed the maximum
* entries. If it does, treat it as an adapter hardware error.
@ -955,7 +946,17 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
rmb();
while (pring->rspidx != portRspPut) {
irsp = (IOCB_t *) IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
/*
* Fetch an entry off the ring and copy it into a local data
* structure. The copy involves a byte-swap since the
* network byte order and pci byte orders are different.
*/
entry = (IOCB_t *) IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
lpfc_sli_pcimem_bcopy((uint32_t *) entry,
(uint32_t *) &rspiocbq.iocb,
sizeof (IOCB_t));
irsp = &rspiocbq.iocb;
type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK);
pring->stats.iocb_rsp++;
rsp_cmpl++;
@ -987,10 +988,6 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
break;
}
rspiocbq.iocb.un.ulpWord[4] = irsp->un.ulpWord[4];
rspiocbq.iocb.ulpStatus = irsp->ulpStatus;
rspiocbq.iocb.ulpContext = irsp->ulpContext;
rspiocbq.iocb.ulpIoTag = irsp->ulpIoTag;
cmdiocbq = lpfc_sli_txcmpl_ring_iotag_lookup(phba,
pring,
&rspiocbq);
@ -1075,9 +1072,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
struct lpfc_iocbq *cmdiocbp;
struct lpfc_iocbq *saveq;
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
HGP *hgp;
PGP *pgp;
MAILBOX_t *mbox;
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
uint8_t iocb_cmd_type;
lpfc_iocb_type type;
uint32_t status, free_saveq;
@ -1089,11 +1084,6 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
spin_lock_irqsave(phba->host->host_lock, iflag);
pring->stats.iocb_event++;
/* The driver assumes SLI-2 mode */
mbox = (MAILBOX_t *) phba->sli.MBhostaddr;
pgp = (PGP *) & mbox->us.s2.port[pring->ringno];
hgp = (HGP *) & mbox->us.s2.host[pring->ringno];
/*
* The next available response entry should never exceed the maximum
* entries. If it does, treat it as an adapter hardware error.
@ -1738,6 +1728,8 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
return;
}
phba->work_hba_events &= ~WORKER_MBOX_TMO;
pmbox = phba->sli.mbox_active;
mb = &pmbox->mb;
@ -1752,7 +1744,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
phba->sli.sli_flag,
phba->sli.mbox_active);
if (phba->sli.mbox_active == pmbox) {
phba->sli.mbox_active = NULL;
if (pmbox->mbox_cmpl) {
mb->mbxStatus = MBX_NOT_FINISHED;
@ -1761,7 +1752,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
spin_lock_irq(phba->host->host_lock);
}
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
}
spin_unlock_irq(phba->host->host_lock);
lpfc_mbox_abort(phba);
@ -1771,7 +1761,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
int
lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
{
MAILBOX_t *mbox;
MAILBOX_t *mb;
struct lpfc_sli *psli;
uint32_t status, evtctr;
@ -1901,15 +1890,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
mb->mbxOwner = OWN_CHIP;
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First copy command data to host SLIM area */
mbox = (MAILBOX_t *) psli->MBhostaddr;
lpfc_sli_pcimem_bcopy(mb, mbox, MAILBOX_CMD_SIZE);
lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE);
} else {
if (mb->mbxCommand == MBX_CONFIG_PORT) {
/* copy command data into host mbox for cmpl */
mbox = (MAILBOX_t *) psli->MBhostaddr;
lpfc_sli_pcimem_bcopy(mb, mbox, MAILBOX_CMD_SIZE);
lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx,
MAILBOX_CMD_SIZE);
}
/* First copy mbox command data to HBA SLIM, skip past first
@ -1946,8 +1933,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
psli->mbox_active = NULL;
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First read mbox status word */
mbox = (MAILBOX_t *) psli->MBhostaddr;
word0 = *((volatile uint32_t *)mbox);
word0 = *((volatile uint32_t *)&phba->slim2p->mbx);
word0 = le32_to_cpu(word0);
} else {
/* First read mbox status word */
@ -1984,8 +1970,8 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First copy command data */
mbox = (MAILBOX_t *) psli->MBhostaddr;
word0 = *((volatile uint32_t *)mbox);
word0 = *((volatile uint32_t *)
&phba->slim2p->mbx);
word0 = le32_to_cpu(word0);
if (mb->mbxCommand == MBX_CONFIG_PORT) {
MAILBOX_t *slimmb;
@ -2009,10 +1995,9 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
}
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First copy command data */
mbox = (MAILBOX_t *) psli->MBhostaddr;
/* copy results back to user */
lpfc_sli_pcimem_bcopy(mbox, mb, MAILBOX_CMD_SIZE);
lpfc_sli_pcimem_bcopy(&phba->slim2p->mbx, mb,
MAILBOX_CMD_SIZE);
} else {
/* First copy command data */
lpfc_memcpy_from_slim(mb, phba->MBslimaddr,
@ -2089,8 +2074,6 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
switch (piocb->iocb.ulpCommand) {
case CMD_QUE_RING_BUF_CN:
case CMD_QUE_RING_BUF64_CN:
case CMD_CLOSE_XRI_CN:
case CMD_ABORT_XRI_CN:
/*
* For IOCBs, like QUE_RING_BUF, that have no rsp ring
* completion, iocb_cmpl MUST be 0.
@ -2573,6 +2556,16 @@ lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return sum;
}
void
lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb)
{
spin_lock_irq(phba->host->host_lock);
list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list);
spin_unlock_irq(phba->host->host_lock);
return;
}
int
lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
uint16_t tgt_id, uint64_t lun_id, uint32_t ctx,
@ -2622,6 +2615,8 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
else
abtsiocb->iocb.ulpCommand = CMD_CLOSE_XRI_CN;
/* Setup callback routine and issue the command. */
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
ret_val = lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0);
if (ret_val == IOCB_ERROR) {
list_add_tail(&abtsiocb->list, lpfc_iocb_list);

View file

@ -1,27 +1,23 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_sli.h 1.42 2005/03/21 02:01:28EST sf_support Exp $
*/
/* forward declaration for LPFC_IOCB_t's use */
struct lpfc_hba;

View file

@ -1,32 +1,29 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Enterprise Fibre Channel Host Bus Adapters. *
* Refer to the README file included with this package for *
* driver version and adapter support. *
* Copyright (C) 2004 Emulex Corporation. *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details, a copy of which *
* can be found in the file COPYING included with this package. *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
/*
* $Id: lpfc_version.h 1.49 2005/04/13 15:07:19EDT sf_support Exp $
*/
#define LPFC_DRIVER_VERSION "8.0.28"
#define LPFC_DRIVER_VERSION "8.0.29"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
LPFC_DRIVER_VERSION
#define LPFC_COPYRIGHT "Copyright(c) 2004-2005 Emulex. All rights reserved."
#define DFC_API_VERSION "0.0.0"

View file

@ -35,6 +35,7 @@
#include <linux/blkdev.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/reboot.h>
@ -1938,7 +1939,7 @@ megaraid_abort(Scsi_Cmnd *cmd)
static int
__megaraid_reset(Scsi_Cmnd *cmd)
megaraid_reset(struct scsi_cmnd *cmd)
{
adapter_t *adapter;
megacmd_t mc;
@ -1950,7 +1951,6 @@ __megaraid_reset(Scsi_Cmnd *cmd)
mc.cmd = MEGA_CLUSTER_CMD;
mc.opcode = MEGA_RESET_RESERVATIONS;
spin_unlock_irq(&adapter->lock);
if( mega_internal_command(adapter, LOCK_INT, &mc, NULL) != 0 ) {
printk(KERN_WARNING
"megaraid: reservation reset failed.\n");
@ -1958,9 +1958,10 @@ __megaraid_reset(Scsi_Cmnd *cmd)
else {
printk(KERN_INFO "megaraid: reservation reset.\n");
}
spin_lock_irq(&adapter->lock);
#endif
spin_lock_irq(&adapter->lock);
rval = megaraid_abort_and_reset(adapter, cmd, SCB_RESET);
/*
@ -1968,24 +1969,11 @@ __megaraid_reset(Scsi_Cmnd *cmd)
* to be communicated over to the mid layer.
*/
mega_rundoneq(adapter);
spin_unlock_irq(&adapter->lock);
return rval;
}
static int
megaraid_reset(Scsi_Cmnd *cmd)
{
adapter_t *adapter = (adapter_t *)cmd->device->host->hostdata;
int rc;
spin_lock_irq(&adapter->lock);
rc = __megaraid_reset(cmd);
spin_unlock_irq(&adapter->lock);
return rc;
}
/**
* megaraid_abort_and_reset()
* @adapter - megaraid soft state
@ -4490,8 +4478,6 @@ mega_internal_command(adapter_t *adapter, lockscope_t ls, megacmd_t *mc,
scb->idx = CMDID_INT_CMDS;
scmd->state = 0;
/*
* Get the lock only if the caller has not acquired it already
*/
@ -4501,15 +4487,7 @@ mega_internal_command(adapter_t *adapter, lockscope_t ls, megacmd_t *mc,
if( ls == LOCK_INT ) spin_unlock_irqrestore(&adapter->lock, flags);
/*
* Wait till this command finishes. Do not use
* wait_event_interruptible(). It causes panic if CTRL-C is hit when
* dumping e.g., physical disk information through /proc interface.
*/
#if 0
wait_event_interruptible(adapter->int_waitq, scmd->state);
#endif
wait_event(adapter->int_waitq, scmd->state);
wait_for_completion(&adapter->int_waitq);
rval = scmd->result;
mc->status = scmd->result;
@ -4543,16 +4521,7 @@ mega_internal_done(Scsi_Cmnd *scmd)
adapter = (adapter_t *)scmd->device->host->hostdata;
scmd->state = 1; /* thread waiting for its command to complete */
/*
* See comment in mega_internal_command() routine for
* wait_event_interruptible()
*/
#if 0
wake_up_interruptible(&adapter->int_waitq);
#endif
wake_up(&adapter->int_waitq);
complete(&adapter->int_waitq);
}
@ -4874,7 +4843,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
init_MUTEX(&adapter->int_mtx);
init_waitqueue_head(&adapter->int_waitq);
init_completion(&adapter->int_waitq);
adapter->this_id = DEFAULT_INITIATOR_ID;
adapter->host->this_id = DEFAULT_INITIATOR_ID;

View file

@ -891,7 +891,7 @@ typedef struct {
Scsi_Cmnd int_scmd;
struct semaphore int_mtx; /* To synchronize the internal
commands */
wait_queue_head_t int_waitq; /* wait queue for internal
struct completion int_waitq; /* wait queue for internal
cmds */
int has_cluster; /* cluster support on this HBA */

View file

@ -719,7 +719,6 @@ megaraid_io_attach(adapter_t *adapter)
// export the parameters required by the mid-layer
scsi_assign_lock(host, adapter->host_lock);
scsi_set_device(host, &adapter->pdev->dev);
host->irq = adapter->irq;
host->unique_id = adapter->unique_id;

View file

@ -7756,7 +7756,6 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt,
* your module_init */
BUG_ON(!ncr53c8xx_transport_template);
instance->transportt = ncr53c8xx_transport_template;
scsi_set_device(instance, device->dev);
/* Patch script to physical addresses */
ncr_script_fill(&script0, &scripth0);

View file

@ -2719,9 +2719,7 @@ static int nsp32_detect(Scsi_Host_Template *sht)
host->unique_id = data->BaseAddress;
host->n_io_port = data->NumAddress;
host->base = (unsigned long)data->MmioAddress;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,63))
scsi_set_device(host, &PCIDEV->dev);
#else
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,63))
scsi_set_pci_device(host, PCIDEV);
#endif

View file

@ -2853,7 +2853,7 @@ qla1280_bus_reset(struct scsi_qla_host *ha, int bus)
ha->bus_settings[bus].failed_reset_count++;
} else {
spin_unlock_irq(HOST_LOCK);
schedule_timeout(reset_delay * HZ);
ssleep(reset_delay);
spin_lock_irq(HOST_LOCK);
ha->bus_settings[bus].scsi_bus_dead = 0;

View file

@ -1,4 +1,6 @@
EXTRA_CFLAGS += -DUNIQUE_FW_NAME
CONFIG_SCSI_QLA24XX=m
EXTRA_CFLAGS += -DCONFIG_SCSI_QLA24XX -DCONFIG_SCSI_QLA24XX_MODULE
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o
@ -14,3 +16,4 @@ obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o
obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.o
obj-$(CONFIG_SCSI_QLA2322) += qla2xxx.o qla2322.o
obj-$(CONFIG_SCSI_QLA6312) += qla2xxx.o qla6312.o
obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o

View file

@ -1,7 +1,7 @@
/*
* QLogic ISP2100 device driver for Linux 2.6.x
* Copyright (C) 2003 Christoph Hellwig.
* Copyright (C) 2003-2004 QLogic Corporation (www.qlogic.com)
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
*
* Released under GPL v2.
*/

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*
* QLogic ISP2200 device driver for Linux 2.6.x
* Copyright (C) 2003 Christoph Hellwig.
* Copyright (C) 2003-2004 QLogic Corporation (www.qlogic.com)
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
*
* Released under GPL v2.
*/

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*
* QLogic ISP2300 device driver for Linux 2.6.x
* Copyright (C) 2003 Christoph Hellwig.
* Copyright (C) 2003-2004 QLogic Corporation (www.qlogic.com)
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
*
* Released under GPL v2.
*/

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
* QLogic ISP2322 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation (www.qlogic.com)
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
*
* Released under GPL v2.
*/

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
* QLogic ISP6312 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation (www.qlogic.com)
* Copyright (C) 2003-2005 QLogic Corporation (www.qlogic.com)
*
* Released under GPL v2.
*/

File diff suppressed because it is too large Load diff

View file

@ -63,23 +63,29 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
ha->host_no);
vfree(ha->fw_dump_buffer);
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha))
free_pages((unsigned long)ha->fw_dump,
ha->fw_dump_order);
ha->fw_dump_reading = 0;
ha->fw_dump_buffer = NULL;
ha->fw_dump = NULL;
ha->fw_dumped = 0;
}
break;
case 1:
if (ha->fw_dump != NULL && !ha->fw_dump_reading) {
if ((ha->fw_dump || ha->fw_dumped) && !ha->fw_dump_reading) {
ha->fw_dump_reading = 1;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
dump_size = FW_DUMP_SIZE_24XX;
else {
dump_size = FW_DUMP_SIZE_1M;
if (ha->fw_memory_size < 0x20000)
dump_size = FW_DUMP_SIZE_128K;
else if (ha->fw_memory_size < 0x80000)
dump_size = FW_DUMP_SIZE_512K;
}
ha->fw_dump_buffer = (char *)vmalloc(dump_size);
if (ha->fw_dump_buffer == NULL) {
qla_printk(KERN_WARNING, ha,
@ -93,10 +99,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
"Firmware dump ready for read on (%ld).\n",
ha->host_no);
memset(ha->fw_dump_buffer, 0, dump_size);
if (IS_QLA2100(ha) || IS_QLA2200(ha))
qla2100_ascii_fw_dump(ha);
else
qla2300_ascii_fw_dump(ha);
ha->isp_ops.ascii_fw_dump(ha);
ha->fw_dump_buffer_len = strlen(ha->fw_dump_buffer);
}
break;
@ -121,23 +124,15 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
uint16_t *witer;
unsigned long flags;
uint16_t cnt;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != sizeof(nvram_t))
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
return 0;
/* Read NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags);
qla2x00_lock_nvram_access(ha);
witer = (uint16_t *)buf;
for (cnt = 0; cnt < count / 2; cnt++) {
*witer = cpu_to_le16(qla2x00_get_nvram_word(ha,
cnt+ha->nvram_base));
witer++;
}
qla2x00_unlock_nvram_access(ha);
ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->nvram_base,
ha->nvram_size);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return (count);
@ -149,34 +144,38 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
uint8_t *iter;
uint16_t *witer;
unsigned long flags;
uint16_t cnt;
uint8_t chksum;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != sizeof(nvram_t))
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
return 0;
/* Checksum NVRAM. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
uint32_t *iter;
uint32_t chksum;
iter = (uint32_t *)buf;
chksum = 0;
for (cnt = 0; cnt < ((count >> 2) - 1); cnt++)
chksum += le32_to_cpu(*iter++);
chksum = ~chksum + 1;
*iter = cpu_to_le32(chksum);
} else {
uint8_t *iter;
uint8_t chksum;
iter = (uint8_t *)buf;
chksum = 0;
for (cnt = 0; cnt < count - 1; cnt++)
chksum += *iter++;
chksum = ~chksum + 1;
*iter = chksum;
}
/* Write NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags);
qla2x00_lock_nvram_access(ha);
qla2x00_release_nvram_protection(ha);
witer = (uint16_t *)buf;
for (cnt = 0; cnt < count / 2; cnt++) {
qla2x00_write_nvram_word(ha, cnt+ha->nvram_base,
cpu_to_le16(*witer));
witer++;
}
qla2x00_unlock_nvram_access(ha);
ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return (count);
@ -188,7 +187,7 @@ static struct bin_attribute sysfs_nvram_attr = {
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = sizeof(nvram_t),
.size = 0,
.read = qla2x00_sysfs_read_nvram,
.write = qla2x00_sysfs_write_nvram,
};
@ -199,6 +198,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
struct Scsi_Host *host = ha->host;
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
sysfs_nvram_attr.size = ha->nvram_size;
sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
}

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -230,4 +230,36 @@ struct qla2100_fw_dump {
uint16_t risc_ram[0xf000];
};
#define FW_DUMP_SIZE_24XX 0x2B0000
struct qla24xx_fw_dump {
uint32_t hccr;
uint32_t host_reg[32];
uint16_t mailbox_reg[32];
uint32_t xseq_gp_reg[128];
uint32_t xseq_0_reg[16];
uint32_t xseq_1_reg[16];
uint32_t rseq_gp_reg[128];
uint32_t rseq_0_reg[16];
uint32_t rseq_1_reg[16];
uint32_t rseq_2_reg[16];
uint32_t cmd_dma_reg[16];
uint32_t req0_dma_reg[15];
uint32_t resp0_dma_reg[15];
uint32_t req1_dma_reg[15];
uint32_t xmt0_dma_reg[32];
uint32_t xmt1_dma_reg[32];
uint32_t xmt2_dma_reg[32];
uint32_t xmt3_dma_reg[32];
uint32_t xmt4_dma_reg[32];
uint32_t xmt_data_dma_reg[16];
uint32_t rcvt0_data_dma_reg[32];
uint32_t rcvt1_data_dma_reg[32];
uint32_t risc_gp_reg[128];
uint32_t shadow_reg[7];
uint32_t lmc_reg[112];
uint32_t fpm_hdw_reg[192];
uint32_t fb_hdw_reg[176];
uint32_t code_ram[0x2000];
uint32_t ext_mem[1];
};

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -33,6 +33,7 @@
#include <linux/mempool.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <asm/semaphore.h>
#include <scsi/scsi.h>
@ -40,27 +41,6 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
/* XXX(hch): move to pci_ids.h */
#ifndef PCI_DEVICE_ID_QLOGIC_ISP2300
#define PCI_DEVICE_ID_QLOGIC_ISP2300 0x2300
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP2312
#define PCI_DEVICE_ID_QLOGIC_ISP2312 0x2312
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP2322
#define PCI_DEVICE_ID_QLOGIC_ISP2322 0x2322
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP6312
#define PCI_DEVICE_ID_QLOGIC_ISP6312 0x6312
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP6322
#define PCI_DEVICE_ID_QLOGIC_ISP6322 0x6322
#endif
#if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE)
#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100)
#else
@ -95,9 +75,28 @@
#define IS_QLA6322(ha) 0
#endif
#if defined(CONFIG_SCSI_QLA24XX) || defined(CONFIG_SCSI_QLA24XX_MODULE)
#define IS_QLA2422(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422)
#define IS_QLA2432(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
#else
#define IS_QLA2422(ha) 0
#define IS_QLA2432(ha) 0
#endif
#if defined(CONFIG_SCSI_QLA25XX) || defined(CONFIG_SCSI_QLA25XX_MODULE)
#define IS_QLA2512(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2512)
#define IS_QLA2522(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2522)
#else
#define IS_QLA2512(ha) 0
#define IS_QLA2522(ha) 0
#endif
#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
IS_QLA6312(ha) || IS_QLA6322(ha))
#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha))
#define IS_QLA25XX(ha) (IS_QLA2512(ha) || IS_QLA2522(ha))
/*
* Only non-ISP2[12]00 have extended addressing support in the firmware.
*/
@ -182,7 +181,7 @@
*/
#define WWN_SIZE 8 /* Size of WWPN, WWN & WWNN */
#define MAX_FIBRE_DEVICES 512
#define MAX_FIBRE_LUNS 256
#define MAX_FIBRE_LUNS 0xFFFF
#define MAX_RSCN_COUNT 32
#define MAX_HOST_COUNT 16
@ -192,7 +191,6 @@
#define MAX_BUSES 1 /* We only have one bus today */
#define MAX_TARGETS_2100 MAX_FIBRE_DEVICES
#define MAX_TARGETS_2200 MAX_FIBRE_DEVICES
#define MAX_TARGETS MAX_FIBRE_DEVICES
#define MIN_LUNS 8
#define MAX_LUNS MAX_FIBRE_LUNS
#define MAX_CMDS_PER_LUN 255
@ -211,10 +209,18 @@
#define MANAGEMENT_SERVER 0xfe
#define BROADCAST 0xff
#define RESERVED_LOOP_ID(x) ((x > LAST_LOCAL_LOOP_ID && \
x < SNS_FIRST_LOOP_ID) || \
x == MANAGEMENT_SERVER || \
x == BROADCAST)
/*
* There is no correspondence between an N-PORT id and an AL_PA. Therefore the
* valid range of an N-PORT id is 0 through 0x7ef.
*/
#define NPH_LAST_HANDLE 0x7ef
#define NPH_SNS 0x7fc /* FFFFFC */
#define NPH_FABRIC_CONTROLLER 0x7fd /* FFFFFD */
#define NPH_F_PORT 0x7fe /* FFFFFE */
#define NPH_IP_BROADCAST 0x7ff /* FFFFFF */
#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
#include "qla_fw.h"
/*
* Timeout timer counts in seconds
@ -231,6 +237,7 @@
#define REQUEST_ENTRY_CNT_2100 128 /* Number of request entries. */
#define REQUEST_ENTRY_CNT_2200 2048 /* Number of request entries. */
#define REQUEST_ENTRY_CNT_2XXX_EXT_MEM 4096 /* Number of request entries. */
#define REQUEST_ENTRY_CNT_24XX 4096 /* Number of request entries. */
#define RESPONSE_ENTRY_CNT_2100 64 /* Number of response entries.*/
#define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/
@ -299,24 +306,24 @@ typedef struct srb {
/*
* ISP I/O Register Set structure definitions.
*/
typedef volatile struct {
volatile uint16_t flash_address; /* Flash BIOS address */
volatile uint16_t flash_data; /* Flash BIOS data */
struct device_reg_2xxx {
uint16_t flash_address; /* Flash BIOS address */
uint16_t flash_data; /* Flash BIOS data */
uint16_t unused_1[1]; /* Gap */
volatile uint16_t ctrl_status; /* Control/Status */
uint16_t ctrl_status; /* Control/Status */
#define CSR_FLASH_64K_BANK BIT_3 /* Flash upper 64K bank select */
#define CSR_FLASH_ENABLE BIT_1 /* Flash BIOS Read/Write enable */
#define CSR_ISP_SOFT_RESET BIT_0 /* ISP soft reset */
volatile uint16_t ictrl; /* Interrupt control */
uint16_t ictrl; /* Interrupt control */
#define ICR_EN_INT BIT_15 /* ISP enable interrupts. */
#define ICR_EN_RISC BIT_3 /* ISP enable RISC interrupts. */
volatile uint16_t istatus; /* Interrupt status */
uint16_t istatus; /* Interrupt status */
#define ISR_RISC_INT BIT_3 /* RISC interrupt */
volatile uint16_t semaphore; /* Semaphore */
volatile uint16_t nvram; /* NVRAM register. */
uint16_t semaphore; /* Semaphore */
uint16_t nvram; /* NVRAM register. */
#define NVR_DESELECT 0
#define NVR_BUSY BIT_15
#define NVR_WRT_ENABLE BIT_14 /* Write enable */
@ -328,78 +335,78 @@ typedef volatile struct {
union {
struct {
volatile uint16_t mailbox0;
volatile uint16_t mailbox1;
volatile uint16_t mailbox2;
volatile uint16_t mailbox3;
volatile uint16_t mailbox4;
volatile uint16_t mailbox5;
volatile uint16_t mailbox6;
volatile uint16_t mailbox7;
uint16_t mailbox0;
uint16_t mailbox1;
uint16_t mailbox2;
uint16_t mailbox3;
uint16_t mailbox4;
uint16_t mailbox5;
uint16_t mailbox6;
uint16_t mailbox7;
uint16_t unused_2[59]; /* Gap */
} __attribute__((packed)) isp2100;
struct {
/* Request Queue */
volatile uint16_t req_q_in; /* In-Pointer */
volatile uint16_t req_q_out; /* Out-Pointer */
uint16_t req_q_in; /* In-Pointer */
uint16_t req_q_out; /* Out-Pointer */
/* Response Queue */
volatile uint16_t rsp_q_in; /* In-Pointer */
volatile uint16_t rsp_q_out; /* Out-Pointer */
uint16_t rsp_q_in; /* In-Pointer */
uint16_t rsp_q_out; /* Out-Pointer */
/* RISC to Host Status */
volatile uint32_t host_status;
uint32_t host_status;
#define HSR_RISC_INT BIT_15 /* RISC interrupt */
#define HSR_RISC_PAUSED BIT_8 /* RISC Paused */
/* Host to Host Semaphore */
volatile uint16_t host_semaphore;
uint16_t host_semaphore;
uint16_t unused_3[17]; /* Gap */
volatile uint16_t mailbox0;
volatile uint16_t mailbox1;
volatile uint16_t mailbox2;
volatile uint16_t mailbox3;
volatile uint16_t mailbox4;
volatile uint16_t mailbox5;
volatile uint16_t mailbox6;
volatile uint16_t mailbox7;
volatile uint16_t mailbox8;
volatile uint16_t mailbox9;
volatile uint16_t mailbox10;
volatile uint16_t mailbox11;
volatile uint16_t mailbox12;
volatile uint16_t mailbox13;
volatile uint16_t mailbox14;
volatile uint16_t mailbox15;
volatile uint16_t mailbox16;
volatile uint16_t mailbox17;
volatile uint16_t mailbox18;
volatile uint16_t mailbox19;
volatile uint16_t mailbox20;
volatile uint16_t mailbox21;
volatile uint16_t mailbox22;
volatile uint16_t mailbox23;
volatile uint16_t mailbox24;
volatile uint16_t mailbox25;
volatile uint16_t mailbox26;
volatile uint16_t mailbox27;
volatile uint16_t mailbox28;
volatile uint16_t mailbox29;
volatile uint16_t mailbox30;
volatile uint16_t mailbox31;
volatile uint16_t fb_cmd;
uint16_t mailbox0;
uint16_t mailbox1;
uint16_t mailbox2;
uint16_t mailbox3;
uint16_t mailbox4;
uint16_t mailbox5;
uint16_t mailbox6;
uint16_t mailbox7;
uint16_t mailbox8;
uint16_t mailbox9;
uint16_t mailbox10;
uint16_t mailbox11;
uint16_t mailbox12;
uint16_t mailbox13;
uint16_t mailbox14;
uint16_t mailbox15;
uint16_t mailbox16;
uint16_t mailbox17;
uint16_t mailbox18;
uint16_t mailbox19;
uint16_t mailbox20;
uint16_t mailbox21;
uint16_t mailbox22;
uint16_t mailbox23;
uint16_t mailbox24;
uint16_t mailbox25;
uint16_t mailbox26;
uint16_t mailbox27;
uint16_t mailbox28;
uint16_t mailbox29;
uint16_t mailbox30;
uint16_t mailbox31;
uint16_t fb_cmd;
uint16_t unused_4[10]; /* Gap */
} __attribute__((packed)) isp2300;
} u;
volatile uint16_t fpm_diag_config;
uint16_t fpm_diag_config;
uint16_t unused_5[0x6]; /* Gap */
volatile uint16_t pcr; /* Processor Control Register. */
uint16_t pcr; /* Processor Control Register. */
uint16_t unused_6[0x5]; /* Gap */
volatile uint16_t mctr; /* Memory Configuration and Timing. */
uint16_t mctr; /* Memory Configuration and Timing. */
uint16_t unused_7[0x3]; /* Gap */
volatile uint16_t fb_cmd_2100; /* Unused on 23XX */
uint16_t fb_cmd_2100; /* Unused on 23XX */
uint16_t unused_8[0x3]; /* Gap */
volatile uint16_t hccr; /* Host command & control register. */
uint16_t hccr; /* Host command & control register. */
#define HCCR_HOST_INT BIT_7 /* Host interrupt bit */
#define HCCR_RISC_PAUSE BIT_5 /* Pause mode bit */
/* HCCR commands */
@ -413,8 +420,8 @@ typedef volatile struct {
#define HCCR_ENABLE_PARITY 0xA000 /* Enable PARITY interrupt */
uint16_t unused_9[5]; /* Gap */
volatile uint16_t gpiod; /* GPIO Data register. */
volatile uint16_t gpioe; /* GPIO Enable register. */
uint16_t gpiod; /* GPIO Data register. */
uint16_t gpioe; /* GPIO Enable register. */
#define GPIO_LED_MASK 0x00C0
#define GPIO_LED_GREEN_OFF_AMBER_OFF 0x0000
#define GPIO_LED_GREEN_ON_AMBER_OFF 0x0040
@ -424,24 +431,31 @@ typedef volatile struct {
union {
struct {
uint16_t unused_10[8]; /* Gap */
volatile uint16_t mailbox8;
volatile uint16_t mailbox9;
volatile uint16_t mailbox10;
volatile uint16_t mailbox11;
volatile uint16_t mailbox12;
volatile uint16_t mailbox13;
volatile uint16_t mailbox14;
volatile uint16_t mailbox15;
volatile uint16_t mailbox16;
volatile uint16_t mailbox17;
volatile uint16_t mailbox18;
volatile uint16_t mailbox19;
volatile uint16_t mailbox20;
volatile uint16_t mailbox21;
volatile uint16_t mailbox22;
volatile uint16_t mailbox23; /* Also probe reg. */
uint16_t mailbox8;
uint16_t mailbox9;
uint16_t mailbox10;
uint16_t mailbox11;
uint16_t mailbox12;
uint16_t mailbox13;
uint16_t mailbox14;
uint16_t mailbox15;
uint16_t mailbox16;
uint16_t mailbox17;
uint16_t mailbox18;
uint16_t mailbox19;
uint16_t mailbox20;
uint16_t mailbox21;
uint16_t mailbox22;
uint16_t mailbox23; /* Also probe reg. */
} __attribute__((packed)) isp2200;
} u_end;
};
typedef struct {
union {
struct device_reg_2xxx isp;
struct device_reg_24xx isp24;
};
} device_reg_t;
#define ISP_REQ_Q_IN(ha, reg) \
@ -524,6 +538,8 @@ typedef struct {
#define MBS_LOOP_ID_USED 0x4008
#define MBS_ALL_IDS_IN_USE 0x4009
#define MBS_NOT_LOGGED_IN 0x400A
#define MBS_LINK_DOWN_ERROR 0x400B
#define MBS_DIAG_ECHO_TEST_ERROR 0x400C
/*
* ISP mailbox asynchronous event status codes
@ -575,7 +591,7 @@ typedef struct {
#define FO1_CTIO_RETRY BIT_3
#define FO1_DISABLE_LIP_F7_SW BIT_4
#define FO1_DISABLE_100MS_LOS_WAIT BIT_5
#define FO1_DISABLE_GPIO6_7 BIT_6
#define FO1_DISABLE_GPIO6_7 BIT_6 /* LED bits */
#define FO1_AE_ON_LOOP_INIT_ERR BIT_7
#define FO1_SET_EMPHASIS_SWING BIT_8
#define FO1_AE_AUTO_BYPASS BIT_9
@ -590,6 +606,15 @@ typedef struct {
#define FO3_ENABLE_EMERG_IOCB BIT_0
#define FO3_AE_RND_ERROR BIT_1
/* 24XX additional firmware options */
#define ADD_FO_COUNT 3
#define ADD_FO1_DISABLE_GPIO_LED_CTRL BIT_6 /* LED bits */
#define ADD_FO1_ENABLE_PUREX_IOCB BIT_10
#define ADD_FO2_ENABLE_SEL_CLS2 BIT_5
#define ADD_FO3_NO_ABT_ON_LINK_DOWN BIT_14
/*
* ISP mailbox commands
*/
@ -658,6 +683,22 @@ typedef struct {
#define MBC_SEND_LFA_COMMAND 0x7D /* Send Loop Fabric Address */
#define MBC_LUN_RESET 0x7E /* Send LUN reset */
/*
* ISP24xx mailbox commands
*/
#define MBC_SERDES_PARAMS 0x10 /* Serdes Tx Parameters. */
#define MBC_GET_IOCB_STATUS 0x12 /* Get IOCB status command. */
#define MBC_GET_TIMEOUT_PARAMS 0x22 /* Get FW timeouts. */
#define MBC_GEN_SYSTEM_ERROR 0x2a /* Generate System Error. */
#define MBC_SET_TIMEOUT_PARAMS 0x32 /* Set FW timeouts. */
#define MBC_MID_INITIALIZE_FIRMWARE 0x48 /* MID Initialize firmware. */
#define MBC_MID_GET_VP_DATABASE 0x49 /* MID Get VP Database. */
#define MBC_MID_GET_VP_ENTRY 0x4a /* MID Get VP Entry. */
#define MBC_HOST_MEMORY_COPY 0x53 /* Host Memory Copy. */
#define MBC_SEND_RNFT_ELS 0x5e /* Send RNFT ELS request */
#define MBC_GET_LINK_PRIV_STATS 0x6d /* Get link & private data. */
#define MBC_SET_VENDOR_ID 0x76 /* Set Vendor ID. */
/* Firmware return data sizes */
#define FCAL_MAP_SIZE 128
@ -887,6 +928,9 @@ typedef struct {
/*
* Get Link Status mailbox command return buffer.
*/
#define GLSO_SEND_RPS BIT_0
#define GLSO_USE_DID BIT_3
typedef struct {
uint32_t link_fail_cnt;
uint32_t loss_sync_cnt;
@ -1181,7 +1225,6 @@ do { \
* ISP queue - command entry structure definition.
*/
#define COMMAND_TYPE 0x11 /* Command entry */
#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
typedef struct {
uint8_t entry_type; /* Entry type. */
uint8_t entry_count; /* Entry count. */
@ -1304,11 +1347,16 @@ typedef struct {
/*
* Status entry entry status
*/
#define RF_RQ_DMA_ERROR BIT_6 /* Request Queue DMA error. */
#define RF_INV_E_ORDER BIT_5 /* Invalid entry order. */
#define RF_INV_E_COUNT BIT_4 /* Invalid entry count. */
#define RF_INV_E_PARAM BIT_3 /* Invalid entry parameter. */
#define RF_INV_E_TYPE BIT_2 /* Invalid entry type. */
#define RF_BUSY BIT_1 /* Busy */
#define RF_MASK (RF_RQ_DMA_ERROR | RF_INV_E_ORDER | RF_INV_E_COUNT | \
RF_INV_E_PARAM | RF_INV_E_TYPE | RF_BUSY)
#define RF_MASK_24XX (RF_INV_E_ORDER | RF_INV_E_COUNT | RF_INV_E_PARAM | \
RF_INV_E_TYPE)
/*
* Status entry SCSI status bit definitions.
@ -1523,9 +1571,6 @@ typedef struct {
port_id_t d_id;
uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE];
uint32_t type;
#define SW_TYPE_IP BIT_1
#define SW_TYPE_SCSI BIT_0
} sw_info_t;
/*
@ -1540,6 +1585,8 @@ typedef struct {
union {
cmd_a64_entry_t cmd;
sts_entry_t rsp;
struct cmd_type_7 cmd24;
struct sts_entry_24xx rsp24;
} p;
uint8_t inq[INQ_DATA_SIZE];
} inq_cmd_rsp_t;
@ -1575,10 +1622,13 @@ typedef struct {
union {
cmd_a64_entry_t cmd;
sts_entry_t rsp;
struct cmd_type_7 cmd24;
struct sts_entry_24xx rsp24;
} p;
rpt_lun_lst_t list;
} rpt_lun_cmd_rsp_t;
/*
* Fibre channel port type.
*/
@ -1666,6 +1716,7 @@ typedef struct fc_port {
#define FCF_FAILOVER_DISABLE BIT_22
#define FCF_DSXXX_DEVICE BIT_23
#define FCF_AA_EVA_DEVICE BIT_24
#define FCF_AA_MSA_DEVICE BIT_25
/* No loop ID flag. */
#define FC_NO_LOOP_ID 0x1000
@ -1937,6 +1988,8 @@ struct qla_board_info {
char isp_name[8];
struct qla_fw_info *fw_info;
char *fw_fname;
struct scsi_host_template *sht;
};
/* Return data from MBC_GET_ID_LIST call. */
@ -1946,9 +1999,51 @@ struct gid_list_info {
uint8_t domain;
uint8_t loop_id_2100; /* ISP2100/ISP2200 -- 4 bytes. */
uint16_t loop_id; /* ISP23XX -- 6 bytes. */
uint16_t reserved_1; /* ISP24XX -- 8 bytes. */
};
#define GID_LIST_SIZE (sizeof(struct gid_list_info) * MAX_FIBRE_DEVICES)
/*
* ISP operations
*/
struct isp_operations {
int (*pci_config) (struct scsi_qla_host *);
void (*reset_chip) (struct scsi_qla_host *);
int (*chip_diag) (struct scsi_qla_host *);
void (*config_rings) (struct scsi_qla_host *);
void (*reset_adapter) (struct scsi_qla_host *);
int (*nvram_config) (struct scsi_qla_host *);
void (*update_fw_options) (struct scsi_qla_host *);
int (*load_risc) (struct scsi_qla_host *, uint32_t *);
char * (*pci_info_str) (struct scsi_qla_host *, char *);
char * (*fw_version_str) (struct scsi_qla_host *, char *);
irqreturn_t (*intr_handler) (int, void *, struct pt_regs *);
void (*enable_intrs) (struct scsi_qla_host *);
void (*disable_intrs) (struct scsi_qla_host *);
int (*abort_command) (struct scsi_qla_host *, srb_t *);
int (*abort_target) (struct fc_port *);
int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t,
uint8_t, uint8_t, uint16_t *, uint8_t);
int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t,
uint8_t, uint8_t);
uint16_t (*calc_req_entries) (uint16_t);
void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint32_t, uint32_t);
int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t,
uint32_t);
void (*fw_dump) (struct scsi_qla_host *, int);
void (*ascii_fw_dump) (struct scsi_qla_host *);
};
/*
* Linux Host Adapter structure
*/
@ -1979,6 +2074,8 @@ typedef struct scsi_qla_host {
uint32_t enable_lip_full_login :1;
uint32_t enable_target_reset :1;
uint32_t enable_led_scheme :1;
uint32_t msi_enabled :1;
uint32_t msix_enabled :1;
} flags;
atomic_t loop_state;
@ -2015,6 +2112,7 @@ typedef struct scsi_qla_host {
#define IODESC_PROCESS_NEEDED 22 /* IO descriptor processing needed */
#define IOCTL_ERROR_RECOVERY 23
#define LOOP_RESET_NEEDED 24
#define BEACON_BLINK_NEEDED 25
uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
@ -2055,8 +2153,7 @@ typedef struct scsi_qla_host {
uint16_t rsp_ring_index; /* Current index. */
uint16_t response_q_length;
uint16_t (*calc_request_entries)(uint16_t);
void (*build_scsi_iocbs)(srb_t *, cmd_entry_t *, uint16_t);
struct isp_operations isp_ops;
/* Outstandings ISP commands. */
srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS];
@ -2099,6 +2196,7 @@ typedef struct scsi_qla_host {
uint8_t serial2;
/* NVRAM configuration data */
uint16_t nvram_size;
uint16_t nvram_base;
uint16_t loop_reset_delay;
@ -2149,6 +2247,7 @@ typedef struct scsi_qla_host {
dma_addr_t gid_list_dma;
struct gid_list_info *gid_list;
int gid_list_info_size;
dma_addr_t rlc_rsp_dma;
rpt_lun_cmd_rsp_t *rlc_rsp;
@ -2159,6 +2258,7 @@ typedef struct scsi_qla_host {
dma_addr_t init_cb_dma;
init_cb_t *init_cb;
int init_cb_size;
dma_addr_t iodesc_pd_dma;
port_database_t *iodesc_pd;
@ -2199,6 +2299,7 @@ typedef struct scsi_qla_host {
uint16_t fw_options[16]; /* slots: 1,2,3,10,11 */
uint8_t fw_seriallink_options[4];
uint16_t fw_seriallink_options24[4];
/* Firmware dump information. */
void *fw_dump;
@ -2207,8 +2308,12 @@ typedef struct scsi_qla_host {
char *fw_dump_buffer;
int fw_dump_buffer_len;
int fw_dumped;
void *fw_dump24;
int fw_dump24_len;
uint8_t host_str[16];
uint16_t pci_attr;
uint32_t pci_attr;
uint16_t product_id[4];
@ -2216,8 +2321,8 @@ typedef struct scsi_qla_host {
#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
char *model_desc;
uint8_t node_name[WWN_SIZE];
uint8_t nvram_version;
uint8_t *node_name;
uint8_t *port_name;
uint32_t isp_abort_cnt;
/* Needed for BEACON */

View file

@ -1,4 +1,4 @@
#define QLA_MODEL_NAMES 0x32
#define QLA_MODEL_NAMES 0x44
/*
* Adapter model names.
@ -53,7 +53,25 @@ static char *qla2x00_model_name[QLA_MODEL_NAMES] = {
" ", /* 0x12e */
"QLA210", /* 0x12f */
"EMC 250", /* 0x130 */
"HP A7538A" /* 0x131 */
"HP A7538A", /* 0x131 */
"QLA210", /* 0x132 */
"QLA2460", /* 0x133 */
"QLA2462", /* 0x134 */
"QMC2462", /* 0x135 */
"QMC2462S", /* 0x136 */
"QLE2460", /* 0x137 */
"QLE2462", /* 0x138 */
"QME2462", /* 0x139 */
"QLA2440", /* 0x13a */
"QLA2442", /* 0x13b */
"QSM2442", /* 0x13c */
"QSM2462", /* 0x13d */
"QLE210", /* 0x13e */
"QLE220", /* 0x13f */
"QLA2460", /* 0x140 */
"QLA2462", /* 0x141 */
"QLE2460", /* 0x142 */
"QLE2462" /* 0x143 */
};
static char *qla2x00_model_desc[QLA_MODEL_NAMES] = {
@ -78,8 +96,8 @@ static char *qla2x00_model_desc[QLA_MODEL_NAMES] = {
" ", /* 0x112 */
" ", /* 0x113 */
" ", /* 0x114 */
"133MHz PCI-X to 2Gb FC Single Channel", /* 0x115 */
"133MHz PCI-X to 2Gb FC Dual Channel", /* 0x116 */
"133MHz PCI-X to 2Gb FC, Single Channel", /* 0x115 */
"133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x116 */
"PCI-Express to 2Gb FC, Single Channel", /* 0x117 */
"PCI-Express to 2Gb FC, Dual Channel", /* 0x118 */
"133MHz PCI-X to 2Gb FC Optical", /* 0x119 */
@ -106,5 +124,23 @@ static char *qla2x00_model_desc[QLA_MODEL_NAMES] = {
" ", /* 0x12e */
"133MHz PCI-X to 2Gb FC SFF", /* 0x12f */
"133MHz PCI-X to 2Gb FC SFF", /* 0x130 */
"HP 1p2g QLA2340" /* 0x131 */
"HP 1p2g QLA2340", /* 0x131 */
"133MHz PCI-X to 2Gb FC, Single Channel", /* 0x132 */
"PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x133 */
"PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x134 */
"IBM eServer BC 4Gb FC Expansion Card", /* 0x135 */
"IBM eServer BC 4Gb FC Expansion Card SFF", /* 0x136 */
"PCI-Express to 4Gb FC, Single Channel", /* 0x137 */
"PCI-Express to 4Gb FC, Dual Channel", /* 0x138 */
"Dell PCI-Express to 4Gb FC, Dual Channel", /* 0x139 */
"PCI-X 1.0 to 4Gb FC, Single Channel", /* 0x13a */
"PCI-X 1.0 to 4Gb FC, Dual Channel", /* 0x13b */
"Server I/O Module 4Gb FC, Single Channel", /* 0x13c */
"Server I/O Module 4Gb FC, Single Channel", /* 0x13d */
"PCI-Express to 2Gb FC, Single Channel", /* 0x13e */
"PCI-Express to 4Gb FC, Single Channel", /* 0x13f */
"Sun PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x140 */
"Sun PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x141 */
"Sun PCI-Express to 2Gb FC, Single Channel", /* 0x142 */
"Sun PCI-Express to 4Gb FC, Single Channel" /* 0x143 */
};

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -32,6 +32,26 @@ extern int qla2x00_probe_one(struct pci_dev *, struct qla_board_info *);
* Global Function Prototypes in qla_init.c source file.
*/
extern int qla2x00_initialize_adapter(scsi_qla_host_t *);
extern int qla2100_pci_config(struct scsi_qla_host *);
extern int qla2300_pci_config(struct scsi_qla_host *);
extern int qla24xx_pci_config(scsi_qla_host_t *);
extern void qla2x00_reset_chip(struct scsi_qla_host *);
extern void qla24xx_reset_chip(struct scsi_qla_host *);
extern int qla2x00_chip_diag(struct scsi_qla_host *);
extern int qla24xx_chip_diag(struct scsi_qla_host *);
extern void qla2x00_config_rings(struct scsi_qla_host *);
extern void qla24xx_config_rings(struct scsi_qla_host *);
extern void qla2x00_reset_adapter(struct scsi_qla_host *);
extern void qla24xx_reset_adapter(struct scsi_qla_host *);
extern int qla2x00_nvram_config(struct scsi_qla_host *);
extern int qla24xx_nvram_config(struct scsi_qla_host *);
extern void qla2x00_update_fw_options(struct scsi_qla_host *);
extern void qla24xx_update_fw_options(scsi_qla_host_t *);
extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
extern int qla24xx_load_risc_flash(scsi_qla_host_t *, uint32_t *);
extern int qla24xx_load_risc_hotplug(scsi_qla_host_t *, uint32_t *);
extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, int);
extern int qla2x00_loop_resync(scsi_qla_host_t *);
@ -83,6 +103,7 @@ extern uint16_t qla2x00_calc_iocbs_64(uint16_t);
extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t);
extern void qla2x00_build_scsi_iocbs_64(srb_t *, cmd_entry_t *, uint16_t);
extern int qla2x00_start_scsi(srb_t *sp);
extern int qla24xx_start_scsi(srb_t *sp);
int qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t);
int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t);
@ -93,10 +114,10 @@ extern int
qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t);
extern int
qla2x00_load_ram_ext(scsi_qla_host_t *, dma_addr_t, uint32_t, uint16_t);
qla2x00_load_ram_ext(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
extern int
qla2x00_execute_fw(scsi_qla_host_t *);
qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
extern void
qla2x00_get_fw_version(scsi_qla_host_t *, uint16_t *,
@ -112,7 +133,7 @@ extern int
qla2x00_mbx_reg_test(scsi_qla_host_t *);
extern int
qla2x00_verify_checksum(scsi_qla_host_t *);
qla2x00_verify_checksum(scsi_qla_host_t *, uint32_t);
extern int
qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
@ -122,7 +143,7 @@ qla2x00_abort_command(scsi_qla_host_t *, srb_t *);
#if USE_ABORT_TGT
extern int
qla2x00_abort_target(fc_port_t *fcport);
qla2x00_abort_target(fc_port_t *);
#endif
extern int
@ -156,12 +177,18 @@ qla2x00_send_sns(scsi_qla_host_t *, dma_addr_t, uint16_t, size_t);
extern int
qla2x00_login_fabric(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t,
uint16_t *, uint8_t);
extern int
qla24xx_login_fabric(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t,
uint16_t *, uint8_t);
extern int
qla2x00_login_local_device(scsi_qla_host_t *, uint16_t, uint16_t *, uint8_t);
extern int
qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id);
qla2x00_fabric_logout(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t);
extern int
qla24xx_fabric_logout(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t);
extern int
qla2x00_full_login_lip(scsi_qla_host_t *ha);
@ -176,11 +203,24 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *,
extern int
qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *);
extern int qla24xx_abort_target(fc_port_t *);
extern int qla2x00_system_error(scsi_qla_host_t *);
extern int
qla2x00_get_serdes_params(scsi_qla_host_t *, uint16_t *, uint16_t *,
uint16_t *);
extern int
qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
/*
* Global Function Prototypes in qla_isr.c source file.
*/
extern irqreturn_t qla2100_intr_handler(int, void *, struct pt_regs *);
extern irqreturn_t qla2300_intr_handler(int, void *, struct pt_regs *);
extern irqreturn_t qla24xx_intr_handler(int, void *, struct pt_regs *);
extern void qla2x00_process_response_queue(struct scsi_qla_host *);
/*
@ -191,20 +231,36 @@ extern void qla2x00_unlock_nvram_access(scsi_qla_host_t *);
extern void qla2x00_release_nvram_protection(scsi_qla_host_t *);
extern uint16_t qla2x00_get_nvram_word(scsi_qla_host_t *, uint32_t);
extern void qla2x00_write_nvram_word(scsi_qla_host_t *, uint32_t, uint16_t);
extern uint32_t *qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *,
uint32_t, uint32_t);
extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
extern uint8_t *qla24xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
/*
* Global Function Prototypes in qla_dbg.c source file.
*/
extern void qla2100_fw_dump(scsi_qla_host_t *, int);
extern void qla2300_fw_dump(scsi_qla_host_t *, int);
extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
extern void qla2100_ascii_fw_dump(scsi_qla_host_t *);
extern void qla2300_ascii_fw_dump(scsi_qla_host_t *);
extern void qla24xx_ascii_fw_dump(scsi_qla_host_t *);
extern void qla2x00_dump_regs(scsi_qla_host_t *);
extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *);
extern void qla2x00_dump_pkt(void *);
/*
* Global Function Prototypes in qla_gs.c source file.
*/
extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
extern int qla2x00_ga_nxt(scsi_qla_host_t *, fc_port_t *);
extern int qla2x00_gid_pt(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_gpn_id(scsi_qla_host_t *, sw_info_t *);

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -18,9 +18,6 @@
*/
#include "qla_def.h"
static inline ms_iocb_entry_t *
qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
static inline struct ct_sns_req *
qla2x00_prep_ct_req(struct ct_sns_req *, uint16_t, uint16_t);
@ -35,14 +32,14 @@ static int qla2x00_sns_rft_id(scsi_qla_host_t *);
static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
/**
* qla2x00_prep_ms_iocb() - Prepare common MS IOCB fields for SNS CT query.
* qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
* @ha: HA context
* @req_size: request size in bytes
* @rsp_size: response size in bytes
*
* Returns a pointer to the @ha's ms_iocb.
*/
static inline ms_iocb_entry_t *
void *
qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size)
{
ms_iocb_entry_t *ms_pkt;
@ -71,6 +68,42 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size)
return (ms_pkt);
}
/**
* qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.
* @ha: HA context
* @req_size: request size in bytes
* @rsp_size: response size in bytes
*
* Returns a pointer to the @ha's ms_iocb.
*/
void *
qla24xx_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size)
{
struct ct_entry_24xx *ct_pkt;
ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
ct_pkt->entry_type = CT_IOCB_TYPE;
ct_pkt->entry_count = 1;
ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS);
ct_pkt->timeout = __constant_cpu_to_le16(25);
ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
return (ct_pkt);
}
/**
* qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
* @ct_req: CT request buffer
@ -93,6 +126,47 @@ qla2x00_prep_ct_req(struct ct_sns_req *ct_req, uint16_t cmd, uint16_t rsp_size)
return (ct_req);
}
static int
qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt,
struct ct_sns_rsp *ct_rsp, const char *routine)
{
int rval;
uint16_t comp_status;
rval = QLA_FUNCTION_FAILED;
if (ms_pkt->entry_status != 0) {
DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n",
ha->host_no, routine, ms_pkt->entry_status));
} else {
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
comp_status =
((struct ct_entry_24xx *)ms_pkt)->comp_status;
else
comp_status = le16_to_cpu(ms_pkt->status);
switch (comp_status) {
case CS_COMPLETE:
case CS_DATA_UNDERRUN:
case CS_DATA_OVERRUN: /* Overrun? */
if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
DEBUG2_3(printk("scsi(%ld): %s failed, "
"rejected request:\n", ha->host_no,
routine));
DEBUG2_3(qla2x00_dump_buffer(
(uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
} else
rval = QLA_SUCCESS;
break;
default:
DEBUG2_3(printk("scsi(%ld): %s failed, completion "
"status (%x).\n", ha->host_no, routine,
comp_status));
break;
}
}
return rval;
}
/**
* qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
@ -116,7 +190,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport)
/* Issue GA_NXT */
/* Prepare common MS IOCB */
ms_pkt = qla2x00_prep_ms_iocb(ha, GA_NXT_REQ_SIZE, GA_NXT_RSP_SIZE);
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GA_NXT_REQ_SIZE, GA_NXT_RSP_SIZE);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD,
@ -135,12 +209,8 @@ qla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport)
/*EMPTY*/
DEBUG2_3(printk("scsi(%ld): GA_NXT issue IOCB failed (%d).\n",
ha->host_no, rval));
} else if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
DEBUG2_3(printk("scsi(%ld): GA_NXT failed, rejected request, "
"ga_nxt_rsp:\n", ha->host_no));
DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "GA_NXT") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
/* Populate fc_port_t entry. */
@ -206,7 +276,7 @@ qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list)
/* Issue GID_PT */
/* Prepare common MS IOCB */
ms_pkt = qla2x00_prep_ms_iocb(ha, GID_PT_REQ_SIZE, GID_PT_RSP_SIZE);
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GID_PT_REQ_SIZE, GID_PT_RSP_SIZE);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD,
@ -223,12 +293,8 @@ qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list)
/*EMPTY*/
DEBUG2_3(printk("scsi(%ld): GID_PT issue IOCB failed (%d).\n",
ha->host_no, rval));
} else if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
DEBUG2_3(printk("scsi(%ld): GID_PT failed, rejected request, "
"gid_pt_rsp:\n", ha->host_no));
DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "GID_PT") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
/* Set port IDs in switch info list. */
@ -282,7 +348,7 @@ qla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list)
for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
/* Issue GPN_ID */
/* Prepare common MS IOCB */
ms_pkt = qla2x00_prep_ms_iocb(ha, GPN_ID_REQ_SIZE,
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GPN_ID_REQ_SIZE,
GPN_ID_RSP_SIZE);
/* Prepare CT request */
@ -302,12 +368,8 @@ qla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list)
/*EMPTY*/
DEBUG2_3(printk("scsi(%ld): GPN_ID issue IOCB failed "
"(%d).\n", ha->host_no, rval));
} else if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
DEBUG2_3(printk("scsi(%ld): GPN_ID failed, rejected "
"request, gpn_id_rsp:\n", ha->host_no));
DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,
"GPN_ID") != QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
/* Save portname */
@ -347,7 +409,7 @@ qla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list)
for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
/* Issue GNN_ID */
/* Prepare common MS IOCB */
ms_pkt = qla2x00_prep_ms_iocb(ha, GNN_ID_REQ_SIZE,
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GNN_ID_REQ_SIZE,
GNN_ID_RSP_SIZE);
/* Prepare CT request */
@ -367,12 +429,8 @@ qla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list)
/*EMPTY*/
DEBUG2_3(printk("scsi(%ld): GNN_ID issue IOCB failed "
"(%d).\n", ha->host_no, rval));
} else if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
DEBUG2_3(printk("scsi(%ld): GNN_ID failed, rejected "
"request, gnn_id_rsp:\n", ha->host_no));
DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,
"GNN_ID") != QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
/* Save nodename */
@ -425,7 +483,7 @@ qla2x00_rft_id(scsi_qla_host_t *ha)
/* Issue RFT_ID */
/* Prepare common MS IOCB */
ms_pkt = qla2x00_prep_ms_iocb(ha, RFT_ID_REQ_SIZE, RFT_ID_RSP_SIZE);
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFT_ID_REQ_SIZE, RFT_ID_RSP_SIZE);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD,
@ -446,12 +504,8 @@ qla2x00_rft_id(scsi_qla_host_t *ha)
/*EMPTY*/
DEBUG2_3(printk("scsi(%ld): RFT_ID issue IOCB failed (%d).\n",
ha->host_no, rval));
} else if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
DEBUG2_3(printk("scsi(%ld): RFT_ID failed, rejected "
"request, rft_id_rsp:\n", ha->host_no));
DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RFT_ID") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n",
@ -484,7 +538,7 @@ qla2x00_rff_id(scsi_qla_host_t *ha)
/* Issue RFF_ID */
/* Prepare common MS IOCB */
ms_pkt = qla2x00_prep_ms_iocb(ha, RFF_ID_REQ_SIZE, RFF_ID_RSP_SIZE);
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFF_ID_REQ_SIZE, RFF_ID_RSP_SIZE);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD,
@ -505,12 +559,8 @@ qla2x00_rff_id(scsi_qla_host_t *ha)
/*EMPTY*/
DEBUG2_3(printk("scsi(%ld): RFF_ID issue IOCB failed (%d).\n",
ha->host_no, rval));
} else if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
DEBUG2_3(printk("scsi(%ld): RFF_ID failed, rejected "
"request, rff_id_rsp:\n", ha->host_no));
DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RFF_ID") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
DEBUG2(printk("scsi(%ld): RFF_ID exiting normally.\n",
@ -541,7 +591,7 @@ qla2x00_rnn_id(scsi_qla_host_t *ha)
/* Issue RNN_ID */
/* Prepare common MS IOCB */
ms_pkt = qla2x00_prep_ms_iocb(ha, RNN_ID_REQ_SIZE, RNN_ID_RSP_SIZE);
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RNN_ID_REQ_SIZE, RNN_ID_RSP_SIZE);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD,
@ -553,7 +603,7 @@ qla2x00_rnn_id(scsi_qla_host_t *ha)
ct_req->req.rnn_id.port_id[1] = ha->d_id.b.area;
ct_req->req.rnn_id.port_id[2] = ha->d_id.b.al_pa;
memcpy(ct_req->req.rnn_id.node_name, ha->init_cb->node_name, WWN_SIZE);
memcpy(ct_req->req.rnn_id.node_name, ha->node_name, WWN_SIZE);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
@ -562,12 +612,8 @@ qla2x00_rnn_id(scsi_qla_host_t *ha)
/*EMPTY*/
DEBUG2_3(printk("scsi(%ld): RNN_ID issue IOCB failed (%d).\n",
ha->host_no, rval));
} else if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
DEBUG2_3(printk("scsi(%ld): RNN_ID failed, rejected "
"request, rnn_id_rsp:\n", ha->host_no));
DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RNN_ID") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n",
@ -603,7 +649,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *ha)
/* Issue RSNN_NN */
/* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */
ms_pkt = qla2x00_prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE);
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD,
@ -611,7 +657,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *ha)
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare CT arguments -- node_name, symbolic node_name, size */
memcpy(ct_req->req.rsnn_nn.node_name, ha->init_cb->node_name, WWN_SIZE);
memcpy(ct_req->req.rsnn_nn.node_name, ha->node_name, WWN_SIZE);
/* Prepare the Symbolic Node Name */
/* Board type */
@ -641,12 +687,8 @@ qla2x00_rsnn_nn(scsi_qla_host_t *ha)
/*EMPTY*/
DEBUG2_3(printk("scsi(%ld): RSNN_NN issue IOCB failed (%d).\n",
ha->host_no, rval));
} else if (ct_rsp->header.response !=
__constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
DEBUG2_3(printk("scsi(%ld): RSNN_NN failed, rejected "
"request, rsnn_id_rsp:\n", ha->host_no));
DEBUG2_3(qla2x00_dump_buffer((uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RSNN_NN") !=
QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
} else {
DEBUG2(printk("scsi(%ld): RSNN_NN exiting normally.\n",
@ -1028,14 +1070,14 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *ha)
sns_cmd->p.cmd.param[1] = ha->d_id.b.area;
sns_cmd->p.cmd.param[2] = ha->d_id.b.domain;
sns_cmd->p.cmd.param[4] = ha->init_cb->node_name[7];
sns_cmd->p.cmd.param[5] = ha->init_cb->node_name[6];
sns_cmd->p.cmd.param[6] = ha->init_cb->node_name[5];
sns_cmd->p.cmd.param[7] = ha->init_cb->node_name[4];
sns_cmd->p.cmd.param[8] = ha->init_cb->node_name[3];
sns_cmd->p.cmd.param[9] = ha->init_cb->node_name[2];
sns_cmd->p.cmd.param[10] = ha->init_cb->node_name[1];
sns_cmd->p.cmd.param[11] = ha->init_cb->node_name[0];
sns_cmd->p.cmd.param[4] = ha->node_name[7];
sns_cmd->p.cmd.param[5] = ha->node_name[6];
sns_cmd->p.cmd.param[6] = ha->node_name[5];
sns_cmd->p.cmd.param[7] = ha->node_name[4];
sns_cmd->p.cmd.param[8] = ha->node_name[3];
sns_cmd->p.cmd.param[9] = ha->node_name[2];
sns_cmd->p.cmd.param[10] = ha->node_name[1];
sns_cmd->p.cmd.param[11] = ha->node_name[0];
/* Execute SNS command. */
rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -117,74 +117,7 @@ static __inline__ void qla2x00_poll(scsi_qla_host_t *);
static inline void
qla2x00_poll(scsi_qla_host_t *ha)
{
if (IS_QLA2100(ha) || IS_QLA2200(ha))
qla2100_intr_handler(0, ha, NULL);
else
qla2300_intr_handler(0, ha, NULL);
}
static __inline__ void qla2x00_enable_intrs(scsi_qla_host_t *);
static __inline__ void qla2x00_disable_intrs(scsi_qla_host_t *);
static inline void
qla2x00_enable_intrs(scsi_qla_host_t *ha)
{
unsigned long flags = 0;
device_reg_t __iomem *reg = ha->iobase;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 1;
/* enable risc and host interrupts */
WRT_REG_WORD(&reg->ictrl, ICR_EN_INT | ICR_EN_RISC);
RD_REG_WORD(&reg->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static inline void
qla2x00_disable_intrs(scsi_qla_host_t *ha)
{
unsigned long flags = 0;
device_reg_t __iomem *reg = ha->iobase;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 0;
/* disable risc and host interrupts */
WRT_REG_WORD(&reg->ictrl, 0);
RD_REG_WORD(&reg->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static __inline__ int qla2x00_is_wwn_zero(uint8_t *);
/*
* qla2x00_is_wwn_zero - Check for zero node name
*
* Input:
* wwn = Pointer to WW name to check
*
* Returns:
* 1 if name is 0x00 else 0
*
* Context:
* Kernel context.
*/
static __inline__ int
qla2x00_is_wwn_zero(uint8_t *wwn)
{
int cnt;
for (cnt = 0; cnt < WWN_SIZE ; cnt++, wwn++) {
if (*wwn != 0)
break;
}
/* if zero return 1 */
if (cnt == WWN_SIZE)
return (1);
else
return (0);
ha->isp_ops.intr_handler(0, ha, NULL);
}
static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *);
@ -225,51 +158,27 @@ qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked)
return (QLA_SUCCESS);
}
static __inline__ void qla2x00_add_timer_to_cmd(srb_t *, int);
static __inline__ void qla2x00_delete_timer_from_cmd(srb_t *);
/**************************************************************************
* qla2x00_add_timer_to_cmd
*
* Description:
* Creates a timer for the specified command. The timeout is usually
* the command time from kernel minus 2 secs.
*
* Input:
* sp - pointer to validate
*
* Returns:
* None.
**************************************************************************/
static inline void
qla2x00_add_timer_to_cmd(srb_t *sp, int timeout)
static inline uint8_t *host_to_fcp_swap(uint8_t *, uint32_t);
static inline uint8_t *
host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
{
init_timer(&sp->timer);
sp->timer.expires = jiffies + timeout * HZ;
sp->timer.data = (unsigned long) sp;
sp->timer.function = (void (*) (unsigned long))qla2x00_cmd_timeout;
add_timer(&sp->timer);
uint32_t *ifcp = (uint32_t *) fcp;
uint32_t *ofcp = (uint32_t *) fcp;
uint32_t iter = bsize >> 2;
for (; iter ; iter--)
*ofcp++ = swab32(*ifcp++);
return fcp;
}
/**************************************************************************
* qla2x00_delete_timer_from_cmd
*
* Description:
* Delete the timer for the specified command.
*
* Input:
* sp - pointer to validate
*
* Returns:
* None.
**************************************************************************/
static inline void
qla2x00_delete_timer_from_cmd(srb_t *sp)
static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t);
static inline int
qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id)
{
if (sp->timer.function != NULL) {
del_timer(&sp->timer);
sp->timer.function = NULL;
sp->timer.data = (unsigned long) NULL;
}
}
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
return (loop_id > NPH_LAST_HANDLE);
return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||
loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST);
};

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -315,13 +315,13 @@ qla2x00_start_scsi(srb_t *sp)
uint16_t cnt;
uint16_t req_cnt;
uint16_t tot_dsds;
device_reg_t __iomem *reg;
struct device_reg_2xxx __iomem *reg;
char tag[2];
/* Setup device pointers. */
ret = 0;
ha = sp->ha;
reg = ha->iobase;
reg = &ha->iobase->isp;
cmd = sp->cmd;
/* So we know we haven't pci_map'ed anything yet */
tot_dsds = 0;
@ -369,7 +369,7 @@ qla2x00_start_scsi(srb_t *sp)
}
/* Calculate the number of request entries needed. */
req_cnt = (ha->calc_request_entries)(tot_dsds);
req_cnt = ha->isp_ops.calc_req_entries(tot_dsds);
if (ha->req_q_cnt < (req_cnt + 2)) {
cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg));
if (ha->req_ring_index < cnt)
@ -419,7 +419,7 @@ qla2x00_start_scsi(srb_t *sp)
cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen);
/* Build IOCB segments */
(ha->build_scsi_iocbs)(sp, cmd_pkt, tot_dsds);
ha->isp_ops.build_iocbs(sp, cmd_pkt, tot_dsds);
/* Set total data segment count. */
cmd_pkt->entry_count = (uint8_t)req_cnt;
@ -472,25 +472,33 @@ int
__qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
uint8_t type)
{
mrk_entry_t *pkt;
mrk_entry_t *mrk;
struct mrk_entry_24xx *mrk24;
pkt = (mrk_entry_t *)qla2x00_req_pkt(ha);
if (pkt == NULL) {
DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__));
mrk24 = NULL;
mrk = (mrk_entry_t *)qla2x00_req_pkt(ha);
if (mrk == NULL) {
DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n",
__func__, ha->host_no));
return (QLA_FUNCTION_FAILED);
}
pkt->entry_type = MARKER_TYPE;
pkt->modifier = type;
mrk->entry_type = MARKER_TYPE;
mrk->modifier = type;
if (type != MK_SYNC_ALL) {
pkt->lun = cpu_to_le16(lun);
SET_TARGET_ID(ha, pkt->target, loop_id);
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
mrk24 = (struct mrk_entry_24xx *) mrk;
mrk24->nport_handle = cpu_to_le16(loop_id);
mrk24->lun[1] = LSB(lun);
mrk24->lun[2] = MSB(lun);
} else {
SET_TARGET_ID(ha, mrk->target, loop_id);
mrk->lun = cpu_to_le16(lun);
}
}
wmb();
/* Issue command to ISP */
qla2x00_isp_cmd(ha);
return (QLA_SUCCESS);
@ -532,7 +540,12 @@ qla2x00_req_pkt(scsi_qla_host_t *ha)
for (timer = HZ; timer; timer--) {
if ((req_cnt + 2) >= ha->req_q_cnt) {
/* Calculate number of free request entries. */
cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg));
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
cnt = (uint16_t)RD_REG_DWORD(
&reg->isp24.req_q_out);
else
cnt = qla2x00_debounce_register(
ISP_REQ_Q_OUT(ha, &reg->isp));
if (ha->req_ring_index < cnt)
ha->req_q_cnt = cnt - ha->req_ring_index;
else
@ -601,6 +614,286 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha)
ha->request_ring_ptr++;
/* Set chip new ring index. */
WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), ha->req_ring_index);
RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, reg)); /* PCI Posting. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
WRT_REG_DWORD(&reg->isp24.req_q_in, ha->req_ring_index);
RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in);
} else {
WRT_REG_WORD(ISP_REQ_Q_IN(ha, &reg->isp), ha->req_ring_index);
RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, &reg->isp));
}
}
/**
* qla24xx_calc_iocbs() - Determine number of Command Type 3 and
* Continuation Type 1 IOCBs to allocate.
*
* @dsds: number of data segment decriptors needed
*
* Returns the number of IOCB entries needed to store @dsds.
*/
static inline uint16_t
qla24xx_calc_iocbs(uint16_t dsds)
{
uint16_t iocbs;
iocbs = 1;
if (dsds > 1) {
iocbs += (dsds - 1) / 5;
if ((dsds - 1) % 5)
iocbs++;
}
return iocbs;
}
/**
* qla24xx_build_scsi_iocbs() - Build IOCB command utilizing Command Type 7
* IOCB types.
*
* @sp: SRB command to process
* @cmd_pkt: Command type 3 IOCB
* @tot_dsds: Total number of segments to transfer
*/
static inline void
qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
uint16_t tot_dsds)
{
uint16_t avail_dsds;
uint32_t *cur_dsd;
scsi_qla_host_t *ha;
struct scsi_cmnd *cmd;
cmd = sp->cmd;
/* Update entry type to indicate Command Type 3 IOCB */
*((uint32_t *)(&cmd_pkt->entry_type)) =
__constant_cpu_to_le32(COMMAND_TYPE_7);
/* No data transfer */
if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
cmd_pkt->byte_count = __constant_cpu_to_le32(0);
return;
}
ha = sp->ha;
/* Set transfer direction */
if (cmd->sc_data_direction == DMA_TO_DEVICE)
cmd_pkt->task_mgmt_flags =
__constant_cpu_to_le16(TMF_WRITE_DATA);
else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
cmd_pkt->task_mgmt_flags =
__constant_cpu_to_le16(TMF_READ_DATA);
/* One DSD is available in the Command Type 3 IOCB */
avail_dsds = 1;
cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
/* Load data segments */
if (cmd->use_sg != 0) {
struct scatterlist *cur_seg;
struct scatterlist *end_seg;
cur_seg = (struct scatterlist *)cmd->request_buffer;
end_seg = cur_seg + tot_dsds;
while (cur_seg < end_seg) {
dma_addr_t sle_dma;
cont_a64_entry_t *cont_pkt;
/* Allocate additional continuation packets? */
if (avail_dsds == 0) {
/*
* Five DSDs are available in the Continuation
* Type 1 IOCB.
*/
cont_pkt = qla2x00_prep_cont_type1_iocb(ha);
cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
avail_dsds = 5;
}
sle_dma = sg_dma_address(cur_seg);
*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
*cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
avail_dsds--;
cur_seg++;
}
} else {
*cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle));
*cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle));
*cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
}
}
/**
* qla24xx_start_scsi() - Send a SCSI command to the ISP
* @sp: command to send to the ISP
*
* Returns non-zero if a failure occured, else zero.
*/
int
qla24xx_start_scsi(srb_t *sp)
{
int ret;
unsigned long flags;
scsi_qla_host_t *ha;
struct scsi_cmnd *cmd;
uint32_t *clr_ptr;
uint32_t index;
uint32_t handle;
struct cmd_type_7 *cmd_pkt;
struct scatterlist *sg;
uint16_t cnt;
uint16_t req_cnt;
uint16_t tot_dsds;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
char tag[2];
/* Setup device pointers. */
ret = 0;
ha = sp->ha;
reg = &ha->iobase->isp24;
cmd = sp->cmd;
/* So we know we haven't pci_map'ed anything yet */
tot_dsds = 0;
/* Send marker if required */
if (ha->marker_needed != 0) {
if (qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) {
return QLA_FUNCTION_FAILED;
}
ha->marker_needed = 0;
}
/* Acquire ring specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Check for room in outstanding command list. */
handle = ha->current_outstanding_cmd;
for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
handle++;
if (handle == MAX_OUTSTANDING_COMMANDS)
handle = 1;
if (ha->outstanding_cmds[handle] == 0)
break;
}
if (index == MAX_OUTSTANDING_COMMANDS)
goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */
if (cmd->use_sg) {
sg = (struct scatterlist *) cmd->request_buffer;
tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
cmd->sc_data_direction);
if (tot_dsds == 0)
goto queuing_error;
} else if (cmd->request_bufflen) {
dma_addr_t req_dma;
req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
cmd->request_bufflen, cmd->sc_data_direction);
if (dma_mapping_error(req_dma))
goto queuing_error;
sp->dma_handle = req_dma;
tot_dsds = 1;
}
req_cnt = qla24xx_calc_iocbs(tot_dsds);
if (ha->req_q_cnt < (req_cnt + 2)) {
cnt = (uint16_t)RD_REG_DWORD_RELAXED(&reg->req_q_out);
if (ha->req_ring_index < cnt)
ha->req_q_cnt = cnt - ha->req_ring_index;
else
ha->req_q_cnt = ha->request_q_length -
(ha->req_ring_index - cnt);
}
if (ha->req_q_cnt < (req_cnt + 2)) {
if (cmd->use_sg)
pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
cmd->sc_data_direction);
goto queuing_error;
}
/* Build command packet. */
ha->current_outstanding_cmd = handle;
ha->outstanding_cmds[handle] = sp;
sp->ha = ha;
sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
ha->req_q_cnt -= req_cnt;
cmd_pkt = (struct cmd_type_7 *)ha->request_ring_ptr;
cmd_pkt->handle = handle;
/* Zero out remaining portion of packet. */
clr_ptr = (uint32_t *)cmd_pkt + 2;
memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
/* Set NPORT-ID and LUN number*/
cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
cmd_pkt->lun[1] = LSB(sp->cmd->device->lun);
cmd_pkt->lun[2] = MSB(sp->cmd->device->lun);
/* Update tagged queuing modifier -- default is TSK_SIMPLE (0). */
if (scsi_populate_tag_msg(cmd, tag)) {
switch (tag[0]) {
case MSG_HEAD_TAG:
cmd_pkt->task = TSK_HEAD_OF_QUEUE;
break;
case MSG_ORDERED_TAG:
cmd_pkt->task = TSK_ORDERED;
break;
}
}
/* Load SCSI command packet. */
memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb));
cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen);
/* Build IOCB segments */
qla24xx_build_scsi_iocbs(sp, cmd_pkt, tot_dsds);
/* Set total data segment count. */
cmd_pkt->entry_count = (uint8_t)req_cnt;
wmb();
/* Adjust ring index. */
ha->req_ring_index++;
if (ha->req_ring_index == ha->request_q_length) {
ha->req_ring_index = 0;
ha->request_ring_ptr = ha->request_ring;
} else
ha->request_ring_ptr++;
sp->flags |= SRB_DMA_VALID;
sp->state = SRB_ACTIVE_STATE;
/* Set chip new ring index. */
WRT_REG_DWORD(&reg->req_q_in, ha->req_ring_index);
RD_REG_DWORD_RELAXED(&reg->req_q_in); /* PCI Posting. */
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
queuing_error:
if (cmd->use_sg && tot_dsds) {
sg = (struct scatterlist *) cmd->request_buffer;
pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
cmd->sc_data_direction);
} else if (tot_dsds) {
pci_unmap_single(ha->pdev, sp->dma_handle,
cmd->request_bufflen, cmd->sc_data_direction);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_FUNCTION_FAILED;
}

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -19,14 +19,17 @@
#include "qla_def.h"
static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
static void qla2x00_async_event(scsi_qla_host_t *, uint32_t);
static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *);
static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
void qla2x00_process_response_queue(struct scsi_qla_host *);
static void qla2x00_status_entry(scsi_qla_host_t *, sts_entry_t *);
static void qla2x00_status_entry(scsi_qla_host_t *, void *);
static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *);
static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);
void qla24xx_process_response_queue(scsi_qla_host_t *);
static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *);
/**
* qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
* @irq:
@ -41,11 +44,11 @@ irqreturn_t
qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
{
scsi_qla_host_t *ha;
device_reg_t __iomem *reg;
struct device_reg_2xxx __iomem *reg;
int status;
unsigned long flags;
unsigned long iter;
uint32_t mbx;
uint16_t mb[4];
ha = (scsi_qla_host_t *) dev_id;
if (!ha) {
@ -54,7 +57,7 @@ qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
return (IRQ_NONE);
}
reg = ha->iobase;
reg = &ha->iobase->isp;
status = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
@ -67,17 +70,20 @@ qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
RD_REG_WORD(&reg->hccr);
/* Get mailbox data. */
mbx = RD_MAILBOX_REG(ha, reg, 0);
if (mbx > 0x3fff && mbx < 0x8000) {
qla2x00_mbx_completion(ha, (uint16_t)mbx);
mb[0] = RD_MAILBOX_REG(ha, reg, 0);
if (mb[0] > 0x3fff && mb[0] < 0x8000) {
qla2x00_mbx_completion(ha, mb[0]);
status |= MBX_INTERRUPT;
} else if (mbx > 0x7fff && mbx < 0xc000) {
qla2x00_async_event(ha, mbx);
} else if (mb[0] > 0x7fff && mb[0] < 0xc000) {
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
mb[2] = RD_MAILBOX_REG(ha, reg, 2);
mb[3] = RD_MAILBOX_REG(ha, reg, 3);
qla2x00_async_event(ha, mb);
} else {
/*EMPTY*/
DEBUG2(printk("scsi(%ld): Unrecognized "
"interrupt type (%d)\n",
ha->host_no, mbx));
"interrupt type (%d).\n",
ha->host_no, mb[0]));
}
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
@ -118,13 +124,13 @@ irqreturn_t
qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
{
scsi_qla_host_t *ha;
device_reg_t __iomem *reg;
struct device_reg_2xxx __iomem *reg;
int status;
unsigned long flags;
unsigned long iter;
uint32_t stat;
uint32_t mbx;
uint16_t hccr;
uint16_t mb[4];
ha = (scsi_qla_host_t *) dev_id;
if (!ha) {
@ -133,7 +139,7 @@ qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
return (IRQ_NONE);
}
reg = ha->iobase;
reg = &ha->iobase->isp;
status = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
@ -146,7 +152,7 @@ qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
"Parity error -- HCCR=%x.\n", hccr);
else
qla_printk(KERN_INFO, ha,
"RISC paused -- HCCR=%x\n", hccr);
"RISC paused -- HCCR=%x.\n", hccr);
/*
* Issue a "HARD" reset in order for the RISC
@ -160,35 +166,41 @@ qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
} else if ((stat & HSR_RISC_INT) == 0)
break;
mbx = MSW(stat);
switch (stat & 0xff) {
case 0x13:
qla2x00_process_response_queue(ha);
break;
case 0x1:
case 0x2:
case 0x10:
case 0x11:
qla2x00_mbx_completion(ha, (uint16_t)mbx);
qla2x00_mbx_completion(ha, MSW(stat));
status |= MBX_INTERRUPT;
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
break;
case 0x12:
qla2x00_async_event(ha, mbx);
mb[0] = MSW(stat);
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
mb[2] = RD_MAILBOX_REG(ha, reg, 2);
mb[3] = RD_MAILBOX_REG(ha, reg, 3);
qla2x00_async_event(ha, mb);
break;
case 0x13:
qla2x00_process_response_queue(ha);
break;
case 0x15:
mbx = mbx << 16 | MBA_CMPLT_1_16BIT;
qla2x00_async_event(ha, mbx);
mb[0] = MBA_CMPLT_1_16BIT;
mb[1] = MSW(stat);
qla2x00_async_event(ha, mb);
break;
case 0x16:
mbx = mbx << 16 | MBA_SCSI_COMPLETION;
qla2x00_async_event(ha, mbx);
mb[0] = MBA_SCSI_COMPLETION;
mb[1] = MSW(stat);
mb[2] = RD_MAILBOX_REG(ha, reg, 2);
qla2x00_async_event(ha, mb);
break;
default:
DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
"(%d)\n",
"(%d).\n",
ha->host_no, stat & 0xff));
break;
}
@ -220,7 +232,7 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
{
uint16_t cnt;
uint16_t __iomem *wptr;
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
/* Load return mailbox registers. */
ha->flags.mbox_int = 1;
@ -250,78 +262,65 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
/**
* qla2x00_async_event() - Process aynchronous events.
* @ha: SCSI driver HA context
* @mb0: Mailbox0 register
* @mb: Mailbox registers (0 - 3)
*/
static void
qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
{
static char *link_speeds[5] = { "1", "2", "4", "?", "10" };
#define LS_UNKNOWN 2
static char *link_speeds[5] = { "1", "2", "?", "4", "10" };
char *link_speed;
uint16_t mb[4];
uint16_t handle_cnt;
uint16_t cnt;
uint32_t handles[5];
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint32_t rscn_entry, host_pid;
uint8_t rscn_queue_index;
/* Setup to process RIO completion. */
handle_cnt = 0;
mb[0] = LSW(mbx);
switch (mb[0]) {
case MBA_SCSI_COMPLETION:
if (IS_QLA2100(ha) || IS_QLA2200(ha))
handles[0] = le32_to_cpu(
((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) |
RD_MAILBOX_REG(ha, reg, 1));
else
handles[0] = le32_to_cpu(
((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) |
MSW(mbx));
handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
handle_cnt = 1;
break;
case MBA_CMPLT_1_16BIT:
if (IS_QLA2100(ha) || IS_QLA2200(ha))
handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
else
handles[0] = MSW(mbx);
handles[0] = mb[1];
handle_cnt = 1;
mb[0] = MBA_SCSI_COMPLETION;
break;
case MBA_CMPLT_2_16BIT:
handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2);
handles[0] = mb[1];
handles[1] = mb[2];
handle_cnt = 2;
mb[0] = MBA_SCSI_COMPLETION;
break;
case MBA_CMPLT_3_16BIT:
handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2);
handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3);
handles[0] = mb[1];
handles[1] = mb[2];
handles[2] = mb[3];
handle_cnt = 3;
mb[0] = MBA_SCSI_COMPLETION;
break;
case MBA_CMPLT_4_16BIT:
handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2);
handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3);
handles[0] = mb[1];
handles[1] = mb[2];
handles[2] = mb[3];
handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
handle_cnt = 4;
mb[0] = MBA_SCSI_COMPLETION;
break;
case MBA_CMPLT_5_16BIT:
handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2);
handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3);
handles[0] = mb[1];
handles[1] = mb[2];
handles[2] = mb[3];
handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
handles[4] = (uint32_t)RD_MAILBOX_REG(ha, reg, 7);
handle_cnt = 5;
mb[0] = MBA_SCSI_COMPLETION;
break;
case MBA_CMPLT_2_32BIT:
handles[0] = le32_to_cpu(
((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) |
RD_MAILBOX_REG(ha, reg, 1));
handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
handles[1] = le32_to_cpu(
((uint32_t)(RD_MAILBOX_REG(ha, reg, 7) << 16)) |
RD_MAILBOX_REG(ha, reg, 6));
@ -356,12 +355,17 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
"ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
mb[1], mb[2], mb[3]);
if (IS_QLA2100(ha) || IS_QLA2200(ha))
qla2100_fw_dump(ha, 1);
else
qla2300_fw_dump(ha, 1);
ha->isp_ops.fw_dump(ha, 1);
if (mb[1] == 0) {
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
if (mb[1] == 0 && mb[2] == 0) {
qla_printk(KERN_ERR, ha,
"Unrecoverable Hardware Error: adapter "
"marked OFFLINE!\n");
ha->flags.online = 0;
} else
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
} else if (mb[1] == 0) {
qla_printk(KERN_INFO, ha,
"Unrecoverable Hardware Error: adapter marked "
"OFFLINE!\n");
@ -392,8 +396,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
break;
case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no,
mb[1]));
qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]);
@ -414,13 +416,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
break;
case MBA_LOOP_UP: /* Loop Up Event */
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
ha->link_data_rate = 0;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
link_speed = link_speeds[0];
} else {
link_speed = link_speeds[3];
link_speed = link_speeds[LS_UNKNOWN];
if (mb[1] < 5)
link_speed = link_speeds[mb[1]];
ha->link_data_rate = mb[1];
@ -438,9 +438,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
break;
case MBA_LOOP_DOWN: /* Loop Down Event */
DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN.\n",
ha->host_no));
qla_printk(KERN_INFO, ha, "LOOP DOWN detected.\n");
DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n",
ha->host_no, mb[1]));
qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]);
if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN);
@ -457,8 +457,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
break;
case MBA_LIP_RESET: /* LIP reset occurred */
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n",
ha->host_no, mb[1]));
qla_printk(KERN_INFO, ha,
@ -509,8 +507,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
if (IS_QLA2100(ha))
break;
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection "
"received.\n",
ha->host_no));
@ -530,16 +526,14 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
break;
case MBA_PORT_UPDATE: /* Port database update */
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
mb[2] = RD_MAILBOX_REG(ha, reg, 2);
/*
* If a single remote port just logged into (or logged out of)
* us, create a new entry in our rscn fcports list and handle
* the event like an RSCN.
*/
if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
!IS_QLA6322(ha) && ha->flags.init_done && mb[1] != 0xffff &&
!IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
ha->flags.init_done && mb[1] != 0xffff &&
((ha->operating_mode == P2P && mb[1] != 0) ||
(ha->operating_mode != P2P && mb[1] !=
SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) {
@ -550,8 +544,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC);
if (rscn_fcport) {
DEBUG14(printk("scsi(%ld): Port Update -- "
"creating RSCN fcport %p for %x/%x.\n",
ha->host_no, rscn_fcport, mb[1], mb[2]));
"creating RSCN fcport %p for %x/%x/%x.\n",
ha->host_no, rscn_fcport, mb[1], mb[2],
mb[3]));
rscn_fcport->loop_id = mb[1];
rscn_fcport->d_id.b24 = INVALID_PORT_ID;
@ -580,15 +575,16 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
if (atomic_read(&ha->loop_state) != LOOP_DOWN &&
atomic_read(&ha->loop_state) != LOOP_DEAD) {
DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE "
"ignored.\n", ha->host_no));
"ignored %04x/%04x/%04x.\n", ha->host_no, mb[1],
mb[2], mb[3]));
break;
}
DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n",
ha->host_no));
DEBUG(printk(KERN_INFO
"scsi(%ld): Port database changed %04x %04x.\n",
ha->host_no, mb[1], mb[2]));
"scsi(%ld): Port database changed %04x %04x %04x.\n",
ha->host_no, mb[1], mb[2], mb[3]));
/*
* Mark all devices as missing so we will login again.
@ -607,9 +603,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
break;
case MBA_RSCN_UPDATE: /* State Change Registration */
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
mb[2] = RD_MAILBOX_REG(ha, reg, 2);
DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
ha->host_no));
DEBUG(printk(KERN_INFO
@ -658,6 +651,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
qla2x00_process_response_queue(ha);
break;
case MBA_DISCARD_RND_FRAME:
DEBUG2(printk("scsi(%ld): Discard RND Frame -- %04x %04x "
"%04x.\n", ha->host_no, mb[1], mb[2], mb[3]));
break;
}
}
@ -710,7 +708,7 @@ qla2x00_process_completed_request(struct scsi_qla_host *ha, uint32_t index)
void
qla2x00_process_response_queue(struct scsi_qla_host *ha)
{
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
sts_entry_t *pkt;
uint16_t handle_cnt;
uint16_t cnt;
@ -804,31 +802,41 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
* @pkt: Entry pointer
*/
static void
qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
{
unsigned b, t, l;
srb_t *sp;
fc_port_t *fcport;
struct scsi_cmnd *cp;
sts_entry_t *sts;
struct sts_entry_24xx *sts24;
uint16_t comp_status;
uint16_t scsi_status;
uint8_t lscsi_status;
int32_t resid;
uint8_t sense_sz = 0;
uint16_t rsp_info_len;
uint32_t sense_len, rsp_info_len, resid_len;
uint8_t *rsp_info, *sense_data;
sts = (sts_entry_t *) pkt;
sts24 = (struct sts_entry_24xx *) pkt;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
comp_status = le16_to_cpu(sts24->comp_status);
scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
} else {
comp_status = le16_to_cpu(sts->comp_status);
scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK;
}
/* Fast path completion. */
if (le16_to_cpu(pkt->comp_status) == CS_COMPLETE &&
(le16_to_cpu(pkt->scsi_status) & SS_MASK) == 0) {
qla2x00_process_completed_request(ha, pkt->handle);
if (comp_status == CS_COMPLETE && scsi_status == 0) {
qla2x00_process_completed_request(ha, sts->handle);
return;
}
/* Validate handle. */
if (pkt->handle < MAX_OUTSTANDING_COMMANDS) {
sp = ha->outstanding_cmds[pkt->handle];
ha->outstanding_cmds[pkt->handle] = NULL;
if (sts->handle < MAX_OUTSTANDING_COMMANDS) {
sp = ha->outstanding_cmds[sts->handle];
ha->outstanding_cmds[sts->handle] = NULL;
} else
sp = NULL;
@ -847,40 +855,49 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
if (cp == NULL) {
DEBUG2(printk("scsi(%ld): Command already returned back to OS "
"pkt->handle=%d sp=%p sp->state:%d\n",
ha->host_no, pkt->handle, sp, sp->state));
ha->host_no, sts->handle, sp, sp->state));
qla_printk(KERN_WARNING, ha,
"Command is NULL: already returned to OS (sp=%p)\n", sp);
return;
}
comp_status = le16_to_cpu(pkt->comp_status);
/* Mask of reserved bits 12-15, before we examine the scsi status */
scsi_status = le16_to_cpu(pkt->scsi_status) & SS_MASK;
lscsi_status = scsi_status & STATUS_MASK;
CMD_ENTRY_STATUS(cp) = pkt->entry_status;
CMD_ENTRY_STATUS(cp) = sts->entry_status;
CMD_COMPL_STATUS(cp) = comp_status;
CMD_SCSI_STATUS(cp) = scsi_status;
/* Generate LU queue on cntrl, target, LUN */
b = cp->device->channel;
t = cp->device->id;
l = cp->device->lun,
fcport = sp->fcport;
sense_len = rsp_info_len = resid_len = 0;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
sense_len = le32_to_cpu(sts24->sense_len);
rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
resid_len = le32_to_cpu(sts24->rsp_residual_count);
rsp_info = sts24->data;
sense_data = sts24->data;
host_to_fcp_swap(sts24->data, sizeof(sts24->data));
} else {
sense_len = le16_to_cpu(sts->req_sense_length);
rsp_info_len = le16_to_cpu(sts->rsp_info_len);
resid_len = le32_to_cpu(sts->residual_length);
rsp_info = sts->rsp_info;
sense_data = sts->req_sense_data;
}
/* Check for any FCP transport errors. */
if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
rsp_info_len = le16_to_cpu(pkt->rsp_info_len);
if (rsp_info_len > 3 && pkt->rsp_info[3]) {
/* Sense data lies beyond any FCP RESPONSE data. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
sense_data += rsp_info_len;
if (rsp_info_len > 3 && rsp_info[3]) {
DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol "
"failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..."
"retrying command\n", ha->host_no, b, t, l,
rsp_info_len, pkt->rsp_info[0], pkt->rsp_info[1],
pkt->rsp_info[2], pkt->rsp_info[3],
pkt->rsp_info[4], pkt->rsp_info[5],
pkt->rsp_info[6], pkt->rsp_info[7]));
"retrying command\n", ha->host_no,
cp->device->channel, cp->device->id,
cp->device->lun, rsp_info_len, rsp_info[0],
rsp_info[1], rsp_info[2], rsp_info[3], rsp_info[4],
rsp_info[5], rsp_info[6], rsp_info[7]));
cp->result = DID_BUS_BUSY << 16;
qla2x00_sp_compl(ha, sp);
@ -898,7 +915,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
break;
}
if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
resid = le32_to_cpu(pkt->residual_length);
resid = resid_len;
cp->resid = resid;
CMD_RESID_LEN(cp) = resid;
}
@ -907,39 +924,34 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
if (lscsi_status != SS_CHECK_CONDITION)
break;
/*
* Copy Sense Data into sense buffer
*/
/* Copy Sense Data into sense buffer. */
memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer));
if (!(scsi_status & SS_SENSE_LEN_VALID))
break;
if (le16_to_cpu(pkt->req_sense_length) <
sizeof(cp->sense_buffer))
sense_sz = le16_to_cpu(pkt->req_sense_length);
else
sense_sz = sizeof(cp->sense_buffer);
if (sense_len >= sizeof(cp->sense_buffer))
sense_len = sizeof(cp->sense_buffer);
CMD_ACTUAL_SNSLEN(cp) = sense_sz;
sp->request_sense_length = sense_sz;
CMD_ACTUAL_SNSLEN(cp) = sense_len;
sp->request_sense_length = sense_len;
sp->request_sense_ptr = cp->sense_buffer;
if (sp->request_sense_length > 32)
sense_sz = 32;
sense_len = 32;
memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz);
memcpy(cp->sense_buffer, sense_data, sense_len);
sp->request_sense_ptr += sense_sz;
sp->request_sense_length -= sense_sz;
sp->request_sense_ptr += sense_len;
sp->request_sense_length -= sense_len;
if (sp->request_sense_length != 0)
ha->status_srb = sp;
DEBUG5(printk("%s(): Check condition Sense data, "
"scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n",
__func__, ha->host_no, b, t, l, cp,
cp->serial_number));
if (sense_sz)
"scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", __func__,
ha->host_no, cp->device->channel, cp->device->id,
cp->device->lun, cp, cp->serial_number));
if (sense_len)
DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
CMD_ACTUAL_SNSLEN(cp)));
break;
@ -947,9 +959,10 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
case CS_DATA_UNDERRUN:
DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n",
ha->host_no, t, l, comp_status, scsi_status));
ha->host_no, cp->device->id, cp->device->lun, comp_status,
scsi_status));
resid = le32_to_cpu(pkt->residual_length);
resid = resid_len;
if (scsi_status & SS_RESIDUAL_UNDER) {
cp->resid = resid;
CMD_RESID_LEN(cp) = resid;
@ -971,31 +984,30 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
if (!(scsi_status & SS_SENSE_LEN_VALID))
break;
if (le16_to_cpu(pkt->req_sense_length) <
sizeof(cp->sense_buffer))
sense_sz = le16_to_cpu(pkt->req_sense_length);
else
sense_sz = sizeof(cp->sense_buffer);
if (sense_len >= sizeof(cp->sense_buffer))
sense_len = sizeof(cp->sense_buffer);
CMD_ACTUAL_SNSLEN(cp) = sense_sz;
sp->request_sense_length = sense_sz;
CMD_ACTUAL_SNSLEN(cp) = sense_len;
sp->request_sense_length = sense_len;
sp->request_sense_ptr = cp->sense_buffer;
if (sp->request_sense_length > 32)
sense_sz = 32;
sense_len = 32;
memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz);
memcpy(cp->sense_buffer, sense_data, sense_len);
sp->request_sense_ptr += sense_sz;
sp->request_sense_length -= sense_sz;
sp->request_sense_ptr += sense_len;
sp->request_sense_length -= sense_len;
if (sp->request_sense_length != 0)
ha->status_srb = sp;
DEBUG5(printk("%s(): Check condition Sense data, "
"scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n",
__func__, ha->host_no, b, t, l, cp,
__func__, ha->host_no, cp->device->channel,
cp->device->id, cp->device->lun, cp,
cp->serial_number));
if (sense_sz)
if (sense_len)
DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
CMD_ACTUAL_SNSLEN(cp)));
} else {
@ -1007,8 +1019,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
if (!(scsi_status & SS_RESIDUAL_UNDER)) {
DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped "
"frame(s) detected (%x of %x bytes)..."
"retrying command.\n",
ha->host_no, b, t, l, resid,
"retrying command.\n", ha->host_no,
cp->device->channel, cp->device->id,
cp->device->lun, resid,
cp->request_bufflen));
cp->result = DID_BUS_BUSY << 16;
@ -1021,8 +1034,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d:%d): Mid-layer underflow "
"detected (%x of %x bytes)...returning "
"error status.\n",
ha->host_no, b, t, l, resid,
"error status.\n", ha->host_no,
cp->device->channel, cp->device->id,
cp->device->lun, resid,
cp->request_bufflen);
cp->result = DID_ERROR << 16;
@ -1037,7 +1051,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
case CS_DATA_OVERRUN:
DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d): OVERRUN status detected 0x%x-0x%x\n",
ha->host_no, t, l, comp_status, scsi_status));
ha->host_no, cp->device->id, cp->device->lun, comp_status,
scsi_status));
DEBUG2(printk(KERN_INFO
"CDB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3],
@ -1045,8 +1060,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
DEBUG2(printk(KERN_INFO
"PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR "
"status!\n",
cp->serial_number, cp->request_bufflen,
le32_to_cpu(pkt->residual_length)));
cp->serial_number, cp->request_bufflen, resid_len));
cp->result = DID_ERROR << 16;
break;
@ -1063,7 +1077,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
*/
DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down "
"pid=%ld, compl status=0x%x, port state=0x%x\n",
ha->host_no, t, l, cp->serial_number, comp_status,
ha->host_no, cp->device->id, cp->device->lun,
cp->serial_number, comp_status,
atomic_read(&fcport->state)));
cp->result = DID_BUS_BUSY << 16;
@ -1094,17 +1109,25 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
break;
case CS_TIMEOUT:
DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x "
"sflags=%x.\n", ha->host_no, b, t, l, comp_status,
scsi_status, le16_to_cpu(pkt->status_flags)));
cp->result = DID_BUS_BUSY << 16;
/* Check to see if logout occurred */
if ((le16_to_cpu(pkt->status_flags) & SF_LOGOUT_SENT)) {
qla2x00_mark_device_lost(ha, fcport, 1);
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d:%d): TIMEOUT status detected "
"0x%x-0x%x\n", ha->host_no, cp->device->channel,
cp->device->id, cp->device->lun, comp_status,
scsi_status));
break;
}
DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x "
"sflags=%x.\n", ha->host_no, cp->device->channel,
cp->device->id, cp->device->lun, comp_status, scsi_status,
le16_to_cpu(sts->status_flags)));
/* Check to see if logout occurred. */
if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
qla2x00_mark_device_lost(ha, fcport, 1);
break;
case CS_QUEUE_FULL:
@ -1120,8 +1143,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
default:
DEBUG3(printk("scsi(%ld): Error detected (unknown status) "
"0x%x-0x%x.\n",
ha->host_no, comp_status, scsi_status));
"0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status));
qla_printk(KERN_INFO, ha,
"Unknown status detected 0x%x-0x%x.\n",
comp_status, scsi_status);
@ -1169,6 +1191,8 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt)
}
/* Move sense data. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
host_to_fcp_swap(pkt->data, sizeof(pkt->data));
memcpy(sp->request_sense_ptr, pkt->data, sense_sz);
DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz));
@ -1231,8 +1255,8 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
}
qla2x00_sp_compl(ha, sp);
} else if (pkt->entry_type == COMMAND_A64_TYPE ||
pkt->entry_type == COMMAND_TYPE) {
} else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type ==
COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7) {
DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n",
ha->host_no));
qla_printk(KERN_WARNING, ha,
@ -1280,3 +1304,229 @@ qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt)
qla2x00_sp_compl(ha, sp);
}
/**
* qla24xx_mbx_completion() - Process mailbox command completions.
* @ha: SCSI driver HA context
* @mb0: Mailbox0 register
*/
static void
qla24xx_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
{
uint16_t cnt;
uint16_t __iomem *wptr;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
/* Load return mailbox registers. */
ha->flags.mbox_int = 1;
ha->mailbox_out[0] = mb0;
wptr = (uint16_t __iomem *)&reg->mailbox1;
for (cnt = 1; cnt < ha->mbx_count; cnt++) {
ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
wptr++;
}
if (ha->mcp) {
DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n",
__func__, ha->host_no, ha->mcp->mb[0]));
} else {
DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n",
__func__, ha->host_no));
}
}
/**
* qla24xx_process_response_queue() - Process response queue entries.
* @ha: SCSI driver HA context
*/
void
qla24xx_process_response_queue(struct scsi_qla_host *ha)
{
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
struct sts_entry_24xx *pkt;
if (!ha->flags.online)
return;
while (ha->response_ring_ptr->signature != RESPONSE_PROCESSED) {
pkt = (struct sts_entry_24xx *)ha->response_ring_ptr;
ha->rsp_ring_index++;
if (ha->rsp_ring_index == ha->response_q_length) {
ha->rsp_ring_index = 0;
ha->response_ring_ptr = ha->response_ring;
} else {
ha->response_ring_ptr++;
}
if (pkt->entry_status != 0) {
DEBUG3(printk(KERN_INFO
"scsi(%ld): Process error entry.\n", ha->host_no));
qla2x00_error_entry(ha, (sts_entry_t *) pkt);
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
wmb();
continue;
}
switch (pkt->entry_type) {
case STATUS_TYPE:
qla2x00_status_entry(ha, pkt);
break;
case STATUS_CONT_TYPE:
qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
break;
case MS_IOCB_TYPE:
qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt);
break;
default:
/* Type Not Supported. */
DEBUG4(printk(KERN_WARNING
"scsi(%ld): Received unknown response pkt type %x "
"entry status=%x.\n",
ha->host_no, pkt->entry_type, pkt->entry_status));
break;
}
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
wmb();
}
/* Adjust ring index */
WRT_REG_DWORD(&reg->rsp_q_out, ha->rsp_ring_index);
}
/**
* qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
* @irq:
* @dev_id: SCSI driver HA context
* @regs:
*
* Called by system whenever the host adapter generates an interrupt.
*
* Returns handled flag.
*/
irqreturn_t
qla24xx_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
{
scsi_qla_host_t *ha;
struct device_reg_24xx __iomem *reg;
int status;
unsigned long flags;
unsigned long iter;
uint32_t stat;
uint32_t hccr;
uint16_t mb[4];
ha = (scsi_qla_host_t *) dev_id;
if (!ha) {
printk(KERN_INFO
"%s(): NULL host pointer\n", __func__);
return IRQ_NONE;
}
reg = &ha->iobase->isp24;
status = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
for (iter = 50; iter--; ) {
stat = RD_REG_DWORD(&reg->host_status);
if (stat & HSRX_RISC_PAUSED) {
hccr = RD_REG_DWORD(&reg->hccr);
qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
"Dumping firmware!\n", hccr);
qla24xx_fw_dump(ha, 1);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break;
} else if ((stat & HSRX_RISC_INT) == 0)
break;
switch (stat & 0xff) {
case 0x1:
case 0x2:
case 0x10:
case 0x11:
qla24xx_mbx_completion(ha, MSW(stat));
status |= MBX_INTERRUPT;
break;
case 0x12:
mb[0] = MSW(stat);
mb[1] = RD_REG_WORD(&reg->mailbox1);
mb[2] = RD_REG_WORD(&reg->mailbox2);
mb[3] = RD_REG_WORD(&reg->mailbox3);
qla2x00_async_event(ha, mb);
break;
case 0x13:
qla24xx_process_response_queue(ha);
break;
default:
DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
"(%d).\n",
ha->host_no, stat & 0xff));
break;
}
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
RD_REG_DWORD_RELAXED(&reg->hccr);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
(status & MBX_INTERRUPT) && ha->flags.mbox_int) {
spin_lock_irqsave(&ha->mbx_reg_lock, flags);
set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
up(&ha->mbx_intr_sem);
spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
}
return IRQ_HANDLED;
}
/**
* qla24xx_ms_entry() - Process a Management Server entry.
* @ha: SCSI driver HA context
* @index: Response queue out pointer
*/
static void
qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
{
srb_t *sp;
DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
__func__, ha->host_no, pkt, pkt->handle));
DEBUG9(printk("%s: ct pkt dump:\n", __func__);)
DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx));)
/* Validate handle. */
if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
sp = ha->outstanding_cmds[pkt->handle];
else
sp = NULL;
if (sp == NULL) {
DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
ha->host_no));
DEBUG10(printk("scsi(%ld): MS entry - invalid handle\n",
ha->host_no));
qla_printk(KERN_WARNING, ha, "MS entry - invalid handle %d\n",
pkt->handle);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
return;
}
CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->comp_status);
CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
/* Free outstanding command slot. */
ha->outstanding_cmds[pkt->handle] = NULL;
qla2x00_sp_compl(ha, sp);
}

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -79,6 +79,11 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xloginretrycount,
"Specify an alternate value for the NVRAM login retry count.");
int ql2xfwloadbin;
module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xfwloadbin,
"Load ISP2xxx firmware image via hotplug.");
static void qla2x00_free_device(scsi_qla_host_t *);
static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
@ -91,6 +96,8 @@ static int qla2xxx_slave_alloc(struct scsi_device *);
static void qla2xxx_slave_destroy(struct scsi_device *);
static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
void (*fn)(struct scsi_cmnd *));
static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
void (*fn)(struct scsi_cmnd *));
static int qla2xxx_eh_abort(struct scsi_cmnd *);
static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
@ -124,6 +131,28 @@ static struct scsi_host_template qla2x00_driver_template = {
.max_sectors = 0xFFFF,
};
static struct scsi_host_template qla24xx_driver_template = {
.module = THIS_MODULE,
.name = "qla2xxx",
.queuecommand = qla24xx_queuecommand,
.eh_abort_handler = qla2xxx_eh_abort,
.eh_device_reset_handler = qla2xxx_eh_device_reset,
.eh_bus_reset_handler = qla2xxx_eh_bus_reset,
.eh_host_reset_handler = qla2xxx_eh_host_reset,
.slave_configure = qla2xxx_slave_configure,
.slave_alloc = qla2xxx_slave_alloc,
.slave_destroy = qla2xxx_slave_destroy,
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
};
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
/* TODO Convert to inlines
@ -171,14 +200,13 @@ static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
static void qla2x00_mem_free(scsi_qla_host_t *ha);
static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
static void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
static srb_t *qla2x00_get_new_sp(scsi_qla_host_t *);
static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *);
void qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *);
/* -------------------------------------------------------------------------- */
static char *
qla2x00_get_pci_info_str(struct scsi_qla_host *ha, char *str)
qla2x00_pci_info_str(struct scsi_qla_host *ha, char *str)
{
static char *pci_bus_modes[] = {
"33", "66", "100", "133",
@ -200,8 +228,56 @@ qla2x00_get_pci_info_str(struct scsi_qla_host *ha, char *str)
return (str);
}
static char *
qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str)
{
static char *pci_bus_modes[] = { "33", "66", "100", "133", };
uint32_t pci_bus;
int pcie_reg;
pcie_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP);
if (pcie_reg) {
char lwstr[6];
uint16_t pcie_lstat, lspeed, lwidth;
pcie_reg += 0x12;
pci_read_config_word(ha->pdev, pcie_reg, &pcie_lstat);
lspeed = pcie_lstat & (BIT_0 | BIT_1 | BIT_2 | BIT_3);
lwidth = (pcie_lstat &
(BIT_4 | BIT_5 | BIT_6 | BIT_7 | BIT_8 | BIT_9)) >> 4;
strcpy(str, "PCIe (");
if (lspeed == 1)
strcat(str, "2.5Gb/s ");
else
strcat(str, "<unknown> ");
snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth);
strcat(str, lwstr);
return str;
}
strcpy(str, "PCI");
pci_bus = (ha->pci_attr & CSRX_PCIX_BUS_MODE_MASK) >> 8;
if (pci_bus == 0 || pci_bus == 8) {
strcat(str, " (");
strcat(str, pci_bus_modes[pci_bus >> 3]);
} else {
strcat(str, "-X ");
if (pci_bus & BIT_2)
strcat(str, "Mode 2");
else
strcat(str, "Mode 1");
strcat(str, " (");
strcat(str, pci_bus_modes[pci_bus & ~BIT_2]);
}
strcat(str, " MHz)");
return str;
}
char *
qla2x00_get_fw_version_str(struct scsi_qla_host *ha, char *str)
qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str)
{
char un_str[10];
@ -238,25 +314,45 @@ qla2x00_get_fw_version_str(struct scsi_qla_host *ha, char *str)
return (str);
}
/**************************************************************************
* qla2x00_queuecommand
*
* Description:
* Queue a command to the controller.
*
* Input:
* cmd - pointer to Scsi cmd structure
* fn - pointer to Scsi done function
*
* Returns:
* 0 - Always
*
* Note:
* The mid-level driver tries to ensures that queuecommand never gets invoked
* concurrently with itself or the interrupt handler (although the
* interrupt handler may call this routine as part of request-completion
* handling).
**************************************************************************/
char *
qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str)
{
sprintf(str, "%d.%02d.%02d ", ha->fw_major_version,
ha->fw_minor_version,
ha->fw_subminor_version);
if (ha->fw_attributes & BIT_0)
strcat(str, "[Class 2] ");
if (ha->fw_attributes & BIT_1)
strcat(str, "[IP] ");
if (ha->fw_attributes & BIT_2)
strcat(str, "[Multi-ID] ");
if (ha->fw_attributes & BIT_13)
strcat(str, "[Experimental]");
return str;
}
static inline srb_t *
qla2x00_get_new_sp(scsi_qla_host_t *ha, fc_port_t *fcport,
struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
srb_t *sp;
sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
if (!sp)
return sp;
atomic_set(&sp->ref_count, 1);
sp->ha = ha;
sp->fcport = fcport;
sp->cmd = cmd;
sp->flags = 0;
CMD_SP(cmd) = (void *)sp;
cmd->scsi_done = done;
return sp;
}
static int
qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
@ -281,18 +377,9 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
spin_unlock_irq(ha->host->host_lock);
/* Allocate a command packet from the "sp" pool. */
if ((sp = qla2x00_get_new_sp(ha)) == NULL) {
sp = qla2x00_get_new_sp(ha, fcport, cmd, done);
if (!sp)
goto qc_host_busy_lock;
}
sp->ha = ha;
sp->fcport = fcport;
sp->cmd = cmd;
sp->flags = 0;
CMD_SP(cmd) = (void *)sp;
cmd->scsi_done = done;
rval = qla2x00_start_scsi(sp);
if (rval != QLA_SUCCESS)
@ -314,7 +401,6 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
qc_host_busy_free_sp:
qla2x00_sp_free_dma(ha, sp);
CMD_SP(cmd) = NULL;
mempool_free(sp, ha->srb_mempool);
qc_host_busy_lock:
@ -329,6 +415,60 @@ qc_fail_command:
return 0;
}
static int
qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
srb_t *sp;
int rval;
if (!fcport) {
cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
goto qc24_host_busy;
}
spin_unlock_irq(ha->host->host_lock);
sp = qla2x00_get_new_sp(ha, fcport, cmd, done);
if (!sp)
goto qc24_host_busy_lock;
rval = qla24xx_start_scsi(sp);
if (rval != QLA_SUCCESS)
goto qc24_host_busy_free_sp;
spin_lock_irq(ha->host->host_lock);
return 0;
qc24_host_busy_free_sp:
qla2x00_sp_free_dma(ha, sp);
mempool_free(sp, ha->srb_mempool);
qc24_host_busy_lock:
spin_lock_irq(ha->host->host_lock);
qc24_host_busy:
return SCSI_MLQUEUE_HOST_BUSY;
qc24_fail_command:
done(cmd);
return 0;
}
/*
* qla2x00_eh_wait_on_command
* Waits for the command to be returned by the Firmware for some
@ -493,7 +633,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
DEBUG3(qla2x00_print_scsi_cmd(cmd);)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (qla2x00_abort_command(ha, sp)) {
if (ha->isp_ops.abort_command(ha, sp)) {
DEBUG2(printk("%s(%ld): abort_command "
"mbx failed.\n", __func__, ha->host_no));
} else {
@ -624,7 +764,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
#if defined(LOGOUT_AFTER_DEVICE_RESET)
if (ret == SUCCESS) {
if (fcport->flags & FC_FABRIC_DEVICE) {
qla2x00_fabric_logout(ha, fcport->loop_id);
ha->isp_ops.fabric_logout(ha, fcport->loop_id);
qla2x00_mark_device_lost(ha, fcport);
}
}
@ -925,32 +1065,18 @@ static int
qla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport)
{
/* Abort Target command will clear Reservation */
return qla2x00_abort_target(reset_fcport);
return ha->isp_ops.abort_target(reset_fcport);
}
static int
qla2xxx_slave_alloc(struct scsi_device *sdev)
{
scsi_qla_host_t *ha = to_qla_host(sdev->host);
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
fc_port_t *fcport;
int found;
if (!rport)
return -ENXIO;
found = 0;
list_for_each_entry(fcport, &ha->fcports, list) {
if (rport->port_name ==
be64_to_cpu(*(uint64_t *)fcport->port_name)) {
found++;
break;
}
}
if (!found)
return -ENXIO;
sdev->hostdata = fcport;
sdev->hostdata = rport->dd_data;
return 0;
}
@ -989,8 +1115,6 @@ qla2x00_config_dma_addressing(scsi_qla_host_t *ha)
{
/* Assume 32bit DMA address */
ha->flags.enable_64bit_addressing = 0;
ha->calc_request_entries = qla2x00_calc_iocbs_32;
ha->build_scsi_iocbs = qla2x00_build_scsi_iocbs_32;
/*
* Given the two variants pci_set_dma_mask(), allow the compiler to
@ -999,8 +1123,8 @@ qla2x00_config_dma_addressing(scsi_qla_host_t *ha)
if (sizeof(dma_addr_t) > 4) {
if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) {
ha->flags.enable_64bit_addressing = 1;
ha->calc_request_entries = qla2x00_calc_iocbs_64;
ha->build_scsi_iocbs = qla2x00_build_scsi_iocbs_64;
ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64;
ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64;
if (pci_set_consistent_dma_mask(ha->pdev,
DMA_64BIT_MASK)) {
@ -1087,6 +1211,61 @@ iospace_error_exit:
return (-ENOMEM);
}
static void
qla2x00_enable_intrs(scsi_qla_host_t *ha)
{
unsigned long flags = 0;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 1;
/* enable risc and host interrupts */
WRT_REG_WORD(&reg->ictrl, ICR_EN_INT | ICR_EN_RISC);
RD_REG_WORD(&reg->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static void
qla2x00_disable_intrs(scsi_qla_host_t *ha)
{
unsigned long flags = 0;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 0;
/* disable risc and host interrupts */
WRT_REG_WORD(&reg->ictrl, 0);
RD_REG_WORD(&reg->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static void
qla24xx_enable_intrs(scsi_qla_host_t *ha)
{
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 1;
WRT_REG_DWORD(&reg->ictrl, ICRX_EN_RISC_INT);
RD_REG_DWORD(&reg->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static void
qla24xx_disable_intrs(scsi_qla_host_t *ha)
{
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 0;
WRT_REG_DWORD(&reg->ictrl, 0);
RD_REG_DWORD(&reg->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
/*
* PCI driver interface
*/
@ -1105,8 +1284,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
if (pci_enable_device(pdev))
goto probe_out;
host = scsi_host_alloc(&qla2x00_driver_template,
sizeof(scsi_qla_host_t));
host = scsi_host_alloc(brd_info->sht ? brd_info->sht:
&qla2x00_driver_template, sizeof(scsi_qla_host_t));
if (host == NULL) {
printk(KERN_WARNING
"qla2xxx: Couldn't allocate host from scsi layer!\n");
@ -1128,18 +1307,41 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
if (ret)
goto probe_failed;
/* Sanitize the information from PCI BIOS. */
host->irq = pdev->irq;
qla_printk(KERN_INFO, ha,
"Found an %s, irq %d, iobase 0x%p\n", ha->brd_info->isp_name,
host->irq, ha->iobase);
pdev->irq, ha->iobase);
spin_lock_init(&ha->hardware_lock);
ha->prev_topology = 0;
ha->ports = MAX_BUSES;
ha->init_cb_size = sizeof(init_cb_t);
/* Assign ISP specific operations. */
ha->isp_ops.pci_config = qla2100_pci_config;
ha->isp_ops.reset_chip = qla2x00_reset_chip;
ha->isp_ops.chip_diag = qla2x00_chip_diag;
ha->isp_ops.config_rings = qla2x00_config_rings;
ha->isp_ops.reset_adapter = qla2x00_reset_adapter;
ha->isp_ops.nvram_config = qla2x00_nvram_config;
ha->isp_ops.update_fw_options = qla2x00_update_fw_options;
ha->isp_ops.load_risc = qla2x00_load_risc;
ha->isp_ops.pci_info_str = qla2x00_pci_info_str;
ha->isp_ops.fw_version_str = qla2x00_fw_version_str;
ha->isp_ops.intr_handler = qla2100_intr_handler;
ha->isp_ops.enable_intrs = qla2x00_enable_intrs;
ha->isp_ops.disable_intrs = qla2x00_disable_intrs;
ha->isp_ops.abort_command = qla2x00_abort_command;
ha->isp_ops.abort_target = qla2x00_abort_target;
ha->isp_ops.fabric_login = qla2x00_login_fabric;
ha->isp_ops.fabric_logout = qla2x00_fabric_logout;
ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32;
ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32;
ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb;
ha->isp_ops.read_nvram = qla2x00_read_nvram_data;
ha->isp_ops.write_nvram = qla2x00_write_nvram_data;
ha->isp_ops.fw_dump = qla2100_fw_dump;
ha->isp_ops.ascii_fw_dump = qla2100_ascii_fw_dump;
if (IS_QLA2100(ha)) {
host->max_id = MAX_TARGETS_2100;
ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
@ -1147,18 +1349,57 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->response_q_length = RESPONSE_ENTRY_CNT_2100;
ha->last_loop_id = SNS_LAST_LOOP_ID_2100;
host->sg_tablesize = 32;
ha->gid_list_info_size = 4;
} else if (IS_QLA2200(ha)) {
host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
ha->request_q_length = REQUEST_ENTRY_CNT_2200;
ha->response_q_length = RESPONSE_ENTRY_CNT_2100;
ha->last_loop_id = SNS_LAST_LOOP_ID_2100;
} else /*if (IS_QLA2300(ha))*/ {
ha->gid_list_info_size = 4;
} else if (IS_QLA23XX(ha)) {
host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
ha->request_q_length = REQUEST_ENTRY_CNT_2200;
ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
ha->isp_ops.pci_config = qla2300_pci_config;
ha->isp_ops.intr_handler = qla2300_intr_handler;
ha->isp_ops.fw_dump = qla2300_fw_dump;
ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump;
ha->gid_list_info_size = 6;
} else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
ha->init_cb_size = sizeof(struct init_cb_24xx);
ha->isp_ops.pci_config = qla24xx_pci_config;
ha->isp_ops.reset_chip = qla24xx_reset_chip;
ha->isp_ops.chip_diag = qla24xx_chip_diag;
ha->isp_ops.config_rings = qla24xx_config_rings;
ha->isp_ops.reset_adapter = qla24xx_reset_adapter;
ha->isp_ops.nvram_config = qla24xx_nvram_config;
ha->isp_ops.update_fw_options = qla24xx_update_fw_options;
ha->isp_ops.load_risc = qla24xx_load_risc_flash;
if (ql2xfwloadbin)
ha->isp_ops.load_risc = qla24xx_load_risc_hotplug;
ha->isp_ops.pci_info_str = qla24xx_pci_info_str;
ha->isp_ops.fw_version_str = qla24xx_fw_version_str;
ha->isp_ops.intr_handler = qla24xx_intr_handler;
ha->isp_ops.enable_intrs = qla24xx_enable_intrs;
ha->isp_ops.disable_intrs = qla24xx_disable_intrs;
ha->isp_ops.abort_command = qla24xx_abort_command;
ha->isp_ops.abort_target = qla24xx_abort_target;
ha->isp_ops.fabric_login = qla24xx_login_fabric;
ha->isp_ops.fabric_logout = qla24xx_fabric_logout;
ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb;
ha->isp_ops.read_nvram = qla24xx_read_nvram_data;
ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
ha->isp_ops.fw_dump = qla24xx_fw_dump;
ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump;
ha->gid_list_info_size = 8;
}
host->can_queue = ha->request_q_length + 128;
@ -1229,18 +1470,15 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
host->max_lun = MAX_LUNS;
host->transportt = qla2xxx_transport_template;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
ret = request_irq(host->irq, qla2100_intr_handler,
SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
else
ret = request_irq(host->irq, qla2300_intr_handler,
ret = request_irq(pdev->irq, ha->isp_ops.intr_handler,
SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
if (ret) {
qla_printk(KERN_WARNING, ha,
"Failed to reserve interrupt %d already in use.\n",
host->irq);
pdev->irq);
goto probe_failed;
}
host->irq = pdev->irq;
/* Initialized the timer */
qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL);
@ -1248,30 +1486,33 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
ha->host_no, ha));
reg = ha->iobase;
ha->isp_ops.disable_intrs(ha);
/* Disable ISP interrupts. */
qla2x00_disable_intrs(ha);
/* Ensure mailbox registers are free. */
spin_lock_irqsave(&ha->hardware_lock, flags);
WRT_REG_WORD(&reg->semaphore, 0);
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
WRT_REG_WORD(&reg->hccr, HCCR_CLR_HOST_INT);
reg = ha->iobase;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
} else {
WRT_REG_WORD(&reg->isp.semaphore, 0);
WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);
WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);
/* Enable proper parity */
if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) {
if (IS_QLA2300(ha))
/* SRAM parity */
WRT_REG_WORD(&reg->hccr, (HCCR_ENABLE_PARITY + 0x1));
WRT_REG_WORD(&reg->isp.hccr,
(HCCR_ENABLE_PARITY + 0x1));
else
/* SRAM, Instruction RAM and GP RAM parity */
WRT_REG_WORD(&reg->hccr, (HCCR_ENABLE_PARITY + 0x7));
WRT_REG_WORD(&reg->isp.hccr,
(HCCR_ENABLE_PARITY + 0x7));
}
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Enable chip interrupts. */
qla2x00_enable_intrs(ha);
ha->isp_ops.enable_intrs(ha);
/* v2.19.5b6 */
/*
@ -1306,9 +1547,9 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
" QLogic %s - %s\n"
" %s: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str,
ha->model_number, ha->model_desc ? ha->model_desc: "",
ha->brd_info->isp_name, qla2x00_get_pci_info_str(ha, pci_info),
pci_name(ha->pdev), ha->flags.enable_64bit_addressing ? '+': '-',
ha->host_no, qla2x00_get_fw_version_str(ha, fw_str));
ha->brd_info->isp_name, ha->isp_ops.pci_info_str(ha, pci_info),
pci_name(pdev), ha->flags.enable_64bit_addressing ? '+': '-',
ha->host_no, ha->isp_ops.fw_version_str(ha, fw_str));
/* Go with fc_rport registration. */
list_for_each_entry(fcport, &ha->fcports, list)
@ -1362,7 +1603,7 @@ qla2x00_free_device(scsi_qla_host_t *ha)
/* turn-off interrupts on the card */
if (ha->interrupts_on)
qla2x00_disable_intrs(ha);
ha->isp_ops.disable_intrs(ha);
/* Disable timer */
if (ha->timer_active)
@ -1576,7 +1817,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
continue;
}
memset(ha->init_cb, 0, sizeof(init_cb_t));
memset(ha->init_cb, 0, ha->init_cb_size);
/* Get consistent memory allocated for Get Port Database cmd */
ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
@ -1788,10 +2029,13 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
if (ha->fw_dump)
free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order);
if (ha->fw_dump_buffer)
vfree(ha->fw_dump24);
vfree(ha->fw_dump_buffer);
ha->fw_dump = NULL;
ha->fw_dump24 = NULL;
ha->fw_dumped = 0;
ha->fw_dump_reading = 0;
ha->fw_dump_buffer = NULL;
}
@ -1951,9 +2195,11 @@ qla2x00_do_dpc(void *data)
if (fcport->flags & FCF_FABRIC_DEVICE) {
if (fcport->flags &
FCF_TAPE_PRESENT)
qla2x00_fabric_logout(
ha,
fcport->loop_id);
ha->isp_ops.fabric_logout(
ha, fcport->loop_id,
fcport->d_id.b.domain,
fcport->d_id.b.area,
fcport->d_id.b.al_pa);
status = qla2x00_fabric_login(
ha, fcport, &next_loopid);
} else
@ -2034,7 +2280,7 @@ qla2x00_do_dpc(void *data)
}
if (!ha->interrupts_on)
qla2x00_enable_intrs(ha);
ha->isp_ops.enable_intrs(ha);
ha->dpc_active = 0;
} /* End of while(1) */
@ -2076,25 +2322,6 @@ qla2x00_rst_aen(scsi_qla_host_t *ha)
}
}
/*
* This routine will allocate SP from the free queue
* input:
* scsi_qla_host_t *
* output:
* srb_t * or NULL
*/
static srb_t *
qla2x00_get_new_sp(scsi_qla_host_t *ha)
{
srb_t *sp;
sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
if (sp)
atomic_set(&sp->ref_count, 1);
return (sp);
}
static void
qla2x00_sp_free_dma(scsi_qla_host_t *ha, srb_t *sp)
{
@ -2110,6 +2337,7 @@ qla2x00_sp_free_dma(scsi_qla_host_t *ha, srb_t *sp)
}
sp->flags &= ~SRB_DMA_VALID;
}
CMD_SP(cmd) = NULL;
}
void
@ -2119,7 +2347,6 @@ qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *sp)
qla2x00_sp_free_dma(ha, sp);
CMD_SP(cmd) = NULL;
mempool_free(sp, ha->srb_mempool);
cmd->scsi_done(cmd);
@ -2164,7 +2391,7 @@ qla2x00_timer(scsi_qla_host_t *ha)
atomic_set(&fcport->state, FCS_DEVICE_DEAD);
DEBUG(printk("scsi(%ld): fcport-%d - port retry count: "
"%d remainning\n",
"%d remaining\n",
ha->host_no,
t, atomic_read(&fcport->port_down_timer)));
}
@ -2227,7 +2454,7 @@ qla2x00_timer(scsi_qla_host_t *ha)
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
}
}
DEBUG3(printk("scsi(%ld): Loop Down - seconds remainning %d\n",
DEBUG3(printk("scsi(%ld): Loop Down - seconds remaining %d\n",
ha->host_no,
atomic_read(&ha->loop_down_timer)));
}
@ -2264,12 +2491,68 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
return -ETIMEDOUT;
}
static struct qla_board_info qla_board_tbl[] = {
{
.drv_name = "qla2400",
.isp_name = "ISP2422",
.fw_fname = "ql2400_fw.bin",
.sht = &qla24xx_driver_template,
},
{
.drv_name = "qla2400",
.isp_name = "ISP2432",
.fw_fname = "ql2400_fw.bin",
.sht = &qla24xx_driver_template,
},
};
static struct pci_device_id qla2xxx_pci_tbl[] = {
{
.vendor = PCI_VENDOR_ID_QLOGIC,
.device = PCI_DEVICE_ID_QLOGIC_ISP2422,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[0],
},
{
.vendor = PCI_VENDOR_ID_QLOGIC,
.device = PCI_DEVICE_ID_QLOGIC_ISP2432,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long)&qla_board_tbl[1],
},
{0, 0},
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
static int __devinit
qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
return qla2x00_probe_one(pdev,
(struct qla_board_info *)id->driver_data);
}
static void __devexit
qla2xxx_remove_one(struct pci_dev *pdev)
{
qla2x00_remove_one(pdev);
}
static struct pci_driver qla2xxx_pci_driver = {
.name = "qla2xxx",
.id_table = qla2xxx_pci_tbl,
.probe = qla2xxx_probe_one,
.remove = __devexit_p(qla2xxx_remove_one),
};
/**
* qla2x00_module_init - Module initialization.
**/
static int __init
qla2x00_module_init(void)
{
int ret = 0;
/* Allocate cache for SRBs. */
srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
@ -2290,7 +2573,12 @@ qla2x00_module_init(void)
return -ENODEV;
printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
return 0;
ret = pci_module_init(&qla2xxx_pci_driver);
if (ret) {
kmem_cache_destroy(srb_cachep);
fc_release_transport(qla2xxx_transport_template);
}
return ret;
}
/**
@ -2299,6 +2587,7 @@ qla2x00_module_init(void)
static void __exit
qla2x00_module_exit(void)
{
pci_unregister_driver(&qla2xxx_pci_driver);
kmem_cache_destroy(srb_cachep);
fc_release_transport(qla2xxx_transport_template);
}

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -348,7 +348,7 @@ static inline struct mbx_entry *
qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle)
{
uint16_t cnt;
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
struct mbx_entry *mbxentry;
mbxentry = NULL;

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -22,33 +22,8 @@
*/
#define DEBUG_QLA2100 0 /* For Debug of qla2x00 */
#define STOP_ON_RESET 0
#define USE_ABORT_TGT 1 /* Use Abort Target mbx cmd */
#define VSA 0 /* Volume Set Addressing */
/* Failover options */
#define MAX_RECOVERYTIME 10 /*
* Max suspend time for a lun recovery
* time
*/
#define MAX_FAILBACKTIME 5 /* Max suspend time before fail back */
#define QLA_CMD_TIMER_DELTA 3
/*
* When a lun is suspended for the "Not Ready" condition then it will suspend
* the lun for increments of 6 sec delays. SUSPEND_COUNT is that count.
*/
#define SUSPEND_COUNT 10 /* 6 secs * 10 retries = 60 secs */
/*
* Defines the time in seconds that the driver extends the command timeout to
* get around the problem where the mid-layer only allows 5 retries for
* commands that return BUS_BUSY
*/
#define EXTEND_CMD_TIMEOUT 60
#define MAX_RETRIES_OF_ISP_ABORT 5
/* Max time to wait for the loop to be in LOOP_READY state */

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -38,7 +38,7 @@ void
qla2x00_lock_nvram_access(scsi_qla_host_t *ha)
{
uint16_t data;
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
data = RD_REG_WORD(&reg->nvram);
@ -70,7 +70,7 @@ qla2x00_lock_nvram_access(scsi_qla_host_t *ha)
void
qla2x00_unlock_nvram_access(scsi_qla_host_t *ha)
{
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
WRT_REG_WORD(&reg->u.isp2300.host_semaphore, 0);
@ -78,56 +78,6 @@ qla2x00_unlock_nvram_access(scsi_qla_host_t *ha)
}
}
/**
* qla2x00_release_nvram_protection() -
* @ha: HA context
*/
void
qla2x00_release_nvram_protection(scsi_qla_host_t *ha)
{
device_reg_t __iomem *reg;
uint32_t word;
reg = ha->iobase;
/* Release NVRAM write protection. */
if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
/* Write enable. */
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_write(ha, 0);
qla2x00_nv_write(ha, 0);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_deselect(ha);
/* Enable protection register. */
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
qla2x00_nv_write(ha, NVR_PR_ENABLE);
qla2x00_nv_write(ha, NVR_PR_ENABLE);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
qla2x00_nv_deselect(ha);
/* Clear protection register (ffff is cleared). */
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
qla2x00_nv_deselect(ha);
/* Wait for NVRAM to become ready. */
WRT_REG_WORD(&reg->nvram, NVR_SELECT);
do {
NVRAM_DELAY();
word = RD_REG_WORD(&reg->nvram);
} while ((word & NVR_DATA_IN) == 0);
}
}
/**
* qla2x00_get_nvram_word() - Calculates word position in NVRAM and calls the
* request routine to get the word from NVRAM.
@ -161,7 +111,7 @@ qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data)
int count;
uint16_t word;
uint32_t nv_cmd;
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_write(ha, 0);
@ -204,6 +154,64 @@ qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data)
qla2x00_nv_deselect(ha);
}
static int
qla2x00_write_nvram_word_tmo(scsi_qla_host_t *ha, uint32_t addr, uint16_t data,
uint32_t tmo)
{
int ret, count;
uint16_t word;
uint32_t nv_cmd;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
ret = QLA_SUCCESS;
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_write(ha, 0);
qla2x00_nv_write(ha, 0);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_deselect(ha);
/* Write data */
nv_cmd = (addr << 16) | NV_WRITE_OP;
nv_cmd |= data;
nv_cmd <<= 5;
for (count = 0; count < 27; count++) {
if (nv_cmd & BIT_31)
qla2x00_nv_write(ha, NVR_DATA_OUT);
else
qla2x00_nv_write(ha, 0);
nv_cmd <<= 1;
}
qla2x00_nv_deselect(ha);
/* Wait for NVRAM to become ready */
WRT_REG_WORD(&reg->nvram, NVR_SELECT);
do {
NVRAM_DELAY();
word = RD_REG_WORD(&reg->nvram);
if (!--tmo) {
ret = QLA_FUNCTION_FAILED;
break;
}
} while ((word & NVR_DATA_IN) == 0);
qla2x00_nv_deselect(ha);
/* Disable writes */
qla2x00_nv_write(ha, NVR_DATA_OUT);
for (count = 0; count < 10; count++)
qla2x00_nv_write(ha, 0);
qla2x00_nv_deselect(ha);
return ret;
}
/**
* qla2x00_nvram_request() - Sends read command to NVRAM and gets data from
* NVRAM.
@ -223,7 +231,7 @@ static uint16_t
qla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd)
{
uint8_t cnt;
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint16_t data = 0;
uint16_t reg_data;
@ -265,7 +273,7 @@ qla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd)
static void
qla2x00_nv_deselect(scsi_qla_host_t *ha)
{
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
WRT_REG_WORD(&reg->nvram, NVR_DESELECT);
RD_REG_WORD(&reg->nvram); /* PCI Posting. */
@ -280,7 +288,7 @@ qla2x00_nv_deselect(scsi_qla_host_t *ha)
static void
qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data)
{
device_reg_t __iomem *reg = ha->iobase;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
WRT_REG_WORD(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
RD_REG_WORD(&reg->nvram); /* PCI Posting. */
@ -294,3 +302,435 @@ qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data)
NVRAM_DELAY();
}
/**
* qla2x00_clear_nvram_protection() -
* @ha: HA context
*/
static int
qla2x00_clear_nvram_protection(scsi_qla_host_t *ha)
{
int ret, stat;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint32_t word;
uint16_t wprot, wprot_old;
/* Clear NVRAM write protection. */
ret = QLA_FUNCTION_FAILED;
wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, 0));
stat = qla2x00_write_nvram_word_tmo(ha, 0,
__constant_cpu_to_le16(0x1234), 100000);
wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, 0));
if (stat != QLA_SUCCESS || wprot != __constant_cpu_to_le16(0x1234)) {
/* Write enable. */
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_write(ha, 0);
qla2x00_nv_write(ha, 0);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_deselect(ha);
/* Enable protection register. */
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
qla2x00_nv_write(ha, NVR_PR_ENABLE);
qla2x00_nv_write(ha, NVR_PR_ENABLE);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
qla2x00_nv_deselect(ha);
/* Clear protection register (ffff is cleared). */
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
qla2x00_nv_deselect(ha);
/* Wait for NVRAM to become ready. */
WRT_REG_WORD(&reg->nvram, NVR_SELECT);
do {
NVRAM_DELAY();
word = RD_REG_WORD(&reg->nvram);
} while ((word & NVR_DATA_IN) == 0);
ret = QLA_SUCCESS;
} else
qla2x00_write_nvram_word(ha, 0, wprot_old);
return ret;
}
static void
qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat)
{
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint32_t word;
if (stat != QLA_SUCCESS)
return;
/* Set NVRAM write protection. */
/* Write enable. */
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_write(ha, 0);
qla2x00_nv_write(ha, 0);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_deselect(ha);
/* Enable protection register. */
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
qla2x00_nv_write(ha, NVR_PR_ENABLE);
qla2x00_nv_write(ha, NVR_PR_ENABLE);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
qla2x00_nv_deselect(ha);
/* Enable protection register. */
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
qla2x00_nv_write(ha, NVR_PR_ENABLE);
qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
for (word = 0; word < 8; word++)
qla2x00_nv_write(ha, NVR_PR_ENABLE);
qla2x00_nv_deselect(ha);
/* Wait for NVRAM to become ready. */
WRT_REG_WORD(&reg->nvram, NVR_SELECT);
do {
NVRAM_DELAY();
word = RD_REG_WORD(&reg->nvram);
} while ((word & NVR_DATA_IN) == 0);
}
/*****************************************************************************/
/* Flash Manipulation Routines */
/*****************************************************************************/
static inline uint32_t
flash_conf_to_access_addr(uint32_t faddr)
{
return FARX_ACCESS_FLASH_CONF | faddr;
}
static inline uint32_t
flash_data_to_access_addr(uint32_t faddr)
{
return FARX_ACCESS_FLASH_DATA | faddr;
}
static inline uint32_t
nvram_conf_to_access_addr(uint32_t naddr)
{
return FARX_ACCESS_NVRAM_CONF | naddr;
}
static inline uint32_t
nvram_data_to_access_addr(uint32_t naddr)
{
return FARX_ACCESS_NVRAM_DATA | naddr;
}
uint32_t
qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr)
{
int rval;
uint32_t cnt, data;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
WRT_REG_DWORD(&reg->flash_addr, addr & ~FARX_DATA_FLAG);
/* Wait for READ cycle to complete. */
rval = QLA_SUCCESS;
for (cnt = 3000;
(RD_REG_DWORD(&reg->flash_addr) & FARX_DATA_FLAG) == 0 &&
rval == QLA_SUCCESS; cnt--) {
if (cnt)
udelay(10);
else
rval = QLA_FUNCTION_TIMEOUT;
}
/* TODO: What happens if we time out? */
data = 0xDEADDEAD;
if (rval == QLA_SUCCESS)
data = RD_REG_DWORD(&reg->flash_data);
return data;
}
uint32_t *
qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
uint32_t dwords)
{
uint32_t i;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
/* Pause RISC. */
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
/* Dword reads to flash. */
for (i = 0; i < dwords; i++, faddr++)
dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
flash_data_to_access_addr(faddr)));
/* Release RISC pause. */
WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
return dwptr;
}
int
qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data)
{
int rval;
uint32_t cnt;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
WRT_REG_DWORD(&reg->flash_data, data);
RD_REG_DWORD(&reg->flash_data); /* PCI Posting. */
WRT_REG_DWORD(&reg->flash_addr, addr | FARX_DATA_FLAG);
/* Wait for Write cycle to complete. */
rval = QLA_SUCCESS;
for (cnt = 500000; (RD_REG_DWORD(&reg->flash_addr) & FARX_DATA_FLAG) &&
rval == QLA_SUCCESS; cnt--) {
if (cnt)
udelay(10);
else
rval = QLA_FUNCTION_TIMEOUT;
}
return rval;
}
void
qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
uint8_t *flash_id)
{
uint32_t ids;
ids = qla24xx_read_flash_dword(ha, flash_data_to_access_addr(0xd03ab));
*man_id = LSB(ids);
*flash_id = MSB(ids);
}
int
qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
uint32_t dwords)
{
int ret;
uint32_t liter;
uint32_t sec_mask, rest_addr, conf_addr;
uint32_t fdata;
uint8_t man_id, flash_id;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
ret = QLA_SUCCESS;
/* Pause RISC. */
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
ha->host_no, man_id, flash_id));
conf_addr = flash_conf_to_access_addr(0x03d8);
switch (man_id) {
case 0xbf: /* STT flash. */
rest_addr = 0x1fff;
sec_mask = 0x3e000;
if (flash_id == 0x80)
conf_addr = flash_conf_to_access_addr(0x0352);
break;
case 0x13: /* ST M25P80. */
rest_addr = 0x3fff;
sec_mask = 0x3c000;
break;
default:
/* Default to 64 kb sector size. */
rest_addr = 0x3fff;
sec_mask = 0x3c000;
break;
}
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
/* Disable flash write-protection. */
qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
do { /* Loop once to provide quick error exit. */
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
/* Are we at the beginning of a sector? */
if ((faddr & rest_addr) == 0) {
fdata = (faddr & sec_mask) << 2;
ret = qla24xx_write_flash_dword(ha, conf_addr,
(fdata & 0xff00) |((fdata << 16) &
0xff0000) | ((fdata >> 16) & 0xff));
if (ret != QLA_SUCCESS) {
DEBUG9(printk("%s(%ld) Unable to flash "
"sector: address=%x.\n", __func__,
ha->host_no, faddr));
break;
}
}
ret = qla24xx_write_flash_dword(ha,
flash_data_to_access_addr(faddr),
cpu_to_le32(*dwptr));
if (ret != QLA_SUCCESS) {
DEBUG9(printk("%s(%ld) Unable to program flash "
"address=%x data=%x.\n", __func__,
ha->host_no, faddr, *dwptr));
break;
}
}
} while (0);
/* Disable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
/* Release RISC pause. */
WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
return ret;
}
uint8_t *
qla2x00_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t bytes)
{
uint32_t i;
uint16_t *wptr;
/* Word reads to NVRAM via registers. */
wptr = (uint16_t *)buf;
qla2x00_lock_nvram_access(ha);
for (i = 0; i < bytes >> 1; i++, naddr++)
wptr[i] = cpu_to_le16(qla2x00_get_nvram_word(ha,
naddr));
qla2x00_unlock_nvram_access(ha);
return buf;
}
uint8_t *
qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t bytes)
{
uint32_t i;
uint32_t *dwptr;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
/* Pause RISC. */
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
/* Dword reads to flash. */
dwptr = (uint32_t *)buf;
for (i = 0; i < bytes >> 2; i++, naddr++)
dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
nvram_data_to_access_addr(naddr)));
/* Release RISC pause. */
WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
return buf;
}
int
qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t bytes)
{
int ret, stat;
uint32_t i;
uint16_t *wptr;
ret = QLA_SUCCESS;
qla2x00_lock_nvram_access(ha);
/* Disable NVRAM write-protection. */
stat = qla2x00_clear_nvram_protection(ha);
wptr = (uint16_t *)buf;
for (i = 0; i < bytes >> 1; i++, naddr++) {
qla2x00_write_nvram_word(ha, naddr,
cpu_to_le16(*wptr));
wptr++;
}
/* Enable NVRAM write-protection. */
qla2x00_set_nvram_protection(ha, stat);
qla2x00_unlock_nvram_access(ha);
return ret;
}
int
qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t bytes)
{
int ret;
uint32_t i;
uint32_t *dwptr;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
ret = QLA_SUCCESS;
/* Pause RISC. */
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
/* Disable NVRAM write-protection. */
qla24xx_write_flash_dword(ha, nvram_conf_to_access_addr(0x101),
0);
qla24xx_write_flash_dword(ha, nvram_conf_to_access_addr(0x101),
0);
/* Dword writes to flash. */
dwptr = (uint32_t *)buf;
for (i = 0; i < bytes >> 2; i++, naddr++, dwptr++) {
ret = qla24xx_write_flash_dword(ha,
nvram_data_to_access_addr(naddr),
cpu_to_le32(*dwptr));
if (ret != QLA_SUCCESS) {
DEBUG9(printk("%s(%ld) Unable to program "
"nvram address=%x data=%x.\n", __func__,
ha->host_no, naddr, *dwptr));
break;
}
}
/* Enable NVRAM write-protection. */
qla24xx_write_flash_dword(ha, nvram_conf_to_access_addr(0x101),
0x8c);
/* Disable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
/* Release RISC pause. */
WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
return ret;
}

View file

@ -2,7 +2,7 @@
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* Copyright (C) 2003-2005 QLogic Corporation
* (www.qlogic.com)
*
* This program is free software; you can redistribute it and/or modify it
@ -19,9 +19,9 @@
/*
* Driver version
*/
#define QLA2XXX_VERSION "8.00.02b5-k"
#define QLA2XXX_VERSION "8.01.00b5-k"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 0
#define QLA_DRIVER_PATCH_VER 2
#define QLA_DRIVER_MINOR_VER 1
#define QLA_DRIVER_PATCH_VER 0
#define QLA_DRIVER_BETA_VER 5

View file

@ -746,7 +746,6 @@ static int isp2x00_detect(Scsi_Host_Template * tmpt)
printk("qlogicfc%d : could not register host.\n", hosts);
continue;
}
scsi_set_device(host, &pdev->dev);
host->max_id = QLOGICFC_MAX_ID + 1;
host->max_lun = QLOGICFC_MAX_LUN;
hostdata = (struct isp2x00_hostdata *) host->hostdata;

View file

@ -694,7 +694,6 @@ static int isp1020_detect(Scsi_Host_Template *tmpt)
memset(hostdata, 0, sizeof(struct isp1020_hostdata));
hostdata->pci_dev = pdev;
scsi_set_device(host, &pdev->dev);
if (isp1020_init(host))
goto fail_and_unregister;

View file

@ -113,6 +113,7 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = {
"Unknown ",
"RAID ",
"Enclosure ",
"Direct-Access-RBC",
};
EXPORT_SYMBOL(scsi_device_types);
@ -259,8 +260,6 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
memset(cmd, 0, sizeof(*cmd));
cmd->device = dev;
cmd->state = SCSI_STATE_UNUSED;
cmd->owner = SCSI_OWNER_NOBODY;
init_timer(&cmd->eh_timeout);
INIT_LIST_HEAD(&cmd->list);
spin_lock_irqsave(&dev->list_lock, flags);
@ -610,10 +609,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
* We will use a queued command if possible, otherwise we will
* emulate the queuing and calling of completion function ourselves.
*/
cmd->state = SCSI_STATE_QUEUED;
cmd->owner = SCSI_OWNER_LOWLEVEL;
atomic_inc(&cmd->device->iorequest_cnt);
/*
@ -683,7 +678,6 @@ void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq)
{
sreq->sr_command = cmd;
cmd->owner = SCSI_OWNER_MIDLEVEL;
cmd->cmd_len = sreq->sr_cmd_len;
cmd->use_sg = sreq->sr_use_sg;
@ -719,7 +713,6 @@ void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq)
/*
* Start the timer ticking.
*/
cmd->abort_reason = 0;
cmd->result = 0;
SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_init_cmd_from_req()\n"));
@ -768,8 +761,6 @@ void __scsi_done(struct scsi_cmnd *cmd)
* Set the serial numbers back to zero
*/
cmd->serial_number = 0;
cmd->state = SCSI_STATE_BHQUEUE;
cmd->owner = SCSI_OWNER_BH_HANDLER;
atomic_inc(&cmd->device->iodone_cnt);
if (cmd->result)
@ -890,9 +881,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
SCSI_LOG_MLCOMPLETE(4, printk("Notifying upper driver of completion "
"for device %d %x\n", sdev->id, cmd->result));
cmd->owner = SCSI_OWNER_HIGHLEVEL;
cmd->state = SCSI_STATE_FINISHED;
/*
* We can get here with use_sg=0, causing a panic in the upper level
*/

View file

@ -73,12 +73,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
spin_lock_irqsave(shost->host_lock, flags);
scsi_eh_eflags_set(scmd, eh_flag);
/*
* FIXME: Can we stop setting owner and state.
*/
scmd->owner = SCSI_OWNER_ERROR_HANDLER;
scmd->state = SCSI_STATE_FAILED;
scmd->eh_eflags |= eh_flag;
list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
set_bit(SHOST_RECOVERY, &shost->shost_state);
shost->host_failed++;
@ -233,8 +228,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
list_for_each_entry(scmd, work_q, eh_entry) {
if (scmd->device == sdev) {
++total_failures;
if (scsi_eh_eflags_chk(scmd,
SCSI_EH_CANCEL_CMD))
if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD)
++cmd_cancel;
else
++cmd_failed;
@ -430,7 +424,7 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
**/
static void scsi_eh_times_out(struct scsi_cmnd *scmd)
{
scsi_eh_eflags_set(scmd, SCSI_EH_REC_TIMEOUT);
scmd->eh_eflags |= SCSI_EH_REC_TIMEOUT;
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd:%p\n", __FUNCTION__,
scmd));
@ -451,7 +445,6 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
*/
if (del_timer(&scmd->eh_timeout)) {
scmd->request->rq_status = RQ_SCSI_DONE;
scmd->owner = SCSI_OWNER_ERROR_HANDLER;
SCSI_LOG_ERROR_RECOVERY(3, printk("%s scmd: %p result: %x\n",
__FUNCTION__, scmd, scmd->result));
@ -484,8 +477,6 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
* we will use a queued command if possible, otherwise we will
* emulate the queuing and calling of completion function ourselves.
*/
scmd->owner = SCSI_OWNER_LOWLEVEL;
if (sdev->scsi_level <= SCSI_2)
scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
(sdev->lun << 5 & 0xe0);
@ -512,9 +503,8 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
* see if timeout. if so, tell the host to forget about it.
* in other words, we don't want a callback any more.
*/
if (scsi_eh_eflags_chk(scmd, SCSI_EH_REC_TIMEOUT)) {
scsi_eh_eflags_clr(scmd, SCSI_EH_REC_TIMEOUT);
scmd->owner = SCSI_OWNER_LOWLEVEL;
if (scmd->eh_eflags & SCSI_EH_REC_TIMEOUT) {
scmd->eh_eflags &= ~SCSI_EH_REC_TIMEOUT;
/*
* as far as the low level driver is
@ -530,8 +520,6 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
shost->hostt->eh_abort_handler(scmd);
scmd->request->rq_status = RQ_SCSI_DONE;
scmd->owner = SCSI_OWNER_ERROR_HANDLER;
rtn = FAILED;
}
@ -641,9 +629,7 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
struct list_head *done_q)
{
scmd->device->host->host_failed--;
scmd->state = SCSI_STATE_BHQUEUE;
scsi_eh_eflags_clr_all(scmd);
scmd->eh_eflags = 0;
/*
* set this back so that the upper level can correctly free up
@ -676,13 +662,11 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
static int scsi_eh_get_sense(struct list_head *work_q,
struct list_head *done_q)
{
struct list_head *lh, *lh_sf;
struct scsi_cmnd *scmd;
struct scsi_cmnd *scmd, *next;
int rtn;
list_for_each_safe(lh, lh_sf, work_q) {
scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
if (scsi_eh_eflags_chk(scmd, SCSI_EH_CANCEL_CMD) ||
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) ||
SCSI_SENSE_VALID(scmd))
continue;
@ -742,9 +726,6 @@ static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
*/
if (scmd->serial_number == 0)
return SUCCESS;
scmd->owner = SCSI_OWNER_LOWLEVEL;
return scmd->device->host->hostt->eh_abort_handler(scmd);
}
@ -815,20 +796,18 @@ retry_tur:
static int scsi_eh_abort_cmds(struct list_head *work_q,
struct list_head *done_q)
{
struct list_head *lh, *lh_sf;
struct scsi_cmnd *scmd;
struct scsi_cmnd *scmd, *next;
int rtn;
list_for_each_safe(lh, lh_sf, work_q) {
scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
if (!scsi_eh_eflags_chk(scmd, SCSI_EH_CANCEL_CMD))
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD))
continue;
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:"
"0x%p\n", current->comm,
scmd));
rtn = scsi_try_to_abort_cmd(scmd);
if (rtn == SUCCESS) {
scsi_eh_eflags_clr(scmd, SCSI_EH_CANCEL_CMD);
scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
if (!scsi_device_online(scmd->device) ||
!scsi_eh_tur(scmd)) {
scsi_eh_finish_cmd(scmd, done_q);
@ -862,10 +841,7 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
if (!scmd->device->host->hostt->eh_device_reset_handler)
return FAILED;
scmd->owner = SCSI_OWNER_LOWLEVEL;
rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
if (rtn == SUCCESS) {
scmd->device->was_reset = 1;
scmd->device->expecting_cc_ua = 1;
@ -938,8 +914,7 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
struct list_head *work_q,
struct list_head *done_q)
{
struct list_head *lh, *lh_sf;
struct scsi_cmnd *scmd, *stu_scmd;
struct scsi_cmnd *scmd, *stu_scmd, *next;
struct scsi_device *sdev;
shost_for_each_device(sdev, shost) {
@ -960,8 +935,8 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
if (!scsi_eh_try_stu(stu_scmd)) {
if (!scsi_device_online(sdev) ||
!scsi_eh_tur(stu_scmd)) {
list_for_each_safe(lh, lh_sf, work_q) {
scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
list_for_each_entry_safe(scmd, next,
work_q, eh_entry) {
if (scmd->device == sdev)
scsi_eh_finish_cmd(scmd, done_q);
}
@ -992,8 +967,7 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
struct list_head *work_q,
struct list_head *done_q)
{
struct list_head *lh, *lh_sf;
struct scsi_cmnd *scmd, *bdr_scmd;
struct scsi_cmnd *scmd, *bdr_scmd, *next;
struct scsi_device *sdev;
int rtn;
@ -1015,11 +989,8 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
if (rtn == SUCCESS) {
if (!scsi_device_online(sdev) ||
!scsi_eh_tur(bdr_scmd)) {
list_for_each_safe(lh, lh_sf,
work_q) {
scmd = list_entry(lh, struct
scsi_cmnd,
eh_entry);
list_for_each_entry_safe(scmd, next,
work_q, eh_entry) {
if (scmd->device == sdev)
scsi_eh_finish_cmd(scmd,
done_q);
@ -1048,7 +1019,6 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
__FUNCTION__));
scmd->owner = SCSI_OWNER_LOWLEVEL;
if (!scmd->device->host->hostt->eh_bus_reset_handler)
return FAILED;
@ -1077,7 +1047,6 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
__FUNCTION__));
scmd->owner = SCSI_OWNER_LOWLEVEL;
if (!scmd->device->host->hostt->eh_host_reset_handler)
return FAILED;
@ -1104,9 +1073,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
struct list_head *work_q,
struct list_head *done_q)
{
struct list_head *lh, *lh_sf;
struct scsi_cmnd *scmd;
struct scsi_cmnd *chan_scmd;
struct scsi_cmnd *scmd, *chan_scmd, *next;
unsigned int channel;
int rtn;
@ -1137,9 +1104,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
channel));
rtn = scsi_try_bus_reset(chan_scmd);
if (rtn == SUCCESS) {
list_for_each_safe(lh, lh_sf, work_q) {
scmd = list_entry(lh, struct scsi_cmnd,
eh_entry);
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
if (channel == scmd->device->channel)
if (!scsi_device_online(scmd->device) ||
!scsi_eh_tur(scmd))
@ -1164,9 +1129,8 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
static int scsi_eh_host_reset(struct list_head *work_q,
struct list_head *done_q)
{
struct scsi_cmnd *scmd, *next;
int rtn;
struct list_head *lh, *lh_sf;
struct scsi_cmnd *scmd;
if (!list_empty(work_q)) {
scmd = list_entry(work_q->next,
@ -1177,8 +1141,7 @@ static int scsi_eh_host_reset(struct list_head *work_q,
rtn = scsi_try_host_reset(scmd);
if (rtn == SUCCESS) {
list_for_each_safe(lh, lh_sf, work_q) {
scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
if (!scsi_device_online(scmd->device) ||
(!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) ||
!scsi_eh_tur(scmd))
@ -1202,11 +1165,9 @@ static int scsi_eh_host_reset(struct list_head *work_q,
static void scsi_eh_offline_sdevs(struct list_head *work_q,
struct list_head *done_q)
{
struct list_head *lh, *lh_sf;
struct scsi_cmnd *scmd;
struct scsi_cmnd *scmd, *next;
list_for_each_safe(lh, lh_sf, work_q) {
scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
printk(KERN_INFO "scsi: Device offlined - not"
" ready after error recovery: host"
" %d channel %d id %d lun %d\n",
@ -1215,7 +1176,7 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q,
scmd->device->id,
scmd->device->lun);
scsi_device_set_state(scmd->device, SDEV_OFFLINE);
if (scsi_eh_eflags_chk(scmd, SCSI_EH_CANCEL_CMD)) {
if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) {
/*
* FIXME: Handle lost cmds.
*/
@ -1534,12 +1495,10 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost,
**/
static void scsi_eh_flush_done_q(struct list_head *done_q)
{
struct list_head *lh, *lh_sf;
struct scsi_cmnd *scmd;
struct scsi_cmnd *scmd, *next;
list_for_each_safe(lh, lh_sf, done_q) {
scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
list_del_init(lh);
list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
list_del_init(&scmd->eh_entry);
if (scsi_device_online(scmd->device) &&
!blk_noretry_request(scmd->request) &&
(++scmd->retries < scmd->allowed)) {
@ -1818,8 +1777,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->request = &req;
memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
scmd->request->rq_status = RQ_SCSI_BUSY;
scmd->state = SCSI_STATE_INITIALIZING;
scmd->owner = SCSI_OWNER_MIDLEVEL;
memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
@ -1829,7 +1786,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->bufflen = 0;
scmd->request_buffer = NULL;
scmd->request_bufflen = 0;
scmd->abort_reason = DID_ABORT;
scmd->cmd_len = 0;

View file

@ -145,12 +145,6 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
else if (reason == SCSI_MLQUEUE_DEVICE_BUSY)
device->device_blocked = device->max_device_blocked;
/*
* Register the fact that we own the thing for now.
*/
cmd->state = SCSI_STATE_MLQUEUE;
cmd->owner = SCSI_OWNER_MIDLEVEL;
/*
* Decrement the counters, since these commands are no longer
* active on the host/device.
@ -299,9 +293,7 @@ EXPORT_SYMBOL(scsi_wait_req);
*/
static int scsi_init_cmd_errh(struct scsi_cmnd *cmd)
{
cmd->owner = SCSI_OWNER_MIDLEVEL;
cmd->serial_number = 0;
cmd->abort_reason = 0;
memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
@ -322,7 +314,6 @@ static int scsi_init_cmd_errh(struct scsi_cmnd *cmd)
memcpy(cmd->data_cmnd, cmd->cmnd, sizeof(cmd->cmnd));
cmd->buffer = cmd->request_buffer;
cmd->bufflen = cmd->request_bufflen;
cmd->abort_reason = 0;
return 1;
}
@ -623,8 +614,6 @@ static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, int gfp_mas
sgp = scsi_sg_pools + cmd->sglist_len;
sgl = mempool_alloc(sgp->pool, gfp_mask);
if (sgl)
memset(sgl, 0, sgp->size);
return sgl;
}

View file

@ -12,17 +12,6 @@ struct scsi_request;
struct Scsi_Host;
/*
* These are the values that the owner field can take.
* They are used as an indication of who the command belongs to.
*/
#define SCSI_OWNER_HIGHLEVEL 0x100
#define SCSI_OWNER_MIDLEVEL 0x101
#define SCSI_OWNER_LOWLEVEL 0x102
#define SCSI_OWNER_ERROR_HANDLER 0x103
#define SCSI_OWNER_BH_HANDLER 0x104
#define SCSI_OWNER_NOBODY 0x105
/*
* Magic values for certain scsi structs. Shouldn't ever be used.
*/
@ -32,15 +21,6 @@ struct Scsi_Host;
/*
* Scsi Error Handler Flags
*/
#define scsi_eh_eflags_chk(scp, flags) \
((scp)->eh_eflags & (flags))
#define scsi_eh_eflags_set(scp, flags) \
do { (scp)->eh_eflags |= (flags); } while(0)
#define scsi_eh_eflags_clr(scp, flags) \
do { (scp)->eh_eflags &= ~(flags); } while(0)
#define scsi_eh_eflags_clr_all(scp) \
(scp->eh_eflags = 0)
#define SCSI_EH_CANCEL_CMD 0x0001 /* Cancel this cmd */
#define SCSI_EH_REC_TIMEOUT 0x0002 /* EH retry timed out */

View file

@ -999,6 +999,38 @@ static int scsilun_to_int(struct scsi_lun *scsilun)
return lun;
}
/**
* int_to_scsilun: reverts an int into a scsi_lun
* @int: integer to be reverted
* @scsilun: struct scsi_lun to be set.
*
* Description:
* Reverts the functionality of the scsilun_to_int, which packed
* an 8-byte lun value into an int. This routine unpacks the int
* back into the lun value.
* Note: the scsilun_to_int() routine does not truly handle all
* 8bytes of the lun value. This functions restores only as much
* as was set by the routine.
*
* Notes:
* Given an integer : 0x0b030a04, this function returns a
* scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00
*
**/
void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
{
int i;
memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
for (i = 0; i < sizeof(lun); i += 2) {
scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
scsilun->scsi_lun[i+1] = lun & 0xFF;
lun = lun >> 16;
}
}
EXPORT_SYMBOL(int_to_scsilun);
/**
* scsi_report_lun_scan - Scan using SCSI REPORT LUN results
* @sdevscan: scan the host, channel, and id of this Scsi_Device

View file

@ -795,7 +795,8 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
}
/* test width */
if (i->f->set_width && spi_max_width(starget) && sdev->wdtr) {
if (i->f->set_width && spi_max_width(starget) &&
scsi_device_wide(sdev)) {
i->f->set_width(starget, 1);
if (spi_dv_device_compare_inquiry(sreq, buffer,
@ -811,14 +812,14 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
return;
/* device can't handle synchronous */
if (!sdev->ppr && !sdev->sdtr)
if (!scsi_device_sync(sdev) && !scsi_device_dt(sdev))
return;
/* see if the device has an echo buffer. If it does we can
* do the SPI pattern write tests */
len = 0;
if (sdev->ppr)
if (scsi_device_dt(sdev))
len = spi_dv_device_get_echo_buffer(sreq, buffer);
retry:
@ -828,8 +829,10 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
DV_SET(period, spi_min_period(starget));
/* try QAS requests; this should be harmless to set if the
* target supports it */
if (scsi_device_qas(sdev))
DV_SET(qas, 1);
/* Also try IU transfers */
if (scsi_device_ius(sdev))
DV_SET(iu, 1);
if (spi_min_period(starget) < 9) {
/* This u320 (or u640). Ignore the coupled parameters

View file

@ -373,9 +373,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
} else {
if (this_count > 0xff)
this_count = 0xff;
SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f);
SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff);
SCpnt->cmnd[3] = (unsigned char) block & 0xff;

Some files were not shown because too many files have changed in this diff Show more