diff options
-rw-r--r-- | drivers/scsi/hpsa.c | 134 | ||||
-rw-r--r-- | drivers/scsi/hpsa.h | 4 | ||||
-rw-r--r-- | drivers/scsi/hpsa_cmd.h | 7 |
3 files changed, 131 insertions, 14 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 2e1edce9b20e..183d3a43c280 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
@@ -187,7 +187,6 @@ static struct scsi_host_template hpsa_driver_template = { | |||
187 | .scan_finished = hpsa_scan_finished, | 187 | .scan_finished = hpsa_scan_finished, |
188 | .change_queue_depth = hpsa_change_queue_depth, | 188 | .change_queue_depth = hpsa_change_queue_depth, |
189 | .this_id = -1, | 189 | .this_id = -1, |
190 | .sg_tablesize = MAXSGENTRIES, | ||
191 | .use_clustering = ENABLE_CLUSTERING, | 190 | .use_clustering = ENABLE_CLUSTERING, |
192 | .eh_device_reset_handler = hpsa_eh_device_reset_handler, | 191 | .eh_device_reset_handler = hpsa_eh_device_reset_handler, |
193 | .ioctl = hpsa_ioctl, | 192 | .ioctl = hpsa_ioctl, |
@@ -844,6 +843,76 @@ static void hpsa_scsi_setup(struct ctlr_info *h) | |||
844 | spin_lock_init(&h->devlock); | 843 | spin_lock_init(&h->devlock); |
845 | } | 844 | } |
846 | 845 | ||
846 | static void hpsa_free_sg_chain_blocks(struct ctlr_info *h) | ||
847 | { | ||
848 | int i; | ||
849 | |||
850 | if (!h->cmd_sg_list) | ||
851 | return; | ||
852 | for (i = 0; i < h->nr_cmds; i++) { | ||
853 | kfree(h->cmd_sg_list[i]); | ||
854 | h->cmd_sg_list[i] = NULL; | ||
855 | } | ||
856 | kfree(h->cmd_sg_list); | ||
857 | h->cmd_sg_list = NULL; | ||
858 | } | ||
859 | |||
860 | static int hpsa_allocate_sg_chain_blocks(struct ctlr_info *h) | ||
861 | { | ||
862 | int i; | ||
863 | |||
864 | if (h->chainsize <= 0) | ||
865 | return 0; | ||
866 | |||
867 | h->cmd_sg_list = kzalloc(sizeof(*h->cmd_sg_list) * h->nr_cmds, | ||
868 | GFP_KERNEL); | ||
869 | if (!h->cmd_sg_list) | ||
870 | return -ENOMEM; | ||
871 | for (i = 0; i < h->nr_cmds; i++) { | ||
872 | h->cmd_sg_list[i] = kmalloc(sizeof(*h->cmd_sg_list[i]) * | ||
873 | h->chainsize, GFP_KERNEL); | ||
874 | if (!h->cmd_sg_list[i]) | ||
875 | goto clean; | ||
876 | } | ||
877 | return 0; | ||
878 | |||
879 | clean: | ||
880 | hpsa_free_sg_chain_blocks(h); | ||
881 | return -ENOMEM; | ||
882 | } | ||
883 | |||
884 | static void hpsa_map_sg_chain_block(struct ctlr_info *h, | ||
885 | struct CommandList *c) | ||
886 | { | ||
887 | struct SGDescriptor *chain_sg, *chain_block; | ||
888 | u64 temp64; | ||
889 | |||
890 | chain_sg = &c->SG[h->max_cmd_sg_entries - 1]; | ||
891 | chain_block = h->cmd_sg_list[c->cmdindex]; | ||
892 | chain_sg->Ext = HPSA_SG_CHAIN; | ||
893 | chain_sg->Len = sizeof(*chain_sg) * | ||
894 | (c->Header.SGTotal - h->max_cmd_sg_entries); | ||
895 | temp64 = pci_map_single(h->pdev, chain_block, chain_sg->Len, | ||
896 | PCI_DMA_TODEVICE); | ||
897 | chain_sg->Addr.lower = (u32) (temp64 & 0x0FFFFFFFFULL); | ||
898 | chain_sg->Addr.upper = (u32) ((temp64 >> 32) & 0x0FFFFFFFFULL); | ||
899 | } | ||
900 | |||
901 | static void hpsa_unmap_sg_chain_block(struct ctlr_info *h, | ||
902 | struct CommandList *c) | ||
903 | { | ||
904 | struct SGDescriptor *chain_sg; | ||
905 | union u64bit temp64; | ||
906 | |||
907 | if (c->Header.SGTotal <= h->max_cmd_sg_entries) | ||
908 | return; | ||
909 | |||
910 | chain_sg = &c->SG[h->max_cmd_sg_entries - 1]; | ||
911 | temp64.val32.lower = chain_sg->Addr.lower; | ||
912 | temp64.val32.upper = chain_sg->Addr.upper; | ||
913 | pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE); | ||
914 | } | ||
915 | |||
847 | static void complete_scsi_command(struct CommandList *cp, | 916 | static void complete_scsi_command(struct CommandList *cp, |
848 | int timeout, u32 tag) | 917 | int timeout, u32 tag) |
849 | { | 918 | { |
@@ -860,6 +929,8 @@ static void complete_scsi_command(struct CommandList *cp, | |||
860 | h = cp->h; | 929 | h = cp->h; |
861 | 930 | ||
862 | scsi_dma_unmap(cmd); /* undo the DMA mappings */ | 931 | scsi_dma_unmap(cmd); /* undo the DMA mappings */ |
932 | if (cp->Header.SGTotal > h->max_cmd_sg_entries) | ||
933 | hpsa_unmap_sg_chain_block(h, cp); | ||
863 | 934 | ||
864 | cmd->result = (DID_OK << 16); /* host byte */ | 935 | cmd->result = (DID_OK << 16); /* host byte */ |
865 | cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ | 936 | cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ |
@@ -1064,6 +1135,7 @@ static int hpsa_scsi_detect(struct ctlr_info *h) | |||
1064 | sh->max_id = HPSA_MAX_LUN; | 1135 | sh->max_id = HPSA_MAX_LUN; |
1065 | sh->can_queue = h->nr_cmds; | 1136 | sh->can_queue = h->nr_cmds; |
1066 | sh->cmd_per_lun = h->nr_cmds; | 1137 | sh->cmd_per_lun = h->nr_cmds; |
1138 | sh->sg_tablesize = h->maxsgentries; | ||
1067 | h->scsi_host = sh; | 1139 | h->scsi_host = sh; |
1068 | sh->hostdata[0] = (unsigned long) h; | 1140 | sh->hostdata[0] = (unsigned long) h; |
1069 | sh->irq = h->intr[PERF_MODE_INT]; | 1141 | sh->irq = h->intr[PERF_MODE_INT]; |
@@ -1765,16 +1837,17 @@ out: | |||
1765 | * dma mapping and fills in the scatter gather entries of the | 1837 | * dma mapping and fills in the scatter gather entries of the |
1766 | * hpsa command, cp. | 1838 | * hpsa command, cp. |
1767 | */ | 1839 | */ |
1768 | static int hpsa_scatter_gather(struct pci_dev *pdev, | 1840 | static int hpsa_scatter_gather(struct ctlr_info *h, |
1769 | struct CommandList *cp, | 1841 | struct CommandList *cp, |
1770 | struct scsi_cmnd *cmd) | 1842 | struct scsi_cmnd *cmd) |
1771 | { | 1843 | { |
1772 | unsigned int len; | 1844 | unsigned int len; |
1773 | struct scatterlist *sg; | 1845 | struct scatterlist *sg; |
1774 | u64 addr64; | 1846 | u64 addr64; |
1775 | int use_sg, i; | 1847 | int use_sg, i, sg_index, chained; |
1848 | struct SGDescriptor *curr_sg; | ||
1776 | 1849 | ||
1777 | BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES); | 1850 | BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); |
1778 | 1851 | ||
1779 | use_sg = scsi_dma_map(cmd); | 1852 | use_sg = scsi_dma_map(cmd); |
1780 | if (use_sg < 0) | 1853 | if (use_sg < 0) |
@@ -1783,15 +1856,33 @@ static int hpsa_scatter_gather(struct pci_dev *pdev, | |||
1783 | if (!use_sg) | 1856 | if (!use_sg) |
1784 | goto sglist_finished; | 1857 | goto sglist_finished; |
1785 | 1858 | ||
1859 | curr_sg = cp->SG; | ||
1860 | chained = 0; | ||
1861 | sg_index = 0; | ||
1786 | scsi_for_each_sg(cmd, sg, use_sg, i) { | 1862 | scsi_for_each_sg(cmd, sg, use_sg, i) { |
1863 | if (i == h->max_cmd_sg_entries - 1 && | ||
1864 | use_sg > h->max_cmd_sg_entries) { | ||
1865 | chained = 1; | ||
1866 | curr_sg = h->cmd_sg_list[cp->cmdindex]; | ||
1867 | sg_index = 0; | ||
1868 | } | ||
1787 | addr64 = (u64) sg_dma_address(sg); | 1869 | addr64 = (u64) sg_dma_address(sg); |
1788 | len = sg_dma_len(sg); | 1870 | len = sg_dma_len(sg); |
1789 | cp->SG[i].Addr.lower = | 1871 | curr_sg->Addr.lower = (u32) (addr64 & 0x0FFFFFFFFULL); |
1790 | (u32) (addr64 & (u64) 0x00000000FFFFFFFF); | 1872 | curr_sg->Addr.upper = (u32) ((addr64 >> 32) & 0x0FFFFFFFFULL); |
1791 | cp->SG[i].Addr.upper = | 1873 | curr_sg->Len = len; |
1792 | (u32) ((addr64 >> 32) & (u64) 0x00000000FFFFFFFF); | 1874 | curr_sg->Ext = 0; /* we are not chaining */ |
1793 | cp->SG[i].Len = len; | 1875 | curr_sg++; |
1794 | cp->SG[i].Ext = 0; /* we are not chaining */ | 1876 | } |
1877 | |||
1878 | if (use_sg + chained > h->maxSG) | ||
1879 | h->maxSG = use_sg + chained; | ||
1880 | |||
1881 | if (chained) { | ||
1882 | cp->Header.SGList = h->max_cmd_sg_entries; | ||
1883 | cp->Header.SGTotal = (u16) (use_sg + 1); | ||
1884 | hpsa_map_sg_chain_block(h, cp); | ||
1885 | return 0; | ||
1795 | } | 1886 | } |
1796 | 1887 | ||
1797 | sglist_finished: | 1888 | sglist_finished: |
@@ -1887,7 +1978,7 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd, | |||
1887 | break; | 1978 | break; |
1888 | } | 1979 | } |
1889 | 1980 | ||
1890 | if (hpsa_scatter_gather(h->pdev, c, cmd) < 0) { /* Fill SG list */ | 1981 | if (hpsa_scatter_gather(h, c, cmd) < 0) { /* Fill SG list */ |
1891 | cmd_free(h, c); | 1982 | cmd_free(h, c); |
1892 | return SCSI_MLQUEUE_HOST_BUSY; | 1983 | return SCSI_MLQUEUE_HOST_BUSY; |
1893 | } | 1984 | } |
@@ -3283,6 +3374,23 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) | |||
3283 | 3374 | ||
3284 | h->board_id = board_id; | 3375 | h->board_id = board_id; |
3285 | h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); | 3376 | h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); |
3377 | h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements)); | ||
3378 | |||
3379 | /* | ||
3380 | * Limit in-command s/g elements to 32 save dma'able memory. | ||
3381 | * Howvever spec says if 0, use 31 | ||
3382 | */ | ||
3383 | |||
3384 | h->max_cmd_sg_entries = 31; | ||
3385 | if (h->maxsgentries > 512) { | ||
3386 | h->max_cmd_sg_entries = 32; | ||
3387 | h->chainsize = h->maxsgentries - h->max_cmd_sg_entries + 1; | ||
3388 | h->maxsgentries--; /* save one for chain pointer */ | ||
3389 | } else { | ||
3390 | h->maxsgentries = 31; /* default to traditional values */ | ||
3391 | h->chainsize = 0; | ||
3392 | } | ||
3393 | |||
3286 | h->product_name = products[prod_index].product_name; | 3394 | h->product_name = products[prod_index].product_name; |
3287 | h->access = *(products[prod_index].access); | 3395 | h->access = *(products[prod_index].access); |
3288 | /* Allow room for some ioctls */ | 3396 | /* Allow room for some ioctls */ |
@@ -3463,6 +3571,8 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, | |||
3463 | rc = -ENOMEM; | 3571 | rc = -ENOMEM; |
3464 | goto clean4; | 3572 | goto clean4; |
3465 | } | 3573 | } |
3574 | if (hpsa_allocate_sg_chain_blocks(h)) | ||
3575 | goto clean4; | ||
3466 | spin_lock_init(&h->lock); | 3576 | spin_lock_init(&h->lock); |
3467 | spin_lock_init(&h->scan_lock); | 3577 | spin_lock_init(&h->scan_lock); |
3468 | init_waitqueue_head(&h->scan_wait_queue); | 3578 | init_waitqueue_head(&h->scan_wait_queue); |
@@ -3485,6 +3595,7 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, | |||
3485 | return 1; | 3595 | return 1; |
3486 | 3596 | ||
3487 | clean4: | 3597 | clean4: |
3598 | hpsa_free_sg_chain_blocks(h); | ||
3488 | kfree(h->cmd_pool_bits); | 3599 | kfree(h->cmd_pool_bits); |
3489 | if (h->cmd_pool) | 3600 | if (h->cmd_pool) |
3490 | pci_free_consistent(h->pdev, | 3601 | pci_free_consistent(h->pdev, |
@@ -3560,6 +3671,7 @@ static void __devexit hpsa_remove_one(struct pci_dev *pdev) | |||
3560 | hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */ | 3671 | hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */ |
3561 | hpsa_shutdown(pdev); | 3672 | hpsa_shutdown(pdev); |
3562 | iounmap(h->vaddr); | 3673 | iounmap(h->vaddr); |
3674 | hpsa_free_sg_chain_blocks(h); | ||
3563 | pci_free_consistent(h->pdev, | 3675 | pci_free_consistent(h->pdev, |
3564 | h->nr_cmds * sizeof(struct CommandList), | 3676 | h->nr_cmds * sizeof(struct CommandList), |
3565 | h->cmd_pool, h->cmd_pool_dhandle); | 3677 | h->cmd_pool, h->cmd_pool_dhandle); |
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index fc15215145d9..1bb5233b09a0 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h | |||
@@ -83,6 +83,10 @@ struct ctlr_info { | |||
83 | unsigned int maxQsinceinit; | 83 | unsigned int maxQsinceinit; |
84 | unsigned int maxSG; | 84 | unsigned int maxSG; |
85 | spinlock_t lock; | 85 | spinlock_t lock; |
86 | int maxsgentries; | ||
87 | u8 max_cmd_sg_entries; | ||
88 | int chainsize; | ||
89 | struct SGDescriptor **cmd_sg_list; | ||
86 | 90 | ||
87 | /* pointers to command and error info pool */ | 91 | /* pointers to command and error info pool */ |
88 | struct CommandList *cmd_pool; | 92 | struct CommandList *cmd_pool; |
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 43b6f1cffe34..cb0c2385f3f6 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h | |||
@@ -23,7 +23,8 @@ | |||
23 | 23 | ||
24 | /* general boundary defintions */ | 24 | /* general boundary defintions */ |
25 | #define SENSEINFOBYTES 32 /* may vary between hbas */ | 25 | #define SENSEINFOBYTES 32 /* may vary between hbas */ |
26 | #define MAXSGENTRIES 31 | 26 | #define MAXSGENTRIES 32 |
27 | #define HPSA_SG_CHAIN 0x80000000 | ||
27 | #define MAXREPLYQS 256 | 28 | #define MAXREPLYQS 256 |
28 | 29 | ||
29 | /* Command Status value */ | 30 | /* Command Status value */ |
@@ -321,8 +322,8 @@ struct CommandList { | |||
321 | */ | 322 | */ |
322 | #define IS_32_BIT ((8 - sizeof(long))/4) | 323 | #define IS_32_BIT ((8 - sizeof(long))/4) |
323 | #define IS_64_BIT (!IS_32_BIT) | 324 | #define IS_64_BIT (!IS_32_BIT) |
324 | #define PAD_32 (8) | 325 | #define PAD_32 (24) |
325 | #define PAD_64 (0) | 326 | #define PAD_64 (16) |
326 | #define COMMANDLIST_PAD (IS_32_BIT * PAD_32 + IS_64_BIT * PAD_64) | 327 | #define COMMANDLIST_PAD (IS_32_BIT * PAD_32 + IS_64_BIT * PAD_64) |
327 | u8 pad[COMMANDLIST_PAD]; | 328 | u8 pad[COMMANDLIST_PAD]; |
328 | }; | 329 | }; |