aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-10-27 13:37:05 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-11 19:22:31 -0500
commit57127f157298ea2dacbbc878a3c5d2a5daca772c (patch)
tree2536d995c36e068576a690b33cd2029f0749ddbe /drivers/scsi/lpfc
parentd1a357fcc8348d325d151f6fe0ea54e317652457 (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.h13
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c12
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h36
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c55
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c76
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h2
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
606struct 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
88static ssize_t 88static ssize_t
89lpfc_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
97static ssize_t
89lpfc_modeldesc_show(struct class_device *cdev, char *buf) 98lpfc_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);
908static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); 917static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
909static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); 918static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
910static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); 919static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
920static CLASS_DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show,
921 NULL);
911 922
912 923
913static char *lpfc_soft_wwn_key = "C99G71SL8032A"; 924static 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);
23struct fc_rport; 23struct fc_rport;
24void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); 24void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
25void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); 25void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
26void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
27
26void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *); 28void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
27int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, 29int 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
2616typedef 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 */
3009typedef 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. */
216static void
217lpfc_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/**********************************************/
88void
89lpfc_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
956static int 959static int
957lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, 960lpfc_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
3015void
3016lpfc_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
2996int 3070int
2997lpfc_sli_setup(struct lpfc_hba *phba) 3071lpfc_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