Merge ../linux-2.6
This commit is contained in:
@@ -940,14 +940,8 @@ static void ahci_host_intr(struct ata_port *ap)
|
||||
return;
|
||||
|
||||
/* ignore interim PIO setup fis interrupts */
|
||||
if (ata_tag_valid(ap->active_tag)) {
|
||||
struct ata_queued_cmd *qc =
|
||||
ata_qc_from_tag(ap, ap->active_tag);
|
||||
|
||||
if (qc && qc->tf.protocol == ATA_PROT_PIO &&
|
||||
(status & PORT_IRQ_PIOS_FIS))
|
||||
return;
|
||||
}
|
||||
if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS))
|
||||
return;
|
||||
|
||||
if (ata_ratelimit())
|
||||
ata_port_printk(ap, KERN_INFO, "spurious interrupt "
|
||||
|
||||
@@ -14,6 +14,8 @@ LIBS= -ldb
|
||||
clean-files:= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) $(PROG)
|
||||
# Override default kernel CFLAGS. This is a userland app.
|
||||
AICASM_CFLAGS:= -I/usr/include -I.
|
||||
LEX= flex
|
||||
YACC= bison
|
||||
YFLAGS= -d
|
||||
|
||||
NOMAN= noman
|
||||
|
||||
@@ -69,6 +69,7 @@ comment "The following drivers are not fully supported"
|
||||
config SCSI_CUMANA_1
|
||||
tristate "CumanaSCSI I support (EXPERIMENTAL)"
|
||||
depends on ARCH_ACORN && EXPERIMENTAL && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
help
|
||||
This enables support for the Cumana SCSI I card. If you have an
|
||||
Acorn system with one of these, say Y. If unsure, say N.
|
||||
@@ -76,6 +77,7 @@ config SCSI_CUMANA_1
|
||||
config SCSI_ECOSCSI
|
||||
tristate "EcoScsi support (EXPERIMENTAL)"
|
||||
depends on ARCH_ACORN && EXPERIMENTAL && (ARCH_ARC || ARCH_A5K) && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
help
|
||||
This enables support for the EcoSCSI card -- a small card that sits
|
||||
in the Econet socket. If you have an Acorn system with one of these,
|
||||
@@ -84,6 +86,7 @@ config SCSI_ECOSCSI
|
||||
config SCSI_OAK1
|
||||
tristate "Oak SCSI support (EXPERIMENTAL)"
|
||||
depends on ARCH_ACORN && EXPERIMENTAL && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
help
|
||||
This enables support for the Oak SCSI card. If you have an Acorn
|
||||
system with one of these, say Y. If unsure, say N.
|
||||
|
||||
@@ -74,7 +74,7 @@ static inline void init_SCp(Scsi_Cmnd *SCpnt)
|
||||
unsigned long len = 0;
|
||||
int buf;
|
||||
|
||||
SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
|
||||
SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
|
||||
SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
|
||||
SCpnt->SCp.ptr = (char *)
|
||||
(page_address(SCpnt->SCp.buffer->page) +
|
||||
|
||||
@@ -390,7 +390,8 @@ static struct ata_port_info piix_port_info[] = {
|
||||
/* ich5_sata */
|
||||
{
|
||||
.sht = &piix_sht,
|
||||
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
|
||||
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR |
|
||||
PIIX_FLAG_IGNORE_PCS,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = 0x7f, /* udma0-6 */
|
||||
@@ -467,6 +468,11 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
static int force_pcs = 0;
|
||||
module_param(force_pcs, int, 0444);
|
||||
MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
|
||||
"device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)");
|
||||
|
||||
/**
|
||||
* piix_pata_cbl_detect - Probe host controller cable detect info
|
||||
* @ap: Port for which cable detect info is desired
|
||||
@@ -531,27 +537,25 @@ static void piix_pata_error_handler(struct ata_port *ap)
|
||||
}
|
||||
|
||||
/**
|
||||
* piix_sata_prereset - prereset for SATA host controller
|
||||
* piix_sata_present_mask - determine present mask for SATA host controller
|
||||
* @ap: Target port
|
||||
*
|
||||
* Reads and configures SATA PCI device's PCI config register
|
||||
* Port Configuration and Status (PCS) to determine port and
|
||||
* device availability. Return -ENODEV to skip reset if no
|
||||
* device is present.
|
||||
* Reads SATA PCI device's PCI config register Port Configuration
|
||||
* and Status (PCS) to determine port and device availability.
|
||||
*
|
||||
* LOCKING:
|
||||
* None (inherited from caller).
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 if device is present, -ENODEV otherwise.
|
||||
* determined present_mask
|
||||
*/
|
||||
static int piix_sata_prereset(struct ata_port *ap)
|
||||
static unsigned int piix_sata_present_mask(struct ata_port *ap)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
|
||||
struct piix_host_priv *hpriv = ap->host_set->private_data;
|
||||
const unsigned int *map = hpriv->map;
|
||||
int base = 2 * ap->hard_port_no;
|
||||
unsigned int present = 0;
|
||||
unsigned int present_mask = 0;
|
||||
int port, i;
|
||||
u16 pcs;
|
||||
|
||||
@@ -564,24 +568,52 @@ static int piix_sata_prereset(struct ata_port *ap)
|
||||
continue;
|
||||
if ((ap->flags & PIIX_FLAG_IGNORE_PCS) ||
|
||||
(pcs & 1 << (hpriv->map_db->present_shift + port)))
|
||||
present = 1;
|
||||
present_mask |= 1 << i;
|
||||
}
|
||||
|
||||
DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
|
||||
ap->id, pcs, present_mask);
|
||||
|
||||
if (!present) {
|
||||
ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n");
|
||||
ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
|
||||
return 0;
|
||||
return present_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* piix_sata_softreset - reset SATA host port via ATA SRST
|
||||
* @ap: port to reset
|
||||
* @classes: resulting classes of attached devices
|
||||
*
|
||||
* Reset SATA host port via ATA SRST. On controllers with
|
||||
* reliable PCS present bits, the bits are used to determine
|
||||
* device presence.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep)
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno otherwise.
|
||||
*/
|
||||
static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes)
|
||||
{
|
||||
unsigned int present_mask;
|
||||
int i, rc;
|
||||
|
||||
present_mask = piix_sata_present_mask(ap);
|
||||
|
||||
rc = ata_std_softreset(ap, classes);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < ATA_MAX_DEVICES; i++) {
|
||||
if (!(present_mask & (1 << i)))
|
||||
classes[i] = ATA_DEV_NONE;
|
||||
}
|
||||
|
||||
return ata_std_prereset(ap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void piix_sata_error_handler(struct ata_port *ap)
|
||||
{
|
||||
ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL,
|
||||
ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL,
|
||||
ata_std_postreset);
|
||||
}
|
||||
|
||||
@@ -785,6 +817,7 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
|
||||
}
|
||||
|
||||
static void __devinit piix_init_pcs(struct pci_dev *pdev,
|
||||
struct ata_port_info *pinfo,
|
||||
const struct piix_map_db *map_db)
|
||||
{
|
||||
u16 pcs, new_pcs;
|
||||
@@ -798,6 +831,18 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev,
|
||||
pci_write_config_word(pdev, ICH5_PCS, new_pcs);
|
||||
msleep(150);
|
||||
}
|
||||
|
||||
if (force_pcs == 1) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"force ignoring PCS (0x%x)\n", new_pcs);
|
||||
pinfo[0].host_flags |= PIIX_FLAG_IGNORE_PCS;
|
||||
pinfo[1].host_flags |= PIIX_FLAG_IGNORE_PCS;
|
||||
} else if (force_pcs == 2) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"force honoring PCS (0x%x)\n", new_pcs);
|
||||
pinfo[0].host_flags &= ~PIIX_FLAG_IGNORE_PCS;
|
||||
pinfo[1].host_flags &= ~PIIX_FLAG_IGNORE_PCS;
|
||||
}
|
||||
}
|
||||
|
||||
static void __devinit piix_init_sata_map(struct pci_dev *pdev,
|
||||
@@ -828,6 +873,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
|
||||
case IDE:
|
||||
WARN_ON((i & 1) || map[i + 1] != IDE);
|
||||
pinfo[i / 2] = piix_port_info[ich5_pata];
|
||||
pinfo[i / 2].private_data = hpriv;
|
||||
i++;
|
||||
printk(" IDE IDE");
|
||||
break;
|
||||
@@ -905,7 +951,8 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (host_flags & ATA_FLAG_SATA) {
|
||||
piix_init_sata_map(pdev, port_info,
|
||||
piix_map_db_table[ent->driver_data]);
|
||||
piix_init_pcs(pdev, piix_map_db_table[ent->driver_data]);
|
||||
piix_init_pcs(pdev, port_info,
|
||||
piix_map_db_table[ent->driver_data]);
|
||||
}
|
||||
|
||||
/* On ICH5, some BIOSen disable the interrupt using the
|
||||
|
||||
@@ -1146,7 +1146,7 @@ static struct sbus_dev sun4_esp_dev;
|
||||
static int __init esp_sun4_probe(struct scsi_host_template *tpnt)
|
||||
{
|
||||
if (sun4_esp_physaddr) {
|
||||
memset(&sun4_esp_dev, 0, sizeof(esp_dev));
|
||||
memset(&sun4_esp_dev, 0, sizeof(sun4_esp_dev));
|
||||
sun4_esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
|
||||
sun4_esp_dev.irqs[0] = 4;
|
||||
sun4_esp_dev.resource[0].start = sun4_esp_physaddr;
|
||||
@@ -1162,6 +1162,7 @@ static int __init esp_sun4_probe(struct scsi_host_template *tpnt)
|
||||
|
||||
static int __devexit esp_sun4_remove(void)
|
||||
{
|
||||
struct of_device *dev = &sun4_esp_dev.ofdev;
|
||||
struct esp *esp = dev_get_drvdata(&dev->dev);
|
||||
|
||||
return esp_remove_common(esp);
|
||||
|
||||
@@ -44,10 +44,6 @@ static char driver_name[] = "hptiop";
|
||||
static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver";
|
||||
static const char driver_ver[] = "v1.0 (060426)";
|
||||
|
||||
static DEFINE_SPINLOCK(hptiop_hba_list_lock);
|
||||
static LIST_HEAD(hptiop_hba_list);
|
||||
static int hptiop_cdev_major = -1;
|
||||
|
||||
static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag);
|
||||
static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag);
|
||||
static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg);
|
||||
@@ -576,7 +572,7 @@ static int hptiop_reset_hba(struct hptiop_hba *hba)
|
||||
if (atomic_xchg(&hba->resetting, 1) == 0) {
|
||||
atomic_inc(&hba->reset_count);
|
||||
writel(IOPMU_INBOUND_MSG0_RESET,
|
||||
&hba->iop->outbound_msgaddr0);
|
||||
&hba->iop->inbound_msgaddr0);
|
||||
hptiop_pci_posting_flush(hba->iop);
|
||||
}
|
||||
|
||||
@@ -619,532 +615,11 @@ static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
|
||||
return queue_depth;
|
||||
}
|
||||
|
||||
struct hptiop_getinfo {
|
||||
char __user *buffer;
|
||||
loff_t buflength;
|
||||
loff_t bufoffset;
|
||||
loff_t buffillen;
|
||||
loff_t filpos;
|
||||
};
|
||||
|
||||
static void hptiop_copy_mem_info(struct hptiop_getinfo *pinfo,
|
||||
char *data, int datalen)
|
||||
{
|
||||
if (pinfo->filpos < pinfo->bufoffset) {
|
||||
if (pinfo->filpos + datalen <= pinfo->bufoffset) {
|
||||
pinfo->filpos += datalen;
|
||||
return;
|
||||
} else {
|
||||
data += (pinfo->bufoffset - pinfo->filpos);
|
||||
datalen -= (pinfo->bufoffset - pinfo->filpos);
|
||||
pinfo->filpos = pinfo->bufoffset;
|
||||
}
|
||||
}
|
||||
|
||||
pinfo->filpos += datalen;
|
||||
if (pinfo->buffillen == pinfo->buflength)
|
||||
return;
|
||||
|
||||
if (pinfo->buflength - pinfo->buffillen < datalen)
|
||||
datalen = pinfo->buflength - pinfo->buffillen;
|
||||
|
||||
if (copy_to_user(pinfo->buffer + pinfo->buffillen, data, datalen))
|
||||
return;
|
||||
|
||||
pinfo->buffillen += datalen;
|
||||
}
|
||||
|
||||
static int hptiop_copy_info(struct hptiop_getinfo *pinfo, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[128];
|
||||
int len;
|
||||
|
||||
va_start(args, fmt);
|
||||
len = vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
hptiop_copy_mem_info(pinfo, buf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static void hptiop_ioctl_done(struct hpt_ioctl_k *arg)
|
||||
{
|
||||
arg->done = NULL;
|
||||
wake_up(&arg->hba->ioctl_wq);
|
||||
}
|
||||
|
||||
static void hptiop_do_ioctl(struct hpt_ioctl_k *arg)
|
||||
{
|
||||
struct hptiop_hba *hba = arg->hba;
|
||||
u32 val;
|
||||
struct hpt_iop_request_ioctl_command __iomem *req;
|
||||
int ioctl_retry = 0;
|
||||
|
||||
dprintk("scsi%d: hptiop_do_ioctl\n", hba->host->host_no);
|
||||
|
||||
/*
|
||||
* check (in + out) buff size from application.
|
||||
* outbuf must be dword aligned.
|
||||
*/
|
||||
if (((arg->inbuf_size + 3) & ~3) + arg->outbuf_size >
|
||||
hba->max_request_size
|
||||
- sizeof(struct hpt_iop_request_header)
|
||||
- 4 * sizeof(u32)) {
|
||||
dprintk("scsi%d: ioctl buf size (%d/%d) is too large\n",
|
||||
hba->host->host_no,
|
||||
arg->inbuf_size, arg->outbuf_size);
|
||||
arg->result = HPT_IOCTL_RESULT_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
retry:
|
||||
spin_lock_irq(hba->host->host_lock);
|
||||
|
||||
val = readl(&hba->iop->inbound_queue);
|
||||
if (val == IOPMU_QUEUE_EMPTY) {
|
||||
spin_unlock_irq(hba->host->host_lock);
|
||||
dprintk("scsi%d: no free req for ioctl\n", hba->host->host_no);
|
||||
arg->result = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
req = (struct hpt_iop_request_ioctl_command __iomem *)
|
||||
((unsigned long)hba->iop + val);
|
||||
|
||||
writel(HPT_CTL_CODE_LINUX_TO_IOP(arg->ioctl_code),
|
||||
&req->ioctl_code);
|
||||
writel(arg->inbuf_size, &req->inbuf_size);
|
||||
writel(arg->outbuf_size, &req->outbuf_size);
|
||||
|
||||
/*
|
||||
* use the buffer on the IOP local memory first, then copy it
|
||||
* back to host.
|
||||
* the caller's request buffer shoudl be little-endian.
|
||||
*/
|
||||
if (arg->inbuf_size)
|
||||
memcpy_toio(req->buf, arg->inbuf, arg->inbuf_size);
|
||||
|
||||
/* correct the controller ID for IOP */
|
||||
if ((arg->ioctl_code == HPT_IOCTL_GET_CHANNEL_INFO ||
|
||||
arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO_V2 ||
|
||||
arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO)
|
||||
&& arg->inbuf_size >= sizeof(u32))
|
||||
writel(0, req->buf);
|
||||
|
||||
writel(IOP_REQUEST_TYPE_IOCTL_COMMAND, &req->header.type);
|
||||
writel(0, &req->header.flags);
|
||||
writel(offsetof(struct hpt_iop_request_ioctl_command, buf)
|
||||
+ arg->inbuf_size, &req->header.size);
|
||||
writel((u32)(unsigned long)arg, &req->header.context);
|
||||
writel(BITS_PER_LONG > 32 ? (u32)((unsigned long)arg>>32) : 0,
|
||||
&req->header.context_hi32);
|
||||
writel(IOP_RESULT_PENDING, &req->header.result);
|
||||
|
||||
arg->result = HPT_IOCTL_RESULT_FAILED;
|
||||
arg->done = hptiop_ioctl_done;
|
||||
|
||||
writel(val, &hba->iop->inbound_queue);
|
||||
hptiop_pci_posting_flush(hba->iop);
|
||||
|
||||
spin_unlock_irq(hba->host->host_lock);
|
||||
|
||||
wait_event_timeout(hba->ioctl_wq, arg->done == NULL, 60 * HZ);
|
||||
|
||||
if (arg->done != NULL) {
|
||||
hptiop_reset_hba(hba);
|
||||
if (ioctl_retry++ < 3)
|
||||
goto retry;
|
||||
}
|
||||
|
||||
dprintk("hpt_iop_ioctl %x result %d\n",
|
||||
arg->ioctl_code, arg->result);
|
||||
}
|
||||
|
||||
static int __hpt_do_ioctl(struct hptiop_hba *hba, u32 code, void *inbuf,
|
||||
u32 insize, void *outbuf, u32 outsize)
|
||||
{
|
||||
struct hpt_ioctl_k arg;
|
||||
arg.hba = hba;
|
||||
arg.ioctl_code = code;
|
||||
arg.inbuf = inbuf;
|
||||
arg.outbuf = outbuf;
|
||||
arg.inbuf_size = insize;
|
||||
arg.outbuf_size = outsize;
|
||||
arg.bytes_returned = NULL;
|
||||
hptiop_do_ioctl(&arg);
|
||||
return arg.result;
|
||||
}
|
||||
|
||||
static inline int hpt_id_valid(__le32 id)
|
||||
{
|
||||
return id != 0 && id != cpu_to_le32(0xffffffff);
|
||||
}
|
||||
|
||||
static int hptiop_get_controller_info(struct hptiop_hba *hba,
|
||||
struct hpt_controller_info *pinfo)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CONTROLLER_INFO,
|
||||
&id, sizeof(int), pinfo, sizeof(*pinfo));
|
||||
}
|
||||
|
||||
|
||||
static int hptiop_get_channel_info(struct hptiop_hba *hba, int bus,
|
||||
struct hpt_channel_info *pinfo)
|
||||
{
|
||||
u32 ids[2];
|
||||
|
||||
ids[0] = 0;
|
||||
ids[1] = bus;
|
||||
return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CHANNEL_INFO,
|
||||
ids, sizeof(ids), pinfo, sizeof(*pinfo));
|
||||
|
||||
}
|
||||
|
||||
static int hptiop_get_logical_devices(struct hptiop_hba *hba,
|
||||
__le32 *pids, int maxcount)
|
||||
{
|
||||
int i;
|
||||
u32 count = maxcount - 1;
|
||||
|
||||
if (__hpt_do_ioctl(hba, HPT_IOCTL_GET_LOGICAL_DEVICES,
|
||||
&count, sizeof(u32),
|
||||
pids, sizeof(u32) * maxcount))
|
||||
return -1;
|
||||
|
||||
maxcount = le32_to_cpu(pids[0]);
|
||||
for (i = 0; i < maxcount; i++)
|
||||
pids[i] = pids[i+1];
|
||||
|
||||
return maxcount;
|
||||
}
|
||||
|
||||
static int hptiop_get_device_info_v3(struct hptiop_hba *hba, __le32 id,
|
||||
struct hpt_logical_device_info_v3 *pinfo)
|
||||
{
|
||||
return __hpt_do_ioctl(hba, HPT_IOCTL_GET_DEVICE_INFO_V3,
|
||||
&id, sizeof(u32),
|
||||
pinfo, sizeof(*pinfo));
|
||||
}
|
||||
|
||||
static const char *get_array_status(struct hpt_logical_device_info_v3 *devinfo)
|
||||
{
|
||||
static char s[64];
|
||||
u32 flags = le32_to_cpu(devinfo->u.array.flags);
|
||||
u32 trans_prog = le32_to_cpu(devinfo->u.array.transforming_progress);
|
||||
u32 reb_prog = le32_to_cpu(devinfo->u.array.rebuilding_progress);
|
||||
|
||||
if (flags & ARRAY_FLAG_DISABLED)
|
||||
return "Disabled";
|
||||
else if (flags & ARRAY_FLAG_TRANSFORMING)
|
||||
sprintf(s, "Expanding/Migrating %d.%d%%%s%s",
|
||||
trans_prog / 100,
|
||||
trans_prog % 100,
|
||||
(flags & (ARRAY_FLAG_NEEDBUILDING|ARRAY_FLAG_BROKEN))?
|
||||
", Critical" : "",
|
||||
((flags & ARRAY_FLAG_NEEDINITIALIZING) &&
|
||||
!(flags & ARRAY_FLAG_REBUILDING) &&
|
||||
!(flags & ARRAY_FLAG_INITIALIZING))?
|
||||
", Unintialized" : "");
|
||||
else if ((flags & ARRAY_FLAG_BROKEN) &&
|
||||
devinfo->u.array.array_type != AT_RAID6)
|
||||
return "Critical";
|
||||
else if (flags & ARRAY_FLAG_REBUILDING)
|
||||
sprintf(s,
|
||||
(flags & ARRAY_FLAG_NEEDINITIALIZING)?
|
||||
"%sBackground initializing %d.%d%%" :
|
||||
"%sRebuilding %d.%d%%",
|
||||
(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
|
||||
reb_prog / 100,
|
||||
reb_prog % 100);
|
||||
else if (flags & ARRAY_FLAG_VERIFYING)
|
||||
sprintf(s, "%sVerifying %d.%d%%",
|
||||
(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
|
||||
reb_prog / 100,
|
||||
reb_prog % 100);
|
||||
else if (flags & ARRAY_FLAG_INITIALIZING)
|
||||
sprintf(s, "%sForground initializing %d.%d%%",
|
||||
(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
|
||||
reb_prog / 100,
|
||||
reb_prog % 100);
|
||||
else if (flags & ARRAY_FLAG_NEEDTRANSFORM)
|
||||
sprintf(s,"%s%s%s", "Need Expanding/Migrating",
|
||||
(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
|
||||
((flags & ARRAY_FLAG_NEEDINITIALIZING) &&
|
||||
!(flags & ARRAY_FLAG_REBUILDING) &&
|
||||
!(flags & ARRAY_FLAG_INITIALIZING))?
|
||||
", Unintialized" : "");
|
||||
else if (flags & ARRAY_FLAG_NEEDINITIALIZING &&
|
||||
!(flags & ARRAY_FLAG_REBUILDING) &&
|
||||
!(flags & ARRAY_FLAG_INITIALIZING))
|
||||
sprintf(s,"%sUninitialized",
|
||||
(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "");
|
||||
else if ((flags & ARRAY_FLAG_NEEDBUILDING) ||
|
||||
(flags & ARRAY_FLAG_BROKEN))
|
||||
return "Critical";
|
||||
else
|
||||
return "Normal";
|
||||
return s;
|
||||
}
|
||||
|
||||
static void hptiop_dump_devinfo(struct hptiop_hba *hba,
|
||||
struct hptiop_getinfo *pinfo, __le32 id, int indent)
|
||||
{
|
||||
struct hpt_logical_device_info_v3 devinfo;
|
||||
int i;
|
||||
u64 capacity;
|
||||
|
||||
for (i = 0; i < indent; i++)
|
||||
hptiop_copy_info(pinfo, "\t");
|
||||
|
||||
if (hptiop_get_device_info_v3(hba, id, &devinfo)) {
|
||||
hptiop_copy_info(pinfo, "unknown\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (devinfo.type) {
|
||||
|
||||
case LDT_DEVICE: {
|
||||
struct hd_driveid *driveid;
|
||||
u32 flags = le32_to_cpu(devinfo.u.device.flags);
|
||||
|
||||
driveid = (struct hd_driveid *)devinfo.u.device.ident;
|
||||
/* model[] is 40 chars long, but we just want 20 chars here */
|
||||
driveid->model[20] = 0;
|
||||
|
||||
if (indent)
|
||||
if (flags & DEVICE_FLAG_DISABLED)
|
||||
hptiop_copy_info(pinfo,"Missing\n");
|
||||
else
|
||||
hptiop_copy_info(pinfo, "CH%d %s\n",
|
||||
devinfo.u.device.path_id + 1,
|
||||
driveid->model);
|
||||
else {
|
||||
capacity = le64_to_cpu(devinfo.capacity) * 512;
|
||||
do_div(capacity, 1000000);
|
||||
hptiop_copy_info(pinfo,
|
||||
"CH%d %s, %lluMB, %s %s%s%s%s\n",
|
||||
devinfo.u.device.path_id + 1,
|
||||
driveid->model,
|
||||
capacity,
|
||||
(flags & DEVICE_FLAG_DISABLED)?
|
||||
"Disabled" : "Normal",
|
||||
devinfo.u.device.read_ahead_enabled?
|
||||
"[RA]" : "",
|
||||
devinfo.u.device.write_cache_enabled?
|
||||
"[WC]" : "",
|
||||
devinfo.u.device.TCQ_enabled?
|
||||
"[TCQ]" : "",
|
||||
devinfo.u.device.NCQ_enabled?
|
||||
"[NCQ]" : ""
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LDT_ARRAY:
|
||||
if (devinfo.target_id != INVALID_TARGET_ID)
|
||||
hptiop_copy_info(pinfo, "[DISK %d_%d] ",
|
||||
devinfo.vbus_id, devinfo.target_id);
|
||||
|
||||
capacity = le64_to_cpu(devinfo.capacity) * 512;
|
||||
do_div(capacity, 1000000);
|
||||
hptiop_copy_info(pinfo, "%s (%s), %lluMB, %s\n",
|
||||
devinfo.u.array.name,
|
||||
devinfo.u.array.array_type==AT_RAID0? "RAID0" :
|
||||
devinfo.u.array.array_type==AT_RAID1? "RAID1" :
|
||||
devinfo.u.array.array_type==AT_RAID5? "RAID5" :
|
||||
devinfo.u.array.array_type==AT_RAID6? "RAID6" :
|
||||
devinfo.u.array.array_type==AT_JBOD? "JBOD" :
|
||||
"unknown",
|
||||
capacity,
|
||||
get_array_status(&devinfo));
|
||||
for (i = 0; i < devinfo.u.array.ndisk; i++) {
|
||||
if (hpt_id_valid(devinfo.u.array.members[i])) {
|
||||
if (cpu_to_le16(1<<i) &
|
||||
devinfo.u.array.critical_members)
|
||||
hptiop_copy_info(pinfo, "\t*");
|
||||
hptiop_dump_devinfo(hba, pinfo,
|
||||
devinfo.u.array.members[i], indent+1);
|
||||
}
|
||||
else
|
||||
hptiop_copy_info(pinfo, "\tMissing\n");
|
||||
}
|
||||
if (id == devinfo.u.array.transform_source) {
|
||||
hptiop_copy_info(pinfo, "\tExpanding/Migrating to:\n");
|
||||
hptiop_dump_devinfo(hba, pinfo,
|
||||
devinfo.u.array.transform_target, indent+1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t hptiop_show_version(struct class_device *class_dev, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", driver_ver);
|
||||
}
|
||||
|
||||
static ssize_t hptiop_cdev_read(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hptiop_hba *hba = filp->private_data;
|
||||
struct hptiop_getinfo info;
|
||||
int i, j, ndev;
|
||||
struct hpt_controller_info con_info;
|
||||
struct hpt_channel_info chan_info;
|
||||
__le32 ids[32];
|
||||
|
||||
info.buffer = buf;
|
||||
info.buflength = count;
|
||||
info.bufoffset = ppos ? *ppos : 0;
|
||||
info.filpos = 0;
|
||||
info.buffillen = 0;
|
||||
|
||||
if (hptiop_get_controller_info(hba, &con_info))
|
||||
return -EIO;
|
||||
|
||||
for (i = 0; i < con_info.num_buses; i++) {
|
||||
if (hptiop_get_channel_info(hba, i, &chan_info) == 0) {
|
||||
if (hpt_id_valid(chan_info.devices[0]))
|
||||
hptiop_dump_devinfo(hba, &info,
|
||||
chan_info.devices[0], 0);
|
||||
if (hpt_id_valid(chan_info.devices[1]))
|
||||
hptiop_dump_devinfo(hba, &info,
|
||||
chan_info.devices[1], 0);
|
||||
}
|
||||
}
|
||||
|
||||
ndev = hptiop_get_logical_devices(hba, ids,
|
||||
sizeof(ids) / sizeof(ids[0]));
|
||||
|
||||
/*
|
||||
* if hptiop_get_logical_devices fails, ndev==-1 and it just
|
||||
* output nothing here
|
||||
*/
|
||||
for (j = 0; j < ndev; j++)
|
||||
hptiop_dump_devinfo(hba, &info, ids[j], 0);
|
||||
|
||||
if (ppos)
|
||||
*ppos += info.buffillen;
|
||||
|
||||
return info.buffillen;
|
||||
}
|
||||
|
||||
static int hptiop_cdev_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct hptiop_hba *hba = file->private_data;
|
||||
struct hpt_ioctl_u ioctl_u;
|
||||
struct hpt_ioctl_k ioctl_k;
|
||||
u32 bytes_returned;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (copy_from_user(&ioctl_u,
|
||||
(void __user *)arg, sizeof(struct hpt_ioctl_u)))
|
||||
return -EINVAL;
|
||||
|
||||
if (ioctl_u.magic != HPT_IOCTL_MAGIC)
|
||||
return -EINVAL;
|
||||
|
||||
ioctl_k.ioctl_code = ioctl_u.ioctl_code;
|
||||
ioctl_k.inbuf = NULL;
|
||||
ioctl_k.inbuf_size = ioctl_u.inbuf_size;
|
||||
ioctl_k.outbuf = NULL;
|
||||
ioctl_k.outbuf_size = ioctl_u.outbuf_size;
|
||||
ioctl_k.hba = hba;
|
||||
ioctl_k.bytes_returned = &bytes_returned;
|
||||
|
||||
/* verify user buffer */
|
||||
if ((ioctl_k.inbuf_size && !access_ok(VERIFY_READ,
|
||||
ioctl_u.inbuf, ioctl_k.inbuf_size)) ||
|
||||
(ioctl_k.outbuf_size && !access_ok(VERIFY_WRITE,
|
||||
ioctl_u.outbuf, ioctl_k.outbuf_size)) ||
|
||||
(ioctl_u.bytes_returned && !access_ok(VERIFY_WRITE,
|
||||
ioctl_u.bytes_returned, sizeof(u32))) ||
|
||||
ioctl_k.inbuf_size + ioctl_k.outbuf_size > 0x10000) {
|
||||
|
||||
dprintk("scsi%d: got bad user address\n", hba->host->host_no);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* map buffer to kernel. */
|
||||
if (ioctl_k.inbuf_size) {
|
||||
ioctl_k.inbuf = kmalloc(ioctl_k.inbuf_size, GFP_KERNEL);
|
||||
if (!ioctl_k.inbuf) {
|
||||
dprintk("scsi%d: fail to alloc inbuf\n",
|
||||
hba->host->host_no);
|
||||
err = -ENOMEM;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (copy_from_user(ioctl_k.inbuf,
|
||||
ioctl_u.inbuf, ioctl_k.inbuf_size)) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl_k.outbuf_size) {
|
||||
ioctl_k.outbuf = kmalloc(ioctl_k.outbuf_size, GFP_KERNEL);
|
||||
if (!ioctl_k.outbuf) {
|
||||
dprintk("scsi%d: fail to alloc outbuf\n",
|
||||
hba->host->host_no);
|
||||
err = -ENOMEM;
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
||||
hptiop_do_ioctl(&ioctl_k);
|
||||
|
||||
if (ioctl_k.result == HPT_IOCTL_RESULT_OK) {
|
||||
if (ioctl_k.outbuf_size &&
|
||||
copy_to_user(ioctl_u.outbuf,
|
||||
ioctl_k.outbuf, ioctl_k.outbuf_size))
|
||||
goto err_exit;
|
||||
|
||||
if (ioctl_u.bytes_returned &&
|
||||
copy_to_user(ioctl_u.bytes_returned,
|
||||
&bytes_returned, sizeof(u32)))
|
||||
goto err_exit;
|
||||
|
||||
err = 0;
|
||||
}
|
||||
|
||||
err_exit:
|
||||
kfree(ioctl_k.inbuf);
|
||||
kfree(ioctl_k.outbuf);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hptiop_cdev_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct hptiop_hba *hba;
|
||||
unsigned i = 0, minor = iminor(inode);
|
||||
int ret = -ENODEV;
|
||||
|
||||
spin_lock(&hptiop_hba_list_lock);
|
||||
list_for_each_entry(hba, &hptiop_hba_list, link) {
|
||||
if (i == minor) {
|
||||
file->private_data = hba;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock(&hptiop_hba_list_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct file_operations hptiop_cdev_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = hptiop_cdev_read,
|
||||
.ioctl = hptiop_cdev_ioctl,
|
||||
.open = hptiop_cdev_open,
|
||||
};
|
||||
|
||||
static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(class_dev);
|
||||
@@ -1295,19 +770,13 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
|
||||
goto unmap_pci_bar;
|
||||
}
|
||||
|
||||
if (scsi_add_host(host, &pcidev->dev)) {
|
||||
printk(KERN_ERR "scsi%d: scsi_add_host failed\n",
|
||||
hba->host->host_no);
|
||||
goto unmap_pci_bar;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pcidev, host);
|
||||
|
||||
if (request_irq(pcidev->irq, hptiop_intr, IRQF_SHARED,
|
||||
driver_name, hba)) {
|
||||
printk(KERN_ERR "scsi%d: request irq %d failed\n",
|
||||
hba->host->host_no, pcidev->irq);
|
||||
goto remove_scsi_host;
|
||||
goto unmap_pci_bar;
|
||||
}
|
||||
|
||||
/* Allocate request mem */
|
||||
@@ -1354,9 +823,12 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
|
||||
if (hptiop_initialize_iop(hba))
|
||||
goto free_request_mem;
|
||||
|
||||
spin_lock(&hptiop_hba_list_lock);
|
||||
list_add_tail(&hba->link, &hptiop_hba_list);
|
||||
spin_unlock(&hptiop_hba_list_lock);
|
||||
if (scsi_add_host(host, &pcidev->dev)) {
|
||||
printk(KERN_ERR "scsi%d: scsi_add_host failed\n",
|
||||
hba->host->host_no);
|
||||
goto free_request_mem;
|
||||
}
|
||||
|
||||
|
||||
scsi_scan_host(host);
|
||||
|
||||
@@ -1371,9 +843,6 @@ free_request_mem:
|
||||
free_request_irq:
|
||||
free_irq(hba->pcidev->irq, hba);
|
||||
|
||||
remove_scsi_host:
|
||||
scsi_remove_host(host);
|
||||
|
||||
unmap_pci_bar:
|
||||
iounmap(hba->iop);
|
||||
|
||||
@@ -1421,10 +890,6 @@ static void hptiop_remove(struct pci_dev *pcidev)
|
||||
|
||||
scsi_remove_host(host);
|
||||
|
||||
spin_lock(&hptiop_hba_list_lock);
|
||||
list_del_init(&hba->link);
|
||||
spin_unlock(&hptiop_hba_list_lock);
|
||||
|
||||
hptiop_shutdown(pcidev);
|
||||
|
||||
free_irq(hba->pcidev->irq, hba);
|
||||
@@ -1461,27 +926,12 @@ static struct pci_driver hptiop_pci_driver = {
|
||||
|
||||
static int __init hptiop_module_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
printk(KERN_INFO "%s %s\n", driver_name_long, driver_ver);
|
||||
|
||||
error = pci_register_driver(&hptiop_pci_driver);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
hptiop_cdev_major = register_chrdev(0, "hptiop", &hptiop_cdev_fops);
|
||||
if (hptiop_cdev_major < 0) {
|
||||
printk(KERN_WARNING "unable to register hptiop device.\n");
|
||||
return hptiop_cdev_major;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return pci_register_driver(&hptiop_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit hptiop_module_exit(void)
|
||||
{
|
||||
dprintk("hptiop_module_exit\n");
|
||||
unregister_chrdev(hptiop_cdev_major, "hptiop");
|
||||
pci_unregister_driver(&hptiop_pci_driver);
|
||||
}
|
||||
|
||||
|
||||
@@ -517,7 +517,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
|
||||
/* No more interrupts */
|
||||
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
|
||||
printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
|
||||
local_irq_enable();
|
||||
local_irq_enable_in_hardirq();
|
||||
if (status.b.check)
|
||||
rq->errors++;
|
||||
idescsi_end_request (drive, 1, 0);
|
||||
|
||||
@@ -43,13 +43,10 @@
|
||||
|
||||
#include "iscsi_tcp.h"
|
||||
|
||||
#define ISCSI_TCP_VERSION "1.0-595"
|
||||
|
||||
MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, "
|
||||
"Alex Aizman <itn780@yahoo.com>");
|
||||
MODULE_DESCRIPTION("iSCSI/TCP data-path");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(ISCSI_TCP_VERSION);
|
||||
/* #define DEBUG_TCP */
|
||||
#define DEBUG_ASSERT
|
||||
|
||||
@@ -185,11 +182,19 @@ iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn)
|
||||
* must be called with session lock
|
||||
*/
|
||||
static void
|
||||
__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
|
||||
iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
|
||||
{
|
||||
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
|
||||
struct iscsi_r2t_info *r2t;
|
||||
struct scsi_cmnd *sc;
|
||||
|
||||
/* flush ctask's r2t queues */
|
||||
while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
|
||||
__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
|
||||
sizeof(void*));
|
||||
debug_scsi("iscsi_tcp_cleanup_ctask pending r2t dropped\n");
|
||||
}
|
||||
|
||||
sc = ctask->sc;
|
||||
if (unlikely(!sc))
|
||||
return;
|
||||
@@ -374,6 +379,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
|
||||
spin_unlock(&session->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
|
||||
BUG_ON(!rc);
|
||||
|
||||
@@ -399,7 +405,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
|
||||
tcp_ctask->exp_r2tsn = r2tsn + 1;
|
||||
tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
|
||||
__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
|
||||
__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
|
||||
list_move_tail(&ctask->running, &conn->xmitqueue);
|
||||
|
||||
scsi_queue_work(session->host, &conn->xmitwork);
|
||||
conn->r2t_pdus_cnt++;
|
||||
@@ -477,6 +483,8 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
|
||||
case ISCSI_OP_SCSI_DATA_IN:
|
||||
tcp_conn->in.ctask = session->cmds[itt];
|
||||
rc = iscsi_data_rsp(conn, tcp_conn->in.ctask);
|
||||
if (rc)
|
||||
return rc;
|
||||
/* fall through */
|
||||
case ISCSI_OP_SCSI_CMD_RSP:
|
||||
tcp_conn->in.ctask = session->cmds[itt];
|
||||
@@ -484,7 +492,7 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
|
||||
goto copy_hdr;
|
||||
|
||||
spin_lock(&session->lock);
|
||||
__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
|
||||
iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
|
||||
rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
|
||||
spin_unlock(&session->lock);
|
||||
break;
|
||||
@@ -500,13 +508,28 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
|
||||
break;
|
||||
case ISCSI_OP_LOGIN_RSP:
|
||||
case ISCSI_OP_TEXT_RSP:
|
||||
case ISCSI_OP_LOGOUT_RSP:
|
||||
case ISCSI_OP_NOOP_IN:
|
||||
case ISCSI_OP_REJECT:
|
||||
case ISCSI_OP_ASYNC_EVENT:
|
||||
/*
|
||||
* It is possible that we could get a PDU with a buffer larger
|
||||
* than 8K, but there are no targets that currently do this.
|
||||
* For now we fail until we find a vendor that needs it
|
||||
*/
|
||||
if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH <
|
||||
tcp_conn->in.datalen) {
|
||||
printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
|
||||
"but conn buffer is only %u (opcode %0x)\n",
|
||||
tcp_conn->in.datalen,
|
||||
DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode);
|
||||
rc = ISCSI_ERR_PROTO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tcp_conn->in.datalen)
|
||||
goto copy_hdr;
|
||||
/* fall through */
|
||||
case ISCSI_OP_LOGOUT_RSP:
|
||||
case ISCSI_OP_NOOP_IN:
|
||||
case ISCSI_OP_SCSI_TMFUNC_RSP:
|
||||
rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
|
||||
break;
|
||||
@@ -523,7 +546,7 @@ copy_hdr:
|
||||
* skbs to complete the command then we have to copy the header
|
||||
* for later use
|
||||
*/
|
||||
if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <
|
||||
if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <=
|
||||
(tcp_conn->in.datalen + tcp_conn->in.padding +
|
||||
(conn->datadgst_en ? 4 : 0))) {
|
||||
debug_tcp("Copying header for later use. in.copy %d in.datalen"
|
||||
@@ -614,9 +637,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask,
|
||||
* byte counters.
|
||||
**/
|
||||
static inline int
|
||||
iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn)
|
||||
iscsi_tcp_copy(struct iscsi_conn *conn)
|
||||
{
|
||||
void *buf = tcp_conn->data;
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
int buf_size = tcp_conn->in.datalen;
|
||||
int buf_left = buf_size - tcp_conn->data_copied;
|
||||
int size = min(tcp_conn->in.copy, buf_left);
|
||||
@@ -627,7 +650,7 @@ iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn)
|
||||
BUG_ON(size <= 0);
|
||||
|
||||
rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
|
||||
(char*)buf + tcp_conn->data_copied, size);
|
||||
(char*)conn->data + tcp_conn->data_copied, size);
|
||||
BUG_ON(rc);
|
||||
|
||||
tcp_conn->in.offset += size;
|
||||
@@ -745,10 +768,11 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
|
||||
done:
|
||||
/* check for non-exceptional status */
|
||||
if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) {
|
||||
debug_scsi("done [sc %lx res %d itt 0x%x]\n",
|
||||
(long)sc, sc->result, ctask->itt);
|
||||
debug_scsi("done [sc %lx res %d itt 0x%x flags 0x%x]\n",
|
||||
(long)sc, sc->result, ctask->itt,
|
||||
tcp_conn->in.hdr->flags);
|
||||
spin_lock(&conn->session->lock);
|
||||
__iscsi_ctask_cleanup(conn, ctask);
|
||||
iscsi_tcp_cleanup_ctask(conn, ctask);
|
||||
__iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
|
||||
spin_unlock(&conn->session->lock);
|
||||
}
|
||||
@@ -769,26 +793,25 @@ iscsi_data_recv(struct iscsi_conn *conn)
|
||||
break;
|
||||
case ISCSI_OP_SCSI_CMD_RSP:
|
||||
spin_lock(&conn->session->lock);
|
||||
__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
|
||||
iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
|
||||
spin_unlock(&conn->session->lock);
|
||||
case ISCSI_OP_TEXT_RSP:
|
||||
case ISCSI_OP_LOGIN_RSP:
|
||||
case ISCSI_OP_NOOP_IN:
|
||||
case ISCSI_OP_ASYNC_EVENT:
|
||||
case ISCSI_OP_REJECT:
|
||||
/*
|
||||
* Collect data segment to the connection's data
|
||||
* placeholder
|
||||
*/
|
||||
if (iscsi_tcp_copy(tcp_conn)) {
|
||||
if (iscsi_tcp_copy(conn)) {
|
||||
rc = -EAGAIN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data,
|
||||
rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, conn->data,
|
||||
tcp_conn->in.datalen);
|
||||
if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP)
|
||||
iscsi_recv_digest_update(tcp_conn, tcp_conn->data,
|
||||
iscsi_recv_digest_update(tcp_conn, conn->data,
|
||||
tcp_conn->in.datalen);
|
||||
break;
|
||||
default:
|
||||
@@ -843,7 +866,7 @@ more:
|
||||
if (rc == -EAGAIN)
|
||||
goto nomore;
|
||||
else {
|
||||
iscsi_conn_failure(conn, rc);
|
||||
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -897,7 +920,7 @@ more:
|
||||
if (rc) {
|
||||
if (rc == -EAGAIN)
|
||||
goto again;
|
||||
iscsi_conn_failure(conn, rc);
|
||||
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
|
||||
return 0;
|
||||
}
|
||||
tcp_conn->in.copy -= tcp_conn->in.padding;
|
||||
@@ -1028,9 +1051,8 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn)
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
|
||||
iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn)
|
||||
{
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
struct sock *sk = tcp_conn->sock->sk;
|
||||
|
||||
/* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
|
||||
@@ -1308,7 +1330,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
|
||||
ctask->imm_count -
|
||||
ctask->unsol_count;
|
||||
|
||||
debug_scsi("cmd [itt %x total %d imm %d imm_data %d "
|
||||
debug_scsi("cmd [itt 0x%x total %d imm %d imm_data %d "
|
||||
"r2t_data %d]\n",
|
||||
ctask->itt, ctask->total_length, ctask->imm_count,
|
||||
ctask->unsol_count, tcp_ctask->r2t_data_count);
|
||||
@@ -1636,7 +1658,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
|
||||
}
|
||||
solicit_again:
|
||||
/*
|
||||
* send Data-Out whitnin this R2T sequence.
|
||||
* send Data-Out within this R2T sequence.
|
||||
*/
|
||||
if (!r2t->data_count)
|
||||
goto data_out_done;
|
||||
@@ -1731,7 +1753,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
|
||||
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
struct iscsi_data_task *dtask = tcp_ctask->dtask;
|
||||
int sent, rc;
|
||||
int sent = 0, rc;
|
||||
|
||||
tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
|
||||
iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
|
||||
@@ -1900,26 +1922,31 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
|
||||
tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
|
||||
/* initial operational parameters */
|
||||
tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
|
||||
tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||
|
||||
/* allocate initial PDU receive place holder */
|
||||
if (tcp_conn->data_size <= PAGE_SIZE)
|
||||
tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL);
|
||||
else
|
||||
tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL,
|
||||
get_order(tcp_conn->data_size));
|
||||
if (!tcp_conn->data)
|
||||
goto max_recv_dlenght_alloc_fail;
|
||||
|
||||
return cls_conn;
|
||||
|
||||
max_recv_dlenght_alloc_fail:
|
||||
kfree(tcp_conn);
|
||||
tcp_conn_alloc_fail:
|
||||
iscsi_conn_teardown(cls_conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_tcp_release_conn(struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
|
||||
if (!tcp_conn->sock)
|
||||
return;
|
||||
|
||||
sock_hold(tcp_conn->sock->sk);
|
||||
iscsi_conn_restore_callbacks(tcp_conn);
|
||||
sock_put(tcp_conn->sock->sk);
|
||||
|
||||
sock_release(tcp_conn->sock);
|
||||
tcp_conn->sock = NULL;
|
||||
conn->recv_lock = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
|
||||
{
|
||||
@@ -1930,6 +1957,7 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
|
||||
if (conn->hdrdgst_en || conn->datadgst_en)
|
||||
digest = 1;
|
||||
|
||||
iscsi_tcp_release_conn(conn);
|
||||
iscsi_conn_teardown(cls_conn);
|
||||
|
||||
/* now free tcp_conn */
|
||||
@@ -1944,15 +1972,18 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
|
||||
crypto_free_tfm(tcp_conn->data_rx_tfm);
|
||||
}
|
||||
|
||||
/* free conn->data, size = MaxRecvDataSegmentLength */
|
||||
if (tcp_conn->data_size <= PAGE_SIZE)
|
||||
kfree(tcp_conn->data);
|
||||
else
|
||||
free_pages((unsigned long)tcp_conn->data,
|
||||
get_order(tcp_conn->data_size));
|
||||
kfree(tcp_conn);
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
|
||||
{
|
||||
struct iscsi_conn *conn = cls_conn->dd_data;
|
||||
|
||||
iscsi_conn_stop(cls_conn, flag);
|
||||
iscsi_tcp_release_conn(conn);
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
|
||||
@@ -2001,52 +2032,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
|
||||
{
|
||||
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
|
||||
struct iscsi_r2t_info *r2t;
|
||||
|
||||
/* flush ctask's r2t queues */
|
||||
while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)))
|
||||
__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
|
||||
sizeof(void*));
|
||||
|
||||
__iscsi_ctask_cleanup(conn, ctask);
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
struct sock *sk;
|
||||
|
||||
if (!tcp_conn->sock)
|
||||
return;
|
||||
|
||||
sk = tcp_conn->sock->sk;
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_tcp_terminate_conn(struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
|
||||
if (!tcp_conn->sock)
|
||||
return;
|
||||
|
||||
sock_hold(tcp_conn->sock->sk);
|
||||
iscsi_conn_restore_callbacks(conn);
|
||||
sock_put(tcp_conn->sock->sk);
|
||||
|
||||
sock_release(tcp_conn->sock);
|
||||
tcp_conn->sock = NULL;
|
||||
conn->recv_lock = NULL;
|
||||
}
|
||||
|
||||
/* called with host lock */
|
||||
static void
|
||||
iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
|
||||
@@ -2057,6 +2042,7 @@ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
|
||||
iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
|
||||
sizeof(struct iscsi_hdr));
|
||||
tcp_mtask->xmstate = XMSTATE_IMM_HDR;
|
||||
tcp_mtask->sent = 0;
|
||||
|
||||
if (mtask->data_count)
|
||||
iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
|
||||
@@ -2138,39 +2124,6 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
|
||||
int value;
|
||||
|
||||
switch(param) {
|
||||
case ISCSI_PARAM_MAX_RECV_DLENGTH: {
|
||||
char *saveptr = tcp_conn->data;
|
||||
gfp_t flags = GFP_KERNEL;
|
||||
|
||||
sscanf(buf, "%d", &value);
|
||||
if (tcp_conn->data_size >= value) {
|
||||
iscsi_set_param(cls_conn, param, buf, buflen);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_bh(&session->lock);
|
||||
if (conn->stop_stage == STOP_CONN_RECOVER)
|
||||
flags = GFP_ATOMIC;
|
||||
spin_unlock_bh(&session->lock);
|
||||
|
||||
if (value <= PAGE_SIZE)
|
||||
tcp_conn->data = kmalloc(value, flags);
|
||||
else
|
||||
tcp_conn->data = (void*)__get_free_pages(flags,
|
||||
get_order(value));
|
||||
if (tcp_conn->data == NULL) {
|
||||
tcp_conn->data = saveptr;
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (tcp_conn->data_size <= PAGE_SIZE)
|
||||
kfree(saveptr);
|
||||
else
|
||||
free_pages((unsigned long)saveptr,
|
||||
get_order(tcp_conn->data_size));
|
||||
iscsi_set_param(cls_conn, param, buf, buflen);
|
||||
tcp_conn->data_size = value;
|
||||
break;
|
||||
}
|
||||
case ISCSI_PARAM_HDRDGST_EN:
|
||||
iscsi_set_param(cls_conn, param, buf, buflen);
|
||||
tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
|
||||
@@ -2361,8 +2314,7 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
|
||||
}
|
||||
|
||||
static struct scsi_host_template iscsi_sht = {
|
||||
.name = "iSCSI Initiator over TCP/IP, v"
|
||||
ISCSI_TCP_VERSION,
|
||||
.name = "iSCSI Initiator over TCP/IP",
|
||||
.queuecommand = iscsi_queuecommand,
|
||||
.change_queue_depth = iscsi_change_queue_depth,
|
||||
.can_queue = ISCSI_XMIT_CMDS_MAX - 1,
|
||||
@@ -2414,10 +2366,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
|
||||
.get_conn_param = iscsi_tcp_conn_get_param,
|
||||
.get_session_param = iscsi_session_get_param,
|
||||
.start_conn = iscsi_conn_start,
|
||||
.stop_conn = iscsi_conn_stop,
|
||||
/* these are called as part of conn recovery */
|
||||
.suspend_conn_recv = iscsi_tcp_suspend_conn_rx,
|
||||
.terminate_conn = iscsi_tcp_terminate_conn,
|
||||
.stop_conn = iscsi_tcp_conn_stop,
|
||||
/* IO */
|
||||
.send_pdu = iscsi_conn_send_pdu,
|
||||
.get_stats = iscsi_conn_get_stats,
|
||||
|
||||
@@ -78,8 +78,6 @@ struct iscsi_tcp_conn {
|
||||
char hdrext[4*sizeof(__u16) +
|
||||
sizeof(__u32)];
|
||||
int data_copied;
|
||||
char *data; /* data placeholder */
|
||||
int data_size; /* actual recv_dlength */
|
||||
int stop_stage; /* conn_stop() flag: *
|
||||
* stop to recover, *
|
||||
* stop to terminate */
|
||||
|
||||
@@ -2746,7 +2746,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
|
||||
if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
|
||||
return rc;
|
||||
|
||||
scontrol = (scontrol & 0x0f0) | 0x302;
|
||||
scontrol = (scontrol & 0x0f0) | 0x304;
|
||||
|
||||
if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
|
||||
return rc;
|
||||
@@ -5185,28 +5185,6 @@ void ata_host_stop (struct ata_host_set *host_set)
|
||||
iounmap(host_set->mmio_base);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_host_remove - Unregister SCSI host structure with upper layers
|
||||
* @ap: Port to unregister
|
||||
* @do_unregister: 1 if we fully unregister, 0 to just stop the port
|
||||
*
|
||||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
|
||||
static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
|
||||
{
|
||||
struct Scsi_Host *sh = ap->host;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
if (do_unregister)
|
||||
scsi_remove_host(sh);
|
||||
|
||||
ap->ops->port_stop(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_init - Initialize an ata_device structure
|
||||
* @dev: Device structure to initialize
|
||||
@@ -5532,8 +5510,11 @@ int ata_device_add(const struct ata_probe_ent *ent)
|
||||
|
||||
err_out:
|
||||
for (i = 0; i < count; i++) {
|
||||
ata_host_remove(host_set->ports[i], 1);
|
||||
scsi_host_put(host_set->ports[i]->host);
|
||||
struct ata_port *ap = host_set->ports[i];
|
||||
if (ap) {
|
||||
ap->ops->port_stop(ap);
|
||||
scsi_host_put(ap->host);
|
||||
}
|
||||
}
|
||||
err_free_ret:
|
||||
kfree(host_set);
|
||||
@@ -5558,7 +5539,7 @@ void ata_port_detach(struct ata_port *ap)
|
||||
int i;
|
||||
|
||||
if (!ap->ops->error_handler)
|
||||
return;
|
||||
goto skip_eh;
|
||||
|
||||
/* tell EH we're leaving & flush EH */
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
@@ -5594,6 +5575,7 @@ void ata_port_detach(struct ata_port *ap)
|
||||
cancel_delayed_work(&ap->hotplug_task);
|
||||
flush_workqueue(ata_aux_wq);
|
||||
|
||||
skip_eh:
|
||||
/* remove the associated SCSI host */
|
||||
scsi_remove_host(ap->host);
|
||||
}
|
||||
@@ -5662,7 +5644,7 @@ int ata_scsi_release(struct Scsi_Host *host)
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
ap->ops->port_disable(ap);
|
||||
ata_host_remove(ap, 0);
|
||||
ap->ops->port_stop(ap);
|
||||
|
||||
DPRINTK("EXIT\n");
|
||||
return 1;
|
||||
|
||||
@@ -763,12 +763,27 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
|
||||
unsigned int action)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct ata_eh_info *ehi = &ap->eh_info;
|
||||
struct ata_eh_context *ehc = &ap->eh_context;
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
ata_eh_clear_action(dev, &ap->eh_info, action);
|
||||
/* Reset is represented by combination of actions and EHI
|
||||
* flags. Suck in all related bits before clearing eh_info to
|
||||
* avoid losing requested action.
|
||||
*/
|
||||
if (action & ATA_EH_RESET_MASK) {
|
||||
ehc->i.action |= ehi->action & ATA_EH_RESET_MASK;
|
||||
ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
|
||||
|
||||
if (!(ap->eh_context.i.flags & ATA_EHI_QUIET))
|
||||
/* make sure all reset actions are cleared & clear EHI flags */
|
||||
action |= ATA_EH_RESET_MASK;
|
||||
ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
|
||||
}
|
||||
|
||||
ata_eh_clear_action(dev, ehi, action);
|
||||
|
||||
if (!(ehc->i.flags & ATA_EHI_QUIET))
|
||||
ap->pflags |= ATA_PFLAG_RECOVERED;
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
@@ -789,6 +804,12 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
|
||||
static void ata_eh_done(struct ata_port *ap, struct ata_device *dev,
|
||||
unsigned int action)
|
||||
{
|
||||
/* if reset is complete, clear all reset actions & reset modifier */
|
||||
if (action & ATA_EH_RESET_MASK) {
|
||||
action |= ATA_EH_RESET_MASK;
|
||||
ap->eh_context.i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
|
||||
}
|
||||
|
||||
ata_eh_clear_action(dev, &ap->eh_context.i, action);
|
||||
}
|
||||
|
||||
@@ -1275,8 +1296,6 @@ static int ata_eh_speed_down(struct ata_device *dev, int is_io,
|
||||
static void ata_eh_autopsy(struct ata_port *ap)
|
||||
{
|
||||
struct ata_eh_context *ehc = &ap->eh_context;
|
||||
unsigned int action = ehc->i.action;
|
||||
struct ata_device *failed_dev = NULL;
|
||||
unsigned int all_err_mask = 0;
|
||||
int tag, is_io = 0;
|
||||
u32 serror;
|
||||
@@ -1293,7 +1312,7 @@ static void ata_eh_autopsy(struct ata_port *ap)
|
||||
ehc->i.serror |= serror;
|
||||
ata_eh_analyze_serror(ap);
|
||||
} else if (rc != -EOPNOTSUPP)
|
||||
action |= ATA_EH_HARDRESET;
|
||||
ehc->i.action |= ATA_EH_HARDRESET;
|
||||
|
||||
/* analyze NCQ failure */
|
||||
ata_eh_analyze_ncq_error(ap);
|
||||
@@ -1314,7 +1333,7 @@ static void ata_eh_autopsy(struct ata_port *ap)
|
||||
qc->err_mask |= ehc->i.err_mask;
|
||||
|
||||
/* analyze TF */
|
||||
action |= ata_eh_analyze_tf(qc, &qc->result_tf);
|
||||
ehc->i.action |= ata_eh_analyze_tf(qc, &qc->result_tf);
|
||||
|
||||
/* DEV errors are probably spurious in case of ATA_BUS error */
|
||||
if (qc->err_mask & AC_ERR_ATA_BUS)
|
||||
@@ -1328,11 +1347,11 @@ static void ata_eh_autopsy(struct ata_port *ap)
|
||||
/* SENSE_VALID trumps dev/unknown error and revalidation */
|
||||
if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
|
||||
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
|
||||
action &= ~ATA_EH_REVALIDATE;
|
||||
ehc->i.action &= ~ATA_EH_REVALIDATE;
|
||||
}
|
||||
|
||||
/* accumulate error info */
|
||||
failed_dev = qc->dev;
|
||||
ehc->i.dev = qc->dev;
|
||||
all_err_mask |= qc->err_mask;
|
||||
if (qc->flags & ATA_QCFLAG_IO)
|
||||
is_io = 1;
|
||||
@@ -1341,25 +1360,22 @@ static void ata_eh_autopsy(struct ata_port *ap)
|
||||
/* enforce default EH actions */
|
||||
if (ap->pflags & ATA_PFLAG_FROZEN ||
|
||||
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
|
||||
action |= ATA_EH_SOFTRESET;
|
||||
ehc->i.action |= ATA_EH_SOFTRESET;
|
||||
else if (all_err_mask)
|
||||
action |= ATA_EH_REVALIDATE;
|
||||
ehc->i.action |= ATA_EH_REVALIDATE;
|
||||
|
||||
/* if we have offending qcs and the associated failed device */
|
||||
if (failed_dev) {
|
||||
if (ehc->i.dev) {
|
||||
/* speed down */
|
||||
action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask);
|
||||
ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io,
|
||||
all_err_mask);
|
||||
|
||||
/* perform per-dev EH action only on the offending device */
|
||||
ehc->i.dev_action[failed_dev->devno] |=
|
||||
action & ATA_EH_PERDEV_MASK;
|
||||
action &= ~ATA_EH_PERDEV_MASK;
|
||||
ehc->i.dev_action[ehc->i.dev->devno] |=
|
||||
ehc->i.action & ATA_EH_PERDEV_MASK;
|
||||
ehc->i.action &= ~ATA_EH_PERDEV_MASK;
|
||||
}
|
||||
|
||||
/* record autopsy result */
|
||||
ehc->i.dev = failed_dev;
|
||||
ehc->i.action |= action;
|
||||
|
||||
DPRINTK("EXIT\n");
|
||||
}
|
||||
|
||||
@@ -1482,6 +1498,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
|
||||
ata_reset_fn_t reset;
|
||||
int i, did_followup_srst, rc;
|
||||
|
||||
/* about to reset */
|
||||
ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
|
||||
|
||||
/* Determine which reset to use and record in ehc->i.action.
|
||||
* prereset() may examine and modify it.
|
||||
*/
|
||||
@@ -1530,8 +1549,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
|
||||
ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
|
||||
reset == softreset ? "soft" : "hard");
|
||||
|
||||
/* reset */
|
||||
ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
|
||||
/* mark that this EH session started with reset */
|
||||
ehc->i.flags |= ATA_EHI_DID_RESET;
|
||||
|
||||
rc = ata_do_reset(ap, reset, classes);
|
||||
@@ -1594,7 +1612,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
|
||||
postreset(ap, classes);
|
||||
|
||||
/* reset successful, schedule revalidation */
|
||||
ata_eh_done(ap, NULL, ATA_EH_RESET_MASK);
|
||||
ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
|
||||
ehc->i.action |= ATA_EH_REVALIDATE;
|
||||
}
|
||||
|
||||
@@ -1847,15 +1865,16 @@ static int ata_eh_skip_recovery(struct ata_port *ap)
|
||||
for (i = 0; i < ata_port_max_devices(ap); i++) {
|
||||
struct ata_device *dev = &ap->device[i];
|
||||
|
||||
if (ata_dev_absent(dev) || ata_dev_ready(dev))
|
||||
if (!(dev->flags & ATA_DFLAG_SUSPENDED))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ata_port_max_devices(ap))
|
||||
return 1;
|
||||
|
||||
/* always thaw frozen port and recover failed devices */
|
||||
if (ap->pflags & ATA_PFLAG_FROZEN || ata_port_nr_enabled(ap))
|
||||
/* thaw frozen port, resume link and recover failed devices */
|
||||
if ((ap->pflags & ATA_PFLAG_FROZEN) ||
|
||||
(ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap))
|
||||
return 0;
|
||||
|
||||
/* skip if class codes for all vacant slots are ATA_DEV_NONE */
|
||||
|
||||
@@ -2353,6 +2353,19 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
|
||||
ata_gen_ata_desc_sense(qc);
|
||||
}
|
||||
|
||||
/* SCSI EH automatically locks door if sdev->locked is
|
||||
* set. Sometimes door lock request continues to
|
||||
* fail, for example, when no media is present. This
|
||||
* creates a loop - SCSI EH issues door lock which
|
||||
* fails and gets invoked again to acquire sense data
|
||||
* for the failed command.
|
||||
*
|
||||
* If door lock fails, always clear sdev->locked to
|
||||
* avoid this infinite loop.
|
||||
*/
|
||||
if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL)
|
||||
qc->dev->sdev->locked = 0;
|
||||
|
||||
qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
|
||||
qc->scsidone(cmd);
|
||||
ata_qc_free(qc);
|
||||
|
||||
@@ -189,6 +189,7 @@ static void iscsi_complete_command(struct iscsi_session *session,
|
||||
{
|
||||
struct scsi_cmnd *sc = ctask->sc;
|
||||
|
||||
ctask->state = ISCSI_TASK_COMPLETED;
|
||||
ctask->sc = NULL;
|
||||
list_del_init(&ctask->running);
|
||||
__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
|
||||
@@ -275,6 +276,25 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
|
||||
{
|
||||
struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
|
||||
|
||||
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
|
||||
conn->tmfrsp_pdus_cnt++;
|
||||
|
||||
if (conn->tmabort_state != TMABORT_INITIAL)
|
||||
return;
|
||||
|
||||
if (tmf->response == ISCSI_TMF_RSP_COMPLETE)
|
||||
conn->tmabort_state = TMABORT_SUCCESS;
|
||||
else if (tmf->response == ISCSI_TMF_RSP_NO_TASK)
|
||||
conn->tmabort_state = TMABORT_NOT_FOUND;
|
||||
else
|
||||
conn->tmabort_state = TMABORT_FAILED;
|
||||
wake_up(&conn->ehwait);
|
||||
}
|
||||
|
||||
/**
|
||||
* __iscsi_complete_pdu - complete pdu
|
||||
* @conn: iscsi conn
|
||||
@@ -340,6 +360,10 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
|
||||
switch(opcode) {
|
||||
case ISCSI_OP_LOGOUT_RSP:
|
||||
if (datalen) {
|
||||
rc = ISCSI_ERR_PROTO;
|
||||
break;
|
||||
}
|
||||
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
|
||||
/* fall through */
|
||||
case ISCSI_OP_LOGIN_RSP:
|
||||
@@ -348,7 +372,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
* login related PDU's exp_statsn is handled in
|
||||
* userspace
|
||||
*/
|
||||
rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
|
||||
if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
|
||||
rc = ISCSI_ERR_CONN_FAILED;
|
||||
list_del(&mtask->running);
|
||||
if (conn->login_mtask != mtask)
|
||||
__kfifo_put(session->mgmtpool.queue,
|
||||
@@ -360,25 +385,17 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
break;
|
||||
}
|
||||
|
||||
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
|
||||
conn->tmfrsp_pdus_cnt++;
|
||||
if (conn->tmabort_state == TMABORT_INITIAL) {
|
||||
conn->tmabort_state =
|
||||
((struct iscsi_tm_rsp *)hdr)->
|
||||
response == ISCSI_TMF_RSP_COMPLETE ?
|
||||
TMABORT_SUCCESS:TMABORT_FAILED;
|
||||
/* unblock eh_abort() */
|
||||
wake_up(&conn->ehwait);
|
||||
}
|
||||
iscsi_tmf_rsp(conn, hdr);
|
||||
break;
|
||||
case ISCSI_OP_NOOP_IN:
|
||||
if (hdr->ttt != ISCSI_RESERVED_TAG) {
|
||||
if (hdr->ttt != ISCSI_RESERVED_TAG || datalen) {
|
||||
rc = ISCSI_ERR_PROTO;
|
||||
break;
|
||||
}
|
||||
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
|
||||
|
||||
rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
|
||||
if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
|
||||
rc = ISCSI_ERR_CONN_FAILED;
|
||||
list_del(&mtask->running);
|
||||
if (conn->login_mtask != mtask)
|
||||
__kfifo_put(session->mgmtpool.queue,
|
||||
@@ -391,14 +408,21 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
} else if (itt == ISCSI_RESERVED_TAG) {
|
||||
switch(opcode) {
|
||||
case ISCSI_OP_NOOP_IN:
|
||||
if (!datalen) {
|
||||
rc = iscsi_check_assign_cmdsn(session,
|
||||
(struct iscsi_nopin*)hdr);
|
||||
if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
|
||||
rc = iscsi_recv_pdu(conn->cls_conn,
|
||||
hdr, NULL, 0);
|
||||
} else
|
||||
if (datalen) {
|
||||
rc = ISCSI_ERR_PROTO;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = iscsi_check_assign_cmdsn(session,
|
||||
(struct iscsi_nopin*)hdr);
|
||||
if (rc)
|
||||
break;
|
||||
|
||||
if (hdr->ttt == ISCSI_RESERVED_TAG)
|
||||
break;
|
||||
|
||||
if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0))
|
||||
rc = ISCSI_ERR_CONN_FAILED;
|
||||
break;
|
||||
case ISCSI_OP_REJECT:
|
||||
/* we need sth like iscsi_reject_rsp()*/
|
||||
@@ -568,20 +592,24 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
|
||||
}
|
||||
|
||||
/* process command queue */
|
||||
while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask,
|
||||
sizeof(void*))) {
|
||||
spin_lock_bh(&conn->session->lock);
|
||||
while (!list_empty(&conn->xmitqueue)) {
|
||||
/*
|
||||
* iscsi tcp may readd the task to the xmitqueue to send
|
||||
* write data
|
||||
*/
|
||||
spin_lock_bh(&conn->session->lock);
|
||||
if (list_empty(&conn->ctask->running))
|
||||
list_add_tail(&conn->ctask->running, &conn->run_list);
|
||||
conn->ctask = list_entry(conn->xmitqueue.next,
|
||||
struct iscsi_cmd_task, running);
|
||||
conn->ctask->state = ISCSI_TASK_RUNNING;
|
||||
list_move_tail(conn->xmitqueue.next, &conn->run_list);
|
||||
spin_unlock_bh(&conn->session->lock);
|
||||
|
||||
rc = tt->xmit_cmd_task(conn, conn->ctask);
|
||||
if (rc)
|
||||
goto again;
|
||||
spin_lock_bh(&conn->session->lock);
|
||||
}
|
||||
spin_unlock_bh(&conn->session->lock);
|
||||
/* done with this ctask */
|
||||
conn->ctask = NULL;
|
||||
|
||||
@@ -691,6 +719,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
|
||||
sc->SCp.phase = session->age;
|
||||
sc->SCp.ptr = (char *)ctask;
|
||||
|
||||
ctask->state = ISCSI_TASK_PENDING;
|
||||
ctask->mtask = NULL;
|
||||
ctask->conn = conn;
|
||||
ctask->sc = sc;
|
||||
@@ -700,7 +729,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
|
||||
|
||||
session->tt->init_cmd_task(ctask);
|
||||
|
||||
__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
|
||||
list_add_tail(&ctask->running, &conn->xmitqueue);
|
||||
debug_scsi(
|
||||
"ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
|
||||
sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
|
||||
@@ -977,31 +1006,27 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
|
||||
/*
|
||||
* xmit mutex and session lock must be held
|
||||
*/
|
||||
#define iscsi_remove_task(tasktype) \
|
||||
static struct iscsi_##tasktype * \
|
||||
iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt) \
|
||||
{ \
|
||||
int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); \
|
||||
struct iscsi_##tasktype *task; \
|
||||
\
|
||||
debug_scsi("searching %d tasks\n", nr_tasks); \
|
||||
\
|
||||
for (i = 0; i < nr_tasks; i++) { \
|
||||
__kfifo_get(fifo, (void*)&task, sizeof(void*)); \
|
||||
debug_scsi("check task %u\n", task->itt); \
|
||||
\
|
||||
if (task->itt == itt) { \
|
||||
debug_scsi("matched task\n"); \
|
||||
return task; \
|
||||
} \
|
||||
\
|
||||
__kfifo_put(fifo, (void*)&task, sizeof(void*)); \
|
||||
} \
|
||||
return NULL; \
|
||||
}
|
||||
static struct iscsi_mgmt_task *
|
||||
iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt)
|
||||
{
|
||||
int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*);
|
||||
struct iscsi_mgmt_task *task;
|
||||
|
||||
iscsi_remove_task(mgmt_task);
|
||||
iscsi_remove_task(cmd_task);
|
||||
debug_scsi("searching %d tasks\n", nr_tasks);
|
||||
|
||||
for (i = 0; i < nr_tasks; i++) {
|
||||
__kfifo_get(fifo, (void*)&task, sizeof(void*));
|
||||
debug_scsi("check task %u\n", task->itt);
|
||||
|
||||
if (task->itt == itt) {
|
||||
debug_scsi("matched task\n");
|
||||
return task;
|
||||
}
|
||||
|
||||
__kfifo_put(fifo, (void*)&task, sizeof(void*));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
|
||||
{
|
||||
@@ -1027,12 +1052,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
|
||||
{
|
||||
struct scsi_cmnd *sc;
|
||||
|
||||
conn->session->tt->cleanup_cmd_task(conn, ctask);
|
||||
iscsi_ctask_mtask_cleanup(ctask);
|
||||
|
||||
sc = ctask->sc;
|
||||
if (!sc)
|
||||
return;
|
||||
|
||||
conn->session->tt->cleanup_cmd_task(conn, ctask);
|
||||
iscsi_ctask_mtask_cleanup(ctask);
|
||||
|
||||
sc->result = err;
|
||||
sc->resid = sc->request_bufflen;
|
||||
iscsi_complete_command(conn->session, ctask);
|
||||
@@ -1043,7 +1069,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
|
||||
struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
|
||||
struct iscsi_conn *conn = ctask->conn;
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct iscsi_cmd_task *pending_ctask;
|
||||
int rc;
|
||||
|
||||
conn->eh_abort_cnt++;
|
||||
@@ -1061,8 +1086,11 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
|
||||
goto failed;
|
||||
|
||||
/* ctask completed before time out */
|
||||
if (!ctask->sc)
|
||||
goto success;
|
||||
if (!ctask->sc) {
|
||||
spin_unlock_bh(&session->lock);
|
||||
debug_scsi("sc completed while abort in progress\n");
|
||||
goto success_rel_mutex;
|
||||
}
|
||||
|
||||
/* what should we do here ? */
|
||||
if (conn->ctask == ctask) {
|
||||
@@ -1071,17 +1099,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* check for the easy pending cmd abort */
|
||||
pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt);
|
||||
if (pending_ctask) {
|
||||
/* iscsi_tcp queues write transfers on the xmitqueue */
|
||||
if (list_empty(&pending_ctask->running)) {
|
||||
debug_scsi("found pending task\n");
|
||||
goto success;
|
||||
} else
|
||||
__kfifo_put(conn->xmitqueue, (void*)&pending_ctask,
|
||||
sizeof(void*));
|
||||
}
|
||||
if (ctask->state == ISCSI_TASK_PENDING)
|
||||
goto success_cleanup;
|
||||
|
||||
conn->tmabort_state = TMABORT_INITIAL;
|
||||
|
||||
@@ -1089,25 +1108,31 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
|
||||
rc = iscsi_exec_abort_task(sc, ctask);
|
||||
spin_lock_bh(&session->lock);
|
||||
|
||||
iscsi_ctask_mtask_cleanup(ctask);
|
||||
if (rc || sc->SCp.phase != session->age ||
|
||||
session->state != ISCSI_STATE_LOGGED_IN)
|
||||
goto failed;
|
||||
iscsi_ctask_mtask_cleanup(ctask);
|
||||
|
||||
/* ctask completed before tmf abort response */
|
||||
if (!ctask->sc) {
|
||||
debug_scsi("sc completed while abort in progress\n");
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (conn->tmabort_state != TMABORT_SUCCESS) {
|
||||
switch (conn->tmabort_state) {
|
||||
case TMABORT_SUCCESS:
|
||||
goto success_cleanup;
|
||||
case TMABORT_NOT_FOUND:
|
||||
if (!ctask->sc) {
|
||||
/* ctask completed before tmf abort response */
|
||||
spin_unlock_bh(&session->lock);
|
||||
debug_scsi("sc completed while abort in progress\n");
|
||||
goto success_rel_mutex;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
/* timedout or failed */
|
||||
spin_unlock_bh(&session->lock);
|
||||
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
|
||||
spin_lock_bh(&session->lock);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
success:
|
||||
success_cleanup:
|
||||
debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
|
||||
spin_unlock_bh(&session->lock);
|
||||
|
||||
@@ -1121,6 +1146,7 @@ success:
|
||||
spin_unlock(&session->lock);
|
||||
write_unlock_bh(conn->recv_lock);
|
||||
|
||||
success_rel_mutex:
|
||||
mutex_unlock(&conn->xmitmutex);
|
||||
return SUCCESS;
|
||||
|
||||
@@ -1263,6 +1289,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
|
||||
if (cmd_task_size)
|
||||
ctask->dd_data = &ctask[1];
|
||||
ctask->itt = cmd_i;
|
||||
INIT_LIST_HEAD(&ctask->running);
|
||||
}
|
||||
|
||||
spin_lock_init(&session->lock);
|
||||
@@ -1282,6 +1309,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
|
||||
if (mgmt_task_size)
|
||||
mtask->dd_data = &mtask[1];
|
||||
mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
|
||||
INIT_LIST_HEAD(&mtask->running);
|
||||
}
|
||||
|
||||
if (scsi_add_host(shost, NULL))
|
||||
@@ -1322,15 +1350,18 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
|
||||
{
|
||||
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
||||
struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
|
||||
struct module *owner = cls_session->transport->owner;
|
||||
|
||||
scsi_remove_host(shost);
|
||||
|
||||
iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
|
||||
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
|
||||
|
||||
kfree(session->targetname);
|
||||
|
||||
iscsi_destroy_session(cls_session);
|
||||
scsi_host_put(shost);
|
||||
module_put(cls_session->transport->owner);
|
||||
module_put(owner);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_session_teardown);
|
||||
|
||||
@@ -1361,12 +1392,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
|
||||
conn->tmabort_state = TMABORT_INITIAL;
|
||||
INIT_LIST_HEAD(&conn->run_list);
|
||||
INIT_LIST_HEAD(&conn->mgmt_run_list);
|
||||
|
||||
/* initialize general xmit PDU commands queue */
|
||||
conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
|
||||
GFP_KERNEL, NULL);
|
||||
if (conn->xmitqueue == ERR_PTR(-ENOMEM))
|
||||
goto xmitqueue_alloc_fail;
|
||||
INIT_LIST_HEAD(&conn->xmitqueue);
|
||||
|
||||
/* initialize general immediate & non-immediate PDU commands queue */
|
||||
conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
|
||||
@@ -1394,7 +1420,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
|
||||
data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
|
||||
if (!data)
|
||||
goto login_mtask_data_alloc_fail;
|
||||
conn->login_mtask->data = data;
|
||||
conn->login_mtask->data = conn->data = data;
|
||||
|
||||
init_timer(&conn->tmabort_timer);
|
||||
mutex_init(&conn->xmitmutex);
|
||||
@@ -1410,8 +1436,6 @@ login_mtask_alloc_fail:
|
||||
mgmtqueue_alloc_fail:
|
||||
kfifo_free(conn->immqueue);
|
||||
immqueue_alloc_fail:
|
||||
kfifo_free(conn->xmitqueue);
|
||||
xmitqueue_alloc_fail:
|
||||
iscsi_destroy_conn(cls_conn);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1432,12 +1456,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
|
||||
|
||||
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
|
||||
mutex_lock(&conn->xmitmutex);
|
||||
if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) {
|
||||
if (session->tt->suspend_conn_recv)
|
||||
session->tt->suspend_conn_recv(conn);
|
||||
|
||||
session->tt->terminate_conn(conn);
|
||||
}
|
||||
|
||||
spin_lock_bh(&session->lock);
|
||||
conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
|
||||
@@ -1474,7 +1492,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
|
||||
}
|
||||
|
||||
spin_lock_bh(&session->lock);
|
||||
kfree(conn->login_mtask->data);
|
||||
kfree(conn->data);
|
||||
kfree(conn->persistent_address);
|
||||
__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
|
||||
sizeof(void*));
|
||||
list_del(&conn->item);
|
||||
@@ -1489,7 +1508,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
|
||||
session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
|
||||
spin_unlock_bh(&session->lock);
|
||||
|
||||
kfifo_free(conn->xmitqueue);
|
||||
kfifo_free(conn->immqueue);
|
||||
kfifo_free(conn->mgmtqueue);
|
||||
|
||||
@@ -1572,7 +1590,7 @@ static void fail_all_commands(struct iscsi_conn *conn)
|
||||
struct iscsi_cmd_task *ctask, *tmp;
|
||||
|
||||
/* flush pending */
|
||||
while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) {
|
||||
list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) {
|
||||
debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
|
||||
ctask->itt);
|
||||
fail_command(conn, ctask, DID_BUS_BUSY << 16);
|
||||
@@ -1615,8 +1633,9 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
|
||||
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
|
||||
spin_unlock_bh(&session->lock);
|
||||
|
||||
if (session->tt->suspend_conn_recv)
|
||||
session->tt->suspend_conn_recv(conn);
|
||||
write_lock_bh(conn->recv_lock);
|
||||
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
|
||||
write_unlock_bh(conn->recv_lock);
|
||||
|
||||
mutex_lock(&conn->xmitmutex);
|
||||
/*
|
||||
@@ -1635,7 +1654,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
|
||||
}
|
||||
}
|
||||
|
||||
session->tt->terminate_conn(conn);
|
||||
/*
|
||||
* flush queues.
|
||||
*/
|
||||
|
||||
@@ -222,7 +222,7 @@ lpfc_issue_lip(struct Scsi_Host *host)
|
||||
pmboxq->mb.mbxCommand = MBX_DOWN_LINK;
|
||||
pmboxq->mb.mbxOwner = OWN_HOST;
|
||||
|
||||
mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||
mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO * 2);
|
||||
|
||||
if ((mbxstatus == MBX_SUCCESS) && (pmboxq->mb.mbxStatus == 0)) {
|
||||
memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
|
||||
@@ -884,7 +884,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
phba->sysfs_mbox.mbox == NULL ) {
|
||||
sysfs_mbox_idle(phba);
|
||||
spin_unlock_irq(host->host_lock);
|
||||
return -EINVAL;
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1000,14 +1000,15 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
rc = lpfc_sli_issue_mbox_wait (phba,
|
||||
phba->sysfs_mbox.mbox,
|
||||
phba->fc_ratov * 2);
|
||||
lpfc_mbox_tmo_val(phba,
|
||||
phba->sysfs_mbox.mbox->mb.mbxCommand) * HZ);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
}
|
||||
|
||||
if (rc != MBX_SUCCESS) {
|
||||
sysfs_mbox_idle(phba);
|
||||
spin_unlock_irq(host->host_lock);
|
||||
return -ENODEV;
|
||||
return (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
|
||||
}
|
||||
phba->sysfs_mbox.state = SMBOX_READING;
|
||||
}
|
||||
@@ -1016,7 +1017,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
printk(KERN_WARNING "mbox_read: Bad State\n");
|
||||
sysfs_mbox_idle(phba);
|
||||
spin_unlock_irq(host->host_lock);
|
||||
return -EINVAL;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
memcpy(buf, (uint8_t *) & phba->sysfs_mbox.mbox->mb + off, count);
|
||||
@@ -1210,8 +1211,10 @@ lpfc_get_stats(struct Scsi_Host *shost)
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct fc_host_statistics *hs = &phba->link_stats;
|
||||
struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
|
||||
LPFC_MBOXQ_t *pmboxq;
|
||||
MAILBOX_t *pmb;
|
||||
unsigned long seconds;
|
||||
int rc = 0;
|
||||
|
||||
pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
@@ -1272,22 +1275,103 @@ lpfc_get_stats(struct Scsi_Host *shost)
|
||||
hs->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
|
||||
hs->error_frames = pmb->un.varRdLnk.crcCnt;
|
||||
|
||||
hs->link_failure_count -= lso->link_failure_count;
|
||||
hs->loss_of_sync_count -= lso->loss_of_sync_count;
|
||||
hs->loss_of_signal_count -= lso->loss_of_signal_count;
|
||||
hs->prim_seq_protocol_err_count -= lso->prim_seq_protocol_err_count;
|
||||
hs->invalid_tx_word_count -= lso->invalid_tx_word_count;
|
||||
hs->invalid_crc_count -= lso->invalid_crc_count;
|
||||
hs->error_frames -= lso->error_frames;
|
||||
|
||||
if (phba->fc_topology == TOPOLOGY_LOOP) {
|
||||
hs->lip_count = (phba->fc_eventTag >> 1);
|
||||
hs->lip_count -= lso->link_events;
|
||||
hs->nos_count = -1;
|
||||
} else {
|
||||
hs->lip_count = -1;
|
||||
hs->nos_count = (phba->fc_eventTag >> 1);
|
||||
hs->nos_count -= lso->link_events;
|
||||
}
|
||||
|
||||
hs->dumped_frames = -1;
|
||||
|
||||
/* FIX ME */
|
||||
/*hs->SecondsSinceLastReset = (jiffies - lpfc_loadtime) / HZ;*/
|
||||
seconds = get_seconds();
|
||||
if (seconds < psli->stats_start)
|
||||
hs->seconds_since_last_reset = seconds +
|
||||
((unsigned long)-1 - psli->stats_start);
|
||||
else
|
||||
hs->seconds_since_last_reset = seconds - psli->stats_start;
|
||||
|
||||
return hs;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_reset_stats(struct Scsi_Host *shost)
|
||||
{
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
|
||||
LPFC_MBOXQ_t *pmboxq;
|
||||
MAILBOX_t *pmb;
|
||||
int rc = 0;
|
||||
|
||||
pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (!pmboxq)
|
||||
return;
|
||||
memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
|
||||
|
||||
pmb = &pmboxq->mb;
|
||||
pmb->mbxCommand = MBX_READ_STATUS;
|
||||
pmb->mbxOwner = OWN_HOST;
|
||||
pmb->un.varWords[0] = 0x1; /* reset request */
|
||||
pmboxq->context1 = NULL;
|
||||
|
||||
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
|
||||
(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
|
||||
rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
|
||||
else
|
||||
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||
|
||||
if (rc != MBX_SUCCESS) {
|
||||
if (rc == MBX_TIMEOUT)
|
||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||
else
|
||||
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
|
||||
pmb->mbxCommand = MBX_READ_LNK_STAT;
|
||||
pmb->mbxOwner = OWN_HOST;
|
||||
pmboxq->context1 = NULL;
|
||||
|
||||
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
|
||||
(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
|
||||
rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
|
||||
else
|
||||
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||
|
||||
if (rc != MBX_SUCCESS) {
|
||||
if (rc == MBX_TIMEOUT)
|
||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||
else
|
||||
mempool_free( pmboxq, phba->mbox_mem_pool);
|
||||
return;
|
||||
}
|
||||
|
||||
lso->link_failure_count = pmb->un.varRdLnk.linkFailureCnt;
|
||||
lso->loss_of_sync_count = pmb->un.varRdLnk.lossSyncCnt;
|
||||
lso->loss_of_signal_count = pmb->un.varRdLnk.lossSignalCnt;
|
||||
lso->prim_seq_protocol_err_count = pmb->un.varRdLnk.primSeqErrCnt;
|
||||
lso->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord;
|
||||
lso->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
|
||||
lso->error_frames = pmb->un.varRdLnk.crcCnt;
|
||||
lso->link_events = (phba->fc_eventTag >> 1);
|
||||
|
||||
psli->stats_start = get_seconds();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The LPFC driver treats linkdown handling as target loss events so there
|
||||
@@ -1431,8 +1515,7 @@ struct fc_function_template lpfc_transport_functions = {
|
||||
*/
|
||||
|
||||
.get_fc_host_stats = lpfc_get_stats,
|
||||
|
||||
/* the LPFC driver doesn't support resetting stats yet */
|
||||
.reset_fc_host_stats = lpfc_reset_stats,
|
||||
|
||||
.dd_fcrport_size = sizeof(struct lpfc_rport_data),
|
||||
.show_rport_maxframe_size = 1,
|
||||
|
||||
@@ -127,6 +127,7 @@ void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
|
||||
int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
|
||||
|
||||
int lpfc_mem_alloc(struct lpfc_hba *);
|
||||
void lpfc_mem_free(struct lpfc_hba *);
|
||||
|
||||
@@ -131,6 +131,7 @@ lpfc_ct_unsol_event(struct lpfc_hba * phba,
|
||||
}
|
||||
|
||||
ct_unsol_event_exit_piocbq:
|
||||
list_del(&head);
|
||||
if (pmbuf) {
|
||||
list_for_each_entry_safe(matp, next_matp, &pmbuf->list, list) {
|
||||
lpfc_mbuf_free(phba, matp->virt, matp->phys);
|
||||
@@ -481,7 +482,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
if (CTrsp->CommandResponse.bits.CmdRsp ==
|
||||
be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
|
||||
"%d:0239 NameServer Rsp "
|
||||
"%d:0208 NameServer Rsp "
|
||||
"Data: x%x\n",
|
||||
phba->brd_no,
|
||||
phba->fc_flag);
|
||||
@@ -588,13 +589,9 @@ lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp)
|
||||
|
||||
lpfc_decode_firmware_rev(phba, fwrev, 0);
|
||||
|
||||
if (phba->Port[0]) {
|
||||
sprintf(symbp, "Emulex %s Port %s FV%s DV%s", phba->ModelName,
|
||||
phba->Port, fwrev, lpfc_release_version);
|
||||
} else {
|
||||
sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName,
|
||||
fwrev, lpfc_release_version);
|
||||
}
|
||||
sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName,
|
||||
fwrev, lpfc_release_version);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1848,9 +1848,12 @@ static void
|
||||
lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
struct lpfc_iocbq * rspiocb)
|
||||
{
|
||||
IOCB_t *irsp;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
LPFC_MBOXQ_t *mbox = NULL;
|
||||
|
||||
irsp = &rspiocb->iocb;
|
||||
|
||||
ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
|
||||
if (cmdiocb->context_un.mbox)
|
||||
mbox = cmdiocb->context_un.mbox;
|
||||
@@ -1893,9 +1896,15 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
mempool_free( mbox, phba->mbox_mem_pool);
|
||||
} else {
|
||||
mempool_free( mbox, phba->mbox_mem_pool);
|
||||
if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
ndlp = NULL;
|
||||
/* Do not call NO_LIST 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)))) {
|
||||
if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
ndlp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2839,7 +2848,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
|
||||
/* Xmit ELS RPS ACC response tag <ulpIoTag> */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||
"%d:0128 Xmit ELS RPS ACC response tag x%x "
|
||||
"%d:0118 Xmit ELS RPS ACC response tag x%x "
|
||||
"Data: x%x x%x x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
elsiocb->iocb.ulpIoTag,
|
||||
@@ -2948,7 +2957,7 @@ lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize,
|
||||
|
||||
/* Xmit ELS RPL ACC response tag <ulpIoTag> */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||
"%d:0128 Xmit ELS RPL ACC response tag x%x "
|
||||
"%d:0120 Xmit ELS RPL ACC response tag x%x "
|
||||
"Data: x%x x%x x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
elsiocb->iocb.ulpIoTag,
|
||||
@@ -3109,7 +3118,7 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
struct lpfc_nodelist *ndlp, *next_ndlp;
|
||||
|
||||
/* FAN received */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:265 FAN received\n",
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n",
|
||||
phba->brd_no);
|
||||
|
||||
icmd = &cmdiocb->iocb;
|
||||
|
||||
@@ -1557,6 +1557,8 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
|
||||
mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
|
||||
if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
|
||||
(ndlp == (struct lpfc_nodelist *) mb->context2)) {
|
||||
@@ -1569,6 +1571,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
|
||||
mempool_free(mb, phba->mbox_mem_pool);
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
lpfc_els_abort(phba,ndlp,0);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
@@ -1782,7 +1785,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
|
||||
/* LOG change to REGLOGIN */
|
||||
/* FIND node DID reglogin */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0931 FIND node DID reglogin"
|
||||
"%d:0901 FIND node DID reglogin"
|
||||
" Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
@@ -1805,7 +1808,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
|
||||
/* LOG change to PRLI */
|
||||
/* FIND node DID prli */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0931 FIND node DID prli "
|
||||
"%d:0902 FIND node DID prli "
|
||||
"Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
@@ -1828,7 +1831,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
|
||||
/* LOG change to NPR */
|
||||
/* FIND node DID npr */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0931 FIND node DID npr "
|
||||
"%d:0903 FIND node DID npr "
|
||||
"Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
@@ -1851,7 +1854,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
|
||||
/* LOG change to UNUSED */
|
||||
/* FIND node DID unused */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0931 FIND node DID unused "
|
||||
"%d:0905 FIND node DID unused "
|
||||
"Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
@@ -2335,7 +2338,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
|
||||
initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (!initlinkmbox) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
|
||||
"%d:0226 Device Discovery "
|
||||
"%d:0206 Device Discovery "
|
||||
"completion error\n",
|
||||
phba->brd_no);
|
||||
phba->hba_state = LPFC_HBA_ERROR;
|
||||
@@ -2365,7 +2368,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
|
||||
if (!clearlambox) {
|
||||
clrlaerr = 1;
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
|
||||
"%d:0226 Device Discovery "
|
||||
"%d:0207 Device Discovery "
|
||||
"completion error\n",
|
||||
phba->brd_no);
|
||||
phba->hba_state = LPFC_HBA_ERROR;
|
||||
|
||||
@@ -1379,6 +1379,7 @@ lpfc_offline(struct lpfc_hba * phba)
|
||||
/* stop all timers associated with this hba */
|
||||
lpfc_stop_timer(phba);
|
||||
phba->work_hba_events = 0;
|
||||
phba->work_ha = 0;
|
||||
|
||||
lpfc_printf_log(phba,
|
||||
KERN_WARNING,
|
||||
@@ -1616,7 +1617,11 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
||||
goto out_free_iocbq;
|
||||
}
|
||||
|
||||
/* We can rely on a queue depth attribute only after SLI HBA setup */
|
||||
/*
|
||||
* Set initial can_queue value since 0 is no longer supported and
|
||||
* scsi_add_host will fail. This will be adjusted later based on the
|
||||
* max xri value determined in hba setup.
|
||||
*/
|
||||
host->can_queue = phba->cfg_hba_queue_depth - 10;
|
||||
|
||||
/* Tell the midlayer we support 16 byte commands */
|
||||
@@ -1656,6 +1661,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
||||
goto out_free_irq;
|
||||
}
|
||||
|
||||
/*
|
||||
* hba setup may have changed the hba_queue_depth so we need to adjust
|
||||
* the value of can_queue.
|
||||
*/
|
||||
host->can_queue = phba->cfg_hba_queue_depth - 10;
|
||||
|
||||
lpfc_discovery_wait(phba);
|
||||
|
||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||
|
||||
@@ -651,3 +651,19 @@ lpfc_mbox_get(struct lpfc_hba * phba)
|
||||
|
||||
return mbq;
|
||||
}
|
||||
|
||||
int
|
||||
lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case MBX_WRITE_NV: /* 0x03 */
|
||||
case MBX_UPDATE_CFG: /* 0x1B */
|
||||
case MBX_DOWN_LOAD: /* 0x1C */
|
||||
case MBX_DEL_LD_ENTRY: /* 0x1D */
|
||||
case MBX_LOAD_AREA: /* 0x81 */
|
||||
case MBX_FLASH_WR_ULA: /* 0x98 */
|
||||
case MBX_LOAD_EXP_ROM: /* 0x9C */
|
||||
return LPFC_MBOX_TMO_FLASH_CMD;
|
||||
}
|
||||
return LPFC_MBOX_TMO;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
|
||||
|
||||
/* Abort outstanding I/O on NPort <nlp_DID> */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
|
||||
"%d:0201 Abort outstanding I/O on NPort x%x "
|
||||
"%d:0205 Abort outstanding I/O on NPort x%x "
|
||||
"Data: x%x x%x x%x\n",
|
||||
phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
|
||||
ndlp->nlp_state, ndlp->nlp_rpi);
|
||||
@@ -393,6 +393,20 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
|
||||
mbox->context2 = ndlp;
|
||||
ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
|
||||
|
||||
/*
|
||||
* If there is an outstanding PLOGI issued, abort it before
|
||||
* sending ACC rsp for received PLOGI. If pending plogi
|
||||
* is not canceled here, the plogi will be rejected by
|
||||
* remote port and will be retried. On a configuration with
|
||||
* single discovery thread, this will cause a huge delay in
|
||||
* discovery. Also this will cause multiple state machines
|
||||
* running in parallel for this node.
|
||||
*/
|
||||
if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
|
||||
/* software abort outstanding PLOGI */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
}
|
||||
|
||||
lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
|
||||
return 1;
|
||||
|
||||
@@ -1601,7 +1615,13 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
|
||||
|
||||
lpfc_rcv_padisc(phba, ndlp, cmdiocb);
|
||||
|
||||
if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
|
||||
/*
|
||||
* Do not start discovery if discovery is about to start
|
||||
* or discovery in progress for this node. Starting discovery
|
||||
* here will affect the counting of discovery threads.
|
||||
*/
|
||||
if ((!(ndlp->nlp_flag & NLP_DELAY_TMO)) &&
|
||||
(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
|
||||
if (ndlp->nlp_flag & NLP_NPR_ADISC) {
|
||||
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
|
||||
ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
@@ -841,6 +842,21 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_block_error_handler(struct scsi_cmnd *cmnd)
|
||||
{
|
||||
struct Scsi_Host *shost = cmnd->device->host;
|
||||
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
|
||||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
while (rport->port_state == FC_PORTSTATE_BLOCKED) {
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
msleep(1000);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
}
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_abort_handler(struct scsi_cmnd *cmnd)
|
||||
@@ -855,6 +871,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
|
||||
unsigned int loop_count = 0;
|
||||
int ret = SUCCESS;
|
||||
|
||||
lpfc_block_error_handler(cmnd);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
|
||||
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
|
||||
@@ -957,6 +974,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
||||
int ret = FAILED;
|
||||
int cnt, loopcnt;
|
||||
|
||||
lpfc_block_error_handler(cmnd);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
/*
|
||||
* If target is not in a MAPPED state, delay the reset until
|
||||
@@ -1073,6 +1091,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
||||
int cnt, loopcnt;
|
||||
struct lpfc_scsi_buf * lpfc_cmd;
|
||||
|
||||
lpfc_block_error_handler(cmnd);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
|
||||
lpfc_cmd = lpfc_get_scsi_buf(phba);
|
||||
@@ -1104,7 +1123,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
||||
ndlp->rport->dd_data);
|
||||
if (ret != SUCCESS) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
||||
"%d:0713 Bus Reset on target %d failed\n",
|
||||
"%d:0700 Bus Reset on target %d failed\n",
|
||||
phba->brd_no, i);
|
||||
err_count++;
|
||||
}
|
||||
|
||||
@@ -320,7 +320,8 @@ lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
|
||||
kfree(old_arr);
|
||||
return iotag;
|
||||
}
|
||||
}
|
||||
} else
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
|
||||
"%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n",
|
||||
@@ -969,9 +970,11 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
|
||||
* 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);
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
"%d:0314 IOCB cmd 0x%x"
|
||||
" processed. Skipping"
|
||||
" completion", phba->brd_no,
|
||||
irsp->ulpCommand);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1104,7 +1107,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
|
||||
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: "
|
||||
"%d:0336 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],
|
||||
@@ -1122,9 +1125,11 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
|
||||
* 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);
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
"%d:0333 IOCB cmd 0x%x"
|
||||
" processed. Skipping"
|
||||
" completion\n", phba->brd_no,
|
||||
irsp->ulpCommand);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1155,7 +1160,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
|
||||
} else {
|
||||
/* Unknown IOCB command */
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"%d:0321 Unknown IOCB command "
|
||||
"%d:0334 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,
|
||||
@@ -1238,7 +1243,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
|
||||
lpfc_printf_log(phba,
|
||||
KERN_ERR,
|
||||
LOG_SLI,
|
||||
"%d:0312 Ring %d handler: portRspPut %d "
|
||||
"%d:0303 Ring %d handler: portRspPut %d "
|
||||
"is bigger then rsp ring %d\n",
|
||||
phba->brd_no,
|
||||
pring->ringno, portRspPut, portRspMax);
|
||||
@@ -1383,7 +1388,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
|
||||
lpfc_printf_log(phba,
|
||||
KERN_ERR,
|
||||
LOG_SLI,
|
||||
"%d:0321 Unknown IOCB command "
|
||||
"%d:0335 Unknown IOCB command "
|
||||
"Data: x%x x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
irsp->ulpCommand,
|
||||
@@ -1399,11 +1404,11 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
|
||||
next_iocb,
|
||||
&saveq->list,
|
||||
list) {
|
||||
list_del(&rspiocbp->list);
|
||||
lpfc_sli_release_iocbq(phba,
|
||||
rspiocbp);
|
||||
}
|
||||
}
|
||||
|
||||
lpfc_sli_release_iocbq(phba, saveq);
|
||||
}
|
||||
}
|
||||
@@ -1711,15 +1716,13 @@ lpfc_sli_brdreset(struct lpfc_hba * phba)
|
||||
phba->fc_myDID = 0;
|
||||
phba->fc_prevDID = 0;
|
||||
|
||||
psli->sli_flag = 0;
|
||||
|
||||
/* Turn off parity checking and serr during the physical reset */
|
||||
pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
|
||||
pci_write_config_word(phba->pcidev, PCI_COMMAND,
|
||||
(cfg_value &
|
||||
~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
|
||||
|
||||
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
|
||||
psli->sli_flag &= ~(LPFC_SLI2_ACTIVE | LPFC_PROCESS_LA);
|
||||
/* Now toggle INITFF bit in the Host Control Register */
|
||||
writel(HC_INITFF, phba->HCregaddr);
|
||||
mdelay(1);
|
||||
@@ -1760,7 +1763,7 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
|
||||
|
||||
/* Restart HBA */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
"%d:0328 Restart HBA Data: x%x x%x\n", phba->brd_no,
|
||||
"%d:0337 Restart HBA Data: x%x x%x\n", phba->brd_no,
|
||||
phba->hba_state, psli->sli_flag);
|
||||
|
||||
word0 = 0;
|
||||
@@ -1792,6 +1795,9 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
|
||||
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
|
||||
psli->stats_start = get_seconds();
|
||||
|
||||
if (skip_post)
|
||||
mdelay(100);
|
||||
else
|
||||
@@ -1902,6 +1908,9 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
|
||||
}
|
||||
|
||||
while (resetcount < 2 && !done) {
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
phba->hba_state = LPFC_STATE_UNKNOWN;
|
||||
lpfc_sli_brdrestart(phba);
|
||||
msleep(2500);
|
||||
@@ -1909,6 +1918,9 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
|
||||
if (rc)
|
||||
break;
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
resetcount++;
|
||||
|
||||
/* Call pre CONFIG_PORT mailbox command initialization. A value of 0
|
||||
@@ -2194,7 +2206,8 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
|
||||
return (MBX_NOT_FINISHED);
|
||||
}
|
||||
/* timeout active mbox command */
|
||||
mod_timer(&psli->mbox_tmo, jiffies + HZ * LPFC_MBOX_TMO);
|
||||
mod_timer(&psli->mbox_tmo, (jiffies +
|
||||
(HZ * lpfc_mbox_tmo_val(phba, mb->mbxCommand))));
|
||||
}
|
||||
|
||||
/* Mailbox cmd <cmd> issue */
|
||||
@@ -2254,7 +2267,6 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
|
||||
break;
|
||||
|
||||
case MBX_POLL:
|
||||
i = 0;
|
||||
psli->mbox_active = NULL;
|
||||
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
|
||||
/* First read mbox status word */
|
||||
@@ -2268,11 +2280,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
|
||||
/* Read the HBA Host Attention Register */
|
||||
ha_copy = readl(phba->HAregaddr);
|
||||
|
||||
i = lpfc_mbox_tmo_val(phba, mb->mbxCommand);
|
||||
i *= 1000; /* Convert to ms */
|
||||
|
||||
/* Wait for command to complete */
|
||||
while (((word0 & OWN_CHIP) == OWN_CHIP) ||
|
||||
(!(ha_copy & HA_MBATT) &&
|
||||
(phba->hba_state > LPFC_WARM_START))) {
|
||||
if (i++ >= 100) {
|
||||
if (i-- <= 0) {
|
||||
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
|
||||
spin_unlock_irqrestore(phba->host->host_lock,
|
||||
drvr_flag);
|
||||
@@ -2290,7 +2305,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
|
||||
|
||||
/* Can be in interrupt context, do not sleep */
|
||||
/* (or might be called with interrupts disabled) */
|
||||
mdelay(i);
|
||||
mdelay(1);
|
||||
|
||||
spin_lock_irqsave(phba->host->host_lock, drvr_flag);
|
||||
|
||||
@@ -3005,7 +3020,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
|
||||
|
||||
if (timeleft == 0) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"%d:0329 IOCB wait timeout error - no "
|
||||
"%d:0338 IOCB wait timeout error - no "
|
||||
"wake response Data x%x\n",
|
||||
phba->brd_no, timeout);
|
||||
retval = IOCB_TIMEDOUT;
|
||||
|
||||
@@ -172,6 +172,18 @@ struct lpfc_sli_stat {
|
||||
uint32_t mbox_busy; /* Mailbox cmd busy */
|
||||
};
|
||||
|
||||
/* Structure to store link status values when port stats are reset */
|
||||
struct lpfc_lnk_stat {
|
||||
uint32_t link_failure_count;
|
||||
uint32_t loss_of_sync_count;
|
||||
uint32_t loss_of_signal_count;
|
||||
uint32_t prim_seq_protocol_err_count;
|
||||
uint32_t invalid_tx_word_count;
|
||||
uint32_t invalid_crc_count;
|
||||
uint32_t error_frames;
|
||||
uint32_t link_events;
|
||||
};
|
||||
|
||||
/* Structure used to hold SLI information */
|
||||
struct lpfc_sli {
|
||||
uint32_t num_rings;
|
||||
@@ -201,6 +213,8 @@ struct lpfc_sli {
|
||||
struct lpfc_iocbq ** iocbq_lookup; /* array to lookup IOCB by IOTAG */
|
||||
size_t iocbq_lookup_len; /* current lengs of the array */
|
||||
uint16_t last_iotag; /* last allocated IOTAG */
|
||||
unsigned long stats_start; /* in seconds */
|
||||
struct lpfc_lnk_stat lnk_stat_offsets;
|
||||
};
|
||||
|
||||
/* Given a pointer to the start of the ring, and the slot number of
|
||||
@@ -211,3 +225,9 @@ struct lpfc_sli {
|
||||
|
||||
#define LPFC_MBOX_TMO 30 /* Sec tmo for outstanding mbox
|
||||
command */
|
||||
#define LPFC_MBOX_TMO_FLASH_CMD 300 /* Sec tmo for outstanding FLASH write
|
||||
* or erase cmds. This is especially
|
||||
* long because of the potential of
|
||||
* multiple flash erases that can be
|
||||
* spawned.
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "8.1.7"
|
||||
#define LPFC_DRIVER_VERSION "8.1.9"
|
||||
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
#define LSI_MAX_CHANNELS 16
|
||||
#define LSI_MAX_LOGICAL_DRIVES_64LD (64+1)
|
||||
|
||||
#define HBA_SIGNATURE_64_BIT 0x299
|
||||
#define PCI_CONF_AMISIG64 0xa4
|
||||
|
||||
#define MEGA_SCSI_INQ_EVPD 1
|
||||
#define MEGA_INVALID_FIELD_IN_CDB 0x24
|
||||
|
||||
|
||||
/**
|
||||
* scb_t - scsi command control block
|
||||
|
||||
@@ -132,6 +132,10 @@ typedef struct uioc {
|
||||
/* Driver Data: */
|
||||
void __user * user_data;
|
||||
uint32_t user_data_len;
|
||||
|
||||
/* 64bit alignment */
|
||||
uint32_t pad_for_64bit_align;
|
||||
|
||||
mraid_passthru_t __user *user_pthru;
|
||||
|
||||
mraid_passthru_t *pthru32;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FILE : megaraid_mbox.c
|
||||
* Version : v2.20.4.8 (Apr 11 2006)
|
||||
* Version : v2.20.4.9 (Jul 16 2006)
|
||||
*
|
||||
* Authors:
|
||||
* Atul Mukker <Atul.Mukker@lsil.com>
|
||||
@@ -736,6 +736,7 @@ megaraid_init_mbox(adapter_t *adapter)
|
||||
struct pci_dev *pdev;
|
||||
mraid_device_t *raid_dev;
|
||||
int i;
|
||||
uint32_t magic64;
|
||||
|
||||
|
||||
adapter->ito = MBOX_TIMEOUT;
|
||||
@@ -879,12 +880,33 @@ megaraid_init_mbox(adapter_t *adapter)
|
||||
|
||||
// Set the DMA mask to 64-bit. All supported controllers as capable of
|
||||
// DMA in this range
|
||||
if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK) != 0) {
|
||||
pci_read_config_dword(adapter->pdev, PCI_CONF_AMISIG64, &magic64);
|
||||
|
||||
con_log(CL_ANN, (KERN_WARNING
|
||||
"megaraid: could not set DMA mask for 64-bit.\n"));
|
||||
if (((magic64 == HBA_SIGNATURE_64_BIT) &&
|
||||
((adapter->pdev->subsystem_device !=
|
||||
PCI_SUBSYS_ID_MEGARAID_SATA_150_6) ||
|
||||
(adapter->pdev->subsystem_device !=
|
||||
PCI_SUBSYS_ID_MEGARAID_SATA_150_4))) ||
|
||||
(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
|
||||
adapter->pdev->device == PCI_DEVICE_ID_VERDE) ||
|
||||
(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
|
||||
adapter->pdev->device == PCI_DEVICE_ID_DOBSON) ||
|
||||
(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
|
||||
adapter->pdev->device == PCI_DEVICE_ID_LINDSAY) ||
|
||||
(adapter->pdev->vendor == PCI_VENDOR_ID_DELL &&
|
||||
adapter->pdev->device == PCI_DEVICE_ID_PERC4_DI_EVERGLADES) ||
|
||||
(adapter->pdev->vendor == PCI_VENDOR_ID_DELL &&
|
||||
adapter->pdev->device == PCI_DEVICE_ID_PERC4E_DI_KOBUK)) {
|
||||
if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK)) {
|
||||
con_log(CL_ANN, (KERN_WARNING
|
||||
"megaraid: DMA mask for 64-bit failed\n"));
|
||||
|
||||
goto out_free_sysfs_res;
|
||||
if (pci_set_dma_mask (adapter->pdev, DMA_32BIT_MASK)) {
|
||||
con_log(CL_ANN, (KERN_WARNING
|
||||
"megaraid: 32-bit DMA mask failed\n"));
|
||||
goto out_free_sysfs_res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setup tasklet for DPC
|
||||
@@ -1638,6 +1660,14 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
|
||||
rdev->last_disp |= (1L << SCP2CHANNEL(scp));
|
||||
}
|
||||
|
||||
if (scp->cmnd[1] & MEGA_SCSI_INQ_EVPD) {
|
||||
scp->sense_buffer[0] = 0x70;
|
||||
scp->sense_buffer[2] = ILLEGAL_REQUEST;
|
||||
scp->sense_buffer[12] = MEGA_INVALID_FIELD_IN_CDB;
|
||||
scp->result = CHECK_CONDITION << 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Fall through */
|
||||
|
||||
case READ_CAPACITY:
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include "megaraid_ioctl.h"
|
||||
|
||||
|
||||
#define MEGARAID_VERSION "2.20.4.8"
|
||||
#define MEGARAID_EXT_VERSION "(Release Date: Mon Apr 11 12:27:22 EST 2006)"
|
||||
#define MEGARAID_VERSION "2.20.4.9"
|
||||
#define MEGARAID_EXT_VERSION "(Release Date: Sun Jul 16 12:27:22 EST 2006)"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FILE : megaraid_mm.c
|
||||
* Version : v2.20.2.6 (Mar 7 2005)
|
||||
* Version : v2.20.2.7 (Jul 16 2006)
|
||||
*
|
||||
* Common management module
|
||||
*/
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
#include "megaraid_ioctl.h"
|
||||
|
||||
|
||||
#define LSI_COMMON_MOD_VERSION "2.20.2.6"
|
||||
#define LSI_COMMON_MOD_VERSION "2.20.2.7"
|
||||
#define LSI_COMMON_MOD_EXT_VERSION \
|
||||
"(Release Date: Mon Mar 7 00:01:03 EST 2005)"
|
||||
"(Release Date: Sun Jul 16 00:01:03 EST 2006)"
|
||||
|
||||
|
||||
#define LSI_DBGLVL dbglevel
|
||||
|
||||
@@ -183,7 +183,8 @@ static struct ata_port_info adma_port_info[] = {
|
||||
{
|
||||
.sht = &adma_ata_sht,
|
||||
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
|
||||
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO,
|
||||
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
|
||||
ATA_FLAG_PIO_POLLING,
|
||||
.pio_mask = 0x10, /* pio4 */
|
||||
.udma_mask = 0x1f, /* udma0-4 */
|
||||
.port_ops = &adma_ata_ops,
|
||||
|
||||
@@ -487,6 +487,7 @@ typedef struct {
|
||||
#define MBA_IP_RCV_BUFFER_EMPTY 0x8026 /* IP receive buffer queue empty. */
|
||||
#define MBA_IP_HDR_DATA_SPLIT 0x8027 /* IP header/data splitting feature */
|
||||
/* used. */
|
||||
#define MBA_TRACE_NOTIFICATION 0x8028 /* Trace/Diagnostic notification. */
|
||||
#define MBA_POINT_TO_POINT 0x8030 /* Point to point mode. */
|
||||
#define MBA_CMPLT_1_16BIT 0x8031 /* Completion 1 16bit IOSB. */
|
||||
#define MBA_CMPLT_2_16BIT 0x8032 /* Completion 2 16bit IOSB. */
|
||||
|
||||
@@ -3063,6 +3063,7 @@ qla2x00_update_fcports(scsi_qla_host_t *ha)
|
||||
int
|
||||
qla2x00_abort_isp(scsi_qla_host_t *ha)
|
||||
{
|
||||
int rval;
|
||||
unsigned long flags = 0;
|
||||
uint16_t cnt;
|
||||
srb_t *sp;
|
||||
@@ -3119,6 +3120,16 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
|
||||
|
||||
ha->isp_abort_cnt = 0;
|
||||
clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
|
||||
|
||||
if (ha->eft) {
|
||||
rval = qla2x00_trace_control(ha, TC_ENABLE,
|
||||
ha->eft_dma, EFT_NUM_BUFFERS);
|
||||
if (rval) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Unable to reinitialize EFT "
|
||||
"(%d).\n", rval);
|
||||
}
|
||||
}
|
||||
} else { /* failed the ISP abort */
|
||||
ha->flags.online = 1;
|
||||
if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
|
||||
|
||||
@@ -471,6 +471,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
|
||||
mrk24->nport_handle = cpu_to_le16(loop_id);
|
||||
mrk24->lun[1] = LSB(lun);
|
||||
mrk24->lun[2] = MSB(lun);
|
||||
host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
|
||||
} else {
|
||||
SET_TARGET_ID(ha, mrk->target, loop_id);
|
||||
mrk->lun = cpu_to_le16(lun);
|
||||
|
||||
@@ -587,6 +587,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
|
||||
DEBUG2(printk("scsi(%ld): Discard RND Frame -- %04x %04x "
|
||||
"%04x.\n", ha->host_no, mb[1], mb[2], mb[3]));
|
||||
break;
|
||||
|
||||
case MBA_TRACE_NOTIFICATION:
|
||||
DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
|
||||
ha->host_no, mb[1], mb[2]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -744,7 +744,6 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
|
||||
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
|
||||
srb_t *sp;
|
||||
int ret;
|
||||
unsigned int id, lun;
|
||||
unsigned long serial;
|
||||
@@ -755,8 +754,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
||||
lun = cmd->device->lun;
|
||||
serial = cmd->serial_number;
|
||||
|
||||
sp = (srb_t *) CMD_SP(cmd);
|
||||
if (!sp || !fcport)
|
||||
if (!fcport)
|
||||
return ret;
|
||||
|
||||
qla_printk(KERN_INFO, ha,
|
||||
@@ -875,7 +873,6 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
|
||||
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
|
||||
srb_t *sp;
|
||||
int ret;
|
||||
unsigned int id, lun;
|
||||
unsigned long serial;
|
||||
@@ -886,8 +883,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
|
||||
lun = cmd->device->lun;
|
||||
serial = cmd->serial_number;
|
||||
|
||||
sp = (srb_t *) CMD_SP(cmd);
|
||||
if (!sp || !fcport)
|
||||
if (!fcport)
|
||||
return ret;
|
||||
|
||||
qla_printk(KERN_INFO, ha,
|
||||
@@ -936,7 +932,6 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
|
||||
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
|
||||
srb_t *sp;
|
||||
int ret;
|
||||
unsigned int id, lun;
|
||||
unsigned long serial;
|
||||
@@ -947,8 +942,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
||||
lun = cmd->device->lun;
|
||||
serial = cmd->serial_number;
|
||||
|
||||
sp = (srb_t *) CMD_SP(cmd);
|
||||
if (!sp || !fcport)
|
||||
if (!fcport)
|
||||
return ret;
|
||||
|
||||
qla_printk(KERN_INFO, ha,
|
||||
@@ -2244,9 +2238,6 @@ qla2x00_do_dpc(void *data)
|
||||
|
||||
next_loopid = 0;
|
||||
list_for_each_entry(fcport, &ha->fcports, list) {
|
||||
if (fcport->port_type != FCT_TARGET)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the port is not ONLINE then try to login
|
||||
* to it if we haven't run out of retries.
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
/*
|
||||
* Driver version
|
||||
*/
|
||||
#define QLA2XXX_VERSION "8.01.05-k3"
|
||||
#define QLA2XXX_VERSION "8.01.07-k1"
|
||||
|
||||
#define QLA_DRIVER_MAJOR_VER 8
|
||||
#define QLA_DRIVER_MINOR_VER 1
|
||||
#define QLA_DRIVER_PATCH_VER 5
|
||||
#define QLA_DRIVER_PATCH_VER 7
|
||||
#define QLA_DRIVER_BETA_VER 0
|
||||
|
||||
@@ -269,8 +269,15 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_20619 },
|
||||
|
||||
/* TODO: remove all associated board_20771 code, as it completely
|
||||
* duplicates board_2037x code, unless reason for separation can be
|
||||
* divined.
|
||||
*/
|
||||
#if 0
|
||||
{ PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
board_20771 },
|
||||
#endif
|
||||
|
||||
{ } /* terminate list */
|
||||
};
|
||||
|
||||
|
||||
@@ -1106,7 +1106,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
probe_ent->irq = pdev->irq;
|
||||
probe_ent->irq_flags = IRQF_SHARED;
|
||||
probe_ent->mmio_base = port_base;
|
||||
probe_ent->private_data = hpriv;
|
||||
|
||||
hpriv->host_base = host_base;
|
||||
|
||||
@@ -74,6 +74,7 @@ enum {
|
||||
static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
|
||||
static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
|
||||
static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
|
||||
static void vt6420_error_handler(struct ata_port *ap);
|
||||
|
||||
static const struct pci_device_id svia_pci_tbl[] = {
|
||||
{ 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
|
||||
@@ -107,7 +108,38 @@ static struct scsi_host_template svia_sht = {
|
||||
.bios_param = ata_std_bios_param,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations svia_sata_ops = {
|
||||
static const struct ata_port_operations vt6420_sata_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
|
||||
.tf_load = ata_tf_load,
|
||||
.tf_read = ata_tf_read,
|
||||
.check_status = ata_check_status,
|
||||
.exec_command = ata_exec_command,
|
||||
.dev_select = ata_std_dev_select,
|
||||
|
||||
.bmdma_setup = ata_bmdma_setup,
|
||||
.bmdma_start = ata_bmdma_start,
|
||||
.bmdma_stop = ata_bmdma_stop,
|
||||
.bmdma_status = ata_bmdma_status,
|
||||
|
||||
.qc_prep = ata_qc_prep,
|
||||
.qc_issue = ata_qc_issue_prot,
|
||||
.data_xfer = ata_pio_data_xfer,
|
||||
|
||||
.freeze = ata_bmdma_freeze,
|
||||
.thaw = ata_bmdma_thaw,
|
||||
.error_handler = vt6420_error_handler,
|
||||
.post_internal_cmd = ata_bmdma_post_internal_cmd,
|
||||
|
||||
.irq_handler = ata_interrupt,
|
||||
.irq_clear = ata_bmdma_irq_clear,
|
||||
|
||||
.port_start = ata_port_start,
|
||||
.port_stop = ata_port_stop,
|
||||
.host_stop = ata_host_stop,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations vt6421_sata_ops = {
|
||||
.port_disable = ata_port_disable,
|
||||
|
||||
.tf_load = ata_tf_load,
|
||||
@@ -141,13 +173,13 @@ static const struct ata_port_operations svia_sata_ops = {
|
||||
.host_stop = ata_host_stop,
|
||||
};
|
||||
|
||||
static struct ata_port_info svia_port_info = {
|
||||
static struct ata_port_info vt6420_port_info = {
|
||||
.sht = &svia_sht,
|
||||
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
|
||||
.pio_mask = 0x1f,
|
||||
.mwdma_mask = 0x07,
|
||||
.udma_mask = 0x7f,
|
||||
.port_ops = &svia_sata_ops,
|
||||
.port_ops = &vt6420_sata_ops,
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Jeff Garzik");
|
||||
@@ -170,6 +202,81 @@ static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
|
||||
outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
|
||||
}
|
||||
|
||||
/**
|
||||
* vt6420_prereset - prereset for vt6420
|
||||
* @ap: target ATA port
|
||||
*
|
||||
* SCR registers on vt6420 are pieces of shit and may hang the
|
||||
* whole machine completely if accessed with the wrong timing.
|
||||
* To avoid such catastrophe, vt6420 doesn't provide generic SCR
|
||||
* access operations, but uses SStatus and SControl only during
|
||||
* boot probing in controlled way.
|
||||
*
|
||||
* As the old (pre EH update) probing code is proven to work, we
|
||||
* strictly follow the access pattern.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep)
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno otherwise.
|
||||
*/
|
||||
static int vt6420_prereset(struct ata_port *ap)
|
||||
{
|
||||
struct ata_eh_context *ehc = &ap->eh_context;
|
||||
unsigned long timeout = jiffies + (HZ * 5);
|
||||
u32 sstatus, scontrol;
|
||||
int online;
|
||||
|
||||
/* don't do any SCR stuff if we're not loading */
|
||||
if (!ATA_PFLAG_LOADING)
|
||||
goto skip_scr;
|
||||
|
||||
/* Resume phy. This is the old resume sequence from
|
||||
* __sata_phy_reset().
|
||||
*/
|
||||
svia_scr_write(ap, SCR_CONTROL, 0x300);
|
||||
svia_scr_read(ap, SCR_CONTROL); /* flush */
|
||||
|
||||
/* wait for phy to become ready, if necessary */
|
||||
do {
|
||||
msleep(200);
|
||||
if ((svia_scr_read(ap, SCR_STATUS) & 0xf) != 1)
|
||||
break;
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
/* open code sata_print_link_status() */
|
||||
sstatus = svia_scr_read(ap, SCR_STATUS);
|
||||
scontrol = svia_scr_read(ap, SCR_CONTROL);
|
||||
|
||||
online = (sstatus & 0xf) == 0x3;
|
||||
|
||||
ata_port_printk(ap, KERN_INFO,
|
||||
"SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n",
|
||||
online ? "up" : "down", sstatus, scontrol);
|
||||
|
||||
/* SStatus is read one more time */
|
||||
svia_scr_read(ap, SCR_STATUS);
|
||||
|
||||
if (!online) {
|
||||
/* tell EH to bail */
|
||||
ehc->i.action &= ~ATA_EH_RESET_MASK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
skip_scr:
|
||||
/* wait for !BSY */
|
||||
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vt6420_error_handler(struct ata_port *ap)
|
||||
{
|
||||
return ata_bmdma_drive_eh(ap, vt6420_prereset, ata_std_softreset,
|
||||
NULL, ata_std_postreset);
|
||||
}
|
||||
|
||||
static const unsigned int svia_bar_sizes[] = {
|
||||
8, 4, 8, 4, 16, 256
|
||||
};
|
||||
@@ -210,7 +317,7 @@ static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
|
||||
static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
|
||||
{
|
||||
struct ata_probe_ent *probe_ent;
|
||||
struct ata_port_info *ppi = &svia_port_info;
|
||||
struct ata_port_info *ppi = &vt6420_port_info;
|
||||
|
||||
probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
|
||||
if (!probe_ent)
|
||||
@@ -239,7 +346,7 @@ static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
|
||||
|
||||
probe_ent->sht = &svia_sht;
|
||||
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY;
|
||||
probe_ent->port_ops = &svia_sata_ops;
|
||||
probe_ent->port_ops = &vt6421_sata_ops;
|
||||
probe_ent->n_ports = N_PORTS;
|
||||
probe_ent->irq = pdev->irq;
|
||||
probe_ent->irq_flags = IRQF_SHARED;
|
||||
|
||||
@@ -460,7 +460,8 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
|
||||
* Return value:
|
||||
* SUCCESS or FAILED or NEEDS_RETRY
|
||||
**/
|
||||
static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense)
|
||||
static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
|
||||
int cmnd_size, int timeout, int copy_sense)
|
||||
{
|
||||
struct scsi_device *sdev = scmd->device;
|
||||
struct Scsi_Host *shost = sdev->host;
|
||||
@@ -490,6 +491,9 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense
|
||||
old_cmd_len = scmd->cmd_len;
|
||||
old_use_sg = scmd->use_sg;
|
||||
|
||||
memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
|
||||
memcpy(scmd->cmnd, cmnd, cmnd_size);
|
||||
|
||||
if (copy_sense) {
|
||||
int gfp_mask = GFP_ATOMIC;
|
||||
|
||||
@@ -610,8 +614,7 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
|
||||
static unsigned char generic_sense[6] =
|
||||
{REQUEST_SENSE, 0, 0, 0, 252, 0};
|
||||
|
||||
memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
|
||||
return scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 1);
|
||||
return scsi_send_eh_cmnd(scmd, generic_sense, 6, SENSE_TIMEOUT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -736,10 +739,7 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
|
||||
int retry_cnt = 1, rtn;
|
||||
|
||||
retry_tur:
|
||||
memcpy(scmd->cmnd, tur_command, sizeof(tur_command));
|
||||
|
||||
|
||||
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 0);
|
||||
rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, SENSE_TIMEOUT, 0);
|
||||
|
||||
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
|
||||
__FUNCTION__, scmd, rtn));
|
||||
@@ -839,8 +839,8 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
|
||||
if (scmd->device->allow_restart) {
|
||||
int rtn;
|
||||
|
||||
memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
|
||||
rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT, 0);
|
||||
rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
|
||||
START_UNIT_TIMEOUT, 0);
|
||||
if (rtn == SUCCESS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -110,11 +110,8 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
|
||||
sshdr.asc, sshdr.ascq);
|
||||
break;
|
||||
case NOT_READY: /* This happens if there is no disc in drive */
|
||||
if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) {
|
||||
printk(KERN_INFO "Device not ready. Make sure"
|
||||
" there is a disc in the drive.\n");
|
||||
if (sdev->removable)
|
||||
break;
|
||||
}
|
||||
case UNIT_ATTENTION:
|
||||
if (sdev->removable) {
|
||||
sdev->changed = 1;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define ISCSI_SESSION_ATTRS 11
|
||||
#define ISCSI_CONN_ATTRS 11
|
||||
#define ISCSI_HOST_ATTRS 0
|
||||
#define ISCSI_TRANSPORT_VERSION "1.1-646"
|
||||
|
||||
struct iscsi_internal {
|
||||
int daemon_pid;
|
||||
@@ -634,13 +635,13 @@ mempool_zone_get_skb(struct mempool_zone *zone)
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb)
|
||||
iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb, gfp_t gfp)
|
||||
{
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
skb_get(skb);
|
||||
rc = netlink_broadcast(nls, skb, 0, 1, GFP_KERNEL);
|
||||
rc = netlink_broadcast(nls, skb, 0, 1, gfp);
|
||||
if (rc < 0) {
|
||||
mempool_free(skb, zone->pool);
|
||||
printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
|
||||
@@ -749,7 +750,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
|
||||
ev->r.connerror.cid = conn->cid;
|
||||
ev->r.connerror.sid = iscsi_conn_get_sid(conn);
|
||||
|
||||
iscsi_broadcast_skb(conn->z_error, skb);
|
||||
iscsi_broadcast_skb(conn->z_error, skb, GFP_ATOMIC);
|
||||
|
||||
dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
|
||||
error);
|
||||
@@ -895,7 +896,7 @@ int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn)
|
||||
* this will occur if the daemon is not up, so we just warn
|
||||
* the user and when the daemon is restarted it will handle it
|
||||
*/
|
||||
rc = iscsi_broadcast_skb(conn->z_pdu, skb);
|
||||
rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
|
||||
if (rc < 0)
|
||||
dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
|
||||
"session destruction event. Check iscsi daemon\n");
|
||||
@@ -958,7 +959,7 @@ int iscsi_if_create_session_done(struct iscsi_cls_conn *conn)
|
||||
* this will occur if the daemon is not up, so we just warn
|
||||
* the user and when the daemon is restarted it will handle it
|
||||
*/
|
||||
rc = iscsi_broadcast_skb(conn->z_pdu, skb);
|
||||
rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
|
||||
if (rc < 0)
|
||||
dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
|
||||
"session creation event. Check iscsi daemon\n");
|
||||
@@ -1613,6 +1614,9 @@ static __init int iscsi_transport_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
printk(KERN_INFO "Loading iSCSI transport class v%s.",
|
||||
ISCSI_TRANSPORT_VERSION);
|
||||
|
||||
err = class_register(&iscsi_transport_class);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -1678,3 +1682,4 @@ MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
|
||||
"Alex Aizman <itn780@yahoo.com>");
|
||||
MODULE_DESCRIPTION("iSCSI Transport Interface");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
static int sg_version_num = 30533; /* 2 digits for each component */
|
||||
#define SG_VERSION_STR "3.5.33"
|
||||
static int sg_version_num = 30534; /* 2 digits for each component */
|
||||
#define SG_VERSION_STR "3.5.34"
|
||||
|
||||
/*
|
||||
* D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
|
||||
@@ -60,7 +60,7 @@ static int sg_version_num = 30533; /* 2 digits for each component */
|
||||
|
||||
#ifdef CONFIG_SCSI_PROC_FS
|
||||
#include <linux/proc_fs.h>
|
||||
static char *sg_version_date = "20050908";
|
||||
static char *sg_version_date = "20060818";
|
||||
|
||||
static int sg_proc_init(void);
|
||||
static void sg_proc_cleanup(void);
|
||||
@@ -1164,7 +1164,7 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
|
||||
len = vma->vm_end - sa;
|
||||
len = (len < sg->length) ? len : sg->length;
|
||||
if (offset < len) {
|
||||
page = sg->page;
|
||||
page = virt_to_page(page_address(sg->page) + offset);
|
||||
get_page(page); /* increment page count */
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2084,7 +2084,7 @@ static struct pci_device_id sym2_id_table[] __devinitdata = {
|
||||
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C860,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
|
||||
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1510,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
|
||||
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SCSI<<8, 0xffff00, 0UL },
|
||||
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C896,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
|
||||
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C895,
|
||||
|
||||
Reference in New Issue
Block a user