aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_attr.c
diff options
context:
space:
mode:
authorJames.Smart@Emulex.Com <James.Smart@Emulex.Com>2005-11-29 16:32:13 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2005-12-13 20:34:14 -0500
commit875fbdfe9b1b4c8f12622a8d8d81428ff0984875 (patch)
tree63c787cb9a7d4a92eaedcc9f8a89a00d5d8f6603 /drivers/scsi/lpfc/lpfc_attr.c
parent5cc36b3cd0e3610ad7c7e2514160998276798fc0 (diff)
[SCSI] lpfc 8.1.1 : Add polled-mode support
- Add functionality to run in polled mode only. Includes run time attribute to enable mode. - Enable runtime writable hba settings for coallescing and delay parameters Customers have requested a mode in the driver to run strictly polled. This is generally to support an environment where the server is extremely loaded and is looking to reclaim some cpu cycles from adapter interrupt handling. This patch adds a new "poll" attribute, and the following behavior: if value is 0 (default): The driver uses the normal method for i/o completion. It uses the firmware feature of interrupt coalesing. The firmware allows a minimum number of i/o completions before an interrupt, or a maximum time delay between interrupts. By default, the driver sets these to no delay (disabled) or 1 i/o - meaning coalescing is disabled. Attributes were provided to change the coalescing values, but it was a module-load time only and global across all adapters. This patch allows them to be writable on a per-adapter basis. if value is 1 : Interrupts are left enabled, expecting that the user has tuned the interrupt coalescing values. When this setting is enabled, the driver will attempt to service completed i/o whenever new i/o is submitted to the adapter. If the coalescing values are large, and the i/o generation rate steady, an interrupt will be avoided by servicing completed i/o prior to the coalescing thresholds kicking in. However, if the i/o completion load is high enough or i/o generation slow, the coalescion values will ensure that completed i/o is serviced in a timely fashion. if value is 3 : Turns off FCP i/o interrupts altogether. The coalescing values now have no effect. A new attribute "poll_tmo" (default 10ms) exists to set the polling interval for i/o completion. When this setting is enabled, the driver will attempt to service completed i/o and restart the interval timer whenever new i/o is submitted. This behavior allows for servicing of completed i/o sooner than the interval timer, but ensures that if no i/o is being issued, then the interval timer will kick in to service the outstanding i/o. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_attr.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c92
1 files changed, 90 insertions, 2 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 89e8222bc7cc..5625a8c2a8fd 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -278,6 +278,71 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
278 return -EIO; 278 return -EIO;
279} 279}
280 280
281static ssize_t
282lpfc_poll_show(struct class_device *cdev, char *buf)
283{
284 struct Scsi_Host *host = class_to_shost(cdev);
285 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
286
287 return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
288}
289
290static ssize_t
291lpfc_poll_store(struct class_device *cdev, const char *buf,
292 size_t count)
293{
294 struct Scsi_Host *host = class_to_shost(cdev);
295 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
296 uint32_t creg_val;
297 uint32_t old_val;
298 int val=0;
299
300 if (!isdigit(buf[0]))
301 return -EINVAL;
302
303 if (sscanf(buf, "%i", &val) != 1)
304 return -EINVAL;
305
306 if ((val & 0x3) != val)
307 return -EINVAL;
308
309 spin_lock_irq(phba->host->host_lock);
310
311 old_val = phba->cfg_poll;
312
313 if (val & ENABLE_FCP_RING_POLLING) {
314 if ((val & DISABLE_FCP_RING_INT) &&
315 !(old_val & DISABLE_FCP_RING_INT)) {
316 creg_val = readl(phba->HCregaddr);
317 creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
318 writel(creg_val, phba->HCregaddr);
319 readl(phba->HCregaddr); /* flush */
320
321 lpfc_poll_start_timer(phba);
322 }
323 } else if (val != 0x0) {
324 spin_unlock_irq(phba->host->host_lock);
325 return -EINVAL;
326 }
327
328 if (!(val & DISABLE_FCP_RING_INT) &&
329 (old_val & DISABLE_FCP_RING_INT))
330 {
331 spin_unlock_irq(phba->host->host_lock);
332 del_timer(&phba->fcp_poll_timer);
333 spin_lock_irq(phba->host->host_lock);
334 creg_val = readl(phba->HCregaddr);
335 creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
336 writel(creg_val, phba->HCregaddr);
337 readl(phba->HCregaddr); /* flush */
338 }
339
340 phba->cfg_poll = val;
341
342 spin_unlock_irq(phba->host->host_lock);
343
344 return strlen(buf);
345}
281 346
282#define lpfc_param_show(attr) \ 347#define lpfc_param_show(attr) \
283static ssize_t \ 348static ssize_t \
@@ -416,6 +481,15 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
416static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR, 481static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
417 lpfc_board_online_show, lpfc_board_online_store); 482 lpfc_board_online_show, lpfc_board_online_store);
418 483
484static int lpfc_poll = 0;
485module_param(lpfc_poll, int, 0);
486MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
487 " 0 - none,"
488 " 1 - poll with interrupts enabled"
489 " 3 - poll and disable FCP ring interrupts");
490
491static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
492 lpfc_poll_show, lpfc_poll_store);
419 493
420/* 494/*
421# lpfc_log_verbose: Only turn this flag on if you are willing to risk being 495# lpfc_log_verbose: Only turn this flag on if you are willing to risk being
@@ -523,10 +597,10 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
523# is 0. Default value of cr_count is 1. The cr_count feature is disabled if 597# is 0. Default value of cr_count is 1. The cr_count feature is disabled if
524# cr_delay is set to 0. 598# cr_delay is set to 0.
525*/ 599*/
526LPFC_ATTR(cr_delay, 0, 0, 63, "A count of milliseconds after which an" 600LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an"
527 "interrupt response is generated"); 601 "interrupt response is generated");
528 602
529LPFC_ATTR(cr_count, 1, 1, 255, "A count of I/O completions after which an" 603LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an"
530 "interrupt response is generated"); 604 "interrupt response is generated");
531 605
532/* 606/*
@@ -553,6 +627,13 @@ LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands"
553LPFC_ATTR_R(max_luns, 256, 1, 32768, 627LPFC_ATTR_R(max_luns, 256, 1, 32768,
554 "Maximum number of LUNs per target driver will support"); 628 "Maximum number of LUNs per target driver will support");
555 629
630/*
631# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
632# Value range is [1,255], default value is 10.
633*/
634LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
635 "Milliseconds driver will wait between polling FCP ring");
636
556struct class_device_attribute *lpfc_host_attrs[] = { 637struct class_device_attribute *lpfc_host_attrs[] = {
557 &class_device_attr_info, 638 &class_device_attr_info,
558 &class_device_attr_serialnum, 639 &class_device_attr_serialnum,
@@ -575,11 +656,15 @@ struct class_device_attribute *lpfc_host_attrs[] = {
575 &class_device_attr_lpfc_topology, 656 &class_device_attr_lpfc_topology,
576 &class_device_attr_lpfc_scan_down, 657 &class_device_attr_lpfc_scan_down,
577 &class_device_attr_lpfc_link_speed, 658 &class_device_attr_lpfc_link_speed,
659 &class_device_attr_lpfc_cr_delay,
660 &class_device_attr_lpfc_cr_count,
578 &class_device_attr_lpfc_fdmi_on, 661 &class_device_attr_lpfc_fdmi_on,
579 &class_device_attr_lpfc_max_luns, 662 &class_device_attr_lpfc_max_luns,
580 &class_device_attr_nport_evt_cnt, 663 &class_device_attr_nport_evt_cnt,
581 &class_device_attr_management_version, 664 &class_device_attr_management_version,
582 &class_device_attr_board_online, 665 &class_device_attr_board_online,
666 &class_device_attr_lpfc_poll,
667 &class_device_attr_lpfc_poll_tmo,
583 NULL, 668 NULL,
584}; 669};
585 670
@@ -1292,6 +1377,9 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
1292 lpfc_fdmi_on_init(phba, lpfc_fdmi_on); 1377 lpfc_fdmi_on_init(phba, lpfc_fdmi_on);
1293 lpfc_discovery_threads_init(phba, lpfc_discovery_threads); 1378 lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
1294 lpfc_max_luns_init(phba, lpfc_max_luns); 1379 lpfc_max_luns_init(phba, lpfc_max_luns);
1380 lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
1381
1382 phba->cfg_poll = lpfc_poll;
1295 1383
1296 /* 1384 /*
1297 * The total number of segments is the configuration value plus 2 1385 * The total number of segments is the configuration value plus 2