diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/Makefile | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 54 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 37 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.h | 19 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 52 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dfs.c | 175 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 30 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 51 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 97 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 120 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 430 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 46 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 80 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 18 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 2 |
15 files changed, 655 insertions, 558 deletions
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index 71ddb5db494..c51fd1f8663 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile @@ -1,4 +1,4 @@ qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ - qla_dbg.o qla_sup.o qla_attr.o qla_mid.o + qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index fb388b8c07c..adf97320574 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -9,7 +9,7 @@ #include <linux/kthread.h> #include <linux/vmalloc.h> -int qla24xx_vport_disable(struct fc_vport *, bool); +static int qla24xx_vport_disable(struct fc_vport *, bool); /* SYSFS attributes --------------------------------------------------------- */ @@ -958,7 +958,7 @@ qla2x00_issue_lip(struct Scsi_Host *shost) { scsi_qla_host_t *ha = shost_priv(shost); - set_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); + qla2x00_loop_reset(ha); return 0; } @@ -967,35 +967,51 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) { scsi_qla_host_t *ha = shost_priv(shost); int rval; - uint16_t mb_stat[1]; - link_stat_t stat_buf; + struct link_statistics *stats; + dma_addr_t stats_dma; struct fc_host_statistics *pfc_host_stat; - rval = QLA_FUNCTION_FAILED; pfc_host_stat = &ha->fc_host_stat; memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); + stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma); + if (stats == NULL) { + DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n", + __func__, ha->host_no)); + goto done; + } + memset(stats, 0, DMA_POOL_SIZE); + + rval = QLA_FUNCTION_FAILED; if (IS_FWI2_CAPABLE(ha)) { - rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, - sizeof(stat_buf) / 4, mb_stat); + rval = qla24xx_get_isp_stats(ha, stats, stats_dma); } else if (atomic_read(&ha->loop_state) == LOOP_READY && !test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) && !test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) && !ha->dpc_active) { /* Must be in a 'READY' state for statistics retrieval. */ - rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf, - mb_stat); + rval = qla2x00_get_link_status(ha, ha->loop_id, stats, + stats_dma); } if (rval != QLA_SUCCESS) - goto done; + goto done_free; + + pfc_host_stat->link_failure_count = stats->link_fail_cnt; + pfc_host_stat->loss_of_sync_count = stats->loss_sync_cnt; + pfc_host_stat->loss_of_signal_count = stats->loss_sig_cnt; + pfc_host_stat->prim_seq_protocol_err_count = stats->prim_seq_err_cnt; + pfc_host_stat->invalid_tx_word_count = stats->inval_xmit_word_cnt; + pfc_host_stat->invalid_crc_count = stats->inval_crc_cnt; + if (IS_FWI2_CAPABLE(ha)) { + pfc_host_stat->tx_frames = stats->tx_frames; + pfc_host_stat->rx_frames = stats->rx_frames; + pfc_host_stat->dumped_frames = stats->dumped_frames; + pfc_host_stat->nos_count = stats->nos_rcvd; + } - pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt; - pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt; - pfc_host_stat->loss_of_signal_count = stat_buf.loss_sig_cnt; - pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt; - pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt; - pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt; +done_free: + dma_pool_free(ha->s_dma_pool, stats, stats_dma); done: return pfc_host_stat; } @@ -1113,7 +1129,7 @@ vport_create_failed_2: return FC_VPORT_FAILED; } -int +static int qla24xx_vport_delete(struct fc_vport *fc_vport) { scsi_qla_host_t *ha = shost_priv(fc_vport->shost); @@ -1124,7 +1140,7 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) down(&ha->vport_sem); ha->cur_vport_count--; - clear_bit(vha->vp_idx, (unsigned long *)ha->vp_idx_map); + clear_bit(vha->vp_idx, ha->vp_idx_map); up(&ha->vport_sem); kfree(vha->node_name); @@ -1146,7 +1162,7 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) return 0; } -int +static int qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable) { scsi_qla_host_t *vha = fc_vport->dd_data; diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index eaa04dabcdf..d88e98c476b 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -1051,6 +1051,7 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) struct qla25xx_fw_dump *fw; uint32_t ext_mem_cnt; void *nxt; + struct qla2xxx_fce_chain *fcec; risc_address = ext_mem_cnt = 0; flags = 0; @@ -1321,10 +1322,31 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) if (rval != QLA_SUCCESS) goto qla25xx_fw_dump_failed_0; + /* Fibre Channel Trace Buffer. */ nxt = qla2xxx_copy_queues(ha, nxt); if (ha->eft) memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); + /* Fibre Channel Event Buffer. */ + if (!ha->fce) + goto qla25xx_fw_dump_failed_0; + + ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); + + fcec = nxt + ntohl(ha->fw_dump->eft_size); + fcec->type = __constant_htonl(DUMP_CHAIN_FCE | DUMP_CHAIN_LAST); + fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) + + fce_calc_size(ha->fce_bufs)); + fcec->size = htonl(fce_calc_size(ha->fce_bufs)); + fcec->addr_l = htonl(LSD(ha->fce_dma)); + fcec->addr_h = htonl(MSD(ha->fce_dma)); + + iter_reg = fcec->eregs; + for (cnt = 0; cnt < 8; cnt++) + *iter_reg++ = htonl(ha->fce_mb[cnt]); + + memcpy(iter_reg, ha->fce, ntohl(fcec->size)); + qla25xx_fw_dump_failed_0: if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, @@ -1428,21 +1450,6 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd) printk(" sp flags=0x%x\n", sp->flags); } -void -qla2x00_dump_pkt(void *pkt) -{ - uint32_t i; - uint8_t *data = (uint8_t *) pkt; - - for (i = 0; i < 64; i++) { - if (!(i % 4)) - printk("\n%02x: ", i); - - printk("%02x ", data[i]); - } - printk("\n"); -} - #if defined(QL_DEBUG_ROUTINES) /* * qla2x00_formatted_dump_buffer diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index a50ecf0b7c8..524598afc81 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -256,6 +256,25 @@ struct qla25xx_fw_dump { #define EFT_BYTES_PER_BUFFER 0x4000 #define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS)) +#define FCE_NUM_BUFFERS 64 +#define FCE_BYTES_PER_BUFFER 0x400 +#define FCE_SIZE ((FCE_BYTES_PER_BUFFER) * (FCE_NUM_BUFFERS)) +#define fce_calc_size(b) ((FCE_BYTES_PER_BUFFER) * (b)) + +struct qla2xxx_fce_chain { + uint32_t type; + uint32_t chain_size; + + uint32_t size; + uint32_t addr_l; + uint32_t addr_h; + uint32_t eregs[8]; +}; + +#define DUMP_CHAIN_VARIANT 0x80000000 +#define DUMP_CHAIN_FCE 0x7FFFFAF0 +#define DUMP_CHAIN_LAST 0x80000000 + struct qla2xxx_fw_dump { uint8_t signature[4]; uint32_t version; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 04e8cbca4c0..6f129da3758 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -623,9 +623,6 @@ typedef struct { #define MBC_GET_LINK_PRIV_STATS 0x6d /* Get link & private data. */ #define MBC_SET_VENDOR_ID 0x76 /* Set Vendor ID. */ -#define TC_ENABLE 4 -#define TC_DISABLE 5 - /* Firmware return data sizes */ #define FCAL_MAP_SIZE 128 @@ -862,14 +859,20 @@ typedef struct { #define GLSO_SEND_RPS BIT_0 #define GLSO_USE_DID BIT_3 -typedef struct { - uint32_t link_fail_cnt; - uint32_t loss_sync_cnt; - uint32_t loss_sig_cnt; - uint32_t prim_seq_err_cnt; - uint32_t inval_xmit_word_cnt; - uint32_t inval_crc_cnt; -} link_stat_t; +struct link_statistics { + uint32_t link_fail_cnt; + uint32_t loss_sync_cnt; + uint32_t loss_sig_cnt; + uint32_t prim_seq_err_cnt; + uint32_t inval_xmit_word_cnt; + uint32_t inval_crc_cnt; + uint32_t unused1[0x1b]; + uint32_t tx_frames; + uint32_t rx_frames; + uint32_t dumped_frames; + uint32_t unused2[2]; + uint32_t nos_rcvd; +}; /* * NVRAM Command values. @@ -2116,14 +2119,6 @@ struct qla_msix_entry { #define WATCH_INTERVAL 1 /* number of seconds */ -/* NPIV */ -#define MAX_MULTI_ID_LOOP 126 -#define MAX_MULTI_ID_FABRIC 64 -#define MAX_NUM_VPORT_LOOP (MAX_MULTI_ID_LOOP - 1) -#define MAX_NUM_VPORT_FABRIC (MAX_MULTI_ID_FABRIC - 1) -#define MAX_NUM_VHBA_LOOP (MAX_MULTI_ID_LOOP - 1) -#define MAX_NUM_VHBA_FABRIC (MAX_MULTI_ID_FABRIC - 1) - /* * Linux Host Adapter structure */ @@ -2161,6 +2156,7 @@ typedef struct scsi_qla_host { uint32_t gpsc_supported :1; uint32_t vsan_enabled :1; uint32_t npiv_supported :1; + uint32_t fce_enabled :1; } flags; atomic_t loop_state; @@ -2273,8 +2269,7 @@ typedef struct scsi_qla_host { int bars; device_reg_t __iomem *iobase; /* Base I/O address */ - unsigned long pio_address; - unsigned long pio_length; + resource_size_t pio_address; #define MIN_IOBASE_LEN 0x100 /* ISP ring lock, rings, and indexes */ @@ -2416,9 +2411,9 @@ typedef struct scsi_qla_host { #define MBX_INTR_WAIT 2 #define MBX_UPDATE_FLASH_ACTIVE 3 - struct semaphore mbx_cmd_sem; /* Serialialize mbx access */ struct semaphore vport_sem; /* Virtual port synchronization */ - struct semaphore mbx_intr_sem; /* Used for completion notification */ + struct completion mbx_cmd_comp; /* Serialize mbx access */ + struct completion mbx_intr_comp; /* Used for completion notification */ uint32_t mbx_flags; #define MBX_IN_PROGRESS BIT_0 @@ -2455,6 +2450,15 @@ typedef struct scsi_qla_host { dma_addr_t eft_dma; void *eft; + struct dentry *dfs_dir; + struct dentry *dfs_fce; + dma_addr_t fce_dma; + void *fce; + uint32_t fce_bufs; + uint16_t fce_mb[8]; + uint64_t fce_wr, fce_rd; + struct mutex fce_mutex; + uint8_t host_str[16]; uint32_t pci_attr; uint16_t chip_revision; @@ -2507,7 +2511,7 @@ typedef struct scsi_qla_host { struct list_head vp_list; /* list of VP */ struct fc_vport *fc_vport; /* holds fc_vport * for each vport */ - uint8_t vp_idx_map[16]; + unsigned long vp_idx_map[(MAX_MULTI_ID_FABRIC / 8) / sizeof(unsigned long)]; uint16_t num_vhosts; /* number of vports created */ uint16_t num_vsans; /* number of vsan created */ uint16_t vp_idx; /* vport ID */ diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c new file mode 100644 index 00000000000..1479c60441c --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -0,0 +1,175 @@ +/* + * QLogic Fibre Channel HBA Driver + * Copyright (c) 2003-2005 QLogic Corporation + * + * See LICENSE.qla2xxx for copyright and licensing details. + */ +#include "qla_def.h" + +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +static struct dentry *qla2x00_dfs_root; +static atomic_t qla2x00_dfs_root_count; + +static int +qla2x00_dfs_fce_show(struct seq_file *s, void *unused) +{ + scsi_qla_host_t *ha = s->private; + uint32_t cnt; + uint32_t *fce; + uint64_t fce_start; + + mutex_lock(&ha->fce_mutex); + + seq_printf(s, "FCE Trace Buffer\n"); + seq_printf(s, "In Pointer = %llx\n\n", ha->fce_wr); + seq_printf(s, "Base = %llx\n\n", (unsigned long long) ha->fce_dma); + seq_printf(s, "FCE Enable Registers\n"); + seq_printf(s, "%08x %08x %08x %08x %08x %08x\n", + ha->fce_mb[0], ha->fce_mb[2], ha->fce_mb[3], ha->fce_mb[4], + ha->fce_mb[5], ha->fce_mb[6]); + + fce = (uint32_t *) ha->fce; + fce_start = (unsigned long long) ha->fce_dma; + for (cnt = 0; cnt < fce_calc_size(ha->fce_bufs) / 4; cnt++) { + if (cnt % 8 == 0) + seq_printf(s, "\n%llx: ", + (unsigned long long)((cnt * 4) + fce_start)); + else + seq_printf(s, " "); + seq_printf(s, "%08x", *fce++); + } + + seq_printf(s, "\nEnd\n"); + + mutex_unlock(&ha->fce_mutex); + + return 0; +} + +static int +qla2x00_dfs_fce_open(struct inode *inode, struct file *file) +{ + scsi_qla_host_t *ha = inode->i_private; + int rval; + + if (!ha->flags.fce_enabled) + goto out; + + mutex_lock(&ha->fce_mutex); + + /* Pause tracing to flush FCE buffers. */ + rval = qla2x00_disable_fce_trace(ha, &ha->fce_wr, &ha->fce_rd); + if (rval) + qla_printk(KERN_WARNING, ha, + "DebugFS: Unable to disable FCE (%d).\n", rval); + + ha->flags.fce_enabled = 0; + + mutex_unlock(&ha->fce_mutex); +out: + return single_open(file, qla2x00_dfs_fce_show, ha); +} + +static int +qla2x00_dfs_fce_release(struct inode *inode, struct file *file) +{ + scsi_qla_host_t *ha = inode->i_private; + int rval; + + if (ha->flags.fce_enabled) + goto out; + + mutex_lock(&ha->fce_mutex); + + /* Re-enable FCE tracing. */ + ha->flags.fce_enabled = 1; + memset(ha->fce, 0, fce_calc_size(ha->fce_bufs)); + rval = qla2x00_enable_fce_trace(ha, ha->fce_dma, ha->fce_bufs, + ha->fce_mb, &ha->fce_bufs); + if (rval) { + qla_printk(KERN_WARNING, ha, + "DebugFS: Unable to reinitialize FCE (%d).\n", rval); + ha->flags.fce_enabled = 0; + } + + mutex_unlock(&ha->fce_mutex); +out: + return single_release(inode, file); +} + +static const struct file_operations dfs_fce_ops = { + .open = qla2x00_dfs_fce_open, + .read = seq_read, + .llseek = seq_lseek, + .release = qla2x00_dfs_fce_release, +}; + +int +qla2x00_dfs_setup(scsi_qla_host_t *ha) +{ + if (!IS_QLA25XX(ha)) + goto out; + if (!ha->fce) + goto out; + + if (qla2x00_dfs_root) + goto create_dir; + + atomic_set(&qla2x00_dfs_root_count, 0); + qla2x00_dfs_root = debugfs_create_dir(QLA2XXX_DRIVER_NAME, NULL); + if (!qla2x00_dfs_root) { + qla_printk(KERN_NOTICE, ha, + "DebugFS: Unable to create root directory.\n"); + goto out; + } + +create_dir: + if (ha->dfs_dir) + goto create_nodes; + + mutex_init(&ha->fce_mutex); + ha->dfs_dir = debugfs_create_dir(ha->host_str, qla2x00_dfs_root); + if (!ha->dfs_dir) { + qla_printk(KERN_NOTICE, ha, + "DebugFS: Unable to create ha directory.\n"); + goto out; + } + + atomic_inc(&qla2x00_dfs_root_count); + +create_nodes: + ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, ha, + &dfs_fce_ops); + if (!ha->dfs_fce) { + qla_printk(KERN_NOTICE, ha, + "DebugFS: Unable to fce node.\n"); + goto out; + } +out: + return 0; +} + +int +qla2x00_dfs_remove(scsi_qla_host_t *ha) +{ + if (ha->dfs_fce) { + debugfs_remove(ha->dfs_fce); + ha->dfs_fce = NULL; + } + + if (ha->dfs_dir) { + debugfs_remove(ha->dfs_dir); + ha->dfs_dir = NULL; + atomic_dec(&qla2x00_dfs_root_count); + } + + if (atomic_read(&qla2x00_dfs_root_count) == 0 && + qla2x00_dfs_root) { + debugfs_remove(qla2x00_dfs_root); + qla2x00_dfs_root = NULL; + } + + return 0; +} diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 25364b1aaf1..9337e138ed6 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -952,9 +952,31 @@ struct device_reg_24xx { uint32_t iobase_sdata; }; +/* Trace Control *************************************************************/ + +#define TC_AEN_DISABLE 0 + +#define TC_EFT_ENABLE 4 +#define TC_EFT_DISABLE 5 + +#define TC_FCE_ENABLE 8 +#define TC_FCE_OPTIONS 0 +#define TC_FCE_DEFAULT_RX_SIZE 2112 +#define TC_FCE_DEFAULT_TX_SIZE 2112 +#define TC_FCE_DISABLE 9 +#define TC_FCE_DISABLE_TRACE BIT_0 + /* MID Support ***************************************************************/ -#define MAX_MID_VPS 125 +#define MIN_MULTI_ID_FABRIC 64 /* Must be power-of-2. */ +#define MAX_MULTI_ID_FABRIC 256 /* ... */ + +#define for_each_mapped_vp_idx(_ha, _idx) \ + for (_idx = find_next_bit((_ha)->vp_idx_map, \ + (_ha)->max_npiv_vports + 1, 1); \ + _idx <= (_ha)->max_npiv_vports; \ + _idx = find_next_bit((_ha)->vp_idx_map, \ + (_ha)->max_npiv_vports + 1, _idx + 1)) \ struct mid_conf_entry_24xx { uint16_t reserved_1; @@ -982,7 +1004,7 @@ struct mid_init_cb_24xx { uint16_t count; uint16_t options; - struct mid_conf_entry_24xx entries[MAX_MID_VPS]; + struct mid_conf_entry_24xx entries[MAX_MULTI_ID_FABRIC]; }; @@ -1002,10 +1024,6 @@ struct mid_db_entry_24xx { uint8_t reserved_1; }; -struct mid_db_24xx { - struct mid_db_entry_24xx entries[MAX_MID_VPS]; -}; - /* * Virtual Fabric ID type definition. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 09cb2a90805..ba35fc26ce6 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -65,33 +65,25 @@ extern int ql2xextended_error_logging; extern int ql2xqfullrampup; extern int num_hosts; +extern int qla2x00_loop_reset(scsi_qla_host_t *); + /* * Global Functions in qla_mid.c source file. */ -extern struct scsi_host_template qla2x00_driver_template; extern struct scsi_host_template qla24xx_driver_template; extern struct scsi_transport_template *qla2xxx_transport_vport_template; -extern uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); extern void qla2x00_timer(scsi_qla_host_t *); extern void qla2x00_start_timer(scsi_qla_host_t *, void *, unsigned long); -extern void qla2x00_stop_timer(scsi_qla_host_t *); -extern uint32_t qla24xx_allocate_vp_id(scsi_qla_host_t *); extern void qla24xx_deallocate_vp_id(scsi_qla_host_t *); extern int qla24xx_disable_vp (scsi_qla_host_t *); extern int qla24xx_enable_vp (scsi_qla_host_t *); -extern void qla2x00_mem_free(scsi_qla_host_t *); extern int qla24xx_control_vp(scsi_qla_host_t *, int ); extern int qla24xx_modify_vp_config(scsi_qla_host_t *); extern int qla2x00_send_change_request(scsi_qla_host_t *, uint16_t, uint16_t); extern void qla2x00_vp_stop_timer(scsi_qla_host_t *); extern int qla24xx_configure_vhba (scsi_qla_host_t *); -extern int qla24xx_get_vp_entry(scsi_qla_host_t *, uint16_t, int); -extern int qla24xx_get_vp_database(scsi_qla_host_t *, uint16_t); -extern int qla2x00_do_dpc_vp(scsi_qla_host_t *); extern void qla24xx_report_id_acquisition(scsi_qla_host_t *, struct vp_rpt_id_entry_24xx *); -extern scsi_qla_host_t * qla24xx_find_vhost_by_name(scsi_qla_host_t *, - uint8_t *); extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *); extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *); extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *); @@ -103,8 +95,6 @@ extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *); extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int); extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int); -extern int qla2x00_down_timeout(struct semaphore *, unsigned long); - extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); @@ -113,7 +103,6 @@ extern void qla2xxx_wake_dpc(scsi_qla_host_t *); extern void qla2x00_alert_all_vps(scsi_qla_host_t *, uint16_t *); extern void qla2x00_async_event(scsi_qla_host_t *, uint16_t *); extern void qla2x00_vp_abort_isp(scsi_qla_host_t *); -extern int qla24xx_vport_delete(struct fc_vport *); /* * Global Function Prototypes in qla_iocb.c source file. @@ -222,21 +211,16 @@ extern int qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); extern int -qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, link_stat_t *, - uint16_t *); +qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *, + dma_addr_t); extern int -qla24xx_get_isp_stats(scsi_qla_host_t *, uint32_t *, uint32_t, uint16_t *); +qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *, + dma_addr_t); extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *); extern int qla24xx_abort_target(fc_port_t *); -extern int qla2x00_system_error(scsi_qla_host_t *); - -extern int -qla2x00_get_serdes_params(scsi_qla_host_t *, uint16_t *, uint16_t *, - uint16_t *); - extern int qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); @@ -244,13 +228,19 @@ extern int qla2x00_stop_firmware(scsi_qla_host_t *); extern int -qla2x00_trace_control(scsi_qla_host_t *, uint16_t, dma_addr_t, uint16_t); +qla2x00_enable_eft_trace(scsi_qla_host_t *, dma_addr_t, uint16_t); +extern int +qla2x00_disable_eft_trace(scsi_qla_host_t *); extern int -qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t); +qla2x00_enable_fce_trace(scsi_qla_host_t *, dma_addr_t, uint16_t , uint16_t *, + uint32_t *); extern int -qla2x00_get_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t *, uint16_t *); +qla2x00_disable_fce_trace(scsi_qla_host_t *, uint64_t *, uint64_t *); + +extern int +qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t); extern int qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *); @@ -270,11 +260,7 @@ extern void qla2x00_free_irqs(scsi_qla_host_t *); /* * Global Function Prototypes in qla_sup.c source file. */ -extern void qla2x00_lock_nvram_access(scsi_qla_host_t *); -extern void qla2x00_unlock_nvram_access(scsi_qla_host_t *); extern void qla2x00_release_nvram_protection(scsi_qla_host_t *); -extern uint16_t qla2x00_get_nvram_word(scsi_qla_host_t *, uint32_t); -extern void qla2x00_write_nvram_word(scsi_qla_host_t *, uint32_t, uint16_t); extern uint32_t *qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *, uint32_t, uint32_t); extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, @@ -321,7 +307,6 @@ extern void qla25xx_fw_dump(scsi_qla_host_t *, int); extern void qla2x00_dump_regs(scsi_qla_host_t *); extern void qla2x00_dump_buffer(uint8_t *, uint32_t); extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *); -extern void qla2x00_dump_pkt(void *); /* * Global Function Prototypes in qla_gs.c source file. @@ -356,4 +341,10 @@ extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); extern void qla2x00_init_host_attr(scsi_qla_host_t *); extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); + +/* + * Global Function Prototypes in qla_dfs.c source file. + */ +extern int qla2x00_dfs_setup(scsi_qla_host_t *); +extern int qla2x00_dfs_remove(scsi_qla_host_t *); #endif /* _QLA_GBL_H */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 191dafd89be..d0633ca894b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -732,9 +732,9 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) { int rval; uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, - eft_size; - dma_addr_t eft_dma; - void *eft; + eft_size, fce_size; + dma_addr_t tc_dma; + void *tc; if (ha->fw_dump) { qla_printk(KERN_WARNING, ha, @@ -743,7 +743,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) } ha->fw_dumped = 0; - fixed_size = mem_size = eft_size = 0; + fixed_size = mem_size = eft_size = fce_size = 0; if (IS_QLA2100(ha) || IS_QLA2200(ha)) { fixed_size = sizeof(struct qla2100_fw_dump); } else if (IS_QLA23XX(ha)) { @@ -758,21 +758,21 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) sizeof(uint32_t); /* Allocate memory for Extended Trace Buffer. */ - eft = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &eft_dma, + tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, GFP_KERNEL); - if (!eft) { + if (!tc) { qla_printk(KERN_WARNING, ha, "Unable to allocate " "(%d KB) for EFT.\n", EFT_SIZE / 1024); goto cont_alloc; } - rval = qla2x00_trace_control(ha, TC_ENABLE, eft_dma, - EFT_NUM_BUFFERS); + memset(tc, 0, EFT_SIZE); + rval = qla2x00_enable_eft_trace(ha, tc_dma, EFT_NUM_BUFFERS); if (rval) { qla_printk(KERN_WARNING, ha, "Unable to initialize " "EFT (%d).\n", rval); - dma_free_coherent(&ha->pdev->dev, EFT_SIZE, eft, - eft_dma); + dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, + tc_dma); goto cont_alloc; } @@ -780,9 +780,40 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) EFT_SIZE / 1024); eft_size = EFT_SIZE; - memset(eft, 0, eft_size); - ha->eft_dma = eft_dma; - ha->eft = eft; + ha->eft_dma = tc_dma; + ha->eft = tc; + + /* Allocate memory for Fibre Channel Event Buffer. */ + if (!IS_QLA25XX(ha)) + goto cont_alloc; + + tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, + GFP_KERNEL); + if (!tc) { + qla_printk(KERN_WARNING, ha, "Unable to allocate " + "(%d KB) for FCE.\n", FCE_SIZE / 1024); + goto cont_alloc; + } + + memset(tc, 0, FCE_SIZE); + rval = qla2x00_enable_fce_trace(ha, tc_dma, FCE_NUM_BUFFERS, + ha->fce_mb, &ha->fce_bufs); + if (rval) { + qla_printk(KERN_WARNING, ha, "Unable to initialize " + "FCE (%d).\n", rval); + dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc, + tc_dma); + ha->flags.fce_enabled = 0; + goto cont_alloc; + } + + qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n", + FCE_SIZE / 1024); + + fce_size = sizeof(struct qla2xxx_fce_chain) + EFT_SIZE; + ha->flags.fce_enabled = 1; + ha->fce_dma = tc_dma; + ha->fce = tc; } cont_alloc: req_q_size = ha->request_q_length * sizeof(request_t); @@ -790,7 +821,7 @@ cont_alloc: dump_size = offsetof(struct qla2xxx_fw_dump, isp); dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + - eft_size; + eft_size + fce_size; ha->fw_dump = vmalloc(dump_size); if (!ha->fw_dump) { @@ -922,9 +953,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) ha->flags.npiv_supported = 1; if ((!ha->max_npiv_vports) || ((ha->max_npiv_vports + 1) % - MAX_MULTI_ID_FABRIC)) + MIN_MULTI_ID_FABRIC)) ha->max_npiv_vports = - MAX_NUM_VPORT_FABRIC; + MIN_MULTI_ID_FABRIC - 1; } if (ql2xallocfwdump) @@ -1162,7 +1193,10 @@ qla2x00_init_rings(scsi_qla_host_t *ha) DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); - mid_init_cb->count = ha->max_npiv_vports; + if (ha->flags.npiv_supported) + mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports); + + mid_init_cb->options = __constant_cpu_to_le16(BIT_1); rval = qla2x00_init_firmware(ha, ha->init_cb_size); if (rval) { @@ -2566,14 +2600,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) /* Bypass virtual ports of the same host. */ if (pha->num_vhosts) { - vp_index = find_next_bit( - (unsigned long *)pha->vp_idx_map, - MAX_MULTI_ID_FABRIC + 1, 1); - - for (;vp_index <= MAX_MULTI_ID_FABRIC; - vp_index = find_next_bit( - (unsigned long *)pha->vp_idx_map, - MAX_MULTI_ID_FABRIC + 1, vp_index + 1)) { + for_each_mapped_vp_idx(pha, vp_index) { empty_vp_index = 1; found_vp = 0; list_for_each_entry(vha, &pha->vp_list, @@ -2592,7 +2619,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) new_fcport->d_id.b24 == vha->d_id.b24) break; } - if (vp_index <= MAX_MULTI_ID_FABRIC) + + if (vp_index <= pha->max_npiv_vports) continue; } @@ -3245,7 +3273,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); if (ha->eft) { - rval = qla2x00_trace_control(ha, TC_ENABLE, + rval = qla2x00_enable_eft_trace(ha, ha->eft_dma, EFT_NUM_BUFFERS); if (rval) { qla_printk(KERN_WARNING, ha, @@ -3253,6 +3281,21 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) "(%d).\n", rval); } } + + if (ha->fce) { + ha->flags.fce_enabled = 1; + memset(ha->fce, 0, + fce_calc_size(ha->fce_bufs)); + rval = qla2x00_enable_fce_trace(ha, + ha->fce_dma, ha->fce_bufs, ha->fce_mb, + &ha->fce_bufs); + if (rval) { + qla_printk(KERN_WARNING, ha, + "Unable to reinitialize FCE " + "(%d).\n", rval); + ha->flags.fce_enabled = 0; + } + } } else { /* failed the ISP abort */ ha->flags.online = 1; if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 1104bd2eed4..642a0c3f09c 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -104,7 +104,7 @@ qla2100_intr_handler(int irq, void *dev_id) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); - up(&ha->mbx_intr_sem); + complete(&ha->mbx_intr_comp); } return (IRQ_HANDLED); @@ -216,7 +216,7 @@ qla2300_intr_handler(int irq, void *dev_id) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); - up(&ha->mbx_intr_sem); + complete(&ha->mbx_intr_comp); } return (IRQ_HANDLED); @@ -347,10 +347,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; case MBA_SYSTEM_ERR: /* System Error */ - mb[1] = RD_MAILBOX_REG(ha, reg, 1); - mb[2] = RD_MAILBOX_REG(ha, reg, 2); - mb[3] = RD_MAILBOX_REG(ha, reg, 3); - qla_printk(KERN_INFO, ha, "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", mb[1], mb[2], mb[3]); @@ -579,12 +575,15 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) /* Check if the Vport has issued a SCR */ if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags)) break; + /* Only handle SCNs for our Vport index. */ + if (ha->flags.npiv_supported && ha->vp_idx != mb[3]) + break; DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", ha->host_no)); DEBUG(printk(KERN_INFO - "scsi(%ld): RSCN database changed -- %04x %04x.\n", - ha->host_no, mb[1], mb[2])); + "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n", + ha->host_no, mb[1], mb[2], mb[3])); rscn_entry = (mb[1] << 16) | mb[2]; host_pid = (ha->d_id.b.domain << 16) | (ha->d_id.b.area << 8) | @@ -823,6 +822,35 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha) WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), ha->rsp_ring_index); } +static inline void +qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len) +{ + struct scsi_cmnd *cp = sp->cmd; + + if (sense_len >= SCSI_SENSE_BUFFERSIZE) + sense_len = SCSI_SENSE_BUFFERSIZE; + + CMD_ACTUAL_SNSLEN(cp) = sense_len; + sp->request_sense_length = sense_len; + sp->request_sense_ptr = cp->sense_buffer; + if (sp->request_sense_length > 32) |