diff options
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_os.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ee47820c30a6..cd15678f9ada 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -68,12 +68,34 @@ MODULE_PARM_DESC(ql4xmaxqdepth, " Maximum queue depth to report for target devices.\n" "\t\t Default: 32."); +static int ql4xqfulltracking = 1; +module_param(ql4xqfulltracking, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ql4xqfulltracking, + " Enable or disable dynamic tracking and adjustment of\n" + "\t\t scsi device queue depth.\n" + "\t\t 0 - Disable.\n" + "\t\t 1 - Enable. (Default)"); + static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO; module_param(ql4xsess_recovery_tmo, int, S_IRUGO); MODULE_PARM_DESC(ql4xsess_recovery_tmo, " Target Session Recovery Timeout.\n" "\t\t Default: 120 sec."); +int ql4xmdcapmask = 0x1F; +module_param(ql4xmdcapmask, int, S_IRUGO); +MODULE_PARM_DESC(ql4xmdcapmask, + " Set the Minidump driver capture mask level.\n" + "\t\t Default is 0x1F.\n" + "\t\t Can be set to 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F"); + +int ql4xenablemd = 1; +module_param(ql4xenablemd, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ql4xenablemd, + " Set to enable minidump.\n" + "\t\t 0 - disable minidump\n" + "\t\t 1 - enable minidump (Default)"); + static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); /* * SCSI host template entry points @@ -140,6 +162,8 @@ static int qla4xxx_slave_configure(struct scsi_device *device); static void qla4xxx_slave_destroy(struct scsi_device *sdev); static umode_t ql4_attr_is_visible(int param_type, int param); static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type); +static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth, + int reason); static struct qla4_8xxx_legacy_intr_set legacy_intr[] = QLA82XX_LEGACY_INTR_CONFIG; @@ -159,6 +183,7 @@ static struct scsi_host_template qla4xxx_driver_template = { .slave_configure = qla4xxx_slave_configure, .slave_alloc = qla4xxx_slave_alloc, .slave_destroy = qla4xxx_slave_destroy, + .change_queue_depth = qla4xxx_change_queue_depth, .this_id = -1, .cmd_per_lun = 3, @@ -1555,19 +1580,53 @@ static void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess) struct iscsi_session *sess; struct ddb_entry *ddb_entry; struct scsi_qla_host *ha; - unsigned long flags; + unsigned long flags, wtime; + struct dev_db_entry *fw_ddb_entry = NULL; + dma_addr_t fw_ddb_entry_dma; + uint32_t ddb_state; + int ret; DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); sess = cls_sess->dd_data; ddb_entry = sess->dd_data; ha = ddb_entry->ha; + fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), + &fw_ddb_entry_dma, GFP_KERNEL); + if (!fw_ddb_entry) { + ql4_printk(KERN_ERR, ha, + "%s: Unable to allocate dma buffer\n", __func__); + goto destroy_session; + } + + wtime = jiffies + (HZ * LOGOUT_TOV); + do { + ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, + fw_ddb_entry, fw_ddb_entry_dma, + NULL, NULL, &ddb_state, NULL, + NULL, NULL); + if (ret == QLA_ERROR) + goto destroy_session; + + if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) || + (ddb_state == DDB_DS_SESSION_FAILED)) + goto destroy_session; + + schedule_timeout_uninterruptible(HZ); + } while ((time_after(wtime, jiffies))); + +destroy_session: qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); spin_lock_irqsave(&ha->hardware_lock, flags); qla4xxx_free_ddb(ha, ddb_entry); spin_unlock_irqrestore(&ha->hardware_lock, flags); + iscsi_session_teardown(cls_sess); + + if (fw_ddb_entry) + dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), + fw_ddb_entry, fw_ddb_entry_dma); } static struct iscsi_cls_conn * @@ -2220,6 +2279,9 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues, ha->queues_dma); + if (ha->fw_dump) + vfree(ha->fw_dump); + ha->queues_len = 0; ha->queues = NULL; ha->queues_dma = 0; @@ -2229,6 +2291,8 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) ha->response_dma = 0; ha->shadow_regs = NULL; ha->shadow_regs_dma = 0; + ha->fw_dump = NULL; + ha->fw_dump_size = 0; /* Free srb pool. */ if (ha->srb_mempool) @@ -5023,6 +5087,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, set_bit(AF_INIT_DONE, &ha->flags); + qla4_8xxx_alloc_sysfs_attr(ha); + printk(KERN_INFO " QLogic iSCSI HBA Driver version: %s\n" " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n", @@ -5149,6 +5215,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) iscsi_boot_destroy_kset(ha->boot_kset); qla4xxx_destroy_fw_ddb_session(ha); + qla4_8xxx_free_sysfs_attr(ha); scsi_remove_host(ha->host); @@ -5217,6 +5284,15 @@ static void qla4xxx_slave_destroy(struct scsi_device *sdev) scsi_deactivate_tcq(sdev, 1); } +static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth, + int reason) +{ + if (!ql4xqfulltracking) + return -EOPNOTSUPP; + + return iscsi_change_queue_depth(sdev, qdepth, reason); +} + /** * qla4xxx_del_from_active_array - returns an active srb * @ha: Pointer to host adapter structure. |