@ -2743,6 +2743,26 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
}
}
static int __devinit hpsa_send_host_reset ( struct ctlr_info * h ,
unsigned char * scsi3addr , u8 reset_type )
{
struct CommandList * c ;
c = cmd_alloc ( h ) ;
if ( ! c )
return - ENOMEM ;
fill_cmd ( c , HPSA_DEVICE_RESET_MSG , h , NULL , 0 , 0 ,
RAID_CTLR_LUNID , TYPE_MSG ) ;
c - > Request . CDB [ 1 ] = reset_type ; /* fill_cmd defaults to target reset */
c - > waiting = NULL ;
enqueue_cmd_and_start_io ( h , c ) ;
/* Don't wait for completion, the reset won't complete. Don't free
* the command either . This is the last command we will send before
* re - initializing everything , so it doesn ' t matter and won ' t leak .
*/
return 0 ;
}
static void fill_cmd ( struct CommandList * c , u8 cmd , struct ctlr_info * h ,
void * buff , size_t size , u8 page_code , unsigned char * scsi3addr ,
int cmd_type )
@ -2820,7 +2840,8 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
c - > Request . Type . Attribute = ATTR_SIMPLE ;
c - > Request . Type . Direction = XFER_NONE ;
c - > Request . Timeout = 0 ; /* Don't time out */
c - > Request . CDB [ 0 ] = 0x01 ; /* RESET_MSG is 0x01 */
memset ( & c - > Request . CDB [ 0 ] , 0 , sizeof ( c - > Request . CDB ) ) ;
c - > Request . CDB [ 0 ] = cmd ;
c - > Request . CDB [ 1 ] = 0x03 ; /* Reset target above */
/* If bytes 4-7 are zero, it means reset the */
/* LunID device */
@ -2986,6 +3007,63 @@ static inline u32 process_nonindexed_cmd(struct ctlr_info *h,
return next_command ( h ) ;
}
/* Some controllers, like p400, will give us one interrupt
* after a soft reset , even if we turned interrupts off .
* Only need to check for this in the hpsa_xxx_discard_completions
* functions .
*/
static int ignore_bogus_interrupt ( struct ctlr_info * h )
{
if ( likely ( ! reset_devices ) )
return 0 ;
if ( likely ( h - > interrupts_enabled ) )
return 0 ;
dev_info ( & h - > pdev - > dev , " Received interrupt while interrupts disabled "
" (known firmware bug.) Ignoring. \n " ) ;
return 1 ;
}
static irqreturn_t hpsa_intx_discard_completions ( int irq , void * dev_id )
{
struct ctlr_info * h = dev_id ;
unsigned long flags ;
u32 raw_tag ;
if ( ignore_bogus_interrupt ( h ) )
return IRQ_NONE ;
if ( interrupt_not_for_us ( h ) )
return IRQ_NONE ;
spin_lock_irqsave ( & h - > lock , flags ) ;
while ( interrupt_pending ( h ) ) {
raw_tag = get_next_completion ( h ) ;
while ( raw_tag ! = FIFO_EMPTY )
raw_tag = next_command ( h ) ;
}
spin_unlock_irqrestore ( & h - > lock , flags ) ;
return IRQ_HANDLED ;
}
static irqreturn_t hpsa_msix_discard_completions ( int irq , void * dev_id )
{
struct ctlr_info * h = dev_id ;
unsigned long flags ;
u32 raw_tag ;
if ( ignore_bogus_interrupt ( h ) )
return IRQ_NONE ;
spin_lock_irqsave ( & h - > lock , flags ) ;
raw_tag = get_next_completion ( h ) ;
while ( raw_tag ! = FIFO_EMPTY )
raw_tag = next_command ( h ) ;
spin_unlock_irqrestore ( & h - > lock , flags ) ;
return IRQ_HANDLED ;
}
static irqreturn_t do_hpsa_intr_intx ( int irq , void * dev_id )
{
struct ctlr_info * h = dev_id ;
@ -3124,7 +3202,6 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
return 0 ;
}
# define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0)
# define hpsa_noop(p) hpsa_message(p, 3, 0)
static int hpsa_controller_hard_reset ( struct pci_dev * pdev ,
@ -3320,7 +3397,7 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
" 'Bit 2 doorbell reset' is "
" supported, but not 'bit 5 doorbell reset'. "
" Firmware update is recommended. \n " ) ;
rc = - ENODEV ;
rc = - ENOTSUPP ; /* try soft reset */
goto unmap_cfgtable ;
}
}
@ -3344,13 +3421,18 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
/* Wait for board to become not ready, then ready. */
dev_info ( & pdev - > dev , " Waiting for board to reset. \n " ) ;
rc = hpsa_wait_for_board_state ( pdev , vaddr , BOARD_NOT_READY ) ;
if ( rc )
if ( rc ) {
dev_warn ( & pdev - > dev ,
" failed waiting for board to reset \n " ) ;
" failed waiting for board to reset. "
" Will try soft reset. \n " ) ;
rc = - ENOTSUPP ; /* Not expected, but try soft reset later */
goto unmap_cfgtable ;
}
rc = hpsa_wait_for_board_state ( pdev , vaddr , BOARD_READY ) ;
if ( rc ) {
dev_warn ( & pdev - > dev ,
" failed waiting for board to become ready \n " ) ;
" failed waiting for board to become ready "
" after hard reset \n " ) ;
goto unmap_cfgtable ;
}
@ -3358,11 +3440,11 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
if ( rc < 0 )
goto unmap_cfgtable ;
if ( rc ) {
dev_warn ( & pdev - > dev , " Unable to successfully reset controller, "
" Ignoring controller.\n " ) ;
rc = - ENODEV ;
dev_warn ( & pdev - > dev , " Unable to successfully reset "
" controller. Will try soft reset . \n " ) ;
rc = - ENOTSUPP ;
} else {
dev_info ( & pdev - > dev , " board ready. \n " ) ;
dev_info ( & pdev - > dev , " board ready after hard reset . \n " ) ;
}
unmap_cfgtable :
@ -3840,7 +3922,7 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
* due to concerns about shared bbwc between 6402 / 6404 pair .
*/
if ( rc = = - ENOTSUPP )
return 0 ; /* just try to do the kdump anyhow. */
return rc ; /* just try to do the kdump anyhow. */
if ( rc )
return - ENODEV ;
@ -3910,18 +3992,79 @@ static int hpsa_request_irq(struct ctlr_info *h,
return 0 ;
}
static int __devinit hpsa_kdump_soft_reset ( struct ctlr_info * h )
{
if ( hpsa_send_host_reset ( h , RAID_CTLR_LUNID ,
HPSA_RESET_TYPE_CONTROLLER ) ) {
dev_warn ( & h - > pdev - > dev , " Resetting array controller failed. \n " ) ;
return - EIO ;
}
dev_info ( & h - > pdev - > dev , " Waiting for board to soft reset. \n " ) ;
if ( hpsa_wait_for_board_state ( h - > pdev , h - > vaddr , BOARD_NOT_READY ) ) {
dev_warn ( & h - > pdev - > dev , " Soft reset had no effect. \n " ) ;
return - 1 ;
}
dev_info ( & h - > pdev - > dev , " Board reset, awaiting READY status. \n " ) ;
if ( hpsa_wait_for_board_state ( h - > pdev , h - > vaddr , BOARD_READY ) ) {
dev_warn ( & h - > pdev - > dev , " Board failed to become ready "
" after soft reset. \n " ) ;
return - 1 ;
}
return 0 ;
}
static void hpsa_undo_allocations_after_kdump_soft_reset ( struct ctlr_info * h )
{
free_irq ( h - > intr [ h - > intr_mode ] , h ) ;
# ifdef CONFIG_PCI_MSI
if ( h - > msix_vector )
pci_disable_msix ( h - > pdev ) ;
else if ( h - > msi_vector )
pci_disable_msi ( h - > pdev ) ;
# endif /* CONFIG_PCI_MSI */
hpsa_free_sg_chain_blocks ( h ) ;
hpsa_free_cmd_pool ( h ) ;
kfree ( h - > blockFetchTable ) ;
pci_free_consistent ( h - > pdev , h - > reply_pool_size ,
h - > reply_pool , h - > reply_pool_dhandle ) ;
if ( h - > vaddr )
iounmap ( h - > vaddr ) ;
if ( h - > transtable )
iounmap ( h - > transtable ) ;
if ( h - > cfgtable )
iounmap ( h - > cfgtable ) ;
pci_release_regions ( h - > pdev ) ;
kfree ( h ) ;
}
static int __devinit hpsa_init_one ( struct pci_dev * pdev ,
const struct pci_device_id * ent )
{
int dac , rc ;
struct ctlr_info * h ;
int try_soft_reset = 0 ;
unsigned long flags ;
if ( number_of_controllers = = 0 )
printk ( KERN_INFO DRIVER_NAME " \n " ) ;
rc = hpsa_init_reset_devices ( pdev ) ;
if ( rc )
return rc ;
if ( rc ) {
if ( rc ! = - ENOTSUPP )
return rc ;
/* If the reset fails in a particular way (it has no way to do
* a proper hard reset , so returns - ENOTSUPP ) we can try to do
* a soft reset once we get the controller configured up to the
* point that it can accept a command .
*/
try_soft_reset = 1 ;
rc = 0 ;
}
reinit_after_soft_reset :
/* Command structures must be aligned on a 32-byte boundary because
* the 5 lower bits of the address are used by the hardware . and by
@ -3981,11 +4124,66 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
h - > ndevices = 0 ;
h - > scsi_host = NULL ;
spin_lock_init ( & h - > devlock ) ;
hpsa_put_ctlr_into_performant_mode ( h ) ;
/* At this point, the controller is ready to take commands.
* Now , if reset_devices and the hard reset didn ' t work , try
* the soft reset and see if that works .
*/
if ( try_soft_reset ) {
/* This is kind of gross. We may or may not get a completion
* from the soft reset command , and if we do , then the value
* from the fifo may or may not be valid . So , we wait 10 secs
* after the reset throwing away any completions we get during
* that time . Unregister the interrupt handler and register
* fake ones to scoop up any residual completions .
*/
spin_lock_irqsave ( & h - > lock , flags ) ;
h - > access . set_intr_mask ( h , HPSA_INTR_OFF ) ;
spin_unlock_irqrestore ( & h - > lock , flags ) ;
free_irq ( h - > intr [ h - > intr_mode ] , h ) ;
rc = hpsa_request_irq ( h , hpsa_msix_discard_completions ,
hpsa_intx_discard_completions ) ;
if ( rc ) {
dev_warn ( & h - > pdev - > dev , " Failed to request_irq after "
" soft reset. \n " ) ;
goto clean4 ;
}
rc = hpsa_kdump_soft_reset ( h ) ;
if ( rc )
/* Neither hard nor soft reset worked, we're hosed. */
goto clean4 ;
dev_info ( & h - > pdev - > dev , " Board READY. \n " ) ;
dev_info ( & h - > pdev - > dev ,
" Waiting for stale completions to drain. \n " ) ;
h - > access . set_intr_mask ( h , HPSA_INTR_ON ) ;
msleep ( 10000 ) ;
h - > access . set_intr_mask ( h , HPSA_INTR_OFF ) ;
rc = controller_reset_failed ( h - > cfgtable ) ;
if ( rc )
dev_info ( & h - > pdev - > dev ,
" Soft reset appears to have failed. \n " ) ;
/* since the controller's reset, we have to go back and re-init
* everything . Easiest to just forget what we ' ve done and do it
* all over again .
*/
hpsa_undo_allocations_after_kdump_soft_reset ( h ) ;
try_soft_reset = 0 ;
if ( rc )
/* don't go to clean4, we already unallocated */
return - ENODEV ;
goto reinit_after_soft_reset ;
}
/* Turn the interrupts on so we can service requests */
h - > access . set_intr_mask ( h , HPSA_INTR_ON ) ;
hpsa_put_ctlr_into_performant_mode ( h ) ;
hpsa_hba_inquiry ( h ) ;
hpsa_register_scsi ( h ) ; /* hook ourselves into SCSI subsystem */
h - > busy_initializing = 0 ;