diff options
author | K. Y. Srinivasan <kys@microsoft.com> | 2015-03-27 03:27:20 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-04-09 16:22:12 -0400 |
commit | be0cf6ca301c61458dc4aa1a37acf4f58d2ed3d6 (patch) | |
tree | 7d25dc148ba1daebb9b706075294a0c091f95655 | |
parent | aaced9934d2231227fec4255f394eb86af818ce2 (diff) |
scsi: storvsc: Set the tablesize based on the information given by the host
Set the tablesize based on the information given by the host.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
Tested-by: Long Li <longli@microsoft.com>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
-rw-r--r-- | drivers/scsi/storvsc_drv.c | 89 |
1 files changed, 64 insertions, 25 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 4156e297ea64..d9dad90344d5 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c | |||
@@ -351,7 +351,10 @@ struct storvsc_cmd_request { | |||
351 | /* Synchronize the request/response if needed */ | 351 | /* Synchronize the request/response if needed */ |
352 | struct completion wait_event; | 352 | struct completion wait_event; |
353 | 353 | ||
354 | struct hv_multipage_buffer data_buffer; | 354 | struct vmbus_channel_packet_multipage_buffer mpb; |
355 | struct vmbus_packet_mpb_array *payload; | ||
356 | u32 payload_sz; | ||
357 | |||
355 | struct vstor_packet vstor_packet; | 358 | struct vstor_packet vstor_packet; |
356 | }; | 359 | }; |
357 | 360 | ||
@@ -1103,6 +1106,8 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) | |||
1103 | struct Scsi_Host *host; | 1106 | struct Scsi_Host *host; |
1104 | struct storvsc_device *stor_dev; | 1107 | struct storvsc_device *stor_dev; |
1105 | struct hv_device *dev = host_dev->dev; | 1108 | struct hv_device *dev = host_dev->dev; |
1109 | u32 payload_sz = cmd_request->payload_sz; | ||
1110 | void *payload = cmd_request->payload; | ||
1106 | 1111 | ||
1107 | stor_dev = get_in_stor_device(dev); | 1112 | stor_dev = get_in_stor_device(dev); |
1108 | host = stor_dev->host; | 1113 | host = stor_dev->host; |
@@ -1132,10 +1137,14 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) | |||
1132 | sense_hdr.ascq); | 1137 | sense_hdr.ascq); |
1133 | 1138 | ||
1134 | scsi_set_resid(scmnd, | 1139 | scsi_set_resid(scmnd, |
1135 | cmd_request->data_buffer.len - | 1140 | cmd_request->payload->range.len - |
1136 | vm_srb->data_transfer_length); | 1141 | vm_srb->data_transfer_length); |
1137 | 1142 | ||
1138 | scmnd->scsi_done(scmnd); | 1143 | scmnd->scsi_done(scmnd); |
1144 | |||
1145 | if (payload_sz > | ||
1146 | sizeof(struct vmbus_channel_packet_multipage_buffer)) | ||
1147 | kfree(payload); | ||
1139 | } | 1148 | } |
1140 | 1149 | ||
1141 | static void storvsc_on_io_completion(struct hv_device *device, | 1150 | static void storvsc_on_io_completion(struct hv_device *device, |
@@ -1337,7 +1346,7 @@ static int storvsc_dev_remove(struct hv_device *device) | |||
1337 | } | 1346 | } |
1338 | 1347 | ||
1339 | static int storvsc_do_io(struct hv_device *device, | 1348 | static int storvsc_do_io(struct hv_device *device, |
1340 | struct storvsc_cmd_request *request) | 1349 | struct storvsc_cmd_request *request) |
1341 | { | 1350 | { |
1342 | struct storvsc_device *stor_device; | 1351 | struct storvsc_device *stor_device; |
1343 | struct vstor_packet *vstor_packet; | 1352 | struct vstor_packet *vstor_packet; |
@@ -1369,13 +1378,14 @@ static int storvsc_do_io(struct hv_device *device, | |||
1369 | 1378 | ||
1370 | 1379 | ||
1371 | vstor_packet->vm_srb.data_transfer_length = | 1380 | vstor_packet->vm_srb.data_transfer_length = |
1372 | request->data_buffer.len; | 1381 | request->payload->range.len; |
1373 | 1382 | ||
1374 | vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB; | 1383 | vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB; |
1375 | 1384 | ||
1376 | if (request->data_buffer.len) { | 1385 | if (request->payload->range.len) { |
1377 | ret = vmbus_sendpacket_multipagebuffer(outgoing_channel, | 1386 | |
1378 | &request->data_buffer, | 1387 | ret = vmbus_sendpacket_mpb_desc(outgoing_channel, |
1388 | request->payload, request->payload_sz, | ||
1379 | vstor_packet, | 1389 | vstor_packet, |
1380 | (sizeof(struct vstor_packet) - | 1390 | (sizeof(struct vstor_packet) - |
1381 | vmscsi_size_delta), | 1391 | vmscsi_size_delta), |
@@ -1549,6 +1559,9 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) | |||
1549 | unsigned int sg_count = 0; | 1559 | unsigned int sg_count = 0; |
1550 | struct vmscsi_request *vm_srb; | 1560 | struct vmscsi_request *vm_srb; |
1551 | struct scatterlist *cur_sgl; | 1561 | struct scatterlist *cur_sgl; |
1562 | struct vmbus_packet_mpb_array *payload; | ||
1563 | u32 payload_sz; | ||
1564 | u32 length; | ||
1552 | 1565 | ||
1553 | if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { | 1566 | if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { |
1554 | /* | 1567 | /* |
@@ -1602,48 +1615,71 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) | |||
1602 | 1615 | ||
1603 | memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length); | 1616 | memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length); |
1604 | 1617 | ||
1605 | cmd_request->data_buffer.len = scsi_bufflen(scmnd); | 1618 | sgl = (struct scatterlist *)scsi_sglist(scmnd); |
1606 | if (scsi_sg_count(scmnd)) { | 1619 | sg_count = scsi_sg_count(scmnd); |
1607 | sgl = (struct scatterlist *)scsi_sglist(scmnd); | ||
1608 | sg_count = scsi_sg_count(scmnd); | ||
1609 | 1620 | ||
1621 | length = scsi_bufflen(scmnd); | ||
1622 | payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb; | ||
1623 | payload_sz = sizeof(cmd_request->mpb); | ||
1624 | |||
1625 | if (sg_count) { | ||
1610 | /* check if we need to bounce the sgl */ | 1626 | /* check if we need to bounce the sgl */ |
1611 | if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { | 1627 | if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { |
1612 | cmd_request->bounce_sgl = | 1628 | cmd_request->bounce_sgl = |
1613 | create_bounce_buffer(sgl, scsi_sg_count(scmnd), | 1629 | create_bounce_buffer(sgl, sg_count, |
1614 | scsi_bufflen(scmnd), | 1630 | length, |
1615 | vm_srb->data_in); | 1631 | vm_srb->data_in); |
1616 | if (!cmd_request->bounce_sgl) | 1632 | if (!cmd_request->bounce_sgl) |
1617 | return SCSI_MLQUEUE_HOST_BUSY; | 1633 | return SCSI_MLQUEUE_HOST_BUSY; |
1618 | 1634 | ||
1619 | cmd_request->bounce_sgl_count = | 1635 | cmd_request->bounce_sgl_count = |
1620 | ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >> | 1636 | ALIGN(length, PAGE_SIZE) >> PAGE_SHIFT; |
1621 | PAGE_SHIFT; | ||
1622 | 1637 | ||
1623 | if (vm_srb->data_in == WRITE_TYPE) | 1638 | if (vm_srb->data_in == WRITE_TYPE) |
1624 | copy_to_bounce_buffer(sgl, | 1639 | copy_to_bounce_buffer(sgl, |
1625 | cmd_request->bounce_sgl, | 1640 | cmd_request->bounce_sgl, sg_count); |
1626 | scsi_sg_count(scmnd)); | ||
1627 | 1641 | ||
1628 | sgl = cmd_request->bounce_sgl; | 1642 | sgl = cmd_request->bounce_sgl; |
1629 | sg_count = cmd_request->bounce_sgl_count; | 1643 | sg_count = cmd_request->bounce_sgl_count; |
1630 | } | 1644 | } |
1631 | 1645 | ||
1632 | cmd_request->data_buffer.offset = sgl[0].offset; | 1646 | |
1647 | if (sg_count > MAX_PAGE_BUFFER_COUNT) { | ||
1648 | |||
1649 | payload_sz = (sg_count * sizeof(void *) + | ||
1650 | sizeof(struct vmbus_packet_mpb_array)); | ||
1651 | payload = kmalloc(payload_sz, GFP_ATOMIC); | ||
1652 | if (!payload) { | ||
1653 | if (cmd_request->bounce_sgl_count) | ||
1654 | destroy_bounce_buffer( | ||
1655 | cmd_request->bounce_sgl, | ||
1656 | cmd_request->bounce_sgl_count); | ||
1657 | |||
1658 | return SCSI_MLQUEUE_DEVICE_BUSY; | ||
1659 | } | ||
1660 | } | ||
1661 | |||
1662 | payload->range.len = length; | ||
1663 | payload->range.offset = sgl[0].offset; | ||
1664 | |||
1633 | cur_sgl = sgl; | 1665 | cur_sgl = sgl; |
1634 | for (i = 0; i < sg_count; i++) { | 1666 | for (i = 0; i < sg_count; i++) { |
1635 | cmd_request->data_buffer.pfn_array[i] = | 1667 | payload->range.pfn_array[i] = |
1636 | page_to_pfn(sg_page((cur_sgl))); | 1668 | page_to_pfn(sg_page((cur_sgl))); |
1637 | cur_sgl = sg_next(cur_sgl); | 1669 | cur_sgl = sg_next(cur_sgl); |
1638 | } | 1670 | } |
1639 | 1671 | ||
1640 | } else if (scsi_sglist(scmnd)) { | 1672 | } else if (scsi_sglist(scmnd)) { |
1641 | cmd_request->data_buffer.offset = | 1673 | payload->range.len = length; |
1674 | payload->range.offset = | ||
1642 | virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1); | 1675 | virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1); |
1643 | cmd_request->data_buffer.pfn_array[0] = | 1676 | payload->range.pfn_array[0] = |
1644 | virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT; | 1677 | virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT; |
1645 | } | 1678 | } |
1646 | 1679 | ||
1680 | cmd_request->payload = payload; | ||
1681 | cmd_request->payload_sz = payload_sz; | ||
1682 | |||
1647 | /* Invokes the vsc to start an IO */ | 1683 | /* Invokes the vsc to start an IO */ |
1648 | ret = storvsc_do_io(dev, cmd_request); | 1684 | ret = storvsc_do_io(dev, cmd_request); |
1649 | 1685 | ||
@@ -1672,10 +1708,7 @@ static struct scsi_host_template scsi_driver = { | |||
1672 | .slave_configure = storvsc_device_configure, | 1708 | .slave_configure = storvsc_device_configure, |
1673 | .cmd_per_lun = 255, | 1709 | .cmd_per_lun = 255, |
1674 | .this_id = -1, | 1710 | .this_id = -1, |
1675 | /* no use setting to 0 since ll_blk_rw reset it to 1 */ | 1711 | .use_clustering = ENABLE_CLUSTERING, |
1676 | /* currently 32 */ | ||
1677 | .sg_tablesize = MAX_MULTIPAGE_BUFFER_COUNT, | ||
1678 | .use_clustering = DISABLE_CLUSTERING, | ||
1679 | /* Make sure we dont get a sg segment crosses a page boundary */ | 1712 | /* Make sure we dont get a sg segment crosses a page boundary */ |
1680 | .dma_boundary = PAGE_SIZE-1, | 1713 | .dma_boundary = PAGE_SIZE-1, |
1681 | .no_write_same = 1, | 1714 | .no_write_same = 1, |
@@ -1812,6 +1845,12 @@ static int storvsc_probe(struct hv_device *device, | |||
1812 | /* max cmd length */ | 1845 | /* max cmd length */ |
1813 | host->max_cmd_len = STORVSC_MAX_CMD_LEN; | 1846 | host->max_cmd_len = STORVSC_MAX_CMD_LEN; |
1814 | 1847 | ||
1848 | /* | ||
1849 | * set the table size based on the info we got | ||
1850 | * from the host. | ||
1851 | */ | ||
1852 | host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT); | ||
1853 | |||
1815 | /* Register the HBA and start the scsi bus scan */ | 1854 | /* Register the HBA and start the scsi bus scan */ |
1816 | ret = scsi_add_host(host, &device->device); | 1855 | ret = scsi_add_host(host, &device->device); |
1817 | if (ret != 0) | 1856 | if (ret != 0) |