2005-04-18 00:04:54 +04:00
/*
2005-10-27 22:10:08 +04:00
* QLogic Fibre Channel HBA Driver
2008-04-04 00:13:13 +04:00
* Copyright ( c ) 2003 - 2008 QLogic Corporation
2005-04-18 00:04:54 +04:00
*
2005-10-27 22:10:08 +04:00
* See LICENSE . qla2xxx for copyright and licensing details .
2005-04-18 00:04:54 +04:00
*/
# include "qla_def.h"
2007-07-06 00:16:51 +04:00
# include <linux/kthread.h>
2005-04-18 01:32:42 +04:00
# include <linux/vmalloc.h>
2008-07-28 06:59:20 +04:00
# include <linux/delay.h>
2005-04-18 00:04:54 +04:00
2008-01-17 20:02:15 +03:00
static int qla24xx_vport_disable ( struct fc_vport * , bool ) ;
2007-07-06 00:16:51 +04:00
2005-04-18 00:04:54 +04:00
/* SYSFS attributes --------------------------------------------------------- */
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_read_fw_dump ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2005-04-18 00:04:54 +04:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2005-04-18 00:04:54 +04:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-18 00:04:54 +04:00
if ( ha - > fw_dump_reading = = 0 )
return 0 ;
2008-07-24 19:31:47 +04:00
return memory_read_from_buffer ( buf , count , & off , ha - > fw_dump ,
ha - > fw_dump_len ) ;
2005-04-18 00:04:54 +04:00
}
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_write_fw_dump ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2005-04-18 00:04:54 +04:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2005-04-18 00:04:54 +04:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-18 00:04:54 +04:00
int reading ;
if ( off ! = 0 )
return ( 0 ) ;
reading = simple_strtol ( buf , NULL , 10 ) ;
switch ( reading ) {
case 0 :
2006-06-24 03:10:29 +04:00
if ( ! ha - > fw_dump_reading )
break ;
2005-04-18 00:04:54 +04:00
2006-06-24 03:10:29 +04:00
qla_printk ( KERN_INFO , ha ,
2008-11-06 21:40:19 +03:00
" Firmware dump cleared on (%ld). \n " , vha - > host_no ) ;
2006-06-24 03:10:29 +04:00
ha - > fw_dump_reading = 0 ;
ha - > fw_dumped = 0 ;
2005-04-18 00:04:54 +04:00
break ;
case 1 :
2006-05-18 02:09:50 +04:00
if ( ha - > fw_dumped & & ! ha - > fw_dump_reading ) {
2005-04-18 00:04:54 +04:00
ha - > fw_dump_reading = 1 ;
qla_printk ( KERN_INFO , ha ,
2006-06-24 03:10:29 +04:00
" Raw firmware dump ready for read on (%ld). \n " ,
2008-11-06 21:40:19 +03:00
vha - > host_no ) ;
2005-04-18 00:04:54 +04:00
}
break ;
2006-06-24 03:10:29 +04:00
case 2 :
2008-11-06 21:40:19 +03:00
qla2x00_alloc_fw_dump ( vha ) ;
2006-06-24 03:10:29 +04:00
break ;
2008-05-13 09:21:13 +04:00
case 3 :
2008-11-06 21:40:19 +03:00
qla2x00_system_error ( vha ) ;
2008-05-13 09:21:13 +04:00
break ;
2005-04-18 00:04:54 +04:00
}
return ( count ) ;
}
static struct bin_attribute sysfs_fw_dump_attr = {
. attr = {
. name = " fw_dump " ,
. mode = S_IRUSR | S_IWUSR ,
} ,
. size = 0 ,
. read = qla2x00_sysfs_read_fw_dump ,
. write = qla2x00_sysfs_write_fw_dump ,
} ;
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_read_nvram ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2005-04-18 00:04:54 +04:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2005-04-18 00:04:54 +04:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-18 00:04:54 +04:00
2008-07-24 19:31:47 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) )
2005-04-18 00:04:54 +04:00
return 0 ;
2007-07-27 00:43:34 +04:00
/* Read NVRAM data from cache. */
2008-07-24 19:31:47 +04:00
return memory_read_from_buffer ( buf , count , & off , ha - > nvram ,
ha - > nvram_size ) ;
2005-04-18 00:04:54 +04:00
}
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_write_nvram ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2005-04-18 00:04:54 +04:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2005-04-18 00:04:54 +04:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-18 00:04:54 +04:00
uint16_t cnt ;
2005-07-06 21:31:07 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) | | off ! = 0 | | count ! = ha - > nvram_size )
2005-04-18 00:04:54 +04:00
return 0 ;
/* Checksum NVRAM. */
2007-07-20 02:05:56 +04:00
if ( IS_FWI2_CAPABLE ( ha ) ) {
2005-07-06 21:31:07 +04:00
uint32_t * iter ;
uint32_t chksum ;
iter = ( uint32_t * ) buf ;
chksum = 0 ;
for ( cnt = 0 ; cnt < ( ( count > > 2 ) - 1 ) ; cnt + + )
chksum + = le32_to_cpu ( * iter + + ) ;
chksum = ~ chksum + 1 ;
* iter = cpu_to_le32 ( chksum ) ;
} else {
uint8_t * iter ;
uint8_t chksum ;
iter = ( uint8_t * ) buf ;
chksum = 0 ;
for ( cnt = 0 ; cnt < count - 1 ; cnt + + )
chksum + = * iter + + ;
chksum = ~ chksum + 1 ;
* iter = chksum ;
}
2005-04-18 00:04:54 +04:00
/* Write NVRAM. */
2008-11-06 21:40:19 +03:00
ha - > isp_ops - > write_nvram ( vha , ( uint8_t * ) buf , ha - > nvram_base , count ) ;
ha - > isp_ops - > read_nvram ( vha , ( uint8_t * ) ha - > nvram , ha - > nvram_base ,
2007-07-27 00:43:34 +04:00
count ) ;
2005-04-18 00:04:54 +04:00
2008-11-06 21:40:19 +03:00
set_bit ( ISP_ABORT_NEEDED , & vha - > dpc_flags ) ;
2007-01-29 21:22:28 +03:00
2005-04-18 00:04:54 +04:00
return ( count ) ;
}
static struct bin_attribute sysfs_nvram_attr = {
. attr = {
. name = " nvram " ,
. mode = S_IRUSR | S_IWUSR ,
} ,
2006-02-01 03:05:12 +03:00
. size = 512 ,
2005-04-18 00:04:54 +04:00
. read = qla2x00_sysfs_read_nvram ,
. write = qla2x00_sysfs_write_nvram ,
} ;
2006-02-01 03:05:17 +03:00
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_read_optrom ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2006-02-01 03:05:17 +03:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2006-02-01 03:05:17 +03:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2006-02-01 03:05:17 +03:00
if ( ha - > optrom_state ! = QLA_SREADING )
return 0 ;
2008-07-24 19:31:47 +04:00
return memory_read_from_buffer ( buf , count , & off , ha - > optrom_buffer ,
ha - > optrom_region_size ) ;
2006-02-01 03:05:17 +03:00
}
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_write_optrom ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2006-02-01 03:05:17 +03:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2006-02-01 03:05:17 +03:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2006-02-01 03:05:17 +03:00
if ( ha - > optrom_state ! = QLA_SWRITING )
return - EINVAL ;
2007-09-21 01:07:35 +04:00
if ( off > ha - > optrom_region_size )
2006-02-01 03:05:17 +03:00
return - ERANGE ;
2007-09-21 01:07:35 +04:00
if ( off + count > ha - > optrom_region_size )
count = ha - > optrom_region_size - off ;
2006-02-01 03:05:17 +03:00
memcpy ( & ha - > optrom_buffer [ off ] , buf , count ) ;
return count ;
}
static struct bin_attribute sysfs_optrom_attr = {
. attr = {
. name = " optrom " ,
. mode = S_IRUSR | S_IWUSR ,
} ,
2007-07-20 07:37:34 +04:00
. size = 0 ,
2006-02-01 03:05:17 +03:00
. read = qla2x00_sysfs_read_optrom ,
. write = qla2x00_sysfs_write_optrom ,
} ;
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_write_optrom_ctl ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2006-02-01 03:05:17 +03:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2006-02-01 03:05:17 +03:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2007-09-21 01:07:35 +04:00
uint32_t start = 0 ;
uint32_t size = ha - > optrom_size ;
int val , valid ;
2006-02-01 03:05:17 +03:00
if ( off )
return 0 ;
2007-09-21 01:07:35 +04:00
if ( sscanf ( buf , " %d:%x:%x " , & val , & start , & size ) < 1 )
return - EINVAL ;
if ( start > ha - > optrom_size )
2006-02-01 03:05:17 +03:00
return - EINVAL ;
switch ( val ) {
case 0 :
if ( ha - > optrom_state ! = QLA_SREADING & &
ha - > optrom_state ! = QLA_SWRITING )
break ;
ha - > optrom_state = QLA_SWAITING ;
2007-09-21 01:07:35 +04:00
DEBUG2 ( qla_printk ( KERN_INFO , ha ,
" Freeing flash region allocation -- 0x%x bytes. \n " ,
ha - > optrom_region_size ) ) ;
2006-02-01 03:05:17 +03:00
vfree ( ha - > optrom_buffer ) ;
ha - > optrom_buffer = NULL ;
break ;
case 1 :
if ( ha - > optrom_state ! = QLA_SWAITING )
break ;
2007-09-21 01:07:35 +04:00
ha - > optrom_region_start = start ;
ha - > optrom_region_size = start + size > ha - > optrom_size ?
ha - > optrom_size - start : size ;
2006-02-01 03:05:17 +03:00
ha - > optrom_state = QLA_SREADING ;
2007-09-21 01:07:35 +04:00
ha - > optrom_buffer = vmalloc ( ha - > optrom_region_size ) ;
2006-02-01 03:05:17 +03:00
if ( ha - > optrom_buffer = = NULL ) {
qla_printk ( KERN_WARNING , ha ,
" Unable to allocate memory for optrom retrieval "
2007-09-21 01:07:35 +04:00
" (%x). \n " , ha - > optrom_region_size ) ;
2006-02-01 03:05:17 +03:00
ha - > optrom_state = QLA_SWAITING ;
return count ;
}
2007-09-21 01:07:35 +04:00
DEBUG2 ( qla_printk ( KERN_INFO , ha ,
" Reading flash region -- 0x%x/0x%x. \n " ,
ha - > optrom_region_start , ha - > optrom_region_size ) ) ;
memset ( ha - > optrom_buffer , 0 , ha - > optrom_region_size ) ;
2008-11-06 21:40:19 +03:00
ha - > isp_ops - > read_optrom ( vha , ha - > optrom_buffer ,
2007-09-21 01:07:35 +04:00
ha - > optrom_region_start , ha - > optrom_region_size ) ;
2006-02-01 03:05:17 +03:00
break ;
case 2 :
if ( ha - > optrom_state ! = QLA_SWAITING )
break ;
2007-09-21 01:07:35 +04:00
/*
* We need to be more restrictive on which FLASH regions are
* allowed to be updated via user - space . Regions accessible
* via this method include :
*
* ISP21xx / ISP22xx / ISP23xx type boards :
*
* 0x000000 - > 0x020000 - - Boot code .
*
* ISP2322 / ISP24xx type boards :
*
* 0x000000 - > 0x07ffff - - Boot code .
* 0x080000 - > 0x0fffff - - Firmware .
*
* ISP25xx type boards :
*
* 0x000000 - > 0x07ffff - - Boot code .
* 0x080000 - > 0x0fffff - - Firmware .
* 0x120000 - > 0x12ffff - - VPD and HBA parameters .
*/
valid = 0 ;
if ( ha - > optrom_size = = OPTROM_SIZE_2300 & & start = = 0 )
valid = 1 ;
2008-09-12 08:22:49 +04:00
else if ( start = = ( ha - > flt_region_boot * 4 ) | |
start = = ( ha - > flt_region_fw * 4 ) )
2007-09-21 01:07:35 +04:00
valid = 1 ;
2009-03-05 22:07:00 +03:00
else if ( IS_QLA25XX ( ha ) | | IS_QLA81XX ( ha ) )
2007-09-21 01:07:35 +04:00
valid = 1 ;
if ( ! valid ) {
qla_printk ( KERN_WARNING , ha ,
" Invalid start region 0x%x/0x%x. \n " , start , size ) ;
return - EINVAL ;
}
ha - > optrom_region_start = start ;
ha - > optrom_region_size = start + size > ha - > optrom_size ?
ha - > optrom_size - start : size ;
2006-02-01 03:05:17 +03:00
ha - > optrom_state = QLA_SWRITING ;
2007-09-21 01:07:35 +04:00
ha - > optrom_buffer = vmalloc ( ha - > optrom_region_size ) ;
2006-02-01 03:05:17 +03:00
if ( ha - > optrom_buffer = = NULL ) {
qla_printk ( KERN_WARNING , ha ,
" Unable to allocate memory for optrom update "
2007-09-21 01:07:35 +04:00
" (%x). \n " , ha - > optrom_region_size ) ;
2006-02-01 03:05:17 +03:00
ha - > optrom_state = QLA_SWAITING ;
return count ;
}
2007-09-21 01:07:35 +04:00
DEBUG2 ( qla_printk ( KERN_INFO , ha ,
" Staging flash region write -- 0x%x/0x%x. \n " ,
ha - > optrom_region_start , ha - > optrom_region_size ) ) ;
memset ( ha - > optrom_buffer , 0 , ha - > optrom_region_size ) ;
2006-02-01 03:05:17 +03:00
break ;
case 3 :
if ( ha - > optrom_state ! = QLA_SWRITING )
break ;
2007-09-21 01:07:35 +04:00
DEBUG2 ( qla_printk ( KERN_INFO , ha ,
" Writing flash region -- 0x%x/0x%x. \n " ,
ha - > optrom_region_start , ha - > optrom_region_size ) ) ;
2008-11-06 21:40:19 +03:00
ha - > isp_ops - > write_optrom ( vha , ha - > optrom_buffer ,
2007-09-21 01:07:35 +04:00
ha - > optrom_region_start , ha - > optrom_region_size ) ;
2006-02-01 03:05:17 +03:00
break ;
2007-09-21 01:07:35 +04:00
default :
count = - EINVAL ;
2006-02-01 03:05:17 +03:00
}
return count ;
}
static struct bin_attribute sysfs_optrom_ctl_attr = {
. attr = {
. name = " optrom_ctl " ,
. mode = S_IWUSR ,
} ,
. size = 0 ,
. write = qla2x00_sysfs_write_optrom_ctl ,
} ;
2006-03-10 01:27:34 +03:00
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_read_vpd ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2006-03-10 01:27:34 +03:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2006-03-10 01:27:34 +03:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2006-03-10 01:27:34 +03:00
2008-07-24 19:31:47 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) )
2006-03-10 01:27:34 +03:00
return 0 ;
2007-07-27 00:43:34 +04:00
/* Read NVRAM data from cache. */
2008-07-24 19:31:47 +04:00
return memory_read_from_buffer ( buf , count , & off , ha - > vpd , ha - > vpd_size ) ;
2006-03-10 01:27:34 +03:00
}
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_write_vpd ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2006-03-10 01:27:34 +03:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2006-03-10 01:27:34 +03:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2006-03-10 01:27:34 +03:00
if ( ! capable ( CAP_SYS_ADMIN ) | | off ! = 0 | | count ! = ha - > vpd_size )
return 0 ;
/* Write NVRAM. */
2008-11-06 21:40:19 +03:00
ha - > isp_ops - > write_nvram ( vha , ( uint8_t * ) buf , ha - > vpd_base , count ) ;
ha - > isp_ops - > read_nvram ( vha , ( uint8_t * ) ha - > vpd , ha - > vpd_base , count ) ;
2006-03-10 01:27:34 +03:00
return count ;
}
static struct bin_attribute sysfs_vpd_attr = {
. attr = {
. name = " vpd " ,
. mode = S_IRUSR | S_IWUSR ,
} ,
. size = 0 ,
. read = qla2x00_sysfs_read_vpd ,
. write = qla2x00_sysfs_write_vpd ,
} ;
2006-06-24 03:10:50 +04:00
static ssize_t
2007-06-09 09:57:22 +04:00
qla2x00_sysfs_read_sfp ( struct kobject * kobj ,
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2006-06-24 03:10:50 +04:00
{
2008-11-06 21:40:19 +03:00
struct scsi_qla_host * vha = shost_priv ( dev_to_shost ( container_of ( kobj ,
2006-06-24 03:10:50 +04:00
struct device , kobj ) ) ) ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2006-06-24 03:10:50 +04:00
uint16_t iter , addr , offset ;
int rval ;
if ( ! capable ( CAP_SYS_ADMIN ) | | off ! = 0 | | count ! = SFP_DEV_SIZE * 2 )
return 0 ;
2008-01-31 23:33:48 +03:00
if ( ha - > sfp_data )
goto do_read ;
ha - > sfp_data = dma_pool_alloc ( ha - > s_dma_pool , GFP_KERNEL ,
& ha - > sfp_data_dma ) ;
if ( ! ha - > sfp_data ) {
qla_printk ( KERN_WARNING , ha ,
" Unable to allocate memory for SFP read-data. \n " ) ;
return 0 ;
}
do_read :
memset ( ha - > sfp_data , 0 , SFP_BLOCK_SIZE ) ;
2006-06-24 03:10:50 +04:00
addr = 0xa0 ;
for ( iter = 0 , offset = 0 ; iter < ( SFP_DEV_SIZE * 2 ) / SFP_BLOCK_SIZE ;
iter + + , offset + = SFP_BLOCK_SIZE ) {
if ( iter = = 4 ) {
/* Skip to next device address. */
addr = 0xa2 ;
offset = 0 ;
}
2008-11-06 21:40:19 +03:00
rval = qla2x00_read_sfp ( vha , ha - > sfp_data_dma , addr , offset ,
2006-06-24 03:10:50 +04:00
SFP_BLOCK_SIZE ) ;
if ( rval ! = QLA_SUCCESS ) {
qla_printk ( KERN_WARNING , ha ,
" Unable to read SFP data (%x/%x/%x). \n " , rval ,
addr , offset ) ;
count = 0 ;
break ;
}
memcpy ( buf , ha - > sfp_data , SFP_BLOCK_SIZE ) ;
buf + = SFP_BLOCK_SIZE ;
}
return count ;
}
static struct bin_attribute sysfs_sfp_attr = {
. attr = {
. name = " sfp " ,
. mode = S_IRUSR | S_IWUSR ,
} ,
. size = SFP_DEV_SIZE * 2 ,
. read = qla2x00_sysfs_read_sfp ,
} ;
2006-10-13 20:33:37 +04:00
static struct sysfs_entry {
char * name ;
struct bin_attribute * attr ;
int is4GBp_only ;
} bin_file_entries [ ] = {
{ " fw_dump " , & sysfs_fw_dump_attr , } ,
{ " nvram " , & sysfs_nvram_attr , } ,
{ " optrom " , & sysfs_optrom_attr , } ,
{ " optrom_ctl " , & sysfs_optrom_ctl_attr , } ,
{ " vpd " , & sysfs_vpd_attr , 1 } ,
{ " sfp " , & sysfs_sfp_attr , 1 } ,
2006-11-27 20:35:42 +03:00
{ NULL } ,
2006-10-13 20:33:37 +04:00
} ;
2005-04-18 00:04:54 +04:00
void
2008-11-06 21:40:19 +03:00
qla2x00_alloc_sysfs_attr ( scsi_qla_host_t * vha )
2005-04-18 00:04:54 +04:00
{
2008-11-06 21:40:19 +03:00
struct Scsi_Host * host = vha - > host ;
2006-10-13 20:33:37 +04:00
struct sysfs_entry * iter ;
int ret ;
2005-04-18 00:04:54 +04:00
2006-10-13 20:33:37 +04:00
for ( iter = bin_file_entries ; iter - > name ; iter + + ) {
2008-11-06 21:40:19 +03:00
if ( iter - > is4GBp_only & & ! IS_FWI2_CAPABLE ( vha - > hw ) )
2006-10-13 20:33:37 +04:00
continue ;
ret = sysfs_create_bin_file ( & host - > shost_gendev . kobj ,
iter - > attr ) ;
if ( ret )
2008-11-06 21:40:19 +03:00
qla_printk ( KERN_INFO , vha - > hw ,
2006-10-13 20:33:37 +04:00
" Unable to create sysfs %s binary attribute "
" (%d). \n " , iter - > name , ret ) ;
2006-06-24 03:10:55 +04:00
}
2005-04-18 00:04:54 +04:00
}
void
2008-11-06 21:40:19 +03:00
qla2x00_free_sysfs_attr ( scsi_qla_host_t * vha )
2005-04-18 00:04:54 +04:00
{
2008-11-06 21:40:19 +03:00
struct Scsi_Host * host = vha - > host ;
2006-10-13 20:33:37 +04:00
struct sysfs_entry * iter ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2006-10-13 20:33:37 +04:00
for ( iter = bin_file_entries ; iter - > name ; iter + + ) {
2007-07-20 02:05:56 +04:00
if ( iter - > is4GBp_only & & ! IS_FWI2_CAPABLE ( ha ) )
2006-10-13 20:33:37 +04:00
continue ;
2005-04-18 00:04:54 +04:00
2006-06-24 03:10:50 +04:00
sysfs_remove_bin_file ( & host - > shost_gendev . kobj ,
2006-10-13 20:33:37 +04:00
iter - > attr ) ;
2006-06-24 03:10:55 +04:00
}
2006-02-01 03:05:07 +03:00
if ( ha - > beacon_blink_led = = 1 )
2008-11-06 21:40:19 +03:00
ha - > isp_ops - > beacon_off ( vha ) ;
2005-04-18 00:04:54 +04:00
}
2005-08-27 06:09:40 +04:00
/* Scsi_Host attributes. */
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_drvr_version_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2005-08-27 06:09:40 +04:00
{
return snprintf ( buf , PAGE_SIZE , " %s \n " , qla2x00_version_str ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_fw_version_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2005-08-27 06:09:40 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
char fw_str [ 128 ] ;
2005-08-27 06:09:40 +04:00
return snprintf ( buf , PAGE_SIZE , " %s \n " ,
2008-11-06 21:40:19 +03:00
ha - > isp_ops - > fw_version_str ( vha , fw_str ) ) ;
2005-08-27 06:09:40 +04:00
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_serial_num_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-08-27 06:09:40 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:09:40 +04:00
uint32_t sn ;
2008-07-11 03:55:53 +04:00
if ( IS_FWI2_CAPABLE ( ha ) ) {
2008-11-06 21:40:19 +03:00
qla2xxx_get_vpd_field ( vha , " SN " , buf , PAGE_SIZE ) ;
2008-07-11 03:55:53 +04:00
return snprintf ( buf , PAGE_SIZE , " %s \n " , buf ) ;
}
2007-10-20 02:59:19 +04:00
2005-08-27 06:09:40 +04:00
sn = ( ( ha - > serial0 & 0x1f ) < < 16 ) | ( ha - > serial2 < < 8 ) | ha - > serial1 ;
return snprintf ( buf , PAGE_SIZE , " %c%05d \n " , ' A ' + sn / 100000 ,
sn % 100000 ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_isp_name_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-08-27 06:09:40 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
return snprintf ( buf , PAGE_SIZE , " ISP%04X \n " , vha - > hw - > pdev - > device ) ;
2005-08-27 06:09:40 +04:00
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_isp_id_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-08-27 06:09:40 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:09:40 +04:00
return snprintf ( buf , PAGE_SIZE , " %04x %04x %04x %04x \n " ,
ha - > product_id [ 0 ] , ha - > product_id [ 1 ] , ha - > product_id [ 2 ] ,
ha - > product_id [ 3 ] ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_model_name_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-08-27 06:09:40 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
return snprintf ( buf , PAGE_SIZE , " %s \n " , vha - > hw - > model_number ) ;
2005-08-27 06:09:40 +04:00
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_model_desc_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-08-27 06:09:40 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
2005-08-27 06:09:40 +04:00
return snprintf ( buf , PAGE_SIZE , " %s \n " ,
2008-11-06 21:40:19 +03:00
vha - > hw - > model_desc ? vha - > hw - > model_desc : " " ) ;
2005-08-27 06:09:40 +04:00
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_pci_info_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-08-27 06:09:40 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
2005-08-27 06:09:40 +04:00
char pci_info [ 30 ] ;
return snprintf ( buf , PAGE_SIZE , " %s \n " ,
2008-11-06 21:40:19 +03:00
vha - > hw - > isp_ops - > pci_info_str ( vha , pci_info ) ) ;
2005-08-27 06:09:40 +04:00
}
static ssize_t
2008-03-18 16:32:28 +03:00
qla2x00_link_state_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-08-27 06:09:40 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:09:40 +04:00
int len = 0 ;
2008-11-06 21:40:19 +03:00
if ( atomic_read ( & vha - > loop_state ) = = LOOP_DOWN | |
atomic_read ( & vha - > loop_state ) = = LOOP_DEAD )
2005-08-27 06:09:40 +04:00
len = snprintf ( buf , PAGE_SIZE , " Link Down \n " ) ;
2008-11-06 21:40:19 +03:00
else if ( atomic_read ( & vha - > loop_state ) ! = LOOP_READY | |
test_bit ( ABORT_ISP_ACTIVE , & vha - > dpc_flags ) | |
test_bit ( ISP_ABORT_NEEDED , & vha - > dpc_flags ) )
2005-08-27 06:09:40 +04:00
len = snprintf ( buf , PAGE_SIZE , " Unknown Link State \n " ) ;
else {
len = snprintf ( buf , PAGE_SIZE , " Link Up - " ) ;
switch ( ha - > current_topology ) {
case ISP_CFG_NL :
len + = snprintf ( buf + len , PAGE_SIZE - len , " Loop \n " ) ;
break ;
case ISP_CFG_FL :
len + = snprintf ( buf + len , PAGE_SIZE - len , " FL_Port \n " ) ;
break ;
case ISP_CFG_N :
len + = snprintf ( buf + len , PAGE_SIZE - len ,
" N_Port to N_Port \n " ) ;
break ;
case ISP_CFG_F :
len + = snprintf ( buf + len , PAGE_SIZE - len , " F_Port \n " ) ;
break ;
default :
len + = snprintf ( buf + len , PAGE_SIZE - len , " Loop \n " ) ;
break ;
}
}
return len ;
}
2005-10-27 22:09:48 +04:00
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_zio_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-10-27 22:09:48 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
2005-10-27 22:09:48 +04:00
int len = 0 ;
2008-11-06 21:40:19 +03:00
switch ( vha - > hw - > zio_mode ) {
2005-10-27 22:09:48 +04:00
case QLA_ZIO_MODE_6 :
len + = snprintf ( buf + len , PAGE_SIZE - len , " Mode 6 \n " ) ;
break ;
case QLA_ZIO_DISABLED :
len + = snprintf ( buf + len , PAGE_SIZE - len , " Disabled \n " ) ;
break ;
}
return len ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_zio_store ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
2005-10-27 22:09:48 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2005-10-27 22:09:48 +04:00
int val = 0 ;
uint16_t zio_mode ;
2006-03-10 01:27:39 +03:00
if ( ! IS_ZIO_SUPPORTED ( ha ) )
return - ENOTSUPP ;
2005-10-27 22:09:48 +04:00
if ( sscanf ( buf , " %d " , & val ) ! = 1 )
return - EINVAL ;
2006-03-10 01:27:39 +03:00
if ( val )
2005-10-27 22:09:48 +04:00
zio_mode = QLA_ZIO_MODE_6 ;
2006-03-10 01:27:39 +03:00
else
2005-10-27 22:09:48 +04:00
zio_mode = QLA_ZIO_DISABLED ;
/* Update per-hba values and queue a reset. */
if ( zio_mode ! = QLA_ZIO_DISABLED | | ha - > zio_mode ! = QLA_ZIO_DISABLED ) {
ha - > zio_mode = zio_mode ;
2008-11-06 21:40:19 +03:00
set_bit ( ISP_ABORT_NEEDED , & vha - > dpc_flags ) ;
2005-10-27 22:09:48 +04:00
}
return strlen ( buf ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_zio_timer_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2005-10-27 22:09:48 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
2005-10-27 22:09:48 +04:00
2008-11-06 21:40:19 +03:00
return snprintf ( buf , PAGE_SIZE , " %d us \n " , vha - > hw - > zio_timer * 100 ) ;
2005-10-27 22:09:48 +04:00
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_zio_timer_store ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
2005-10-27 22:09:48 +04:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
2005-10-27 22:09:48 +04:00
int val = 0 ;
uint16_t zio_timer ;
if ( sscanf ( buf , " %d " , & val ) ! = 1 )
return - EINVAL ;
if ( val > 25500 | | val < 100 )
return - ERANGE ;
zio_timer = ( uint16_t ) ( val / 100 ) ;
2008-11-06 21:40:19 +03:00
vha - > hw - > zio_timer = zio_timer ;
2005-10-27 22:09:48 +04:00
return strlen ( buf ) ;
}
2006-02-01 03:05:07 +03:00
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_beacon_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
2006-02-01 03:05:07 +03:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
2006-02-01 03:05:07 +03:00
int len = 0 ;
2008-11-06 21:40:19 +03:00
if ( vha - > hw - > beacon_blink_led )
2006-02-01 03:05:07 +03:00
len + = snprintf ( buf + len , PAGE_SIZE - len , " Enabled \n " ) ;
else
len + = snprintf ( buf + len , PAGE_SIZE - len , " Disabled \n " ) ;
return len ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_beacon_store ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
2006-02-01 03:05:07 +03:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2006-02-01 03:05:07 +03:00
int val = 0 ;
int rval ;
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
return - EPERM ;
2008-11-06 21:40:19 +03:00
if ( test_bit ( ABORT_ISP_ACTIVE , & vha - > dpc_flags ) ) {
2006-02-01 03:05:07 +03:00
qla_printk ( KERN_WARNING , ha ,
" Abort ISP active -- ignoring beacon request. \n " ) ;
return - EBUSY ;
}
if ( sscanf ( buf , " %d " , & val ) ! = 1 )
return - EINVAL ;
if ( val )
2008-11-06 21:40:19 +03:00
rval = ha - > isp_ops - > beacon_on ( vha ) ;
2006-02-01 03:05:07 +03:00
else
2008-11-06 21:40:19 +03:00
rval = ha - > isp_ops - > beacon_off ( vha ) ;
2006-02-01 03:05:07 +03:00
if ( rval ! = QLA_SUCCESS )
count = 0 ;
return count ;
}
2007-01-29 21:22:21 +03:00
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_optrom_bios_version_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2007-01-29 21:22:21 +03:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2007-01-29 21:22:21 +03:00
return snprintf ( buf , PAGE_SIZE , " %d.%02d \n " , ha - > bios_revision [ 1 ] ,
ha - > bios_revision [ 0 ] ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_optrom_efi_version_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2007-01-29 21:22:21 +03:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2007-01-29 21:22:21 +03:00
return snprintf ( buf , PAGE_SIZE , " %d.%02d \n " , ha - > efi_revision [ 1 ] ,
ha - > efi_revision [ 0 ] ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_optrom_fcode_version_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2007-01-29 21:22:21 +03:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2007-01-29 21:22:21 +03:00
return snprintf ( buf , PAGE_SIZE , " %d.%02d \n " , ha - > fcode_revision [ 1 ] ,
ha - > fcode_revision [ 0 ] ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
qla2x00_optrom_fw_version_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2007-01-29 21:22:21 +03:00
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2007-01-29 21:22:21 +03:00
return snprintf ( buf , PAGE_SIZE , " %d.%02d.%02d %d \n " ,
ha - > fw_revision [ 0 ] , ha - > fw_revision [ 1 ] , ha - > fw_revision [ 2 ] ,
ha - > fw_revision [ 3 ] ) ;
}
2008-07-11 03:55:49 +04:00
static ssize_t
qla2x00_total_isp_aborts_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
2008-07-11 03:55:49 +04:00
return snprintf ( buf , PAGE_SIZE , " %d \n " ,
ha - > qla_stats . total_isp_aborts ) ;
}
2009-01-05 22:18:11 +03:00
static ssize_t
qla2x00_mpi_version_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
{
scsi_qla_host_t * vha = shost_priv ( class_to_shost ( dev ) ) ;
struct qla_hw_data * ha = vha - > hw ;
if ( ! IS_QLA81XX ( ha ) )
return snprintf ( buf , PAGE_SIZE , " \n " ) ;
return snprintf ( buf , PAGE_SIZE , " %02x.%02x.%02x.%02x (%x) \n " ,
ha - > mpi_version [ 0 ] , ha - > mpi_version [ 1 ] , ha - > mpi_version [ 2 ] ,
ha - > mpi_version [ 3 ] , ha - > mpi_capabilities ) ;
}
2008-02-22 02:13:36 +03:00
static DEVICE_ATTR ( driver_version , S_IRUGO , qla2x00_drvr_version_show , NULL ) ;
static DEVICE_ATTR ( fw_version , S_IRUGO , qla2x00_fw_version_show , NULL ) ;
static DEVICE_ATTR ( serial_num , S_IRUGO , qla2x00_serial_num_show , NULL ) ;
static DEVICE_ATTR ( isp_name , S_IRUGO , qla2x00_isp_name_show , NULL ) ;
static DEVICE_ATTR ( isp_id , S_IRUGO , qla2x00_isp_id_show , NULL ) ;
static DEVICE_ATTR ( model_name , S_IRUGO , qla2x00_model_name_show , NULL ) ;
static DEVICE_ATTR ( model_desc , S_IRUGO , qla2x00_model_desc_show , NULL ) ;
static DEVICE_ATTR ( pci_info , S_IRUGO , qla2x00_pci_info_show , NULL ) ;
2008-03-18 16:32:28 +03:00
static DEVICE_ATTR ( link_state , S_IRUGO , qla2x00_link_state_show , NULL ) ;
2008-02-22 02:13:36 +03:00
static DEVICE_ATTR ( zio , S_IRUGO | S_IWUSR , qla2x00_zio_show , qla2x00_zio_store ) ;
static DEVICE_ATTR ( zio_timer , S_IRUGO | S_IWUSR , qla2x00_zio_timer_show ,
qla2x00_zio_timer_store ) ;
static DEVICE_ATTR ( beacon , S_IRUGO | S_IWUSR , qla2x00_beacon_show ,
qla2x00_beacon_store ) ;
static DEVICE_ATTR ( optrom_bios_version , S_IRUGO ,
qla2x00_optrom_bios_version_show , NULL ) ;
static DEVICE_ATTR ( optrom_efi_version , S_IRUGO ,
qla2x00_optrom_efi_version_show , NULL ) ;
static DEVICE_ATTR ( optrom_fcode_version , S_IRUGO ,
qla2x00_optrom_fcode_version_show , NULL ) ;
static DEVICE_ATTR ( optrom_fw_version , S_IRUGO , qla2x00_optrom_fw_version_show ,
NULL ) ;
2008-07-11 03:55:49 +04:00
static DEVICE_ATTR ( total_isp_aborts , S_IRUGO , qla2x00_total_isp_aborts_show ,
NULL ) ;
2009-01-05 22:18:11 +03:00
static DEVICE_ATTR ( mpi_version , S_IRUGO , qla2x00_mpi_version_show , NULL ) ;
2008-02-22 02:13:36 +03:00
struct device_attribute * qla2x00_host_attrs [ ] = {
& dev_attr_driver_version ,
& dev_attr_fw_version ,
& dev_attr_serial_num ,
& dev_attr_isp_name ,
& dev_attr_isp_id ,
& dev_attr_model_name ,
& dev_attr_model_desc ,
& dev_attr_pci_info ,
2008-03-18 16:32:28 +03:00
& dev_attr_link_state ,
2008-02-22 02:13:36 +03:00
& dev_attr_zio ,
& dev_attr_zio_timer ,
& dev_attr_beacon ,
& dev_attr_optrom_bios_version ,
& dev_attr_optrom_efi_version ,
& dev_attr_optrom_fcode_version ,
& dev_attr_optrom_fw_version ,
2008-07-11 03:55:49 +04:00
& dev_attr_total_isp_aborts ,
2009-01-05 22:18:11 +03:00
& dev_attr_mpi_version ,
2005-08-27 06:09:40 +04:00
NULL ,
} ;
2005-04-18 00:04:54 +04:00
/* Host attributes. */
static void
qla2x00_get_host_port_id ( struct Scsi_Host * shost )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( shost ) ;
2005-04-18 00:04:54 +04:00
2008-11-06 21:40:19 +03:00
fc_host_port_id ( shost ) = vha - > d_id . b . domain < < 16 |
vha - > d_id . b . area < < 8 | vha - > d_id . b . al_pa ;
2005-04-18 00:04:54 +04:00
}
2006-02-01 03:04:51 +03:00
static void
qla2x00_get_host_speed ( struct Scsi_Host * shost )
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = ( ( struct scsi_qla_host * )
( shost_priv ( shost ) ) ) - > hw ;
2008-04-04 00:13:14 +04:00
u32 speed = FC_PORTSPEED_UNKNOWN ;
2006-02-01 03:04:51 +03:00
switch ( ha - > link_data_rate ) {
2006-10-02 23:00:43 +04:00
case PORT_SPEED_1GB :
2008-04-04 00:13:14 +04:00
speed = FC_PORTSPEED_1GBIT ;
2006-02-01 03:04:51 +03:00
break ;
2006-10-02 23:00:43 +04:00
case PORT_SPEED_2GB :
2008-04-04 00:13:14 +04:00
speed = FC_PORTSPEED_2GBIT ;
2006-02-01 03:04:51 +03:00
break ;
2006-10-02 23:00:43 +04:00
case PORT_SPEED_4GB :
2008-04-04 00:13:14 +04:00
speed = FC_PORTSPEED_4GBIT ;
2006-02-01 03:04:51 +03:00
break ;
2008-01-31 23:33:52 +03:00
case PORT_SPEED_8GB :
2008-04-04 00:13:14 +04:00
speed = FC_PORTSPEED_8GBIT ;
2008-01-31 23:33:52 +03:00
break ;
2009-01-05 22:18:11 +03:00
case PORT_SPEED_10GB :
speed = FC_PORTSPEED_10GBIT ;
break ;
2006-02-01 03:04:51 +03:00
}
fc_host_speed ( shost ) = speed ;
}
2006-02-01 03:04:56 +03:00
static void
qla2x00_get_host_port_type ( struct Scsi_Host * shost )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( shost ) ;
2006-02-01 03:04:56 +03:00
uint32_t port_type = FC_PORTTYPE_UNKNOWN ;
2008-11-06 21:40:19 +03:00
if ( vha - > vp_idx ) {
2008-05-13 09:21:07 +04:00
fc_host_port_type ( shost ) = FC_PORTTYPE_NPIV ;
return ;
}
2008-11-06 21:40:19 +03:00
switch ( vha - > hw - > current_topology ) {
2006-02-01 03:04:56 +03:00
case ISP_CFG_NL :
port_type = FC_PORTTYPE_LPORT ;
break ;
case ISP_CFG_FL :
port_type = FC_PORTTYPE_NLPORT ;
break ;
case ISP_CFG_N :
port_type = FC_PORTTYPE_PTP ;
break ;
case ISP_CFG_F :
port_type = FC_PORTTYPE_NPORT ;
break ;
}
fc_host_port_type ( shost ) = port_type ;
}
2005-04-18 00:04:54 +04:00
static void
qla2x00_get_starget_node_name ( struct scsi_target * starget )
{
struct Scsi_Host * host = dev_to_shost ( starget - > dev . parent ) ;
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( host ) ;
2005-04-18 00:06:53 +04:00
fc_port_t * fcport ;
2005-09-01 02:21:20 +04:00
u64 node_name = 0 ;
2005-04-18 00:04:54 +04:00
2008-11-06 21:40:19 +03:00
list_for_each_entry ( fcport , & vha - > vp_fcports , list ) {
2008-04-04 00:13:16 +04:00
if ( fcport - > rport & &
starget - > id = = fcport - > rport - > scsi_target_id ) {
2005-09-01 02:21:20 +04:00
node_name = wwn_to_u64 ( fcport - > node_name ) ;
2005-04-18 00:06:53 +04:00
break ;
}
}
2005-09-01 02:21:20 +04:00
fc_starget_node_name ( starget ) = node_name ;
2005-04-18 00:04:54 +04:00
}
static void
qla2x00_get_starget_port_name ( struct scsi_target * starget )
{
struct Scsi_Host * host = dev_to_shost ( starget - > dev . parent ) ;
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( host ) ;
2005-04-18 00:06:53 +04:00
fc_port_t * fcport ;
2005-09-01 02:21:20 +04:00
u64 port_name = 0 ;
2005-04-18 00:04:54 +04:00
2008-11-06 21:40:19 +03:00
list_for_each_entry ( fcport , & vha - > vp_fcports , list ) {
2008-04-04 00:13:16 +04:00
if ( fcport - > rport & &
starget - > id = = fcport - > rport - > scsi_target_id ) {
2005-09-01 02:21:20 +04:00
port_name = wwn_to_u64 ( fcport - > port_name ) ;
2005-04-18 00:06:53 +04:00
break ;
}
}
2005-09-01 02:21:20 +04:00
fc_starget_port_name ( starget ) = port_name ;
2005-04-18 00:04:54 +04:00
}
static void
qla2x00_get_starget_port_id ( struct scsi_target * starget )
{
struct Scsi_Host * host = dev_to_shost ( starget - > dev . parent ) ;
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( host ) ;
2005-04-18 00:06:53 +04:00
fc_port_t * fcport ;
uint32_t port_id = ~ 0U ;
2008-11-06 21:40:19 +03:00
list_for_each_entry ( fcport , & vha - > vp_fcports , list ) {
2008-04-04 00:13:16 +04:00
if ( fcport - > rport & &
starget - > id = = fcport - > rport - > scsi_target_id ) {
2005-04-18 00:06:53 +04:00
port_id = fcport - > d_id . b . domain < < 16 |
fcport - > d_id . b . area < < 8 | fcport - > d_id . b . al_pa ;
break ;
}
}
2005-04-18 00:04:54 +04:00
fc_starget_port_id ( starget ) = port_id ;
}
static void
qla2x00_set_rport_loss_tmo ( struct fc_rport * rport , uint32_t timeout )
{
if ( timeout )
2008-07-11 03:55:48 +04:00
rport - > dev_loss_tmo = timeout ;
2005-04-18 00:04:54 +04:00
else
2008-07-11 03:55:48 +04:00
rport - > dev_loss_tmo = 1 ;
2005-04-18 00:04:54 +04:00
}
2008-07-11 03:55:47 +04:00
static void
qla2x00_dev_loss_tmo_callbk ( struct fc_rport * rport )
{
struct Scsi_Host * host = rport_to_shost ( rport ) ;
fc_port_t * fcport = * ( fc_port_t * * ) rport - > dd_data ;
2009-01-22 20:45:38 +03:00
if ( ! fcport )
return ;
2008-07-11 03:55:47 +04:00
qla2x00_abort_fcport_cmds ( fcport ) ;
/*
* Transport has effectively ' deleted ' the rport , clear
* all local references .
*/
spin_lock_irq ( host - > host_lock ) ;
fcport - > rport = NULL ;
* ( ( fc_port_t * * ) rport - > dd_data ) = NULL ;
spin_unlock_irq ( host - > host_lock ) ;
}
static void
qla2x00_terminate_rport_io ( struct fc_rport * rport )
{
fc_port_t * fcport = * ( fc_port_t * * ) rport - > dd_data ;
2009-01-22 20:45:38 +03:00
if ( ! fcport )
return ;
2008-08-14 08:36:56 +04:00
/*
* At this point all fcport ' s software - states are cleared . Perform any
* final cleanup of firmware resources ( PCBs and XCBs ) .
*/
2009-03-24 19:08:02 +03:00
if ( fcport - > loop_id ! = FC_NO_LOOP_ID )
2008-11-06 21:40:19 +03:00
fcport - > vha - > hw - > isp_ops - > fabric_logout ( fcport - > vha ,
fcport - > loop_id , fcport - > d_id . b . domain ,
fcport - > d_id . b . area , fcport - > d_id . b . al_pa ) ;
2008-08-14 08:36:56 +04:00
2008-07-11 03:55:47 +04:00
qla2x00_abort_fcport_cmds ( fcport ) ;
}
2005-10-28 03:03:37 +04:00
static int
qla2x00_issue_lip ( struct Scsi_Host * shost )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( shost ) ;
2005-10-28 03:03:37 +04:00
2008-11-06 21:40:19 +03:00
qla2x00_loop_reset ( vha ) ;
2005-10-28 03:03:37 +04:00
return 0 ;
}
2006-02-01 03:05:02 +03:00
static struct fc_host_statistics *
qla2x00_get_fc_host_stats ( struct Scsi_Host * shost )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( shost ) ;
struct qla_hw_data * ha = vha - > hw ;
struct scsi_qla_host * base_vha = pci_get_drvdata ( ha - > pdev ) ;
2006-02-01 03:05:02 +03:00
int rval ;
2008-01-17 20:02:08 +03:00
struct link_statistics * stats ;
dma_addr_t stats_dma ;
2006-02-01 03:05:02 +03:00
struct fc_host_statistics * pfc_host_stat ;
pfc_host_stat = & ha - > fc_host_stat ;
memset ( pfc_host_stat , - 1 , sizeof ( struct fc_host_statistics ) ) ;
2008-01-17 20:02:08 +03:00
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 " ,
2008-11-06 21:40:19 +03:00
__func__ , base_vha - > host_no ) ) ;
2008-01-17 20:02:08 +03:00
goto done ;
}
memset ( stats , 0 , DMA_POOL_SIZE ) ;
rval = QLA_FUNCTION_FAILED ;
2007-07-20 02:05:56 +04:00
if ( IS_FWI2_CAPABLE ( ha ) ) {
2008-11-06 21:40:19 +03:00
rval = qla24xx_get_isp_stats ( base_vha , stats , stats_dma ) ;
} else if ( atomic_read ( & base_vha - > loop_state ) = = LOOP_READY & &
! test_bit ( ABORT_ISP_ACTIVE , & base_vha - > dpc_flags ) & &
! test_bit ( ISP_ABORT_NEEDED , & base_vha - > dpc_flags ) & &
2007-01-29 21:22:25 +03:00
! ha - > dpc_active ) {
/* Must be in a 'READY' state for statistics retrieval. */
2008-11-06 21:40:19 +03:00
rval = qla2x00_get_link_status ( base_vha , base_vha - > loop_id ,
stats , stats_dma ) ;
2006-02-01 03:05:02 +03:00
}
2007-01-29 21:22:25 +03:00
if ( rval ! = QLA_SUCCESS )
2008-01-17 20:02:08 +03:00
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 ) ) {
2008-07-11 03:55:50 +04:00
pfc_host_stat - > lip_count = stats - > lip_cnt ;
2008-01-17 20:02:08 +03:00
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 ;
}
2008-09-12 08:22:47 +04:00
pfc_host_stat - > fcp_input_megabytes = ha - > qla_stats . input_bytes > > 20 ;
pfc_host_stat - > fcp_output_megabytes = ha - > qla_stats . output_bytes > > 20 ;
2006-02-01 03:05:02 +03:00
2008-01-17 20:02:08 +03:00
done_free :
dma_pool_free ( ha - > s_dma_pool , stats , stats_dma ) ;
2007-01-29 21:22:25 +03:00
done :
2006-02-01 03:05:02 +03:00
return pfc_host_stat ;
}
2006-10-02 23:00:44 +04:00
static void
qla2x00_get_host_symbolic_name ( struct Scsi_Host * shost )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( shost ) ;
2006-10-02 23:00:44 +04:00
2008-11-06 21:40:19 +03:00
qla2x00_get_sym_node_name ( vha , fc_host_symbolic_name ( shost ) ) ;
2006-10-02 23:00:44 +04:00
}
2006-10-02 23:00:45 +04:00
static void
qla2x00_set_host_system_hostname ( struct Scsi_Host * shost )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( shost ) ;
2006-10-02 23:00:45 +04:00
2008-11-06 21:40:19 +03:00
set_bit ( REGISTER_FDMI_NEEDED , & vha - > dpc_flags ) ;
2006-10-02 23:00:45 +04:00
}
2006-10-02 23:00:46 +04:00
static void
qla2x00_get_host_fabric_name ( struct Scsi_Host * shost )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( shost ) ;
2006-10-02 23:00:46 +04:00
u64 node_name ;
2008-11-06 21:40:19 +03:00
if ( vha - > device_flags & SWITCH_FOUND )
node_name = wwn_to_u64 ( vha - > fabric_node_name ) ;
2006-10-02 23:00:46 +04:00
else
2008-11-06 21:40:19 +03:00
node_name = wwn_to_u64 ( vha - > node_name ) ;
2006-10-02 23:00:46 +04:00
fc_host_fabric_name ( shost ) = node_name ;
}
2006-10-02 23:00:47 +04:00
static void
qla2x00_get_host_port_state ( struct Scsi_Host * shost )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = shost_priv ( shost ) ;
struct scsi_qla_host * base_vha = pci_get_drvdata ( vha - > hw - > pdev ) ;
2006-10-02 23:00:47 +04:00
2008-11-06 21:40:19 +03:00
if ( ! base_vha - > flags . online )
2006-10-02 23:00:47 +04:00
fc_host_port_state ( shost ) = FC_PORTSTATE_OFFLINE ;
2008-11-06 21:40:19 +03:00
else if ( atomic_read ( & base_vha - > loop_state ) = = LOOP_TIMEOUT )
2006-10-02 23:00:47 +04:00
fc_host_port_state ( shost ) = FC_PORTSTATE_UNKNOWN ;
else
fc_host_port_state ( shost ) = FC_PORTSTATE_ONLINE ;
}
2007-07-06 00:16:51 +04:00
static int
qla24xx_vport_create ( struct fc_vport * fc_vport , bool disable )
{
int ret = 0 ;
2008-12-10 03:45:39 +03:00
int cnt = 0 ;
uint8_t qos = QLA_DEFAULT_QUE_QOS ;
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * base_vha = shost_priv ( fc_vport - > shost ) ;
scsi_qla_host_t * vha = NULL ;
2008-12-10 03:45:39 +03:00
struct qla_hw_data * ha = base_vha - > hw ;
2007-07-06 00:16:51 +04:00
ret = qla24xx_vport_create_req_sanity_check ( fc_vport ) ;
if ( ret ) {
DEBUG15 ( printk ( " qla24xx_vport_create_req_sanity_check failed, "
" status %x \n " , ret ) ) ;
return ( ret ) ;
}
vha = qla24xx_create_vhost ( fc_vport ) ;
if ( vha = = NULL ) {
DEBUG15 ( printk ( " qla24xx_create_vhost failed, vha = %p \n " ,
vha ) ) ;
return FC_VPORT_FAILED ;
}
if ( disable ) {
atomic_set ( & vha - > vp_state , VP_OFFLINE ) ;
fc_vport_set_state ( fc_vport , FC_VPORT_DISABLED ) ;
} else
atomic_set ( & vha - > vp_state , VP_FAILED ) ;
/* ready to create vport */
2008-11-06 21:40:19 +03:00
qla_printk ( KERN_INFO , vha - > hw , " VP entry id %d assigned. \n " ,
vha - > vp_idx ) ;
2007-07-06 00:16:51 +04:00
/* initialized vport states */
atomic_set ( & vha - > loop_state , LOOP_DOWN ) ;
vha - > vp_err_state = VP_ERR_PORTDWN ;
vha - > vp_prev_err_state = VP_ERR_UNKWN ;
/* Check if physical ha port is Up */
2008-11-06 21:40:19 +03:00
if ( atomic_read ( & base_vha - > loop_state ) = = LOOP_DOWN | |
atomic_read ( & base_vha - > loop_state ) = = LOOP_DEAD ) {
2007-07-06 00:16:51 +04:00
/* Don't retry or attempt login of this virtual port */
DEBUG15 ( printk ( " scsi(%ld): pport loop_state is not UP. \n " ,
2008-11-06 21:40:19 +03:00
base_vha - > host_no ) ) ;
2007-07-06 00:16:51 +04:00
atomic_set ( & vha - > loop_state , LOOP_DEAD ) ;
if ( ! disable )
fc_vport_set_state ( fc_vport , FC_VPORT_LINKDOWN ) ;
}
if ( scsi_add_host ( vha - > host , & fc_vport - > dev ) ) {
DEBUG15 ( printk ( " scsi(%ld): scsi_add_host failure for VP[%d]. \n " ,
vha - > host_no , vha - > vp_idx ) ) ;
goto vport_create_failed_2 ;
}
/* initialize attributes */
fc_host_node_name ( vha - > host ) = wwn_to_u64 ( vha - > node_name ) ;
fc_host_port_name ( vha - > host ) = wwn_to_u64 ( vha - > port_name ) ;
fc_host_supported_classes ( vha - > host ) =
2008-11-06 21:40:19 +03:00
fc_host_supported_classes ( base_vha - > host ) ;
2007-07-06 00:16:51 +04:00
fc_host_supported_speeds ( vha - > host ) =
2008-11-06 21:40:19 +03:00
fc_host_supported_speeds ( base_vha - > host ) ;
2007-07-06 00:16:51 +04:00
qla24xx_vport_disable ( fc_vport , disable ) ;
2008-12-10 03:45:39 +03:00
/* Create a queue pair for the vport */
if ( ha - > mqenable ) {
if ( ha - > npiv_info ) {
for ( ; cnt < ha - > nvram_npiv_size ; cnt + + ) {
if ( ha - > npiv_info [ cnt ] . port_name = =
vha - > port_name & &
ha - > npiv_info [ cnt ] . node_name = =
vha - > node_name ) {
qos = ha - > npiv_info [ cnt ] . q_qos ;
break ;
}
}
}
qla25xx_create_queues ( vha , qos ) ;
}
2007-07-06 00:16:51 +04:00
return 0 ;
vport_create_failed_2 :
qla24xx_disable_vp ( vha ) ;
qla24xx_deallocate_vp_id ( vha ) ;
scsi_host_put ( vha - > host ) ;
return FC_VPORT_FAILED ;
}
2008-01-17 20:02:15 +03:00
static int
2007-07-06 00:16:51 +04:00
qla24xx_vport_delete ( struct fc_vport * fc_vport )
{
scsi_qla_host_t * vha = fc_vport - > dd_data ;
2008-11-06 21:40:19 +03:00
fc_port_t * fcport , * tfcport ;
2008-12-10 03:45:39 +03:00
struct qla_hw_data * ha = vha - > hw ;
uint16_t id = vha - > vp_idx ;
2008-07-24 19:31:49 +04:00
while ( test_bit ( LOOP_RESYNC_ACTIVE , & vha - > dpc_flags ) | |
2008-11-06 21:40:19 +03:00
test_bit ( FCPORT_UPDATE_NEEDED , & vha - > dpc_flags ) )
2008-07-24 19:31:49 +04:00
msleep ( 1000 ) ;
2007-07-06 00:16:51 +04:00
qla24xx_disable_vp ( vha ) ;
2008-11-06 21:40:19 +03:00
fc_remove_host ( vha - > host ) ;
scsi_remove_host ( vha - > host ) ;
list_for_each_entry_safe ( fcport , tfcport , & vha - > vp_fcports , list ) {
list_del ( & fcport - > list ) ;
kfree ( fcport ) ;
fcport = NULL ;
}
qla24xx_deallocate_vp_id ( vha ) ;
2007-07-06 00:16:51 +04:00
if ( vha - > timer_active ) {
qla2x00_vp_stop_timer ( vha ) ;
DEBUG15 ( printk ( " scsi(%ld): timer for the vport[%d] = %p "
" has stopped \n " ,
vha - > host_no , vha - > vp_idx , vha ) ) ;
}
2009-02-09 07:50:13 +03:00
if ( ha - > mqenable ) {
if ( qla25xx_delete_queues ( vha , 0 ) ! = QLA_SUCCESS )
qla_printk ( KERN_WARNING , ha ,
" Queue delete failed. \n " ) ;
}
2007-07-06 00:16:51 +04:00
scsi_host_put ( vha - > host ) ;
2008-12-10 03:45:39 +03:00
qla_printk ( KERN_INFO , ha , " vport %d deleted \n " , id ) ;
2007-07-06 00:16:51 +04:00
return 0 ;
}
2008-01-17 20:02:15 +03:00
static int
2007-07-06 00:16:51 +04:00
qla24xx_vport_disable ( struct fc_vport * fc_vport , bool disable )
{
scsi_qla_host_t * vha = fc_vport - > dd_data ;
if ( disable )
qla24xx_disable_vp ( vha ) ;
else
qla24xx_enable_vp ( vha ) ;
return 0 ;
}
2005-04-22 00:13:36 +04:00
struct fc_function_template qla2xxx_transport_functions = {
2005-04-18 00:04:54 +04:00
. show_host_node_name = 1 ,
. show_host_port_name = 1 ,
2005-08-27 06:08:10 +04:00
. show_host_supported_classes = 1 ,
2008-04-04 00:13:14 +04:00
. show_host_supported_speeds = 1 ,
2005-08-27 06:08:10 +04:00
2005-04-18 00:04:54 +04:00
. get_host_port_id = qla2x00_get_host_port_id ,
. show_host_port_id = 1 ,
2006-02-01 03:04:51 +03:00
. get_host_speed = qla2x00_get_host_speed ,
. show_host_speed = 1 ,
2006-02-01 03:04:56 +03:00
. get_host_port_type = qla2x00_get_host_port_type ,
. show_host_port_type = 1 ,
2006-10-02 23:00:44 +04:00
. get_host_symbolic_name = qla2x00_get_host_symbolic_name ,
. show_host_symbolic_name = 1 ,
2006-10-02 23:00:45 +04:00
. set_host_system_hostname = qla2x00_set_host_system_hostname ,
. show_host_system_hostname = 1 ,
2006-10-02 23:00:46 +04:00
. get_host_fabric_name = qla2x00_get_host_fabric_name ,
. show_host_fabric_name = 1 ,
2006-10-02 23:00:47 +04:00
. get_host_port_state = qla2x00_get_host_port_state ,
. show_host_port_state = 1 ,
2005-04-18 00:04:54 +04:00
2005-04-18 00:06:53 +04:00
. dd_fcrport_size = sizeof ( struct fc_port * ) ,
2005-08-27 06:08:10 +04:00
. show_rport_supported_classes = 1 ,
2005-04-18 00:04:54 +04:00
. get_starget_node_name = qla2x00_get_starget_node_name ,
. show_starget_node_name = 1 ,
. get_starget_port_name = qla2x00_get_starget_port_name ,
. show_starget_port_name = 1 ,
. get_starget_port_id = qla2x00_get_starget_port_id ,
. show_starget_port_id = 1 ,
. set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo ,
. show_rport_dev_loss_tmo = 1 ,
2005-10-28 03:03:37 +04:00
. issue_fc_host_lip = qla2x00_issue_lip ,
2008-07-11 03:55:47 +04:00
. dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk ,
. terminate_rport_io = qla2x00_terminate_rport_io ,
2006-02-01 03:05:02 +03:00
. get_fc_host_stats = qla2x00_get_fc_host_stats ,
2007-07-06 00:16:51 +04:00
. vport_create = qla24xx_vport_create ,
. vport_disable = qla24xx_vport_disable ,
. vport_delete = qla24xx_vport_delete ,
} ;
struct fc_function_template qla2xxx_transport_vport_functions = {
. show_host_node_name = 1 ,
. show_host_port_name = 1 ,
. show_host_supported_classes = 1 ,
. get_host_port_id = qla2x00_get_host_port_id ,
. show_host_port_id = 1 ,
. get_host_speed = qla2x00_get_host_speed ,
. show_host_speed = 1 ,
. get_host_port_type = qla2x00_get_host_port_type ,
. show_host_port_type = 1 ,
. get_host_symbolic_name = qla2x00_get_host_symbolic_name ,
. show_host_symbolic_name = 1 ,
. set_host_system_hostname = qla2x00_set_host_system_hostname ,
. show_host_system_hostname = 1 ,
. get_host_fabric_name = qla2x00_get_host_fabric_name ,
. show_host_fabric_name = 1 ,
. get_host_port_state = qla2x00_get_host_port_state ,
. show_host_port_state = 1 ,
. dd_fcrport_size = sizeof ( struct fc_port * ) ,
. show_rport_supported_classes = 1 ,
. get_starget_node_name = qla2x00_get_starget_node_name ,
. show_starget_node_name = 1 ,
. get_starget_port_name = qla2x00_get_starget_port_name ,
. show_starget_port_name = 1 ,
. get_starget_port_id = qla2x00_get_starget_port_id ,
. show_starget_port_id = 1 ,
. set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo ,
. show_rport_dev_loss_tmo = 1 ,
. issue_fc_host_lip = qla2x00_issue_lip ,
2008-07-11 03:55:47 +04:00
. dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk ,
. terminate_rport_io = qla2x00_terminate_rport_io ,
2007-07-06 00:16:51 +04:00
. get_fc_host_stats = qla2x00_get_fc_host_stats ,
2005-04-18 00:04:54 +04:00
} ;
void
2008-11-06 21:40:19 +03:00
qla2x00_init_host_attr ( scsi_qla_host_t * vha )
2005-04-18 00:04:54 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2008-04-04 00:13:14 +04:00
u32 speed = FC_PORTSPEED_UNKNOWN ;
2008-11-06 21:40:19 +03:00
fc_host_node_name ( vha - > host ) = wwn_to_u64 ( vha - > node_name ) ;
fc_host_port_name ( vha - > host ) = wwn_to_u64 ( vha - > port_name ) ;
fc_host_supported_classes ( vha - > host ) = FC_COS_CLASS3 ;
fc_host_max_npiv_vports ( vha - > host ) = ha - > max_npiv_vports ;
fc_host_npiv_vports_inuse ( vha - > host ) = ha - > cur_vport_count ;
2008-04-04 00:13:14 +04:00
2009-01-05 22:18:11 +03:00
if ( IS_QLA81XX ( ha ) )
speed = FC_PORTSPEED_10GBIT ;
else if ( IS_QLA25XX ( ha ) )
2008-04-04 00:13:14 +04:00
speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT ;
2008-04-04 00:13:26 +04:00
else if ( IS_QLA24XX_TYPE ( ha ) )
2008-04-04 00:13:14 +04:00
speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
FC_PORTSPEED_1GBIT ;
else if ( IS_QLA23XX ( ha ) )
speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT ;
else
speed = FC_PORTSPEED_1GBIT ;
2008-11-06 21:40:19 +03:00
fc_host_supported_speeds ( vha - > host ) = speed ;
2005-04-18 00:04:54 +04:00
}