Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57127f15 authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[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: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent d1a357fc
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -569,6 +569,7 @@ struct lpfc_hba {
	atomic_t slow_ring_trc_cnt;
#endif

	uint8_t temp_sensor_support;
	/* Fields used for heart beat. */
	unsigned long last_completion_time;
	struct timer_list hb_tmofunc;
@@ -599,4 +600,14 @@ lpfc_is_link_up(struct lpfc_hba *phba)
}

#define FC_REG_DUMP_EVENT		0x10	/* Register for Dump events */
#define FC_REG_TEMPERATURE_EVENT	0x20    /* Register for temperature
						   event */

struct temp_event {
	uint32_t event_type;
	uint32_t event_code;
	uint32_t data;
};
#define LPFC_CRIT_TEMP		0x1
#define LPFC_THRESHOLD_TEMP	0x2
#define LPFC_NORMAL_TEMP	0x3
+12 −0
Original line number Diff line number Diff line
@@ -85,6 +85,15 @@ lpfc_serialnum_show(struct class_device *cdev, char *buf)
	return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
}

static ssize_t
lpfc_temp_sensor_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host *shost = class_to_shost(cdev);
	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
	struct lpfc_hba   *phba = vport->phba;
	return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support);
}

static ssize_t
lpfc_modeldesc_show(struct class_device *cdev, char *buf)
{
@@ -908,6 +917,8 @@ static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
static CLASS_DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show,
			 NULL);


static char *lpfc_soft_wwn_key = "C99G71SL8032A";
@@ -1494,6 +1505,7 @@ struct class_device_attribute *lpfc_hba_attrs[] = {
	&class_device_attr_state,
	&class_device_attr_num_discovered_ports,
	&class_device_attr_lpfc_drvr_version,
	&class_device_attr_lpfc_temp_sensor,
	&class_device_attr_lpfc_log_verbose,
	&class_device_attr_lpfc_lun_queue_depth,
	&class_device_attr_lpfc_hba_queue_depth,
+2 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param);
struct fc_rport;
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);

void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
		 struct lpfc_dmabuf *mp);
