2006-09-19 21:28:00 +04:00
/*
* QLogic iSCSI HBA Driver
2010-12-03 09:12:51 +03:00
* Copyright ( c ) 2003 - 2010 QLogic Corporation
2006-09-19 21:28:00 +04:00
*
* See LICENSE . qla4xxx for copyright and licensing details .
*/
# include "ql4_def.h"
2007-05-24 05:03:27 +04:00
# include "ql4_glbl.h"
# include "ql4_dbg.h"
# include "ql4_inline.h"
2006-09-19 21:28:00 +04:00
/**
* qla4xxx_mailbox_command - issues mailbox commands
* @ ha : Pointer to host adapter structure .
* @ inCount : number of mailbox registers to load .
* @ outCount : number of mailbox registers to return .
* @ mbx_cmd : data pointer for mailbox in registers .
* @ mbx_sts : data pointer for mailbox out registers .
*
2011-05-10 12:16:21 +04:00
* This routine issue mailbox commands and waits for completion .
2006-09-19 21:28:00 +04:00
* If outCount is 0 , this routine completes successfully WITHOUT waiting
* for the mailbox command to complete .
* */
2010-07-28 14:23:44 +04:00
int qla4xxx_mailbox_command ( struct scsi_qla_host * ha , uint8_t inCount ,
uint8_t outCount , uint32_t * mbx_cmd ,
uint32_t * mbx_sts )
2006-09-19 21:28:00 +04:00
{
int status = QLA_ERROR ;
uint8_t i ;
u_long wait_count ;
uint32_t intr_status ;
unsigned long flags = 0 ;
2011-03-21 13:34:25 +03:00
uint32_t dev_state ;
2006-09-19 21:28:00 +04:00
/* Make sure that pointers are valid */
if ( ! mbx_cmd | | ! mbx_sts ) {
DEBUG2 ( printk ( " scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
" pointer \n " , ha - > host_no , __func__ ) ) ;
2007-01-22 23:26:11 +03:00
return status ;
}
2010-07-30 12:58:07 +04:00
2011-03-21 13:34:25 +03:00
if ( is_qla8022 ( ha ) ) {
if ( test_bit ( AF_FW_RECOVERY , & ha - > flags ) ) {
DEBUG2 ( ql4_printk ( KERN_WARNING , ha , " scsi%ld: %s: "
" prematurely completing mbx cmd as firmware "
" recovery detected \n " , ha - > host_no , __func__ ) ) ;
return status ;
}
/* Do not send any mbx cmd if h/w is in failed state*/
qla4_8xxx_idc_lock ( ha ) ;
dev_state = qla4_8xxx_rd_32 ( ha , QLA82XX_CRB_DEV_STATE ) ;
qla4_8xxx_idc_unlock ( ha ) ;
if ( dev_state = = QLA82XX_DEV_FAILED ) {
ql4_printk ( KERN_WARNING , ha , " scsi%ld: %s: H/W is in "
" failed state, do not send any mailbox commands \n " ,
ha - > host_no , __func__ ) ;
return status ;
}
2010-07-30 12:58:07 +04:00
}
2010-07-30 13:08:47 +04:00
if ( ( is_aer_supported ( ha ) ) & &
( test_bit ( AF_PCI_CHANNEL_IO_PERM_FAILURE , & ha - > flags ) ) ) {
DEBUG2 ( printk ( KERN_WARNING " scsi%ld: %s: Perm failure on EEH, "
" timeout MBX Exiting. \n " , ha - > host_no , __func__ ) ) ;
return status ;
}
2007-01-22 23:26:11 +03:00
/* Mailbox code active */
wait_count = MBOX_TOV * 100 ;
while ( wait_count - - ) {
mutex_lock ( & ha - > mbox_sem ) ;
if ( ! test_bit ( AF_MBOX_COMMAND , & ha - > flags ) ) {
set_bit ( AF_MBOX_COMMAND , & ha - > flags ) ;
mutex_unlock ( & ha - > mbox_sem ) ;
break ;
}
mutex_unlock ( & ha - > mbox_sem ) ;
if ( ! wait_count ) {
DEBUG2 ( printk ( " scsi%ld: %s: mbox_sem failed \n " ,
ha - > host_no , __func__ ) ) ;
return status ;
}
msleep ( 10 ) ;
2006-09-19 21:28:00 +04:00
}
spin_lock_irqsave ( & ha - > hardware_lock , flags ) ;
2010-07-28 14:23:44 +04:00
2006-09-19 21:28:00 +04:00
ha - > mbox_status_count = outCount ;
for ( i = 0 ; i < outCount ; i + + )
ha - > mbox_status [ i ] = 0 ;
2010-07-28 14:23:44 +04:00
if ( is_qla8022 ( ha ) ) {
/* Load all mailbox registers, except mailbox 0. */
DEBUG5 (
printk ( " scsi%ld: %s: Cmd " , ha - > host_no , __func__ ) ;
for ( i = 0 ; i < inCount ; i + + )
printk ( " mb%d=%04x " , i , mbx_cmd [ i ] ) ;
printk ( " \n " ) ) ;
for ( i = 1 ; i < inCount ; i + + )
writel ( mbx_cmd [ i ] , & ha - > qla4_8xxx_reg - > mailbox_in [ i ] ) ;
writel ( mbx_cmd [ 0 ] , & ha - > qla4_8xxx_reg - > mailbox_in [ 0 ] ) ;
readl ( & ha - > qla4_8xxx_reg - > mailbox_in [ 0 ] ) ;
writel ( HINT_MBX_INT_PENDING , & ha - > qla4_8xxx_reg - > hint ) ;
} else {
/* Load all mailbox registers, except mailbox 0. */
for ( i = 1 ; i < inCount ; i + + )
writel ( mbx_cmd [ i ] , & ha - > reg - > mailbox [ i ] ) ;
/* Wakeup firmware */
writel ( mbx_cmd [ 0 ] , & ha - > reg - > mailbox [ 0 ] ) ;
readl ( & ha - > reg - > mailbox [ 0 ] ) ;
writel ( set_rmask ( CSR_INTR_RISC ) , & ha - > reg - > ctrl_status ) ;
readl ( & ha - > reg - > ctrl_status ) ;
}
2006-09-19 21:28:00 +04:00
spin_unlock_irqrestore ( & ha - > hardware_lock , flags ) ;
/* Wait for completion */
/*
* If we don ' t want status , don ' t wait for the mailbox command to
* complete . For example , MBOX_CMD_RESET_FW doesn ' t return status ,
* you must poll the inbound Interrupt Mask for completion .
*/
if ( outCount = = 0 ) {
status = QLA_SUCCESS ;
goto mbox_exit ;
}
2010-07-28 14:23:44 +04:00
/*
* Wait for completion : Poll or completion queue
*/
if ( test_bit ( AF_IRQ_ATTACHED , & ha - > flags ) & &
test_bit ( AF_INTERRUPTS_ON , & ha - > flags ) & &
test_bit ( AF_ONLINE , & ha - > flags ) & &
2011-03-21 13:34:29 +03:00
! test_bit ( AF_HA_REMOVAL , & ha - > flags ) ) {
2010-07-28 14:23:44 +04:00
/* Do not poll for completion. Use completion queue */
set_bit ( AF_MBOX_COMMAND_NOPOLL , & ha - > flags ) ;
wait_for_completion_timeout ( & ha - > mbx_intr_comp , MBOX_TOV * HZ ) ;
clear_bit ( AF_MBOX_COMMAND_NOPOLL , & ha - > flags ) ;
} else {
/* Poll for command to complete */
wait_count = jiffies + MBOX_TOV * HZ ;
while ( test_bit ( AF_MBOX_COMMAND_DONE , & ha - > flags ) = = 0 ) {
if ( time_after_eq ( jiffies , wait_count ) )
break ;
2010-07-30 13:08:47 +04:00
2006-09-19 21:28:00 +04:00
/*
* Service the interrupt .
* The ISR will save the mailbox status registers
* to a temporary storage location in the adapter
* structure .
*/
2010-07-28 14:23:44 +04:00
spin_lock_irqsave ( & ha - > hardware_lock , flags ) ;
if ( is_qla8022 ( ha ) ) {
intr_status =
readl ( & ha - > qla4_8xxx_reg - > host_int ) ;
if ( intr_status & ISRX_82XX_RISC_INT ) {
ha - > mbox_status_count = outCount ;
intr_status =
readl ( & ha - > qla4_8xxx_reg - > host_status ) ;
ha - > isp_ops - > interrupt_service_routine (
ha , intr_status ) ;
if ( test_bit ( AF_INTERRUPTS_ON ,
& ha - > flags ) & &
test_bit ( AF_INTx_ENABLED ,
& ha - > flags ) )
qla4_8xxx_wr_32 ( ha ,
ha - > nx_legacy_intr . tgt_mask_reg ,
0xfbff ) ;
}
} else {
intr_status = readl ( & ha - > reg - > ctrl_status ) ;
if ( intr_status & INTR_PENDING ) {
/*
* Service the interrupt .
* The ISR will save the mailbox status
* registers to a temporary storage
* location in the adapter structure .
*/
ha - > mbox_status_count = outCount ;
ha - > isp_ops - > interrupt_service_routine (
ha , intr_status ) ;
}
}
spin_unlock_irqrestore ( & ha - > hardware_lock , flags ) ;
msleep ( 10 ) ;
2006-09-19 21:28:00 +04:00
}
}
/* Check for mailbox timeout. */
if ( ! test_bit ( AF_MBOX_COMMAND_DONE , & ha - > flags ) ) {
2010-07-30 12:58:07 +04:00
if ( is_qla8022 ( ha ) & &
test_bit ( AF_FW_RECOVERY , & ha - > flags ) ) {
DEBUG2 ( ql4_printk ( KERN_INFO , ha ,
" scsi%ld: %s: prematurely completing mbx cmd as "
" firmware recovery detected \n " ,
ha - > host_no , __func__ ) ) ;
goto mbox_exit ;
}
2006-09-19 21:28:00 +04:00
DEBUG2 ( printk ( " scsi%ld: Mailbox Cmd 0x%08X timed out ..., "
" Scheduling Adapter Reset \n " , ha - > host_no ,
mbx_cmd [ 0 ] ) ) ;
ha - > mailbox_timeout_count + + ;
mbx_sts [ 0 ] = ( - 1 ) ;
set_bit ( DPC_RESET_HA , & ha - > dpc_flags ) ;
goto mbox_exit ;
}
/*
* Copy the mailbox out registers to the caller ' s mailbox in / out
* structure .
*/
spin_lock_irqsave ( & ha - > hardware_lock , flags ) ;
for ( i = 0 ; i < outCount ; i + + )
mbx_sts [ i ] = ha - > mbox_status [ i ] ;
/* Set return status and error flags (if applicable). */
switch ( ha - > mbox_status [ 0 ] ) {
case MBOX_STS_COMMAND_COMPLETE :
status = QLA_SUCCESS ;
break ;
case MBOX_STS_INTERMEDIATE_COMPLETION :
status = QLA_SUCCESS ;
break ;
case MBOX_STS_BUSY :
DEBUG2 ( printk ( " scsi%ld: %s: Cmd = %08X, ISP BUSY \n " ,
ha - > host_no , __func__ , mbx_cmd [ 0 ] ) ) ;
ha - > mailbox_timeout_count + + ;
break ;
default :
DEBUG2 ( printk ( " scsi%ld: %s: **** FAILED, cmd = %08X, "
" sts = %08X **** \n " , ha - > host_no , __func__ ,
mbx_cmd [ 0 ] , mbx_sts [ 0 ] ) ) ;
break ;
}
spin_unlock_irqrestore ( & ha - > hardware_lock , flags ) ;
mbox_exit :
2007-01-22 23:26:11 +03:00
mutex_lock ( & ha - > mbox_sem ) ;
2006-09-19 21:28:00 +04:00
clear_bit ( AF_MBOX_COMMAND , & ha - > flags ) ;
mutex_unlock ( & ha - > mbox_sem ) ;
2007-01-22 23:26:11 +03:00
clear_bit ( AF_MBOX_COMMAND_DONE , & ha - > flags ) ;
2006-09-19 21:28:00 +04:00
return status ;
}
2010-07-30 12:58:07 +04:00
void qla4xxx_mailbox_premature_completion ( struct scsi_qla_host * ha )
{
set_bit ( AF_FW_RECOVERY , & ha - > flags ) ;
ql4_printk ( KERN_INFO , ha , " scsi%ld: %s: set FW RECOVERY! \n " ,
ha - > host_no , __func__ ) ;
if ( test_bit ( AF_MBOX_COMMAND , & ha - > flags ) ) {
if ( test_bit ( AF_MBOX_COMMAND_NOPOLL , & ha - > flags ) ) {
complete ( & ha - > mbx_intr_comp ) ;
ql4_printk ( KERN_INFO , ha , " scsi%ld: %s: Due to fw "
" recovery, doing premature completion of "
" mbx cmd \n " , ha - > host_no , __func__ ) ;
} else {
set_bit ( AF_MBOX_COMMAND_DONE , & ha - > flags ) ;
ql4_printk ( KERN_INFO , ha , " scsi%ld: %s: Due to fw "
" recovery, doing premature completion of "
" polling mbx cmd \n " , ha - > host_no , __func__ ) ;
}
}
}
2006-09-19 21:28:00 +04:00
2010-07-28 14:23:44 +04:00
static uint8_t
2010-04-28 10:07:07 +04:00
qla4xxx_set_ifcb ( struct scsi_qla_host * ha , uint32_t * mbox_cmd ,
uint32_t * mbox_sts , dma_addr_t init_fw_cb_dma )
{
memset ( mbox_cmd , 0 , sizeof ( mbox_cmd [ 0 ] ) * MBOX_REG_COUNT ) ;
memset ( mbox_sts , 0 , sizeof ( mbox_sts [ 0 ] ) * MBOX_REG_COUNT ) ;
2010-10-07 09:50:29 +04:00
if ( is_qla8022 ( ha ) )
qla4_8xxx_wr_32 ( ha , ha - > nx_db_wr_ptr , 0 ) ;
2010-04-28 10:07:07 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_INITIALIZE_FIRMWARE ;
mbox_cmd [ 1 ] = 0 ;
mbox_cmd [ 2 ] = LSDW ( init_fw_cb_dma ) ;
mbox_cmd [ 3 ] = MSDW ( init_fw_cb_dma ) ;
mbox_cmd [ 4 ] = sizeof ( struct addr_ctrl_blk ) ;
mbox_cmd [ 5 ] = ( IFCB_VER_MAX < < 8 ) | IFCB_VER_MIN ;
if ( qla4xxx_mailbox_command ( ha , 6 , 6 , mbox_cmd , mbox_sts ) ! =
QLA_SUCCESS ) {
DEBUG2 ( printk ( KERN_WARNING " scsi%ld: %s: "
" MBOX_CMD_INITIALIZE_FIRMWARE "
" failed w/ status %04X \n " ,
ha - > host_no , __func__ , mbox_sts [ 0 ] ) ) ;
return QLA_ERROR ;
}
return QLA_SUCCESS ;
}
2011-07-25 22:48:38 +04:00
uint8_t
2010-04-28 10:07:07 +04:00
qla4xxx_get_ifcb ( struct scsi_qla_host * ha , uint32_t * mbox_cmd ,
uint32_t * mbox_sts , dma_addr_t init_fw_cb_dma )
{
memset ( mbox_cmd , 0 , sizeof ( mbox_cmd [ 0 ] ) * MBOX_REG_COUNT ) ;
memset ( mbox_sts , 0 , sizeof ( mbox_sts [ 0 ] ) * MBOX_REG_COUNT ) ;
mbox_cmd [ 0 ] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK ;
mbox_cmd [ 2 ] = LSDW ( init_fw_cb_dma ) ;
mbox_cmd [ 3 ] = MSDW ( init_fw_cb_dma ) ;
mbox_cmd [ 4 ] = sizeof ( struct addr_ctrl_blk ) ;
if ( qla4xxx_mailbox_command ( ha , 5 , 5 , mbox_cmd , mbox_sts ) ! =
QLA_SUCCESS ) {
DEBUG2 ( printk ( KERN_WARNING " scsi%ld: %s: "
" MBOX_CMD_GET_INIT_FW_CTRL_BLOCK "
" failed w/ status %04X \n " ,
ha - > host_no , __func__ , mbox_sts [ 0 ] ) ) ;
return QLA_ERROR ;
}
return QLA_SUCCESS ;
}
2010-07-28 14:23:44 +04:00
static void
2010-04-28 10:07:07 +04:00
qla4xxx_update_local_ip ( struct scsi_qla_host * ha ,
2011-07-25 22:48:39 +04:00
struct addr_ctrl_blk * init_fw_cb )
2010-04-28 10:07:07 +04:00
{
2011-07-25 22:48:39 +04:00
ha - > ip_config . tcp_options = le16_to_cpu ( init_fw_cb - > ipv4_tcp_opts ) ;
ha - > ip_config . ipv4_options = le16_to_cpu ( init_fw_cb - > ipv4_ip_opts ) ;
ha - > ip_config . ipv4_addr_state =
le16_to_cpu ( init_fw_cb - > ipv4_addr_state ) ;
2011-08-01 14:26:13 +04:00
ha - > ip_config . eth_mtu_size =
le16_to_cpu ( init_fw_cb - > eth_mtu_size ) ;
2011-08-01 14:26:19 +04:00
ha - > ip_config . ipv4_port = le16_to_cpu ( init_fw_cb - > ipv4_port ) ;
2011-07-25 22:48:39 +04:00
if ( ha - > acb_version = = ACB_SUPPORTED ) {
ha - > ip_config . ipv6_options = le16_to_cpu ( init_fw_cb - > ipv6_opts ) ;
ha - > ip_config . ipv6_addl_options =
le16_to_cpu ( init_fw_cb - > ipv6_addtl_opts ) ;
}
2010-04-28 10:07:07 +04:00
/* Save IPv4 Address Info */
2011-07-25 22:48:39 +04:00
memcpy ( ha - > ip_config . ip_address , init_fw_cb - > ipv4_addr ,
min ( sizeof ( ha - > ip_config . ip_address ) ,
sizeof ( init_fw_cb - > ipv4_addr ) ) ) ;
memcpy ( ha - > ip_config . subnet_mask , init_fw_cb - > ipv4_subnet ,
min ( sizeof ( ha - > ip_config . subnet_mask ) ,
sizeof ( init_fw_cb - > ipv4_subnet ) ) ) ;
memcpy ( ha - > ip_config . gateway , init_fw_cb - > ipv4_gw_addr ,
min ( sizeof ( ha - > ip_config . gateway ) ,
sizeof ( init_fw_cb - > ipv4_gw_addr ) ) ) ;
2010-04-28 10:07:07 +04:00
2011-07-25 22:48:49 +04:00
ha - > ip_config . ipv4_vlan_tag = be16_to_cpu ( init_fw_cb - > ipv4_vlan_tag ) ;
2010-04-28 10:07:07 +04:00
if ( is_ipv6_enabled ( ha ) ) {
/* Save IPv6 Address */
2011-07-25 22:48:39 +04:00
ha - > ip_config . ipv6_link_local_state =
le16_to_cpu ( init_fw_cb - > ipv6_lnk_lcl_addr_state ) ;
ha - > ip_config . ipv6_addr0_state =
le16_to_cpu ( init_fw_cb - > ipv6_addr0_state ) ;
ha - > ip_config . ipv6_addr1_state =
le16_to_cpu ( init_fw_cb - > ipv6_addr1_state ) ;
ha - > ip_config . ipv6_default_router_state =
le16_to_cpu ( init_fw_cb - > ipv6_dflt_rtr_state ) ;
ha - > ip_config . ipv6_link_local_addr . in6_u . u6_addr8 [ 0 ] = 0xFE ;
ha - > ip_config . ipv6_link_local_addr . in6_u . u6_addr8 [ 1 ] = 0x80 ;
memcpy ( & ha - > ip_config . ipv6_link_local_addr . in6_u . u6_addr8 [ 8 ] ,
init_fw_cb - > ipv6_if_id ,
min ( sizeof ( ha - > ip_config . ipv6_link_local_addr ) / 2 ,
sizeof ( init_fw_cb - > ipv6_if_id ) ) ) ;
memcpy ( & ha - > ip_config . ipv6_addr0 , init_fw_cb - > ipv6_addr0 ,
min ( sizeof ( ha - > ip_config . ipv6_addr0 ) ,
sizeof ( init_fw_cb - > ipv6_addr0 ) ) ) ;
memcpy ( & ha - > ip_config . ipv6_addr1 , init_fw_cb - > ipv6_addr1 ,
min ( sizeof ( ha - > ip_config . ipv6_addr1 ) ,
sizeof ( init_fw_cb - > ipv6_addr1 ) ) ) ;
memcpy ( & ha - > ip_config . ipv6_default_router_addr ,
init_fw_cb - > ipv6_dflt_rtr_addr ,
min ( sizeof ( ha - > ip_config . ipv6_default_router_addr ) ,
sizeof ( init_fw_cb - > ipv6_dflt_rtr_addr ) ) ) ;
2011-07-25 22:48:49 +04:00
ha - > ip_config . ipv6_vlan_tag =
be16_to_cpu ( init_fw_cb - > ipv6_vlan_tag ) ;
2011-08-01 14:26:19 +04:00
ha - > ip_config . ipv6_port = le16_to_cpu ( init_fw_cb - > ipv6_port ) ;
2010-04-28 10:07:07 +04:00
}
}
2011-07-25 22:48:38 +04:00
uint8_t
2010-04-28 10:07:07 +04:00
qla4xxx_update_local_ifcb ( struct scsi_qla_host * ha ,
uint32_t * mbox_cmd ,
uint32_t * mbox_sts ,
struct addr_ctrl_blk * init_fw_cb ,
dma_addr_t init_fw_cb_dma )
{
if ( qla4xxx_get_ifcb ( ha , mbox_cmd , mbox_sts , init_fw_cb_dma )
! = QLA_SUCCESS ) {
DEBUG2 ( printk ( KERN_WARNING
" scsi%ld: %s: Failed to get init_fw_ctrl_blk \n " ,
ha - > host_no , __func__ ) ) ;
return QLA_ERROR ;
}
DEBUG2 ( qla4xxx_dump_buffer ( init_fw_cb , sizeof ( struct addr_ctrl_blk ) ) ) ;
/* Save some info in adapter structure. */
ha - > acb_version = init_fw_cb - > acb_version ;
ha - > firmware_options = le16_to_cpu ( init_fw_cb - > fw_options ) ;
ha - > heartbeat_interval = init_fw_cb - > hb_interval ;
memcpy ( ha - > name_string , init_fw_cb - > iscsi_name ,
min ( sizeof ( ha - > name_string ) ,
sizeof ( init_fw_cb - > iscsi_name ) ) ) ;
/*memcpy(ha->alias, init_fw_cb->Alias,
min ( sizeof ( ha - > alias ) , sizeof ( init_fw_cb - > Alias ) ) ) ; */
qla4xxx_update_local_ip ( ha , init_fw_cb ) ;
return QLA_SUCCESS ;
}
2006-09-19 21:28:00 +04:00
/**
* qla4xxx_initialize_fw_cb - initializes firmware control block .
* @ ha : Pointer to host adapter structure .
* */
int qla4xxx_initialize_fw_cb ( struct scsi_qla_host * ha )
{
2010-04-28 10:07:07 +04:00
struct addr_ctrl_blk * init_fw_cb ;
2006-09-19 21:28:00 +04:00
dma_addr_t init_fw_cb_dma ;
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
int status = QLA_ERROR ;
init_fw_cb = dma_alloc_coherent ( & ha - > pdev - > dev ,
2010-04-28 10:07:07 +04:00
sizeof ( struct addr_ctrl_blk ) ,
2006-09-19 21:28:00 +04:00
& init_fw_cb_dma , GFP_KERNEL ) ;
if ( init_fw_cb = = NULL ) {
DEBUG2 ( printk ( " scsi%ld: %s: Unable to alloc init_cb \n " ,
ha - > host_no , __func__ ) ) ;
2010-07-10 13:19:38 +04:00
goto exit_init_fw_cb_no_free ;
2006-09-19 21:28:00 +04:00
}
2010-04-28 10:07:07 +04:00
memset ( init_fw_cb , 0 , sizeof ( struct addr_ctrl_blk ) ) ;
2006-09-19 21:28:00 +04:00
/* Get Initialize Firmware Control Block. */
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
2007-05-24 05:03:27 +04:00
2010-04-28 10:07:07 +04:00
if ( qla4xxx_get_ifcb ( ha , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] , init_fw_cb_dma ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS ) {
dma_free_coherent ( & ha - > pdev - > dev ,
2010-04-28 10:07:07 +04:00
sizeof ( struct addr_ctrl_blk ) ,
2006-09-19 21:28:00 +04:00
init_fw_cb , init_fw_cb_dma ) ;
2010-04-28 10:07:07 +04:00
goto exit_init_fw_cb ;
2006-09-19 21:28:00 +04:00
}
/* Initialize request and response queues. */
qla4xxx_init_rings ( ha ) ;
/* Fill in the request and response queue information. */
2010-04-28 10:07:07 +04:00
init_fw_cb - > rqq_consumer_idx = cpu_to_le16 ( ha - > request_out ) ;
init_fw_cb - > compq_producer_idx = cpu_to_le16 ( ha - > response_in ) ;
init_fw_cb - > rqq_len = __constant_cpu_to_le16 ( REQUEST_QUEUE_DEPTH ) ;
init_fw_cb - > compq_len = __constant_cpu_to_le16 ( RESPONSE_QUEUE_DEPTH ) ;
init_fw_cb - > rqq_addr_lo = cpu_to_le32 ( LSDW ( ha - > request_dma ) ) ;
init_fw_cb - > rqq_addr_hi = cpu_to_le32 ( MSDW ( ha - > request_dma ) ) ;
init_fw_cb - > compq_addr_lo = cpu_to_le32 ( LSDW ( ha - > response_dma ) ) ;
init_fw_cb - > compq_addr_hi = cpu_to_le32 ( MSDW ( ha - > response_dma ) ) ;
init_fw_cb - > shdwreg_addr_lo = cpu_to_le32 ( LSDW ( ha - > shadow_regs_dma ) ) ;
init_fw_cb - > shdwreg_addr_hi = cpu_to_le32 ( MSDW ( ha - > shadow_regs_dma ) ) ;
2006-09-19 21:28:00 +04:00
/* Set up required options. */
2010-04-28 10:07:07 +04:00
init_fw_cb - > fw_options | =
2006-09-19 21:28:00 +04:00
__constant_cpu_to_le16 ( FWOPT_SESSION_MODE |
FWOPT_INITIATOR_MODE ) ;
2010-10-07 09:50:29 +04:00
if ( is_qla8022 ( ha ) )
init_fw_cb - > fw_options | =
__constant_cpu_to_le16 ( FWOPT_ENABLE_CRBDB ) ;
2010-04-28 10:07:07 +04:00
init_fw_cb - > fw_options & = __constant_cpu_to_le16 ( ~ FWOPT_TARGET_MODE ) ;
2006-09-19 21:28:00 +04:00
2011-03-21 13:34:35 +03:00
init_fw_cb - > add_fw_options = 0 ;
init_fw_cb - > add_fw_options | =
2011-07-25 22:48:53 +04:00
__constant_cpu_to_le16 ( ADFWOPT_SERIALIZE_TASK_MGMT ) ;
init_fw_cb - > add_fw_options | =
__constant_cpu_to_le16 ( ADFWOPT_AUTOCONN_DISABLE ) ;
2011-03-21 13:34:35 +03:00
2010-04-28 10:07:07 +04:00
if ( qla4xxx_set_ifcb ( ha , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] , init_fw_cb_dma )
! = QLA_SUCCESS ) {
DEBUG2 ( printk ( KERN_WARNING
" scsi%ld: %s: Failed to set init_fw_ctrl_blk \n " ,
ha - > host_no , __func__ ) ) ;
goto exit_init_fw_cb ;
}
2007-05-24 05:03:27 +04:00
2010-04-28 10:07:07 +04:00
if ( qla4xxx_update_local_ifcb ( ha , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ,
init_fw_cb , init_fw_cb_dma ) ! = QLA_SUCCESS ) {
DEBUG2 ( printk ( " scsi%ld: %s: Failed to update local ifcb \n " ,
ha - > host_no , __func__ ) ) ;
goto exit_init_fw_cb ;
2006-09-19 21:28:00 +04:00
}
2010-04-28 10:07:07 +04:00
status = QLA_SUCCESS ;
exit_init_fw_cb :
dma_free_coherent ( & ha - > pdev - > dev , sizeof ( struct addr_ctrl_blk ) ,
init_fw_cb , init_fw_cb_dma ) ;
2010-07-10 13:19:38 +04:00
exit_init_fw_cb_no_free :
2006-09-19 21:28:00 +04:00
return status ;
}
/**
* qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP
* @ ha : Pointer to host adapter structure .
* */
int qla4xxx_get_dhcp_ip_address ( struct scsi_qla_host * ha )
{
2010-04-28 10:07:07 +04:00
struct addr_ctrl_blk * init_fw_cb ;
2006-09-19 21:28:00 +04:00
dma_addr_t init_fw_cb_dma ;
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
init_fw_cb = dma_alloc_coherent ( & ha - > pdev - > dev ,
2010-04-28 10:07:07 +04:00
sizeof ( struct addr_ctrl_blk ) ,
2006-09-19 21:28:00 +04:00
& init_fw_cb_dma , GFP_KERNEL ) ;
if ( init_fw_cb = = NULL ) {
printk ( " scsi%ld: %s: Unable to alloc init_cb \n " , ha - > host_no ,
__func__ ) ;
2010-07-10 13:19:38 +04:00
return QLA_ERROR ;
2006-09-19 21:28:00 +04:00
}
/* Get Initialize Firmware Control Block. */
2010-04-28 10:07:07 +04:00
memset ( init_fw_cb , 0 , sizeof ( struct addr_ctrl_blk ) ) ;
if ( qla4xxx_get_ifcb ( ha , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] , init_fw_cb_dma ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS ) {
DEBUG2 ( printk ( " scsi%ld: %s: Failed to get init_fw_ctrl_blk \n " ,
ha - > host_no , __func__ ) ) ;
dma_free_coherent ( & ha - > pdev - > dev ,
2010-04-28 10:07:07 +04:00
sizeof ( struct addr_ctrl_blk ) ,
2006-09-19 21:28:00 +04:00
init_fw_cb , init_fw_cb_dma ) ;
return QLA_ERROR ;
}
/* Save IP Address. */
2010-04-28 10:07:07 +04:00
qla4xxx_update_local_ip ( ha , init_fw_cb ) ;
dma_free_coherent ( & ha - > pdev - > dev , sizeof ( struct addr_ctrl_blk ) ,
init_fw_cb , init_fw_cb_dma ) ;
2006-09-19 21:28:00 +04:00
return QLA_SUCCESS ;
}
/**
* qla4xxx_get_firmware_state - gets firmware state of HBA
* @ ha : Pointer to host adapter structure .
* */
int qla4xxx_get_firmware_state ( struct scsi_qla_host * ha )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
/* Get firmware version */
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
2007-05-24 05:03:27 +04:00
2006-09-19 21:28:00 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_GET_FW_STATE ;
2007-05-24 05:03:27 +04:00
if ( qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 4 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS ) {
DEBUG2 ( printk ( " scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
" status %04X \n " , ha - > host_no , __func__ ,
mbox_sts [ 0 ] ) ) ;
return QLA_ERROR ;
}
ha - > firmware_state = mbox_sts [ 1 ] ;
ha - > board_id = mbox_sts [ 2 ] ;
ha - > addl_fw_state = mbox_sts [ 3 ] ;
DEBUG2 ( printk ( " scsi%ld: %s firmware_state=0x%x \n " ,
ha - > host_no , __func__ , ha - > firmware_state ) ; )
2010-07-28 14:23:44 +04:00
return QLA_SUCCESS ;
2006-09-19 21:28:00 +04:00
}
/**
* qla4xxx_get_firmware_status - retrieves firmware status
* @ ha : Pointer to host adapter structure .
* */
int qla4xxx_get_firmware_status ( struct scsi_qla_host * ha )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
/* Get firmware version */
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
2007-05-24 05:03:27 +04:00
2006-09-19 21:28:00 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_GET_FW_STATUS ;
2007-05-24 05:03:27 +04:00
if ( qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 3 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS ) {
DEBUG2 ( printk ( " scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
" status %04X \n " , ha - > host_no , __func__ ,
mbox_sts [ 0 ] ) ) ;
return QLA_ERROR ;
}
2010-07-28 14:23:44 +04:00
ql4_printk ( KERN_INFO , ha , " %ld firmare IOCBs available (%d). \n " ,
2010-10-07 09:47:48 +04:00
ha - > host_no , mbox_sts [ 2 ] ) ;
2010-07-28 14:23:44 +04:00
2006-09-19 21:28:00 +04:00
return QLA_SUCCESS ;
}
/**
* qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
* @ ha : Pointer to host adapter structure .
* @ fw_ddb_index : Firmware ' s device database index
* @ fw_ddb_entry : Pointer to firmware ' s device database entry structure
* @ num_valid_ddb_entries : Pointer to number of valid ddb entries
* @ next_ddb_index : Pointer to next valid device database index
* @ fw_ddb_device_state : Pointer to device state
* */
int qla4xxx_get_fwddb_entry ( struct scsi_qla_host * ha ,
uint16_t fw_ddb_index ,
struct dev_db_entry * fw_ddb_entry ,
dma_addr_t fw_ddb_entry_dma ,
uint32_t * num_valid_ddb_entries ,
uint32_t * next_ddb_index ,
uint32_t * fw_ddb_device_state ,
uint32_t * conn_err_detail ,
uint16_t * tcp_source_port_num ,
uint16_t * connection_id )
{
int status = QLA_ERROR ;
2010-04-28 10:07:07 +04:00
uint16_t options ;
2006-09-19 21:28:00 +04:00
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
/* Make sure the device index is valid */
if ( fw_ddb_index > = MAX_DDB_ENTRIES ) {
2010-07-28 14:23:44 +04:00
DEBUG2 ( printk ( " scsi%ld: %s: ddb [%d] out of range. \n " ,
2006-09-19 21:28:00 +04:00
ha - > host_no , __func__ , fw_ddb_index ) ) ;
goto exit_get_fwddb ;
}
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
2007-05-24 05:03:27 +04:00
2006-09-19 21:28:00 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_GET_DATABASE_ENTRY ;
mbox_cmd [ 1 ] = ( uint32_t ) fw_ddb_index ;
mbox_cmd [ 2 ] = LSDW ( fw_ddb_entry_dma ) ;
mbox_cmd [ 3 ] = MSDW ( fw_ddb_entry_dma ) ;
2007-05-24 05:03:27 +04:00
mbox_cmd [ 4 ] = sizeof ( struct dev_db_entry ) ;
if ( qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 7 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) = =
2006-09-19 21:28:00 +04:00
QLA_ERROR ) {
DEBUG2 ( printk ( " scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed "
" with status 0x%04X \n " , ha - > host_no , __func__ ,
mbox_sts [ 0 ] ) ) ;
goto exit_get_fwddb ;
}
if ( fw_ddb_index ! = mbox_sts [ 1 ] ) {
2010-07-28 14:23:44 +04:00
DEBUG2 ( printk ( " scsi%ld: %s: ddb mismatch [%d] != [%d]. \n " ,
2006-09-19 21:28:00 +04:00
ha - > host_no , __func__ , fw_ddb_index ,
mbox_sts [ 1 ] ) ) ;
goto exit_get_fwddb ;
}
if ( fw_ddb_entry ) {
2010-04-28 10:07:07 +04:00
options = le16_to_cpu ( fw_ddb_entry - > options ) ;
if ( options & DDB_OPT_IPV6_DEVICE ) {
2010-07-10 13:21:02 +04:00
ql4_printk ( KERN_INFO , ha , " %s: DDB[%d] MB0 %04x Tot %d "
2010-04-28 10:07:07 +04:00
" Next %d State %04x ConnErr %08x %pI6 "
" :%04d \" %s \" \n " , __func__ , fw_ddb_index ,
mbox_sts [ 0 ] , mbox_sts [ 2 ] , mbox_sts [ 3 ] ,
mbox_sts [ 4 ] , mbox_sts [ 5 ] ,
fw_ddb_entry - > ip_addr ,
le16_to_cpu ( fw_ddb_entry - > port ) ,
fw_ddb_entry - > iscsi_name ) ;
} else {
2010-07-10 13:21:02 +04:00
ql4_printk ( KERN_INFO , ha , " %s: DDB[%d] MB0 %04x Tot %d "
2010-04-28 10:07:07 +04:00
" Next %d State %04x ConnErr %08x %pI4 "
" :%04d \" %s \" \n " , __func__ , fw_ddb_index ,
mbox_sts [ 0 ] , mbox_sts [ 2 ] , mbox_sts [ 3 ] ,
mbox_sts [ 4 ] , mbox_sts [ 5 ] ,
fw_ddb_entry - > ip_addr ,
le16_to_cpu ( fw_ddb_entry - > port ) ,
fw_ddb_entry - > iscsi_name ) ;
}
2006-09-19 21:28:00 +04:00
}
if ( num_valid_ddb_entries )
* num_valid_ddb_entries = mbox_sts [ 2 ] ;
if ( next_ddb_index )
* next_ddb_index = mbox_sts [ 3 ] ;
if ( fw_ddb_device_state )
* fw_ddb_device_state = mbox_sts [ 4 ] ;
/*
* RA : This mailbox has been changed to pass connection error and
* details . Its true for ISP4010 as per Version E - Not sure when it
* was changed . Get the time2wait from the fw_dd_entry field :
* default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY
* struct .
*/
if ( conn_err_detail )
* conn_err_detail = mbox_sts [ 5 ] ;
if ( tcp_source_port_num )
2010-04-22 22:02:14 +04:00
* tcp_source_port_num = ( uint16_t ) ( mbox_sts [ 6 ] > > 16 ) ;
2006-09-19 21:28:00 +04:00
if ( connection_id )
* connection_id = ( uint16_t ) mbox_sts [ 6 ] & 0x00FF ;
status = QLA_SUCCESS ;
exit_get_fwddb :
return status ;
}
2011-07-25 22:48:53 +04:00
int qla4xxx_conn_open ( struct scsi_qla_host * ha , uint16_t fw_ddb_index )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
int status ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_CONN_OPEN ;
mbox_cmd [ 1 ] = fw_ddb_index ;
status = qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 2 , & mbox_cmd [ 0 ] ,
& mbox_sts [ 0 ] ) ;
DEBUG2 ( ql4_printk ( KERN_INFO , ha ,
" %s: status = %d mbx0 = 0x%x mbx1 = 0x%x \n " ,
__func__ , status , mbox_sts [ 0 ] , mbox_sts [ 1 ] ) ) ;
return status ;
}
2006-09-19 21:28:00 +04:00
/**
* qla4xxx_set_fwddb_entry - sets a ddb entry .
* @ ha : Pointer to host adapter structure .
* @ fw_ddb_index : Firmware ' s device database index
2011-07-25 22:48:53 +04:00
* @ fw_ddb_entry_dma : dma address of ddb entry
* @ mbx_sts : mailbox 0 to be returned or NULL
2006-09-19 21:28:00 +04:00
*
* This routine initializes or updates the adapter ' s device database
2011-07-25 22:48:53 +04:00
* entry for the specified device .
2006-09-19 21:28:00 +04:00
* */
int qla4xxx_set_ddb_entry ( struct scsi_qla_host * ha , uint16_t fw_ddb_index ,
2011-07-25 22:48:53 +04:00
dma_addr_t fw_ddb_entry_dma , uint32_t * mbx_sts )
2006-09-19 21:28:00 +04:00
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
2010-07-28 14:23:44 +04:00
int status ;
2006-09-19 21:28:00 +04:00
/* Do not wait for completion. The firmware will send us an
* ASTS_DATABASE_CHANGED ( 0x8014 ) to notify us of the login status .
*/
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_SET_DATABASE_ENTRY ;
mbox_cmd [ 1 ] = ( uint32_t ) fw_ddb_index ;
mbox_cmd [ 2 ] = LSDW ( fw_ddb_entry_dma ) ;
mbox_cmd [ 3 ] = MSDW ( fw_ddb_entry_dma ) ;
2007-05-24 05:03:27 +04:00
mbox_cmd [ 4 ] = sizeof ( struct dev_db_entry ) ;
2006-09-19 21:28:00 +04:00
2010-07-28 14:23:44 +04:00
status = qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 5 , & mbox_cmd [ 0 ] ,
2011-07-25 22:48:53 +04:00
& mbox_sts [ 0 ] ) ;
if ( mbx_sts )
* mbx_sts = mbox_sts [ 0 ] ;
2010-07-28 14:23:44 +04:00
DEBUG2 ( printk ( " scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x \n " ,
ha - > host_no , __func__ , status , mbox_sts [ 0 ] , mbox_sts [ 4 ] ) ; )
return status ;
2006-09-19 21:28:00 +04:00
}
2011-07-25 22:48:53 +04:00
int qla4xxx_session_logout_ddb ( struct scsi_qla_host * ha ,
struct ddb_entry * ddb_entry , int options )
{
int status ;
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT ;
mbox_cmd [ 1 ] = ddb_entry - > fw_ddb_index ;
mbox_cmd [ 3 ] = options ;
status = qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 2 , & mbox_cmd [ 0 ] ,
& mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_INFO , ha ,
" %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
" failed sts %04X %04X " , __func__ ,
mbox_sts [ 0 ] , mbox_sts [ 1 ] ) ) ;
}
return status ;
}
2006-09-19 21:28:00 +04:00
/**
* qla4xxx_get_crash_record - retrieves crash record .
* @ ha : Pointer to host adapter structure .
*
* This routine retrieves a crash record from the QLA4010 after an 8002 h aen .
* */
void qla4xxx_get_crash_record ( struct scsi_qla_host * ha )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
struct crash_record * crash_record = NULL ;
dma_addr_t crash_record_dma = 0 ;
uint32_t crash_record_size = 0 ;
2007-05-24 05:03:27 +04:00
2006-09-19 21:28:00 +04:00
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_cmd ) ) ;
/* Get size of crash record. */
mbox_cmd [ 0 ] = MBOX_CMD_GET_CRASH_RECORD ;
2007-05-24 05:03:27 +04:00
if ( qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 5 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS ) {
DEBUG2 ( printk ( " scsi%ld: %s: ERROR: Unable to retrieve size! \n " ,
ha - > host_no , __func__ ) ) ;
goto exit_get_crash_record ;
}
crash_record_size = mbox_sts [ 4 ] ;
if ( crash_record_size = = 0 ) {
DEBUG2 ( printk ( " scsi%ld: %s: ERROR: Crash record size is 0! \n " ,
ha - > host_no , __func__ ) ) ;
goto exit_get_crash_record ;
}
/* Alloc Memory for Crash Record. */
crash_record = dma_alloc_coherent ( & ha - > pdev - > dev , crash_record_size ,
& crash_record_dma , GFP_KERNEL ) ;
if ( crash_record = = NULL )
goto exit_get_crash_record ;
/* Get Crash Record. */
2007-05-24 05:03:27 +04:00
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_cmd ) ) ;
2006-09-19 21:28:00 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_GET_CRASH_RECORD ;
mbox_cmd [ 2 ] = LSDW ( crash_record_dma ) ;
mbox_cmd [ 3 ] = MSDW ( crash_record_dma ) ;
mbox_cmd [ 4 ] = crash_record_size ;
2007-05-24 05:03:27 +04:00
if ( qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 5 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS )
goto exit_get_crash_record ;
/* Dump Crash Record. */
exit_get_crash_record :
if ( crash_record )
dma_free_coherent ( & ha - > pdev - > dev , crash_record_size ,
crash_record , crash_record_dma ) ;
}
/**
* qla4xxx_get_conn_event_log - retrieves connection event log
* @ ha : Pointer to host adapter structure .
* */
void qla4xxx_get_conn_event_log ( struct scsi_qla_host * ha )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
struct conn_event_log_entry * event_log = NULL ;
dma_addr_t event_log_dma = 0 ;
uint32_t event_log_size = 0 ;
uint32_t num_valid_entries ;
uint32_t oldest_entry = 0 ;
uint32_t max_event_log_entries ;
uint8_t i ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_cmd ) ) ;
/* Get size of crash record. */
mbox_cmd [ 0 ] = MBOX_CMD_GET_CONN_EVENT_LOG ;
2007-05-24 05:03:27 +04:00
if ( qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 5 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS )
goto exit_get_event_log ;
event_log_size = mbox_sts [ 4 ] ;
if ( event_log_size = = 0 )
goto exit_get_event_log ;
/* Alloc Memory for Crash Record. */
event_log = dma_alloc_coherent ( & ha - > pdev - > dev , event_log_size ,
& event_log_dma , GFP_KERNEL ) ;
if ( event_log = = NULL )
goto exit_get_event_log ;
/* Get Crash Record. */
2007-05-24 05:03:27 +04:00
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_cmd ) ) ;
2006-09-19 21:28:00 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_GET_CONN_EVENT_LOG ;
mbox_cmd [ 2 ] = LSDW ( event_log_dma ) ;
mbox_cmd [ 3 ] = MSDW ( event_log_dma ) ;
2007-05-24 05:03:27 +04:00
if ( qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 5 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS ) {
DEBUG2 ( printk ( " scsi%ld: %s: ERROR: Unable to retrieve event "
" log! \n " , ha - > host_no , __func__ ) ) ;
goto exit_get_event_log ;
}
/* Dump Event Log. */
num_valid_entries = mbox_sts [ 1 ] ;
max_event_log_entries = event_log_size /
sizeof ( struct conn_event_log_entry ) ;
if ( num_valid_entries > max_event_log_entries )
oldest_entry = num_valid_entries % max_event_log_entries ;
DEBUG3 ( printk ( " scsi%ld: Connection Event Log Dump (%d entries): \n " ,
ha - > host_no , num_valid_entries ) ) ;
2006-10-06 20:54:59 +04:00
if ( ql4xextended_error_logging = = 3 ) {
2006-09-19 21:28:00 +04:00
if ( oldest_entry = = 0 ) {
/* Circular Buffer has not wrapped around */
for ( i = 0 ; i < num_valid_entries ; i + + ) {
qla4xxx_dump_buffer ( ( uint8_t * ) event_log +
( i * sizeof ( * event_log ) ) ,
sizeof ( * event_log ) ) ;
}
}
else {
/* Circular Buffer has wrapped around -
* display accordingly */
for ( i = oldest_entry ; i < max_event_log_entries ; i + + ) {
qla4xxx_dump_buffer ( ( uint8_t * ) event_log +
( i * sizeof ( * event_log ) ) ,
sizeof ( * event_log ) ) ;
}
for ( i = 0 ; i < oldest_entry ; i + + ) {
qla4xxx_dump_buffer ( ( uint8_t * ) event_log +
( i * sizeof ( * event_log ) ) ,
sizeof ( * event_log ) ) ;
}
}
}
exit_get_event_log :
if ( event_log )
dma_free_coherent ( & ha - > pdev - > dev , event_log_size , event_log ,
event_log_dma ) ;
}
2010-04-28 10:12:24 +04:00
/**
* qla4xxx_abort_task - issues Abort Task
* @ ha : Pointer to host adapter structure .
* @ srb : Pointer to srb entry
*
* This routine performs a LUN RESET on the specified target / lun .
* The caller must ensure that the ddb_entry and lun_entry pointers
* are valid before calling this routine .
* */
int qla4xxx_abort_task ( struct scsi_qla_host * ha , struct srb * srb )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
struct scsi_cmnd * cmd = srb - > cmd ;
int status = QLA_SUCCESS ;
unsigned long flags = 0 ;
uint32_t index ;
/*
* Send abort task command to ISP , so that the ISP will return
* request with ABORT status
*/
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
spin_lock_irqsave ( & ha - > hardware_lock , flags ) ;
index = ( unsigned long ) ( unsigned char * ) cmd - > host_scribble ;
spin_unlock_irqrestore ( & ha - > hardware_lock , flags ) ;
/* Firmware already posted completion on response queue */
if ( index = = MAX_SRBS )
return status ;
mbox_cmd [ 0 ] = MBOX_CMD_ABORT_TASK ;
2010-12-03 09:12:22 +03:00
mbox_cmd [ 1 ] = srb - > ddb - > fw_ddb_index ;
2010-04-28 10:12:24 +04:00
mbox_cmd [ 2 ] = index ;
/* Immediate Command Enable */
mbox_cmd [ 5 ] = 0x01 ;
qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 5 , & mbox_cmd [ 0 ] ,
& mbox_sts [ 0 ] ) ;
if ( mbox_sts [ 0 ] ! = MBOX_STS_COMMAND_COMPLETE ) {
status = QLA_ERROR ;
DEBUG2 ( printk ( KERN_WARNING " scsi%ld:%d:%d: abort task FAILED: "
" mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X \n " ,
ha - > host_no , cmd - > device - > id , cmd - > device - > lun , mbox_sts [ 0 ] ,
mbox_sts [ 1 ] , mbox_sts [ 2 ] , mbox_sts [ 3 ] , mbox_sts [ 4 ] ) ) ;
}
return status ;
}
2006-09-19 21:28:00 +04:00
/**
* qla4xxx_reset_lun - issues LUN Reset
* @ ha : Pointer to host adapter structure .
2010-07-28 14:23:44 +04:00
* @ ddb_entry : Pointer to device database entry
* @ lun : lun number
2006-09-19 21:28:00 +04:00
*
* This routine performs a LUN RESET on the specified target / lun .
* The caller must ensure that the ddb_entry and lun_entry pointers
* are valid before calling this routine .
* */
int qla4xxx_reset_lun ( struct scsi_qla_host * ha , struct ddb_entry * ddb_entry ,
int lun )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
int status = QLA_SUCCESS ;
DEBUG2 ( printk ( " scsi%ld:%d:%d: lun reset issued \n " , ha - > host_no ,
2010-07-28 14:23:44 +04:00
ddb_entry - > fw_ddb_index , lun ) ) ;
2006-09-19 21:28:00 +04:00
/*
* Send lun reset command to ISP , so that the ISP will return all
* outstanding requests with RESET status
*/
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
2007-05-24 05:03:27 +04:00
2006-09-19 21:28:00 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_LUN_RESET ;
mbox_cmd [ 1 ] = ddb_entry - > fw_ddb_index ;
mbox_cmd [ 2 ] = lun < < 8 ;
mbox_cmd [ 5 ] = 0x01 ; /* Immediate Command Enable */
2007-05-24 05:03:27 +04:00
qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 1 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ;
2006-09-19 21:28:00 +04:00
if ( mbox_sts [ 0 ] ! = MBOX_STS_COMMAND_COMPLETE & &
mbox_sts [ 0 ] ! = MBOX_STS_COMMAND_ERROR )
status = QLA_ERROR ;
return status ;
}
2008-03-01 03:25:20 +03:00
/**
* qla4xxx_reset_target - issues target Reset
* @ ha : Pointer to host adapter structure .
* @ db_entry : Pointer to device database entry
* @ un_entry : Pointer to lun entry structure
*
* This routine performs a TARGET RESET on the specified target .
* The caller must ensure that the ddb_entry pointers
* are valid before calling this routine .
* */
int qla4xxx_reset_target ( struct scsi_qla_host * ha ,
struct ddb_entry * ddb_entry )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
int status = QLA_SUCCESS ;
DEBUG2 ( printk ( " scsi%ld:%d: target reset issued \n " , ha - > host_no ,
2010-07-28 14:23:44 +04:00
ddb_entry - > fw_ddb_index ) ) ;
2008-03-01 03:25:20 +03:00
/*
* Send target reset command to ISP , so that the ISP will return all
* outstanding requests with RESET status
*/
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_TARGET_WARM_RESET ;
mbox_cmd [ 1 ] = ddb_entry - > fw_ddb_index ;
mbox_cmd [ 5 ] = 0x01 ; /* Immediate Command Enable */
qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 1 , & mbox_cmd [ 0 ] ,
& mbox_sts [ 0 ] ) ;
if ( mbox_sts [ 0 ] ! = MBOX_STS_COMMAND_COMPLETE & &
mbox_sts [ 0 ] ! = MBOX_STS_COMMAND_ERROR )
status = QLA_ERROR ;
return status ;
}
2006-09-19 21:28:00 +04:00
int qla4xxx_get_flash ( struct scsi_qla_host * ha , dma_addr_t dma_addr ,
uint32_t offset , uint32_t len )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
2007-05-24 05:03:27 +04:00
2006-09-19 21:28:00 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_READ_FLASH ;
mbox_cmd [ 1 ] = LSDW ( dma_addr ) ;
mbox_cmd [ 2 ] = MSDW ( dma_addr ) ;
mbox_cmd [ 3 ] = offset ;
mbox_cmd [ 4 ] = len ;
2007-05-24 05:03:27 +04:00
if ( qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 2 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS ) {
DEBUG2 ( printk ( " scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
" status %04X %04X, offset %08x, len %08x \n " , ha - > host_no ,
__func__ , mbox_sts [ 0 ] , mbox_sts [ 1 ] , offset , len ) ) ;
return QLA_ERROR ;
}
return QLA_SUCCESS ;
}
/**
2011-05-18 10:17:11 +04:00
* qla4xxx_about_firmware - gets FW , iscsi draft and boot loader version
2006-09-19 21:28:00 +04:00
* @ ha : Pointer to host adapter structure .
*
2011-05-18 10:17:11 +04:00
* Retrieves the FW version , iSCSI draft version & bootloader version of HBA .
* Mailboxes 2 & 3 may hold an address for data . Make sure that we write 0 to
* those mailboxes , if unused .
2006-09-19 21:28:00 +04:00
* */
2011-05-18 10:17:11 +04:00
int qla4xxx_about_firmware ( struct scsi_qla_host * ha )
2006-09-19 21:28:00 +04:00
{
2011-05-18 10:17:11 +04:00
struct about_fw_info * about_fw = NULL ;
dma_addr_t about_fw_dma ;
2006-09-19 21:28:00 +04:00
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
2011-05-18 10:17:11 +04:00
int status = QLA_ERROR ;
about_fw = dma_alloc_coherent ( & ha - > pdev - > dev ,
sizeof ( struct about_fw_info ) ,
& about_fw_dma , GFP_KERNEL ) ;
if ( ! about_fw ) {
DEBUG2 ( ql4_printk ( KERN_ERR , ha , " %s: Unable to alloc memory "
" for about_fw \n " , __func__ ) ) ;
return status ;
}
2006-09-19 21:28:00 +04:00
2011-05-18 10:17:11 +04:00
memset ( about_fw , 0 , sizeof ( struct about_fw_info ) ) ;
2006-09-19 21:28:00 +04:00
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
2007-05-24 05:03:27 +04:00
2006-09-19 21:28:00 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_ABOUT_FW ;
2011-05-18 10:17:11 +04:00
mbox_cmd [ 2 ] = LSDW ( about_fw_dma ) ;
mbox_cmd [ 3 ] = MSDW ( about_fw_dma ) ;
mbox_cmd [ 4 ] = sizeof ( struct about_fw_info ) ;
status = qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , MBOX_REG_COUNT ,
& mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_WARNING , ha , " %s: MBOX_CMD_ABOUT_FW "
" failed w/ status %04X \n " , __func__ ,
mbox_sts [ 0 ] ) ) ;
goto exit_about_fw ;
2006-09-19 21:28:00 +04:00
}
2011-05-18 10:17:11 +04:00
/* Save version information. */
ha - > firmware_version [ 0 ] = le16_to_cpu ( about_fw - > fw_major ) ;
ha - > firmware_version [ 1 ] = le16_to_cpu ( about_fw - > fw_minor ) ;
ha - > patch_number = le16_to_cpu ( about_fw - > fw_patch ) ;
ha - > build_number = le16_to_cpu ( about_fw - > fw_build ) ;
ha - > iscsi_major = le16_to_cpu ( about_fw - > iscsi_major ) ;
ha - > iscsi_minor = le16_to_cpu ( about_fw - > iscsi_minor ) ;
ha - > bootload_major = le16_to_cpu ( about_fw - > bootload_major ) ;
ha - > bootload_minor = le16_to_cpu ( about_fw - > bootload_minor ) ;
ha - > bootload_patch = le16_to_cpu ( about_fw - > bootload_patch ) ;
ha - > bootload_build = le16_to_cpu ( about_fw - > bootload_build ) ;
status = QLA_SUCCESS ;
2006-09-19 21:28:00 +04:00
2011-05-18 10:17:11 +04:00
exit_about_fw :
dma_free_coherent ( & ha - > pdev - > dev , sizeof ( struct about_fw_info ) ,
about_fw , about_fw_dma ) ;
return status ;
2006-09-19 21:28:00 +04:00
}
2011-07-25 22:48:53 +04:00
static int qla4xxx_get_default_ddb ( struct scsi_qla_host * ha , uint32_t options ,
2007-04-26 11:35:16 +04:00
dma_addr_t dma_addr )
2006-09-19 21:28:00 +04:00
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS ;
2011-07-25 22:48:53 +04:00
mbox_cmd [ 1 ] = options ;
2006-09-19 21:28:00 +04:00
mbox_cmd [ 2 ] = LSDW ( dma_addr ) ;
mbox_cmd [ 3 ] = MSDW ( dma_addr ) ;
2007-05-24 05:03:27 +04:00
if ( qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 1 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ! =
2006-09-19 21:28:00 +04:00
QLA_SUCCESS ) {
DEBUG2 ( printk ( " scsi%ld: %s: failed status %04X \n " ,
ha - > host_no , __func__ , mbox_sts [ 0 ] ) ) ;
return QLA_ERROR ;
}
return QLA_SUCCESS ;
}
2011-07-25 22:48:53 +04:00
int qla4xxx_req_ddb_entry ( struct scsi_qla_host * ha , uint32_t ddb_index ,
uint32_t * mbx_sts )
2006-09-19 21:28:00 +04:00
{
2011-07-25 22:48:53 +04:00
int status ;
2006-09-19 21:28:00 +04:00
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_REQUEST_DATABASE_ENTRY ;
2011-07-25 22:48:53 +04:00
mbox_cmd [ 1 ] = ddb_index ;
2006-09-19 21:28:00 +04:00
2011-07-25 22:48:53 +04:00
status = qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 1 , & mbox_cmd [ 0 ] ,
& mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_ERR , ha , " %s: failed status %04X \n " ,
__func__ , mbox_sts [ 0 ] ) ) ;
2006-09-19 21:28:00 +04:00
}
2011-07-25 22:48:53 +04:00
* mbx_sts = mbox_sts [ 0 ] ;
return status ;
2006-09-19 21:28:00 +04:00
}
2011-07-25 22:48:53 +04:00
int qla4xxx_clear_ddb_entry ( struct scsi_qla_host * ha , uint32_t ddb_index )
{
int status ;
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_CLEAR_DATABASE_ENTRY ;
mbox_cmd [ 1 ] = ddb_index ;
status = qla4xxx_mailbox_command ( ha , 2 , 1 , & mbox_cmd [ 0 ] ,
& mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_ERR , ha , " %s: failed status %04X \n " ,
__func__ , mbox_sts [ 0 ] ) ) ;
}
return status ;
}
2011-07-25 22:48:38 +04:00
int qla4xxx_set_flash ( struct scsi_qla_host * ha , dma_addr_t dma_addr ,
uint32_t offset , uint32_t length , uint32_t options )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
int status = QLA_SUCCESS ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_WRITE_FLASH ;
mbox_cmd [ 1 ] = LSDW ( dma_addr ) ;
mbox_cmd [ 2 ] = MSDW ( dma_addr ) ;
mbox_cmd [ 3 ] = offset ;
mbox_cmd [ 4 ] = length ;
mbox_cmd [ 5 ] = options ;
status = qla4xxx_mailbox_command ( ha , 6 , 2 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_WARNING , ha , " %s: MBOX_CMD_WRITE_FLASH "
" failed w/ status %04X, mbx1 %04X \n " ,
__func__ , mbox_sts [ 0 ] , mbox_sts [ 1 ] ) ) ;
}
return status ;
}
2011-07-25 22:48:55 +04:00
int qla4xxx_bootdb_by_index ( struct scsi_qla_host * ha ,
struct dev_db_entry * fw_ddb_entry ,
dma_addr_t fw_ddb_entry_dma , uint16_t ddb_index )
{
uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO ;
uint32_t dev_db_end_offset ;
int status = QLA_ERROR ;
memset ( fw_ddb_entry , 0 , sizeof ( * fw_ddb_entry ) ) ;
dev_db_start_offset + = ( ddb_index * sizeof ( * fw_ddb_entry ) ) ;
dev_db_end_offset = FLASH_OFFSET_DB_END ;
if ( dev_db_start_offset > dev_db_end_offset ) {
DEBUG2 ( ql4_printk ( KERN_ERR , ha ,
" %s:Invalid DDB index %d " , __func__ ,
ddb_index ) ) ;
goto exit_bootdb_failed ;
}
if ( qla4xxx_get_flash ( ha , fw_ddb_entry_dma , dev_db_start_offset ,
sizeof ( * fw_ddb_entry ) ) ! = QLA_SUCCESS ) {
ql4_printk ( KERN_ERR , ha , " scsi%ld: %s: Get Flash "
" failed \n " , ha - > host_no , __func__ ) ;
goto exit_bootdb_failed ;
}
if ( fw_ddb_entry - > cookie = = DDB_VALID_COOKIE )
status = QLA_SUCCESS ;
exit_bootdb_failed :
return status ;
}
int qla4xxx_get_chap ( struct scsi_qla_host * ha , char * username , char * password ,
uint16_t idx )
{
int ret = 0 ;
int rval = QLA_ERROR ;
2011-10-08 03:55:42 +04:00
uint32_t offset = 0 , chap_size ;
2011-07-25 22:48:55 +04:00
struct ql4_chap_table * chap_table ;
dma_addr_t chap_dma ;
chap_table = dma_pool_alloc ( ha - > chap_dma_pool , GFP_KERNEL , & chap_dma ) ;
if ( chap_table = = NULL ) {
ret = - ENOMEM ;
goto exit_get_chap ;
}
2011-10-08 03:55:42 +04:00
chap_size = sizeof ( struct ql4_chap_table ) ;
memset ( chap_table , 0 , chap_size ) ;
if ( is_qla40XX ( ha ) )
offset = FLASH_CHAP_OFFSET | ( idx * chap_size ) ;
else {
offset = FLASH_RAW_ACCESS_ADDR + ( ha - > hw . flt_region_chap < < 2 ) ;
/* flt_chap_size is CHAP table size for both ports
* so divide it by 2 to calculate the offset for second port
*/
if ( ha - > port_num = = 1 )
offset + = ( ha - > hw . flt_chap_size / 2 ) ;
offset + = ( idx * chap_size ) ;
}
2011-07-25 22:48:55 +04:00
2011-10-08 03:55:42 +04:00
rval = qla4xxx_get_flash ( ha , chap_dma , offset , chap_size ) ;
2011-07-25 22:48:55 +04:00
if ( rval ! = QLA_SUCCESS ) {
ret = - EINVAL ;
goto exit_get_chap ;
}
DEBUG2 ( ql4_printk ( KERN_INFO , ha , " Chap Cookie: x%x \n " ,
__le16_to_cpu ( chap_table - > cookie ) ) ) ;
if ( __le16_to_cpu ( chap_table - > cookie ) ! = CHAP_VALID_COOKIE ) {
ql4_printk ( KERN_ERR , ha , " No valid chap entry found \n " ) ;
goto exit_get_chap ;
}
strncpy ( password , chap_table - > secret , QL4_CHAP_MAX_SECRET_LEN ) ;
strncpy ( username , chap_table - > name , QL4_CHAP_MAX_NAME_LEN ) ;
chap_table - > cookie = __constant_cpu_to_le16 ( CHAP_VALID_COOKIE ) ;
exit_get_chap :
dma_pool_free ( ha - > chap_dma_pool , chap_table , chap_dma ) ;
return ret ;
}
2011-07-25 22:48:53 +04:00
static int qla4xxx_set_chap ( struct scsi_qla_host * ha , char * username ,
char * password , uint16_t idx , int bidi )
{
int ret = 0 ;
int rval = QLA_ERROR ;
uint32_t offset = 0 ;
struct ql4_chap_table * chap_table ;
dma_addr_t chap_dma ;
chap_table = dma_pool_alloc ( ha - > chap_dma_pool , GFP_KERNEL , & chap_dma ) ;
if ( chap_table = = NULL ) {
ret = - ENOMEM ;
goto exit_set_chap ;
}
memset ( chap_table , 0 , sizeof ( struct ql4_chap_table ) ) ;
if ( bidi )
chap_table - > flags | = BIT_6 ; /* peer */
else
chap_table - > flags | = BIT_7 ; /* local */
chap_table - > secret_len = strlen ( password ) ;
strncpy ( chap_table - > secret , password , MAX_CHAP_SECRET_LEN ) ;
strncpy ( chap_table - > name , username , MAX_CHAP_NAME_LEN ) ;
chap_table - > cookie = __constant_cpu_to_le16 ( CHAP_VALID_COOKIE ) ;
2011-10-08 03:55:42 +04:00
offset = FLASH_CHAP_OFFSET | ( idx * sizeof ( struct ql4_chap_table ) ) ;
2011-07-25 22:48:53 +04:00
rval = qla4xxx_set_flash ( ha , chap_dma , offset ,
sizeof ( struct ql4_chap_table ) ,
FLASH_OPT_RMW_COMMIT ) ;
2011-10-08 03:55:42 +04:00
if ( rval = = QLA_SUCCESS & & ha - > chap_list ) {
/* Update ha chap_list cache */
memcpy ( ( struct ql4_chap_table * ) ha - > chap_list + idx ,
chap_table , sizeof ( struct ql4_chap_table ) ) ;
}
2011-07-25 22:48:53 +04:00
dma_pool_free ( ha - > chap_dma_pool , chap_table , chap_dma ) ;
if ( rval ! = QLA_SUCCESS )
ret = - EINVAL ;
exit_set_chap :
return ret ;
}
2011-10-08 03:55:42 +04:00
/**
* qla4xxx_get_chap_index - Get chap index given username and secret
* @ ha : pointer to adapter structure
* @ username : CHAP username to be searched
* @ password : CHAP password to be searched
* @ bidi : Is this a BIDI CHAP
* @ chap_index : CHAP index to be returned
*
* Match the username and password in the chap_list , return the index if a
* match is found . If a match is not found then add the entry in FLASH and
* return the index at which entry is written in the FLASH .
* */
static int qla4xxx_get_chap_index ( struct scsi_qla_host * ha , char * username ,
char * password , int bidi , uint16_t * chap_index )
{
int i , rval ;
int free_index = - 1 ;
int found_index = 0 ;
int max_chap_entries = 0 ;
struct ql4_chap_table * chap_table ;
if ( is_qla8022 ( ha ) )
max_chap_entries = ( ha - > hw . flt_chap_size / 2 ) /
sizeof ( struct ql4_chap_table ) ;
else
max_chap_entries = MAX_CHAP_ENTRIES_40XX ;
if ( ! ha - > chap_list ) {
ql4_printk ( KERN_ERR , ha , " Do not have CHAP table cache \n " ) ;
return QLA_ERROR ;
}
mutex_lock ( & ha - > chap_sem ) ;
for ( i = 0 ; i < max_chap_entries ; i + + ) {
chap_table = ( struct ql4_chap_table * ) ha - > chap_list + i ;
if ( chap_table - > cookie ! =
__constant_cpu_to_le16 ( CHAP_VALID_COOKIE ) ) {
if ( i > MAX_RESRV_CHAP_IDX & & free_index = = - 1 )
free_index = i ;
continue ;
}
if ( bidi ) {
if ( chap_table - > flags & BIT_7 )
continue ;
} else {
if ( chap_table - > flags & BIT_6 )
continue ;
}
if ( ! strncmp ( chap_table - > secret , password ,
MAX_CHAP_SECRET_LEN ) & &
! strncmp ( chap_table - > name , username ,
MAX_CHAP_NAME_LEN ) ) {
* chap_index = i ;
found_index = 1 ;
break ;
}
}
/* If chap entry is not present and a free index is available then
* write the entry in flash
*/
if ( ! found_index & & free_index ! = - 1 ) {
rval = qla4xxx_set_chap ( ha , username , password ,
free_index , bidi ) ;
if ( ! rval ) {
* chap_index = free_index ;
found_index = 1 ;
}
}
mutex_unlock ( & ha - > chap_sem ) ;
if ( found_index )
return QLA_SUCCESS ;
return QLA_ERROR ;
}
2011-07-25 22:48:38 +04:00
int qla4xxx_conn_close_sess_logout ( struct scsi_qla_host * ha ,
uint16_t fw_ddb_index ,
uint16_t connection_id ,
uint16_t option )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
int status = QLA_SUCCESS ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT ;
mbox_cmd [ 1 ] = fw_ddb_index ;
mbox_cmd [ 2 ] = connection_id ;
mbox_cmd [ 3 ] = option ;
status = qla4xxx_mailbox_command ( ha , 4 , 2 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_WARNING , ha , " %s: MBOX_CMD_CONN_CLOSE "
" option %04x failed w/ status %04X %04X \n " ,
__func__ , option , mbox_sts [ 0 ] , mbox_sts [ 1 ] ) ) ;
}
return status ;
}
int qla4xxx_disable_acb ( struct scsi_qla_host * ha )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
int status = QLA_SUCCESS ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_DISABLE_ACB ;
status = qla4xxx_mailbox_command ( ha , 8 , 5 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_WARNING , ha , " %s: MBOX_CMD_DISABLE_ACB "
" failed w/ status %04X %04X %04X " , __func__ ,
mbox_sts [ 0 ] , mbox_sts [ 1 ] , mbox_sts [ 2 ] ) ) ;
}
return status ;
}
2011-08-12 13:51:27 +04:00
int qla4xxx_get_acb ( struct scsi_qla_host * ha , dma_addr_t acb_dma ,
uint32_t acb_type , uint32_t len )
2011-07-25 22:48:38 +04:00
{
2011-08-12 13:51:27 +04:00
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
2011-07-25 22:48:38 +04:00
int status = QLA_SUCCESS ;
2011-08-12 13:51:27 +04:00
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
2011-07-25 22:48:38 +04:00
mbox_cmd [ 0 ] = MBOX_CMD_GET_ACB ;
2011-08-12 13:51:27 +04:00
mbox_cmd [ 1 ] = acb_type ;
2011-07-25 22:48:38 +04:00
mbox_cmd [ 2 ] = LSDW ( acb_dma ) ;
mbox_cmd [ 3 ] = MSDW ( acb_dma ) ;
2011-08-12 13:51:27 +04:00
mbox_cmd [ 4 ] = len ;
2011-07-25 22:48:38 +04:00
status = qla4xxx_mailbox_command ( ha , 5 , 5 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_WARNING , ha , " %s: MBOX_CMD_GET_ACB "
" failed w/ status %04X \n " , __func__ ,
mbox_sts [ 0 ] ) ) ;
}
return status ;
}
int qla4xxx_set_acb ( struct scsi_qla_host * ha , uint32_t * mbox_cmd ,
uint32_t * mbox_sts , dma_addr_t acb_dma )
{
int status = QLA_SUCCESS ;
memset ( mbox_cmd , 0 , sizeof ( mbox_cmd [ 0 ] ) * MBOX_REG_COUNT ) ;
memset ( mbox_sts , 0 , sizeof ( mbox_sts [ 0 ] ) * MBOX_REG_COUNT ) ;
mbox_cmd [ 0 ] = MBOX_CMD_SET_ACB ;
mbox_cmd [ 1 ] = 0 ; /* Primary ACB */
mbox_cmd [ 2 ] = LSDW ( acb_dma ) ;
mbox_cmd [ 3 ] = MSDW ( acb_dma ) ;
mbox_cmd [ 4 ] = sizeof ( struct addr_ctrl_blk ) ;
status = qla4xxx_mailbox_command ( ha , 5 , 5 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_WARNING , ha , " %s: MBOX_CMD_SET_ACB "
" failed w/ status %04X \n " , __func__ ,
mbox_sts [ 0 ] ) ) ;
}
return status ;
}
2011-07-25 22:48:53 +04:00
int qla4xxx_set_param_ddbentry ( struct scsi_qla_host * ha ,
struct ddb_entry * ddb_entry ,
struct iscsi_cls_conn * cls_conn ,
uint32_t * mbx_sts )
{
struct dev_db_entry * fw_ddb_entry ;
struct iscsi_conn * conn ;
struct iscsi_session * sess ;
struct qla_conn * qla_conn ;
struct sockaddr * dst_addr ;
dma_addr_t fw_ddb_entry_dma ;
int status = QLA_SUCCESS ;
int rval = 0 ;
struct sockaddr_in * addr ;
struct sockaddr_in6 * addr6 ;
char * ip ;
uint16_t iscsi_opts = 0 ;
uint32_t options = 0 ;
uint16_t idx ;
fw_ddb_entry = dma_alloc_coherent ( & ha - > pdev - > dev , sizeof ( * fw_ddb_entry ) ,
& fw_ddb_entry_dma , GFP_KERNEL ) ;
if ( ! fw_ddb_entry ) {
DEBUG2 ( ql4_printk ( KERN_ERR , ha ,
" %s: Unable to allocate dma buffer. \n " ,
__func__ ) ) ;
rval = - ENOMEM ;
goto exit_set_param_no_free ;
}
conn = cls_conn - > dd_data ;
qla_conn = conn - > dd_data ;
sess = conn - > session ;
dst_addr = & qla_conn - > qla_ep - > dst_addr ;
if ( dst_addr - > sa_family = = AF_INET6 )
options | = IPV6_DEFAULT_DDB_ENTRY ;
status = qla4xxx_get_default_ddb ( ha , options , fw_ddb_entry_dma ) ;
if ( status = = QLA_ERROR ) {
rval = - EINVAL ;
goto exit_set_param ;
}
iscsi_opts = le16_to_cpu ( fw_ddb_entry - > iscsi_options ) ;
memset ( fw_ddb_entry - > iscsi_alias , 0 , sizeof ( fw_ddb_entry - > iscsi_alias ) ) ;
memset ( fw_ddb_entry - > iscsi_name , 0 , sizeof ( fw_ddb_entry - > iscsi_name ) ) ;
if ( sess - > targetname ! = NULL ) {
memcpy ( fw_ddb_entry - > iscsi_name , sess - > targetname ,
min ( strlen ( sess - > targetname ) ,
sizeof ( fw_ddb_entry - > iscsi_name ) ) ) ;
}
memset ( fw_ddb_entry - > ip_addr , 0 , sizeof ( fw_ddb_entry - > ip_addr ) ) ;
memset ( fw_ddb_entry - > tgt_addr , 0 , sizeof ( fw_ddb_entry - > tgt_addr ) ) ;
fw_ddb_entry - > options = DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE ;
if ( dst_addr - > sa_family = = AF_INET ) {
addr = ( struct sockaddr_in * ) dst_addr ;
ip = ( char * ) & addr - > sin_addr ;
memcpy ( fw_ddb_entry - > ip_addr , ip , IP_ADDR_LEN ) ;
fw_ddb_entry - > port = cpu_to_le16 ( ntohs ( addr - > sin_port ) ) ;
DEBUG2 ( ql4_printk ( KERN_INFO , ha ,
" %s: Destination Address [%pI4]: index [%d] \n " ,
__func__ , fw_ddb_entry - > ip_addr ,
ddb_entry - > fw_ddb_index ) ) ;
} else if ( dst_addr - > sa_family = = AF_INET6 ) {
addr6 = ( struct sockaddr_in6 * ) dst_addr ;
ip = ( char * ) & addr6 - > sin6_addr ;
memcpy ( fw_ddb_entry - > ip_addr , ip , IPv6_ADDR_LEN ) ;
fw_ddb_entry - > port = cpu_to_le16 ( ntohs ( addr6 - > sin6_port ) ) ;
fw_ddb_entry - > options | = DDB_OPT_IPV6_DEVICE ;
DEBUG2 ( ql4_printk ( KERN_INFO , ha ,
" %s: Destination Address [%pI6]: index [%d] \n " ,
__func__ , fw_ddb_entry - > ip_addr ,
ddb_entry - > fw_ddb_index ) ) ;
} else {
ql4_printk ( KERN_ERR , ha ,
" %s: Failed to get IP Address \n " ,
__func__ ) ;
rval = - EINVAL ;
goto exit_set_param ;
}
/* CHAP */
if ( sess - > username ! = NULL & & sess - > password ! = NULL ) {
if ( strlen ( sess - > username ) & & strlen ( sess - > password ) ) {
iscsi_opts | = BIT_7 ;
2011-10-08 03:55:42 +04:00
rval = qla4xxx_get_chap_index ( ha , sess - > username ,
sess - > password ,
LOCAL_CHAP , & idx ) ;
2011-07-25 22:48:53 +04:00
if ( rval )
goto exit_set_param ;
fw_ddb_entry - > chap_tbl_idx = cpu_to_le16 ( idx ) ;
}
}
if ( sess - > username_in ! = NULL & & sess - > password_in ! = NULL ) {
/* Check if BIDI CHAP */
if ( strlen ( sess - > username_in ) & & strlen ( sess - > password_in ) ) {
iscsi_opts | = BIT_4 ;
2011-10-08 03:55:42 +04:00
rval = qla4xxx_get_chap_index ( ha , sess - > username_in ,
sess - > password_in ,
BIDI_CHAP , & idx ) ;
2011-07-25 22:48:53 +04:00
if ( rval )
goto exit_set_param ;
}
}
if ( sess - > initial_r2t_en )
iscsi_opts | = BIT_10 ;
if ( sess - > imm_data_en )
iscsi_opts | = BIT_11 ;
fw_ddb_entry - > iscsi_options = cpu_to_le16 ( iscsi_opts ) ;
if ( conn - > max_recv_dlength )
fw_ddb_entry - > iscsi_max_rcv_data_seg_len =
__constant_cpu_to_le16 ( ( conn - > max_recv_dlength / BYTE_UNITS ) ) ;
if ( sess - > max_r2t )
fw_ddb_entry - > iscsi_max_outsnd_r2t = cpu_to_le16 ( sess - > max_r2t ) ;
if ( sess - > first_burst )
fw_ddb_entry - > iscsi_first_burst_len =
__constant_cpu_to_le16 ( ( sess - > first_burst / BYTE_UNITS ) ) ;
if ( sess - > max_burst )
fw_ddb_entry - > iscsi_max_burst_len =
__constant_cpu_to_le16 ( ( sess - > max_burst / BYTE_UNITS ) ) ;
if ( sess - > time2wait )
fw_ddb_entry - > iscsi_def_time2wait =
cpu_to_le16 ( sess - > time2wait ) ;
if ( sess - > time2retain )
fw_ddb_entry - > iscsi_def_time2retain =
cpu_to_le16 ( sess - > time2retain ) ;
status = qla4xxx_set_ddb_entry ( ha , ddb_entry - > fw_ddb_index ,
fw_ddb_entry_dma , mbx_sts ) ;
if ( status ! = QLA_SUCCESS )
rval = - EINVAL ;
exit_set_param :
dma_free_coherent ( & ha - > pdev - > dev , sizeof ( * fw_ddb_entry ) ,
fw_ddb_entry , fw_ddb_entry_dma ) ;
exit_set_param_no_free :
return rval ;
}
int qla4xxx_get_mgmt_data ( struct scsi_qla_host * ha , uint16_t fw_ddb_index ,
uint16_t stats_size , dma_addr_t stats_dma )
{
int status = QLA_SUCCESS ;
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
memset ( mbox_cmd , 0 , sizeof ( mbox_cmd [ 0 ] ) * MBOX_REG_COUNT ) ;
memset ( mbox_sts , 0 , sizeof ( mbox_sts [ 0 ] ) * MBOX_REG_COUNT ) ;
mbox_cmd [ 0 ] = MBOX_CMD_GET_MANAGEMENT_DATA ;
mbox_cmd [ 1 ] = fw_ddb_index ;
mbox_cmd [ 2 ] = LSDW ( stats_dma ) ;
mbox_cmd [ 3 ] = MSDW ( stats_dma ) ;
mbox_cmd [ 4 ] = stats_size ;
status = qla4xxx_mailbox_command ( ha , 5 , 1 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_WARNING , ha ,
" %s: MBOX_CMD_GET_MANAGEMENT_DATA "
" failed w/ status %04X \n " , __func__ ,
mbox_sts [ 0 ] ) ) ;
}
return status ;
}
2011-08-01 14:26:15 +04:00
int qla4xxx_get_ip_state ( struct scsi_qla_host * ha , uint32_t acb_idx ,
uint32_t ip_idx , uint32_t * sts )
{
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
int status = QLA_SUCCESS ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_GET_IP_ADDR_STATE ;
mbox_cmd [ 1 ] = acb_idx ;
mbox_cmd [ 2 ] = ip_idx ;
status = qla4xxx_mailbox_command ( ha , 3 , 8 , & mbox_cmd [ 0 ] , & mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_WARNING , ha , " %s: "
" MBOX_CMD_GET_IP_ADDR_STATE failed w/ "
" status %04X \n " , __func__ , mbox_sts [ 0 ] ) ) ;
}
memcpy ( sts , mbox_sts , sizeof ( mbox_sts ) ) ;
return status ;
}
2011-08-01 14:26:16 +04:00
int qla4xxx_get_nvram ( struct scsi_qla_host * ha , dma_addr_t nvram_dma ,
uint32_t offset , uint32_t size )
{
int status = QLA_SUCCESS ;
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_GET_NVRAM ;
mbox_cmd [ 1 ] = LSDW ( nvram_dma ) ;
mbox_cmd [ 2 ] = MSDW ( nvram_dma ) ;
mbox_cmd [ 3 ] = offset ;
mbox_cmd [ 4 ] = size ;
status = qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 1 , & mbox_cmd [ 0 ] ,
& mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_ERR , ha , " scsi%ld: %s: failed "
" status %04X \n " , ha - > host_no , __func__ ,
mbox_sts [ 0 ] ) ) ;
}
return status ;
}
int qla4xxx_set_nvram ( struct scsi_qla_host * ha , dma_addr_t nvram_dma ,
uint32_t offset , uint32_t size )
{
int status = QLA_SUCCESS ;
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_SET_NVRAM ;
mbox_cmd [ 1 ] = LSDW ( nvram_dma ) ;
mbox_cmd [ 2 ] = MSDW ( nvram_dma ) ;
mbox_cmd [ 3 ] = offset ;
mbox_cmd [ 4 ] = size ;
status = qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 1 , & mbox_cmd [ 0 ] ,
& mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_ERR , ha , " scsi%ld: %s: failed "
" status %04X \n " , ha - > host_no , __func__ ,
mbox_sts [ 0 ] ) ) ;
}
return status ;
}
2011-08-12 13:51:26 +04:00
int qla4xxx_restore_factory_defaults ( struct scsi_qla_host * ha ,
uint32_t region , uint32_t field0 ,
uint32_t field1 )
{
int status = QLA_SUCCESS ;
uint32_t mbox_cmd [ MBOX_REG_COUNT ] ;
uint32_t mbox_sts [ MBOX_REG_COUNT ] ;
memset ( & mbox_cmd , 0 , sizeof ( mbox_cmd ) ) ;
memset ( & mbox_sts , 0 , sizeof ( mbox_sts ) ) ;
mbox_cmd [ 0 ] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS ;
mbox_cmd [ 3 ] = region ;
mbox_cmd [ 4 ] = field0 ;
mbox_cmd [ 5 ] = field1 ;
status = qla4xxx_mailbox_command ( ha , MBOX_REG_COUNT , 3 , & mbox_cmd [ 0 ] ,
& mbox_sts [ 0 ] ) ;
if ( status ! = QLA_SUCCESS ) {
DEBUG2 ( ql4_printk ( KERN_ERR , ha , " scsi%ld: %s: failed "
" status %04X \n " , ha - > host_no , __func__ ,
mbox_sts [ 0 ] ) ) ;
}
return status ;
}