aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/hpsa.c134
-rw-r--r--drivers/scsi/hpsa.h4
-rw-r--r--drivers/scsi/hpsa_cmd.h7
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
846static 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
860static 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
879clean:
880 hpsa_free_sg_chain_blocks(h);
881 return -ENOMEM;
882}
883
884static 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
901static 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
847static void complete_scsi_command(struct CommandList *cp, 916static 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 */
1768static int hpsa_scatter_gather(struct pci_dev *pdev, 1840static 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
1797sglist_finished: 1888sglist_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
3487clean4: 3597clean4:
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};