diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-25 17:19:08 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-25 17:19:08 -0800 |
commit | 9b73e76f3cf63379dcf45fcd4f112f5812418d0a (patch) | |
tree | 4e6bef87cd0cd6d848fc39a5ae25b981dbbe035b /drivers/scsi/qla2xxx | |
parent | 50d9a126240f9961cfdd063336bbeb91f77a7dce (diff) | |
parent | 23c3e290fb9ce38cabc2822b47583fc8702411bf (diff) | |
download | blackbird-op-linux-9b73e76f3cf63379dcf45fcd4f112f5812418d0a.tar.gz blackbird-op-linux-9b73e76f3cf63379dcf45fcd4f112f5812418d0a.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (200 commits)
[SCSI] usbstorage: use last_sector_bug flag universally
[SCSI] libsas: abstract STP task status into a function
[SCSI] ultrastor: clean up inline asm warnings
[SCSI] aic7xxx: fix firmware build
[SCSI] aacraid: fib context lock for management ioctls
[SCSI] ch: remove forward declarations
[SCSI] ch: fix device minor number management bug
[SCSI] ch: handle class_device_create failure properly
[SCSI] NCR5380: fix section mismatch
[SCSI] sg: fix /proc/scsi/sg/devices when no SCSI devices
[SCSI] IB/iSER: add logical unit reset support
[SCSI] don't use __GFP_DMA for sense buffers if not required
[SCSI] use dynamically allocated sense buffer
[SCSI] scsi.h: add macro for enclosure bit of inquiry data
[SCSI] sd: add fix for devices with last sector access problems
[SCSI] fix pcmcia compile problem
[SCSI] aacraid: add Voodoo Lite class of cards.
[SCSI] aacraid: add new driver features flags
[SCSI] qla2xxx: Update version number to 8.02.00-k7.
[SCSI] qla2xxx: Issue correct MBC_INITIALIZE_FIRMWARE command.
...
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 71ddb5db4944..c51fd1f86639 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 fb388b8c07cf..adf97320574b 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 eaa04dabcdf6..d88e98c476b0 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 a50ecf0b7c84..524598afc81c 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 04e8cbca4c0d..6f129da37589 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 000000000000..1479c60441c8 --- /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 25364b1aaf12..9337e138ed63 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 09cb2a908059..ba35fc26ce6b 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 191dafd89be0..d0633ca894be 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 1104bd2eed40..642a0c3f09c6 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) + sense_len = 32; + + memcpy(cp->sense_buffer, sense_data, sense_len); + + sp->request_sense_ptr += sense_len; + sp->request_sense_length -= sense_len; + if (sp->request_sense_length != 0) + sp->ha->status_srb = sp; + + DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) " + "cmd=%p pid=%ld\n", __func__, sp->ha->host_no, cp->device->channel, + cp->device->id, cp->device->lun, cp, cp->serial_number)); + if (sense_len) + DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, + CMD_ACTUAL_SNSLEN(cp))); +} + /** * qla2x00_status_entry() - Process a Status IOCB entry. * @ha: SCSI driver HA context @@ -977,36 +1005,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) if (lscsi_status != SS_CHECK_CONDITION) break; - /* Copy Sense Data into sense buffer. */ - memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer)); - + memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); if (!(scsi_status & SS_SENSE_LEN_VALID)) break; - if (sense_len >= sizeof(cp->sense_buffer)) - sense_len = sizeof(cp->sense_buffer); - - 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) - sense_len = 32; - - memcpy(cp->sense_buffer, sense_data, sense_len); - - sp->request_sense_ptr += sense_len; - sp->request_sense_length -= sense_len; - if (sp->request_sense_length != 0) - ha->status_srb = sp; - - DEBUG5(printk("%s(): Check condition Sense data, " - "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", __func__, - ha->host_no, cp->device->channel, cp->device->id, - cp->device->lun, cp, cp->serial_number)); - if (sense_len) - DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, - CMD_ACTUAL_SNSLEN(cp))); + qla2x00_handle_sense(sp, sense_data, sense_len); break; case CS_DATA_UNDERRUN: @@ -1061,34 +1064,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) if (lscsi_status != SS_CHECK_CONDITION) break; - /* Copy Sense Data into sense buffer */ - memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer)); - + memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); if (!(scsi_status & SS_SENSE_LEN_VALID)) break; - if (sense_len >= sizeof(cp->sense_buffer)) - sense_len = sizeof(cp->sense_buffer); - - 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) - sense_len = 32; - - memcpy(cp->sense_buffer, sense_data, sense_len); - - sp->request_sense_ptr += sense_len; - sp->request_sense_length -= sense_len; - if (sp->request_sense_length != 0) - ha->status_srb = sp; - - DEBUG5(printk("%s(): Check condition Sense data, " - "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", - __func__, ha->host_no, cp->device->channel, - cp->device->id, cp->device->lun, cp, - cp->serial_number)); + qla2x00_handle_sense(sp, sense_data, sense_len); /* * In case of a Underrun condition, set both the lscsi @@ -1108,10 +1088,6 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) cp->result = DID_ERROR << 16 | lscsi_status; } - - if (sense_len) - DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, - CMD_ACTUAL_SNSLEN(cp))); } else { /* * If RISC reports underrun and target does not report @@ -1621,7 +1597,7 @@ qla24xx_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; @@ -1758,7 +1734,7 @@ qla24xx_msix_default(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; @@ -1853,6 +1829,18 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) goto skip_msix; } + if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP && + (ha->pdev->subsystem_device == 0x7040 || + ha->pdev->subsystem_device == 0x7041 || + ha->pdev->subsystem_device == 0x1705)) { + DEBUG2(qla_printk(KERN_WARNING, ha, + "MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X, 0x%X).\n", + ha->pdev->subsystem_vendor, + ha->pdev->subsystem_device)); + + goto skip_msi; + } + ret = qla24xx_enable_msix(ha); if (!ret) { DEBUG2(qla_printk(KERN_INFO, ha, diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index ccd662a6f5dc..0c10c0b0fb73 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -8,19 +8,6 @@ #include <linux/delay.h> -static void -qla2x00_mbx_sem_timeout(unsigned long data) -{ - struct semaphore *sem_ptr = (struct semaphore *)data; - - DEBUG11(printk("qla2x00_sem_timeout: entered.\n")); - - if (sem_ptr != NULL) { - up(sem_ptr); - } - - DEBUG11(printk("qla2x00_mbx_sem_timeout: exiting.\n")); -} /* * qla2x00_mailbox_command @@ -47,7 +34,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) int rval; unsigned long flags = 0; device_reg_t __iomem *reg; - struct timer_list tmp_intr_timer; uint8_t abort_active; uint8_t io_lock_on; uint16_t command; @@ -72,7 +58,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) * non ISP abort time. */ if (!abort_active) { - if (qla2x00_down_timeout(&ha->mbx_cmd_sem, mcp->tov * HZ)) { + if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, + mcp->tov * HZ)) { /* Timeout occurred. Return error. */ DEBUG2_3_11(printk("%s(%ld): cmd access timeout. " "Exiting.\n", __func__, ha->host_no)); @@ -135,22 +122,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) /* Wait for mbx cmd completion until timeout */ if (!abort_active && io_lock_on) { - /* sleep on completion semaphore */ - DEBUG11(printk("%s(%ld): INTERRUPT MODE. Initializing timer.\n", - __func__, ha->host_no)); - - init_timer(&tmp_intr_timer); - tmp_intr_timer.data = (unsigned long)&ha->mbx_intr_sem; - tmp_intr_timer.expires = jiffies + mcp->tov * HZ; - tmp_intr_timer.function = - (void (*)(unsigned long))qla2x00_mbx_sem_timeout; - - DEBUG11(printk("%s(%ld): Adding timer.\n", __func__, - ha->host_no)); - add_timer(&tmp_intr_timer); - - DEBUG11(printk("%s(%ld): going to unlock & sleep. " - "time=0x%lx.\n", __func__, ha->host_no, jiffies)); set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); @@ -160,17 +131,10 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); spin_unlock_irqrestore(&ha->hardware_lock, flags); - /* Wait for either the timer to expire - * or the mbox completion interrupt - */ - down(&ha->mbx_intr_sem); + wait_for_completion_timeout(&ha->mbx_intr_comp, mcp->tov * HZ); - DEBUG11(printk("%s(%ld): waking up. time=0x%lx\n", __func__, - ha->host_no, jiffies)); clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); - /* delete the timer */ - del_timer(&tmp_intr_timer); } else { DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, ha->host_no, command)); @@ -299,7 +263,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) /* Allow next mbx cmd to come in. */ if (!abort_active) - up(&ha->mbx_cmd_sem); + complete(&ha->mbx_cmd_comp); if (rval) { DEBUG2_3_11(printk("%s(%ld): **** FAILED. mbx0=%x, mbx1=%x, " @@ -905,7 +869,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; mcp->mb[9] = ha->vp_idx; - mcp->out_mb = MBX_0; + mcp->out_mb = MBX_9|MBX_0; mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; @@ -1016,7 +980,7 @@ qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size) DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", ha->host_no)); - if (ha->flags.npiv_supported) + if (ha->fw_attributes & BIT_2) mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE; else mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; @@ -2042,29 +2006,20 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) */ int qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, - link_stat_t *ret_buf, uint16_t *status) + struct link_statistics *stats, dma_addr_t stats_dma) { int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - link_stat_t *stat_buf; - dma_addr_t stat_buf_dma; + uint32_t *siter, *diter, dwords; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - stat_buf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &stat_buf_dma); - if (stat_buf == NULL) { - DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n", - __func__, ha->host_no)); - return BIT_0; - } - memset(stat_buf, 0, sizeof(link_stat_t)); - mcp->mb[0] = MBC_GET_LINK_STATUS; - mcp->mb[2] = MSW(stat_buf_dma); - mcp->mb[3] = LSW(stat_buf_dma); - mcp->mb[6] = MSW(MSD(stat_buf_dma)); - mcp->mb[7] = LSW(MSD(stat_buf_dma)); + mcp->mb[2] = MSW(stats_dma); + mcp->mb[3] = LSW(stats_dma); + mcp->mb[6] = MSW(MSD(stats_dma)); + mcp->mb[7] = LSW(MSD(stats_dma)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->in_mb = MBX_0; if (IS_FWI2_CAPABLE(ha)) { @@ -2089,78 +2044,43 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n", __func__, ha->host_no, mcp->mb[0])); - status[0] = mcp->mb[0]; - rval = BIT_1; + rval = QLA_FUNCTION_FAILED; } else { - /* copy over data -- firmware data is LE. */ - ret_buf->link_fail_cnt = - le32_to_cpu(stat_buf->link_fail_cnt); - ret_buf->loss_sync_cnt = - le32_to_cpu(stat_buf->loss_sync_cnt); - ret_buf->loss_sig_cnt = - le32_to_cpu(stat_buf->loss_sig_cnt); - ret_buf->prim_seq_err_cnt = - le32_to_cpu(stat_buf->prim_seq_err_cnt); - ret_buf->inval_xmit_word_cnt = - le32_to_cpu(stat_buf->inval_xmit_word_cnt); - ret_buf->inval_crc_cnt = - le32_to_cpu(stat_buf->inval_crc_cnt); - - DEBUG11(printk("%s(%ld): stat dump: fail_cnt=%d " - "loss_sync=%d loss_sig=%d seq_err=%d " - "inval_xmt_word=%d inval_crc=%d.\n", __func__, - ha->host_no, stat_buf->link_fail_cnt, - stat_buf->loss_sync_cnt, stat_buf->loss_sig_cnt, - stat_buf->prim_seq_err_cnt, - stat_buf->inval_xmit_word_cnt, - stat_buf->inval_crc_cnt)); + /* Copy over data -- firmware data is LE. */ + dwords = offsetof(struct link_statistics, unused1) / 4; + siter = diter = &stats->link_fail_cnt; + while (dwords--) + *diter++ = le32_to_cpu(*siter++); } } else { /* Failed. */ DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, ha->host_no, rval)); - rval = BIT_1; } - dma_pool_free(ha->s_dma_pool, stat_buf, stat_buf_dma); - return rval; } int -qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords, - uint16_t *status) +qla24xx_get_isp_stats(scsi_qla_host_t *ha, struct link_statistics *stats, + dma_addr_t stats_dma) { int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - uint32_t *sbuf, *siter; - dma_addr_t sbuf_dma; + uint32_t *siter, *diter, dwords; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - if (dwords > (DMA_POOL_SIZE / 4)) { - DEBUG2_3_11(printk("%s(%ld): Unabled to retrieve %d DWORDs " - "(max %d).\n", __func__, ha->host_no, dwords, - DMA_POOL_SIZE / 4)); - return BIT_0; - } - sbuf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &sbuf_dma); - if (sbuf == NULL) { - DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n", - __func__, ha->host_no)); - return BIT_0; - } - memset(sbuf, 0, DMA_POOL_SIZE); - mcp->mb[0] = MBC_GET_LINK_PRIV_STATS; - mcp->mb[2] = MSW(sbuf_dma); - mcp->mb[3] = LSW(sbuf_dma); - mcp->mb[6] = MSW(MSD(sbuf_dma)); - mcp->mb[7] = LSW(MSD(sbuf_dma)); - mcp->mb[8] = dwords; + mcp->mb[2] = MSW(stats_dma); + mcp->mb[3] = LSW(stats_dma); + mcp->mb[6] = MSW(MSD(stats_dma)); + mcp->mb[7] = LSW(MSD(stats_dma)); + mcp->mb[8] = sizeof(struct link_statistics) / 4; + mcp->mb[9] = ha->vp_idx; mcp->mb[10] = 0; - mcp->out_mb = MBX_10|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; + mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->in_mb = MBX_2|MBX_1|MBX_0; mcp->tov = 30; mcp->flags = IOCTL_CMD; @@ -2170,23 +2090,20 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords, if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n", __func__, ha->host_no, mcp->mb[0])); - status[0] = mcp->mb[0]; - rval = BIT_1; + rval = QLA_FUNCTION_FAILED; } else { /* Copy over data -- firmware data is LE. */ - siter = sbuf; + dwords = sizeof(struct link_statistics) / 4; + siter = diter = &stats->link_fail_cnt; while (dwords--) - *dwbuf++ = le32_to_cpu(*siter++); + *diter++ = le32_to_cpu(*siter++); } } else { /* Failed. */ DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, ha->host_no, rval)); - rval = BIT_1; } - dma_pool_free(ha->s_dma_pool, sbuf, sbuf_dma); - return rval; } @@ -2331,6 +2248,8 @@ atarget_done: return rval; } +#if 0 + int qla2x00_system_error(scsi_qla_host_t *ha) { @@ -2360,47 +2279,7 @@ qla2x00_system_error(scsi_qla_host_t *ha) return rval; } -/** - * qla2x00_get_serdes_params() - - * @ha: HA context - * - * Returns - */ -int -qla2x00_get_serdes_params(scsi_qla_host_t *ha, uint16_t *sw_em_1g, - uint16_t *sw_em_2g, uint16_t *sw_em_4g) -{ - int rval; - mbx_cmd_t mc; - mbx_cmd_t *mcp = &mc; - - DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - - mcp->mb[0] = MBC_SERDES_PARAMS; - mcp->mb[1] = 0; - mcp->out_mb = MBX_1|MBX_0; - mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_0; - mcp->tov = 30; - mcp->flags = 0; - rval = qla2x00_mailbox_command(ha, mcp); - - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__, - ha->host_no, rval, mcp->mb[0])); - } else { - DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); - - if (sw_em_1g) - *sw_em_1g = mcp->mb[2]; - if (sw_em_2g) - *sw_em_2g = mcp->mb[3]; - if (sw_em_4g) - *sw_em_4g = mcp->mb[4]; - } - - return rval; -} +#endif /* 0 */ /** * qla2x00_set_serdes_params() - @@ -2471,7 +2350,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha) } int -qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma, +qla2x00_enable_eft_trace(scsi_qla_host_t *ha, dma_addr_t eft_dma, uint16_t buffers) { int rval; @@ -2484,22 +2363,18 @@ qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma, DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); mcp->mb[0] = MBC_TRACE_CONTROL; - mcp->mb[1] = ctrl; - mcp->out_mb = MBX_1|MBX_0; + mcp->mb[1] = TC_EFT_ENABLE; + mcp->mb[2] = LSW(eft_dma); + mcp->mb[3] = MSW(eft_dma); + mcp->mb[4] = LSW(MSD(eft_dma)); + mcp->mb[5] = MSW(MSD(eft_dma)); + mcp->mb[6] = buffers; + mcp->mb[7] = TC_AEN_DISABLE; + mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_1|MBX_0; - if (ctrl == TC_ENABLE) { - mcp->mb[2] = LSW(eft_dma); - mcp->mb[3] = MSW(eft_dma); - mcp->mb[4] = LSW(MSD(eft_dma)); - mcp->mb[5] = MSW(MSD(eft_dma)); - mcp->mb[6] = buffers; - mcp->mb[7] = 0; - mcp->out_mb |= MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2; - } mcp->tov = 30; mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); - if (rval != QLA_SUCCESS) { DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n", __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1])); @@ -2511,8 +2386,7 @@ qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma, } int -qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr, - uint16_t off, uint16_t count) +qla2x00_disable_eft_trace(scsi_qla_host_t *ha) { int rval; mbx_cmd_t mc; @@ -2523,24 +2397,16 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr, DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - mcp->mb[0] = MBC_READ_SFP; - mcp->mb[1] = addr; - mcp->mb[2] = MSW(sfp_dma); - mcp->mb[3] = LSW(sfp_dma); - mcp->mb[6] = MSW(MSD(sfp_dma)); - mcp->mb[7] = LSW(MSD(sfp_dma)); - mcp->mb[8] = count; - mcp->mb[9] = off; - mcp->mb[10] = 0; - mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_0; + mcp->mb[0] = MBC_TRACE_CONTROL; + mcp->mb[1] = TC_EFT_DISABLE; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); - if (rval != QLA_SUCCESS) { - DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__, - ha->host_no, rval, mcp->mb[0])); + DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n", + __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1])); } else { DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); } @@ -2549,176 +2415,168 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr, } int -qla2x00_get_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, - uint16_t *port_speed, uint16_t *mb) +qla2x00_enable_fce_trace(scsi_qla_host_t *ha, dma_addr_t fce_dma, + uint16_t buffers, uint16_t *mb, uint32_t *dwords) { int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_IIDMA_CAPABLE(ha)) + if (!IS_QLA25XX(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - mcp->mb[0] = MBC_PORT_PARAMS; - mcp->mb[1] = loop_id; - mcp->mb[2] = mcp->mb[3] = mcp->mb[4] = mcp->mb[5] = 0; - mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0; + mcp->mb[0] = MBC_TRACE_CONTROL; + mcp->mb[1] = TC_FCE_ENABLE; + mcp->mb[2] = LSW(fce_dma); + mcp->mb[3] = MSW(fce_dma); + mcp->mb[4] = LSW(MSD(fce_dma)); + mcp->mb[5] = MSW(MSD(fce_dma)); + mcp->mb[6] = buffers; + mcp->mb[7] = TC_AEN_DISABLE; + mcp->mb[8] = 0; + mcp->mb[9] = TC_FCE_DEFAULT_RX_SIZE; + mcp->mb[10] = TC_FCE_DEFAULT_TX_SIZE; + mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2| + MBX_1|MBX_0; + mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); - - /* Return mailbox statuses. */ - if (mb != NULL) { - mb[0] = mcp->mb[0]; - mb[1] = mcp->mb[1]; - mb[3] = mcp->mb[3]; - mb[4] = mcp->mb[4]; - mb[5] = mcp->mb[5]; - } - if (rval != QLA_SUCCESS) { - DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, - ha->host_no, rval)); + DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n", + __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1])); } else { DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); - if (port_speed) - *port_speed = mcp->mb[3]; + + if (mb) + memcpy(mb, mcp->mb, 8 * sizeof(*mb)); + if (dwords) + *dwords = mcp->mb[6]; } return rval; } int -qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, - uint16_t port_speed, uint16_t *mb) +qla2x00_disable_fce_trace(scsi_qla_host_t *ha, uint64_t *wr, uint64_t *rd) { int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_IIDMA_CAPABLE(ha)) + if (!IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - mcp->mb[0] = MBC_PORT_PARAMS; - mcp->mb[1] = loop_id; - mcp->mb[2] = BIT_0; - mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0); - mcp->mb[4] = mcp->mb[5] = 0; - mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0; + mcp->mb[0] = MBC_TRACE_CONTROL; + mcp->mb[1] = TC_FCE_DISABLE; + mcp->mb[2] = TC_FCE_DISABLE_TRACE; + mcp->out_mb = MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2| + MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); - - /* Return mailbox statuses. */ - if (mb != NULL) { - mb[0] = mcp->mb[0]; - mb[1] = mcp->mb[1]; - mb[3] = mcp->mb[3]; - mb[4] = mcp->mb[4]; - mb[5] = mcp->mb[5]; - } - if (rval != QLA_SUCCESS) { - DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, - ha->host_no, rval)); + DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n", + __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1])); } else { DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); + + if (wr) + *wr = (uint64_t) mcp->mb[5] << 48 | + (uint64_t) mcp->mb[4] << 32 | + (uint64_t) mcp->mb[3] << 16 | + (uint64_t) mcp->mb[2]; + if (rd) + *rd = (uint64_t) mcp->mb[9] << 48 | + (uint64_t) mcp->mb[8] << 32 | + (uint64_t) mcp->mb[7] << 16 | + (uint64_t) mcp->mb[6]; } return rval; } -/* - * qla24xx_get_vp_database - * Get the VP's database for all configured ports. - * - * Input: - * ha = adapter block pointer. - * size = size of initialization control block. - * - * Returns: - * qla2x00 local function return status code. - * - * Context: - * Kernel context. - */ int -qla24xx_get_vp_database(scsi_qla_host_t *ha, uint16_t size) +qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr, + uint16_t off, uint16_t count) { int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - DEBUG11(printk("scsi(%ld):%s - entered.\n", - ha->host_no, __func__)); + if (!IS_FWI2_CAPABLE(ha)) + return QLA_FUNCTION_FAILED; - mcp->mb[0] = MBC_MID_GET_VP_DATABASE; - mcp->mb[2] = MSW(ha->init_cb_dma); - mcp->mb[3] = LSW(ha->init_cb_dma); - mcp->mb[4] = 0; - mcp->mb[5] = 0; - mcp->mb[6] = MSW(MSD(ha->init_cb_dma)); - mcp->mb[7] = LSW(MSD(ha->init_cb_dma)); - mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; - mcp->in_mb = MBX_1|MBX_0; - mcp->buf_size = size; - mcp->flags = MBX_DMA_OUT; - mcp->tov = MBX_TOV_SECONDS; + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); + + mcp->mb[0] = MBC_READ_SFP; + mcp->mb[1] = addr; + mcp->mb[2] = MSW(sfp_dma); + mcp->mb[3] = LSW(sfp_dma); + mcp->mb[6] = MSW(MSD(sfp_dma)); + mcp->mb[7] = LSW(MSD(sfp_dma)); + mcp->mb[8] = count; + mcp->mb[9] = off; + mcp->mb[10] = 0; + mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); if (rval != QLA_SUCCESS) { - /*EMPTY*/ - DEBUG2_3_11(printk("%s(%ld): failed=%x " - "mb0=%x.\n", - __func__, ha->host_no, rval, mcp->mb[0])); + DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__, + ha->host_no, rval, mcp->mb[0])); } else { - /*EMPTY*/ - DEBUG11(printk("%s(%ld): done.\n", - __func__, ha->host_no)); + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); } return rval; } int -qla24xx_get_vp_entry(scsi_qla_host_t *ha, uint16_t size, int vp_id) +qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, + uint16_t port_speed, uint16_t *mb) { int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; + if (!IS_IIDMA_CAPABLE(ha)) + return QLA_FUNCTION_FAILED; + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - mcp->mb[0] = MBC_MID_GET_VP_ENTRY; - mcp->mb[2] = MSW(ha->init_cb_dma); - mcp->mb[3] = LSW(ha->init_cb_dma); - mcp->mb[4] = 0; - mcp->mb[5] = 0; - mcp->mb[6] = MSW(MSD(ha->init_cb_dma)); - mcp->mb[7] = LSW(MSD(ha->init_cb_dma)); - mcp->mb[9] = vp_id; - mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; - mcp->in_mb = MBX_0; - mcp->buf_size = size; - mcp->flags = MBX_DMA_OUT; + mcp->mb[0] = MBC_PORT_PARAMS; + mcp->mb[1] = loop_id; + mcp->mb[2] = BIT_0; + mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0); + mcp->mb[4] = mcp->mb[5] = 0; + mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0; mcp->tov = 30; + mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); + /* Return mailbox statuses. */ + if (mb != NULL) { + mb[0] = mcp->mb[0]; + mb[1] = mcp->mb[1]; + mb[3] = mcp->mb[3]; + mb[4] = mcp->mb[4]; + mb[5] = mcp->mb[5]; + } + if (rval != QLA_SUCCESS) { - /*EMPTY*/ - DEBUG2_3_11(printk("qla24xx_get_vp_entry(%ld): failed=%x " - "mb0=%x.\n", - ha->host_no, rval, mcp->mb[0])); + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, + ha->host_no, rval)); } else { - /*EMPTY*/ - DEBUG11(printk("qla24xx_get_vp_entry(%ld): done.\n", - ha->host_no)); + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); } return rval; @@ -2873,7 +2731,7 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) DEBUG11(printk("%s(%ld): entered. Enabling index %d\n", __func__, ha->host_no, vp_index)); - if (vp_index == 0 || vp_index >= MAX_MULTI_ID_LOOP) + if (vp_index == 0 || vp_index >= ha->max_npiv_vports) return QLA_PARAMETER_ERROR; vce = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma); diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 821ee74aadc6..cf784cdafb01 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -39,7 +39,7 @@ qla2x00_vp_stop_timer(scsi_qla_host_t *vha) } } -uint32_t +static uint32_t qla24xx_allocate_vp_id(scsi_qla_host_t *vha) { uint32_t vp_id; @@ -47,16 +47,15 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) /* Find an empty slot and assign an vp_id */ down(&ha->vport_sem); - vp_id = find_first_zero_bit((unsigned long *)ha->vp_idx_map, - MAX_MULTI_ID_FABRIC); - if (vp_id > MAX_MULTI_ID_FABRIC) { - DEBUG15(printk ("vp_id %d is bigger than MAX_MULTI_ID_FABRID\n", - vp_id)); + vp_id = find_first_zero_bit(ha->vp_idx_map, ha->max_npiv_vports + 1); + if (vp_id > ha->max_npiv_vports) { + DEBUG15(printk ("vp_id %d is bigger than max-supported %d.\n", + vp_id, ha->max_npiv_vports)); up(&ha->vport_sem); return vp_id; } - set_bit(vp_id, (unsigned long *)ha->vp_idx_map); + set_bit(vp_id, ha->vp_idx_map); ha->num_vhosts++; vha->vp_idx = vp_id; list_add_tail(&vha->vp_list, &ha->vp_list); @@ -73,12 +72,12 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) down(&ha->vport_sem); vp_id = vha->vp_idx; ha->num_vhosts--; - clear_bit(vp_id, (unsigned long *)ha->vp_idx_map); + clear_bit(vp_id, ha->vp_idx_map); list_del(&vha->vp_list); up(&ha->vport_sem); } -scsi_qla_host_t * +static scsi_qla_host_t * qla24xx_find_vhost_by_name(scsi_qla_host_t *ha, uint8_t *port_name) { scsi_qla_host_t *vha; @@ -216,11 +215,7 @@ qla2x00_alert_all_vps(scsi_qla_host_t *ha, uint16_t *mb) if (ha->parent) return; - i = find_next_bit((unsigned long *)ha->vp_idx_map, - MAX_MULTI_ID_FABRIC + 1, 1); - for (;i <= MAX_MULTI_ID_FABRIC; - i = find_next_bit((unsigned long *)ha->vp_idx_map, - MAX_MULTI_ID_FABRIC + 1, i + 1)) { + for_each_mapped_vp_idx(ha, i) { vp_idx_matched = 0; list_for_each_entry(vha, &ha->vp_list, vp_list) { @@ -270,7 +265,7 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha) qla24xx_enable_vp(vha); } -int +static int qla2x00_do_dpc_vp(scsi_qla_host_t *vha) { if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) { @@ -311,11 +306,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *ha) clear_bit(VP_DPC_NEEDED, &ha->dpc_flags); - i = find_next_bit((unsigned long *)ha->vp_idx_map, - MAX_MULTI_ID_FABRIC + 1, 1); - for (;i <= MAX_MULTI_ID_FABRIC; - i = find_next_bit((unsigned long *)ha->vp_idx_map, - MAX_MULTI_ID_FABRIC + 1, i + 1)) { + for_each_mapped_vp_idx(ha, i) { vp_idx_matched = 0; list_for_each_entry(vha, &ha->vp_list, vp_list) { @@ -350,15 +341,17 @@ qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport) /* Check up unique WWPN */ u64_to_wwn(fc_vport->port_name, port_name); + if (!memcmp(port_name, ha->port_name, WWN_SIZE)) + return VPCERR_BAD_WWN; vha = qla24xx_find_vhost_by_name(ha, port_name); if (vha) return VPCERR_BAD_WWN; /* Check up max-npiv-supports */ if (ha->num_vhosts > ha->max_npiv_vports) { - DEBUG15(printk("scsi(%ld): num_vhosts %d is bigger than " - "max_npv_vports %d.\n", ha->host_no, - (uint16_t) ha->num_vhosts, (int) ha->max_npiv_vports)); + DEBUG15(printk("scsi(%ld): num_vhosts %ud is bigger than " + "max_npv_vports %ud.\n", ha->host_no, + ha->num_vhosts, ha->max_npiv_vports)); return VPCERR_UNSUPPORTED; } return 0; @@ -412,8 +405,9 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) } vha->mgmt_svr_loop_id = 10 + vha->vp_idx; - init_MUTEX(&vha->mbx_cmd_sem); - init_MUTEX_LOCKED(&vha->mbx_intr_sem); + init_completion(&vha->mbx_cmd_comp); + complete(&vha->mbx_cmd_comp); + init_completion(&vha->mbx_intr_comp); INIT_LIST_HEAD(&vha->list); INIT_LIST_HEAD(&vha->fcports); @@ -450,7 +444,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) num_hosts++; down(&ha->vport_sem); - set_bit(vha->vp_idx, (unsigned long *)ha->vp_idx_map); + set_bit(vha->vp_idx, ha->vp_idx_map); ha->cur_vport_count++; up(&ha->vport_sem); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 8ecc0470b8f3..aba1e6d48066 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -105,13 +105,12 @@ static int qla2xxx_eh_abort(struct scsi_cmnd *); static int qla2xxx_eh_device_reset(struct scsi_cmnd *); static int qla2xxx_eh_bus_reset(struct scsi_cmnd *); static int qla2xxx_eh_host_reset(struct scsi_cmnd *); -static int qla2x00_loop_reset(scsi_qla_host_t *ha); static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); static int qla2x00_change_queue_depth(struct scsi_device *, int); static int qla2x00_change_queue_type(struct scsi_device *, int); -struct scsi_host_template qla2x00_driver_template = { +static struct scsi_host_template qla2x00_driver_template = { .module = THIS_MODULE, .name = QLA2XXX_DRIVER_NAME, .queuecommand = qla2x00_queuecommand, @@ -179,13 +178,6 @@ struct scsi_transport_template *qla2xxx_transport_vport_template = NULL; * Timer routines */ -void qla2x00_timer(scsi_qla_host_t *); - -__inline__ void qla2x00_start_timer(scsi_qla_host_t *, - void *, unsigned long); -static __inline__ void qla2x00_restart_timer(scsi_qla_host_t *, unsigned long); -__inline__ void qla2x00_stop_timer(scsi_qla_host_t *); - __inline__ void qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval) { @@ -203,7 +195,7 @@ qla2x00_restart_timer(scsi_qla_host_t *ha, unsigned long interval) mod_timer(&ha->timer, jiffies + interval * HZ); } -__inline__ void +static __inline__ void qla2x00_stop_timer(scsi_qla_host_t *ha) { del_timer_sync(&ha->timer); @@ -214,12 +206,11 @@ static int qla2x00_do_dpc(void *data); static void qla2x00_rst_aen(scsi_qla_host_t *); -uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); -void qla2x00_mem_free(scsi_qla_host_t *ha); +static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); +static void qla2x00_mem_free(scsi_qla_host_t *ha); static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); static void qla2x00_free_sp_pool(scsi_qla_host_t *ha); static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); -void qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *); /* -------------------------------------------------------------------------- */ @@ -1060,7 +1051,7 @@ eh_host_reset_lock: * Returns: * 0 = success */ -static int +int qla2x00_loop_reset(scsi_qla_host_t *ha) { int ret; @@ -1479,8 +1470,7 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) static int qla2x00_iospace_config(scsi_qla_host_t *ha) { - unsigned long pio, pio_len, pio_flags; - unsigned long mmio, mmio_len, mmio_flags; + resource_size_t pio; if (pci_request_selected_regions(ha->pdev, ha->bars, QLA2XXX_DRIVER_NAME)) { @@ -1495,10 +1485,8 @@ qla2x00_iospace_config(scsi_qla_host_t *ha) /* We only need PIO for Flash operations on ISP2312 v2 chips. */ pio = pci_resource_start(ha->pdev, 0); - pio_len = pci_resource_len(ha->pdev, 0); - pio_flags = pci_resource_flags(ha->pdev, 0); - if (pio_flags & IORESOURCE_IO) { - if (pio_len < MIN_IOBASE_LEN) { + if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) { + if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) { qla_printk(KERN_WARNING, ha, "Invalid PCI I/O region size (%s)...\n", pci_name(ha->pdev)); @@ -1511,28 +1499,23 @@ qla2x00_iospace_config(scsi_qla_host_t *ha) pio = 0; } ha->pio_address = pio; - ha->pio_length = pio_len; skip_pio: /* Use MMIO operations for all accesses. */ - mmio = pci_resource_start(ha->pdev, 1); - mmio_len = pci_resource_len(ha->pdev, 1); - mmio_flags = pci_resource_flags(ha->pdev, 1); - - if (!(mmio_flags & IORESOURCE_MEM)) { + if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) { qla_printk(KERN_ERR, ha, - "region #0 not an MMIO resource (%s), aborting\n", + "region #1 not an MMIO resource (%s), aborting\n", pci_name(ha->pdev)); goto iospace_error_exit; } - if (mmio_len < MIN_IOBASE_LEN) { + if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) { qla_printk(KERN_ERR, ha, "Invalid PCI mem region size (%s), aborting\n", pci_name(ha->pdev)); goto iospace_error_exit; } - ha->iobase = ioremap(mmio, MIN_IOBASE_LEN); + ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN); if (!ha->iobase) { qla_printk(KERN_ERR, ha, "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev)); @@ -1701,9 +1684,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* load the F/W, read paramaters, and init the H/W */ ha->instance = num_hosts; - init_MUTEX(&ha->mbx_cmd_sem); init_MUTEX(&ha->vport_sem); - init_MUTEX_LOCKED(&ha->mbx_intr_sem); + init_completion(&ha->mbx_cmd_comp); + complete(&ha->mbx_cmd_comp); + init_completion(&ha->mbx_intr_comp); INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); @@ -1807,6 +1791,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) qla2x00_init_host_attr(ha); + qla2x00_dfs_setup(ha); + qla_printk(KERN_INFO, ha, "\n" " QLogic Fibre Channel HBA Driver: %s\n" " QLogic %s - %s\n" @@ -1838,6 +1824,8 @@ qla2x00_remove_one(struct pci_dev *pdev) ha = pci_get_drvdata(pdev); + qla2x00_dfs_remove(ha); + qla2x00_free_sysfs_attr(ha); fc_remove_host(ha->host); @@ -1871,8 +1859,11 @@ qla2x00_free_device(scsi_qla_host_t *ha) kthread_stop(t); } + if (ha->flags.fce_enabled) + qla2x00_disable_fce_trace(ha, NULL, NULL); + if (ha->eft) - qla2x00_trace_control(ha, TC_DISABLE, 0, 0); + qla2x00_disable_eft_trace(ha); ha->flags.online = 0; @@ -2016,7 +2007,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) * 0 = success. * 1 = failure. */ -uint8_t +static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *ha) { char name[16]; @@ -2213,7 +2204,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) * Input: * ha = adapter block pointer. */ -void +static void qla2x00_mem_free(scsi_qla_host_t *ha) { struct list_head *fcpl, *fcptemp; @@ -2228,6 +2219,10 @@ qla2x00_mem_free(scsi_qla_host_t *ha) /* free sp pool */ qla2x00_free_sp_pool(ha); + if (ha->fce) + dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce, + ha->fce_dma); + if (ha->fw_dump) { if (ha->eft) dma_free_coherent(&ha->pdev->dev, @@ -2748,23 +2743,6 @@ qla2x00_timer(scsi_qla_host_t *ha) qla2x00_restart_timer(ha, WATCH_INTERVAL); } -/* XXX(hch): crude hack to emulate a down_timeout() */ -int -qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) -{ - const unsigned int step = 100; /* msecs */ - unsigned int iterations = jiffies_to_msecs(timeout)/100; - - do { - if (!down_trylock(sema)) - return 0; - if (msleep_interruptible(step)) - break; - } while (--iterations > 0); - - return -ETIMEDOUT; -} - /* Firmware interface routines. */ #define FW_BLOBS 6 diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index ad2fa01bd233..b68fb73613ed 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -22,7 +22,7 @@ static void qla2x00_nv_write(scsi_qla_host_t *, uint16_t); * qla2x00_lock_nvram_access() - * @ha: HA context */ -void +static void qla2x00_lock_nvram_access(scsi_qla_host_t *ha) { uint16_t data; @@ -55,7 +55,7 @@ qla2x00_lock_nvram_access(scsi_qla_host_t *ha) * qla2x00_unlock_nvram_access() - * @ha: HA context */ -void +static void qla2x00_unlock_nvram_access(scsi_qla_host_t *ha) { struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; @@ -74,7 +74,7 @@ qla2x00_unlock_nvram_access(scsi_qla_host_t *ha) * * Returns the word read from nvram @addr. */ -uint16_t +static uint16_t qla2x00_get_nvram_word(scsi_qla_host_t *ha, uint32_t addr) { uint16_t data; @@ -93,7 +93,7 @@ qla2x00_get_nvram_word(scsi_qla_host_t *ha, uint32_t addr) * @addr: Address in NVRAM to write * @data: word to program */ -void +static void qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data) { int count; @@ -550,7 +550,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, int ret; uint32_t liter, miter; uint32_t sec_mask, rest_addr, conf_addr; - uint32_t fdata, findex ; + uint32_t fdata, findex, cnt; uint8_t man_id, flash_id; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; dma_addr_t optrom_dma; @@ -690,8 +690,14 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, 0xff0000) | ((fdata >> 16) & 0xff)); } - /* Enable flash write-protection. */ + /* Enable flash write-protection and wait for completion. */ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c); + for (cnt = 300; cnt && + qla24xx_read_flash_dword(ha, + flash_conf_to_access_addr(0x005)) & BIT_0; + cnt--) { + udelay(10); + } /* Disable flash write. */ WRT_REG_DWORD(®->ctrl_status, diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index ae6f7a2fb19f..2c2f6b4697c7 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.00-k5" +#define QLA2XXX_VERSION "8.02.00-k7" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 |