+35 −1
Original line number Diff line number Diff line
@@ -1228,7 +1228,8 @@ typedef struct { /* FireFly BIU registers */
#define HS_FFER3       0x20000000	/* Bit 29 */
#define HS_FFER2       0x40000000	/* Bit 30 */
#define HS_FFER1       0x80000000	/* Bit 31 */
#define HS_FFERM       0xFF000000	/* Mask for error bits 31:24 */
#define HS_CRIT_TEMP   0x00000100	/* Bit 8  */
#define HS_FFERM       0xFF000100	/* Mask for error bits 31:24 and 8 */

/* Host Control Register */

@@ -1282,6 +1283,7 @@ typedef struct { /* FireFly BIU registers */
#define MBX_KILL_BOARD      0x24
#define MBX_CONFIG_FARP     0x25
#define MBX_BEACON          0x2A
#define MBX_ASYNCEVT_ENABLE 0x33
#define MBX_HEARTBEAT       0x31

#define MBX_CONFIG_HBQ	    0x7C
@@ -1344,6 +1346,7 @@ typedef struct { /* FireFly BIU registers */

/*  SLI_2 IOCB Command Set */

#define CMD_ASYNC_STATUS        0x7C
#define CMD_RCV_SEQUENCE64_CX   0x81
#define CMD_XMIT_SEQUENCE64_CR  0x82
#define CMD_XMIT_SEQUENCE64_CX  0x83
@@ -1406,6 +1409,8 @@ typedef struct { /* FireFly BIU registers */
#define MBX_BUSY                   0xffffff /* Attempted cmd to busy Mailbox */
#define MBX_TIMEOUT                0xfffffe /* time-out expired waiting for */

#define TEMPERATURE_OFFSET 0xB0	/* Slim offset for critical temperature event */

/*
 *    Begin Structure Definitions for Mailbox Commands
 */
@@ -2606,6 +2611,18 @@ typedef struct {
	uint32_t IPAddress;
} CONFIG_FARP_VAR;

/* Structure for MB Command MBX_ASYNCEVT_ENABLE (0x33) */

typedef struct {
#ifdef __BIG_ENDIAN_BITFIELD
	uint32_t rsvd:30;
	uint32_t ring:2;	/* Ring for ASYNC_EVENT iocb Bits 0-1*/
#else /*  __LITTLE_ENDIAN */
	uint32_t ring:2;	/* Ring for ASYNC_EVENT iocb Bits 0-1*/
	uint32_t rsvd:30;
#endif
} ASYNCEVT_ENABLE_VAR;

/* Union of all Mailbox Command types */
#define MAILBOX_CMD_WSIZE	32
#define MAILBOX_CMD_SIZE	(MAILBOX_CMD_WSIZE * sizeof(uint32_t))
@@ -2645,6 +2662,7 @@ typedef union {
	CONFIG_PORT_VAR varCfgPort;	/* cmd = 0x88 (CONFIG_PORT)  */
	REG_VPI_VAR varRegVpi;		/* cmd = 0x96 (REG_VPI) */
	UNREG_VPI_VAR varUnregVpi;	/* cmd = 0x97 (UNREG_VPI) */
	ASYNCEVT_ENABLE_VAR varCfgAsyncEvent; /*cmd = x33 (CONFIG_ASYNC) */
} MAILVARIANTS;

/*
@@ -2987,6 +3005,21 @@ typedef struct {
	uint32_t fcpt_Length;	/* transfer ready for IWRITE */
} FCPT_FIELDS64;

/* IOCB Command template for Async Status iocb commands */
typedef struct {
	uint32_t rsvd[4];
	uint32_t param;
#ifdef __BIG_ENDIAN_BITFIELD
	uint16_t evt_code;		/* High order bits word 5 */
	uint16_t sub_ctxt_tag;		/* Low  order bits word 5 */
#else   /*  __LITTLE_ENDIAN_BITFIELD */
	uint16_t sub_ctxt_tag;		/* High order bits word 5 */
	uint16_t evt_code;		/* Low  order bits word 5 */
#endif
} ASYNCSTAT_FIELDS;
#define ASYNC_TEMP_WARN		0x100
#define ASYNC_TEMP_SAFE		0x101

/* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7)
   or CMD_IOCB_RCV_SEQ64_CX (0xB5) */

@@ -3028,6 +3061,7 @@ typedef struct _IOCB { /* IOCB structure */
		XMT_SEQ_FIELDS64 xseq64;	/* XMIT / BCAST cmd */
		FCPI_FIELDS64 fcpi64;	/* FCP 64 bit Initiator template */
		FCPT_FIELDS64 fcpt64;	/* FCP 64 bit target template */
		ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */

		uint32_t ulpWord[IOCB_WORD_SZ - 2];	/* generic 6 'words' */
	} un;
+55 −0
Original line number Diff line number Diff line
@@ -212,6 +212,18 @@ out_free_mbox:
	return 0;
}

/* Completion handler for config async event mailbox command. */
static void
lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
{
	if (pmboxq->mb.mbxStatus == MBX_SUCCESS)
		phba->temp_sensor_support = 1;
	else
		phba->temp_sensor_support = 0;
	mempool_free(pmboxq, phba->mbox_mem_pool);
	return;
}

/************************************************************************/
/*                                                                      */
/*    lpfc_config_port_post                                             */
@@ -409,7 +421,21 @@ lpfc_config_port_post(struct lpfc_hba *phba)
		return -EIO;
	}
	/* MBOX buffer will be freed in mbox compl */
	pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
	lpfc_config_async(phba, pmb, LPFC_ELS_RING);
	pmb->mbox_cmpl = lpfc_config_async_cmpl;
	pmb->vport = phba->pport;
	rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);

	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
		lpfc_printf_log(phba,
				KERN_ERR,
				LOG_INIT,
				"0456 Adapter failed to issue "
				"ASYNCEVT_ENABLE mbox status x%x \n.",
				rc);
		mempool_free(pmb, phba->mbox_mem_pool);
	}
	return (0);
}

@@ -601,6 +627,8 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
	struct lpfc_sli_ring  *pring;
	struct lpfc_vport **vports;
	uint32_t event_data;
	unsigned long temperature;
	struct temp_event temp_event_data;
	struct Scsi_Host  *shost;
	int i;

@@ -655,6 +683,33 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
			return;
		}
		lpfc_unblock_mgmt_io(phba);
	} else if (phba->work_hs & HS_CRIT_TEMP) {
		temperature = readl(phba->MBslimaddr + TEMPERATURE_OFFSET);
		temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
		temp_event_data.event_code = LPFC_CRIT_TEMP;
		temp_event_data.data = (uint32_t)temperature;

		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
				"0459 Adapter maximum temperature exceeded "
				"(%ld), taking this port offline "
				"Data: x%x x%x x%x\n",
				temperature, phba->work_hs,
				phba->work_status[0], phba->work_status[1]);

		shost = lpfc_shost_from_vport(phba->pport);
		fc_host_post_vendor_event(shost, fc_get_event_number(),
					  sizeof(temp_event_data),
					  (char *) &temp_event_data,
					  SCSI_NL_VID_TYPE_PCI
					  | PCI_VENDOR_ID_EMULEX);

		psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
		lpfc_offline_prep(phba);
		lpfc_offline(phba);
		lpfc_unblock_mgmt_io(phba);
		phba->link_state = LPFC_HBA_ERROR;
		lpfc_hba_down_post(phba);

	} else {
		/* The if clause above forces this code path when the status
		 * failure is a value other than FFER6.  Do not call the offline
Loading