#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
+#include <linux/smp_lock.h>
#include <linux/delay.h>
-#include <linux/kthread.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h>
* Either SUCCESS or FAILED.
*
* Note:
-* Only return FAILED if command not returned by firmware.
**************************************************************************/
int
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
unsigned int id, lun;
unsigned long serial;
unsigned long flags;
- int wait = 0;
if (!CMD_SP(cmd))
- return SUCCESS;
+ return FAILED;
- ret = SUCCESS;
+ ret = FAILED;
id = cmd->device->id;
lun = cmd->device->lun;
} else {
DEBUG3(printk("%s(%ld): abort_command "
"mbx success.\n", __func__, ha->host_no));
- wait = 1;
+ ret = SUCCESS;
}
spin_lock_irqsave(&ha->hardware_lock, flags);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Wait for the command to be returned. */
- if (wait) {
+ if (ret == SUCCESS) {
if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
qla_printk(KERN_ERR, ha,
"scsi(%ld:%d:%d): Abort handler timed out -- %lx "
"%x.\n", ha->host_no, id, lun, serial, ret);
- ret = FAILED;
}
}
qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n",
- ha->host_no, id, lun, wait, serial, ret);
+ "scsi(%ld:%d:%d): Abort command issued -- %lx %x.\n", ha->host_no,
+ id, lun, serial, ret);
return ret;
}
pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK);
}
-static inline void
-qla2x00_set_isp_flags(scsi_qla_host_t *ha)
-{
- ha->device_type = DT_EXTENDED_IDS;
- switch (ha->pdev->device) {
- case PCI_DEVICE_ID_QLOGIC_ISP2100:
- ha->device_type |= DT_ISP2100;
- ha->device_type &= ~DT_EXTENDED_IDS;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP2200:
- ha->device_type |= DT_ISP2200;
- ha->device_type &= ~DT_EXTENDED_IDS;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP2300:
- ha->device_type |= DT_ISP2300;
- ha->device_type |= DT_ZIO_SUPPORTED;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP2312:
- ha->device_type |= DT_ISP2312;
- ha->device_type |= DT_ZIO_SUPPORTED;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP2322:
- ha->device_type |= DT_ISP2322;
- ha->device_type |= DT_ZIO_SUPPORTED;
- if (ha->pdev->subsystem_vendor == 0x1028 &&
- ha->pdev->subsystem_device == 0x0170)
- ha->device_type |= DT_OEM_001;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP6312:
- ha->device_type |= DT_ISP6312;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP6322:
- ha->device_type |= DT_ISP6322;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP2422:
- ha->device_type |= DT_ISP2422;
- ha->device_type |= DT_ZIO_SUPPORTED;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP2432:
- ha->device_type |= DT_ISP2432;
- ha->device_type |= DT_ZIO_SUPPORTED;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP5422:
- ha->device_type |= DT_ISP5422;
- break;
- case PCI_DEVICE_ID_QLOGIC_ISP5432:
- ha->device_type |= DT_ISP5432;
- break;
- }
-}
-
static int
qla2x00_iospace_config(scsi_qla_host_t *ha)
{
ha->brd_info = brd_info;
sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no);
- /* Set ISP-type information. */
- qla2x00_set_isp_flags(ha);
+ ha->dpc_pid = -1;
/* Configure PCI I/O space */
ret = qla2x00_iospace_config(ha);
ha->gid_list_info_size = 6;
if (IS_QLA2322(ha) || IS_QLA6322(ha))
ha->optrom_size = OPTROM_SIZE_2322;
- } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+ } else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
*/
spin_lock_init(&ha->mbx_reg_lock);
+ init_completion(&ha->dpc_inited);
+ init_completion(&ha->dpc_exited);
+
qla2x00_config_dma_addressing(ha);
if (qla2x00_mem_alloc(ha)) {
qla_printk(KERN_WARNING, ha,
/*
* Startup the kernel thread for this host adapter
*/
- ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
- "%s_dpc", ha->host_str);
- if (IS_ERR(ha->dpc_thread)) {
+ ha->dpc_should_die = 0;
+ ha->dpc_pid = kernel_thread(qla2x00_do_dpc, ha, 0);
+ if (ha->dpc_pid < 0) {
qla_printk(KERN_WARNING, ha,
"Unable to start DPC thread!\n");
- ret = PTR_ERR(ha->dpc_thread);
+
+ ret = -ENODEV;
goto probe_failed;
}
+ wait_for_completion(&ha->dpc_inited);
host->this_id = 255;
host->cmd_per_lun = 3;
spin_lock_irqsave(&ha->hardware_lock, flags);
reg = ha->iobase;
- if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT);
WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT);
} else {
static void
qla2x00_free_device(scsi_qla_host_t *ha)
{
+ int ret;
+
/* Abort any outstanding IO descriptors. */
if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
qla2x00_cancel_io_descriptors(ha);
qla2x00_stop_timer(ha);
/* Kill the kernel thread for this host */
- if (ha->dpc_thread) {
- struct task_struct *t = ha->dpc_thread;
+ if (ha->dpc_pid >= 0) {
+ ha->dpc_should_die = 1;
+ wmb();
+ ret = kill_proc(ha->dpc_pid, SIGHUP, 1);
+ if (ret) {
+ qla_printk(KERN_ERR, ha,
+ "Unable to signal DPC thread -- (%d)\n", ret);
- /*
- * qla2xxx_wake_dpc checks for ->dpc_thread
- * so we need to zero it out.
- */
- ha->dpc_thread = NULL;
- kthread_stop(t);
+ /* TODO: SOMETHING MORE??? */
+ } else {
+ wait_for_completion(&ha->dpc_exited);
+ }
}
/* Stop currently executing firmware. */
ha->flags.online = 0;
/* Detach interrupts */
- if (ha->host->irq)
- free_irq(ha->host->irq, ha);
+ if (ha->pdev->irq)
+ free_irq(ha->pdev->irq, ha);
/* release io space registers */
if (ha->iobase)
atomic_set(&fcport->state, FCS_DEVICE_LOST);
}
- if (defer)
- qla2xxx_wake_dpc(ha);
+ if (defer && ha->dpc_wait && !ha->dpc_active)
+ up(ha->dpc_wait);
}
/*
{
struct list_head *fcpl, *fcptemp;
fc_port_t *fcport;
+ unsigned int wtime;/* max wait time if mbx cmd is busy. */
if (ha == NULL) {
/* error */
return;
}
+ /* Make sure all other threads are stopped. */
+ wtime = 60 * 1000;
+ while (ha->dpc_wait && wtime)
+ wtime = msleep_interruptible(wtime);
+
/* free ioctl memory */
qla2x00_free_ioctl_mem(ha);
int rval;
rval = QLA_SUCCESS;
- ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
+ ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab,
+ mempool_free_slab, srb_cachep);
if (ha->srb_mempool == NULL) {
qla_printk(KERN_INFO, ha, "Unable to allocate SRB mempool.\n");
rval = QLA_FUNCTION_FAILED;
static int
qla2x00_do_dpc(void *data)
{
+ DECLARE_MUTEX_LOCKED(sem);
scsi_qla_host_t *ha;
fc_port_t *fcport;
uint8_t status;
ha = (scsi_qla_host_t *)data;
+ lock_kernel();
+
+ daemonize("%s_dpc", ha->host_str);
+ allow_signal(SIGHUP);
+
+ ha->dpc_wait = &sem;
+
set_user_nice(current, -20);
- while (!kthread_should_stop()) {
+ unlock_kernel();
+
+ complete(&ha->dpc_inited);
+
+ while (1) {
DEBUG3(printk("qla2x00: DPC handler sleeping\n"));
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- __set_current_state(TASK_RUNNING);
+ if (down_interruptible(&sem))
+ break;
+
+ if (ha->dpc_should_die)
+ break;
DEBUG3(printk("qla2x00: DPC handler waking up\n"));
/* Initialization not yet finished. Don't do anything yet. */
- if (!ha->flags.init_done)
+ if (!ha->flags.init_done || ha->dpc_active)
continue;
DEBUG3(printk("scsi(%ld): DPC handler\n", ha->host_no));
} else
status =
qla2x00_local_device_login(
- ha, fcport);
+ ha, fcport->loop_id);
if (status == QLA_SUCCESS) {
fcport->old_loop_id = fcport->loop_id;
/*
* Make sure that nobody tries to wake us up again.
*/
+ ha->dpc_wait = NULL;
ha->dpc_active = 0;
- return 0;
-}
-
-void
-qla2xxx_wake_dpc(scsi_qla_host_t *ha)
-{
- if (ha->dpc_thread)
- wake_up_process(ha->dpc_thread);
+ complete_and_exit(&ha->dpc_exited, 0);
}
/*
test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
- test_bit(RELOGIN_NEEDED, &ha->dpc_flags)))
- qla2xxx_wake_dpc(ha);
+ test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) &&
+ ha->dpc_wait && !ha->dpc_active) {
+
+ up(ha->dpc_wait);
+ }
qla2x00_restart_timer(ha, WATCH_INTERVAL);
}
/* Firmware interface routines. */
-#define FW_BLOBS 5
+#define FW_BLOBS 6
#define FW_ISP21XX 0
#define FW_ISP22XX 1
#define FW_ISP2300 2
#define FW_ISP2322 3
-#define FW_ISP24XX 4
+#define FW_ISP63XX 4
+#define FW_ISP24XX 5
static DECLARE_MUTEX(qla_fw_lock);
{ .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, },
{ .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, },
{ .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
+ { .name = "ql6312_fw.bin", .segs = { 0x800, 0 }, },
{ .name = "ql2400_fw.bin", },
};
blob = &qla_fw_blobs[FW_ISP21XX];
} else if (IS_QLA2200(ha)) {
blob = &qla_fw_blobs[FW_ISP22XX];
- } else if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
+ } else if (IS_QLA2300(ha) || IS_QLA2312(ha)) {
blob = &qla_fw_blobs[FW_ISP2300];
- } else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ } else if (IS_QLA2322(ha)) {
blob = &qla_fw_blobs[FW_ISP2322];
- } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+ } else if (IS_QLA6312(ha) || IS_QLA6322(ha)) {
+ blob = &qla_fw_blobs[FW_ISP63XX];
+ } else if (IS_QLA24XX(ha)) {
blob = &qla_fw_blobs[FW_ISP24XX];
}
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432,
PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422,
- PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432,
- PCI_ANY_ID, PCI_ANY_ID, },
{ 0 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);