2014-02-26 04:15:06 -05:00
/*
* QLogic Fibre Channel HBA Driver
2014-04-11 16:54:24 -04:00
* Copyright ( c ) 2003 - 2014 QLogic Corporation
2014-02-26 04:15:06 -05:00
*
* See LICENSE . qla2xxx for copyright and licensing details .
*/
# include "qla_def.h"
# include "qla_tmpl.h"
2019-03-12 11:08:20 -07:00
# define ISPREG(vha) (&(vha)->hw->iobase->isp24)
# define IOBAR(reg) offsetof(typeof(*(reg)), iobase_addr)
# define IOBASE(vha) IOBAR(ISPREG(vha))
2014-02-26 04:15:06 -05:00
static inline void
qla27xx_insert16 ( uint16_t value , void * buf , ulong * len )
{
if ( buf ) {
buf + = * len ;
* ( __le16 * ) buf = cpu_to_le16 ( value ) ;
}
* len + = sizeof ( value ) ;
}
static inline void
qla27xx_insert32 ( uint32_t value , void * buf , ulong * len )
{
if ( buf ) {
buf + = * len ;
* ( __le32 * ) buf = cpu_to_le32 ( value ) ;
}
* len + = sizeof ( value ) ;
}
static inline void
qla27xx_insertbuf ( void * mem , ulong size , void * buf , ulong * len )
{
2014-09-25 05:16:35 -04:00
if ( buf & & mem & & size ) {
2014-02-26 04:15:06 -05:00
buf + = * len ;
2014-09-25 05:16:35 -04:00
memcpy ( buf , mem , size ) ;
2014-02-26 04:15:06 -05:00
}
* len + = size ;
}
static inline void
2015-07-09 07:24:50 -07:00
qla27xx_read8 ( void __iomem * window , void * buf , ulong * len )
2014-02-26 04:15:06 -05:00
{
uint8_t value = ~ 0 ;
if ( buf ) {
2015-07-09 07:24:50 -07:00
value = RD_REG_BYTE ( window ) ;
2014-02-26 04:15:06 -05:00
}
qla27xx_insert32 ( value , buf , len ) ;
}
static inline void
2015-07-09 07:24:50 -07:00
qla27xx_read16 ( void __iomem * window , void * buf , ulong * len )
2014-02-26 04:15:06 -05:00
{
uint16_t value = ~ 0 ;
if ( buf ) {
2015-07-09 07:24:50 -07:00
value = RD_REG_WORD ( window ) ;
2014-02-26 04:15:06 -05:00
}
qla27xx_insert32 ( value , buf , len ) ;
}
static inline void
2015-07-09 07:24:50 -07:00
qla27xx_read32 ( void __iomem * window , void * buf , ulong * len )
2014-02-26 04:15:06 -05:00
{
uint32_t value = ~ 0 ;
if ( buf ) {
2015-07-09 07:24:50 -07:00
value = RD_REG_DWORD ( window ) ;
2014-02-26 04:15:06 -05:00
}
qla27xx_insert32 ( value , buf , len ) ;
}
2015-07-09 07:24:50 -07:00
static inline void ( * qla27xx_read_vector ( uint width ) ) ( void __iomem * , void * , ulong * )
2014-02-26 04:15:06 -05:00
{
return
( width = = 1 ) ? qla27xx_read8 :
( width = = 2 ) ? qla27xx_read16 :
qla27xx_read32 ;
}
static inline void
qla27xx_read_reg ( __iomem struct device_reg_24xx * reg ,
uint offset , void * buf , ulong * len )
{
2015-07-09 07:24:50 -07:00
void __iomem * window = ( void __iomem * ) reg + offset ;
2014-02-26 04:15:06 -05:00
qla27xx_read32 ( window , buf , len ) ;
}
static inline void
qla27xx_write_reg ( __iomem struct device_reg_24xx * reg ,
uint offset , uint32_t data , void * buf )
{
if ( buf ) {
2019-03-12 11:08:19 -07:00
void __iomem * window = ( void __iomem * ) reg + offset ;
2014-02-26 04:15:06 -05:00
WRT_REG_DWORD ( window , data ) ;
}
}
static inline void
qla27xx_read_window ( __iomem struct device_reg_24xx * reg ,
2014-04-11 16:54:36 -04:00
uint32_t addr , uint offset , uint count , uint width , void * buf ,
2014-02-26 04:15:06 -05:00
ulong * len )
{
2015-07-09 07:24:50 -07:00
void __iomem * window = ( void __iomem * ) reg + offset ;
void ( * readn ) ( void __iomem * , void * , ulong * ) = qla27xx_read_vector ( width ) ;
2014-02-26 04:15:06 -05:00
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( reg , IOBAR ( reg ) , addr , buf ) ;
2014-02-26 04:15:06 -05:00
while ( count - - ) {
2014-04-11 16:54:36 -04:00
qla27xx_insert32 ( addr , buf , len ) ;
2014-02-26 04:15:06 -05:00
readn ( window , buf , len ) ;
window + = width ;
2014-04-11 16:54:36 -04:00
addr + + ;
2014-02-26 04:15:06 -05:00
}
}
static inline void
qla27xx_skip_entry ( struct qla27xx_fwdt_entry * ent , void * buf )
{
if ( buf )
ent - > hdr . driver_flags | = DRIVER_FLAG_SKIP_ENTRY ;
}
2019-02-15 14:37:21 -08:00
static inline struct qla27xx_fwdt_entry *
qla27xx_next_entry ( struct qla27xx_fwdt_entry * ent )
{
2019-03-12 11:08:16 -07:00
return ( void * ) ent + le32_to_cpu ( ent - > hdr . size ) ;
2019-02-15 14:37:21 -08:00
}
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t0 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
ql_dbg ( ql_dbg_misc , vha , 0xd100 ,
" %s: nop [%lx] \n " , __func__ , * len ) ;
qla27xx_skip_entry ( ent , buf ) ;
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t255 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
ql_dbg ( ql_dbg_misc , vha , 0xd1ff ,
" %s: end [%lx] \n " , __func__ , * len ) ;
qla27xx_skip_entry ( ent , buf ) ;
/* terminate */
2019-02-15 14:37:21 -08:00
return NULL ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t256 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong addr = le32_to_cpu ( ent - > t256 . base_addr ) ;
uint offset = ent - > t256 . pci_offset ;
ulong count = le16_to_cpu ( ent - > t256 . reg_count ) ;
uint width = ent - > t256 . reg_width ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd200 ,
" %s: rdio t1 [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_read_window ( ISPREG ( vha ) , addr , offset , count , width , buf , len ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t257 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong addr = le32_to_cpu ( ent - > t257 . base_addr ) ;
uint offset = ent - > t257 . pci_offset ;
ulong data = le32_to_cpu ( ent - > t257 . write_data ) ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd201 ,
" %s: wrio t1 [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , IOBASE ( vha ) , addr , buf ) ;
qla27xx_write_reg ( ISPREG ( vha ) , offset , data , buf ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t258 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
uint banksel = ent - > t258 . banksel_offset ;
ulong bank = le32_to_cpu ( ent - > t258 . bank ) ;
ulong addr = le32_to_cpu ( ent - > t258 . base_addr ) ;
uint offset = ent - > t258 . pci_offset ;
uint count = le16_to_cpu ( ent - > t258 . reg_count ) ;
uint width = ent - > t258 . reg_width ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd202 ,
" %s: rdio t2 [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , banksel , bank , buf ) ;
qla27xx_read_window ( ISPREG ( vha ) , addr , offset , count , width , buf , len ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t259 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong addr = le32_to_cpu ( ent - > t259 . base_addr ) ;
uint banksel = ent - > t259 . banksel_offset ;
ulong bank = le32_to_cpu ( ent - > t259 . bank ) ;
uint offset = ent - > t259 . pci_offset ;
ulong data = le32_to_cpu ( ent - > t259 . write_data ) ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd203 ,
" %s: wrio t2 [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , IOBASE ( vha ) , addr , buf ) ;
qla27xx_write_reg ( ISPREG ( vha ) , banksel , bank , buf ) ;
qla27xx_write_reg ( ISPREG ( vha ) , offset , data , buf ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t260 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
uint offset = ent - > t260 . pci_offset ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd204 ,
" %s: rdpci [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:16 -07:00
qla27xx_insert32 ( offset , buf , len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_read_reg ( ISPREG ( vha ) , offset , buf , len ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t261 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
uint offset = ent - > t261 . pci_offset ;
ulong data = le32_to_cpu ( ent - > t261 . write_data ) ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd205 ,
" %s: wrpci [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , offset , data , buf ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t262 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
uint area = ent - > t262 . ram_area ;
ulong start = le32_to_cpu ( ent - > t262 . start_addr ) ;
ulong end = le32_to_cpu ( ent - > t262 . end_addr ) ;
2014-02-26 04:15:06 -05:00
ulong dwords ;
ql_dbg ( ql_dbg_misc , vha , 0xd206 ,
" %s: rdram(%x) [%lx] \n " , __func__ , ent - > t262 . ram_area , * len ) ;
2019-03-12 11:08:16 -07:00
if ( area = = T262_RAM_AREA_CRITICAL_RAM ) {
2014-02-26 04:15:06 -05:00
;
2019-03-12 11:08:16 -07:00
} else if ( area = = T262_RAM_AREA_EXTERNAL_RAM ) {
2014-02-26 04:15:06 -05:00
end = vha - > hw - > fw_memory_size ;
if ( buf )
2019-03-12 11:08:16 -07:00
ent - > t262 . end_addr = cpu_to_le32 ( end ) ;
} else if ( area = = T262_RAM_AREA_SHARED_RAM ) {
2014-02-26 04:15:06 -05:00
start = vha - > hw - > fw_shared_ram_start ;
end = vha - > hw - > fw_shared_ram_end ;
if ( buf ) {
2019-03-12 11:08:16 -07:00
ent - > t262 . start_addr = cpu_to_le32 ( start ) ;
ent - > t262 . end_addr = cpu_to_le32 ( end ) ;
2014-02-26 04:15:06 -05:00
}
2019-03-12 11:08:16 -07:00
} else if ( area = = T262_RAM_AREA_DDR_RAM ) {
2016-07-06 11:14:18 -04:00
start = vha - > hw - > fw_ddr_ram_start ;
end = vha - > hw - > fw_ddr_ram_end ;
if ( buf ) {
2019-03-12 11:08:16 -07:00
ent - > t262 . start_addr = cpu_to_le32 ( start ) ;
ent - > t262 . end_addr = cpu_to_le32 ( end ) ;
2016-07-06 11:14:18 -04:00
}
2019-03-12 11:08:16 -07:00
} else if ( area = = T262_RAM_AREA_MISC ) {
2019-02-15 14:37:21 -08:00
if ( buf ) {
2019-03-12 11:08:16 -07:00
ent - > t262 . start_addr = cpu_to_le32 ( start ) ;
ent - > t262 . end_addr = cpu_to_le32 ( end ) ;
2019-02-15 14:37:21 -08:00
}
2014-02-26 04:15:06 -05:00
} else {
ql_dbg ( ql_dbg_misc , vha , 0xd022 ,
2019-03-12 11:08:16 -07:00
" %s: unknown area %x \n " , __func__ , area ) ;
2014-02-26 04:15:06 -05:00
qla27xx_skip_entry ( ent , buf ) ;
goto done ;
}
2017-05-24 18:06:21 -07:00
if ( end < start | | start = = 0 | | end = = 0 ) {
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd023 ,
2019-03-12 11:08:16 -07:00
" %s: unusable range (start=%lx end=%lx) \n " ,
__func__ , start , end ) ;
2014-02-26 04:15:06 -05:00
qla27xx_skip_entry ( ent , buf ) ;
goto done ;
}
dwords = end - start + 1 ;
if ( buf ) {
buf + = * len ;
qla24xx_dump_ram ( vha - > hw , start , buf , dwords , & buf ) ;
}
* len + = dwords * sizeof ( uint32_t ) ;
done :
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t263 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
uint type = ent - > t263 . queue_type ;
2014-02-26 04:15:06 -05:00
uint count = 0 ;
uint i ;
uint length ;
2019-03-12 11:08:16 -07:00
ql_dbg ( ql_dbg_misc + ql_dbg_verbose , vha , 0xd207 ,
" %s: getq(%x) [%lx] \n " , __func__ , type , * len ) ;
if ( type = = T263_QUEUE_TYPE_REQ ) {
2014-02-26 04:15:06 -05:00
for ( i = 0 ; i < vha - > hw - > max_req_queues ; i + + ) {
struct req_que * req = vha - > hw - > req_q_map [ i ] ;
2016-02-04 11:45:16 -05:00
2014-02-26 04:15:06 -05:00
if ( req | | ! buf ) {
length = req ?
req - > length : REQUEST_ENTRY_CNT_24XX ;
qla27xx_insert16 ( i , buf , len ) ;
qla27xx_insert16 ( length , buf , len ) ;
qla27xx_insertbuf ( req ? req - > ring : NULL ,
length * sizeof ( * req - > ring ) , buf , len ) ;
count + + ;
}
}
2019-03-12 11:08:16 -07:00
} else if ( type = = T263_QUEUE_TYPE_RSP ) {
2014-02-26 04:15:06 -05:00
for ( i = 0 ; i < vha - > hw - > max_rsp_queues ; i + + ) {
struct rsp_que * rsp = vha - > hw - > rsp_q_map [ i ] ;
2016-02-04 11:45:16 -05:00
2014-02-26 04:15:06 -05:00
if ( rsp | | ! buf ) {
length = rsp ?
rsp - > length : RESPONSE_ENTRY_CNT_MQ ;
qla27xx_insert16 ( i , buf , len ) ;
qla27xx_insert16 ( length , buf , len ) ;
qla27xx_insertbuf ( rsp ? rsp - > ring : NULL ,
length * sizeof ( * rsp - > ring ) , buf , len ) ;
count + + ;
}
}
2016-12-23 18:06:06 -08:00
} else if ( QLA_TGT_MODE_ENABLED ( ) & &
ent - > t263 . queue_type = = T263_QUEUE_TYPE_ATIO ) {
struct qla_hw_data * ha = vha - > hw ;
struct atio * atr = ha - > tgt . atio_ring ;
if ( atr | | ! buf ) {
length = ha - > tgt . atio_q_length ;
qla27xx_insert16 ( 0 , buf , len ) ;
qla27xx_insert16 ( length , buf , len ) ;
qla27xx_insertbuf ( atr , length * sizeof ( * atr ) , buf , len ) ;
count + + ;
}
2014-02-26 04:15:06 -05:00
} else {
ql_dbg ( ql_dbg_misc , vha , 0xd026 ,
2019-03-12 11:08:16 -07:00
" %s: unknown queue %x \n " , __func__ , type ) ;
2014-02-26 04:15:06 -05:00
qla27xx_skip_entry ( ent , buf ) ;
}
2017-08-23 15:05:22 -07:00
if ( buf ) {
if ( count )
ent - > t263 . num_queues = count ;
else
qla27xx_skip_entry ( ent , buf ) ;
}
2014-04-11 16:54:36 -04:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t264 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
ql_dbg ( ql_dbg_misc , vha , 0xd208 ,
" %s: getfce [%lx] \n " , __func__ , * len ) ;
if ( vha - > hw - > fce ) {
if ( buf ) {
ent - > t264 . fce_trace_size = FCE_SIZE ;
ent - > t264 . write_pointer = vha - > hw - > fce_wr ;
ent - > t264 . base_pointer = vha - > hw - > fce_dma ;
ent - > t264 . fce_enable_mb0 = vha - > hw - > fce_mb [ 0 ] ;
ent - > t264 . fce_enable_mb2 = vha - > hw - > fce_mb [ 2 ] ;
ent - > t264 . fce_enable_mb3 = vha - > hw - > fce_mb [ 3 ] ;
ent - > t264 . fce_enable_mb4 = vha - > hw - > fce_mb [ 4 ] ;
ent - > t264 . fce_enable_mb5 = vha - > hw - > fce_mb [ 5 ] ;
ent - > t264 . fce_enable_mb6 = vha - > hw - > fce_mb [ 6 ] ;
}
qla27xx_insertbuf ( vha - > hw - > fce , FCE_SIZE , buf , len ) ;
} else {
ql_dbg ( ql_dbg_misc , vha , 0xd027 ,
" %s: missing fce \n " , __func__ ) ;
qla27xx_skip_entry ( ent , buf ) ;
}
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t265 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:20 -07:00
ql_dbg ( ql_dbg_misc + ql_dbg_verbose , vha , 0xd209 ,
2014-02-26 04:15:06 -05:00
" %s: pause risc [%lx] \n " , __func__ , * len ) ;
if ( buf )
2019-03-12 11:08:20 -07:00
qla24xx_pause_risc ( ISPREG ( vha ) , vha - > hw ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t266 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
ql_dbg ( ql_dbg_misc , vha , 0xd20a ,
" %s: reset risc [%lx] \n " , __func__ , * len ) ;
if ( buf )
2019-08-08 20:01:57 -07:00
WARN_ON_ONCE ( qla24xx_soft_reset ( vha - > hw ) ! = QLA_SUCCESS ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t267 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
uint offset = ent - > t267 . pci_offset ;
ulong data = le32_to_cpu ( ent - > t267 . data ) ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd20b ,
" %s: dis intr [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , offset , data , buf ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t268 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
ql_dbg ( ql_dbg_misc , vha , 0xd20c ,
" %s: gethb(%x) [%lx] \n " , __func__ , ent - > t268 . buf_type , * len ) ;
2017-12-28 12:33:14 -08:00
switch ( ent - > t268 . buf_type ) {
case T268_BUF_TYPE_EXTD_TRACE :
2014-02-26 04:15:06 -05:00
if ( vha - > hw - > eft ) {
if ( buf ) {
ent - > t268 . buf_size = EFT_SIZE ;
ent - > t268 . start_addr = vha - > hw - > eft_dma ;
}
qla27xx_insertbuf ( vha - > hw - > eft , EFT_SIZE , buf , len ) ;
} else {
ql_dbg ( ql_dbg_misc , vha , 0xd028 ,
" %s: missing eft \n " , __func__ ) ;
qla27xx_skip_entry ( ent , buf ) ;
}
2017-12-28 12:33:14 -08:00
break ;
case T268_BUF_TYPE_EXCH_BUFOFF :
if ( vha - > hw - > exchoffld_buf ) {
if ( buf ) {
ent - > t268 . buf_size = vha - > hw - > exchoffld_size ;
ent - > t268 . start_addr =
vha - > hw - > exchoffld_buf_dma ;
}
qla27xx_insertbuf ( vha - > hw - > exchoffld_buf ,
vha - > hw - > exchoffld_size , buf , len ) ;
} else {
ql_dbg ( ql_dbg_misc , vha , 0xd028 ,
" %s: missing exch offld \n " , __func__ ) ;
qla27xx_skip_entry ( ent , buf ) ;
}
break ;
case T268_BUF_TYPE_EXTD_LOGIN :
if ( vha - > hw - > exlogin_buf ) {
if ( buf ) {
ent - > t268 . buf_size = vha - > hw - > exlogin_size ;
ent - > t268 . start_addr =
vha - > hw - > exlogin_buf_dma ;
}
qla27xx_insertbuf ( vha - > hw - > exlogin_buf ,
vha - > hw - > exlogin_size , buf , len ) ;
} else {
ql_dbg ( ql_dbg_misc , vha , 0xd028 ,
" %s: missing ext login \n " , __func__ ) ;
qla27xx_skip_entry ( ent , buf ) ;
}
break ;
2018-08-02 13:16:48 -07:00
case T268_BUF_TYPE_REQ_MIRROR :
case T268_BUF_TYPE_RSP_MIRROR :
/*
* Mirror pointers are not implemented in the
* driver , instead shadow pointers are used by
* the drier . Skip these entries .
*/
qla27xx_skip_entry ( ent , buf ) ;
break ;
2017-12-28 12:33:14 -08:00
default :
ql_dbg ( ql_dbg_async , vha , 0xd02b ,
2014-09-25 05:16:40 -04:00
" %s: unknown buffer %x \n " , __func__ , ent - > t268 . buf_type ) ;
2014-02-26 04:15:06 -05:00
qla27xx_skip_entry ( ent , buf ) ;
2017-12-28 12:33:14 -08:00
break ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t269 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
ql_dbg ( ql_dbg_misc , vha , 0xd20d ,
" %s: scratch [%lx] \n " , __func__ , * len ) ;
qla27xx_insert32 ( 0xaaaaaaaa , buf , len ) ;
qla27xx_insert32 ( 0xbbbbbbbb , buf , len ) ;
qla27xx_insert32 ( 0xcccccccc , buf , len ) ;
qla27xx_insert32 ( 0xdddddddd , buf , len ) ;
qla27xx_insert32 ( * len + sizeof ( uint32_t ) , buf , len ) ;
if ( buf )
ent - > t269 . scratch_size = 5 * sizeof ( uint32_t ) ;
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t270 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong addr = le32_to_cpu ( ent - > t270 . addr ) ;
ulong dwords = le32_to_cpu ( ent - > t270 . count ) ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd20e ,
" %s: rdremreg [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , IOBASE_ADDR , 0x40 , buf ) ;
2014-02-26 04:15:06 -05:00
while ( dwords - - ) {
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , 0xc0 , addr | 0x80000000 , buf ) ;
2014-02-26 04:15:06 -05:00
qla27xx_insert32 ( addr , buf , len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_read_reg ( ISPREG ( vha ) , 0xc4 , buf , len ) ;
2014-04-11 16:54:23 -04:00
addr + = sizeof ( uint32_t ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t271 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong addr = le32_to_cpu ( ent - > t271 . addr ) ;
ulong data = le32_to_cpu ( ent - > t271 . data ) ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd20f ,
" %s: wrremreg [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , IOBASE ( vha ) , 0x40 , buf ) ;
qla27xx_write_reg ( ISPREG ( vha ) , 0xc4 , data , buf ) ;
qla27xx_write_reg ( ISPREG ( vha ) , 0xc0 , addr , buf ) ;
2014-02-26 04:15:06 -05:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t272 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong dwords = le32_to_cpu ( ent - > t272 . count ) ;
ulong start = le32_to_cpu ( ent - > t272 . addr ) ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd210 ,
" %s: rdremram [%lx] \n " , __func__ , * len ) ;
if ( buf ) {
ql_dbg ( ql_dbg_misc , vha , 0xd02c ,
" %s: @%lx -> (%lx dwords) \n " , __func__ , start , dwords ) ;
buf + = * len ;
qla27xx_dump_mpi_ram ( vha - > hw , start , buf , dwords , & buf ) ;
}
* len + = dwords * sizeof ( uint32_t ) ;
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_t273 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong dwords = le32_to_cpu ( ent - > t273 . count ) ;
ulong addr = le32_to_cpu ( ent - > t273 . addr ) ;
2014-02-26 04:15:06 -05:00
uint32_t value ;
ql_dbg ( ql_dbg_misc , vha , 0xd211 ,
" %s: pcicfg [%lx] \n " , __func__ , * len ) ;
while ( dwords - - ) {
value = ~ 0 ;
if ( pci_read_config_dword ( vha - > hw - > pdev , addr , & value ) )
ql_dbg ( ql_dbg_misc , vha , 0xd02d ,
" %s: failed pcicfg read at %lx \n " , __func__ , addr ) ;
qla27xx_insert32 ( addr , buf , len ) ;
qla27xx_insert32 ( value , buf , len ) ;
2014-04-11 16:54:36 -04:00
addr + = sizeof ( uint32_t ) ;
}
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-04-11 16:54:36 -04:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-04-11 16:54:36 -04:00
qla27xx_fwdt_entry_t274 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong type = ent - > t274 . queue_type ;
2014-04-11 16:54:36 -04:00
uint count = 0 ;
uint i ;
2019-03-12 11:08:16 -07:00
ql_dbg ( ql_dbg_misc + ql_dbg_verbose , vha , 0xd212 ,
" %s: getqsh(%lx) [%lx] \n " , __func__ , type , * len ) ;
if ( type = = T274_QUEUE_TYPE_REQ_SHAD ) {
2014-04-11 16:54:36 -04:00
for ( i = 0 ; i < vha - > hw - > max_req_queues ; i + + ) {
struct req_que * req = vha - > hw - > req_q_map [ i ] ;
2016-02-04 11:45:16 -05:00
2014-04-11 16:54:36 -04:00
if ( req | | ! buf ) {
qla27xx_insert16 ( i , buf , len ) ;
qla27xx_insert16 ( 1 , buf , len ) ;
2014-04-11 16:54:37 -04:00
qla27xx_insert32 ( req & & req - > out_ptr ?
* req - > out_ptr : 0 , buf , len ) ;
2014-04-11 16:54:36 -04:00
count + + ;
}
}
2019-03-12 11:08:16 -07:00
} else if ( type = = T274_QUEUE_TYPE_RSP_SHAD ) {
2014-04-11 16:54:36 -04:00
for ( i = 0 ; i < vha - > hw - > max_rsp_queues ; i + + ) {
struct rsp_que * rsp = vha - > hw - > rsp_q_map [ i ] ;
2016-02-04 11:45:16 -05:00
2014-04-11 16:54:36 -04:00
if ( rsp | | ! buf ) {
qla27xx_insert16 ( i , buf , len ) ;
qla27xx_insert16 ( 1 , buf , len ) ;
2014-04-11 16:54:37 -04:00
qla27xx_insert32 ( rsp & & rsp - > in_ptr ?
* rsp - > in_ptr : 0 , buf , len ) ;
2014-04-11 16:54:36 -04:00
count + + ;
}
}
2016-12-23 18:06:06 -08:00
} else if ( QLA_TGT_MODE_ENABLED ( ) & &
ent - > t274 . queue_type = = T274_QUEUE_TYPE_ATIO_SHAD ) {
struct qla_hw_data * ha = vha - > hw ;
struct atio * atr = ha - > tgt . atio_ring_ptr ;
if ( atr | | ! buf ) {
qla27xx_insert16 ( 0 , buf , len ) ;
qla27xx_insert16 ( 1 , buf , len ) ;
qla27xx_insert32 ( ha - > tgt . atio_q_in ?
readl ( ha - > tgt . atio_q_in ) : 0 , buf , len ) ;
count + + ;
}
2014-04-11 16:54:36 -04:00
} else {
ql_dbg ( ql_dbg_misc , vha , 0xd02f ,
2019-03-12 11:08:16 -07:00
" %s: unknown queue %lx \n " , __func__ , type ) ;
2014-04-11 16:54:36 -04:00
qla27xx_skip_entry ( ent , buf ) ;
2014-02-26 04:15:06 -05:00
}
2017-08-23 15:05:22 -07:00
if ( buf ) {
if ( count )
ent - > t274 . num_queues = count ;
else
qla27xx_skip_entry ( ent , buf ) ;
}
2014-04-11 16:54:36 -04:00
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-09-25 05:16:36 -04:00
qla27xx_fwdt_entry_t275 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
ulong offset = offsetof ( typeof ( * ent ) , t275 . buffer ) ;
2019-03-12 11:08:16 -07:00
ulong length = le32_to_cpu ( ent - > t275 . length ) ;
ulong size = le32_to_cpu ( ent - > hdr . size ) ;
void * buffer = ent - > t275 . buffer ;
2014-09-25 05:16:36 -04:00
2019-03-12 11:08:16 -07:00
ql_dbg ( ql_dbg_misc + ql_dbg_verbose , vha , 0xd213 ,
" %s: buffer(%lx) [%lx] \n " , __func__ , length , * len ) ;
if ( ! length ) {
2014-09-25 05:16:36 -04:00
ql_dbg ( ql_dbg_misc , vha , 0xd020 ,
" %s: buffer zero length \n " , __func__ ) ;
qla27xx_skip_entry ( ent , buf ) ;
goto done ;
}
2019-03-12 11:08:16 -07:00
if ( offset + length > size ) {
2019-03-12 11:08:19 -07:00
length = size - offset ;
2014-09-25 05:16:36 -04:00
ql_dbg ( ql_dbg_misc , vha , 0xd030 ,
2019-03-12 11:08:19 -07:00
" %s: buffer overflow, truncate [%lx] \n " , __func__ , length ) ;
ent - > t275 . length = cpu_to_le32 ( length ) ;
2014-09-25 05:16:36 -04:00
}
2019-03-12 11:08:16 -07:00
qla27xx_insertbuf ( buffer , length , buf , len ) ;
2014-09-25 05:16:36 -04:00
done :
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
}
static struct qla27xx_fwdt_entry *
qla27xx_fwdt_entry_t276 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
ql_dbg ( ql_dbg_misc + ql_dbg_verbose , vha , 0xd214 ,
" %s: cond [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:19 -07:00
if ( buf ) {
ulong cond1 = le32_to_cpu ( ent - > t276 . cond1 ) ;
ulong cond2 = le32_to_cpu ( ent - > t276 . cond2 ) ;
uint type = vha - > hw - > pdev - > device > > 4 & 0xf ;
uint func = vha - > hw - > port_no & 0x3 ;
if ( type ! = cond1 | | func ! = cond2 ) {
struct qla27xx_fwdt_template * tmp = buf ;
tmp - > count - - ;
ent = qla27xx_next_entry ( ent ) ;
qla27xx_skip_entry ( ent , buf ) ;
}
2019-02-15 14:37:21 -08:00
}
return qla27xx_next_entry ( ent ) ;
}
static struct qla27xx_fwdt_entry *
qla27xx_fwdt_entry_t277 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong cmd_addr = le32_to_cpu ( ent - > t277 . cmd_addr ) ;
ulong wr_cmd_data = le32_to_cpu ( ent - > t277 . wr_cmd_data ) ;
ulong data_addr = le32_to_cpu ( ent - > t277 . data_addr ) ;
2019-02-15 14:37:21 -08:00
ql_dbg ( ql_dbg_misc + ql_dbg_verbose , vha , 0xd215 ,
" %s: rdpep [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:16 -07:00
qla27xx_insert32 ( wr_cmd_data , buf , len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , cmd_addr , wr_cmd_data , buf ) ;
qla27xx_read_reg ( ISPREG ( vha ) , data_addr , buf , len ) ;
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
}
static struct qla27xx_fwdt_entry *
qla27xx_fwdt_entry_t278 ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong cmd_addr = le32_to_cpu ( ent - > t278 . cmd_addr ) ;
ulong wr_cmd_data = le32_to_cpu ( ent - > t278 . wr_cmd_data ) ;
ulong data_addr = le32_to_cpu ( ent - > t278 . data_addr ) ;
ulong wr_data = le32_to_cpu ( ent - > t278 . wr_data ) ;
2019-02-15 14:37:21 -08:00
ql_dbg ( ql_dbg_misc + ql_dbg_verbose , vha , 0xd216 ,
" %s: wrpep [%lx] \n " , __func__ , * len ) ;
2019-03-12 11:08:20 -07:00
qla27xx_write_reg ( ISPREG ( vha ) , data_addr , wr_data , buf ) ;
qla27xx_write_reg ( ISPREG ( vha ) , cmd_addr , wr_cmd_data , buf ) ;
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-09-25 05:16:36 -04:00
}
2019-02-15 14:37:21 -08:00
static struct qla27xx_fwdt_entry *
2014-02-26 04:15:06 -05:00
qla27xx_fwdt_entry_other ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_entry * ent , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
ulong type = le32_to_cpu ( ent - > hdr . type ) ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd2ff ,
2019-03-12 11:08:16 -07:00
" %s: other %lx [%lx] \n " , __func__ , type , * len ) ;
2014-02-26 04:15:06 -05:00
qla27xx_skip_entry ( ent , buf ) ;
2019-02-15 14:37:21 -08:00
return qla27xx_next_entry ( ent ) ;
2014-02-26 04:15:06 -05:00
}
2019-02-15 14:37:21 -08:00
static struct {
2014-09-25 05:16:33 -04:00
uint type ;
2019-02-15 14:37:21 -08:00
typeof ( qla27xx_fwdt_entry_other ) ( * call ) ;
} qla27xx_fwdt_entry_call [ ] = {
2019-02-15 14:37:20 -08:00
{ ENTRY_TYPE_NOP , qla27xx_fwdt_entry_t0 } ,
{ ENTRY_TYPE_TMP_END , qla27xx_fwdt_entry_t255 } ,
{ ENTRY_TYPE_RD_IOB_T1 , qla27xx_fwdt_entry_t256 } ,
{ ENTRY_TYPE_WR_IOB_T1 , qla27xx_fwdt_entry_t257 } ,
{ ENTRY_TYPE_RD_IOB_T2 , qla27xx_fwdt_entry_t258 } ,
{ ENTRY_TYPE_WR_IOB_T2 , qla27xx_fwdt_entry_t259 } ,
{ ENTRY_TYPE_RD_PCI , qla27xx_fwdt_entry_t260 } ,
{ ENTRY_TYPE_WR_PCI , qla27xx_fwdt_entry_t261 } ,
{ ENTRY_TYPE_RD_RAM , qla27xx_fwdt_entry_t262 } ,
{ ENTRY_TYPE_GET_QUEUE , qla27xx_fwdt_entry_t263 } ,
{ ENTRY_TYPE_GET_FCE , qla27xx_fwdt_entry_t264 } ,
{ ENTRY_TYPE_PSE_RISC , qla27xx_fwdt_entry_t265 } ,
{ ENTRY_TYPE_RST_RISC , qla27xx_fwdt_entry_t266 } ,
{ ENTRY_TYPE_DIS_INTR , qla27xx_fwdt_entry_t267 } ,
{ ENTRY_TYPE_GET_HBUF , qla27xx_fwdt_entry_t268 } ,
{ ENTRY_TYPE_SCRATCH , qla27xx_fwdt_entry_t269 } ,
{ ENTRY_TYPE_RDREMREG , qla27xx_fwdt_entry_t270 } ,
{ ENTRY_TYPE_WRREMREG , qla27xx_fwdt_entry_t271 } ,
{ ENTRY_TYPE_RDREMRAM , qla27xx_fwdt_entry_t272 } ,
{ ENTRY_TYPE_PCICFG , qla27xx_fwdt_entry_t273 } ,
{ ENTRY_TYPE_GET_SHADOW , qla27xx_fwdt_entry_t274 } ,
{ ENTRY_TYPE_WRITE_BUF , qla27xx_fwdt_entry_t275 } ,
2019-02-15 14:37:21 -08:00
{ ENTRY_TYPE_CONDITIONAL , qla27xx_fwdt_entry_t276 } ,
{ ENTRY_TYPE_RDPEPREG , qla27xx_fwdt_entry_t277 } ,
{ ENTRY_TYPE_WRPEPREG , qla27xx_fwdt_entry_t278 } ,
2019-02-15 14:37:20 -08:00
{ - 1 , qla27xx_fwdt_entry_other }
2014-02-26 04:15:06 -05:00
} ;
2019-02-15 14:37:21 -08:00
static inline
typeof ( qla27xx_fwdt_entry_call - > call ) ( qla27xx_find_entry ( uint type ) )
2014-02-26 04:15:06 -05:00
{
2019-02-15 14:37:21 -08:00
typeof ( * qla27xx_fwdt_entry_call ) * list = qla27xx_fwdt_entry_call ;
2014-02-26 04:15:06 -05:00
2014-09-25 05:16:33 -04:00
while ( list - > type < type )
2014-02-26 04:15:06 -05:00
list + + ;
2014-09-25 05:16:33 -04:00
if ( list - > type = = type )
return list - > call ;
return qla27xx_fwdt_entry_other ;
2014-02-26 04:15:06 -05:00
}
static void
qla27xx_walk_template ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_template * tmp , void * buf , ulong * len )
{
2019-03-12 11:08:16 -07:00
struct qla27xx_fwdt_entry * ent = ( void * ) tmp +
le32_to_cpu ( tmp - > entry_offset ) ;
2019-03-12 11:08:19 -07:00
ulong type ;
2014-02-26 04:15:06 -05:00
2019-03-12 11:08:19 -07:00
tmp - > count = le32_to_cpu ( tmp - > entry_count ) ;
2014-02-26 04:15:06 -05:00
ql_dbg ( ql_dbg_misc , vha , 0xd01a ,
2019-03-12 11:08:19 -07:00
" %s: entry count %u \n " , __func__ , tmp - > count ) ;
while ( ent & & tmp - > count - - ) {
2019-03-12 11:08:16 -07:00
type = le32_to_cpu ( ent - > hdr . type ) ;
ent = qla27xx_find_entry ( type ) ( vha , ent , buf , len ) ;
2019-02-15 14:37:21 -08:00
if ( ! ent )
2017-06-02 09:11:55 -07:00
break ;
2014-02-26 04:15:06 -05:00
}
2014-09-25 05:16:32 -04:00
2019-03-12 11:08:19 -07:00
if ( tmp - > count )
2014-09-25 05:16:32 -04:00
ql_dbg ( ql_dbg_misc , vha , 0xd018 ,
2019-03-12 11:08:19 -07:00
" %s: entry count residual=+%u \n " , __func__ , tmp - > count ) ;
2014-09-25 05:16:32 -04:00
2019-02-15 14:37:21 -08:00
if ( ent )
2014-09-25 05:16:32 -04:00
ql_dbg ( ql_dbg_misc , vha , 0xd019 ,
2019-03-12 11:08:17 -07:00
" %s: missing end entry \n " , __func__ ) ;
2014-02-26 04:15:06 -05:00
}
static void
qla27xx_time_stamp ( struct qla27xx_fwdt_template * tmp )
{
tmp - > capture_timestamp = jiffies ;
}
static void
qla27xx_driver_info ( struct qla27xx_fwdt_template * tmp )
{
uint8_t v [ ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-08-08 20:01:45 -07:00
WARN_ON_ONCE ( sscanf ( qla2x00_version_str ,
" %hhu.%hhu.%hhu.%hhu.%hhu.%hhu " ,
v + 0 , v + 1 , v + 2 , v + 3 , v + 4 , v + 5 ) ! = 6 ) ;
2014-02-26 04:15:06 -05:00
tmp - > driver_info [ 0 ] = v [ 3 ] < < 24 | v [ 2 ] < < 16 | v [ 1 ] < < 8 | v [ 0 ] ;
tmp - > driver_info [ 1 ] = v [ 5 ] < < 8 | v [ 4 ] ;
tmp - > driver_info [ 2 ] = 0x12345678 ;
}
static void
2019-03-12 11:08:17 -07:00
qla27xx_firmware_info ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_template * tmp )
2014-02-26 04:15:06 -05:00
{
tmp - > firmware_version [ 0 ] = vha - > hw - > fw_major_version ;
tmp - > firmware_version [ 1 ] = vha - > hw - > fw_minor_version ;
tmp - > firmware_version [ 2 ] = vha - > hw - > fw_subminor_version ;
tmp - > firmware_version [ 3 ] =
vha - > hw - > fw_attributes_h < < 16 | vha - > hw - > fw_attributes ;
tmp - > firmware_version [ 4 ] =
vha - > hw - > fw_attributes_ext [ 1 ] < < 16 | vha - > hw - > fw_attributes_ext [ 0 ] ;
}
static void
ql27xx_edit_template ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_template * tmp )
{
qla27xx_time_stamp ( tmp ) ;
qla27xx_driver_info ( tmp ) ;
2019-03-12 11:08:17 -07:00
qla27xx_firmware_info ( vha , tmp ) ;
2014-02-26 04:15:06 -05:00
}
static inline uint32_t
qla27xx_template_checksum ( void * p , ulong size )
{
2019-03-12 11:08:16 -07:00
__le32 * buf = p ;
2014-02-26 04:15:06 -05:00
uint64_t sum = 0 ;
size / = sizeof ( * buf ) ;
2019-03-12 11:08:16 -07:00
for ( ; size - - ; buf + + )
sum + = le32_to_cpu ( * buf ) ;
2014-02-26 04:15:06 -05:00
sum = ( sum & 0xffffffff ) + ( sum > > 32 ) ;
return ~ sum ;
}
static inline int
qla27xx_verify_template_checksum ( struct qla27xx_fwdt_template * tmp )
{
return qla27xx_template_checksum ( tmp , tmp - > template_size ) = = 0 ;
}
static inline int
qla27xx_verify_template_header ( struct qla27xx_fwdt_template * tmp )
{
2019-03-12 11:08:16 -07:00
return le32_to_cpu ( tmp - > template_type ) = = TEMPLATE_TYPE_FWDUMP ;
2014-02-26 04:15:06 -05:00
}
2019-03-12 11:08:17 -07:00
static ulong
qla27xx_execute_fwdt_template ( struct scsi_qla_host * vha ,
struct qla27xx_fwdt_template * tmp , void * buf )
2014-02-26 04:15:06 -05:00
{
2019-03-12 11:08:17 -07:00
ulong len = 0 ;
2014-02-26 04:15:06 -05:00
if ( qla27xx_fwdt_template_valid ( tmp ) ) {
len = tmp - > template_size ;
2019-03-12 11:08:17 -07:00
tmp = memcpy ( buf , tmp , len ) ;
2014-02-26 04:15:06 -05:00
ql27xx_edit_template ( vha , tmp ) ;
2019-03-12 11:08:17 -07:00
qla27xx_walk_template ( vha , tmp , buf , & len ) ;
2014-02-26 04:15:06 -05:00
}
2019-03-12 11:08:17 -07:00
return len ;
2014-02-26 04:15:06 -05:00
}
ulong
2019-03-12 11:08:17 -07:00
qla27xx_fwdt_calculate_dump_size ( struct scsi_qla_host * vha , void * p )
2014-02-26 04:15:06 -05:00
{
2019-03-12 11:08:17 -07:00
struct qla27xx_fwdt_template * tmp = p ;
2014-02-26 04:15:06 -05:00
ulong len = 0 ;
if ( qla27xx_fwdt_template_valid ( tmp ) ) {
len = tmp - > template_size ;
qla27xx_walk_template ( vha , tmp , NULL , & len ) ;
}
return len ;
}
ulong
qla27xx_fwdt_template_size ( void * p )
{
struct qla27xx_fwdt_template * tmp = p ;
return tmp - > template_size ;
}
int
qla27xx_fwdt_template_valid ( void * p )
{
struct qla27xx_fwdt_template * tmp = p ;
if ( ! qla27xx_verify_template_header ( tmp ) ) {
ql_log ( ql_log_warn , NULL , 0xd01c ,
2019-03-12 11:08:16 -07:00
" %s: template type %x \n " , __func__ ,
le32_to_cpu ( tmp - > template_type ) ) ;
2014-02-26 04:15:06 -05:00
return false ;
}
if ( ! qla27xx_verify_template_checksum ( tmp ) ) {
ql_log ( ql_log_warn , NULL , 0xd01d ,
" %s: failed template checksum \n " , __func__ ) ;
return false ;
}
return true ;
}
void
qla27xx_fwdump ( scsi_qla_host_t * vha , int hardware_locked )
{
ulong flags = 0 ;
2015-07-09 07:25:46 -07:00
# ifndef __CHECKER__
2014-02-26 04:15:06 -05:00
if ( ! hardware_locked )
spin_lock_irqsave ( & vha - > hw - > hardware_lock , flags ) ;
2015-07-09 07:25:46 -07:00
# endif
2014-02-26 04:15:06 -05:00
2019-03-12 11:08:17 -07:00
if ( ! vha - > hw - > fw_dump ) {
ql_log ( ql_log_warn , vha , 0xd01e , " -> fwdump no buffer \n " ) ;
} else if ( vha - > hw - > fw_dumped ) {
ql_log ( ql_log_warn , vha , 0xd01f ,
" -> Firmware already dumped (%p) -- ignoring request \n " ,
vha - > hw - > fw_dump ) ;
} else {
struct fwdt * fwdt = vha - > hw - > fwdt ;
uint j ;
ulong len ;
void * buf = vha - > hw - > fw_dump ;
for ( j = 0 ; j < 2 ; j + + , fwdt + + , buf + = len ) {
ql_log ( ql_log_warn , vha , 0xd011 ,
" -> fwdt%u running... \n " , j ) ;
if ( ! fwdt - > template ) {
ql_log ( ql_log_warn , vha , 0xd012 ,
" -> fwdt%u no template \n " , j ) ;
break ;
}
len = qla27xx_execute_fwdt_template ( vha ,
fwdt - > template , buf ) ;
if ( len ! = fwdt - > dump_size ) {
ql_log ( ql_log_warn , vha , 0xd013 ,
" -> fwdt%u fwdump residual=%+ld \n " ,
j , fwdt - > dump_size - len ) ;
}
}
vha - > hw - > fw_dump_len = buf - ( void * ) vha - > hw - > fw_dump ;
vha - > hw - > fw_dumped = 1 ;
ql_log ( ql_log_warn , vha , 0xd015 ,
" -> Firmware dump saved to buffer (%lu/%p) <%lx> \n " ,
vha - > host_no , vha - > hw - > fw_dump , vha - > hw - > fw_dump_cap_flags ) ;
qla2x00_post_uevent_work ( vha , QLA_UEVENT_CODE_FW_DUMP ) ;
2018-08-02 13:16:46 -07:00
}
2014-02-26 04:15:06 -05:00
2015-07-09 07:25:46 -07:00
# ifndef __CHECKER__
2014-02-26 04:15:06 -05:00
if ( ! hardware_locked )
spin_unlock_irqrestore ( & vha - > hw - > hardware_lock , flags ) ;
2015-07-09 07:25:46 -07:00
# endif
2014-02-26 04:15:06 -05:00
}