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

Commit 9399627f authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[SCSI] lpfc 8.2.8 : Add MSI-X support



Add support for MSI-X Multi-Message interrupts. We use different vectors
for fast-path interrupts (i/o) and slow-patch interrupts (discovery, etc).

Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 0f1f53a7
Loading
Loading
Loading
Loading
+34 −1
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ struct lpfc_sli2_slim;
#define LPFC_HB_MBOX_INTERVAL   5	/* Heart beat interval in seconds. */
#define LPFC_HB_MBOX_TIMEOUT    30	/* Heart beat timeout  in seconds. */

/* Error Attention event polling interval */
#define LPFC_ERATT_POLL_INTERVAL	5 /* EATT poll interval in seconds */

/* Define macros for 64 bit support */
#define putPaddrLow(addr)    ((uint32_t) (0xffffffff & (u64)(addr)))
#define putPaddrHigh(addr)   ((uint32_t) (0xffffffff & (((u64)(addr))>>32)))
@@ -60,6 +63,9 @@ struct lpfc_sli2_slim;

#define MAX_HBAEVT	32

/* Number of MSI-X vectors the driver uses */
#define LPFC_MSIX_VECTORS	2

/* lpfc wait event data ready flag */
#define LPFC_DATA_READY		(1<<0)

@@ -423,12 +429,16 @@ struct lpfc_hba {
#define LS_NPIV_FAB_SUPPORTED 0x2	/* Fabric supports NPIV */
#define LS_IGNORE_ERATT       0x4	/* intr handler should ignore ERATT */

	uint32_t hba_flag;	/* hba generic flags */
#define HBA_ERATT_HANDLED	0x1 /* This flag is set when eratt handled */

	struct lpfc_dmabuf slim2p;

	MAILBOX_t *mbox;
	uint32_t *inb_ha_copy;
	uint32_t *inb_counter;
	uint32_t inb_last_counter;
	uint32_t ha_copy;
	struct _PCB *pcb;
	struct _IOCB *IOCBs;

@@ -544,6 +554,7 @@ struct lpfc_hba {
	uint8_t soft_wwn_enable;

	struct timer_list fcp_poll_timer;
	struct timer_list eratt_poll;

	/*
	 * stat  counters
@@ -573,7 +584,7 @@ struct lpfc_hba {

	struct fc_host_statistics link_stats;
	enum intr_type_t intr_type;
	struct msix_entry msix_entries[1];
	struct msix_entry msix_entries[LPFC_MSIX_VECTORS];

	struct list_head port_list;
	struct lpfc_vport *pport;	/* physical lpfc_vport pointer */
@@ -660,6 +671,28 @@ lpfc_worker_wake_up(struct lpfc_hba *phba)
	return;
}

static inline void
lpfc_sli_read_hs(struct lpfc_hba *phba)
{
	/*
	 * There was a link/board error. Read the status register to retrieve
	 * the error event and process it.
	 */
	phba->sli.slistat.err_attn_event++;

	/* Save status info */
	phba->work_hs = readl(phba->HSregaddr);
	phba->work_status[0] = readl(phba->MBslimaddr + 0xa8);
	phba->work_status[1] = readl(phba->MBslimaddr + 0xac);

	/* Clear chip Host Attention error bit */
	writel(HA_ERATT, phba->HAregaddr);
	readl(phba->HAregaddr); /* flush */
	phba->pport->stopped = 1;

	return;
}

#define FC_REG_DUMP_EVENT		0x10	/* Register for Dump events */
#define FC_REG_TEMPERATURE_EVENT	0x20    /* Register for temperature
						   event */
+4 −4
Original line number Diff line number Diff line
@@ -2372,12 +2372,12 @@ LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
/*
# lpfc_use_msi: Use MSI (Message Signaled Interrupts) in systems that
#		support this feature
#       0  = MSI disabled (default)
#       0  = MSI disabled
#       1  = MSI enabled
#	2  = MSI-X enabled
# Value range is [0,2]. Default value is 0.
#       2  = MSI-X enabled (default)
# Value range is [0,2]. Default value is 2.
*/
LPFC_ATTR_R(use_msi, 0, 0, 2, "Use Message Signaled Interrupts (1) or "
LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or "
	    "MSI-X (2), if possible");

/*
+22 −21
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@
 * included with this package.                                     *
 *******************************************************************/

typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param);
typedef int (*node_filter)(struct lpfc_nodelist *, void *);

struct fc_rport;
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
@@ -26,11 +26,11 @@ 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);
int lpfc_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *);
void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport);
void lpfc_issue_clear_la(struct lpfc_hba *, struct lpfc_vport *);
void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_config_msi(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *, int);
void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -43,7 +43,7 @@ void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);

struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove);
void lpfc_cleanup_rpis(struct lpfc_vport *, int);
int lpfc_linkdown(struct lpfc_hba *);
void lpfc_port_link_failure(struct lpfc_vport *);
void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -135,7 +135,7 @@ void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
void lpfc_fdmi_tmo(unsigned long);
void lpfc_fdmi_timeout_handler(struct lpfc_vport *vport);
void lpfc_fdmi_timeout_handler(struct lpfc_vport *);

int lpfc_config_port_prep(struct lpfc_hba *);
int lpfc_config_port_post(struct lpfc_hba *);
@@ -155,6 +155,8 @@ int lpfc_sli_queue_setup(struct lpfc_hba *);
void lpfc_handle_eratt(struct lpfc_hba *);
void lpfc_handle_latt(struct lpfc_hba *);
irqreturn_t lpfc_intr_handler(int, void *);
irqreturn_t lpfc_sp_intr_handler(int, void *);
irqreturn_t lpfc_fp_intr_handler(int, void *);

void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
@@ -175,11 +177,12 @@ void lpfc_mem_free(struct lpfc_hba *);
void lpfc_stop_vport_timers(struct lpfc_vport *);

void lpfc_poll_timeout(unsigned long ptr);
void lpfc_poll_start_timer(struct lpfc_hba * phba);
void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
void lpfc_poll_start_timer(struct lpfc_hba *);
void lpfc_poll_eratt(unsigned long);
void lpfc_sli_poll_fcp_ring(struct lpfc_hba *);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);

void lpfc_reset_barrier(struct lpfc_hba * phba);
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
@@ -187,11 +190,13 @@ int lpfc_sli_brdkill(struct lpfc_hba *);
int lpfc_sli_brdreset(struct lpfc_hba *);
int lpfc_sli_brdrestart(struct lpfc_hba *);
int lpfc_sli_hba_setup(struct lpfc_hba *);
int lpfc_sli_config_port(struct lpfc_hba *, int);
int lpfc_sli_host_down(struct lpfc_vport *);
int lpfc_sli_hba_down(struct lpfc_hba *);
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
int lpfc_sli_handle_mb_event(struct lpfc_hba *);
int lpfc_sli_flush_mbox_queue(struct lpfc_hba *);
int lpfc_sli_check_eratt(struct lpfc_hba *);
int lpfc_sli_handle_slow_ring_event(struct lpfc_hba *,
				    struct lpfc_sli_ring *, uint32_t);
void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -227,17 +232,13 @@ struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_vport *, uint32_t);
struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *,
					 struct lpfc_name *);

int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
			     uint32_t timeout);

int lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
			     struct lpfc_sli_ring * pring,
			     struct lpfc_iocbq * piocb,
			     struct lpfc_iocbq * prspiocbq,
			     uint32_t timeout);
void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba,
			     struct lpfc_iocbq * cmdiocb,
			     struct lpfc_iocbq * rspiocb);
int lpfc_sli_issue_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);

int lpfc_sli_issue_iocb_wait(struct lpfc_hba *, struct lpfc_sli_ring *,
			     struct lpfc_iocbq *, struct lpfc_iocbq *,
			     uint32_t);
void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *, struct lpfc_iocbq *,
			     struct lpfc_iocbq *);

void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *);

+2 −0
Original line number Diff line number Diff line
@@ -369,6 +369,7 @@ lpfc_work_done(struct lpfc_hba *phba)
	spin_unlock_irq(&phba->hbalock);

	if (ha_copy & HA_ERATT)
		/* Handle the error attention event */
		lpfc_handle_eratt(phba);

	if (ha_copy & HA_MBATT)
