diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-10-27 13:37:05 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:22:31 -0500 |
commit | 57127f157298ea2dacbbc878a3c5d2a5daca772c (patch) | |
tree | 2536d995c36e068576a690b33cd2029f0749ddbe /drivers/scsi/lpfc | |
parent | d1a357fcc8348d325d151f6fe0ea54e317652457 (diff) |
[SCSI] lpfc 8.2.3 : Added support for ASICs that report temperature
Added support for ASICs that report temperature. Temperature notices are
reported as events and logged. Temperature can be read via sysfs.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 13 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 36 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 55 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_logmsg.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 18 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 76 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 2 |
9 files changed, 213 insertions, 2 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index ba3ecab9baf3..c1343fb2fcf4 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -569,6 +569,7 @@ struct lpfc_hba { | |||
569 | atomic_t slow_ring_trc_cnt; | 569 | atomic_t slow_ring_trc_cnt; |
570 | #endif | 570 | #endif |
571 | 571 | ||
572 | uint8_t temp_sensor_support; | ||
572 | /* Fields used for heart beat. */ | 573 | /* Fields used for heart beat. */ |
573 | unsigned long last_completion_time; | 574 | unsigned long last_completion_time; |
574 | struct timer_list hb_tmofunc; | 575 | struct timer_list hb_tmofunc; |
@@ -598,5 +599,15 @@ lpfc_is_link_up(struct lpfc_hba *phba) | |||
598 | phba->link_state == LPFC_HBA_READY; | 599 | phba->link_state == LPFC_HBA_READY; |
599 | } | 600 | } |
600 | 601 | ||
601 | #define FC_REG_DUMP_EVENT 0x10 /* Register for Dump events */ | 602 | #define FC_REG_DUMP_EVENT 0x10 /* Register for Dump events */ |
603 | #define FC_REG_TEMPERATURE_EVENT 0x20 /* Register for temperature | ||
604 | event */ | ||
602 | 605 | ||
606 | struct temp_event { | ||
607 | uint32_t event_type; | ||
608 | uint32_t event_code; | ||
609 | uint32_t data; | ||
610 | }; | ||
611 | #define LPFC_CRIT_TEMP 0x1 | ||
612 | #define LPFC_THRESHOLD_TEMP 0x2 | ||
613 | #define LPFC_NORMAL_TEMP 0x3 | ||
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 80a11218b9bb..bd35e9c7b995 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -86,6 +86,15 @@ lpfc_serialnum_show(struct class_device *cdev, char *buf) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static ssize_t | 88 | static ssize_t |
89 | lpfc_temp_sensor_show(struct class_device *cdev, char *buf) | ||
90 | { | ||
91 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
92 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
93 | struct lpfc_hba *phba = vport->phba; | ||
94 | return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support); | ||
95 | } | ||
96 | |||
97 | static ssize_t | ||
89 | lpfc_modeldesc_show(struct class_device *cdev, char *buf) | 98 | lpfc_modeldesc_show(struct class_device *cdev, char *buf) |
90 | { | 99 | { |
91 | struct Scsi_Host *shost = class_to_shost(cdev); | 100 | struct Scsi_Host *shost = class_to_shost(cdev); |
@@ -908,6 +917,8 @@ static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL); | |||
908 | static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); | 917 | static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); |
909 | static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); | 918 | static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); |
910 | static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); | 919 | static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); |
920 | static CLASS_DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, | ||
921 | NULL); | ||
911 | 922 | ||
912 | 923 | ||
913 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; | 924 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; |
@@ -1494,6 +1505,7 @@ struct class_device_attribute *lpfc_hba_attrs[] = { | |||
1494 | &class_device_attr_state, | 1505 | &class_device_attr_state, |
1495 | &class_device_attr_num_discovered_ports, | 1506 | &class_device_attr_num_discovered_ports, |
1496 | &class_device_attr_lpfc_drvr_version, | 1507 | &class_device_attr_lpfc_drvr_version, |
1508 | &class_device_attr_lpfc_temp_sensor, | ||
1497 | &class_device_attr_lpfc_log_verbose, | 1509 | &class_device_attr_lpfc_log_verbose, |
1498 | &class_device_attr_lpfc_lun_queue_depth, | 1510 | &class_device_attr_lpfc_lun_queue_depth, |
1499 | &class_device_attr_lpfc_hba_queue_depth, | 1511 | &class_device_attr_lpfc_hba_queue_depth, |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index a599e1510710..f3916645e817 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -23,6 +23,8 @@ typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param); | |||
23 | struct fc_rport; | 23 | struct fc_rport; |
24 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); | 24 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); |
25 | void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); | 25 | void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); |
26 | void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); | ||
27 | |||
26 | void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *); | 28 | void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *); |
27 | int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, | 29 | int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, |
28 | struct lpfc_dmabuf *mp); | 30 | struct lpfc_dmabuf *mp); |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 451accd5564b..098dd022a7eb 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -1228,7 +1228,8 @@ typedef struct { /* FireFly BIU registers */ | |||
1228 | #define HS_FFER3 0x20000000 /* Bit 29 */ | 1228 | #define HS_FFER3 0x20000000 /* Bit 29 */ |
1229 | #define HS_FFER2 0x40000000 /* Bit 30 */ | 1229 | #define HS_FFER2 0x40000000 /* Bit 30 */ |
1230 | #define HS_FFER1 0x80000000 /* Bit 31 */ | 1230 | #define HS_FFER1 0x80000000 /* Bit 31 */ |
1231 | #define HS_FFERM 0xFF000000 /* Mask for error bits 31:24 */ | 1231 | #define HS_CRIT_TEMP 0x00000100 /* Bit 8 */ |
1232 | #define HS_FFERM 0xFF000100 /* Mask for error bits 31:24 and 8 */ | ||
1232 | 1233 | ||
1233 | /* Host Control Register */ | 1234 | /* Host Control Register */ |
1234 | 1235 | ||
@@ -1282,6 +1283,7 @@ typedef struct { /* FireFly BIU registers */ | |||
1282 | #define MBX_KILL_BOARD 0x24 | 1283 | #define MBX_KILL_BOARD 0x24 |
1283 | #define MBX_CONFIG_FARP 0x25 | 1284 | #define MBX_CONFIG_FARP 0x25 |
1284 | #define MBX_BEACON 0x2A | 1285 | #define MBX_BEACON 0x2A |
1286 | #define MBX_ASYNCEVT_ENABLE 0x33 | ||
1285 | #define MBX_HEARTBEAT 0x31 | 1287 | #define MBX_HEARTBEAT 0x31 |
1286 | 1288 | ||
1287 | #define MBX_CONFIG_HBQ 0x7C | 1289 | #define MBX_CONFIG_HBQ 0x7C |
@@ -1344,6 +1346,7 @@ typedef struct { /* FireFly BIU registers */ | |||
1344 | 1346 | ||
1345 | /* SLI_2 IOCB Command Set */ | 1347 | /* SLI_2 IOCB Command Set */ |
1346 | 1348 | ||
1349 | #define CMD_ASYNC_STATUS 0x7C | ||
1347 | #define CMD_RCV_SEQUENCE64_CX 0x81 | 1350 | #define CMD_RCV_SEQUENCE64_CX 0x81 |
1348 | #define CMD_XMIT_SEQUENCE64_CR 0x82 | 1351 | #define CMD_XMIT_SEQUENCE64_CR 0x82 |
1349 | #define CMD_XMIT_SEQUENCE64_CX 0x83 | 1352 | #define CMD_XMIT_SEQUENCE64_CX 0x83 |
@@ -1406,6 +1409,8 @@ typedef struct { /* FireFly BIU registers */ | |||
1406 | #define MBX_BUSY 0xffffff /* Attempted cmd to busy Mailbox */ | 1409 | #define MBX_BUSY 0xffffff /* Attempted cmd to busy Mailbox */ |
1407 | #define MBX_TIMEOUT 0xfffffe /* time-out expired waiting for */ | 1410 | #define MBX_TIMEOUT 0xfffffe /* time-out expired waiting for */ |
1408 | 1411 | ||
1412 | #define TEMPERATURE_OFFSET 0xB0 /* Slim offset for critical temperature event */ | ||
1413 | |||
1409 | /* | 1414 | /* |
1410 | * Begin Structure Definitions for Mailbox Commands | 1415 | * Begin Structure Definitions for Mailbox Commands |
1411 | */ | 1416 | */ |
@@ -2606,6 +2611,18 @@ typedef struct { | |||
2606 | uint32_t IPAddress; | 2611 | uint32_t IPAddress; |
2607 | } CONFIG_FARP_VAR; | 2612 | } CONFIG_FARP_VAR; |
2608 | 2613 | ||
2614 | /* Structure for MB Command MBX_ASYNCEVT_ENABLE (0x33) */ | ||
2615 | |||
2616 | typedef struct { | ||
2617 | #ifdef __BIG_ENDIAN_BITFIELD | ||
2618 | uint32_t rsvd:30; | ||
2619 | uint32_t ring:2; /* Ring for ASYNC_EVENT iocb Bits 0-1*/ | ||
2620 | #else /* __LITTLE_ENDIAN */ | ||
2621 | uint32_t ring:2; /* Ring for ASYNC_EVENT iocb Bits 0-1*/ | ||
2622 | uint32_t rsvd:30; | ||
2623 | #endif | ||
2624 | } ASYNCEVT_ENABLE_VAR; | ||
2625 | |||
2609 | /* Union of all Mailbox Command types */ | 2626 | /* Union of all Mailbox Command types */ |
2610 | #define MAILBOX_CMD_WSIZE 32 | 2627 | #define MAILBOX_CMD_WSIZE 32 |
2611 | #define MAILBOX_CMD_SIZE (MAILBOX_CMD_WSIZE * sizeof(uint32_t)) | 2628 | #define MAILBOX_CMD_SIZE (MAILBOX_CMD_WSIZE * sizeof(uint32_t)) |
@@ -2645,6 +2662,7 @@ typedef union { | |||
2645 | CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT) */ | 2662 | CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT) */ |
2646 | REG_VPI_VAR varRegVpi; /* cmd = 0x96 (REG_VPI) */ | 2663 | REG_VPI_VAR varRegVpi; /* cmd = 0x96 (REG_VPI) */ |
2647 | UNREG_VPI_VAR varUnregVpi; /* cmd = 0x97 (UNREG_VPI) */ | 2664 | UNREG_VPI_VAR varUnregVpi; /* cmd = 0x97 (UNREG_VPI) */ |
2665 | ASYNCEVT_ENABLE_VAR varCfgAsyncEvent; /*cmd = x33 (CONFIG_ASYNC) */ | ||
2648 | } MAILVARIANTS; | 2666 | } MAILVARIANTS; |
2649 | 2667 | ||
2650 | /* | 2668 | /* |
@@ -2987,6 +3005,21 @@ typedef struct { | |||
2987 | uint32_t fcpt_Length; /* transfer ready for IWRITE */ | 3005 | uint32_t fcpt_Length; /* transfer ready for IWRITE */ |
2988 | } FCPT_FIELDS64; | 3006 | } FCPT_FIELDS64; |
2989 | 3007 | ||
3008 | /* IOCB Command template for Async Status iocb commands */ | ||
3009 | typedef struct { | ||
3010 | uint32_t rsvd[4]; | ||
3011 | uint32_t param; | ||
3012 | #ifdef __BIG_ENDIAN_BITFIELD | ||
3013 | uint16_t evt_code; /* High order bits word 5 */ | ||
3014 | uint16_t sub_ctxt_tag; /* Low order bits word 5 */ | ||
3015 | #else /* __LITTLE_ENDIAN_BITFIELD */ | ||
3016 | uint16_t sub_ctxt_tag; /* High order bits word 5 */ | ||
3017 | uint16_t evt_code; /* Low order bits word 5 */ | ||
3018 | #endif | ||
3019 | } ASYNCSTAT_FIELDS; | ||
3020 | #define ASYNC_TEMP_WARN 0x100 | ||
3021 | #define ASYNC_TEMP_SAFE 0x101 | ||
3022 | |||
2990 | /* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7) | 3023 | /* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7) |
2991 | or CMD_IOCB_RCV_SEQ64_CX (0xB5) */ | 3024 | or CMD_IOCB_RCV_SEQ64_CX (0xB5) */ |
2992 | 3025 | ||
@@ -3028,6 +3061,7 @@ typedef struct _IOCB { /* IOCB structure */ | |||
3028 | XMT_SEQ_FIELDS64 xseq64; /* XMIT / BCAST cmd */ | 3061 | XMT_SEQ_FIELDS64 xseq64; /* XMIT / BCAST cmd */ |
3029 | FCPI_FIELDS64 fcpi64; /* FCP 64 bit Initiator template */ | 3062 | FCPI_FIELDS64 fcpi64; /* FCP 64 bit Initiator template */ |
3030 | FCPT_FIELDS64 fcpt64; /* FCP 64 bit target template */ | 3063 | FCPT_FIELDS64 fcpt64; /* FCP 64 bit target template */ |
3064 | ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */ | ||
3031 | 3065 | ||
3032 | uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */ | 3066 | uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */ |
3033 | } un; | 3067 | } un; |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index ecebdfa00470..17f445478beb 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -212,6 +212,18 @@ out_free_mbox: | |||
212 | return 0; | 212 | return 0; |
213 | } | 213 | } |
214 | 214 | ||
215 | /* Completion handler for config async event mailbox command. */ | ||
216 | static void | ||
217 | lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) | ||
218 | { | ||
219 | if (pmboxq->mb.mbxStatus == MBX_SUCCESS) | ||
220 | phba->temp_sensor_support = 1; | ||
221 | else | ||
222 | phba->temp_sensor_support = 0; | ||
223 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
224 | return; | ||
225 | } | ||
226 | |||
215 | /************************************************************************/ | 227 | /************************************************************************/ |
216 | /* */ | 228 | /* */ |
217 | /* lpfc_config_port_post */ | 229 | /* lpfc_config_port_post */ |
@@ -409,7 +421,21 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
409 | return -EIO; | 421 | return -EIO; |
410 | } | 422 | } |
411 | /* MBOX buffer will be freed in mbox compl */ | 423 | /* MBOX buffer will be freed in mbox compl */ |
424 | pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
425 | lpfc_config_async(phba, pmb, LPFC_ELS_RING); | ||
426 | pmb->mbox_cmpl = lpfc_config_async_cmpl; | ||
427 | pmb->vport = phba->pport; | ||
428 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | ||
412 | 429 | ||
430 | if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { | ||
431 | lpfc_printf_log(phba, | ||
432 | KERN_ERR, | ||
433 | LOG_INIT, | ||
434 | "0456 Adapter failed to issue " | ||
435 | "ASYNCEVT_ENABLE mbox status x%x \n.", | ||
436 | rc); | ||
437 | mempool_free(pmb, phba->mbox_mem_pool); | ||
438 | } | ||
413 | return (0); | 439 | return (0); |
414 | } | 440 | } |
415 | 441 | ||
@@ -601,6 +627,8 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
601 | struct lpfc_sli_ring *pring; | 627 | struct lpfc_sli_ring *pring; |
602 | struct lpfc_vport **vports; | 628 | struct lpfc_vport **vports; |
603 | uint32_t event_data; | 629 | uint32_t event_data; |
630 | unsigned long temperature; | ||
631 | struct temp_event temp_event_data; | ||
604 | struct Scsi_Host *shost; | 632 | struct Scsi_Host *shost; |
605 | int i; | 633 | int i; |
606 | 634 | ||
@@ -655,6 +683,33 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
655 | return; | 683 | return; |
656 | } | 684 | } |
657 | lpfc_unblock_mgmt_io(phba); | 685 | lpfc_unblock_mgmt_io(phba); |
686 | } else if (phba->work_hs & HS_CRIT_TEMP) { | ||
687 | temperature = readl(phba->MBslimaddr + TEMPERATURE_OFFSET); | ||
688 | temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; | ||
689 | temp_event_data.event_code = LPFC_CRIT_TEMP; | ||
690 | temp_event_data.data = (uint32_t)temperature; | ||
691 | |||
692 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
693 | "0459 Adapter maximum temperature exceeded " | ||
694 | "(%ld), taking this port offline " | ||
695 | "Data: x%x x%x x%x\n", | ||
696 | temperature, phba->work_hs, | ||
697 | phba->work_status[0], phba->work_status[1]); | ||
698 | |||
699 | shost = lpfc_shost_from_vport(phba->pport); | ||
700 | fc_host_post_vendor_event(shost, fc_get_event_number(), | ||
701 | sizeof(temp_event_data), | ||
702 | (char *) &temp_event_data, | ||
703 | SCSI_NL_VID_TYPE_PCI | ||
704 | | PCI_VENDOR_ID_EMULEX); | ||
705 | |||
706 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | ||
707 | lpfc_offline_prep(phba); | ||
708 | lpfc_offline(phba); | ||
709 | lpfc_unblock_mgmt_io(phba); | ||
710 | phba->link_state = LPFC_HBA_ERROR; | ||
711 | lpfc_hba_down_post(phba); | ||
712 | |||
658 | } else { | 713 | } else { |
659 | /* The if clause above forces this code path when the status | 714 | /* The if clause above forces this code path when the status |
660 | * failure is a value other than FFER6. Do not call the offline | 715 | * failure is a value other than FFER6. Do not call the offline |
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index 626e4d878725..c5841d7565f7 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define LOG_IP 0x20 /* IP traffic history */ | 26 | #define LOG_IP 0x20 /* IP traffic history */ |
27 | #define LOG_FCP 0x40 /* FCP traffic history */ | 27 | #define LOG_FCP 0x40 /* FCP traffic history */ |
28 | #define LOG_NODE 0x80 /* Node table events */ | 28 | #define LOG_NODE 0x80 /* Node table events */ |
29 | #define LOG_TEMP 0x100 /* Temperature sensor events */ | ||
29 | #define LOG_MISC 0x400 /* Miscellaneous events */ | 30 | #define LOG_MISC 0x400 /* Miscellaneous events */ |
30 | #define LOG_SLI 0x800 /* SLI events */ | 31 | #define LOG_SLI 0x800 /* SLI events */ |
31 | #define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */ | 32 | #define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */ |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index a592733664e9..7256be3f4e2f 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -82,6 +82,24 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
82 | } | 82 | } |
83 | 83 | ||
84 | /**********************************************/ | 84 | /**********************************************/ |
85 | /* lpfc_config_async Issue a */ | ||
86 | /* MBX_ASYNC_EVT_ENABLE mailbox command */ | ||
87 | /**********************************************/ | ||
88 | void | ||
89 | lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, | ||
90 | uint32_t ring) | ||
91 | { | ||
92 | MAILBOX_t *mb; | ||
93 | |||
94 | mb = &pmb->mb; | ||
95 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | ||
96 | mb->mbxCommand = MBX_ASYNCEVT_ENABLE; | ||
97 | mb->un.varCfgAsyncEvent.ring = ring; | ||
98 | mb->mbxOwner = OWN_HOST; | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | /**********************************************/ | ||
85 | /* lpfc_heart_beat Issue a HEART_BEAT */ | 103 | /* lpfc_heart_beat Issue a HEART_BEAT */ |
86 | /* mailbox command */ | 104 | /* mailbox command */ |
87 | /**********************************************/ | 105 | /**********************************************/ |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index ce348c5c706c..41f13a300ba5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -199,6 +199,7 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) | |||
199 | case CMD_RCV_ELS_REQ_CX: | 199 | case CMD_RCV_ELS_REQ_CX: |
200 | case CMD_RCV_SEQUENCE64_CX: | 200 | case CMD_RCV_SEQUENCE64_CX: |
201 | case CMD_RCV_ELS_REQ64_CX: | 201 | case CMD_RCV_ELS_REQ64_CX: |
202 | case CMD_ASYNC_STATUS: | ||
202 | case CMD_IOCB_RCV_SEQ64_CX: | 203 | case CMD_IOCB_RCV_SEQ64_CX: |
203 | case CMD_IOCB_RCV_ELS64_CX: | 204 | case CMD_IOCB_RCV_ELS64_CX: |
204 | case CMD_IOCB_RCV_CONT64_CX: | 205 | case CMD_IOCB_RCV_CONT64_CX: |
@@ -754,6 +755,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) | |||
754 | case MBX_FLASH_WR_ULA: | 755 | case MBX_FLASH_WR_ULA: |
755 | case MBX_SET_DEBUG: | 756 | case MBX_SET_DEBUG: |
756 | case MBX_LOAD_EXP_ROM: | 757 | case MBX_LOAD_EXP_ROM: |
758 | case MBX_ASYNCEVT_ENABLE: | ||
757 | case MBX_REG_VPI: | 759 | case MBX_REG_VPI: |
758 | case MBX_UNREG_VPI: | 760 | case MBX_UNREG_VPI: |
759 | case MBX_HEARTBEAT: | 761 | case MBX_HEARTBEAT: |
@@ -953,6 +955,7 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) | |||
953 | return &new_hbq_entry->dbuf; | 955 | return &new_hbq_entry->dbuf; |
954 | } | 956 | } |
955 | 957 | ||
958 | |||
956 | static int | 959 | static int |
957 | lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 960 | lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
958 | struct lpfc_iocbq *saveq) | 961 | struct lpfc_iocbq *saveq) |
@@ -964,6 +967,22 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
964 | 967 | ||
965 | match = 0; | 968 | match = 0; |
966 | irsp = &(saveq->iocb); | 969 | irsp = &(saveq->iocb); |
970 | |||
971 | if (irsp->ulpCommand == CMD_ASYNC_STATUS) { | ||
972 | if (pring->lpfc_sli_rcv_async_status) | ||
973 | pring->lpfc_sli_rcv_async_status(phba, pring, saveq); | ||
974 | else | ||
975 | lpfc_printf_log(phba, | ||
976 | KERN_WARNING, | ||
977 | LOG_SLI, | ||
978 | "0316 Ring %d handler: unexpected " | ||
979 | "ASYNC_STATUS iocb received evt_code " | ||
980 | "0x%x\n", | ||
981 | pring->ringno, | ||
982 | irsp->un.asyncstat.evt_code); | ||
983 | return 1; | ||
984 | } | ||
985 | |||
967 | if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX) | 986 | if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX) |
968 | || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX) | 987 | || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX) |
969 | || (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX) | 988 | || (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX) |
@@ -2993,6 +3012,61 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) | |||
2993 | return 0; | 3012 | return 0; |
2994 | } | 3013 | } |
2995 | 3014 | ||
3015 | void | ||
3016 | lpfc_sli_async_event_handler(struct lpfc_hba * phba, | ||
3017 | struct lpfc_sli_ring * pring, struct lpfc_iocbq * iocbq) | ||
3018 | { | ||
3019 | IOCB_t *icmd; | ||
3020 | uint16_t evt_code; | ||
3021 | uint16_t temp; | ||
3022 | struct temp_event temp_event_data; | ||
3023 | struct Scsi_Host *shost; | ||
3024 | |||
3025 | icmd = &iocbq->iocb; | ||
3026 | evt_code = icmd->un.asyncstat.evt_code; | ||
3027 | temp = icmd->ulpContext; | ||
3028 | |||
3029 | if ((evt_code != ASYNC_TEMP_WARN) && | ||
3030 | (evt_code != ASYNC_TEMP_SAFE)) { | ||
3031 | lpfc_printf_log(phba, | ||
3032 | KERN_ERR, | ||
3033 | LOG_SLI, | ||
3034 | "0327 Ring %d handler: unexpected ASYNC_STATUS" | ||
3035 | " evt_code 0x%x\n", | ||
3036 | pring->ringno, | ||
3037 | icmd->un.asyncstat.evt_code); | ||
3038 | return; | ||
3039 | } | ||
3040 | temp_event_data.data = (uint32_t)temp; | ||
3041 | temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; | ||
3042 | if (evt_code == ASYNC_TEMP_WARN) { | ||
3043 | temp_event_data.event_code = LPFC_THRESHOLD_TEMP; | ||
3044 | lpfc_printf_log(phba, | ||
3045 | KERN_WARNING, | ||
3046 | LOG_TEMP, | ||
3047 | "0339 Adapter is very hot, please take " | ||
3048 | "corrective action. temperature : %d Celsius\n", | ||
3049 | temp); | ||
3050 | } | ||
3051 | if (evt_code == ASYNC_TEMP_SAFE) { | ||
3052 | temp_event_data.event_code = LPFC_NORMAL_TEMP; | ||
3053 | lpfc_printf_log(phba, | ||
3054 | KERN_INFO, | ||
3055 | LOG_TEMP, | ||
3056 | "0340 Adapter temperature is OK now. " | ||
3057 | "temperature : %d Celsius\n", | ||
3058 | temp); | ||
3059 | } | ||
3060 | |||
3061 | /* Send temperature change event to applications */ | ||
3062 | shost = lpfc_shost_from_vport(phba->pport); | ||
3063 | fc_host_post_vendor_event(shost, fc_get_event_number(), | ||
3064 | sizeof(temp_event_data), (char *) &temp_event_data, | ||
3065 | SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); | ||
3066 | |||
3067 | } | ||
3068 | |||
3069 | |||
2996 | int | 3070 | int |
2997 | lpfc_sli_setup(struct lpfc_hba *phba) | 3071 | lpfc_sli_setup(struct lpfc_hba *phba) |
2998 | { | 3072 | { |
@@ -3059,6 +3133,8 @@ lpfc_sli_setup(struct lpfc_hba *phba) | |||
3059 | pring->fast_iotag = 0; | 3133 | pring->fast_iotag = 0; |
3060 | pring->iotag_ctr = 0; | 3134 | pring->iotag_ctr = 0; |
3061 | pring->iotag_max = 4096; | 3135 | pring->iotag_max = 4096; |
3136 | pring->lpfc_sli_rcv_async_status = | ||
3137 | lpfc_sli_async_event_handler; | ||
3062 | pring->num_mask = 4; | 3138 | pring->num_mask = 4; |
3063 | pring->prt[0].profile = 0; /* Mask 0 */ | 3139 | pring->prt[0].profile = 0; /* Mask 0 */ |
3064 | pring->prt[0].rctl = FC_ELS_REQ; | 3140 | pring->prt[0].rctl = FC_ELS_REQ; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 51b2b6b949be..8b1fe2f62d84 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -166,6 +166,8 @@ struct lpfc_sli_ring { | |||
166 | 166 | ||
167 | struct lpfc_sli_ring_mask prt[LPFC_MAX_RING_MASK]; | 167 | struct lpfc_sli_ring_mask prt[LPFC_MAX_RING_MASK]; |
168 | uint32_t num_mask; /* number of mask entries in prt array */ | 168 | uint32_t num_mask; /* number of mask entries in prt array */ |
169 | void (*lpfc_sli_rcv_async_status) (struct lpfc_hba *, | ||
170 | struct lpfc_sli_ring *, struct lpfc_iocbq *); | ||
169 | 171 | ||
170 | struct lpfc_sli_ring_stat stats; /* SLI statistical info */ | 172 | struct lpfc_sli_ring_stat stats; /* SLI statistical info */ |
171 | 173 | ||