aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2015-03-27 03:27:20 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-04-09 16:22:12 -0400
commitbe0cf6ca301c61458dc4aa1a37acf4f58d2ed3d6 (patch)
tree7d25dc148ba1daebb9b706075294a0c091f95655
parentaaced9934d2231227fec4255f394eb86af818ce2 (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.c89
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
1141static void storvsc_on_io_completion(struct hv_device *device, 1150static 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
1339static int storvsc_do_io(struct hv_device *device, 1348static 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)