aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hpsa.c
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2010-02-25 15:03:27 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-03-03 08:07:22 -0500
commit33a2ffce51d9598380d73c515a27fc6cff3bd9c4 (patch)
treec370a96166c005f82c44353f4098778e85db0f72 /drivers/scsi/hpsa.c
parentdb61bfcfe2a68dc71402c270686cd73b80971efc (diff)
[SCSI] hpsa: Increase the number of scatter gather elements supported.
This uses the scatter-gather chaining feature of Smart Array controllers. 32 scatter-gather elements are embedded in the "command list", and the last element in the list may be marked as a "chain pointer", and point to an additional block of scatter gather elements. The precise number of scatter gather elements supported is dependent on the particular kind of Smart Array, and is determined at runtime by querying the hardware. Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r--drivers/scsi/hpsa.c134
1 files changed, 123 insertions, 11 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);