提交 f61ea1b0 编写于 作者: L Linus Torvalds
Release Date : Fri Nov 11 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
Current Version : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
Older Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
1. Sorted out PCI IDs to remove megaraid support overlaps.
Based on the patch from Daniel, sorted out PCI IDs along with
charactor node name change from 'megadev' to 'megadev_legacy' to avoid
conflict.
---
Hopefully we'll be getting the build restriction zapped much sooner,
but we should also be thinking about totally removing the hardware
support overlap in the megaraid drivers.
This patch pencils in a date of Feb 06 for this, and performs some
printk abuse in hope that existing legacy users might pick up on what's
going on.
Signed-off-by: Daniel Drake <dsd@gentoo.org>
---
2. Fixed a issue: megaraid always fails to reset handler.
---
I found that the megaraid driver always fails to reset the
adapter with the following message:
megaraid: resetting the host...
megaraid mbox: reset sequence completed successfully
megaraid: fast sync command timed out
megaraid: reservation reset failed
when the "Cluster mode" of the adapter BIOS is enabled.
So, whenever the reset occurs, the adapter goes to
offline and just become unavailable.
Jun'ichi Nomura [mailto:jnomura@mtc.biglobe.ne.jp]
---
Release Date : Mon Mar 07 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
Current Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
Older Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
......
......@@ -150,7 +150,8 @@ scsi devices of which only the first 2 respond:
LLD mid level LLD
===-------------------=========--------------------===------
scsi_host_alloc() -->
scsi_add_host() --------+
scsi_add_host() ---->
scsi_scan_host() -------+
|
slave_alloc()
slave_configure() --> scsi_adjust_queue_depth()
......@@ -196,7 +197,7 @@ of the issues involved. See the section on reference counting below.
The hotplug concept may be extended to SCSI devices. Currently, when an
HBA is added, the scsi_add_host() function causes a scan for SCSI devices
HBA is added, the scsi_scan_host() function causes a scan for SCSI devices
attached to the HBA's SCSI transport. On newer SCSI transports the HBA
may become aware of a new SCSI device _after_ the scan has completed.
An LLD can use this sequence to make the mid level aware of a SCSI device:
......@@ -372,7 +373,7 @@ names all start with "scsi_".
Summary:
scsi_activate_tcq - turn on tag command queueing
scsi_add_device - creates new scsi device (lu) instance
scsi_add_host - perform sysfs registration and SCSI bus scan.
scsi_add_host - perform sysfs registration and set up transport class
scsi_adjust_queue_depth - change the queue depth on a SCSI device
scsi_assign_lock - replace default host_lock with given lock
scsi_bios_ptable - return copy of block device's partition table
......@@ -386,6 +387,7 @@ 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_scan_host - scan SCSI bus
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()]
......@@ -425,10 +427,10 @@ void scsi_activate_tcq(struct scsi_device *sdev, int depth)
* Might block: yes
*
* Notes: This call is usually performed internally during a scsi
* bus scan when an HBA is added (i.e. scsi_add_host()). So it
* bus scan when an HBA is added (i.e. scsi_scan_host()). So it
* should only be called if the HBA becomes aware of a new scsi
* device (lu) after scsi_add_host() has completed. If successful
* this call we lead to slave_alloc() and slave_configure() callbacks
* device (lu) after scsi_scan_host() has completed. If successful
* this call can lead to slave_alloc() and slave_configure() callbacks
* into the LLD.
*
* Defined in: drivers/scsi/scsi_scan.c
......@@ -439,7 +441,7 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
/**
* scsi_add_host - perform sysfs registration and SCSI bus scan.
* scsi_add_host - perform sysfs registration and set up transport class
* @shost: pointer to scsi host instance
* @dev: pointer to struct device of type scsi class
*
......@@ -448,7 +450,11 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
* Might block: no
*
* Notes: Only required in "hotplug initialization model" after a
* successful call to scsi_host_alloc().
* successful call to scsi_host_alloc(). This function does not
* scan the bus; this can be done by calling scsi_scan_host() or
* in some other transport-specific way. The LLD must set up
* the transport template before calling this function and may only
* access the transport class data after this function has been called.
*
* Defined in: drivers/scsi/hosts.c
**/
......@@ -559,7 +565,7 @@ void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
* area for the LLD's exclusive use.
* Both associated refcounting objects have their refcount set to 1.
* Full registration (in sysfs) and a bus scan are performed later when
* scsi_add_host() is called.
* scsi_add_host() and scsi_scan_host() are called.
*
* Defined in: drivers/scsi/hosts.c .
**/
......@@ -698,6 +704,19 @@ int scsi_remove_host(struct Scsi_Host *shost)
void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)
/**
* scsi_scan_host - scan SCSI bus
* @shost: a pointer to a scsi host instance
*
* Might block: yes
*
* Notes: Should be called after scsi_add_host()
*
* Defined in: drivers/scsi/scsi_scan.c
**/
void scsi_scan_host(struct Scsi_Host *shost)
/**
* scsi_track_queue_full - track successive QUEUE_FULL events on given
* device to determine if and when there is a need
......
......@@ -239,7 +239,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
q->backing_dev_info.state = 0;
q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
blk_queue_max_sectors(q, MAX_SECTORS);
blk_queue_max_sectors(q, SAFE_MAX_SECTORS);
blk_queue_hardsect_size(q, 512);
blk_queue_dma_alignment(q, 511);
blk_queue_congestion_threshold(q);
......@@ -555,7 +555,12 @@ void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors)
printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors);
}
q->max_sectors = q->max_hw_sectors = max_sectors;
if (BLK_DEF_MAX_SECTORS > max_sectors)
q->max_hw_sectors = q->max_sectors = max_sectors;
else {
q->max_sectors = BLK_DEF_MAX_SECTORS;
q->max_hw_sectors = max_sectors;
}
}
EXPORT_SYMBOL(blk_queue_max_sectors);
......@@ -657,8 +662,8 @@ EXPORT_SYMBOL(blk_queue_hardsect_size);
void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b)
{
/* zero is "infinity" */
t->max_sectors = t->max_hw_sectors =
min_not_zero(t->max_sectors,b->max_sectors);
t->max_sectors = min_not_zero(t->max_sectors,b->max_sectors);
t->max_hw_sectors = min_not_zero(t->max_hw_sectors,b->max_hw_sectors);
t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments);
t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments);
......@@ -1293,9 +1298,15 @@ static inline int ll_new_hw_segment(request_queue_t *q,
static int ll_back_merge_fn(request_queue_t *q, struct request *req,
struct bio *bio)
{
unsigned short max_sectors;
int len;
if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
if (unlikely(blk_pc_request(req)))
max_sectors = q->max_hw_sectors;
else
max_sectors = q->max_sectors;
if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
req->flags |= REQ_NOMERGE;
if (req == q->last_merge)
q->last_merge = NULL;
......@@ -1325,9 +1336,16 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req,
static int ll_front_merge_fn(request_queue_t *q, struct request *req,
struct bio *bio)
{
unsigned short max_sectors;
int len;
if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
if (unlikely(blk_pc_request(req)))
max_sectors = q->max_hw_sectors;
else
max_sectors = q->max_sectors;
if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
req->flags |= REQ_NOMERGE;
if (req == q->last_merge)
q->last_merge = NULL;
......@@ -2144,7 +2162,7 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
struct bio *bio;
int reading;
if (len > (q->max_sectors << 9))
if (len > (q->max_hw_sectors << 9))
return -EINVAL;
if (!len || !ubuf)
return -EINVAL;
......@@ -2259,7 +2277,7 @@ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
{
struct bio *bio;
if (len > (q->max_sectors << 9))
if (len > (q->max_hw_sectors << 9))
return -EINVAL;
if (!len || !kbuf)
return -EINVAL;
......@@ -2306,6 +2324,8 @@ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
generic_unplug_device(q);
}
EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
/**
* blk_execute_rq - insert a request into queue for execution
* @q: queue to insert the request in
......@@ -2444,7 +2464,7 @@ void disk_round_stats(struct gendisk *disk)
/*
* queue lock must be held
*/
static void __blk_put_request(request_queue_t *q, struct request *req)
void __blk_put_request(request_queue_t *q, struct request *req)
{
struct request_list *rl = req->rl;
......@@ -2473,6 +2493,8 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
}
}
EXPORT_SYMBOL_GPL(__blk_put_request);
void blk_put_request(struct request *req)
{
unsigned long flags;
......
......@@ -233,7 +233,7 @@ static int sg_io(struct file *file, request_queue_t *q,
if (verify_command(file, cmd))
return -EPERM;
if (hdr->dxfer_len > (q->max_sectors << 9))
if (hdr->dxfer_len > (q->max_hw_sectors << 9))
return -EIO;
if (hdr->dxfer_len)
......
......@@ -638,7 +638,7 @@ int dm_split_args(int *argc, char ***argvp, char *input)
static void check_for_valid_limits(struct io_restrictions *rs)
{
if (!rs->max_sectors)
rs->max_sectors = MAX_SECTORS;
rs->max_sectors = SAFE_MAX_SECTORS;
if (!rs->max_phys_segments)
rs->max_phys_segments = MAX_PHYS_SEGMENTS;
if (!rs->max_hw_segments)
......
......@@ -313,13 +313,13 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
if (ioc->bus_type == FC)
mpt_fc_log_info(ioc, log_info);
else if (ioc->bus_type == SCSI)
else if (ioc->bus_type == SPI)
mpt_sp_log_info(ioc, log_info);
else if (ioc->bus_type == SAS)
mpt_sas_log_info(ioc, log_info);
}
if (ioc_stat & MPI_IOCSTATUS_MASK) {
if (ioc->bus_type == SCSI &&
if (ioc->bus_type == SPI &&
cb_idx != mpt_stm_index &&
cb_idx != mpt_lan_index)
mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
......@@ -1376,7 +1376,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
ioc->prod_name = "LSI53C1030";
ioc->bus_type = SCSI;
ioc->bus_type = SPI;
/* 1030 Chip Fix. Disable Split transactions
* for PCIX. Set MOST bits to zero if Rev < C0( = 8).
*/
......@@ -1389,7 +1389,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
ioc->prod_name = "LSI53C1035";
ioc->bus_type = SCSI;
ioc->bus_type = SPI;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
ioc->prod_name = "LSISAS1064";
......@@ -3042,7 +3042,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
/* Clear the internal flash bad bit - autoincrementing register,
* so must do two writes.
*/
if (ioc->bus_type == SCSI) {
if (ioc->bus_type == SPI) {
/*
* 1030 and 1035 H/W errata, workaround to access
* the ClearFlashBadSignatureBit
......@@ -3152,7 +3152,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
int cnt,cntdn;
dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
if (ioc->bus_type == SCSI) {
if (ioc->bus_type == SPI) {
/* Always issue a Msg Unit Reset first. This will clear some
* SCSI bus hang conditions.
*/
......@@ -3580,7 +3580,7 @@ initChainBuffers(MPT_ADAPTER *ioc)
dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
ioc->name, numSGE, num_sge, num_chain));
if (ioc->bus_type == SCSI)
if (ioc->bus_type == SPI)
num_chain *= MPT_SCSI_CAN_QUEUE;
else
num_chain *= MPT_FC_CAN_QUEUE;
......
......@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
#define MPT_LINUX_VERSION_COMMON "3.03.04"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.04"
#define MPT_LINUX_VERSION_COMMON "3.03.05"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.05"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
......@@ -321,7 +321,7 @@ typedef struct _SYSIF_REGS
* Dynamic Multi-Pathing specific stuff...
*/
/* VirtDevice negoFlags field */
/* VirtTarget negoFlags field */
#define MPT_TARGET_NO_NEGO_WIDE 0x01
#define MPT_TARGET_NO_NEGO_SYNC 0x02
#define MPT_TARGET_NO_NEGO_QAS 0x04
......@@ -330,8 +330,7 @@ typedef struct _SYSIF_REGS
/*
* VirtDevice - FC LUN device or SCSI target device
*/
typedef struct _VirtDevice {
struct scsi_device *device;
typedef struct _VirtTarget {
u8 tflags;
u8 ioc_id;
u8 target_id;
......@@ -342,21 +341,18 @@ typedef struct _VirtDevice {
u8 negoFlags; /* bit field, see above */
u8 raidVolume; /* set, if RAID Volume */
u8 type; /* byte 0 of Inquiry data */
u8 cflags; /* controller flags */
u8 rsvd1raid;
u16 fc_phys_lun;
u16 fc_xlat_lun;
u32 num_luns;
u32 luns[8]; /* Max LUNs is 256 */
u8 pad[4];
u8 inq_data[8];
/* IEEE Registered Extended Identifier
obtained via INQUIRY VPD page 0x83 */
/* NOTE: Do not separate uniq_prepad and uniq_data
as they are treateed as a single entity in the code */
u8 uniq_prepad[8];
u8 uniq_data[20];
u8 pad2[4];
} VirtTarget;
typedef struct _VirtDevice {
VirtTarget *vtarget;
u8 ioc_id;
u8 bus_id;
u8 target_id;
u8 configured_lun;
u32 lun;
} VirtDevice;
/*
......@@ -903,7 +899,7 @@ typedef struct _MPT_LOCAL_REPLY {
typedef enum {
FC,
SCSI,
SPI,
SAS
} BUS_TYPE;
......@@ -912,7 +908,7 @@ typedef struct _MPT_SCSI_HOST {
int port;
u32 pad0;
struct scsi_cmnd **ScsiLookup;
VirtDevice **Targets;
VirtTarget **Targets;
MPT_LOCAL_REPLY *pLocal; /* used for internal commands */
struct timer_list timer;
/* Pool of memory for holding SCpnts before doing
......
......@@ -1245,7 +1245,7 @@ mptctl_gettargetinfo (unsigned long arg)
MPT_ADAPTER *ioc;
struct Scsi_Host *sh;
MPT_SCSI_HOST *hd;
VirtDevice *vdev;
VirtTarget *vdev;
char *pmem;
int *pdata;
IOCPage2_t *pIoc2;
......@@ -1822,7 +1822,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
case MPI_FUNCTION_SCSI_IO_REQUEST:
if (ioc->sh) {
SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
VirtDevice *pTarget = NULL;
VirtTarget *pTarget = NULL;
MPT_SCSI_HOST *hd = NULL;
int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
int scsidir = 0;
......
......@@ -84,13 +84,16 @@ static int mptfcTaskCtx = -1;
static int mptfcInternalCtx = -1; /* Used only for internal commands */
static struct scsi_host_template mptfc_driver_template = {
.module = THIS_MODULE,
.proc_name = "mptfc",
.proc_info = mptscsih_proc_info,
.name = "MPT FC Host",
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
.target_alloc = mptscsih_target_alloc,
.slave_alloc = mptscsih_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.target_destroy = mptscsih_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
......@@ -167,13 +170,15 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping because it's not operational!\n",
ioc->name);
return -ENODEV;
error = -ENODEV;
goto out_mptfc_probe;
}
if (!ioc->active) {
printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
ioc->name);
return -ENODEV;
error = -ENODEV;
goto out_mptfc_probe;
}
/* Sanity check - ensure at least 1 port is INITIATOR capable
......@@ -198,7 +203,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Unable to register controller with SCSI subsystem\n",
ioc->name);
return -1;
error = -1;
goto out_mptfc_probe;
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
......@@ -266,7 +272,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptfc_probe_failed;
goto out_mptfc_probe;
}
memset(mem, 0, sz);
......@@ -284,14 +290,14 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptfc_probe_failed;
goto out_mptfc_probe;
}
memset(mem, 0, sz);
hd->Targets = (VirtDevice **) mem;
hd->Targets = (VirtTarget **) mem;
dprintk((KERN_INFO
" Targets @ %p, sz=%d\n", hd->Targets, sz));
" vdev @ %p, sz=%d\n", hd->Targets, sz));
/* Clear the TM flags
*/
......@@ -330,13 +336,13 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if(error) {
dprintk((KERN_ERR MYNAM
"scsi_add_host failed\n"));
goto mptfc_probe_failed;
goto out_mptfc_probe;
}
scsi_scan_host(sh);
return 0;
mptfc_probe_failed:
out_mptfc_probe:
mptscsih_remove(pdev);
return error;
......
......@@ -228,31 +228,35 @@ static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
* implement ->target_alloc.
*/
static int
mptsas_slave_alloc(struct scsi_device *device)
mptsas_slave_alloc(struct scsi_device *sdev)
{
struct Scsi_Host *host = device->host;
struct Scsi_Host *host = sdev->host;
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
struct sas_rphy *rphy;
struct mptsas_portinfo *p;
VirtTarget *vtarget;
VirtDevice *vdev;
uint target = device->id;
struct scsi_target *starget;
int i;
if ((vdev = hd->Targets[target]) != NULL)
goto out;
vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
if (!vdev) {
printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
hd->ioc->name, sizeof(VirtDevice));
return -ENOMEM;
}
memset(vdev, 0, sizeof(VirtDevice));
vdev->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
vdev->ioc_id = hd->ioc->id;
sdev->hostdata = vdev;
starget = scsi_target(sdev);
vtarget = starget->hostdata;
vdev->vtarget = vtarget;
if (vtarget->num_luns == 0) {
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
hd->Targets[sdev->id] = vtarget;
}
rphy = dev_to_rphy(device->sdev_target->dev.parent);
rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
list_for_each_entry(p, &hd->ioc->sas_topology, list) {
for (i = 0; i < p->num_phys; i++) {
if (p->phy_info[i].attached.sas_address ==
......@@ -260,7 +264,7 @@ mptsas_slave_alloc(struct scsi_device *device)
vdev->target_id =
p->phy_info[i].attached.target;
vdev->bus_id = p->phy_info[i].attached.bus;
hd->Targets[device->id] = vdev;
vdev->lun = sdev->lun;
goto out;
}
}
......@@ -271,19 +275,24 @@ mptsas_slave_alloc(struct scsi_device *device)
return -ENODEV;
out:
vdev->num_luns++;
device->hostdata = vdev;
vtarget->ioc_id = vdev->ioc_id;
vtarget->target_id = vdev->target_id;
vtarget->bus_id = vdev->bus_id;
vtarget->num_luns++;
return 0;
}
static struct scsi_host_template mptsas_driver_template = {
.module = THIS_MODULE,
.proc_name = "mptsas",
.proc_info = mptscsih_proc_info,
.name = "MPT SPI Host",
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
.target_alloc = mptscsih_target_alloc,
.slave_alloc = mptsas_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.target_destroy = mptscsih_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
......@@ -986,7 +995,6 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
goto out_free_port_info;
list_add_tail(&port_info->list, &ioc->sas_topology);
for (i = 0; i < port_info->num_phys; i++) {
mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
(MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
......@@ -1133,13 +1141,15 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping because it's not operational!\n",
ioc->name);
return -ENODEV;
error = -ENODEV;
goto out_mptsas_probe;
}
if (!ioc->active) {
printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
ioc->name);
return -ENODEV;
error = -ENODEV;
goto out_mptsas_probe;
}
/* Sanity check - ensure at least 1 port is INITIATOR capable
......@@ -1163,7 +1173,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Unable to register controller with SCSI subsystem\n",
ioc->name);
return -1;
error = -1;
goto out_mptsas_probe;
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
......@@ -1237,7 +1248,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptsas_probe_failed;
goto out_mptsas_probe;
}
memset(mem, 0, sz);
......@@ -1255,14 +1266,14 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptsas_probe_failed;
goto out_mptsas_probe;
}
memset(mem, 0, sz);
hd->Targets = (VirtDevice **) mem;
hd->Targets = (VirtTarget **) mem;
dprintk((KERN_INFO
" Targets @ %p, sz=%d\n", hd->Targets, sz));
" vtarget @ %p, sz=%d\n", hd->Targets, sz));
/* Clear the TM flags
*/
......@@ -1308,14 +1319,14 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (error) {
dprintk((KERN_ERR MYNAM
"scsi_add_host failed\n"));
goto mptsas_probe_failed;
goto out_mptsas_probe;
}
mptsas_scan_sas_topology(ioc);
return 0;
mptsas_probe_failed:
out_mptsas_probe:
mptscsih_remove(pdev);
return error;
......
此差异已折叠。
......@@ -91,7 +91,9 @@ extern int mptscsih_resume(struct pci_dev *pdev);
extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
extern const char * mptscsih_info(struct Scsi_Host *SChost);
extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
extern int mptscsih_target_alloc(struct scsi_target *starget);
extern int mptscsih_slave_alloc(struct scsi_device *device);
extern void mptscsih_target_destroy(struct scsi_target *starget);
extern void mptscsih_slave_destroy(struct scsi_device *device);
extern int mptscsih_slave_configure(struct scsi_device *device);
extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
......
......@@ -103,13 +103,16 @@ static int mptspiTaskCtx = -1;
static int mptspiInternalCtx = -1; /* Used only for internal commands */
static struct scsi_host_template mptspi_driver_template = {
.module = THIS_MODULE,
.proc_name = "mptspi",
.proc_info = mptscsih_proc_info,
.name = "MPT SPI Host",
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
.target_alloc = mptscsih_target_alloc,
.slave_alloc = mptscsih_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.target_destroy = mptscsih_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
......@@ -177,13 +180,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping because it's not operational!\n",
ioc->name);
return -ENODEV;
error = -ENODEV;
goto out_mptspi_probe;
}
if (!ioc->active) {
printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
ioc->name);
return -ENODEV;
error = -ENODEV;
goto out_mptspi_probe;
}
/* Sanity check - ensure at least 1 port is INITIATOR capable
......@@ -208,7 +213,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Unable to register controller with SCSI subsystem\n",
ioc->name);
return -1;
error = -1;
goto out_mptspi_probe;
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
......@@ -286,7 +292,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptspi_probe_failed;
goto out_mptspi_probe;
}
memset(mem, 0, sz);
......@@ -304,14 +310,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptspi_probe_failed;
goto out_mptspi_probe;
}
memset(mem, 0, sz);
hd->Targets = (VirtDevice **) mem;
hd->Targets = (VirtTarget **) mem;
dprintk((KERN_INFO
" Targets @ %p, sz=%d\n", hd->Targets, sz));
" vdev @ %p, sz=%d\n", hd->Targets, sz));
/* Clear the TM flags
*/
......@@ -385,13 +391,13 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if(error) {
dprintk((KERN_ERR MYNAM
"scsi_add_host failed\n"));
goto mptspi_probe_failed;
goto out_mptspi_probe;
}
scsi_scan_host(sh);
return 0;
mptspi_probe_failed:
out_mptspi_probe:
mptscsih_remove(pdev);
return error;
......
......@@ -857,7 +857,7 @@ process_extended_message(struct Scsi_Host *host,
printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ",
host->host_no, pun, lun,
NCR_700_phase[(dsps & 0xf00) >> 8]);
scsi_print_msg(hostdata->msgin);
spi_print_msg(hostdata->msgin);
printk("\n");
/* just reject it */
hostdata->msgout[0] = A_REJECT_MSG;
......@@ -887,7 +887,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata
#ifdef NCR_700_DEBUG
printk("scsi%d (%d:%d): message %s: ", host->host_no, pun, lun,
NCR_700_phase[(dsps & 0xf00) >> 8]);
scsi_print_msg(hostdata->msgin);
spi_print_msg(hostdata->msgin);
printk("\n");
#endif
......@@ -939,7 +939,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata
host->host_no, pun, lun,
NCR_700_phase[(dsps & 0xf00) >> 8]);
scsi_print_msg(hostdata->msgin);
spi_print_msg(hostdata->msgin);
printk("\n");
/* just reject it */
hostdata->msgout[0] = A_REJECT_MSG;
......
......@@ -238,21 +238,23 @@ struct NCR_700_Host_Parameters {
#ifdef CONFIG_53C700_LE_ON_BE
#define bE (hostdata->force_le_on_be ? 0 : 3)
#define bSWAP (hostdata->force_le_on_be)
/* This is terrible, but there's no raw version of ioread32. That means
* that on a be board we swap twice (once in ioread32 and once again to
* get the value correct) */
#define bS_to_io(x) ((hostdata->force_le_on_be) ? (x) : cpu_to_le32(x))
#define bEBus (!hostdata->force_le_on_be)
#elif defined(__BIG_ENDIAN)
#define bE 3
#define bSWAP 0
#define bS_to_io(x) (x)
#elif defined(__LITTLE_ENDIAN)
#define bE 0
#define bSWAP 0
#define bS_to_io(x) (x)
#else
#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined, did you include byteorder.h?"
#endif
#ifndef bEBus
#ifdef CONFIG_53C700_BE_BUS
#define bEBus 1
#else
#define bEBus 0
#endif
#endif
#define bS_to_cpu(x) (bSWAP ? le32_to_cpu(x) : (x))
#define bS_to_host(x) (bSWAP ? cpu_to_le32(x) : (x))
......@@ -466,14 +468,15 @@ NCR_700_readl(struct Scsi_Host *host, __u32 reg)
{
const struct NCR_700_Host_Parameters *hostdata
= (struct NCR_700_Host_Parameters *)host->hostdata[0];
__u32 value = ioread32(hostdata->base + reg);
__u32 value = bEBus ? ioread32be(hostdata->base + reg) :
ioread32(hostdata->base + reg);
#if 1
/* sanity check the register */
if((reg & 0x3) != 0)
BUG();
#endif
return bS_to_io(value);
return value;
}
static inline void
......@@ -497,7 +500,8 @@ NCR_700_writel(__u32 value, struct Scsi_Host *host, __u32 reg)
BUG();
#endif
iowrite32(bS_to_io(value), hostdata->base + reg);
bEBus ? iowrite32be(value, hostdata->base + reg):
iowrite32(value, hostdata->base + reg);
}
#endif
......@@ -282,6 +282,7 @@
#include "scsi.h"
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_spi.h>
#include "53c7xx.h"
#include <linux/stat.h>
#include <linux/stddef.h>
......@@ -1724,7 +1725,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) {
printk ("scsi%d : status ", host->host_no);
scsi_print_status (status);
printk ("\nscsi%d : message ", host->host_no);
scsi_print_msg (&msg);
spi_print_msg(&msg);
printk ("\n");
} else if (hostdata->test_completed == 3) {
printk("scsi%d : test 2 no connection with target %d\n",
......@@ -2313,7 +2314,7 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct
printk ("scsi%d : received message", host->host_no);
if (c)
printk (" from target %d lun %d ", c->device->id, c->device->lun);
scsi_print_msg ((unsigned char *) hostdata->msg_buf);
spi_print_msg((unsigned char *) hostdata->msg_buf);
printk("\n");
}
......@@ -5540,7 +5541,7 @@ print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) {
i > 0 && !check_address ((unsigned long) ptr, 1);
ptr += len, i -= len) {
printk(" ");
len = scsi_print_msg (ptr);
len = spi_print_msg(ptr);
printk("\n");
if (!len)
break;
......
......@@ -336,6 +336,7 @@ config SCSI_ACARD
config SCSI_AHA152X
tristate "Adaptec AHA152X/2825 support"
depends on ISA && SCSI && !64BIT
select SCSI_SPI_ATTRS
---help---
This is a driver for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825
SCSI host adapters. It also works for the AVA-1505, but the IRQ etc.
......@@ -623,6 +624,7 @@ config SCSI_OMIT_FLASHPOINT
config SCSI_DMX3191D
tristate "DMX3191D SCSI support"
depends on PCI && SCSI
select SCSI_SPI_ATTRS
help
This is support for Domex DMX3191D SCSI Host Adapters.
......@@ -632,6 +634,7 @@ config SCSI_DMX3191D
config SCSI_DTC3280
tristate "DTC3180/3280 SCSI support"
depends on ISA && SCSI
select SCSI_SPI_ATTRS
help
This is support for DTC 3180/3280 SCSI Host Adapters. Please read
the SCSI-HOWTO, available from
......@@ -752,6 +755,7 @@ config SCSI_GDTH
config SCSI_GENERIC_NCR5380
tristate "Generic NCR5380/53c400 SCSI PIO support"
depends on ISA && SCSI
select SCSI_SPI_ATTRS
---help---
This is a driver for the old NCR 53c80 series of SCSI controllers
on boards using PIO. Most boards such as the Trantor T130 fit this
......@@ -771,6 +775,7 @@ config SCSI_GENERIC_NCR5380
config SCSI_GENERIC_NCR5380_MMIO
tristate "Generic NCR5380/53c400 SCSI MMIO support"
depends on ISA && SCSI
select SCSI_SPI_ATTRS
---help---
This is a driver for the old NCR 53c80 series of SCSI controllers
on boards using memory mapped I/O.
......@@ -1254,6 +1259,7 @@ config SCSI_MCA_53C9X
config SCSI_PAS16
tristate "PAS16 SCSI support"
depends on ISA && SCSI
select SCSI_SPI_ATTRS
---help---
This is support for a SCSI host adapter. It is explained in section
3.10 of the SCSI-HOWTO, available from
......@@ -1423,6 +1429,7 @@ config SCSI_DC390T
config SCSI_T128
tristate "Trantor T128/T128F/T228 SCSI support"
depends on ISA && SCSI
select SCSI_SPI_ATTRS
---help---
This is support for a SCSI host adapter. It is explained in section
3.11 of the SCSI-HOWTO, available from
......@@ -1681,6 +1688,7 @@ config OKTAGON_SCSI
config ATARI_SCSI
tristate "Atari native SCSI support"
depends on ATARI && SCSI && BROKEN
select SCSI_SPI_ATTRS
---help---
If you have an Atari with built-in NCR5380 SCSI controller (TT,
Falcon, ...) say Y to get it supported. Of course also, if you have
......@@ -1722,6 +1730,7 @@ config TT_DMA_EMUL
config MAC_SCSI
bool "Macintosh NCR5380 SCSI"
depends on MAC && SCSI=y
select SCSI_SPI_ATTRS
help
This is the NCR 5380 SCSI controller included on most of the 68030
based Macintoshes. If you have one of these say Y and read the
......@@ -1743,6 +1752,7 @@ config SCSI_MAC_ESP
config MVME147_SCSI
bool "WD33C93 SCSI driver for MVME147"
depends on MVME147 && SCSI=y
select SCSI_SPI_ATTRS
help
Support for the on-board SCSI controller on the Motorola MVME147
single-board computer.
......@@ -1750,6 +1760,7 @@ config MVME147_SCSI
config MVME16x_SCSI
bool "NCR53C710 SCSI driver for MVME16x"
depends on MVME16x && SCSI && BROKEN
select SCSI_SPI_ATTRS
help
The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
SCSI controller chip. Almost everyone using one of these boards
......@@ -1758,6 +1769,7 @@ config MVME16x_SCSI
config BVME6000_SCSI
bool "NCR53C710 SCSI driver for BVME6000"
depends on BVME6000 && SCSI && BROKEN
select SCSI_SPI_ATTRS
help
The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
SCSI controller chip. Almost everyone using one of these boards
......@@ -1774,6 +1786,7 @@ config SCSI_NCR53C7xx_FAST
config SUN3_SCSI
tristate "Sun3 NCR5380 SCSI"
depends on SUN3 && SCSI && BROKEN
select SCSI_SPI_ATTRS
help
This option will enable support for the OBIO (onboard io) NCR5380
SCSI controller found in the Sun 3/50 and 3/60, as well as for
......
......@@ -87,6 +87,7 @@
* the high level code.
*/
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_transport_spi.h>
#ifndef NDEBUG
#define NDEBUG 0
......@@ -2377,7 +2378,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
* 3..length+1 arguments
*
* Start the extended message buffer with the EXTENDED_MESSAGE
* byte, since scsi_print_msg() wants the whole thing.
* byte, since spi_print_msg() wants the whole thing.
*/
extended_msg[0] = EXTENDED_MESSAGE;
/* Accept first byte by clearing ACK */
......@@ -2424,7 +2425,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
default:
if (!tmp) {
printk("scsi%d: rejecting message ", instance->host_no);
scsi_print_msg(extended_msg);
spi_print_msg(extended_msg);
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
scmd_printk(KERN_INFO, cmd,
......@@ -2560,7 +2561,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
if (!(msg[0] & 0x80)) {
printk(KERN_ERR "scsi%d : expecting IDENTIFY message, got ", instance->host_no);
scsi_print_msg(msg);
spi_print_msg(msg);
abort = 1;
} else {
/* Accept message by clearing ACK */
......
......@@ -259,6 +259,7 @@
#include "scsi.h"
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_spi.h>
#include "aha152x.h"
......@@ -1845,7 +1846,7 @@ static void msgi_run(struct Scsi_Host *shpnt)
#if defined(AHA152X_DEBUG)
if (HOSTDATA(shpnt)->debug & debug_msgi) {
printk(INFO_LEAD "inbound message %02x ", CMDINFO(CURRENT_SC), MSGI(0));
scsi_print_msg(&MSGI(0));
spi_print_msg(&MSGI(0));
printk("\n");
}
#endif
......@@ -1933,7 +1934,7 @@ static void msgi_run(struct Scsi_Host *shpnt)
break;
printk(INFO_LEAD, CMDINFO(CURRENT_SC));
scsi_print_msg(&MSGI(0));
spi_print_msg(&MSGI(0));
printk("\n");
ticks = (MSGI(3) * 4 + 49) / 50;
......@@ -2031,7 +2032,7 @@ static void msgo_init(struct Scsi_Host *shpnt)
int i;
printk(DEBUG_LEAD "messages( ", CMDINFO(CURRENT_SC));
for (i=0; i<MSGOLEN; i+=scsi_print_msg(&MSGO(i)), printk(" "))
for (i=0; i<MSGOLEN; i+=spi_print_msg(&MSGO(i)), printk(" "))
;
printk(")\n");
}
......
......@@ -1064,6 +1064,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
struct Scsi_Host *host;
char *new_name;
u_long s;
int retval;
template->name = ahd->description;
host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
......@@ -1096,9 +1097,15 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
host->transportt = ahd_linux_transport_template;
scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
retval = scsi_add_host(host, &ahd->dev_softc->dev);
if (retval) {
printk(KERN_WARNING "aic79xx: scsi_add_host failed\n");
scsi_host_put(host);
return retval;
}
scsi_scan_host(host);
return (0);
return 0;
}
uint64_t
......
......@@ -1061,10 +1061,11 @@ uint32_t aic7xxx_verbose;
int
ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *template)
{
char buf[80];
struct Scsi_Host *host;
char buf[80];
struct Scsi_Host *host;
char *new_name;
u_long s;
u_long s;
int retval;
template->name = ahc->description;
host = scsi_host_alloc(template, sizeof(struct ahc_softc *));
......@@ -1097,9 +1098,16 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
host->transportt = ahc_linux_transport_template;
scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
retval = scsi_add_host(host,
(ahc->dev_softc ? &ahc->dev_softc->dev : NULL));
if (retval) {
printk(KERN_WARNING "aic7xxx: scsi_add_host failed\n");
scsi_host_put(host);
return retval;
}
scsi_scan_host(host);
return (0);
return 0;
}
/*
......
......@@ -4,6 +4,7 @@
config SCSI_ACORNSCSI_3
tristate "Acorn SCSI card (aka30) support"
depends on ARCH_ACORN && SCSI && BROKEN
select SCSI_SPI_ATTRS
help
This enables support for the Acorn SCSI card (aka30). If you have an
Acorn system with one of these, say Y. If unsure, say N.
......
......@@ -152,6 +152,7 @@
#include "../scsi.h"
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_spi.h>
#include "acornscsi.h"
#include "msgqueue.h"
#include "scsi.h"
......@@ -1370,7 +1371,7 @@ void acornscsi_sendmessage(AS_Host *host)
host->scsi.last_message = msg->msg[0];
#if (DEBUG & DEBUG_MESSAGES)
scsi_print_msg(msg->msg);
spi_print_msg(msg->msg);
#endif
break;
......@@ -1392,7 +1393,7 @@ void acornscsi_sendmessage(AS_Host *host)
while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
unsigned int i;
#if (DEBUG & DEBUG_MESSAGES)
scsi_print_msg(msg);
spi_print_msg(msg);
#endif
i = 0;
if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000))
......@@ -1488,7 +1489,7 @@ void acornscsi_message(AS_Host *host)
#if (DEBUG & DEBUG_MESSAGES)
printk("scsi%d.%c: message in: ",
host->host->host_no, acornscsi_target(host));
scsi_print_msg(message);
spi_print_msg(message);
printk("\n");
#endif
......
......@@ -74,6 +74,7 @@
* the high level code.
*/
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_transport_spi.h>
#if (NDEBUG & NDEBUG_LISTS)
#define LIST(x,y) \
......@@ -2355,7 +2356,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
* 3..length+1 arguments
*
* Start the extended message buffer with the EXTENDED_MESSAGE
* byte, since scsi_print_msg() wants the whole thing.
* byte, since spi_print_msg() wants the whole thing.
*/
extended_msg[0] = EXTENDED_MESSAGE;
/* Accept first byte by clearing ACK */
......@@ -2408,7 +2409,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
default:
if (!tmp) {
printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
scsi_print_msg (extended_msg);
spi_print_msg(extended_msg);
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
printk(KERN_DEBUG "scsi%d: rejecting unknown "
......@@ -2541,7 +2542,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
if (!(msg[0] & 0x80)) {
printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
scsi_print_msg(msg);
spi_print_msg(msg);
do_abort(instance);
return;
}
......
......@@ -75,7 +75,7 @@ static int vendor_counts[CH_TYPES-4];
module_param_array(vendor_firsts, int, NULL, 0444);
module_param_array(vendor_counts, int, NULL, 0444);
static char *vendor_labels[CH_TYPES-4] = {
static const char * vendor_labels[CH_TYPES-4] = {
"v0", "v1", "v2", "v3"
};
// module_param_string_array(vendor_labels, NULL, 0444);
......@@ -140,7 +140,7 @@ static struct file_operations changer_fops =
#endif
};
static struct {
static const struct {
unsigned char sense;
unsigned char asc;
unsigned char ascq;
......
......@@ -1065,7 +1065,7 @@ struct error_info2 {
const char * fmt;
};
static struct error_info2 additional2[] =
static const struct error_info2 additional2[] =
{
{0x40,0x00,0x7f,"Ram failure (%x)"},
{0x40,0x80,0xff,"Diagnostic failure on component (%x)"},
......@@ -1077,7 +1077,7 @@ static struct error_info2 additional2[] =
};
/* description of the sense key values */
static const char *snstext[] = {
static const char * const snstext[] = {
"No Sense", /* 0: There is no sense information */
"Recovered Error", /* 1: The last command completed successfully
but used error correction */
......@@ -1278,114 +1278,6 @@ void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq)
}
EXPORT_SYMBOL(scsi_print_req_sense);
#ifdef CONFIG_SCSI_CONSTANTS
static const char *one_byte_msgs[] = {
/* 0x00 */ "Command Complete", NULL, "Save Pointers",
/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error",
/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error",
/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag",
/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue",
/* 0x0f */ "Initiate Recovery", "Release Recovery"
};
#define NO_ONE_BYTE_MSGS (sizeof(one_byte_msgs) / sizeof (const char *))
static const char *two_byte_msgs[] = {
/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag"
/* 0x23 */ "Ignore Wide Residue"
};
#define NO_TWO_BYTE_MSGS (sizeof(two_byte_msgs) / sizeof (const char *))
static const char *extended_msgs[] = {
/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request",
/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request"
};
#define NO_EXTENDED_MSGS (sizeof(two_byte_msgs) / sizeof (const char *))
int scsi_print_msg (const unsigned char *msg)
{
int len = 0, i;
if (msg[0] == EXTENDED_MESSAGE) {
len = 3 + msg[1];
if (msg[2] < NO_EXTENDED_MSGS)
printk ("%s ", extended_msgs[msg[2]]);
else
printk ("Extended Message, reserved code (0x%02x) ",
(int) msg[2]);
switch (msg[2]) {
case EXTENDED_MODIFY_DATA_POINTER:
printk("pointer = %d", (int) (msg[3] << 24) |
(msg[4] << 16) | (msg[5] << 8) | msg[6]);
break;
case EXTENDED_SDTR:
printk("period = %d ns, offset = %d",
(int) msg[3] * 4, (int) msg[4]);
break;
case EXTENDED_WDTR:
printk("width = 2^%d bytes", msg[3]);
break;
default:
for (i = 2; i < len; ++i)
printk("%02x ", msg[i]);
}
/* Identify */
} else if (msg[0] & 0x80) {
printk("Identify disconnect %sallowed %s %d ",
(msg[0] & 0x40) ? "" : "not ",
(msg[0] & 0x20) ? "target routine" : "lun",
msg[0] & 0x7);
len = 1;
/* Normal One byte */
} else if (msg[0] < 0x1f) {
if (msg[0] < NO_ONE_BYTE_MSGS)
printk(one_byte_msgs[msg[0]]);
else
printk("reserved (%02x) ", msg[0]);
len = 1;
/* Two byte */
} else if (msg[0] <= 0x2f) {
if ((msg[0] - 0x20) < NO_TWO_BYTE_MSGS)
printk("%s %02x ", two_byte_msgs[msg[0] - 0x20],
msg[1]);
else
printk("reserved two byte (%02x %02x) ",
msg[0], msg[1]);
len = 2;
} else
printk("reserved");
return len;
}
EXPORT_SYMBOL(scsi_print_msg);
#else /* ifndef CONFIG_SCSI_CONSTANTS */
int scsi_print_msg (const unsigned char *msg)
{
int len = 0, i;
if (msg[0] == EXTENDED_MESSAGE) {
len = 3 + msg[1];
for (i = 0; i < len; ++i)
printk("%02x ", msg[i]);
/* Identify */
} else if (msg[0] & 0x80) {
printk("%02x ", msg[0]);
len = 1;
/* Normal One byte */
} else if (msg[0] < 0x1f) {
printk("%02x ", msg[0]);
len = 1;
/* Two byte */
} else if (msg[0] <= 0x2f) {
printk("%02x %02x", msg[0], msg[1]);
len = 2;
} else
printk("%02x ", msg[0]);
return len;
}
EXPORT_SYMBOL(scsi_print_msg);
#endif /* ! CONFIG_SCSI_CONSTANTS */
void scsi_print_command(struct scsi_cmnd *cmd)
{
/* Assume appended output (i.e. not at start of line) */
......@@ -1397,7 +1289,7 @@ EXPORT_SYMBOL(scsi_print_command);
#ifdef CONFIG_SCSI_CONSTANTS
static const char * hostbyte_table[]={
static const char * const hostbyte_table[]={
"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"};
......@@ -1422,12 +1314,12 @@ void scsi_print_hostbyte(int scsiresult)
#ifdef CONFIG_SCSI_CONSTANTS
static const char * driverbyte_table[]={
static const char * const driverbyte_table[]={
"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR",
"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
#define NUM_DRIVERBYTE_STRS (sizeof(driverbyte_table) / sizeof(const char *))
static const char * driversuggest_table[]={"SUGGEST_OK",
static const char * const driversuggest_table[]={"SUGGEST_OK",
"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
"SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"};
#define NUM_SUGGEST_STRS (sizeof(driversuggest_table) / sizeof(const char *))
......
......@@ -5887,7 +5887,12 @@ static int __devinit ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
ENTER;
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
dev_dbg(&ioa_cfg->pdev->dev, "ioa_cfg adx: 0x%p\n", ioa_cfg);
_ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_enable_ioa, IPR_SHUTDOWN_NONE);
if (ioa_cfg->needs_hard_reset) {
ioa_cfg->needs_hard_reset = 0;
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
} else
_ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_enable_ioa,
IPR_SHUTDOWN_NONE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
......@@ -6264,6 +6269,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
unsigned long ipr_regs_pci;
void __iomem *ipr_regs;
u32 rc = PCIBIOS_SUCCESSFUL;
volatile u32 mask, uproc;
ENTER;
......@@ -6356,6 +6362,15 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
goto cleanup_nomem;
}
/*
* If HRRQ updated interrupt is not masked, or reset alert is set,
* the card is in an unknown state and needs a hard reset
*/
mask = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg);
if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT))
ioa_cfg->needs_hard_reset = 1;
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
rc = request_irq(pdev->irq, ipr_isr, SA_SHIRQ, IPR_NAME, ioa_cfg);
......
......@@ -36,8 +36,8 @@
/*
* Literals
*/
#define IPR_DRIVER_VERSION "2.1.0"
#define IPR_DRIVER_DATE "(October 31, 2005)"
#define IPR_DRIVER_VERSION "2.1.1"
#define IPR_DRIVER_DATE "(November 15, 2005)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
......@@ -922,6 +922,7 @@ struct ipr_ioa_cfg {
u8 dump_taken:1;
u8 allow_cmds:1;
u8 allow_ml_add_del:1;
u8 needs_hard_reset:1;
enum ipr_cache_state cache_state;
u16 type; /* CCIN of the card */
......
......@@ -49,7 +49,7 @@ MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, "
"Alex Aizman <itn780@yahoo.com>");
MODULE_DESCRIPTION("iSCSI/TCP data-path");
MODULE_LICENSE("GPL");
MODULE_VERSION("0:4.409");
MODULE_VERSION("0:4.445");
/* #define DEBUG_TCP */
/* #define DEBUG_SCSI */
#define DEBUG_ASSERT
......@@ -581,10 +581,16 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) +
conn->in.ahslen);
if (cdgst != rdgst) {
printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
"recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
cdgst);
return ISCSI_ERR_HDR_DGST;
}
}
/* save opcode for later */
conn->in.opcode = hdr->opcode;
conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK;
/* verify itt (itt encoding: age+cid+itt) */
if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
......@@ -610,13 +616,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
conn->in.ahslen, conn->in.datalen);
if (conn->in.itt < session->cmds_max) {
if (conn->hdrdgst_en && cdgst != rdgst) {
printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
"recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
cdgst);
return ISCSI_ERR_HDR_DGST;
}
ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt];
if (!ctask->sc) {
......@@ -642,9 +641,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
switch(conn->in.opcode) {
case ISCSI_OP_SCSI_CMD_RSP:
BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE)
rc = iscsi_cmd_rsp(conn, ctask);
else if (!conn->in.datalen)
if (!conn->in.datalen)
rc = iscsi_cmd_rsp(conn, ctask);
else
/*
......@@ -666,8 +663,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
break;
case ISCSI_OP_R2T:
BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE &&
ctask->sc->sc_data_direction == DMA_TO_DEVICE)
if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
rc = iscsi_r2t_rsp(conn, ctask);
else
rc = ISCSI_ERR_PROTO;
......@@ -906,11 +902,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg,
crypto_digest_update(conn->data_rx_tfm, &temp, 1);
}
static void
iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len)
{
struct scatterlist tmp;
sg_init_one(&tmp, buf, len);
crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
}
static int iscsi_scsi_data_in(struct iscsi_conn *conn)
{
struct iscsi_cmd_task *ctask = conn->in.ctask;
struct scsi_cmnd *sc = ctask->sc;
struct scatterlist tmp, *sg;
struct scatterlist *sg;
int i, offset, rc = 0;
BUG_ON((void*)ctask != sc->SCp.ptr);
......@@ -924,10 +929,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
sc->request_bufflen, ctask->data_offset);
if (rc == -EAGAIN)
return rc;
if (conn->datadgst_en) {
sg_init_one(&tmp, sc->request_buffer, i);
crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
}
if (conn->datadgst_en)
iscsi_recv_digest_update(conn, sc->request_buffer, i);
rc = 0;
goto done;
}
......@@ -1021,6 +1024,9 @@ iscsi_data_recv(struct iscsi_conn *conn)
conn->in.hdr = &conn->hdr;
conn->senselen = (conn->data[0] << 8) | conn->data[1];
rc = iscsi_cmd_rsp(conn, conn->in.ctask);
if (!rc && conn->datadgst_en)
iscsi_recv_digest_update(conn, conn->data,
conn->in.datalen);
}
break;
case ISCSI_OP_TEXT_RSP:
......@@ -1045,6 +1051,11 @@ iscsi_data_recv(struct iscsi_conn *conn)
rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
conn->data, conn->in.datalen);
if (!rc && conn->datadgst_en &&
conn->in.opcode != ISCSI_OP_LOGIN_RSP)
iscsi_recv_digest_update(conn, conn->data,
conn->in.datalen);
if (mtask && conn->login_mtask != mtask) {
spin_lock(&session->lock);
__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
......@@ -1053,6 +1064,8 @@ iscsi_data_recv(struct iscsi_conn *conn)
}
}
break;
case ISCSI_OP_ASYNC_EVENT:
case ISCSI_OP_REJECT:
default:
BUG_ON(1);
}
......@@ -1114,8 +1127,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
*/
rc = iscsi_hdr_recv(conn);
if (!rc && conn->in.datalen) {
if (conn->datadgst_en &&
conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
if (conn->datadgst_en) {
BUG_ON(!conn->data_rx_tfm);
crypto_digest_init(conn->data_rx_tfm);
}
......@@ -1127,26 +1139,24 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
}
if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
uint32_t recv_digest;
debug_tcp("extra data_recv offset %d copy %d\n",
conn->in.offset, conn->in.copy);
if (conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
uint32_t recv_digest;
skb_copy_bits(conn->in.skb, conn->in.offset,
&recv_digest, 4);
conn->in.offset += 4;
conn->in.copy -= 4;
if (recv_digest != conn->in.datadgst) {
debug_tcp("iscsi_tcp: data digest error!"
"0x%x != 0x%x\n", recv_digest,
conn->in.datadgst);
iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
return 0;
} else {
debug_tcp("iscsi_tcp: data digest match!"
"0x%x == 0x%x\n", recv_digest,
conn->in.datadgst);
conn->in_progress = IN_PROGRESS_WAIT_HEADER;
}
skb_copy_bits(conn->in.skb, conn->in.offset,
&recv_digest, 4);
conn->in.offset += 4;
conn->in.copy -= 4;
if (recv_digest != conn->in.datadgst) {
debug_tcp("iscsi_tcp: data digest error!"
"0x%x != 0x%x\n", recv_digest,
conn->in.datadgst);
iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
return 0;
} else {
debug_tcp("iscsi_tcp: data digest match!"
"0x%x == 0x%x\n", recv_digest,
conn->in.datadgst);
conn->in_progress = IN_PROGRESS_WAIT_HEADER;
}
}
......@@ -1167,8 +1177,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
}
conn->in.copy -= conn->in.padding;
conn->in.offset += conn->in.padding;
if (conn->datadgst_en &&
conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
if (conn->datadgst_en) {
if (conn->in.padding) {
debug_tcp("padding -> %d\n", conn->in.padding);
memset(pad, 0, conn->in.padding);
......@@ -1237,8 +1246,9 @@ iscsi_tcp_state_change(struct sock *sk)
conn = (struct iscsi_conn*)sk->sk_user_data;
session = conn->session;
if (sk->sk_state == TCP_CLOSE_WAIT ||
sk->sk_state == TCP_CLOSE) {
if ((sk->sk_state == TCP_CLOSE_WAIT ||
sk->sk_state == TCP_CLOSE) &&
!atomic_read(&sk->sk_rmem_alloc)) {
debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n");
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
}
......@@ -2388,6 +2398,15 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
return 0;
}
static int
iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
{
if (depth > ISCSI_MAX_CMD_PER_LUN)
depth = ISCSI_MAX_CMD_PER_LUN;
scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
return sdev->queue_depth;
}
static int
iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
{
......@@ -2853,8 +2872,11 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
* in hdr_extract() and will be re-negotiated at
* set_param() time.
*/
if (flag == STOP_CONN_RECOVER)
if (flag == STOP_CONN_RECOVER) {
conn->hdr_size = sizeof(struct iscsi_hdr);
conn->hdrdgst_en = 0;
conn->datadgst_en = 0;
}
}
up(&conn->xmitsema);
}
......@@ -3247,13 +3269,14 @@ iscsi_r2tpool_free(struct iscsi_session *session)
static struct scsi_host_template iscsi_sht = {
.name = "iSCSI Initiator over TCP/IP, v."
ISCSI_VERSION_STR,
.queuecommand = iscsi_queuecommand,
.queuecommand = iscsi_queuecommand,
.change_queue_depth = iscsi_change_queue_depth,
.can_queue = ISCSI_XMIT_CMDS_MAX - 1,
.sg_tablesize = ISCSI_SG_TABLESIZE,
.cmd_per_lun = ISCSI_CMD_PER_LUN,
.eh_abort_handler = iscsi_eh_abort,
.eh_host_reset_handler = iscsi_eh_host_reset,
.use_clustering = DISABLE_CLUSTERING,
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
.eh_abort_handler = iscsi_eh_abort,
.eh_host_reset_handler = iscsi_eh_host_reset,
.use_clustering = DISABLE_CLUSTERING,
.proc_name = "iscsi_tcp",
.this_id = -1,
};
......
......@@ -71,7 +71,8 @@
#define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */
#define ISCSI_MGMT_ITT_OFFSET 0xa00
#define ISCSI_SG_TABLESIZE SG_ALL
#define ISCSI_CMD_PER_LUN 128
#define ISCSI_DEF_CMD_PER_LUN 32
#define ISCSI_MAX_CMD_PER_LUN 128
#define ISCSI_TCP_MAX_CMD_LEN 16
#define ITT_MASK (0xfff)
......
......@@ -29,9 +29,10 @@ struct lpfc_sli2_slim;
#define LPFC_LC_HBA_Q_DEPTH 1024 /* max cmds per low cost hba */
#define LPFC_LP101_HBA_Q_DEPTH 128 /* max cmds per low cost hba */
#define LPFC_CMD_PER_LUN 30 /* max outstanding cmds per lun */
#define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */
#define LPFC_SG_SEG_CNT 64 /* sg element count per scsi cmnd */
#define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */
#define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */
/* Define macros for 64 bit support */
#define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr)))
......@@ -45,6 +46,11 @@ struct lpfc_sli2_slim;
#define MAX_HBAEVT 32
enum lpfc_polling_flags {
ENABLE_FCP_RING_POLLING = 0x1,
DISABLE_FCP_RING_INT = 0x2
};
/* Provide DMA memory definitions the driver uses per port instance. */
struct lpfc_dmabuf {
struct list_head list;
......@@ -167,6 +173,7 @@ struct lpfc_hba {
dma_addr_t slim2p_mapping;
uint16_t pci_cfg_value;
struct semaphore hba_can_block;
uint32_t hba_state;
#define LPFC_INIT_START 1 /* Initial state after board reset */
......@@ -286,6 +293,8 @@ struct lpfc_hba {
uint32_t cfg_fcp_bind_method;
uint32_t cfg_discovery_threads;
uint32_t cfg_max_luns;
uint32_t cfg_poll;
uint32_t cfg_poll_tmo;
uint32_t cfg_sg_seg_cnt;
uint32_t cfg_sg_dma_buf_size;
......@@ -337,7 +346,9 @@ struct lpfc_hba {
#define VPD_PORT 0x8 /* valid vpd port data */
#define VPD_MASK 0xf /* mask for any vpd data */
struct timer_list fcp_poll_timer;
struct timer_list els_tmofunc;
/*
* stat counters
*/
......@@ -348,6 +359,7 @@ struct lpfc_hba {
struct lpfc_sysfs_mbox sysfs_mbox;
/* fastpath list. */
spinlock_t scsi_buf_list_lock;
struct list_head lpfc_scsi_buf_list;
uint32_t total_scsi_bufs;
struct list_head lpfc_iocb_list;
......
......@@ -278,6 +278,71 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
return -EIO;
}
static ssize_t
lpfc_poll_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
}
static ssize_t
lpfc_poll_store(struct class_device *cdev, const char *buf,
size_t count)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
uint32_t creg_val;
uint32_t old_val;
int val=0;
if (!isdigit(buf[0]))
return -EINVAL;
if (sscanf(buf, "%i", &val) != 1)
return -EINVAL;
if ((val & 0x3) != val)
return -EINVAL;
spin_lock_irq(phba->host->host_lock);
old_val = phba->cfg_poll;
if (val & ENABLE_FCP_RING_POLLING) {
if ((val & DISABLE_FCP_RING_INT) &&
!(old_val & DISABLE_FCP_RING_INT)) {
creg_val = readl(phba->HCregaddr);
creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
writel(creg_val, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
lpfc_poll_start_timer(phba);
}
} else if (val != 0x0) {
spin_unlock_irq(phba->host->host_lock);
return -EINVAL;
}
if (!(val & DISABLE_FCP_RING_INT) &&
(old_val & DISABLE_FCP_RING_INT))
{
spin_unlock_irq(phba->host->host_lock);
del_timer(&phba->fcp_poll_timer);
spin_lock_irq(phba->host->host_lock);
creg_val = readl(phba->HCregaddr);
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
writel(creg_val, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
}
phba->cfg_poll = val;
spin_unlock_irq(phba->host->host_lock);
return strlen(buf);
}
#define lpfc_param_show(attr) \
static ssize_t \
......@@ -416,6 +481,15 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
lpfc_board_online_show, lpfc_board_online_store);
static int lpfc_poll = 0;
module_param(lpfc_poll, int, 0);
MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
" 0 - none,"
" 1 - poll with interrupts enabled"
" 3 - poll and disable FCP ring interrupts");
static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
lpfc_poll_show, lpfc_poll_store);
/*
# lpfc_log_verbose: Only turn this flag on if you are willing to risk being
......@@ -523,10 +597,10 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
# is 0. Default value of cr_count is 1. The cr_count feature is disabled if
# cr_delay is set to 0.
*/
LPFC_ATTR(cr_delay, 0, 0, 63, "A count of milliseconds after which an"
LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an"
"interrupt response is generated");
LPFC_ATTR(cr_count, 1, 1, 255, "A count of I/O completions after which an"
LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an"
"interrupt response is generated");
/*
......@@ -553,6 +627,13 @@ LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands"
LPFC_ATTR_R(max_luns, 256, 1, 32768,
"Maximum number of LUNs per target driver will support");
/*
# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
# Value range is [1,255], default value is 10.
*/
LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
"Milliseconds driver will wait between polling FCP ring");
struct class_device_attribute *lpfc_host_attrs[] = {
&class_device_attr_info,
&class_device_attr_serialnum,
......@@ -575,11 +656,15 @@ struct class_device_attribute *lpfc_host_attrs[] = {
&class_device_attr_lpfc_topology,
&class_device_attr_lpfc_scan_down,
&class_device_attr_lpfc_link_speed,
&class_device_attr_lpfc_cr_delay,
&class_device_attr_lpfc_cr_count,
&class_device_attr_lpfc_fdmi_on,
&class_device_attr_lpfc_max_luns,
&class_device_attr_nport_evt_cnt,
&class_device_attr_management_version,
&class_device_attr_board_online,
&class_device_attr_lpfc_poll,
&class_device_attr_lpfc_poll_tmo,
NULL,
};
......@@ -1292,6 +1377,9 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_fdmi_on_init(phba, lpfc_fdmi_on);
lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
lpfc_max_luns_init(phba, lpfc_max_luns);
lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
phba->cfg_poll = lpfc_poll;
/*
* The total number of segments is the configuration value plus 2
......
......@@ -143,6 +143,9 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
int lpfc_mem_alloc(struct lpfc_hba *);
void lpfc_mem_free(struct lpfc_hba *);
void lpfc_poll_timeout(unsigned long ptr);
void lpfc_poll_start_timer(struct lpfc_hba * phba);
void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
......
......@@ -73,6 +73,8 @@ struct lpfc_nodelist {
struct lpfc_hba *nlp_phba;
struct lpfc_work_evt nodev_timeout_evt;
struct lpfc_work_evt els_retry_evt;
unsigned long last_ramp_up_time; /* jiffy of last ramp up */
unsigned long last_q_full_time; /* jiffy of last queue full */
};
/* Defines for nlp_flag (uint32) */
......
......@@ -720,6 +720,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
(irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
}
......@@ -869,6 +870,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
(irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
goto out;
}
......@@ -1054,6 +1056,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
(irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
}
......@@ -1205,6 +1208,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
(irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
goto out;
}
......
......@@ -1017,12 +1017,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rport_ids.port_id = ndlp->nlp_DID;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
if (ndlp->nlp_type & NLP_FCP_TARGET)
rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
if (ndlp->nlp_type & NLP_FCP_INITIATOR)
rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
scsi_block_requests(phba->host);
ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
if (!rport) {
dev_printk(KERN_WARNING, &phba->pcidev->dev,
......@@ -1039,7 +1034,16 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
}
rdata = rport->dd_data;
rdata->pnode = ndlp;
scsi_unblock_requests(phba->host);
if (ndlp->nlp_type & NLP_FCP_TARGET)
rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
if (ndlp->nlp_type & NLP_FCP_INITIATOR)
rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN)
fc_remote_port_rolechg(rport, rport_ids.roles);
return;
}
......@@ -1053,9 +1057,7 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba,
ndlp->rport = NULL;
rdata->pnode = NULL;
scsi_block_requests(phba->host);
fc_remote_port_delete(rport);
scsi_unblock_requests(phba->host);
return;
}
......
......@@ -266,9 +266,11 @@ struct lpfc_name {
struct {
#ifdef __BIG_ENDIAN_BITFIELD
uint8_t nameType:4; /* FC Word 0, bit 28:31 */
uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit
8:11 of IEEE ext */
#else /* __LITTLE_ENDIAN_BITFIELD */
uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit
8:11 of IEEE ext */
uint8_t nameType:4; /* FC Word 0, bit 28:31 */
#endif
......@@ -278,7 +280,8 @@ struct lpfc_name {
#define NAME_IP_TYPE 0x4 /* IP address */
#define NAME_CCITT_TYPE 0xC
#define NAME_CCITT_GR_TYPE 0xE
uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */
uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE
extended Lsb */
uint8_t IEEE[6]; /* FC IEEE address */
} s;
uint8_t wwn[8];
......@@ -1024,23 +1027,38 @@ typedef struct {
/* Start FireFly Register definitions */
#define PCI_VENDOR_ID_EMULEX 0x10df
#define PCI_DEVICE_ID_FIREFLY 0x1ae5
#define PCI_DEVICE_ID_SUPERFLY 0xf700
#define PCI_DEVICE_ID_DRAGONFLY 0xf800
#define PCI_DEVICE_ID_RFLY 0xf095
#define PCI_DEVICE_ID_PFLY 0xf098
#define PCI_DEVICE_ID_LP101 0xf0a1
#define PCI_DEVICE_ID_TFLY 0xf0a5
#define PCI_DEVICE_ID_BSMB 0xf0d1
#define PCI_DEVICE_ID_BMID 0xf0d5
#define PCI_DEVICE_ID_ZSMB 0xf0e1
#define PCI_DEVICE_ID_ZMID 0xf0e5
#define PCI_DEVICE_ID_NEPTUNE 0xf0f5
#define PCI_DEVICE_ID_NEPTUNE_SCSP 0xf0f6
#define PCI_DEVICE_ID_NEPTUNE_DCSP 0xf0f7
#define PCI_DEVICE_ID_SUPERFLY 0xf700
#define PCI_DEVICE_ID_DRAGONFLY 0xf800
#define PCI_DEVICE_ID_CENTAUR 0xf900
#define PCI_DEVICE_ID_PEGASUS 0xf980
#define PCI_DEVICE_ID_THOR 0xfa00
#define PCI_DEVICE_ID_VIPER 0xfb00
#define PCI_DEVICE_ID_LP10000S 0xfc00
#define PCI_DEVICE_ID_LP11000S 0xfc10
#define PCI_DEVICE_ID_LPE11000S 0xfc20
#define PCI_DEVICE_ID_HELIOS 0xfd00
#define PCI_DEVICE_ID_BMID 0xf0d5
#define PCI_DEVICE_ID_BSMB 0xf0d1
#define PCI_DEVICE_ID_HELIOS_SCSP 0xfd11
#define PCI_DEVICE_ID_HELIOS_DCSP 0xfd12
#define PCI_DEVICE_ID_ZEPHYR 0xfe00
#define PCI_DEVICE_ID_ZMID 0xf0e5
#define PCI_DEVICE_ID_ZSMB 0xf0e1
#define PCI_DEVICE_ID_LP101 0xf0a1
#define PCI_DEVICE_ID_LP10000S 0xfc00
#define PCI_DEVICE_ID_ZEPHYR_SCSP 0xfe11
#define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12
#define PCI_SUBSYSTEM_ID_LP11000S 0xfc11
#define PCI_SUBSYSTEM_ID_LP11002S 0xfc12
#define PCI_SUBSYSTEM_ID_LPE11000S 0xfc21
#define PCI_SUBSYSTEM_ID_LPE11002S 0xfc22
#define PCI_SUBSYSTEM_ID_LPE11010S 0xfc2A
#define JEDEC_ID_ADDRESS 0x0080001c
#define FIREFLY_JEDEC_ID 0x1ACC
......
......@@ -126,34 +126,26 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
return -ERESTART;
}
/* The HBA's current state is provided by the ProgType and rr fields.
* Read and check the value of these fields before continuing to config
* this port.
/*
* The value of rr must be 1 since the driver set the cv field to 1.
* This setting requires the FW to set all revision fields.
*/
if (mb->un.varRdRev.rr == 0 || mb->un.varRdRev.un.b.ProgType != 2) {
/* Old firmware */
if (mb->un.varRdRev.rr == 0) {
vp->rev.rBit = 0;
lpfc_printf_log(phba,
KERN_ERR,
LOG_INIT,
"%d:0440 Adapter failed to init, mbxCmd x%x "
"READ_REV detected outdated firmware"
"Data: x%x\n",
phba->brd_no,
mb->mbxCommand, 0);
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"%d:0440 Adapter failed to init, READ_REV has "
"missing revision information.\n",
phba->brd_no);
mempool_free(pmb, phba->mbox_mem_pool);
return -ERESTART;
} else {
vp->rev.rBit = 1;
vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
memcpy(vp->rev.sli1FwName,
(char*)mb->un.varRdRev.sli1FwName, 16);
vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
memcpy(vp->rev.sli2FwName,
(char *)mb->un.varRdRev.sli2FwName, 16);
}
/* Save information as VPD data */
vp->rev.rBit = 1;
vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
memcpy(vp->rev.sli1FwName, (char*) mb->un.varRdRev.sli1FwName, 16);
vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
memcpy(vp->rev.sli2FwName, (char *) mb->un.varRdRev.sli2FwName, 16);
vp->rev.biuRev = mb->un.varRdRev.biuRev;
vp->rev.smRev = mb->un.varRdRev.smRev;
vp->rev.smFwRev = mb->un.varRdRev.un.smFwRev;
......@@ -378,6 +370,10 @@ lpfc_config_port_post(struct lpfc_hba * phba)
if (psli->num_rings > 3)
status |= HC_R3INT_ENA;
if ((phba->cfg_poll & ENABLE_FCP_RING_POLLING) &&
(phba->cfg_poll & DISABLE_FCP_RING_INT))
status &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
writel(status, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock_irq(phba->host->host_lock);
......@@ -571,6 +567,8 @@ lpfc_handle_latt(struct lpfc_hba * phba)
rc = -EIO;
/* Cleanup any outstanding ELS commands */
lpfc_els_flush_cmd(phba);
psli->slistat.link_event++;
lpfc_read_la(phba, pmb, mp);
......@@ -765,96 +763,139 @@ static void
lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
{
lpfc_vpd_t *vp;
uint32_t id;
uint8_t hdrtype;
char str[16];
uint16_t dev_id = phba->pcidev->device;
uint16_t dev_subid = phba->pcidev->subsystem_device;
uint8_t hdrtype = phba->pcidev->hdr_type;
char *model_str = "";
vp = &phba->vpd;
pci_read_config_dword(phba->pcidev, PCI_VENDOR_ID, &id);
pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
switch ((id >> 16) & 0xffff) {
switch (dev_id) {
case PCI_DEVICE_ID_FIREFLY:
strcpy(str, "LP6000 1");
model_str = "LP6000 1Gb PCI";
break;
case PCI_DEVICE_ID_SUPERFLY:
if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)
strcpy(str, "LP7000 1");
model_str = "LP7000 1Gb PCI";
else
strcpy(str, "LP7000E 1");
model_str = "LP7000E 1Gb PCI";
break;
case PCI_DEVICE_ID_DRAGONFLY:
strcpy(str, "LP8000 1");
model_str = "LP8000 1Gb PCI";
break;
case PCI_DEVICE_ID_CENTAUR:
if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)
strcpy(str, "LP9002 2");
model_str = "LP9002 2Gb PCI";
else
strcpy(str, "LP9000 1");
model_str = "LP9000 1Gb PCI";
break;
case PCI_DEVICE_ID_RFLY:
strcpy(str, "LP952 2");
model_str = "LP952 2Gb PCI";
break;
case PCI_DEVICE_ID_PEGASUS:
strcpy(str, "LP9802 2");
model_str = "LP9802 2Gb PCI-X";
break;
case PCI_DEVICE_ID_THOR:
if (hdrtype == 0x80)
strcpy(str, "LP10000DC 2");
model_str = "LP10000DC 2Gb 2-port PCI-X";
else
strcpy(str, "LP10000 2");
model_str = "LP10000 2Gb PCI-X";
break;
case PCI_DEVICE_ID_VIPER:
strcpy(str, "LPX1000 10");
model_str = "LPX1000 10Gb PCI-X";
break;
case PCI_DEVICE_ID_PFLY:
strcpy(str, "LP982 2");
model_str = "LP982 2Gb PCI-X";
break;
case PCI_DEVICE_ID_TFLY:
if (hdrtype == 0x80)
strcpy(str, "LP1050DC 2");
model_str = "LP1050DC 2Gb 2-port PCI-X";
else
strcpy(str, "LP1050 2");
model_str = "LP1050 2Gb PCI-X";
break;
case PCI_DEVICE_ID_HELIOS:
if (hdrtype == 0x80)
strcpy(str, "LP11002 4");
model_str = "LP11002 4Gb 2-port PCI-X2";
else
model_str = "LP11000 4Gb PCI-X2";
break;
case PCI_DEVICE_ID_HELIOS_SCSP:
model_str = "LP11000-SP 4Gb PCI-X2";
break;
case PCI_DEVICE_ID_HELIOS_DCSP:
model_str = "LP11002-SP 4Gb 2-port PCI-X2";
break;
case PCI_DEVICE_ID_NEPTUNE:
if (hdrtype == 0x80)
model_str = "LPe1002 4Gb 2-port";
else
strcpy(str, "LP11000 4");
model_str = "LPe1000 4Gb PCIe";
break;
case PCI_DEVICE_ID_NEPTUNE_SCSP:
model_str = "LPe1000-SP 4Gb PCIe";
break;
case PCI_DEVICE_ID_NEPTUNE_DCSP:
model_str = "LPe1002-SP 4Gb 2-port PCIe";
break;
case PCI_DEVICE_ID_BMID:
strcpy(str, "LP1150 4");
model_str = "LP1150 4Gb PCI-X2";
break;
case PCI_DEVICE_ID_BSMB:
strcpy(str, "LP111 4");
model_str = "LP111 4Gb PCI-X2";
break;
case PCI_DEVICE_ID_ZEPHYR:
if (hdrtype == 0x80)
strcpy(str, "LPe11002 4");
model_str = "LPe11002 4Gb 2-port PCIe";
else
strcpy(str, "LPe11000 4");
model_str = "LPe11000 4Gb PCIe";
break;
case PCI_DEVICE_ID_ZEPHYR_SCSP:
model_str = "LPe11000-SP 4Gb PCIe";
break;
case PCI_DEVICE_ID_ZEPHYR_DCSP:
model_str = "LPe11002-SP 4Gb 2-port PCIe";
break;
case PCI_DEVICE_ID_ZMID:
strcpy(str, "LPe1150 4");
model_str = "LPe1150 4Gb PCIe";
break;
case PCI_DEVICE_ID_ZSMB:
strcpy(str, "LPe111 4");
model_str = "LPe111 4Gb PCIe";
break;
case PCI_DEVICE_ID_LP101:
strcpy(str, "LP101 2");
model_str = "LP101 2Gb PCI-X";
break;
case PCI_DEVICE_ID_LP10000S:
strcpy(str, "LP10000-S 2");
model_str = "LP10000-S 2Gb PCI";
break;
case PCI_DEVICE_ID_LP11000S:
case PCI_DEVICE_ID_LPE11000S:
switch (dev_subid) {
case PCI_SUBSYSTEM_ID_LP11000S:
model_str = "LP11002-S 4Gb PCI-X2";
break;
case PCI_SUBSYSTEM_ID_LP11002S:
model_str = "LP11000-S 4Gb 2-port PCI-X2";
break;
case PCI_SUBSYSTEM_ID_LPE11000S:
model_str = "LPe11002-S 4Gb PCIe";
break;
case PCI_SUBSYSTEM_ID_LPE11002S:
model_str = "LPe11002-S 4Gb 2-port PCIe";
break;
case PCI_SUBSYSTEM_ID_LPE11010S:
model_str = "LPe11010-S 4Gb 10-port PCIe";
break;
default:
break;
}
break;
default:
memset(str, 0, 16);
break;
}
if (mdp)
sscanf(str, "%s", mdp);
sscanf(model_str, "%s", mdp);
if (descp)
sprintf(descp, "Emulex LightPulse %s Gigabit PCI Fibre "
"Channel Adapter", str);
sprintf(descp, "Emulex %s Fibre Channel Adapter", model_str);
}
/**************************************************/
......@@ -1196,6 +1237,7 @@ lpfc_stop_timer(struct lpfc_hba * phba)
}
}
del_timer_sync(&phba->fcp_poll_timer);
del_timer_sync(&phba->fc_estabtmo);
del_timer_sync(&phba->fc_disctmo);
del_timer_sync(&phba->fc_fdmitmo);
......@@ -1351,7 +1393,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_put_host;
host->unique_id = phba->brd_no;
init_MUTEX(&phba->hba_can_block);
INIT_LIST_HEAD(&phba->ctrspbuflist);
INIT_LIST_HEAD(&phba->rnidrspbuflist);
INIT_LIST_HEAD(&phba->freebufList);
......@@ -1375,6 +1417,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
psli->mbox_tmo.function = lpfc_mbox_timeout;
psli->mbox_tmo.data = (unsigned long)phba;
init_timer(&phba->fcp_poll_timer);
phba->fcp_poll_timer.function = lpfc_poll_timeout;
phba->fcp_poll_timer.data = (unsigned long)phba;
/*
* Get all the module params for configuring this host and then
* establish the host parameters.
......@@ -1489,6 +1535,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
host->max_cmd_len = 16;
/* Initialize the list of scsi buffers used by driver for scsi IO. */
spin_lock_init(&phba->scsi_buf_list_lock);
INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
host->transportt = lpfc_transport_template;
......@@ -1520,6 +1567,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
if (error)
goto out_free_irq;
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
spin_lock_irq(phba->host->host_lock);
lpfc_poll_start_timer(phba);
spin_unlock_irq(phba->host->host_lock);
}
/*
* set fixed host attributes
* Must done after lpfc_sli_hba_setup()
......@@ -1679,14 +1732,28 @@ static struct pci_device_id lpfc_id_table[] = {
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PFLY,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_SCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_DCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_SCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_DCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BMID,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BSMB,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_SCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_DCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZMID,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZSMB,
......@@ -1697,6 +1764,10 @@ static struct pci_device_id lpfc_id_table[] = {
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP10000S,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP11000S,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
PCI_ANY_ID, PCI_ANY_ID, },
{ 0 }
};
......
......@@ -55,55 +55,76 @@ lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
return (1);
}
int
lpfc_check_sparm(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, struct serv_parm * sp,
uint32_t class)
{
volatile struct serv_parm *hsp = &phba->fc_sparam;
/* First check for supported version */
/* Next check for class validity */
uint16_t hsp_value, ssp_value = 0;
/*
* The receive data field size and buffer-to-buffer receive data field
* size entries are 16 bits but are represented as two 8-bit fields in
* the driver data structure to account for rsvd bits and other control
* bits. Reconstruct and compare the fields as a 16-bit values before
* correcting the byte values.
*/
if (sp->cls1.classValid) {
if (sp->cls1.rcvDataSizeMsb > hsp->cls1.rcvDataSizeMsb)
sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
if (sp->cls1.rcvDataSizeLsb > hsp->cls1.rcvDataSizeLsb)
hsp_value = (hsp->cls1.rcvDataSizeMsb << 8) |
hsp->cls1.rcvDataSizeLsb;
ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
sp->cls1.rcvDataSizeLsb;
if (ssp_value > hsp_value) {
sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
}
} else if (class == CLASS1) {
return (0);
return 0;
}
if (sp->cls2.classValid) {
if (sp->cls2.rcvDataSizeMsb > hsp->cls2.rcvDataSizeMsb)
sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
if (sp->cls2.rcvDataSizeLsb > hsp->cls2.rcvDataSizeLsb)
hsp_value = (hsp->cls2.rcvDataSizeMsb << 8) |
hsp->cls2.rcvDataSizeLsb;
ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
sp->cls2.rcvDataSizeLsb;
if (ssp_value > hsp_value) {
sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
}
} else if (class == CLASS2) {
return (0);
return 0;
}
if (sp->cls3.classValid) {
if (sp->cls3.rcvDataSizeMsb > hsp->cls3.rcvDataSizeMsb)
sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
if (sp->cls3.rcvDataSizeLsb > hsp->cls3.rcvDataSizeLsb)
hsp_value = (hsp->cls3.rcvDataSizeMsb << 8) |
hsp->cls3.rcvDataSizeLsb;
ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
sp->cls3.rcvDataSizeLsb;
if (ssp_value > hsp_value) {
sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
}
} else if (class == CLASS3) {
return (0);
return 0;
}
if (sp->cmn.bbRcvSizeMsb > hsp->cmn.bbRcvSizeMsb)
sp->cmn.bbRcvSizeMsb = hsp->cmn.bbRcvSizeMsb;
if (sp->cmn.bbRcvSizeLsb > hsp->cmn.bbRcvSizeLsb)
/*
* Preserve the upper four bits of the MSB from the PLOGI response.
* These bits contain the Buffer-to-Buffer State Change Number
* from the target and need to be passed to the FW.
*/
hsp_value = (hsp->cmn.bbRcvSizeMsb << 8) | hsp->cmn.bbRcvSizeLsb;
ssp_value = (sp->cmn.bbRcvSizeMsb << 8) | sp->cmn.bbRcvSizeLsb;
if (ssp_value > hsp_value) {
sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb;
sp->cmn.bbRcvSizeMsb = (sp->cmn.bbRcvSizeMsb & 0xF0) |
(hsp->cmn.bbRcvSizeMsb & 0x0F);
}
/* If check is good, copy wwpn wwnn into ndlp */
memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
return (1);
return 1;
}
static void *
......
......@@ -41,6 +41,20 @@
#define LPFC_ABORT_WAIT 2
static inline void
lpfc_block_requests(struct lpfc_hba * phba)
{
down(&phba->hba_can_block);
scsi_block_requests(phba->host);
}
static inline void
lpfc_unblock_requests(struct lpfc_hba * phba)
{
scsi_unblock_requests(phba->host);
up(&phba->hba_can_block);
}
/*
* This routine allocates a scsi buffer, which contains all the necessary
* information needed to initiate a SCSI I/O. The non-DMAable buffer region
......@@ -137,18 +151,22 @@ lpfc_new_scsi_buf(struct lpfc_hba * phba)
}
struct lpfc_scsi_buf*
lpfc_sli_get_scsi_buf(struct lpfc_hba * phba)
lpfc_get_scsi_buf(struct lpfc_hba * phba)
{
struct lpfc_scsi_buf * lpfc_cmd = NULL;
struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
unsigned long iflag = 0;
spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
return lpfc_cmd;
}
static void
lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
{
unsigned long iflag = 0;
/*
* There are only two special cases to consider. (1) the scsi command
* requested scatter-gather usage or (2) the scsi command allocated
......@@ -166,8 +184,10 @@ lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
}
}
spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
psb->pCmd = NULL;
list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
}
static int
......@@ -389,7 +409,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
struct lpfc_nodelist *pnode = rdata->pnode;
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
unsigned long iflag;
int result;
struct scsi_device *sdev, *tmp_sdev;
int depth = 0;
lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
......@@ -441,11 +463,64 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
*lp, *(lp + 3), cmd->retries, cmd->resid);
}
result = cmd->result;
sdev = cmd->device;
cmd->scsi_done(cmd);
spin_lock_irqsave(phba->host->host_lock, iflag);
if (!result &&
((jiffies - pnode->last_ramp_up_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
((jiffies - pnode->last_q_full_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
(phba->cfg_lun_queue_depth > sdev->queue_depth)) {
shost_for_each_device(tmp_sdev, sdev->host) {
if (phba->cfg_lun_queue_depth > tmp_sdev->queue_depth) {
if (tmp_sdev->id != sdev->id)
continue;
if (tmp_sdev->ordered_tags)
scsi_adjust_queue_depth(tmp_sdev,
MSG_ORDERED_TAG,
tmp_sdev->queue_depth+1);
else
scsi_adjust_queue_depth(tmp_sdev,
MSG_SIMPLE_TAG,
tmp_sdev->queue_depth+1);
pnode->last_ramp_up_time = jiffies;
}
}
}
/*
* Check for queue full. If the lun is reporting queue full, then
* back off the lun queue depth to prevent target overloads.
*/
if (result == SAM_STAT_TASK_SET_FULL) {
pnode->last_q_full_time = jiffies;
shost_for_each_device(tmp_sdev, sdev->host) {
if (tmp_sdev->id != sdev->id)
continue;
depth = scsi_track_queue_full(tmp_sdev,
tmp_sdev->queue_depth - 1);
}
/*
* The queue depth cannot be lowered any more.
* Modify the returned error code to store
* the final depth value set by
* scsi_track_queue_full.
*/
if (depth == -1)
depth = sdev->host->cmd_per_lun;
if (depth) {
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
"%d:0711 detected queue full - lun queue depth "
" adjusted to %d.\n", phba->brd_no, depth);
}
}
lpfc_release_scsi_buf(phba, lpfc_cmd);
spin_unlock_irqrestore(phba->host->host_lock, iflag);
}
static void
......@@ -693,6 +768,37 @@ lpfc_info(struct Scsi_Host *host)
return lpfcinfobuf;
}
static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba)
{
unsigned long poll_tmo_expires =
(jiffies + msecs_to_jiffies(phba->cfg_poll_tmo));
if (phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt)
mod_timer(&phba->fcp_poll_timer,
poll_tmo_expires);
}
void lpfc_poll_start_timer(struct lpfc_hba * phba)
{
lpfc_poll_rearm_timer(phba);
}
void lpfc_poll_timeout(unsigned long ptr)
{
struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
unsigned long iflag;
spin_lock_irqsave(phba->host->host_lock, iflag);
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_poll_fcp_ring (phba);
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_poll_rearm_timer(phba);
}
spin_unlock_irqrestore(phba->host->host_lock, iflag);
}
static int
lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
{
......@@ -719,10 +825,11 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
goto out_fail_command;
}
lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
lpfc_cmd = lpfc_get_scsi_buf (phba);
if (lpfc_cmd == NULL) {
printk(KERN_WARNING "%s: No buffer available - list empty, "
"total count %d\n", __FUNCTION__, phba->total_scsi_bufs);
lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
"%d:0707 driver's buffer pool is empty, "
"IO busied\n", phba->brd_no);
goto out_host_busy;
}
......@@ -746,11 +853,17 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
&lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
if (err)
goto out_host_busy_free_buf;
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_poll_fcp_ring(phba);
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_poll_rearm_timer(phba);
}
return 0;
out_host_busy_free_buf:
lpfc_release_scsi_buf(phba, lpfc_cmd);
cmnd->host_scribble = NULL;
out_host_busy:
return SCSI_MLQUEUE_HOST_BUSY;
......@@ -759,11 +872,12 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
return 0;
}
static int
__lpfc_abort_handler(struct scsi_cmnd *cmnd)
lpfc_abort_handler(struct scsi_cmnd *cmnd)
{
struct lpfc_hba *phba =
(struct lpfc_hba *)cmnd->device->host->hostdata[0];
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
struct lpfc_iocbq *iocb;
struct lpfc_iocbq *abtsiocb;
......@@ -772,6 +886,8 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
unsigned int loop_count = 0;
int ret = SUCCESS;
lpfc_block_requests(phba);
spin_lock_irq(shost->host_lock);
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
BUG_ON(!lpfc_cmd);
......@@ -821,9 +937,15 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
goto out;
}
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_sli_poll_fcp_ring (phba);
/* Wait for abort to complete */
while (lpfc_cmd->pCmd == cmnd)
{
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_sli_poll_fcp_ring (phba);
spin_unlock_irq(phba->host->host_lock);
schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
......@@ -844,26 +966,19 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
out:
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
"%d:0749 SCSI layer issued abort device: ret %#x, "
"ID %d, LUN %d, snum %#lx\n",
"%d:0749 SCSI Layer I/O Abort Request "
"Status x%x ID %d LUN %d snum %#lx\n",
phba->brd_no, ret, cmnd->device->id,
cmnd->device->lun, cmnd->serial_number);
return ret;
}
spin_unlock_irq(shost->host_lock);
lpfc_unblock_requests(phba);
static int
lpfc_abort_handler(struct scsi_cmnd *cmnd)
{
int rc;
spin_lock_irq(cmnd->device->host->host_lock);
rc = __lpfc_abort_handler(cmnd);
spin_unlock_irq(cmnd->device->host->host_lock);
return rc;
return ret;
}
static int
__lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
......@@ -871,9 +986,12 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
struct lpfc_iocbq *iocbq, *iocbqrsp;
struct lpfc_rport_data *rdata = cmnd->device->hostdata;
struct lpfc_nodelist *pnode = rdata->pnode;
uint32_t cmd_result = 0, cmd_status = 0;
int ret = FAILED;
int cnt, loopcnt;
lpfc_block_requests(phba);
spin_lock_irq(shost->host_lock);
/*
* If target is not in a MAPPED state, delay the reset until
* target is rediscovered or nodev timeout expires.
......@@ -891,7 +1009,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
break;
}
lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
lpfc_cmd = lpfc_get_scsi_buf (phba);
if (lpfc_cmd == NULL)
goto out;
......@@ -916,26 +1034,28 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
if (ret == IOCB_SUCCESS)
ret = SUCCESS;
lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4];
lpfc_cmd->status = iocbqrsp->iocb.ulpStatus;
if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT)
if (lpfc_cmd->result & IOERR_DRVR_MASK)
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
cmd_result = iocbqrsp->iocb.un.ulpWord[4];
cmd_status = iocbqrsp->iocb.ulpStatus;
lpfc_sli_release_iocbq(phba, iocbqrsp);
lpfc_release_scsi_buf(phba, lpfc_cmd);
/*
* All outstanding txcmplq I/Os should have been aborted by the target.
* All outstanding txcmplq I/Os should have been aborted by the device.
* Unfortunately, some targets do not abide by this forcing the driver
* to double check.
*/
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
cmnd->device->id, cmnd->device->lun, 0,
LPFC_CTX_LUN);
cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
cmnd->device->id, cmnd->device->lun,
LPFC_CTX_LUN);
if (cnt)
lpfc_sli_abort_iocb(phba,
&phba->sli.ring[phba->sli.fcp_ring],
cmnd->device->id, cmnd->device->lun,
0, LPFC_CTX_LUN);
loopcnt = 0;
while((cnt = lpfc_sli_sum_iocb(phba,
&phba->sli.ring[phba->sli.fcp_ring],
cmnd->device->id, cmnd->device->lun,
LPFC_CTX_LUN))) {
while(cnt) {
spin_unlock_irq(phba->host->host_lock);
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
......@@ -943,6 +1063,11 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
if (++loopcnt
> (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT)
break;
cnt = lpfc_sli_sum_iocb(phba,
&phba->sli.ring[phba->sli.fcp_ring],
cmnd->device->id, cmnd->device->lun,
LPFC_CTX_LUN);
}
if (cnt) {
......@@ -952,35 +1077,21 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
ret = FAILED;
}
lpfc_sli_release_iocbq(phba, iocbqrsp);
out_free_scsi_buf:
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0713 SCSI layer issued LUN reset (%d, %d) "
"Data: x%x x%x x%x\n",
phba->brd_no, lpfc_cmd->pCmd->device->id,
lpfc_cmd->pCmd->device->lun, ret, lpfc_cmd->status,
lpfc_cmd->result);
lpfc_release_scsi_buf(phba, lpfc_cmd);
phba->brd_no, cmnd->device->id,cmnd->device->lun,
ret, cmd_status, cmd_result);
out:
spin_unlock_irq(shost->host_lock);
lpfc_unblock_requests(phba);
return ret;
}
static int
lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
{
int rc;
spin_lock_irq(cmnd->device->host->host_lock);
rc = __lpfc_reset_lun_handler(cmnd);
spin_unlock_irq(cmnd->device->host->host_lock);
return rc;
}
/*
* Note: midlayer calls this function with the host_lock held
*/
static int
__lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
......@@ -991,7 +1102,10 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
unsigned int midlayer_id = 0;
struct lpfc_scsi_buf * lpfc_cmd;
lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
lpfc_block_requests(phba);
spin_lock_irq(shost->host_lock);
lpfc_cmd = lpfc_get_scsi_buf(phba);
if (lpfc_cmd == NULL)
goto out;
......@@ -1022,18 +1136,31 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
lpfc_cmd->pCmd->device->hostdata = ndlp->rport->dd_data;
ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba);
if (ret != SUCCESS) {
lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0713 Bus Reset on target %d failed\n",
phba->brd_no, i);
err_count++;
}
}
if (err_count == 0)
ret = SUCCESS;
lpfc_release_scsi_buf(phba, lpfc_cmd);
/*
* All outstanding txcmplq I/Os should have been aborted by
* the targets. Unfortunately, some targets do not abide by
* this forcing the driver to double check.
*/
cmnd->device->id = midlayer_id;
cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
0, 0, LPFC_CTX_HOST);
if (cnt)
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
0, 0, 0, LPFC_CTX_HOST);
loopcnt = 0;
while((cnt = lpfc_sli_sum_iocb(phba,
&phba->sli.ring[phba->sli.fcp_ring],
0, 0, LPFC_CTX_HOST))) {
while(cnt) {
spin_unlock_irq(phba->host->host_lock);
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
......@@ -1041,44 +1168,30 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
if (++loopcnt
> (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT)
break;
cnt = lpfc_sli_sum_iocb(phba,
&phba->sli.ring[phba->sli.fcp_ring],
0, 0, LPFC_CTX_HOST);
}
if (cnt) {
/* flush all outstanding commands on the host */
i = lpfc_sli_abort_iocb(phba,
&phba->sli.ring[phba->sli.fcp_ring], 0, 0, 0,
LPFC_CTX_HOST);
lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0715 Bus Reset I/O flush failure: cnt x%x left x%x\n",
phba->brd_no, cnt, i);
}
if (cnt == 0)
ret = SUCCESS;
else
ret = FAILED;
}
lpfc_release_scsi_buf(phba, lpfc_cmd);
lpfc_printf_log(phba,
KERN_ERR,
LOG_FCP,
"%d:0714 SCSI layer issued Bus Reset Data: x%x\n",
phba->brd_no, ret);
out:
spin_unlock_irq(shost->host_lock);
lpfc_unblock_requests(phba);
return ret;
}
static int
lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
{
int rc;
spin_lock_irq(cmnd->device->host->host_lock);
rc = __lpfc_reset_bus_handler(cmnd);
spin_unlock_irq(cmnd->device->host->host_lock);
return rc;
}
static int
lpfc_slave_alloc(struct scsi_device *sdev)
{
......@@ -1127,10 +1240,10 @@ lpfc_slave_alloc(struct scsi_device *sdev)
break;
}
spin_lock_irqsave(phba->host->host_lock, flags);
spin_lock_irqsave(&phba->scsi_buf_list_lock, flags);
phba->total_scsi_bufs++;
list_add_tail(&scsi_buf->list, &phba->lpfc_scsi_buf_list);
spin_unlock_irqrestore(phba->host->host_lock, flags);
spin_unlock_irqrestore(&phba->scsi_buf_list_lock, flags);
}
return 0;
}
......@@ -1154,6 +1267,12 @@ lpfc_slave_configure(struct scsi_device *sdev)
*/
rport->dev_loss_tmo = phba->cfg_nodev_tmo + 5;
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_poll_fcp_ring(phba);
if (phba->cfg_poll & DISABLE_FCP_RING_INT)
lpfc_poll_rearm_timer(phba);
}
return 0;
}
......
......@@ -886,6 +886,182 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
return rc;
}
static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring)
{
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
/*
* Ring <ringno> handler: portRspPut <portRspPut> is bigger then
* rsp ring <portRspMax>
*/
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"%d:0312 Ring %d handler: portRspPut %d "
"is bigger then rsp ring %d\n",
phba->brd_no, pring->ringno,
le32_to_cpu(pgp->rspPutInx),
pring->numRiocb);
phba->hba_state = LPFC_HBA_ERROR;
/*
* All error attention handlers are posted to
* worker thread
*/
phba->work_ha |= HA_ERATT;
phba->work_hs = HS_FFER3;
if (phba->work_wait)
wake_up(phba->work_wait);
return;
}
void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
{
struct lpfc_sli * psli = &phba->sli;
struct lpfc_sli_ring * pring = &psli->ring[LPFC_FCP_RING];
IOCB_t *irsp = NULL;
IOCB_t *entry = NULL;
struct lpfc_iocbq *cmdiocbq = NULL;
struct lpfc_iocbq rspiocbq;
struct lpfc_pgp *pgp;
uint32_t status;
uint32_t portRspPut, portRspMax;
int type;
uint32_t rsp_cmpl = 0;
void __iomem *to_slim;
uint32_t ha_copy;
pring->stats.iocb_event++;
/* The driver assumes SLI-2 mode */
pgp = &phba->slim2p->mbx.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.
*/
portRspMax = pring->numRiocb;
portRspPut = le32_to_cpu(pgp->rspPutInx);
if (unlikely(portRspPut >= portRspMax)) {
lpfc_sli_rsp_pointers_error(phba, pring);
return;
}
rmb();
while (pring->rspidx != portRspPut) {
entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
if (++pring->rspidx >= portRspMax)
pring->rspidx = 0;
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++;
if (unlikely(irsp->ulpStatus)) {
/* Rsp ring <ringno> error: IOCB */
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
"%d:0326 Rsp Ring %d error: IOCB Data: "
"x%x x%x x%x x%x x%x x%x x%x x%x\n",
phba->brd_no, pring->ringno,
irsp->un.ulpWord[0],
irsp->un.ulpWord[1],
irsp->un.ulpWord[2],
irsp->un.ulpWord[3],
irsp->un.ulpWord[4],
irsp->un.ulpWord[5],
*(((uint32_t *) irsp) + 6),
*(((uint32_t *) irsp) + 7));
}
switch (type) {
case LPFC_ABORT_IOCB:
case LPFC_SOL_IOCB:
/*
* Idle exchange closed via ABTS from port. No iocb
* resources need to be recovered.
*/
if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) {
printk(KERN_INFO "%s: IOCB cmd 0x%x processed."
" Skipping completion\n", __FUNCTION__,
irsp->ulpCommand);
break;
}
cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
&rspiocbq);
if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
&rspiocbq);
}
break;
default:
if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
char adaptermsg[LPFC_MAX_ADPTMSG];
memset(adaptermsg, 0, LPFC_MAX_ADPTMSG);
memcpy(&adaptermsg[0], (uint8_t *) irsp,
MAX_MSG_DATA);
dev_warn(&((phba->pcidev)->dev), "lpfc%d: %s",
phba->brd_no, adaptermsg);
} else {
/* Unknown IOCB command */
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"%d:0321 Unknown IOCB command "
"Data: x%x, x%x x%x x%x x%x\n",
phba->brd_no, type,
irsp->ulpCommand,
irsp->ulpStatus,
irsp->ulpIoTag,
irsp->ulpContext);
}
break;
}
/*
* The response IOCB has been processed. Update the ring
* pointer in SLIM. If the port response put pointer has not
* been updated, sync the pgp->rspPutInx and fetch the new port
* response put pointer.
*/
to_slim = phba->MBslimaddr +
(SLIMOFF + (pring->ringno * 2) + 1) * 4;
writeb(pring->rspidx, to_slim);
if (pring->rspidx == portRspPut)
portRspPut = le32_to_cpu(pgp->rspPutInx);
}
ha_copy = readl(phba->HAregaddr);
ha_copy >>= (LPFC_FCP_RING * 4);
if ((rsp_cmpl > 0) && (ha_copy & HA_R0RE_REQ)) {
pring->stats.iocb_rsp_full++;
status = ((CA_R0ATT | CA_R0RE_RSP) << (LPFC_FCP_RING * 4));
writel(status, phba->CAregaddr);
readl(phba->CAregaddr);
}
if ((ha_copy & HA_R0CE_RSP) &&
(pring->flag & LPFC_CALL_RING_AVAILABLE)) {
pring->flag &= ~LPFC_CALL_RING_AVAILABLE;
pring->stats.iocb_cmd_empty++;
/* Force update of the local copy of cmdGetInx */
pring->local_getidx = le32_to_cpu(pgp->cmdGetInx);
lpfc_sli_resume_iocb(phba, pring);
if ((pring->lpfc_sli_cmd_available))
(pring->lpfc_sli_cmd_available) (phba, pring);
}
return;
}
/*
* This routine presumes LPFC_FCP_RING handling and doesn't bother
* to check it explicitly.
......@@ -917,24 +1093,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
portRspMax = pring->numRiocb;
portRspPut = le32_to_cpu(pgp->rspPutInx);
if (unlikely(portRspPut >= portRspMax)) {
/*
* Ring <ringno> handler: portRspPut <portRspPut> is bigger then
* rsp ring <portRspMax>
*/
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"%d:0312 Ring %d handler: portRspPut %d "
"is bigger then rsp ring %d\n",
phba->brd_no, pring->ringno, portRspPut,
portRspMax);
phba->hba_state = LPFC_HBA_ERROR;
/* All error attention handlers are posted to worker thread */
phba->work_ha |= HA_ERATT;
phba->work_hs = HS_FFER3;
if (phba->work_wait)
wake_up(phba->work_wait);
lpfc_sli_rsp_pointers_error(phba, pring);
spin_unlock_irqrestore(phba->host->host_lock, iflag);
return 1;
}
......@@ -947,6 +1106,10 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
* network byte order and pci byte orders are different.
*/
entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
if (++pring->rspidx >= portRspMax)
pring->rspidx = 0;
lpfc_sli_pcimem_bcopy((uint32_t *) entry,
(uint32_t *) &rspiocbq.iocb,
sizeof (IOCB_t));
......@@ -1020,9 +1183,6 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
* been updated, sync the pgp->rspPutInx and fetch the new port
* response put pointer.
*/
if (++pring->rspidx >= portRspMax)
pring->rspidx = 0;
to_slim = phba->MBslimaddr +
(SLIMOFF + (pring->ringno * 2) + 1) * 4;
writel(pring->rspidx, to_slim);
......@@ -2615,6 +2775,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
DECLARE_WAIT_QUEUE_HEAD(done_q);
long timeleft, timeout_req = 0;
int retval = IOCB_SUCCESS;
uint32_t creg_val;
/*
* If the caller has provided a response iocbq buffer, then context2
......@@ -2630,6 +2791,13 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
piocb->context_un.wait_queue = &done_q;
piocb->iocb_flag &= ~LPFC_IO_WAKE;
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
creg_val = readl(phba->HCregaddr);
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
writel(creg_val, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
}
retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0);
if (retval == IOCB_SUCCESS) {
timeout_req = timeout * HZ;
......@@ -2663,6 +2831,13 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
retval = IOCB_ERROR;
}
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
creg_val = readl(phba->HCregaddr);
creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
writel(creg_val, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
}
if (prspiocbq)
piocb->context2 = NULL;
......
......@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
#define LPFC_DRIVER_VERSION "8.1.0"
#define LPFC_DRIVER_VERSION "8.1.1"
#define LPFC_DRIVER_NAME "lpfc"
......
......@@ -2,7 +2,7 @@
*
* Linux MegaRAID device driver
*
* Copyright 2002 LSI Logic Corporation.
* Copyright (c) 2002 LSI Logic Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -17,7 +17,8 @@
* Copyright (c) 2003 Christoph Hellwig <hch@lst.de>
* - new-style, hotplug-aware pci probing and scsi registration
*
* Version : v2.00.3 (Feb 19, 2003) - Atul Mukker <Atul.Mukker@lsil.com>
* Version : v2.00.4 Mon Nov 14 14:02:43 EST 2005 - Seokmann Ju
* <Seokmann.Ju@lsil.com>
*
* Description: Linux device driver for LSI Logic MegaRAID controller
*
......@@ -51,10 +52,10 @@
#include "megaraid.h"
#define MEGARAID_MODULE_VERSION "2.00.3"
#define MEGARAID_MODULE_VERSION "2.00.4"
MODULE_AUTHOR ("LSI Logic Corporation");
MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
MODULE_AUTHOR ("sju@lsil.com");
MODULE_DESCRIPTION ("LSI Logic MegaRAID legacy driver");
MODULE_LICENSE ("GPL");
MODULE_VERSION(MEGARAID_MODULE_VERSION);
......@@ -4553,7 +4554,7 @@ mega_internal_done(Scsi_Cmnd *scmd)
static struct scsi_host_template megaraid_template = {
.module = THIS_MODULE,
.name = "MegaRAID",
.proc_name = "megaraid",
.proc_name = "megaraid_legacy",
.info = megaraid_info,
.queuecommand = megaraid_queue,
.bios_param = megaraid_biosparam,
......@@ -5037,22 +5038,12 @@ megaraid_shutdown(struct pci_dev *pdev)
}
static struct pci_device_id megaraid_pci_tbl[] = {
{PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DISCOVERY,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_PERC4_DI,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, BOARD_64BIT},
{PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_PERC4_QC_VERDE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, BOARD_64BIT},
{PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, megaraid_pci_tbl);
......@@ -5095,7 +5086,7 @@ static int __init megaraid_init(void)
* First argument (major) to register_chrdev implies a dynamic
* major number allocation.
*/
major = register_chrdev(0, "megadev", &megadev_fops);
major = register_chrdev(0, "megadev_legacy", &megadev_fops);
if (!major) {
printk(KERN_WARNING
"megaraid: failed to register char device\n");
......@@ -5109,7 +5100,7 @@ static void __exit megaraid_exit(void)
/*
* Unregister the character device interface to the driver.
*/
unregister_chrdev(major, "megadev");
unregister_chrdev(major, "megadev_legacy");
pci_unregister_driver(&megaraid_pci_driver);
......
......@@ -64,7 +64,6 @@ config MEGARAID_MAILBOX
To compile this driver as a module, choose M here: the
module will be called megaraid_mbox
if MEGARAID_NEWGEN=n
config MEGARAID_LEGACY
tristate "LSI Logic Legacy MegaRAID Driver"
depends on PCI && SCSI
......@@ -75,7 +74,6 @@ config MEGARAID_LEGACY
To compile this driver as a module, choose M here: the
module will be called megaraid
endif
config MEGARAID_SAS
tristate "LSI Logic MegaRAID SAS RAID Module"
......
......@@ -10,12 +10,13 @@
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_mbox.c
* Version : v2.20.4.6 (Mar 07 2005)
* Version : v2.20.4.7 (Nov 14 2005)
*
* Authors:
* Atul Mukker <Atul.Mukker@lsil.com>
* Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
* Manoj Jose <Manoj.Jose@lsil.com>
* Seokmann Ju <Seokmann.Ju@lsil.com>
*
* List of supported controllers
*
......@@ -136,7 +137,7 @@ static int wait_till_fw_empty(adapter_t *);
MODULE_AUTHOR("LSI Logic Corporation");
MODULE_AUTHOR("sju@lsil.com");
MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(MEGARAID_VERSION);
......@@ -278,68 +279,14 @@ static struct pci_device_id pci_id_table_g[] = {
{
PCI_VENDOR_ID_AMI,
PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_VENDOR_ID_DELL,
PCI_SUBSYS_ID_PERC3_QC,
},
{
PCI_VENDOR_ID_AMI,
PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_VENDOR_ID_DELL,
PCI_SUBSYS_ID_PERC3_DC,
},
{
PCI_VENDOR_ID_AMI,
PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_VENDOR_ID_DELL,
PCI_SUBSYS_ID_PERC3_SC,
},
{
PCI_VENDOR_ID_AMI,
PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_VENDOR_ID_AMI,
PCI_SUBSYS_ID_PERC3_SC,
},
{
PCI_VENDOR_ID_AMI,
PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_VENDOR_ID_AMI,
PCI_SUBSYS_ID_PERC3_DC,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_MEGARAID_SCSI_320_0,
PCI_VENDOR_ID_LSI_LOGIC,
PCI_SUBSYS_ID_MEGARAID_SCSI_320_0,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_MEGARAID_SCSI_320_1,
PCI_VENDOR_ID_LSI_LOGIC,
PCI_SUBSYS_ID_MEGARAID_SCSI_320_1,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_MEGARAID_SCSI_320_2,
PCI_VENDOR_ID_LSI_LOGIC,
PCI_SUBSYS_ID_MEGARAID_SCSI_320_2,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_MEGARAID_I4_133_RAID,
PCI_VENDOR_ID_LSI_LOGIC,
PCI_SUBSYS_ID_MEGARAID_I4_133_RAID,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_MEGARAID_SATA_150_4,
PCI_VENDOR_ID_LSI_LOGIC,
PCI_SUBSYS_ID_MEGARAID_SATA_150_4,
PCI_ANY_ID,
PCI_ANY_ID,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_MEGARAID_SATA_150_6,
PCI_VENDOR_ID_LSI_LOGIC,
PCI_SUBSYS_ID_MEGARAID_SATA_150_6,
PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_ANY_ID,
PCI_ANY_ID,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
......@@ -347,18 +294,6 @@ static struct pci_device_id pci_id_table_g[] = {
PCI_ANY_ID,
PCI_ANY_ID,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_INTEL_RAID_SRCS16,
PCI_VENDOR_ID_INTEL,
PCI_SUBSYS_ID_INTEL_RAID_SRCS16,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
PCI_VENDOR_ID_INTEL,
PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
},
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, pci_id_table_g);
......@@ -2985,6 +2920,7 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
for (i = 0; i < 0xFFFFF; i++) {
if (mbox->numstatus != 0xFF) break;
rmb();
}
if (i == 0xFFFFF) {
......
......@@ -21,8 +21,8 @@
#include "megaraid_ioctl.h"
#define MEGARAID_VERSION "2.20.4.6"
#define MEGARAID_EXT_VERSION "(Release Date: Mon Mar 07 12:27:22 EST 2005)"
#define MEGARAID_VERSION "2.20.4.7"
#define MEGARAID_EXT_VERSION "(Release Date: Mon Nov 14 12:27:22 EST 2005)"
/*
......
此差异已折叠。
此差异已折叠。
config SCSI_QLA2XXX
tristate
default (SCSI && PCI)
depends on SCSI && PCI
tristate "QLogic QLA2XXX Fibre Channel Support"
depends on PCI && SCSI
select SCSI_FC_ATTRS
select FW_LOADER
---help---
This qla2xxx driver supports all QLogic Fibre Channel
PCI and PCIe host adapters.
config SCSI_QLA21XX
tristate "QLogic ISP2100 host adapter family support"
By default, firmware for the ISP parts will be loaded
via the Firmware Loader interface.
ISP Firmware Filename
---------- -----------------
21xx ql2100_fw.bin
22xx ql2200_fw.bin
2300, 2312 ql2300_fw.bin
2322 ql2322_fw.bin
6312, 6322 ql6312_fw.bin
24xx ql2400_fw.bin
Upon request, the driver caches the firmware image until
the driver is unloaded.
NOTE: The original method of building firmware-loader
modules has been deprecated as the firmware-images will
be removed from the kernel sources.
config SCSI_QLA2XXX_EMBEDDED_FIRMWARE
bool " Use firmware-loader modules (DEPRECATED)"
depends on SCSI_QLA2XXX
select SCSI_FC_ATTRS
select FW_LOADER
config SCSI_QLA21XX
tristate " Build QLogic ISP2100 firmware-module"
depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 21xx (ISP2100) host adapter family.
config SCSI_QLA22XX
tristate "QLogic ISP2200 host adapter family support"
depends on SCSI_QLA2XXX
select SCSI_FC_ATTRS
select FW_LOADER
tristate " Build QLogic ISP2200 firmware-module"
depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 22xx (ISP2200) host adapter family.
config SCSI_QLA2300
tristate "QLogic ISP2300 host adapter family support"
depends on SCSI_QLA2XXX
select SCSI_FC_ATTRS
select FW_LOADER
tristate " Build QLogic ISP2300 firmware-module"
depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 2300 (ISP2300 and ISP2312) host
adapter family.
config SCSI_QLA2322
tristate "QLogic ISP2322 host adapter family support"
depends on SCSI_QLA2XXX
select SCSI_FC_ATTRS
select FW_LOADER
tristate " Build QLogic ISP2322 firmware-module"
depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 2322 (ISP2322) host adapter family.
config SCSI_QLA6312
tristate "QLogic ISP63xx host adapter family support"
depends on SCSI_QLA2XXX
select SCSI_FC_ATTRS
select FW_LOADER
tristate " Build QLogic ISP63xx firmware-module"
depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 63xx (ISP6312 and ISP6322) host
adapter family.
config SCSI_QLA24XX
tristate "QLogic ISP24xx host adapter family support"
depends on SCSI_QLA2XXX
select SCSI_FC_ATTRS
select FW_LOADER
tristate " Build QLogic ISP24xx firmware-module"
depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 24xx (ISP2422 and ISP2432) host
adapter family.
......@@ -3,15 +3,18 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME
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
obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx.o
qla2100-y := ql2100.o ql2100_fw.o
qla2200-y := ql2200.o ql2200_fw.o
qla2300-y := ql2300.o ql2300_fw.o
qla2322-y := ql2322.o ql2322_fw.o
qla6312-y := ql6312.o ql6312_fw.o
qla2400-y := ql2400.o ql2400_fw.o
obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o
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
obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2005 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "qla_def.h"
static char qla_driver_name[] = "qla2400";
extern uint32_t fw2400_version_str[];
extern uint32_t fw2400_addr01;
extern uint32_t fw2400_code01[];
extern uint32_t fw2400_length01;
extern uint32_t fw2400_addr02;
extern uint32_t fw2400_code02[];
extern uint32_t fw2400_length02;
static struct qla_fw_info qla_fw_tbl[] = {
{
.addressing = FW_INFO_ADDR_EXTENDED,
.fwcode = (unsigned short *)&fw2400_code01[0],
.fwlen = (unsigned short *)&fw2400_length01,
.lfwstart = (unsigned long *)&fw2400_addr01,
},
{
.addressing = FW_INFO_ADDR_EXTENDED,
.fwcode = (unsigned short *)&fw2400_code02[0],
.fwlen = (unsigned short *)&fw2400_length02,
.lfwstart = (unsigned long *)&fw2400_addr02,
},
{ FW_INFO_ADDR_NOMORE, },
};
static struct qla_board_info qla_board_tbl[] = {
{
.drv_name = qla_driver_name,
.isp_name = "ISP2422",
.fw_info = qla_fw_tbl,
.fw_fname = "ql2400_fw.bin",
},
{
.drv_name = qla_driver_name,
.isp_name = "ISP2432",
.fw_info = qla_fw_tbl,
.fw_fname = "ql2400_fw.bin",
},
};
static struct pci_device_id qla24xx_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, qla24xx_pci_tbl);
static int __devinit
qla24xx_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
qla24xx_remove_one(struct pci_dev *pdev)
{
qla2x00_remove_one(pdev);
}
static struct pci_driver qla24xx_pci_driver = {
.name = "qla2400",
.id_table = qla24xx_pci_tbl,
.probe = qla24xx_probe_one,
.remove = __devexit_p(qla24xx_remove_one),
};
static int __init
qla24xx_init(void)
{
return pci_module_init(&qla24xx_pci_driver);
}
static void __exit
qla24xx_exit(void)
{
pci_unregister_driver(&qla24xx_pci_driver);
}
module_init(qla24xx_init);
module_exit(qla24xx_exit);
MODULE_AUTHOR("QLogic Corporation");
MODULE_DESCRIPTION("QLogic ISP24xx FC-SCSI Host Bus Adapter driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(QLA2XXX_VERSION);
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册