diff options
-rw-r--r-- | drivers/block/cciss_scsi.c | 85 |
1 files changed, 59 insertions, 26 deletions
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 6dc15b669694..e1d0e2cfec72 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -84,7 +84,6 @@ static struct scsi_host_template cciss_driver_template = { | |||
84 | .queuecommand = cciss_scsi_queue_command, | 84 | .queuecommand = cciss_scsi_queue_command, |
85 | .can_queue = SCSI_CCISS_CAN_QUEUE, | 85 | .can_queue = SCSI_CCISS_CAN_QUEUE, |
86 | .this_id = 7, | 86 | .this_id = 7, |
87 | .sg_tablesize = MAXSGENTRIES, | ||
88 | .cmd_per_lun = 1, | 87 | .cmd_per_lun = 1, |
89 | .use_clustering = DISABLE_CLUSTERING, | 88 | .use_clustering = DISABLE_CLUSTERING, |
90 | /* Can't have eh_bus_reset_handler or eh_host_reset_handler for cciss */ | 89 | /* Can't have eh_bus_reset_handler or eh_host_reset_handler for cciss */ |
@@ -94,13 +93,14 @@ static struct scsi_host_template cciss_driver_template = { | |||
94 | 93 | ||
95 | #pragma pack(1) | 94 | #pragma pack(1) |
96 | 95 | ||
97 | #define SCSI_PAD_32 4 | 96 | #define SCSI_PAD_32 0 |
98 | #define SCSI_PAD_64 4 | 97 | #define SCSI_PAD_64 0 |
99 | 98 | ||
100 | struct cciss_scsi_cmd_stack_elem_t { | 99 | struct cciss_scsi_cmd_stack_elem_t { |
101 | CommandList_struct cmd; | 100 | CommandList_struct cmd; |
102 | ErrorInfo_struct Err; | 101 | ErrorInfo_struct Err; |
103 | __u32 busaddr; | 102 | __u32 busaddr; |
103 | int cmdindex; | ||
104 | u8 pad[IS_32_BIT * SCSI_PAD_32 + IS_64_BIT * SCSI_PAD_64]; | 104 | u8 pad[IS_32_BIT * SCSI_PAD_32 + IS_64_BIT * SCSI_PAD_64]; |
105 | }; | 105 | }; |
106 | 106 | ||
@@ -122,6 +122,7 @@ struct cciss_scsi_cmd_stack_t { | |||
122 | struct cciss_scsi_adapter_data_t { | 122 | struct cciss_scsi_adapter_data_t { |
123 | struct Scsi_Host *scsi_host; | 123 | struct Scsi_Host *scsi_host; |
124 | struct cciss_scsi_cmd_stack_t cmd_stack; | 124 | struct cciss_scsi_cmd_stack_t cmd_stack; |
125 | SGDescriptor_struct **cmd_sg_list; | ||
125 | int registered; | 126 | int registered; |
126 | spinlock_t lock; // to protect ccissscsi[ctlr]; | 127 | spinlock_t lock; // to protect ccissscsi[ctlr]; |
127 | }; | 128 | }; |
@@ -156,6 +157,7 @@ scsi_cmd_alloc(ctlr_info_t *h) | |||
156 | memset(&c->Err, 0, sizeof(c->Err)); | 157 | memset(&c->Err, 0, sizeof(c->Err)); |
157 | /* set physical addr of cmd and addr of scsi parameters */ | 158 | /* set physical addr of cmd and addr of scsi parameters */ |
158 | c->cmd.busaddr = c->busaddr; | 159 | c->cmd.busaddr = c->busaddr; |
160 | c->cmd.cmdindex = c->cmdindex; | ||
159 | /* (__u32) (stk->cmd_pool_handle + | 161 | /* (__u32) (stk->cmd_pool_handle + |
160 | (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top)); */ | 162 | (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top)); */ |
161 | 163 | ||
@@ -201,6 +203,11 @@ scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa) | |||
201 | struct cciss_scsi_cmd_stack_t *stk; | 203 | struct cciss_scsi_cmd_stack_t *stk; |
202 | size_t size; | 204 | size_t size; |
203 | 205 | ||
206 | sa->cmd_sg_list = cciss_allocate_sg_chain_blocks(hba[ctlr], | ||
207 | hba[ctlr]->chainsize, CMD_STACK_SIZE); | ||
208 | if (!sa->cmd_sg_list && hba[ctlr]->chainsize > 0) | ||
209 | return -ENOMEM; | ||
210 | |||
204 | stk = &sa->cmd_stack; | 211 | stk = &sa->cmd_stack; |
205 | size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; | 212 | size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; |
206 | 213 | ||
@@ -211,14 +218,16 @@ scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa) | |||
211 | pci_alloc_consistent(hba[ctlr]->pdev, size, &stk->cmd_pool_handle); | 218 | pci_alloc_consistent(hba[ctlr]->pdev, size, &stk->cmd_pool_handle); |
212 | 219 | ||
213 | if (stk->pool == NULL) { | 220 | if (stk->pool == NULL) { |
214 | printk("stk->pool is null\n"); | 221 | cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE); |
215 | return -1; | 222 | sa->cmd_sg_list = NULL; |
223 | return -ENOMEM; | ||
216 | } | 224 | } |
217 | 225 | ||
218 | for (i=0; i<CMD_STACK_SIZE; i++) { | 226 | for (i=0; i<CMD_STACK_SIZE; i++) { |
219 | stk->elem[i] = &stk->pool[i]; | 227 | stk->elem[i] = &stk->pool[i]; |
220 | stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle + | 228 | stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle + |
221 | (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i)); | 229 | (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i)); |
230 | stk->elem[i]->cmdindex = i; | ||
222 | } | 231 | } |
223 | stk->top = CMD_STACK_SIZE-1; | 232 | stk->top = CMD_STACK_SIZE-1; |
224 | return 0; | 233 | return 0; |
@@ -243,6 +252,7 @@ scsi_cmd_stack_free(int ctlr) | |||
243 | 252 | ||
244 | pci_free_consistent(hba[ctlr]->pdev, size, stk->pool, stk->cmd_pool_handle); | 253 | pci_free_consistent(hba[ctlr]->pdev, size, stk->pool, stk->cmd_pool_handle); |
245 | stk->pool = NULL; | 254 | stk->pool = NULL; |
255 | cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE); | ||
246 | } | 256 | } |
247 | 257 | ||
248 | #if 0 | 258 | #if 0 |
@@ -726,6 +736,8 @@ complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag) | |||
726 | ctlr = hba[cp->ctlr]; | 736 | ctlr = hba[cp->ctlr]; |
727 | 737 | ||
728 | scsi_dma_unmap(cmd); | 738 | scsi_dma_unmap(cmd); |
739 | if (cp->Header.SGTotal > ctlr->max_cmd_sgentries) | ||
740 | cciss_unmap_sg_chain_block(ctlr, cp); | ||
729 | 741 | ||
730 | cmd->result = (DID_OK << 16); /* host byte */ | 742 | cmd->result = (DID_OK << 16); /* host byte */ |
731 | cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ | 743 | cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ |
@@ -848,6 +860,7 @@ cciss_scsi_detect(int ctlr) | |||
848 | sh->io_port = 0; // good enough? FIXME, | 860 | sh->io_port = 0; // good enough? FIXME, |
849 | sh->n_io_port = 0; // I don't think we use these two... | 861 | sh->n_io_port = 0; // I don't think we use these two... |
850 | sh->this_id = SELF_SCSI_ID; | 862 | sh->this_id = SELF_SCSI_ID; |
863 | sh->sg_tablesize = hba[ctlr]->maxsgentries; | ||
851 | 864 | ||
852 | ((struct cciss_scsi_adapter_data_t *) | 865 | ((struct cciss_scsi_adapter_data_t *) |
853 | hba[ctlr]->scsi_ctlr)->scsi_host = sh; | 866 | hba[ctlr]->scsi_ctlr)->scsi_host = sh; |
@@ -1365,34 +1378,54 @@ cciss_scsi_proc_info(struct Scsi_Host *sh, | |||
1365 | dma mapping and fills in the scatter gather entries of the | 1378 | dma mapping and fills in the scatter gather entries of the |
1366 | cciss command, cp. */ | 1379 | cciss command, cp. */ |
1367 | 1380 | ||
1368 | static void | 1381 | static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *cp, |
1369 | cciss_scatter_gather(struct pci_dev *pdev, | 1382 | struct scsi_cmnd *cmd) |
1370 | CommandList_struct *cp, | ||
1371 | struct scsi_cmnd *cmd) | ||
1372 | { | 1383 | { |
1373 | unsigned int len; | 1384 | unsigned int len; |
1374 | struct scatterlist *sg; | 1385 | struct scatterlist *sg; |
1375 | __u64 addr64; | 1386 | __u64 addr64; |
1376 | int use_sg, i; | 1387 | int request_nsgs, i, chained, sg_index; |
1377 | 1388 | struct cciss_scsi_adapter_data_t *sa = h->scsi_ctlr; | |
1378 | BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES); | 1389 | SGDescriptor_struct *curr_sg; |
1379 | 1390 | ||
1380 | use_sg = scsi_dma_map(cmd); | 1391 | BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); |
1381 | if (use_sg) { /* not too many addrs? */ | 1392 | |
1382 | scsi_for_each_sg(cmd, sg, use_sg, i) { | 1393 | chained = 0; |
1394 | sg_index = 0; | ||
1395 | curr_sg = cp->SG; | ||
1396 | request_nsgs = scsi_dma_map(cmd); | ||
1397 | if (request_nsgs) { | ||
1398 | scsi_for_each_sg(cmd, sg, request_nsgs, i) { | ||
1399 | if (sg_index + 1 == h->max_cmd_sgentries && | ||
1400 | !chained && request_nsgs - i > 1) { | ||
1401 | chained = 1; | ||
1402 | sg_index = 0; | ||
1403 | curr_sg = sa->cmd_sg_list[cp->cmdindex]; | ||
1404 | } | ||
1383 | addr64 = (__u64) sg_dma_address(sg); | 1405 | addr64 = (__u64) sg_dma_address(sg); |
1384 | len = sg_dma_len(sg); | 1406 | len = sg_dma_len(sg); |
1385 | cp->SG[i].Addr.lower = | 1407 | curr_sg[sg_index].Addr.lower = |
1386 | (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); | 1408 | (__u32) (addr64 & 0x0FFFFFFFFULL); |
1387 | cp->SG[i].Addr.upper = | 1409 | curr_sg[sg_index].Addr.upper = |
1388 | (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); | 1410 | (__u32) ((addr64 >> 32) & 0x0FFFFFFFFULL); |
1389 | cp->SG[i].Len = len; | 1411 | curr_sg[sg_index].Len = len; |
1390 | cp->SG[i].Ext = 0; // we are not chaining | 1412 | curr_sg[sg_index].Ext = 0; |
1413 | ++sg_index; | ||
1391 | } | 1414 | } |
1415 | if (chained) | ||
1416 | cciss_map_sg_chain_block(h, cp, | ||
1417 | sa->cmd_sg_list[cp->cmdindex], | ||
1418 | (request_nsgs - (h->max_cmd_sgentries - 1)) * | ||
1419 | sizeof(SGDescriptor_struct)); | ||
1392 | } | 1420 | } |
1393 | 1421 | /* track how many SG entries we are using */ | |
1394 | cp->Header.SGList = (__u8) use_sg; /* no. SGs contig in this cmd */ | 1422 | if (request_nsgs > h->maxSG) |
1395 | cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */ | 1423 | h->maxSG = request_nsgs; |
1424 | cp->Header.SGTotal = (__u8) request_nsgs + chained; | ||
1425 | if (request_nsgs > h->max_cmd_sgentries) | ||
1426 | cp->Header.SGList = h->max_cmd_sgentries; | ||
1427 | else | ||
1428 | cp->Header.SGList = cp->Header.SGTotal; | ||
1396 | return; | 1429 | return; |
1397 | } | 1430 | } |
1398 | 1431 | ||
@@ -1490,7 +1523,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd | |||
1490 | BUG(); | 1523 | BUG(); |
1491 | break; | 1524 | break; |
1492 | } | 1525 | } |
1493 | cciss_scatter_gather(c->pdev, cp, cmd); | 1526 | cciss_scatter_gather(c, cp, cmd); |
1494 | 1527 | ||
1495 | /* Put the request on the tail of the request queue */ | 1528 | /* Put the request on the tail of the request queue */ |
1496 | 1529 | ||