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 | ||
