Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Rishi Mehta and committed by
James Bottomley
2a815b5a a2713cce

+60 -6
+46 -3
drivers/scsi/vmw_pvscsi.c
··· 72 72 bool use_msi; 73 73 bool use_msix; 74 74 bool use_msg; 75 + bool use_req_threshold; 75 76 76 77 spinlock_t hw_lock; 77 78 ··· 110 109 static bool pvscsi_disable_msi; 111 110 static bool pvscsi_disable_msix; 112 111 static bool pvscsi_use_msg = true; 112 + static bool pvscsi_use_req_threshold = true; 113 113 114 114 #define PVSCSI_RW (S_IRUSR | S_IWUSR) 115 115 ··· 134 132 135 133 module_param_named(use_msg, pvscsi_use_msg, bool, PVSCSI_RW); 136 134 MODULE_PARM_DESC(use_msg, "Use msg ring when available - (default=1)"); 135 + 136 + module_param_named(use_req_threshold, pvscsi_use_req_threshold, 137 + bool, PVSCSI_RW); 138 + MODULE_PARM_DESC(use_req_threshold, "Use driver-based request coalescing if configured - (default=1)"); 137 139 138 140 static const struct pci_device_id pvscsi_pci_tbl[] = { 139 141 { PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_PVSCSI) }, ··· 288 282 static void pvscsi_kick_io(const struct pvscsi_adapter *adapter, 289 283 unsigned char op) 290 284 { 291 - if (scsi_is_rw(op)) 292 - pvscsi_kick_rw_io(adapter); 293 - else 285 + if (scsi_is_rw(op)) { 286 + struct PVSCSIRingsState *s = adapter->rings_state; 287 + 288 + if (!adapter->use_req_threshold || 289 + s->reqProdIdx - s->reqConsIdx >= s->reqCallThreshold) 290 + pvscsi_kick_rw_io(adapter); 291 + } else { 294 292 pvscsi_process_request_ring(adapter); 293 + } 295 294 } 296 295 297 296 static void ll_adapter_reset(const struct pvscsi_adapter *adapter) ··· 1088 1077 return 1; 1089 1078 } 1090 1079 1080 + static bool pvscsi_setup_req_threshold(struct pvscsi_adapter *adapter, 1081 + bool enable) 1082 + { 1083 + u32 val; 1084 + 1085 + if (!pvscsi_use_req_threshold) 1086 + return false; 1087 + 1088 + pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_COMMAND, 1089 + PVSCSI_CMD_SETUP_REQCALLTHRESHOLD); 1090 + val = pvscsi_reg_read(adapter, PVSCSI_REG_OFFSET_COMMAND_STATUS); 1091 + if (val == -1) { 1092 + printk(KERN_INFO "vmw_pvscsi: device does not support req_threshold\n"); 1093 + return false; 1094 + } else { 1095 + struct PVSCSICmdDescSetupReqCall cmd_msg = { 0 }; 1096 + cmd_msg.enable = enable; 1097 + printk(KERN_INFO 1098 + "vmw_pvscsi: %sabling reqCallThreshold\n", 1099 + enable ? "en" : "dis"); 1100 + pvscsi_write_cmd_desc(adapter, 1101 + PVSCSI_CMD_SETUP_REQCALLTHRESHOLD, 1102 + &cmd_msg, sizeof(cmd_msg)); 1103 + return pvscsi_reg_read(adapter, 1104 + PVSCSI_REG_OFFSET_COMMAND_STATUS) != 0; 1105 + } 1106 + } 1107 + 1091 1108 static irqreturn_t pvscsi_isr(int irq, void *devp) 1092 1109 { 1093 1110 struct pvscsi_adapter *adapter = devp; ··· 1454 1415 adapter->irq = pdev->irq; 1455 1416 flags = IRQF_SHARED; 1456 1417 } 1418 + 1419 + adapter->use_req_threshold = pvscsi_setup_req_threshold(adapter, true); 1420 + printk(KERN_DEBUG "vmw_pvscsi: driver-based request coalescing %sabled\n", 1421 + adapter->use_req_threshold ? "en" : "dis"); 1457 1422 1458 1423 error = request_irq(adapter->irq, pvscsi_isr, flags, 1459 1424 "vmw_pvscsi", adapter);
+14 -3
drivers/scsi/vmw_pvscsi.h
··· 26 26 27 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 31 #define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128 32 32 ··· 117 117 PVSCSI_CMD_CONFIG = 7, 118 118 PVSCSI_CMD_SETUP_MSG_RING = 8, 119 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 /* ··· 140 139 u64 configPageAddress; 141 140 u32 configPageNum; 142 141 u32 _pad; 142 + } __packed; 143 + 144 + /* 145 + * Command descriptor for PVSCSI_CMD_SETUP_REQCALLTHRESHOLD -- 146 + */ 147 + 148 + struct PVSCSICmdDescSetupReqCall { 149 + u32 enable; 143 150 } __packed; 144 151 145 152 enum PVSCSIConfigPageType { ··· 270 261 u32 cmpConsIdx; 271 262 u32 cmpNumEntriesLog2; 272 263 273 - u8 _pad[104]; 264 + u32 reqCallThreshold; 265 + 266 + u8 _pad[100]; 274 267 275 268 u32 msgProdIdx; 276 269 u32 msgConsIdx;