hpsa updates for May 2010
Subsystems (3)
cover hpsa updates for May 2010
hpsa: The following series implements mostly small cleanups in the initialization code with the aim to make hpsa_pci_init() a little smaller and more readable. Fixed a bug that some ioremapped memory was not being unmapped in all cases. Fixed a minor bug that would cause large commands (many scatter gather elements) to not be fetched out of host memory in a single transaction. Added some documentation and an entry in MAINTAINERS. Added /sys entry to show controller firmware revision.
---
Stephen M. Cameron (24):
hpsa: save pdev pointer in per hba structure early to avoid passing it around so much.
hpsa: factor out hpsa_lookup_board_id
hpsa: factor out hpsa_board_disabled
hpsa: remove redundant board_id parameter from hpsa_interrupt_mode
hpsa: factor out hpsa_find_memory_BAR
hpsa: factor out hpsa_wait_for_board_ready
hpsa: factor out hpsa_find_cfgtables
hpsa: fix leak of ioremapped memory
hpsa: hpsa factor out hpsa_find_board_params
hpsa: factor out hpsa-CISS-signature-present
hpsa: factor out hpsa_enable_scsi_prefetch
hpsa: factor out hpsa_p600_dma_prefetch_quirk
hpsa: factor out hpsa_enter_simple_mode
hpsa: check that simple mode is supported
hpsa: clean up debug ifdefs
hpsa: mark hpsa_mark_hpsa_put_ctlr_into_performant_mode as __devinit
hpsa: factor out hpsa_wait_for_mode_change_ack
hpsa: remove unused variable trans_offset
hpsa: factor out hpsa_enter_performant_mode
hpsa: remove unused firm_ver member of the per-hba structure
hpsa: Add hpsa.txt to Documentation/scsi
hpsa: expose controller firmware revision via /sys.
hpsa: fix block fetch table problem.
hpsa: add entry to MAINTAINERS
Documentation/scsi/hpsa.txt | 107 ++++++++++ MAINTAINERS | 8 + drivers/scsi/hpsa.c | 440 ++++++++++++++++++++++++++----------------- drivers/scsi/hpsa.h | 1 4 files changed, 381 insertions(+), 175 deletions(-) create mode 100644 Documentation/scsi/hpsa.txt
Signature · 1 line
Signature
PATCH 1/24 hpsa: save pdev pointer in per hba structure early to avoid passing it around so much.
From: Stephen M. Cameron <[email protected]>
hpsa: save pdev pointer in per hba structure early to avoid passing it around so much.
--- drivers/scsi/hpsa.c | 75 ++++++++++++++++++++++++++------------------------- 1 files changed, 38 insertions(+), 37 deletions(-)
drivers/scsi/hpsa.c +38 -37
@@ -3217,8 +3217,7 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)* controllers that are capable. If not, we use IO-APIC mode. */ -static void __devinit hpsa_interrupt_mode (struct ctlr_info *h, -struct pci_dev *pdev,u32 board_id) +static void __devinit hpsa_interrupt_mode (struct ctlr_info *h,u32 board_id) {#ifdef CONFIG_PCI_MSI int err;
@@ -3231,9 +3230,9 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, (board_id == 0x40800E11) || (board_id == 0x40820E11) || (board_id == 0x40830E11)) goto default_int_mode; -if (pci_find_capability (pdev,PCI_CAP_ID_MSIX )) { -dev_info (&pdev->dev,"MSIX\n" ); - err =pci_enable_msix (pdev, hpsa_msix_entries,4 ); +if (pci_find_capability (h->pdev,PCI_CAP_ID_MSIX )) { +dev_info (&h->pdev->dev,"MSIX\n" ); + err =pci_enable_msix (h->pdev, hpsa_msix_entries,4 );if (!err) { h->intr[0 ] = hpsa_msix_entries[0 ].vector; h->intr[1 ] = hpsa_msix_entries[1 ].vector;
@@ -3243,29 +3242,29 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, return; }if (err >0 ) { -dev_warn (&pdev->dev,"only %d MSI-X vectors " +dev_warn (&h->pdev->dev,"only %d MSI-X vectors " "available\n" , err); goto default_int_mode; }else { -dev_warn (&pdev->dev,"MSI-X init failed %d\n" , +dev_warn (&h->pdev->dev,"MSI-X init failed %d\n" , err); goto default_int_mode; } } -if (pci_find_capability (pdev,PCI_CAP_ID_MSI )) { -dev_info (&pdev->dev,"MSI\n" ); -if (!pci_enable_msi (pdev)) +if (pci_find_capability (h->pdev,PCI_CAP_ID_MSI )) { +dev_info (&h->pdev->dev,"MSI\n" ); +if (!pci_enable_msi (h->pdev)) h->msi_vector =1 ;else -dev_warn (&pdev->dev,"MSI init failed\n" ); +dev_warn (&h->pdev->dev,"MSI init failed\n" ); } default_int_mode:#endif /* CONFIG_PCI_MSI */ /* if we get here we're going to use the default interrupt mode */ - h->intr[PERF_MODE_INT ] = pdev->irq; + h->intr[PERF_MODE_INT ] = h->pdev->irq; } -static int __devinit hpsa_pci_init (struct ctlr_info *h,struct pci_dev *pdev) +static int __devinit hpsa_pci_init (struct ctlr_info *h) {ushort subsystem_vendor_id, subsystem_device_id, command;u32 board_id, scratchpad =0 ;
@@ -3275,8 +3274,8 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)u32 trans_offset;int i, prod_index, err; - subsystem_vendor_id = pdev->subsystem_vendor; - subsystem_device_id = pdev->subsystem_device; + subsystem_vendor_id = h->pdev->subsystem_vendor; + subsystem_device_id = h->pdev->subsystem_device; board_id = (((u32) (subsystem_device_id <<16 ) &0xffff0000 ) | subsystem_vendor_id);
@@ -3290,7 +3289,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) prod_index--;if (subsystem_vendor_id !=PCI_VENDOR_ID_HP || !hpsa_allow_any) { -dev_warn (&pdev->dev,"unrecognized board ID:" +dev_warn (&h->pdev->dev,"unrecognized board ID:" " 0x%08lx, ignoring.\n" , (unsigned long ) board_id);return -ENODEV ;
@@ -3299,41 +3298,42 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)/* check to see if controller has been disabled * BEFORE trying to enable it */ - (void )pci_read_config_word (pdev,PCI_COMMAND , &command); + (void )pci_read_config_word (h->pdev,PCI_COMMAND , &command);if (!(command &0x02 )) { -dev_warn (&pdev->dev,"controller appears to be disabled\n" ); +dev_warn (&h->pdev->dev,"controller appears to be disabled\n" );return -ENODEV ; } - err =pci_enable_device (pdev); + err =pci_enable_device (h->pdev);if (err) { -dev_warn (&pdev->dev,"unable to enable PCI device\n" ); +dev_warn (&h->pdev->dev,"unable to enable PCI device\n" );return err; } - err =pci_request_regions (pdev,"hpsa" ); + err =pci_request_regions (h->pdev,"hpsa" );if (err) { -dev_err (&pdev->dev,"cannot obtain PCI resources, aborting\n" ); +dev_err (&h->pdev->dev, +"cannot obtain PCI resources, aborting\n" );return err; }/* If the kernel supports MSI/MSI-X we will try to enable that, * else we use the IO-APIC interrupt assigned to us by system ROM. */ -hpsa_interrupt_mode (h, pdev, board_id); +hpsa_interrupt_mode (h, board_id);/* find the memory BAR */ for (i =0 ; i <DEVICE_COUNT_RESOURCE ; i++) { -if (pci_resource_flags (pdev, i) &IORESOURCE_MEM ) +if (pci_resource_flags (h->pdev, i) &IORESOURCE_MEM )break ; }if (i ==DEVICE_COUNT_RESOURCE ) { -dev_warn (&pdev->dev,"no memory BAR found\n" ); +dev_warn (&h->pdev->dev,"no memory BAR found\n" ); err = -ENODEV ; goto err_out_free_res; } - h->paddr =pci_resource_start (pdev, i);/* addressing mode bits + h->paddr =pci_resource_start (h->pdev, i);/* addressing mode bits * already removed */
@@ -3347,7 +3347,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)msleep (HPSA_BOARD_READY_POLL_INTERVAL_MSECS ); }if (scratchpad !=HPSA_FIRMWARE_READY ) { -dev_warn (&pdev->dev,"board not ready, timed out.\n" ); +dev_warn (&h->pdev->dev,"board not ready, timed out.\n" ); err = -ENODEV ; goto err_out_free_res; }
@@ -3355,20 +3355,20 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)/* get the address index number */ cfg_base_addr =readl (h->vaddr +SA5_CTCFG_OFFSET ); cfg_base_addr &= (u32 )0x0000ffff ; - cfg_base_addr_index =find_PCI_BAR_index (pdev, cfg_base_addr); + cfg_base_addr_index =find_PCI_BAR_index (h->pdev, cfg_base_addr);if (cfg_base_addr_index ==-1 ) { -dev_warn (&pdev->dev,"cannot find cfg_base_addr_index\n" ); +dev_warn (&h->pdev->dev,"cannot find cfg_base_addr_index\n" ); err = -ENODEV ; goto err_out_free_res; } cfg_offset =readl (h->vaddr +SA5_CTMEM_OFFSET ); - h->cfgtable =remap_pci_mem (pci_resource_start (pdev, + h->cfgtable =remap_pci_mem (pci_resource_start (h->pdev, cfg_base_addr_index) + cfg_offset,sizeof (h->cfgtable));/* Find performant mode table. */ trans_offset =readl (&(h->cfgtable->TransMethodOffset)); - h->transtable =remap_pci_mem (pci_resource_start (pdev, + h->transtable =remap_pci_mem (pci_resource_start (h->pdev, cfg_base_addr_index)+cfg_offset+trans_offset,sizeof (*h->transtable));
@@ -3400,7 +3400,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) (readb(&h->cfgtable->Signature[1]) != 'I') || (readb(&h->cfgtable->Signature[2]) != 'S') || (readb(&h->cfgtable->Signature[3]) != 'S')) { -dev_warn (&pdev->dev,"not a valid CISS config table\n" ); +dev_warn (&h->pdev->dev,"not a valid CISS config table\n" ); err = -ENODEV ; goto err_out_free_res; }
@@ -3442,11 +3442,12 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) }#ifdef HPSA_DEBUG -print_cfg_table (&pdev->dev, h->cfgtable); +print_cfg_table (&h->pdev->dev, h->cfgtable);#endif /* HPSA_DEBUG */ if (!(readl (&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { -dev_warn (&pdev->dev,"unable to get board into simple mode\n" ); +dev_warn (&h->pdev->dev, +"unable to get board into simple mode\n" ); err = -ENODEV ; goto err_out_free_res; }
@@ -3457,7 +3458,7 @@ err_out_free_res:* Deliberately omit pci_disable_device(): it does something nasty to * Smart Array controllers that pci_enable_device does not undo */ -pci_release_regions (pdev); +pci_release_regions (h->pdev);return err; }
@@ -3515,17 +3516,17 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,if (!h)return -ENOMEM ; + h->pdev = pdev; h->busy_initializing =1 ;INIT_HLIST_HEAD (&h->cmpQ);INIT_HLIST_HEAD (&h->reqQ); - rc =hpsa_pci_init (h, pdev); + rc =hpsa_pci_init (h);if (rc !=0 ) goto clean1;sprintf (h->devname,"hpsa%d" , number_of_controllers); h->ctlr = number_of_controllers; number_of_controllers++; - h->pdev = pdev;/* configure PCI DMA stuff */ rc =pci_set_dma_mask (pdev,DMA_BIT_MASK (64 ));
PATCH 2/24 hpsa: factor out hpsa_lookup_board_id
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_lookup_board_id
--- drivers/scsi/hpsa.c | 58 +++++++++++++++++++++++++++------------------------ 1 files changed, 31 insertions(+), 27 deletions(-)
drivers/scsi/hpsa.c +31 -27
@@ -3264,37 +3264,44 @@ default_int_mode: h->intr[PERF_MODE_INT ] = h->pdev->irq; } +static int __devinit hpsa_lookup_board_id (struct pci_dev *pdev,u32 *board_id) +{ +int i; +u32 subsystem_vendor_id, subsystem_device_id; + + subsystem_vendor_id = pdev->subsystem_vendor; + subsystem_device_id = pdev->subsystem_device; + *board_id = ((subsystem_device_id <<16 ) &0xffff0000 ) | + subsystem_vendor_id; + +for (i =0 ; i <ARRAY_SIZE (products); i++) +if (*board_id == products[i].board_id) +return i; + +if (subsystem_vendor_id !=PCI_VENDOR_ID_HP || !hpsa_allow_any) { +dev_warn (&pdev->dev,"unrecognized board ID: " +"0x%08x, ignoring.\n" , *board_id); +return -ENODEV ; + } +return ARRAY_SIZE (products) -1 ;/* generic unknown smart array */ +} +static int __devinit hpsa_pci_init (struct ctlr_info *h) { -ushort subsystem_vendor_id, subsystem_device_id, command; -u32 board_id, scratchpad =0 ; +ushort command; +u32 scratchpad =0 ;u64 cfg_offset;u32 cfg_base_addr;u64 cfg_base_addr_index;u32 trans_offset;int i, prod_index, err; - subsystem_vendor_id = h->pdev->subsystem_vendor; - subsystem_device_id = h->pdev->subsystem_device; - board_id = (((u32) (subsystem_device_id <<16 ) &0xffff0000 ) | - subsystem_vendor_id); - -for (i =0 ; i <ARRAY_SIZE (products); i++) -if (board_id == products[i].board_id) -break ; - - prod_index = i; + prod_index =hpsa_lookup_board_id (h->pdev, &h->board_id); +if (prod_index <0 ) +return -ENODEV ; + h->product_name = products[prod_index].product_name; + h->access = *(products[prod_index].access); -if (prod_index ==ARRAY_SIZE (products)) { - prod_index--; -if (subsystem_vendor_id !=PCI_VENDOR_ID_HP || - !hpsa_allow_any) { -dev_warn (&h->pdev->dev,"unrecognized board ID:" -" 0x%08lx, ignoring.\n" , - (unsigned long ) board_id); -return -ENODEV ; - } - }/* check to see if controller has been disabled * BEFORE trying to enable it */
@@ -3320,7 +3327,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)/* If the kernel supports MSI/MSI-X we will try to enable that, * else we use the IO-APIC interrupt assigned to us by system ROM. */ -hpsa_interrupt_mode (h, board_id); +hpsa_interrupt_mode (h, h->board_id);/* find the memory BAR */ for (i =0 ; i <DEVICE_COUNT_RESOURCE ; i++) {
@@ -3372,7 +3379,6 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) cfg_base_addr_index)+cfg_offset+trans_offset, sizeof(*h->transtable)); - h->board_id = board_id; h->max_commands =readl (&(h->cfgtable->MaxPerformantModeCommands)); h->maxsgentries =readl (&(h->cfgtable->MaxScatterGatherElements));
@@ -3391,8 +3397,6 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) h->chainsize =0 ; } - h->product_name = products[prod_index].product_name; - h->access = *(products[prod_index].access);/* Allow room for some ioctls */ h->nr_cmds = h->max_commands -4 ;
@@ -3418,7 +3422,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)* An ASIC bug may result in a prefetch beyond * physical memory. */ -if (board_id ==0x3225103C ) { +if (h->board_id ==0x3225103C ) {u32 dma_prefetch; dma_prefetch =readl (h->vaddr +I2O_DMA1_CFG ); dma_prefetch |=0x8000 ;
PATCH 3/24 hpsa: factor out hpsa_board_disabled
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_board_disabled
--- drivers/scsi/hpsa.c | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-)
drivers/scsi/hpsa.c +9 -7
@@ -3286,9 +3286,16 @@ static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)return ARRAY_SIZE (products) -1 ;/* generic unknown smart array */ } +static inline bool hpsa_board_disabled (struct pci_dev *pdev) +{ +u16 command; + + (void )pci_read_config_word (pdev,PCI_COMMAND , &command); +return ((command &PCI_COMMAND_MEMORY ) ==0 ); +} +static int __devinit hpsa_pci_init (struct ctlr_info *h) { -ushort command;u32 scratchpad =0 ;u64 cfg_offset;u32 cfg_base_addr;
@@ -3302,15 +3309,10 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) h->product_name = products[prod_index].product_name; h->access = *(products[prod_index].access); -/* check to see if controller has been disabled -* BEFORE trying to enable it -*/ - (void )pci_read_config_word (h->pdev,PCI_COMMAND , &command); -if (!(command &0x02 )) { +if (hpsa_board_disabled (h->pdev)) {dev_warn (&h->pdev->dev,"controller appears to be disabled\n" );return -ENODEV ; } - err =pci_enable_device (h->pdev);if (err) {dev_warn (&h->pdev->dev,"unable to enable PCI device\n" );
PATCH 4/24 hpsa: remove redundant board_id parameter from hpsa_interrupt_mode
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: remove redundant board_id parameter from hpsa_interrupt_mode and delete duplicated comment
--- drivers/scsi/hpsa.c | 13 ++++--------- 1 files changed, 4 insertions(+), 9 deletions(-)
drivers/scsi/hpsa.c +4 -9
@@ -3217,7 +3217,7 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)* controllers that are capable. If not, we use IO-APIC mode. */ -static void __devinit hpsa_interrupt_mode (struct ctlr_info *h,u32 board_id) +static void __devinit hpsa_interrupt_mode (struct ctlr_info *h) {#ifdef CONFIG_PCI_MSI int err;
@@ -3226,9 +3226,8 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, u32 board_id) };/* Some boards advertise MSI but don't really support it */ -if ((board_id ==0x40700E11 ) || - (board_id ==0x40800E11 ) || - (board_id ==0x40820E11 ) || (board_id ==0x40830E11 )) +if ((h->board_id ==0x40700E11 ) || (h->board_id ==0x40800E11 ) || + (h->board_id ==0x40820E11 ) || (h->board_id ==0x40830E11 )) goto default_int_mode;if (pci_find_capability (h->pdev,PCI_CAP_ID_MSIX )) {dev_info (&h->pdev->dev,"MSIX\n" );
@@ -3325,11 +3324,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) "cannot obtain PCI resources, aborting\n");return err; } - -/* If the kernel supports MSI/MSI-X we will try to enable that, -* else we use the IO-APIC interrupt assigned to us by system ROM. -*/ -hpsa_interrupt_mode (h, h->board_id); +hpsa_interrupt_mode (h);/* find the memory BAR */ for (i =0 ; i <DEVICE_COUNT_RESOURCE ; i++) {
PATCH 5/24 hpsa: factor out hpsa_find_memory_BAR
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_find_memory_BAR
--- drivers/scsi/hpsa.c | 34 +++++++++++++++++++--------------- 1 files changed, 19 insertions(+), 15 deletions(-)
drivers/scsi/hpsa.c +19 -15
@@ -3293,6 +3293,23 @@ static inline bool hpsa_board_disabled(struct pci_dev *pdev)return ((command &PCI_COMMAND_MEMORY ) ==0 ); } +static int __devinit hpsa_pci_find_memory_BAR (struct ctlr_info *h, +unsigned long *memory_bar) +{ +int i; + +for (i =0 ; i <DEVICE_COUNT_RESOURCE ; i++) +if (pci_resource_flags (h->pdev, i) &IORESOURCE_MEM ) { +/* addressing mode bits already removed */ + *memory_bar =pci_resource_start (h->pdev, i); +dev_dbg (&h->pdev->dev,"memory BAR = %lx\n" , + *memory_bar); +return 0 ; + } +dev_warn (&h->pdev->dev,"no memory BAR found\n" ); +return -ENODEV ; +} +static int __devinit hpsa_pci_init (struct ctlr_info *h) {u32 scratchpad =0 ;
@@ -3325,22 +3342,9 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)return err; }hpsa_interrupt_mode (h); - -/* find the memory BAR */ -for (i =0 ; i <DEVICE_COUNT_RESOURCE ; i++) { -if (pci_resource_flags (h->pdev, i) &IORESOURCE_MEM ) -break ; - } -if (i ==DEVICE_COUNT_RESOURCE ) { -dev_warn (&h->pdev->dev,"no memory BAR found\n" ); - err = -ENODEV ; + err =hpsa_pci_find_memory_BAR (h, &h->paddr); +if (err) goto err_out_free_res; - } - - h->paddr =pci_resource_start (h->pdev, i);/* addressing mode bits -* already removed -*/ - h->vaddr =remap_pci_mem (h->paddr,0x250 );/* Wait for the board to become ready. */
PATCH 6/24 hpsa: factor out hpsa_wait_for_board_ready
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_wait_for_board_ready
--- drivers/scsi/hpsa.c | 29 +++++++++++++++++------------ 1 files changed, 17 insertions(+), 12 deletions(-)
drivers/scsi/hpsa.c +17 -12
@@ -3310,9 +3310,23 @@ static int __devinit hpsa_pci_find_memory_BAR(struct ctlr_info *h,return -ENODEV ; } +static int __devinit hpsa_wait_for_board_ready (struct ctlr_info *h) +{ +int i; +u32 scratchpad; + +for (i =0 ; i <HPSA_BOARD_READY_ITERATIONS ; i++) { + scratchpad =readl (h->vaddr +SA5_SCRATCHPAD_OFFSET ); +if (scratchpad ==HPSA_FIRMWARE_READY ) +return 0 ; +msleep (HPSA_BOARD_READY_POLL_INTERVAL_MSECS ); + } +dev_warn (&h->pdev->dev,"board not ready, timed out.\n" ); +return -ENODEV ; +} +static int __devinit hpsa_pci_init (struct ctlr_info *h) { -u32 scratchpad =0 ;u64 cfg_offset;u32 cfg_base_addr;u64 cfg_base_addr_index;
@@ -3347,18 +3361,9 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) goto err_out_free_res; h->vaddr =remap_pci_mem (h->paddr,0x250 ); -/* Wait for the board to become ready. */ -for (i =0 ; i <HPSA_BOARD_READY_ITERATIONS ; i++) { - scratchpad =readl (h->vaddr +SA5_SCRATCHPAD_OFFSET ); -if (scratchpad ==HPSA_FIRMWARE_READY ) -break ; -msleep (HPSA_BOARD_READY_POLL_INTERVAL_MSECS ); - } -if (scratchpad !=HPSA_FIRMWARE_READY ) { -dev_warn (&h->pdev->dev,"board not ready, timed out.\n" ); - err = -ENODEV ; + err =hpsa_wait_for_board_ready (h); +if (err) goto err_out_free_res; - }/* get the address index number */ cfg_base_addr =readl (h->vaddr +SA5_CTCFG_OFFSET );
PATCH 7/24 hpsa: factor out hpsa_find_cfgtables
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_find_cfgtables
--- drivers/scsi/hpsa.c | 50 ++++++++++++++++++++++++++++++-------------------- 1 files changed, 30 insertions(+), 20 deletions(-)
drivers/scsi/hpsa.c +30 -20
@@ -3325,12 +3325,39 @@ static int __devinit hpsa_wait_for_board_ready(struct ctlr_info *h)return -ENODEV ; } -static int __devinit hpsa_pci_init (struct ctlr_info *h) +static int __devinit hpsa_find_cfgtables (struct ctlr_info *h) {u64 cfg_offset;u32 cfg_base_addr;u64 cfg_base_addr_index;u32 trans_offset; + +/* get the address index number */ + cfg_base_addr =readl (h->vaddr +SA5_CTCFG_OFFSET ); + cfg_base_addr &= (u32 )0x0000ffff ; + cfg_base_addr_index =find_PCI_BAR_index (h->pdev, cfg_base_addr); +if (cfg_base_addr_index ==-1 ) { +dev_warn (&h->pdev->dev,"cannot find cfg_base_addr_index\n" ); +return -ENODEV ; + } + cfg_offset =readl (h->vaddr +SA5_CTMEM_OFFSET ); + h->cfgtable =remap_pci_mem (pci_resource_start (h->pdev, + cfg_base_addr_index) + cfg_offset, +sizeof (h->cfgtable)); +if (!h->cfgtable) +return -ENOMEM ; +/* Find performant mode table. */ + trans_offset =readl (&(h->cfgtable->TransMethodOffset)); + h->transtable =remap_pci_mem (pci_resource_start (h->pdev, + cfg_base_addr_index)+cfg_offset+trans_offset, +sizeof (*h->transtable)); +if (!h->transtable) +return -ENOMEM ; +return 0 ; +} + +static int __devinit hpsa_pci_init (struct ctlr_info *h) +{int i, prod_index, err; prod_index =hpsa_lookup_board_id (h->pdev, &h->board_id);
@@ -3364,26 +3391,9 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) err =hpsa_wait_for_board_ready (h);if (err) goto err_out_free_res; - -/* get the address index number */ - cfg_base_addr =readl (h->vaddr +SA5_CTCFG_OFFSET ); - cfg_base_addr &= (u32 )0x0000ffff ; - cfg_base_addr_index =find_PCI_BAR_index (h->pdev, cfg_base_addr); -if (cfg_base_addr_index ==-1 ) { -dev_warn (&h->pdev->dev,"cannot find cfg_base_addr_index\n" ); - err = -ENODEV ; + err =hpsa_find_cfgtables (h); +if (err) goto err_out_free_res; - } - - cfg_offset =readl (h->vaddr +SA5_CTMEM_OFFSET ); - h->cfgtable =remap_pci_mem (pci_resource_start (h->pdev, - cfg_base_addr_index) + cfg_offset, -sizeof (h->cfgtable)); -/* Find performant mode table. */ - trans_offset =readl (&(h->cfgtable->TransMethodOffset)); - h->transtable =remap_pci_mem (pci_resource_start (h->pdev, - cfg_base_addr_index)+cfg_offset+trans_offset, -sizeof (*h->transtable)); h->max_commands =readl (&(h->cfgtable->MaxPerformantModeCommands)); h->maxsgentries =readl (&(h->cfgtable->MaxScatterGatherElements));
PATCH 8/24 hpsa: fix leak of ioremapped memory
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: fix leak of ioremapped memory
in hpsa_pci_init error path.
--- drivers/scsi/hpsa.c | 13 ++++++++++++- 1 files changed, 12 insertions(+), 1 deletions(-)
drivers/scsi/hpsa.c +12 -1
@@ -3387,7 +3387,10 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)if (err) goto err_out_free_res; h->vaddr =remap_pci_mem (h->paddr,0x250 ); - +if (!h->vaddr) { + err = -ENOMEM ; + goto err_out_free_res; + } err =hpsa_wait_for_board_ready (h);if (err) goto err_out_free_res;
@@ -3474,6 +3477,12 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)return 0 ; err_out_free_res: +if (h->transtable) +iounmap (h->transtable); +if (h->cfgtable) +iounmap (h->cfgtable); +if (h->vaddr) +iounmap (h->vaddr);/* * Deliberately omit pci_disable_device(): it does something nasty to * Smart Array controllers that pci_enable_device does not undo
@@ -3692,6 +3701,8 @@ static void __devexit hpsa_remove_one(struct pci_dev *pdev)hpsa_unregister_scsi (h);/* unhook from SCSI subsystem */ hpsa_shutdown (pdev);iounmap (h->vaddr); +iounmap (h->transtable); +iounmap (h->cfgtable);hpsa_free_sg_chain_blocks (h); pci_free_consistent(h->pdev, h->nr_cmds * sizeof(struct CommandList),
Re: [PATCH 08/24] hpsa: fix leak of ioremapped memory
Quoted 4 lines · Stephen M. Cameron
From: Stephen M. Cameron <[email protected]>
hpsa: fix leak of ioremapped memory
inhpsa_pci_initerror path.
If you had used devres to track your resources you got this for free.
drivers/scsi/hpsa.c static int __devinit hpsa_pci_init(struct ctlr_info · line 3485
Quoted 10 lines
drivers/scsi/hpsa.c +6
-0@@ -3474,6 +3477,12 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) return 0; err_out_free_res: +if (h->transtable) +iounmap (h->transtable); +if (h->cfgtable) +iounmap (h->cfgtable); +if (h->vaddr) +iounmap (h->vaddr);
I wonder if that shouldn't use pci_iomap() instead. Also the page aligning tricks in remap_pci_mem() look a bit dubious to me. If your pci BAR is >= PAGE_SIZE this isn't needed at all anyway since those mappings are aligned to at least their size in physical address space anyway and the logical address shouldn't matter for the driver.
Eike
Re: [PATCH 08/24] hpsa: fix leak of ioremapped memory
Quoted 8 lines · Rolf Eike Beer
Quoted 4 lines · Stephen M. Cameron
From: Stephen M. Cameron <[email protected]>
hpsa: fix leak of ioremapped memory
inhpsa_pci_initerror path.If you had used devres to track your resources you got this for free.
Thanks, I was unaware of devres. I'll look into it.
Quoted 16 lines
drivers/scsi/hpsa.c static int __devinit hpsa_pci_init(struct ctlr_info · line 3485
Quoted 10 lines
drivers/scsi/hpsa.c +6
-0@@ -3474,6 +3477,12 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) return 0; err_out_free_res: +if (h->transtable) +iounmap (h->transtable); +if (h->cfgtable) +iounmap (h->cfgtable); +if (h->vaddr) +iounmap (h->vaddr);I wonder if that shouldn't use
pci_iomap()instead. Also the page aligning tricks inremap_pci_mem()look a bit dubious to me. If your pci BAR is >=PAGE_SIZEthis isn't needed at all anyway since those mappings are aligned to at least their size in physical address space anyway and the logical address shouldn't matter for the driver.
Ok, I'll look into these as well.
Quoted 2 lines
Eike
PATCH 9/24 hpsa: hpsa factor out hpsa_find_board_params
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: hpsa factor out hpsa_find_board_params
--- drivers/scsi/hpsa.c | 46 +++++++++++++++++++++++++--------------------- 1 files changed, 25 insertions(+), 21 deletions(-)
drivers/scsi/hpsa.c +25 -21
@@ -3356,6 +3356,30 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)return 0 ; } +/* Interrogate the hardware for some limits: +* max commands, max SG elements without chaining, and with chaining, +* SG chain block size, etc. +*/ +static void __devinit hpsa_find_board_params (struct ctlr_info *h) +{ + h->max_commands =readl (&(h->cfgtable->MaxPerformantModeCommands)); + h->nr_cmds = h->max_commands -4 ;/* Allow room for some ioctls */ + h->maxsgentries =readl (&(h->cfgtable->MaxScatterGatherElements)); +/* +* Limit in-command s/g elements to 32 save dma'able memory. +* Howvever spec says if 0, use 31 +*/ + h->max_cmd_sg_entries =31 ; +if (h->maxsgentries >512 ) { + h->max_cmd_sg_entries =32 ; + h->chainsize = h->maxsgentries - h->max_cmd_sg_entries +1 ; + h->maxsgentries--;/* save one for chain pointer */ + }else { + h->maxsgentries =31 ;/* default to traditional values */ + h->chainsize =0 ; + } +} +static int __devinit hpsa_pci_init (struct ctlr_info *h) {int i, prod_index, err;
@@ -3397,27 +3421,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) err =hpsa_find_cfgtables (h);if (err) goto err_out_free_res; - - h->max_commands =readl (&(h->cfgtable->MaxPerformantModeCommands)); - h->maxsgentries =readl (&(h->cfgtable->MaxScatterGatherElements)); - -/* -* Limit in-command s/g elements to 32 save dma'able memory. -* Howvever spec says if 0, use 31 -*/ - - h->max_cmd_sg_entries =31 ; -if (h->maxsgentries >512 ) { - h->max_cmd_sg_entries =32 ; - h->chainsize = h->maxsgentries - h->max_cmd_sg_entries +1 ; - h->maxsgentries--;/* save one for chain pointer */ - }else { - h->maxsgentries =31 ;/* default to traditional values */ - h->chainsize =0 ; - } - -/* Allow room for some ioctls */ - h->nr_cmds = h->max_commands -4 ; +hpsa_find_board_params (h); if ((readb(&h->cfgtable->Signature[0]) != 'C') || (readb(&h->cfgtable->Signature[1]) != 'I') ||
PATCH 10/24 hpsa: factor out hpsa-CISS-signature-present
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa-CISS-signature-present
--- drivers/scsi/hpsa.c | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-)
drivers/scsi/hpsa.c +13 -5
@@ -3380,6 +3380,18 @@ static void __devinit hpsa_find_board_params(struct ctlr_info *h) } } +static inline bool hpsa_CISS_signature_present (struct ctlr_info *h) +{ +if ((readb (&h->cfgtable->Signature[0 ]) !='C' ) || + (readb (&h->cfgtable->Signature[1 ]) !='I' ) || + (readb (&h->cfgtable->Signature[2 ]) !='S' ) || + (readb (&h->cfgtable->Signature[3 ]) !='S' )) { +dev_warn (&h->pdev->dev,"not a valid CISS config table\n" ); +return false; + } +return true; +} +static int __devinit hpsa_pci_init (struct ctlr_info *h) {int i, prod_index, err;
@@ -3423,11 +3435,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) goto err_out_free_res;hpsa_find_board_params (h); -if ((readb (&h->cfgtable->Signature[0 ]) !='C' ) || - (readb (&h->cfgtable->Signature[1 ]) !='I' ) || - (readb (&h->cfgtable->Signature[2 ]) !='S' ) || - (readb (&h->cfgtable->Signature[3 ]) !='S' )) { -dev_warn (&h->pdev->dev,"not a valid CISS config table\n" ); +if (!hpsa_CISS_signature_present (h)) { err = -ENODEV ; goto err_out_free_res; }
PATCH 11/24 hpsa: factor out hpsa_enable_scsi_prefetch
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_enable_scsi_prefetch
--- drivers/scsi/hpsa.c | 22 +++++++++++++--------- 1 files changed, 13 insertions(+), 9 deletions(-)
drivers/scsi/hpsa.c +13 -9
@@ -3392,6 +3392,18 @@ static inline bool hpsa_CISS_signature_present(struct ctlr_info *h)return true; } +/* Need to enable prefetch in the SCSI core for 6400 in x86 */ +static inline void hpsa_enable_scsi_prefetch (struct ctlr_info *h) +{ +#ifdef CONFIG_X86 +u32 prefetch; + + prefetch =readl (&(h->cfgtable->SCSI_Prefetch)); + prefetch |=0x100 ; +writel (prefetch, &(h->cfgtable->SCSI_Prefetch)); +#endif +} +static int __devinit hpsa_pci_init (struct ctlr_info *h) {int i, prod_index, err;
@@ -3439,15 +3451,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) err = -ENODEV ; goto err_out_free_res; } -#ifdef CONFIG_X86 - { -/* Need to enable prefetch in the SCSI core for 6400 in x86 */ -u32 prefetch; - prefetch =readl (&(h->cfgtable->SCSI_Prefetch)); - prefetch |=0x100 ; -writel (prefetch, &(h->cfgtable->SCSI_Prefetch)); - } -#endif +hpsa_enable_scsi_prefetch (h);/* Disabling DMA prefetch for the P600 * An ASIC bug may result in a prefetch beyond
PATCH 12/24 hpsa: factor out hpsa_p600_dma_prefetch_quirk
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_p600_dma_prefetch_quirk
--- drivers/scsi/hpsa.c | 26 +++++++++++++++----------- 1 files changed, 15 insertions(+), 11 deletions(-)
drivers/scsi/hpsa.c +15 -11
@@ -3404,6 +3404,20 @@ static inline void hpsa_enable_scsi_prefetch(struct ctlr_info *h)#endif } +/* Disable DMA prefetch for the P600. Otherwise an ASIC bug may result +* in a prefetch beyond physical memory. +*/ +static inline void hpsa_p600_dma_prefetch_quirk (struct ctlr_info *h) +{ +u32 dma_prefetch; + +if (h->board_id !=0x3225103C ) +return ; + dma_prefetch =readl (h->vaddr +I2O_DMA1_CFG ); + dma_prefetch |=0x8000 ; +writel (dma_prefetch, h->vaddr +I2O_DMA1_CFG ); +} +static int __devinit hpsa_pci_init (struct ctlr_info *h) {int i, prod_index, err;
@@ -3452,17 +3466,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) goto err_out_free_res; }hpsa_enable_scsi_prefetch (h); - -/* Disabling DMA prefetch for the P600 -* An ASIC bug may result in a prefetch beyond -* physical memory. -*/ -if (h->board_id ==0x3225103C ) { -u32 dma_prefetch; - dma_prefetch =readl (h->vaddr +I2O_DMA1_CFG ); - dma_prefetch |=0x8000 ; -writel (dma_prefetch, h->vaddr +I2O_DMA1_CFG ); - } +hpsa_p600_dma_prefetch_quirk (h); h->max_commands =readl (&(h->cfgtable->CmdsOutMax));/* Update the field, and then ring the doorbell */
PATCH 13/24 hpsa: factor out hpsa_enter_simple_mode
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_enter_simple_mode
--- drivers/scsi/hpsa.c | 62 +++++++++++++++++++++++++++++---------------------- 1 files changed, 35 insertions(+), 27 deletions(-)
drivers/scsi/hpsa.c +35 -27
@@ -3418,9 +3418,41 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h)writel (dma_prefetch, h->vaddr +I2O_DMA1_CFG ); } +static int __devinit hpsa_enter_simple_mode (struct ctlr_info *h) +{ +int i; + + h->max_commands =readl (&(h->cfgtable->CmdsOutMax)); +/* Update the field, and then ring the doorbell */ +writel (CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); +writel (CFGTBL_ChangeReq, h->vaddr +SA5_DOORBELL ); + +/* under certain very rare conditions, this can take awhile. +* (e.g.: hot replace a failed 144GB drive in a RAID 5 set right +* as we enter this code.) +*/ +for (i =0 ; i <MAX_CONFIG_WAIT ; i++) { +if (!(readl (h->vaddr +SA5_DOORBELL ) & CFGTBL_ChangeReq)) +break ; +/* delay and try again */ +msleep (10 ); + } + +#ifdef HPSA_DEBUG +print_cfg_table (&h->pdev->dev, h->cfgtable); +#endif /* HPSA_DEBUG */ + +if (!(readl (&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { +dev_warn (&h->pdev->dev, +"unable to get board into simple mode\n" ); +return -ENODEV ; + } +return 0 ; +} +static int __devinit hpsa_pci_init (struct ctlr_info *h) { -int i, prod_index, err; +int prod_index, err; prod_index =hpsa_lookup_board_id (h->pdev, &h->board_id);if (prod_index <0 )
@@ -3467,33 +3499,9 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) }hpsa_enable_scsi_prefetch (h);hpsa_p600_dma_prefetch_quirk (h); - - h->max_commands =readl (&(h->cfgtable->CmdsOutMax)); -/* Update the field, and then ring the doorbell */ -writel (CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); -writel (CFGTBL_ChangeReq, h->vaddr +SA5_DOORBELL ); - -/* under certain very rare conditions, this can take awhile. -* (e.g.: hot replace a failed 144GB drive in a RAID 5 set right -* as we enter this code.) -*/ -for (i =0 ; i <MAX_CONFIG_WAIT ; i++) { -if (!(readl (h->vaddr +SA5_DOORBELL ) & CFGTBL_ChangeReq)) -break ; -/* delay and try again */ -msleep (10 ); - } - -#ifdef HPSA_DEBUG -print_cfg_table (&h->pdev->dev, h->cfgtable); -#endif /* HPSA_DEBUG */ - -if (!(readl (&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { -dev_warn (&h->pdev->dev, -"unable to get board into simple mode\n" ); - err = -ENODEV ; + err =hpsa_enter_simple_mode (h); +if (err) goto err_out_free_res; - }return 0 ; err_out_free_res:
PATCH 14/24 hpsa: check that simple mode is supported
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: check that simple mode is supported before trying to enter simple mode transport method.
--- drivers/scsi/hpsa.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
drivers/scsi/hpsa.c +5 -0
@@ -3421,6 +3421,11 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h)static int __devinit hpsa_enter_simple_mode (struct ctlr_info *h) {int i; +u32 trans_support; + + trans_support =readl (&(h->cfgtable->TransportSupport)); +if (!(trans_support &SIMPLE_MODE )) +return -ENOTSUPP ; h->max_commands =readl (&(h->cfgtable->CmdsOutMax));/* Update the field, and then ring the doorbell */
PATCH 15/24 hpsa: clean up debug ifdefs
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: clean up debug ifdefsS
--- drivers/scsi/hpsa.c | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-)
drivers/scsi/hpsa.c +2 -6
@@ -3143,9 +3143,9 @@ static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev)* the io functions. * This is for debug only. */ -#ifdef HPSA_DEBUG static void print_cfg_table (struct device *dev,struct CfgTable *tb) { +#ifdef HPSA_DEBUG int i;char temp_name[17 ];
@@ -3175,8 +3175,8 @@ static void print_cfg_table(struct device *dev, struct CfgTable *tb)dev_info (dev," Server Name = %s\n" , temp_name);dev_info (dev," Heartbeat Counter = 0x%x\n\n\n" ,readl (&(tb->HeartBeat))); -}#endif /* HPSA_DEBUG */ +}static int find_PCI_BAR_index (struct pci_dev *pdev,unsigned long pci_bar_addr) {
@@ -3442,11 +3442,7 @@ static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h)/* delay and try again */ msleep (10 ); } - -#ifdef HPSA_DEBUG print_cfg_table (&h->pdev->dev, h->cfgtable); -#endif /* HPSA_DEBUG */ -if (!(readl (&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {dev_warn (&h->pdev->dev,"unable to get board into simple mode\n" );
PATCH 16/24 hpsa: mark hpsa_mark_hpsa_put_ctlr_into_performant_mode as __devinit
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: mark hpsa_mark_hpsa_put_ctlr_into_performant_mode as __devinit
--- drivers/scsi/hpsa.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/hpsa.c +2 -2
@@ -158,7 +158,7 @@ static void check_ioctl_unit_attention(struct ctlr_info *h,/* performant mode helper functions */ static void calc_bucket_map (int *bucket,int num_buckets,int nsgs,int *bucket_map); -static void hpsa_put_ctlr_into_performant_mode (struct ctlr_info *h); +static __devinit void hpsa_put_ctlr_into_performant_mode (struct ctlr_info *h);static inline u32 next_command (struct ctlr_info *h); static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
@@ -3811,7 +3811,7 @@ static void calc_bucket_map(int bucket[], int num_buckets, } } -static void hpsa_put_ctlr_into_performant_mode (struct ctlr_info *h) +static __devinit void hpsa_put_ctlr_into_performant_mode (struct ctlr_info *h) {u32 trans_support;u64 trans_offset;
PATCH 17/24 hpsa: factor out hpsa_wait_for_mode_change_ack
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_wait_for_mode_change_ack
--- drivers/scsi/hpsa.c | 40 +++++++++++++++++----------------------- 1 files changed, 17 insertions(+), 23 deletions(-)
drivers/scsi/hpsa.c +17 -23
@@ -3418,19 +3418,9 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h)writel (dma_prefetch, h->vaddr +I2O_DMA1_CFG ); } -static int __devinit hpsa_enter_simple_mode (struct ctlr_info *h) +static void __devinit hpsa_wait_for_mode_change_ack (struct ctlr_info *h) {int i; -u32 trans_support; - - trans_support =readl (&(h->cfgtable->TransportSupport)); -if (!(trans_support &SIMPLE_MODE )) -return -ENOTSUPP ; - - h->max_commands =readl (&(h->cfgtable->CmdsOutMax)); -/* Update the field, and then ring the doorbell */ -writel (CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); -writel (CFGTBL_ChangeReq, h->vaddr +SA5_DOORBELL );/* under certain very rare conditions, this can take awhile. * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
@@ -3442,6 +3432,21 @@ static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h)/* delay and try again */ msleep (10 ); } +} + +static int __devinit hpsa_enter_simple_mode (struct ctlr_info *h) +{ +u32 trans_support; + + trans_support =readl (&(h->cfgtable->TransportSupport)); +if (!(trans_support &SIMPLE_MODE )) +return -ENOTSUPP ; + + h->max_commands =readl (&(h->cfgtable->CmdsOutMax)); +/* Update the field, and then ring the doorbell */ +writel (CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); +writel (CFGTBL_ChangeReq, h->vaddr +SA5_DOORBELL ); +hpsa_wait_for_mode_change_ack (h);print_cfg_table (&h->pdev->dev, h->cfgtable);if (!(readl (&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { dev_warn(&h->pdev->dev,
@@ -3822,7 +3827,6 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)*/ int bft[8 ] = {5 ,6 ,8 ,10 ,12 ,20 ,28 ,35 };/* for scatter/gathers */ int i =0 ; -int l =0 ;unsigned long register_value; trans_support =readl (&(h->cfgtable->TransportSupport));
@@ -3866,17 +3870,7 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)writel (CFGTBL_Trans_Performant, &(h->cfgtable->HostWrite.TransportRequest));writel (CFGTBL_ChangeReq, h->vaddr +SA5_DOORBELL ); -/* under certain very rare conditions, this can take awhile. -* (e.g.: hot replace a failed 144GB drive in a RAID 5 set right -* as we enter this code.) */ -for (l =0 ; l <MAX_CONFIG_WAIT ; l++) { - register_value =readl (h->vaddr +SA5_DOORBELL ); -if (!(register_value & CFGTBL_ChangeReq)) -break ; -/* delay and try again */ -set_current_state (TASK_INTERRUPTIBLE ); -schedule_timeout (10 ); - } +hpsa_wait_for_mode_change_ack (h); register_value =readl (&(h->cfgtable->TransportActive));if (!(register_value & CFGTBL_Trans_Performant)) { dev_warn(&h->pdev->dev, "unable to get board into"
PATCH 18/24 hpsa: remove unused variable trans_offset
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: remove unused variable trans_offset
--- drivers/scsi/hpsa.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/scsi/hpsa.c +0 -2
@@ -3819,7 +3819,6 @@ static void calc_bucket_map(int bucket[], int num_buckets,static __devinit void hpsa_put_ctlr_into_performant_mode (struct ctlr_info *h) {u32 trans_support; -u64 trans_offset;/* 5 = 1 s/g entry or 4k * 6 = 2 s/g entry or 8k * 8 = 4 s/g entry or 16k
@@ -3854,7 +3853,6 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)memset (h->reply_pool,0 , h->reply_pool_size); h->reply_pool_head = h->reply_pool; - trans_offset =readl (&(h->cfgtable->TransMethodOffset)); bft[7 ] = h->max_sg_entries +4 ;calc_bucket_map (bft,ARRAY_SIZE (bft),32 , h->blockFetchTable);for (i =0 ; i <8 ; i++)
PATCH 19/24 hpsa: factor out hpsa_enter_performant_mode
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: factor out hpsa_enter_performant_mode
--- drivers/scsi/hpsa.c | 54 ++++++++++++++++++++++++++++----------------------- 1 files changed, 30 insertions(+), 24 deletions(-)
drivers/scsi/hpsa.c +30 -24
@@ -3816,36 +3816,16 @@ static void calc_bucket_map(int bucket[], int num_buckets, } } -static __devinit void hpsa_put_ctlr_into_performant_mode (struct ctlr_info *h) +static __devinit void hpsa_enter_performant_mode (struct ctlr_info *h) { -u32 trans_support; +int i; +unsigned long register_value; +int bft[8 ] = {5 ,6 ,8 ,10 ,12 ,20 ,28 ,35 };/* for scatter/gathers */ /* 5 = 1 s/g entry or 4k * 6 = 2 s/g entry or 8k * 8 = 4 s/g entry or 16k * 10 = 6 s/g entry or 24k */ -int bft[8 ] = {5 ,6 ,8 ,10 ,12 ,20 ,28 ,35 };/* for scatter/gathers */ -int i =0 ; -unsigned long register_value; - - trans_support =readl (&(h->cfgtable->TransportSupport)); -if (!(trans_support &PERFORMANT_MODE )) -return ; - - h->max_commands =readl (&(h->cfgtable->MaxPerformantModeCommands)); - h->max_sg_entries =32 ; -/* Performant mode ring buffer and supporting data structures */ - h->reply_pool_size = h->max_commands *sizeof (u64); - h->reply_pool =pci_alloc_consistent (h->pdev, h->reply_pool_size, - &(h->reply_pool_dhandle)); - -/* Need a block fetch table for performant mode */ - h->blockFetchTable =kmalloc (((h->max_sg_entries+1 ) * -sizeof (u32)),GFP_KERNEL ); - -if ((h->reply_pool ==NULL ) - || (h->blockFetchTable ==NULL )) - goto clean_up; h->reply_pool_wraparound =1 ;/* spec: init to 1 */
@@ -3875,6 +3855,32 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) " performant mode\n");return ; } +} + +static __devinit void hpsa_put_ctlr_into_performant_mode (struct ctlr_info *h) +{ +u32 trans_support; + + trans_support =readl (&(h->cfgtable->TransportSupport)); +if (!(trans_support &PERFORMANT_MODE )) +return ; + + h->max_commands =readl (&(h->cfgtable->MaxPerformantModeCommands)); + h->max_sg_entries =32 ; +/* Performant mode ring buffer and supporting data structures */ + h->reply_pool_size = h->max_commands *sizeof (u64); + h->reply_pool =pci_alloc_consistent (h->pdev, h->reply_pool_size, + &(h->reply_pool_dhandle)); + +/* Need a block fetch table for performant mode */ + h->blockFetchTable =kmalloc (((h->max_sg_entries+1 ) * +sizeof (u32)),GFP_KERNEL ); + +if ((h->reply_pool ==NULL ) + || (h->blockFetchTable ==NULL )) + goto clean_up; + +hpsa_enter_performant_mode (h);/* Change the access methods to the performant access methods */ h->access = SA5_performant_access;
PATCH 20/24 hpsa: remove unused firm_ver member of the per-hba structure
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: remove unused firm_ver member of the per-hba structure
--- drivers/scsi/hpsa.c | 6 ------ drivers/scsi/hpsa.h | 1 - 2 files changed, 0 insertions(+), 7 deletions(-)
drivers/scsi/hpsa.c +0 -6
@@ -1440,12 +1440,6 @@ static int hpsa_update_device_info(struct ctlr_info *h, goto bail_out; } -/* As a side effect, record the firmware version number -* if we happen to be talking to the RAID controller. -*/ -if (is_hba_lunid (scsi3addr)) -memcpy (h->firm_ver, &inq_buff[32 ],4 ); - this_device->devtype = (inq_buff[0 ] &0x1f );memcpy (this_device->scsi3addr, scsi3addr,8 ); memcpy(this_device->vendor, &inq_buff[8],
drivers/scsi/hpsa.h +0 -1
@@ -53,7 +53,6 @@ struct ctlr_info {int ctlr;char devname[8 ];char *product_name; -char firm_ver[4 ];/* Firmware version */ struct pci_dev *pdev;u32 board_id;void __iomem *vaddr;
PATCH 21/24 hpsa: Add hpsa.txt to Documentation/scsi
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: Add hpsa.txt to Documentation/scsi
--- Documentation/scsi/hpsa.txt | 100 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 100 insertions(+), 0 deletions(-) create mode 100644 Documentation/scsi/hpsa.txt
Documentation/scsi/hpsa.txt new file +100 -0
@@ -0,0 +1,100 @@ + +HPSA - Hewlett Packard Smart Array driver +----------------------------------------- + +This file describes the hpsa SCSI driver for HP Smart Array controllers. +The hpsa driver is intended to supplant the cciss driver for newer +Smart Array controllers. The hpsa driver is a SCSI driver, while the +cciss driver is a "block" driver. Actually cciss is both a block +driver (for logical drives) AND a SCSI driver (for tape drives). This +"split-brained" design of the cciss driver is a source of excess +complexity and eliminating that complexity is one of the reasons +for hpsa to exist. + +Supported devices: +------------------ + +Smart Array P212 +Smart Array P410 +Smart Array P410i +Smart Array P411 +Smart Array P812 +Smart Array P712m +Smart Array P711m +StorageWorks P1210m + +Additionally, older Smart Arrays may work with the hpsa driver if the kernel +boot parameter "hpsa_allow_any=1" is specified, however these are not tested +nor supported by HP with this driver. For older Smart Arrays, the cciss +driver should still be used. + +HPSA specific entries in /sys +----------------------------- + + In addition to the generic SCSI attributes available in /sys, hpsa supports + the following attributes: + + HPSA specific host attributes: + ------------------------------ + + /sys/class/scsi_host/host*/rescan + + the host "rescan" attribute is a write only attribute. Writing to this + attribute will cause the driver to scan for new, changed, or removed devices + (e.g. hot-plugged tape drives, or newly configured or deleted logical drives, + etc.) and notify the SCSI midlayer of any changes detected. Normally this is + triggered automatically by HP's Array Configuration Utility (either the GUI or + command line variety) so for logical drive changes, the user should not + normally have to use this. It may be useful when hot plugging devices like + tape drives, or entire storage boxes containing pre-configured logical drives. + + HPSA specific disk attributes: + ------------------------------ + + /sys/class/scsi_disk/c:b:t:l/device/unique_id + /sys/class/scsi_disk/c:b:t:l/device/raid_level + /sys/class/scsi_disk/c:b:t:l/device/lunid + + (where c:b:t:l are the controller, bus, target and lun of the device) + + For example: + + root@host:/sys/class/scsi_disk/4:0:0:0/device# cat unique_id + 600508B1001044395355323037570F77 + root@host:/sys/class/scsi_disk/4:0:0:0/device# cat lunid + 0x0000004000000000 + root@host:/sys/class/scsi_disk/4:0:0:0/device# cat raid_level + RAID 0 + +HPSA specific ioctls: +--------------------- + + For compatibility with applications written for the cciss driver, many, but + not all of the ioctls supported by the cciss driver are also supported by the + hpsa driver. The data structures used by these are described in + include/linux/cciss_ioctl.h + + CCISS_DEREGDISK + CCISS_REGNEWDISK + CCISS_REGNEWD + + The above three ioctls all do exactly the same thing, which is to cause the driver + to rescan for new devices. This does exactly the same thing as writing to the + hpsa specific host "rescan" attribute. + + CCISS_GETPCIINFO + + Returns PCI domain, bus, device and function and "board ID" (PCI subsystem ID). + + CCISS_GETDRIVVER + + Returns driver version in three bytes encoded as: + (major_version << 16) | (minor_version << 8) | (subminor_version) + + CCISS_PASSTHRU + CCISS_BIG_PASSTHRU + + Allows "BMIC" and "CISS" commands to be passed through to the Smart Array. + These are used extensively by the HP Array Configuration Utility, SNMP storage + agents, etc. See cciss_vol_status at http://cciss.sf.net for some examples. +
PATCH 22/24 hpsa: expose controller firmware revision via /sys.
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: expose controller firmware revision via /sys.
--- Documentation/scsi/hpsa.txt | 7 +++++++ drivers/scsi/hpsa.c | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 0 deletions(-)
Documentation/scsi/hpsa.txt +7 -0
@@ -38,6 +38,7 @@ HPSA specific entries in /sys ------------------------------ /sys/class/scsi_host/host*/rescan + /sys/class/scsi_host/host*/firmware_revision the host "rescan" attribute is a write only attribute. Writing to this attribute will cause the driver to scan for new, changed, or removed devices
@@ -48,6 +49,12 @@ HPSA specific entries in /sys normally have to use this. It may be useful when hot plugging devices like tape drives, or entire storage boxes containing pre-configured logical drives. + The "firmware_revision" attribute contains the firmware version of the Smart Array. + For example: + + root@host:/sys/class/scsi_host/host4# cat firmware_revision + 7.14 + HPSA specific disk attributes: ------------------------------
drivers/scsi/hpsa.c +20 -0
@@ -148,6 +148,8 @@ static ssize_t lunid_show(struct device *dev, struct device_attribute *attr, char *buf);static ssize_t unique_id_show (struct device *dev,struct device_attribute *attr,char *buf); +static ssize_t host_show_firmware_revision (struct device *dev, +struct device_attribute *attr,char *buf);static void hpsa_update_scsi_devices (struct ctlr_info *h,int hostno);static ssize_t host_store_rescan (struct device *dev,struct device_attribute *attr,const char *buf,size_t count);
@@ -165,6 +167,8 @@ static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL); static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); +static DEVICE_ATTR(firmware_revision, S_IRUGO, + host_show_firmware_revision, NULL);static struct device_attribute *hpsa_sdev_attrs[] = { &dev_attr_raid_level,
@@ -175,6 +179,7 @@ static struct device_attribute *hpsa_sdev_attrs[] = {static struct device_attribute *hpsa_shost_attrs[] = { &dev_attr_rescan, + &dev_attr_firmware_revision,NULL , };
@@ -260,6 +265,21 @@ static ssize_t host_store_rescan(struct device *dev,return count; } +static ssize_t host_show_firmware_revision (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct ctlr_info *h; +struct Scsi_Host *shost =class_to_shost (dev); +unsigned char *fwrev; + + h =shost_to_hba (shost); +if (!h->hba_inquiry_data) +return 0 ; + fwrev = &h->hba_inquiry_data[32 ]; +return snprintf (buf,20 ,"%c%c%c%c\n" , + fwrev[0 ], fwrev[1 ], fwrev[2 ], fwrev[3 ]); +} +/* Enqueuing and dequeuing functions for cmdlists. */ static inline void addQ (struct hlist_head *list,struct CommandList *c) {
PATCH 23/24 hpsa: fix block fetch table problem.
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: fix block fetch table problem.
We have 32 (MAXSGENTRIES) scatter gather elements embedded in the command. With all these, the total command size is about 576 bytes. However, the last entry in the block fetch table is 35. (the block fetch table contains the number of 16-byte chunks the firmware needs to fetch for a given number of scatter gather elements.) 35 * 16 = 560 bytes, which isn't enough. It needs to be
36. (36 * 16 == 576) or, MAXSGENTRIES + 4. (plus 4 because there's a bunch of stuff at the front of the command before the first scatter gather element that takes up 4 * 16 bytes.) Without this fix, the controller may have to perform two DMA operations to fetch the command since the first one may not get the whole thing.
--- drivers/scsi/hpsa.c | 21 ++++++++++++++++++++- 1 files changed, 20 insertions(+), 1 deletions(-)
drivers/scsi/hpsa.c +20 -1
@@ -3834,7 +3834,26 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h) {int i;unsigned long register_value; -int bft[8 ] = {5 ,6 ,8 ,10 ,12 ,20 ,28 ,35 };/* for scatter/gathers */ + +/* This is a bit complicated. There are 8 registers on +* the controller which we write to to tell it 8 different +* sizes of commands which there may be. It's a way of +* reducing the DMA done to fetch each command. Encoded into +* each command's tag are 3 bits which communicate to the controller +* which of the eight sizes that command fits within. The size of +* each command depends on how many scatter gather entries there are. +* Each SG entry requires 16 bytes. The eight registers are programmed +* with the number of 16-byte blocks a command of that size requires. +* The smallest command possible requires 5 such 16 byte blocks. +* the largest command possible requires MAXSGENTRIES + 4 16-byte +* blocks. Note, this only extends to the SG entries contained +* within the command block, and does not extend to chained blocks +* of SG elements. bft[] contains the eight values we write to +* the registers. They are not evenly distributed, but have more +* sizes for small commands, and fewer sizes for larger commands. +*/ +int bft[8 ] = {5 ,6 ,8 ,10 ,12 ,20 ,28 ,MAXSGENTRIES +4 }; +BUILD_BUG_ON (28 >MAXSGENTRIES +4 );/* 5 = 1 s/g entry or 4k * 6 = 2 s/g entry or 8k * 8 = 4 s/g entry or 16k
PATCH 24/24 hpsa: add entry to MAINTAINERS
In reply to Stephen M. CameronFrom: Stephen M. Cameron <[email protected]>
hpsa: add entry to MAINTAINERS
--- MAINTAINERS | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
MAINTAINERS +8 -0
@@ -2569,6 +2569,14 @@ S: Maintained F: Documentation/blockdev/cpqarray.txt F: drivers/block/cpqarray.* +HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa) +M: Stephen M. Cameron <[email protected]> +L: [email protected] +S: Supported +F: Documentation/scsi/hpsa.txt +F: drivers/scsi/hpsa*.[ch] +F: include/linux/cciss*.h + HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss) M: Mike Miller <[email protected]> L: [email protected]