diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_attr.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 92 |
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 | ||
281 | static ssize_t | ||
282 | lpfc_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 | |||
290 | static ssize_t | ||
291 | lpfc_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) \ |
283 | static ssize_t \ | 348 | static ssize_t \ |
@@ -416,6 +481,15 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show, | |||
416 | static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR, | 481 | static 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 | ||
484 | static int lpfc_poll = 0; | ||
485 | module_param(lpfc_poll, int, 0); | ||
486 | MODULE_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 | |||
491 | static 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 | */ |
526 | LPFC_ATTR(cr_delay, 0, 0, 63, "A count of milliseconds after which an" | 600 | LPFC_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 | ||
529 | LPFC_ATTR(cr_count, 1, 1, 255, "A count of I/O completions after which an" | 603 | LPFC_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" | |||
553 | LPFC_ATTR_R(max_luns, 256, 1, 32768, | 627 | LPFC_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 | */ | ||
634 | LPFC_ATTR_RW(poll_tmo, 10, 1, 255, | ||
635 | "Milliseconds driver will wait between polling FCP ring"); | ||
636 | |||
556 | struct class_device_attribute *lpfc_host_attrs[] = { | 637 | struct 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 |