@@ -376,6 +377,7 @@ lpfc_work_done(struct lpfc_hba *phba)

	if (ha_copy & HA_LATT)
		lpfc_handle_latt(phba);

	vports = lpfc_create_vport_work_array(phba);
	if (vports != NULL)
		for(i = 0; i <= phba->max_vpi; i++) {
+62 −1
Original line number Diff line number Diff line
@@ -1203,6 +1203,18 @@ typedef struct { /* FireFly BIU registers */
#define HA_RXATT       0x00000008	/* Bit  3 */
#define HA_RXMASK      0x0000000f

#define HA_R0_CLR_MSK	(HA_R0RE_REQ | HA_R0CE_RSP | HA_R0ATT)
#define HA_R1_CLR_MSK	(HA_R1RE_REQ | HA_R1CE_RSP | HA_R1ATT)
#define HA_R2_CLR_MSK	(HA_R2RE_REQ | HA_R2CE_RSP | HA_R2ATT)
#define HA_R3_CLR_MSK	(HA_R3RE_REQ | HA_R3CE_RSP | HA_R3ATT)

#define HA_R0_POS	3
#define HA_R1_POS	7
#define HA_R2_POS	11
#define HA_R3_POS	15
#define HA_LE_POS	29
#define HA_MB_POS	30
#define HA_ER_POS	31
/* Chip Attention Register */

#define CA_REG_OFFSET  4	/* Byte offset from register base address */
@@ -1240,7 +1252,7 @@ typedef struct { /* FireFly BIU registers */

/* Host Control Register */

#define HC_REG_OFFSET  12	/* Word offset from register base address */
#define HC_REG_OFFSET  12	/* Byte offset from register base address */

#define HC_MBINT_ENA   0x00000001	/* Bit  0 */
#define HC_R0INT_ENA   0x00000002	/* Bit  1 */
@@ -1253,6 +1265,19 @@ typedef struct { /* FireFly BIU registers */
#define HC_LAINT_ENA   0x20000000	/* Bit 29 */
#define HC_ERINT_ENA   0x80000000	/* Bit 31 */

/* Message Signaled Interrupt eXtension (MSI-X) message identifiers */
#define MSIX_DFLT_ID	0
#define MSIX_RNG0_ID	0
#define MSIX_RNG1_ID	1
#define MSIX_RNG2_ID	2
#define MSIX_RNG3_ID	3

#define MSIX_LINK_ID	4
#define MSIX_MBOX_ID	5

#define MSIX_SPARE0_ID	6
#define MSIX_SPARE1_ID	7

/* Mailbox Commands */
#define MBX_SHUTDOWN        0x00	/* terminate testing */
#define MBX_LOAD_SM         0x01
@@ -1290,6 +1315,7 @@ typedef struct { /* FireFly BIU registers */
#define MBX_KILL_BOARD      0x24
#define MBX_CONFIG_FARP     0x25
#define MBX_BEACON          0x2A
#define MBX_CONFIG_MSI      0x30
#define MBX_HEARTBEAT       0x31
#define MBX_WRITE_VPARMS    0x32
#define MBX_ASYNCEVT_ENABLE 0x33
@@ -2599,6 +2625,40 @@ typedef struct {

} CONFIG_PORT_VAR;

/* Structure for MB Command CONFIG_MSI (0x30) */
struct config_msi_var {
#ifdef __BIG_ENDIAN_BITFIELD
	uint32_t dfltMsgNum:8;	/* Default message number            */
	uint32_t rsvd1:11;	/* Reserved                          */
	uint32_t NID:5;		/* Number of secondary attention IDs */
	uint32_t rsvd2:5;	/* Reserved                          */
	uint32_t dfltPresent:1;	/* Default message number present    */
	uint32_t addFlag:1;	/* Add association flag              */
	uint32_t reportFlag:1;	/* Report association flag           */
#else	/*  __LITTLE_ENDIAN_BITFIELD */
	uint32_t reportFlag:1;	/* Report association flag           */
	uint32_t addFlag:1;	/* Add association flag              */
	uint32_t dfltPresent:1;	/* Default message number present    */
	uint32_t rsvd2:5;	/* Reserved                          */
	uint32_t NID:5;		/* Number of secondary attention IDs */
	uint32_t rsvd1:11;	/* Reserved                          */
	uint32_t dfltMsgNum:8;	/* Default message number            */
#endif
	uint32_t attentionConditions[2];
	uint8_t  attentionId[16];
	uint8_t  messageNumberByHA[64];
	uint8_t  messageNumberByID[16];
	uint32_t autoClearHA[2];
#ifdef __BIG_ENDIAN_BITFIELD
	uint32_t rsvd3:16;
	uint32_t autoClearID:16;
#else	/*  __LITTLE_ENDIAN_BITFIELD */
	uint32_t autoClearID:16;
	uint32_t rsvd3:16;
#endif
	uint32_t rsvd4;
};

/* SLI-2 Port Control Block */

/* SLIM POINTER */
@@ -2722,6 +2782,7 @@ typedef union {
	REG_VPI_VAR varRegVpi;		/* cmd = 0x96 (REG_VPI) */
	UNREG_VPI_VAR varUnregVpi;	/* cmd = 0x97 (UNREG_VPI) */
	ASYNCEVT_ENABLE_VAR varCfgAsyncEvent; /*cmd = x33 (CONFIG_ASYNC) */
	struct config_msi_var varCfgMSI;/* cmd = x30 (CONFIG_MSI)     */
} MAILVARIANTS;

/*
Loading