diff options
author | Rishi Mehta <rmehta@vmware.com> | 2014-03-11 16:51:33 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2014-03-19 18:04:45 -0400 |
commit | 2a815b5ac374d670f347f2d3a39db07105715398 (patch) | |
tree | 8be49db5de5327ac0271efbe3fee7cb6560a2b2f /drivers/scsi | |
parent | a2713cceb3a8efef8b86bec06f10689c95ddbc8c (diff) |
[SCSI] vmw_pvscsi: Add support for I/O requests coalescing.
This change allows pvscsi driver to coalesce I/O requests
before issuing them. The number of I/O's coalesced can be
dynamically configured based on the workload.
Signed-off-by: Rishi Mehta <rmehta@vmware.com>
Signed-off-by: Arvind Kumar <arvindkumar@vmware.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/vmw_pvscsi.c | 49 | ||||
-rw-r--r-- | drivers/scsi/vmw_pvscsi.h | 17 |
2 files changed, 60 insertions, 6 deletions
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index 7c5abd7f6c67..b92ea94be98f 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c | |||
@@ -72,6 +72,7 @@ struct pvscsi_adapter { | |||
72 | bool use_msi; | 72 | bool use_msi; |
73 | bool use_msix; | 73 | bool use_msix; |
74 | bool use_msg; | 74 | bool use_msg; |
75 | bool use_req_threshold; | ||
75 | 76 | ||
76 | spinlock_t hw_lock; | 77 | spinlock_t hw_lock; |
77 | 78 | ||
@@ -109,6 +110,7 @@ static int pvscsi_cmd_per_lun = PVSCSI_DEFAULT_QUEUE_DEPTH; | |||
109 | static bool pvscsi_disable_msi; | 110 | static bool pvscsi_disable_msi; |
110 | static bool pvscsi_disable_msix; | 111 | static bool pvscsi_disable_msix; |
111 | static bool pvscsi_use_msg = true; | 112 | static bool pvscsi_use_msg = true; |
113 | static bool pvscsi_use_req_threshold = true; | ||
112 | 114 | ||
113 | #define PVSCSI_RW (S_IRUSR | S_IWUSR) | 115 | #define PVSCSI_RW (S_IRUSR | S_IWUSR) |
114 | 116 | ||
@@ -133,6 +135,10 @@ MODULE_PARM_DESC(disable_msix, "Disable MSI-X use in driver - (default=0)"); | |||
133 | module_param_named(use_msg, pvscsi_use_msg, bool, PVSCSI_RW); | 135 | module_param_named(use_msg, pvscsi_use_msg, bool, PVSCSI_RW); |
134 | MODULE_PARM_DESC(use_msg, "Use msg ring when available - (default=1)"); | 136 | MODULE_PARM_DESC(use_msg, "Use msg ring when available - (default=1)"); |
135 | 137 | ||
138 | module_param_named(use_req_threshold, pvscsi_use_req_threshold, | ||
139 | bool, PVSCSI_RW); | ||
140 | MODULE_PARM_DESC(use_req_threshold, "Use driver-based request coalescing if configured - (default=1)"); | ||
141 | |||
136 | static const struct pci_device_id pvscsi_pci_tbl[] = { | 142 | static const struct pci_device_id pvscsi_pci_tbl[] = { |
137 | { PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_PVSCSI) }, | 143 | { PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_PVSCSI) }, |
138 | { 0 } | 144 | { 0 } |
@@ -282,10 +288,15 @@ static int scsi_is_rw(unsigned char op) | |||
282 | static void pvscsi_kick_io(const struct pvscsi_adapter *adapter, | 288 | static void pvscsi_kick_io(const struct pvscsi_adapter *adapter, |
283 | unsigned char op) | 289 | unsigned char op) |
284 | { | 290 | { |
285 | if (scsi_is_rw(op)) | 291 | if (scsi_is_rw(op)) { |
286 | pvscsi_kick_rw_io(adapter); | 292 | struct PVSCSIRingsState *s = adapter->rings_state; |
287 | else | 293 | |
294 | if (!adapter->use_req_threshold || | ||
295 | s->reqProdIdx - s->reqConsIdx >= s->reqCallThreshold) | ||
296 | pvscsi_kick_rw_io(adapter); | ||
297 | } else { | ||
288 | pvscsi_process_request_ring(adapter); | 298 | pvscsi_process_request_ring(adapter); |
299 | } | ||
289 | } | 300 | } |
290 | 301 | ||
291 | static void ll_adapter_reset(const struct pvscsi_adapter *adapter) | 302 | static void ll_adapter_reset(const struct pvscsi_adapter *adapter) |
@@ -1077,6 +1088,34 @@ static int pvscsi_setup_msg_workqueue(struct pvscsi_adapter *adapter) | |||
1077 | return 1; | 1088 | return 1; |
1078 | } | 1089 | } |
1079 | 1090 | ||
1091 | static bool pvscsi_setup_req_threshold(struct pvscsi_adapter *adapter, | ||
1092 | bool enable) | ||
1093 | { | ||
1094 | u32 val; | ||
1095 | |||
1096 | if (!pvscsi_use_req_threshold) | ||
1097 | return false; | ||
1098 | |||
1099 | pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_COMMAND, | ||
1100 | PVSCSI_CMD_SETUP_REQCALLTHRESHOLD); | ||
1101 | val = pvscsi_reg_read(adapter, PVSCSI_REG_OFFSET_COMMAND_STATUS); | ||
1102 | if (val == -1) { | ||
1103 | printk(KERN_INFO "vmw_pvscsi: device does not support req_threshold\n"); | ||
1104 | return false; | ||
1105 | } else { | ||
1106 | struct PVSCSICmdDescSetupReqCall cmd_msg = { 0 }; | ||
1107 | cmd_msg.enable = enable; | ||
1108 | printk(KERN_INFO | ||
1109 | "vmw_pvscsi: %sabling reqCallThreshold\n", | ||
1110 | enable ? "en" : "dis"); | ||
1111 | pvscsi_write_cmd_desc(adapter, | ||
1112 | PVSCSI_CMD_SETUP_REQCALLTHRESHOLD, | ||
1113 | &cmd_msg, sizeof(cmd_msg)); | ||
1114 | return pvscsi_reg_read(adapter, | ||
1115 | PVSCSI_REG_OFFSET_COMMAND_STATUS) != 0; | ||
1116 | } | ||
1117 | } | ||
1118 | |||
1080 | static irqreturn_t pvscsi_isr(int irq, void *devp) | 1119 | static irqreturn_t pvscsi_isr(int irq, void *devp) |
1081 | { | 1120 | { |
1082 | struct pvscsi_adapter *adapter = devp; | 1121 | struct pvscsi_adapter *adapter = devp; |
@@ -1416,6 +1455,10 @@ static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1416 | flags = IRQF_SHARED; | 1455 | flags = IRQF_SHARED; |
1417 | } | 1456 | } |
1418 | 1457 | ||
1458 | adapter->use_req_threshold = pvscsi_setup_req_threshold(adapter, true); | ||
1459 | printk(KERN_DEBUG "vmw_pvscsi: driver-based request coalescing %sabled\n", | ||
1460 | adapter->use_req_threshold ? "en" : "dis"); | ||
1461 | |||
1419 | error = request_irq(adapter->irq, pvscsi_isr, flags, | 1462 | error = request_irq(adapter->irq, pvscsi_isr, flags, |
1420 | "vmw_pvscsi", adapter); | 1463 | "vmw_pvscsi", adapter); |
1421 | if (error) { | 1464 | if (error) { |
diff --git a/drivers/scsi/vmw_pvscsi.h b/drivers/scsi/vmw_pvscsi.h index a6437758384f..15a9ac68a50b 100644 --- a/drivers/scsi/vmw_pvscsi.h +++ b/drivers/scsi/vmw_pvscsi.h | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | 28 | ||
29 | #define PVSCSI_DRIVER_VERSION_STRING "1.0.3.0-k" | 29 | #define PVSCSI_DRIVER_VERSION_STRING "1.0.4.0-k" |
30 | 30 | ||
31 | #define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128 | 31 | #define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128 |
32 | 32 | ||
@@ -117,8 +117,9 @@ enum PVSCSICommands { | |||
117 | PVSCSI_CMD_CONFIG = 7, | 117 | PVSCSI_CMD_CONFIG = 7, |
118 | PVSCSI_CMD_SETUP_MSG_RING = 8, | 118 | PVSCSI_CMD_SETUP_MSG_RING = 8, |
119 | PVSCSI_CMD_DEVICE_UNPLUG = 9, | 119 | PVSCSI_CMD_DEVICE_UNPLUG = 9, |
120 | PVSCSI_CMD_SETUP_REQCALLTHRESHOLD = 10, | ||
120 | 121 | ||
121 | PVSCSI_CMD_LAST = 10 /* has to be last */ | 122 | PVSCSI_CMD_LAST = 11 /* has to be last */ |
122 | }; | 123 | }; |
123 | 124 | ||
124 | /* | 125 | /* |
@@ -141,6 +142,14 @@ struct PVSCSICmdDescConfigCmd { | |||
141 | u32 _pad; | 142 | u32 _pad; |
142 | } __packed; | 143 | } __packed; |
143 | 144 | ||
145 | /* | ||
146 | * Command descriptor for PVSCSI_CMD_SETUP_REQCALLTHRESHOLD -- | ||
147 | */ | ||
148 | |||
149 | struct PVSCSICmdDescSetupReqCall { | ||
150 | u32 enable; | ||
151 | } __packed; | ||
152 | |||
144 | enum PVSCSIConfigPageType { | 153 | enum PVSCSIConfigPageType { |
145 | PVSCSI_CONFIG_PAGE_CONTROLLER = 0x1958, | 154 | PVSCSI_CONFIG_PAGE_CONTROLLER = 0x1958, |
146 | PVSCSI_CONFIG_PAGE_PHY = 0x1959, | 155 | PVSCSI_CONFIG_PAGE_PHY = 0x1959, |
@@ -261,7 +270,9 @@ struct PVSCSIRingsState { | |||
261 | u32 cmpConsIdx; | 270 | u32 cmpConsIdx; |
262 | u32 cmpNumEntriesLog2; | 271 | u32 cmpNumEntriesLog2; |
263 | 272 | ||
264 | u8 _pad[104]; | 273 | u32 reqCallThreshold; |
274 | |||
275 | u8 _pad[100]; | ||
265 | 276 | ||
266 | u32 msgProdIdx; | 277 | u32 msgProdIdx; |
267 | u32 msgConsIdx; | 278 | u32 msgConsIdx; |