aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamie Wellnitz <Jamie.Wellnitz@emulex.com>2006-02-28 19:25:27 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-02-28 20:00:36 -0500
commit41415862a23f422b80eccc92cf885935139e2415 (patch)
treee3a9537653e472f15405778c4dcc678a56304848
parentd9d959c41f013439508e0fa1d31f5644d8d626ef (diff)
[SCSI] lpfc 8.1.2: Add ERROR and WARM_START modes for diagnostic purposes.
Add ERROR and WARM_START modes for diagnostic purposes. Signed-off-by: Jamie Wellnitz <Jamie.Wellnitz@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/lpfc/lpfc.h34
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c64
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h9
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h18
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c32
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c57
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c13
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c311
9 files changed, 390 insertions, 152 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 214ab436e035..c4cca9124f45 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -175,25 +175,27 @@ struct lpfc_hba {
175 uint16_t pci_cfg_value; 175 uint16_t pci_cfg_value;
176 176
177 struct semaphore hba_can_block; 177 struct semaphore hba_can_block;
178 uint32_t hba_state; 178 int32_t hba_state;
179 179
180#define LPFC_INIT_START 1 /* Initial state after board reset */ 180#define LPFC_STATE_UNKNOWN 0 /* HBA state is unknown */
181#define LPFC_INIT_MBX_CMDS 2 /* Initialize HBA with mbox commands */ 181#define LPFC_WARM_START 1 /* HBA state after selective reset */
182#define LPFC_LINK_DOWN 3 /* HBA initialized, link is down */ 182#define LPFC_INIT_START 2 /* Initial state after board reset */
183#define LPFC_LINK_UP 4 /* Link is up - issue READ_LA */ 183#define LPFC_INIT_MBX_CMDS 3 /* Initialize HBA with mbox commands */
184#define LPFC_LOCAL_CFG_LINK 5 /* local NPORT Id configured */ 184#define LPFC_LINK_DOWN 4 /* HBA initialized, link is down */
185#define LPFC_FLOGI 6 /* FLOGI sent to Fabric */ 185#define LPFC_LINK_UP 5 /* Link is up - issue READ_LA */
186#define LPFC_FABRIC_CFG_LINK 7 /* Fabric assigned NPORT Id 186#define LPFC_LOCAL_CFG_LINK 6 /* local NPORT Id configured */
187#define LPFC_FLOGI 7 /* FLOGI sent to Fabric */
188#define LPFC_FABRIC_CFG_LINK 8 /* Fabric assigned NPORT Id
187 configured */ 189 configured */
188#define LPFC_NS_REG 8 /* Register with NameServer */ 190#define LPFC_NS_REG 9 /* Register with NameServer */
189#define LPFC_NS_QRY 9 /* Query NameServer for NPort ID list */ 191#define LPFC_NS_QRY 10 /* Query NameServer for NPort ID list */
190#define LPFC_BUILD_DISC_LIST 10 /* Build ADISC and PLOGI lists for 192#define LPFC_BUILD_DISC_LIST 11 /* Build ADISC and PLOGI lists for
191 * device authentication / discovery */ 193 * device authentication / discovery */
192#define LPFC_DISC_AUTH 11 /* Processing ADISC list */ 194#define LPFC_DISC_AUTH 12 /* Processing ADISC list */
193#define LPFC_CLEAR_LA 12 /* authentication cmplt - issue 195#define LPFC_CLEAR_LA 13 /* authentication cmplt - issue
194 CLEAR_LA */ 196 CLEAR_LA */
195#define LPFC_HBA_READY 32 197#define LPFC_HBA_READY 32
196#define LPFC_HBA_ERROR 0xff 198#define LPFC_HBA_ERROR -1
197 199
198 uint8_t fc_linkspeed; /* Link speed after last READ_LA */ 200 uint8_t fc_linkspeed; /* Link speed after last READ_LA */
199 201
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index c8fb43d60882..e7aca3c4b26e 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -149,6 +149,8 @@ lpfc_state_show(struct class_device *cdev, char *buf)
149 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; 149 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
150 int len = 0; 150 int len = 0;
151 switch (phba->hba_state) { 151 switch (phba->hba_state) {
152 case LPFC_STATE_UNKNOWN:
153 case LPFC_WARM_START:
152 case LPFC_INIT_START: 154 case LPFC_INIT_START:
153 case LPFC_INIT_MBX_CMDS: 155 case LPFC_INIT_MBX_CMDS:
154 case LPFC_LINK_DOWN: 156 case LPFC_LINK_DOWN:
@@ -279,6 +281,58 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
279} 281}
280 282
281static ssize_t 283static ssize_t
284lpfc_board_mode_show(struct class_device *cdev, char *buf)
285{
286 struct Scsi_Host *host = class_to_shost(cdev);
287 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
288 char * state;
289
290 if (phba->hba_state == LPFC_HBA_ERROR)
291 state = "error";
292 else if (phba->hba_state == LPFC_WARM_START)
293 state = "warm start";
294 else if (phba->hba_state == LPFC_INIT_START)
295 state = "offline";
296 else
297 state = "online";
298
299 return snprintf(buf, PAGE_SIZE, "%s\n", state);
300}
301
302static ssize_t
303lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
304{
305 struct Scsi_Host *host = class_to_shost(cdev);
306 struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
307 struct completion online_compl;
308 int status=0;
309
310 init_completion(&online_compl);
311
312 if(strncmp(buf, "online", sizeof("online") - 1) == 0)
313 lpfc_workq_post_event(phba, &status, &online_compl,
314 LPFC_EVT_ONLINE);
315 else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
316 lpfc_workq_post_event(phba, &status, &online_compl,
317 LPFC_EVT_OFFLINE);
318 else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
319 lpfc_workq_post_event(phba, &status, &online_compl,
320 LPFC_EVT_WARM_START);
321 else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
322 lpfc_workq_post_event(phba, &status, &online_compl,
323 LPFC_EVT_KILL);
324 else
325 return -EINVAL;
326
327 wait_for_completion(&online_compl);
328
329 if (!status)
330 return strlen(buf);
331 else
332 return -EIO;
333}
334
335static ssize_t
282lpfc_poll_show(struct class_device *cdev, char *buf) 336lpfc_poll_show(struct class_device *cdev, char *buf)
283{ 337{
284 struct Scsi_Host *host = class_to_shost(cdev); 338 struct Scsi_Host *host = class_to_shost(cdev);
@@ -480,6 +534,8 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
480 NULL); 534 NULL);
481static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR, 535static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
482 lpfc_board_online_show, lpfc_board_online_store); 536 lpfc_board_online_show, lpfc_board_online_store);
537static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
538 lpfc_board_mode_show, lpfc_board_mode_store);
483 539
484static int lpfc_poll = 0; 540static int lpfc_poll = 0;
485module_param(lpfc_poll, int, 0); 541module_param(lpfc_poll, int, 0);
@@ -674,6 +730,7 @@ struct class_device_attribute *lpfc_host_attrs[] = {
674 &class_device_attr_nport_evt_cnt, 730 &class_device_attr_nport_evt_cnt,
675 &class_device_attr_management_version, 731 &class_device_attr_management_version,
676 &class_device_attr_board_online, 732 &class_device_attr_board_online,
733 &class_device_attr_board_mode,
677 &class_device_attr_lpfc_poll, 734 &class_device_attr_lpfc_poll,
678 &class_device_attr_lpfc_poll_tmo, 735 &class_device_attr_lpfc_poll_tmo,
679 NULL, 736 NULL,
@@ -883,8 +940,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
883 case MBX_DUMP_MEMORY: 940 case MBX_DUMP_MEMORY:
884 case MBX_DOWN_LOAD: 941 case MBX_DOWN_LOAD:
885 case MBX_UPDATE_CFG: 942 case MBX_UPDATE_CFG:
943 case MBX_KILL_BOARD:
886 case MBX_LOAD_AREA: 944 case MBX_LOAD_AREA:
887 case MBX_LOAD_EXP_ROM: 945 case MBX_LOAD_EXP_ROM:
946 case MBX_BEACON:
947 case MBX_DEL_LD_ENTRY:
888 break; 948 break;
889 case MBX_READ_SPARM64: 949 case MBX_READ_SPARM64:
890 case MBX_READ_LA: 950 case MBX_READ_LA:
@@ -1042,6 +1102,8 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
1042 fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; 1102 fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
1043 else { 1103 else {
1044 switch (phba->hba_state) { 1104 switch (phba->hba_state) {
1105 case LPFC_STATE_UNKNOWN:
1106 case LPFC_WARM_START:
1045 case LPFC_INIT_START: 1107 case LPFC_INIT_START:
1046 case LPFC_INIT_MBX_CMDS: 1108 case LPFC_INIT_MBX_CMDS:
1047 case LPFC_LINK_DOWN: 1109 case LPFC_LINK_DOWN:
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 0ae49811b916..cafddf2f1af8 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * * 7 * *
@@ -107,6 +107,7 @@ void lpfc_fdmi_tmo_handler(struct lpfc_hba *);
107int lpfc_config_port_prep(struct lpfc_hba *); 107int lpfc_config_port_prep(struct lpfc_hba *);
108int lpfc_config_port_post(struct lpfc_hba *); 108int lpfc_config_port_post(struct lpfc_hba *);
109int lpfc_hba_down_prep(struct lpfc_hba *); 109int lpfc_hba_down_prep(struct lpfc_hba *);
110int lpfc_hba_down_post(struct lpfc_hba *);
110void lpfc_hba_init(struct lpfc_hba *, uint32_t *); 111void lpfc_hba_init(struct lpfc_hba *, uint32_t *);
111int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int); 112int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int);
112void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); 113void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int);
@@ -123,6 +124,7 @@ irqreturn_t lpfc_intr_handler(int, void *, struct pt_regs *);
123void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *); 124void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
124void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *); 125void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
125void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *); 126void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *);
127void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *);
126void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *); 128void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
127LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); 129LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
128 130
@@ -135,6 +137,11 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
135struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *); 137struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
136void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); 138void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
137uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); 139uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
140
141int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
142int lpfc_sli_brdkill(struct lpfc_hba *);
143int lpfc_sli_brdreset(struct lpfc_hba *);
144int lpfc_sli_brdrestart(struct lpfc_hba *);
138int lpfc_sli_hba_setup(struct lpfc_hba *); 145int lpfc_sli_hba_setup(struct lpfc_hba *);
139int lpfc_sli_hba_down(struct lpfc_hba *); 146int lpfc_sli_hba_down(struct lpfc_hba *);
140int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); 147int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index ed6c81660e03..4dfcd4eda2fc 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * * 7 * *
@@ -28,18 +28,24 @@
28 * This is used by Fibre Channel protocol to support FCP. 28 * This is used by Fibre Channel protocol to support FCP.
29 */ 29 */
30 30
31/* worker thread events */
32enum lpfc_work_type {
33 LPFC_EVT_NODEV_TMO,
34 LPFC_EVT_ONLINE,
35 LPFC_EVT_OFFLINE,
36 LPFC_EVT_WARM_START,
37 LPFC_EVT_KILL,
38 LPFC_EVT_ELS_RETRY,
39};
40
31/* structure used to queue event to the discovery tasklet */ 41/* structure used to queue event to the discovery tasklet */
32struct lpfc_work_evt { 42struct lpfc_work_evt {
33 struct list_head evt_listp; 43 struct list_head evt_listp;
34 void * evt_arg1; 44 void * evt_arg1;
35 void * evt_arg2; 45 void * evt_arg2;
36 uint32_t evt; 46 enum lpfc_work_type evt;
37}; 47};
38 48
39#define LPFC_EVT_NODEV_TMO 0x1
40#define LPFC_EVT_ONLINE 0x2
41#define LPFC_EVT_OFFLINE 0x3
42#define LPFC_EVT_ELS_RETRY 0x4
43 49
44struct lpfc_nodelist { 50struct lpfc_nodelist {
45 struct list_head nlp_listp; 51 struct list_head nlp_listp;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 5c396171ebe8..55454923029d 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -120,11 +120,33 @@ lpfc_work_list_done(struct lpfc_hba * phba)
120 free_evt = 0; 120 free_evt = 0;
121 break; 121 break;
122 case LPFC_EVT_ONLINE: 122 case LPFC_EVT_ONLINE:
123 *(int *)(evtp->evt_arg1) = lpfc_online(phba); 123 if (phba->hba_state < LPFC_LINK_DOWN)
124 *(int *)(evtp->evt_arg1) = lpfc_online(phba);
125 else
126 *(int *)(evtp->evt_arg1) = 0;
124 complete((struct completion *)(evtp->evt_arg2)); 127 complete((struct completion *)(evtp->evt_arg2));
125 break; 128 break;
126 case LPFC_EVT_OFFLINE: 129 case LPFC_EVT_OFFLINE:
127 *(int *)(evtp->evt_arg1) = lpfc_offline(phba); 130 if (phba->hba_state >= LPFC_LINK_DOWN)
131 lpfc_offline(phba);
132 lpfc_sli_brdrestart(phba);
133 *(int *)(evtp->evt_arg1) =
134 lpfc_sli_brdready(phba,HS_FFRDY | HS_MBRDY);
135 complete((struct completion *)(evtp->evt_arg2));
136 break;
137 case LPFC_EVT_WARM_START:
138 if (phba->hba_state >= LPFC_LINK_DOWN)
139 lpfc_offline(phba);
140 lpfc_sli_brdreset(phba);
141 lpfc_hba_down_post(phba);
142 *(int *)(evtp->evt_arg1) =
143 lpfc_sli_brdready(phba, HS_MBRDY);
144 complete((struct completion *)(evtp->evt_arg2));
145 break;
146 case LPFC_EVT_KILL:
147 if (phba->hba_state >= LPFC_LINK_DOWN)
148 lpfc_offline(phba);
149 *(int *)(evtp->evt_arg1) = lpfc_sli_brdkill(phba);
128 complete((struct completion *)(evtp->evt_arg2)); 150 complete((struct completion *)(evtp->evt_arg2));
129 break; 151 break;
130 } 152 }
@@ -287,6 +309,10 @@ lpfc_linkdown(struct lpfc_hba * phba)
287 LPFC_MBOXQ_t *mb; 309 LPFC_MBOXQ_t *mb;
288 int rc, i; 310 int rc, i;
289 311
312 if (phba->hba_state == LPFC_LINK_DOWN) {
313 return 0;
314 }
315
290 psli = &phba->sli; 316 psli = &phba->sli;
291 317
292 /* sysfs or selective reset may call this routine to clean up */ 318 /* sysfs or selective reset may call this routine to clean up */
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index e613dd07d2ad..98d39cea7954 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * * 7 * *
@@ -1233,7 +1233,9 @@ typedef struct { /* FireFly BIU registers */
1233#define MBX_SET_MASK 0x20 1233#define MBX_SET_MASK 0x20
1234#define MBX_SET_SLIM 0x21 1234#define MBX_SET_SLIM 0x21
1235#define MBX_UNREG_D_ID 0x23 1235#define MBX_UNREG_D_ID 0x23
1236#define MBX_KILL_BOARD 0x24
1236#define MBX_CONFIG_FARP 0x25 1237#define MBX_CONFIG_FARP 0x25
1238#define MBX_BEACON 0x2A
1237 1239
1238#define MBX_LOAD_AREA 0x81 1240#define MBX_LOAD_AREA 0x81
1239#define MBX_RUN_BIU_DIAG64 0x84 1241#define MBX_RUN_BIU_DIAG64 0x84
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 5e92c451f96e..391ca50293f2 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -459,11 +459,47 @@ lpfc_hba_down_prep(struct lpfc_hba * phba)
459 lpfc_els_flush_cmd(phba); 459 lpfc_els_flush_cmd(phba);
460 lpfc_disc_flush_list(phba); 460 lpfc_disc_flush_list(phba);
461 461
462 /* Disable SLI2 since we disabled interrupts */
463 phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
462 return (0); 464 return (0);
463} 465}
464 466
465/************************************************************************/ 467/************************************************************************/
466/* */ 468/* */
469/* lpfc_hba_down_post */
470/* This routine will do uninitialization after the HBA is reset */
471/* when bringing down the SLI Layer. */
472/* This routine returns 0 on success. Any other return value */
473/* indicates an error. */
474/* */
475/************************************************************************/
476int
477lpfc_hba_down_post(struct lpfc_hba * phba)
478{
479 struct lpfc_sli *psli = &phba->sli;
480 struct lpfc_sli_ring *pring;
481 struct lpfc_dmabuf *mp, *next_mp;
482 int i;
483
484 /* Cleanup preposted buffers on the ELS ring */
485 pring = &psli->ring[LPFC_ELS_RING];
486 list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
487 list_del(&mp->list);
488 pring->postbufq_cnt--;
489 lpfc_mbuf_free(phba, mp->virt, mp->phys);
490 kfree(mp);
491 }
492
493 for (i = 0; i < psli->num_rings; i++) {
494 pring = &psli->ring[i];
495 lpfc_sli_abort_iocb_ring(phba, pring);
496 }
497
498 return 0;
499}
500
501/************************************************************************/
502/* */
467/* lpfc_handle_eratt */ 503/* lpfc_handle_eratt */
468/* This routine will handle processing a Host Attention */ 504/* This routine will handle processing a Host Attention */
469/* Error Status event. This will be initialized */ 505/* Error Status event. This will be initialized */
@@ -476,20 +512,6 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
476 struct lpfc_sli *psli = &phba->sli; 512 struct lpfc_sli *psli = &phba->sli;
477 struct lpfc_sli_ring *pring; 513 struct lpfc_sli_ring *pring;
478 514
479 /*
480 * If a reset is sent to the HBA restore PCI configuration registers.
481 */
482 if ( phba->hba_state == LPFC_INIT_START ) {
483 mdelay(1);
484 readl(phba->HCregaddr); /* flush */
485 writel(0, phba->HCregaddr);
486 readl(phba->HCregaddr); /* flush */
487
488 /* Restore PCI cmd register */
489 pci_write_config_word(phba->pcidev,
490 PCI_COMMAND, phba->pci_cfg_value);
491 }
492
493 if (phba->work_hs & HS_FFER6) { 515 if (phba->work_hs & HS_FFER6) {
494 /* Re-establishing Link */ 516 /* Re-establishing Link */
495 lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, 517 lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
@@ -516,6 +538,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
516 * attempt to restart it. 538 * attempt to restart it.
517 */ 539 */
518 lpfc_offline(phba); 540 lpfc_offline(phba);
541 lpfc_sli_brdrestart(phba);
519 if (lpfc_online(phba) == 0) { /* Initialize the HBA */ 542 if (lpfc_online(phba) == 0) { /* Initialize the HBA */
520 mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); 543 mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
521 return; 544 return;
@@ -532,7 +555,8 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
532 phba->work_status[0], phba->work_status[1]); 555 phba->work_status[0], phba->work_status[1]);
533 556
534 lpfc_offline(phba); 557 lpfc_offline(phba);
535 558 phba->hba_state = LPFC_HBA_ERROR;
559 lpfc_hba_down_post(phba);
536 } 560 }
537} 561}
538 562
@@ -1695,6 +1719,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
1695 * the HBA. 1719 * the HBA.
1696 */ 1720 */
1697 lpfc_sli_hba_down(phba); 1721 lpfc_sli_hba_down(phba);
1722 lpfc_sli_brdrestart(phba);
1698 1723
1699 /* Release the irq reservation */ 1724 /* Release the irq reservation */
1700 free_irq(phba->pcidev->irq, phba); 1725 free_irq(phba->pcidev->irq, phba);
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 6c4b21a32c7f..df88b78707de 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -637,6 +637,17 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
637} 637}
638 638
639void 639void
640lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
641{
642 MAILBOX_t *mb = &pmb->mb;
643
644 memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
645 mb->mbxCommand = MBX_KILL_BOARD;
646 mb->mbxOwner = OWN_HOST;
647 return;
648}
649
650void
640lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) 651lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
641{ 652{
642 struct lpfc_sli *psli; 653 struct lpfc_sli *psli;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 1f876328b44b..d6ffe26ae123 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1,7 +1,7 @@
1/******************************************************************* 1/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for * 2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. * 3 * Fibre Channel Host Bus Adapters. *
4 * Copyright (C) 2004-2005 Emulex. All rights reserved. * 4 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
5 * EMULEX and SLI are trademarks of Emulex. * 5 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com * 6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig * 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -513,7 +513,9 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
513 case MBX_SET_MASK: 513 case MBX_SET_MASK:
514 case MBX_SET_SLIM: 514 case MBX_SET_SLIM:
515 case MBX_UNREG_D_ID: 515 case MBX_UNREG_D_ID:
516 case MBX_KILL_BOARD:
516 case MBX_CONFIG_FARP: 517 case MBX_CONFIG_FARP:
518 case MBX_BEACON:
517 case MBX_LOAD_AREA: 519 case MBX_LOAD_AREA:
518 case MBX_RUN_BIU_DIAG64: 520 case MBX_RUN_BIU_DIAG64:
519 case MBX_CONFIG_PORT: 521 case MBX_CONFIG_PORT:
@@ -1512,98 +1514,162 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
1512 return errcnt; 1514 return errcnt;
1513} 1515}
1514 1516
1515/****************************************************************************** 1517int
1516* lpfc_sli_send_reset 1518lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
1517*
1518* Note: After returning from this function, the HBA cannot be accessed for
1519* 1 ms. Since we do not wish to delay in interrupt context, it is the
1520* responsibility of the caller to perform the mdelay(1) and flush via readl().
1521******************************************************************************/
1522static int
1523lpfc_sli_send_reset(struct lpfc_hba * phba, uint16_t skip_post)
1524{ 1519{
1525 MAILBOX_t *swpmb; 1520 uint32_t status;
1526 volatile uint32_t word0; 1521 int i = 0;
1527 void __iomem *to_slim; 1522 int retval = 0;
1528 unsigned long flags = 0;
1529 1523
1530 spin_lock_irqsave(phba->host->host_lock, flags); 1524 /* Read the HBA Host Status Register */
1525 status = readl(phba->HSregaddr);
1531 1526
1532 /* A board reset must use REAL SLIM. */ 1527 /*
1533 phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE; 1528 * Check status register every 100ms for 5 retries, then every
1529 * 500ms for 5, then every 2.5 sec for 5, then reset board and
1530 * every 2.5 sec for 4.
1531 * Break our of the loop if errors occurred during init.
1532 */
1533 while (((status & mask) != mask) &&
1534 !(status & HS_FFERM) &&
1535 i++ < 20) {
1534 1536
1535 word0 = 0; 1537 if (i <= 5)
1536 swpmb = (MAILBOX_t *) & word0; 1538 msleep(10);
1537 swpmb->mbxCommand = MBX_RESTART; 1539 else if (i <= 10)
1538 swpmb->mbxHc = 1; 1540 msleep(500);
1541 else
1542 msleep(2500);
1539 1543
1540 to_slim = phba->MBslimaddr; 1544 if (i == 15) {
1541 writel(*(uint32_t *) swpmb, to_slim); 1545 phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
1542 readl(to_slim); /* flush */ 1546 lpfc_sli_brdrestart(phba);
1547 }
1548 /* Read the HBA Host Status Register */
1549 status = readl(phba->HSregaddr);
1550 }
1543 1551
1544 /* Only skip post after fc_ffinit is completed */ 1552 /* Check to see if any errors occurred during init */
1545 if (skip_post) { 1553 if ((status & HS_FFERM) || (i >= 20)) {
1546 word0 = 1; /* This is really setting up word1 */ 1554 phba->hba_state = LPFC_HBA_ERROR;
1547 } else { 1555 retval = 1;
1548 word0 = 0; /* This is really setting up word1 */
1549 } 1556 }
1550 to_slim = phba->MBslimaddr + sizeof (uint32_t);
1551 writel(*(uint32_t *) swpmb, to_slim);
1552 readl(to_slim); /* flush */
1553 1557
1554 /* Turn off parity checking and serr during the physical reset */ 1558 return retval;
1555 pci_read_config_word(phba->pcidev, PCI_COMMAND, &phba->pci_cfg_value); 1559}
1556 pci_write_config_word(phba->pcidev, PCI_COMMAND,
1557 (phba->pci_cfg_value &
1558 ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
1559 1560
1560 writel(HC_INITFF, phba->HCregaddr); 1561int
1562lpfc_sli_brdkill(struct lpfc_hba * phba)
1563{
1564 struct lpfc_sli *psli;
1565 LPFC_MBOXQ_t *pmb;
1566 uint32_t status;
1567 uint32_t ha_copy;
1568 int retval;
1569 int i = 0;
1561 1570
1562 phba->hba_state = LPFC_INIT_START; 1571 psli = &phba->sli;
1563 spin_unlock_irqrestore(phba->host->host_lock, flags);
1564 1572
1565 return 0; 1573 /* Kill HBA */
1574 lpfc_printf_log(phba,
1575 KERN_INFO,
1576 LOG_SLI,
1577 "%d:0329 Kill HBA Data: x%x x%x\n",
1578 phba->brd_no,
1579 phba->hba_state,
1580 psli->sli_flag);
1581
1582 if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
1583 GFP_ATOMIC)) == 0) {
1584 return 1;
1585 }
1586
1587 /* Disable the error attention */
1588 spin_lock_irq(phba->host->host_lock);
1589 status = readl(phba->HCregaddr);
1590 status &= ~HC_ERINT_ENA;
1591 writel(status, phba->HCregaddr);
1592 readl(phba->HCregaddr); /* flush */
1593 spin_unlock_irq(phba->host->host_lock);
1594
1595 lpfc_kill_board(phba, pmb);
1596 pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
1597 retval = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
1598
1599 if (retval != MBX_SUCCESS) {
1600 if (retval != MBX_BUSY)
1601 mempool_free(pmb, phba->mbox_mem_pool);
1602 return 1;
1603 }
1604
1605 mempool_free(pmb, phba->mbox_mem_pool);
1606
1607 /* There is no completion for a KILL_BOARD mbox cmd. Check for an error
1608 * attention every 100ms for 3 seconds. If we don't get ERATT after
1609 * 3 seconds we still set HBA_ERROR state because the status of the
1610 * board is now undefined.
1611 */
1612 ha_copy = readl(phba->HAregaddr);
1613
1614 while ((i++ < 30) && !(ha_copy & HA_ERATT)) {
1615 mdelay(100);
1616 ha_copy = readl(phba->HAregaddr);
1617 }
1618
1619 del_timer_sync(&psli->mbox_tmo);
1620
1621 spin_lock_irq(phba->host->host_lock);
1622 psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
1623 spin_unlock_irq(phba->host->host_lock);
1624
1625 psli->mbox_active = NULL;
1626 lpfc_hba_down_post(phba);
1627 phba->hba_state = LPFC_HBA_ERROR;
1628
1629 return (ha_copy & HA_ERATT ? 0 : 1);
1566} 1630}
1567 1631
1568static int 1632int
1569lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post) 1633lpfc_sli_brdreset(struct lpfc_hba * phba)
1570{ 1634{
1635 struct lpfc_sli *psli;
1571 struct lpfc_sli_ring *pring; 1636 struct lpfc_sli_ring *pring;
1637 uint16_t cfg_value;
1572 int i; 1638 int i;
1573 struct lpfc_dmabuf *mp, *next_mp;
1574 unsigned long flags = 0;
1575
1576 lpfc_sli_send_reset(phba, skip_post);
1577 mdelay(1);
1578 1639
1579 spin_lock_irqsave(phba->host->host_lock, flags); 1640 psli = &phba->sli;
1580 /* Risk the write on flush case ie no delay after the readl */
1581 readl(phba->HCregaddr); /* flush */
1582 /* Now toggle INITFF bit set by lpfc_sli_send_reset */
1583 writel(0, phba->HCregaddr);
1584 readl(phba->HCregaddr); /* flush */
1585 1641
1586 /* Restore PCI cmd register */ 1642 /* Reset HBA */
1587 pci_write_config_word(phba->pcidev, PCI_COMMAND, phba->pci_cfg_value); 1643 lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
1644 "%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no,
1645 phba->hba_state, psli->sli_flag);
1588 1646
1589 /* perform board reset */ 1647 /* perform board reset */
1590 phba->fc_eventTag = 0; 1648 phba->fc_eventTag = 0;
1591 phba->fc_myDID = 0; 1649 phba->fc_myDID = 0;
1592 phba->fc_prevDID = Mask_DID; 1650 phba->fc_prevDID = 0;
1593 1651
1594 /* Reset HBA */ 1652 psli->sli_flag = 0;
1595 lpfc_printf_log(phba, 1653
1596 KERN_INFO, 1654 /* Turn off parity checking and serr during the physical reset */
1597 LOG_SLI, 1655 pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
1598 "%d:0325 Reset HBA Data: x%x x%x x%x\n", 1656 pci_write_config_word(phba->pcidev, PCI_COMMAND,
1599 phba->brd_no, 1657 (cfg_value &
1600 phba->hba_state, 1658 ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
1601 phba->sli.sli_flag, 1659
1602 skip_post); 1660 /* Now toggle INITFF bit in the Host Control Register */
1661 writel(HC_INITFF, phba->HCregaddr);
1662 mdelay(1);
1663 readl(phba->HCregaddr); /* flush */
1664 writel(0, phba->HCregaddr);
1665 readl(phba->HCregaddr); /* flush */
1666
1667 /* Restore PCI cmd register */
1668 pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value);
1603 1669
1604 /* Initialize relevant SLI info */ 1670 /* Initialize relevant SLI info */
1605 for (i = 0; i < phba->sli.num_rings; i++) { 1671 for (i = 0; i < psli->num_rings; i++) {
1606 pring = &phba->sli.ring[i]; 1672 pring = &psli->ring[i];
1607 pring->flag = 0; 1673 pring->flag = 0;
1608 pring->rspidx = 0; 1674 pring->rspidx = 0;
1609 pring->next_cmdidx = 0; 1675 pring->next_cmdidx = 0;
@@ -1611,27 +1677,62 @@ lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post)
1611 pring->cmdidx = 0; 1677 pring->cmdidx = 0;
1612 pring->missbufcnt = 0; 1678 pring->missbufcnt = 0;
1613 } 1679 }
1614 spin_unlock_irqrestore(phba->host->host_lock, flags);
1615 1680
1616 if (skip_post) { 1681 phba->hba_state = LPFC_WARM_START;
1617 mdelay(100); 1682 return 0;
1683}
1684
1685int
1686lpfc_sli_brdrestart(struct lpfc_hba * phba)
1687{
1688 MAILBOX_t *mb;
1689 struct lpfc_sli *psli;
1690 uint16_t skip_post;
1691 volatile uint32_t word0;
1692 void __iomem *to_slim;
1693
1694 spin_lock_irq(phba->host->host_lock);
1695
1696 psli = &phba->sli;
1697
1698 /* Restart HBA */
1699 lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
1700 "%d:0328 Restart HBA Data: x%x x%x\n", phba->brd_no,
1701 phba->hba_state, psli->sli_flag);
1702
1703 word0 = 0;
1704 mb = (MAILBOX_t *) &word0;
1705 mb->mbxCommand = MBX_RESTART;
1706 mb->mbxHc = 1;
1707
1708 to_slim = phba->MBslimaddr;
1709 writel(*(uint32_t *) mb, to_slim);
1710 readl(to_slim); /* flush */
1711
1712 /* Only skip post after fc_ffinit is completed */
1713 if (phba->hba_state) {
1714 skip_post = 1;
1715 word0 = 1; /* This is really setting up word1 */
1618 } else { 1716 } else {
1619 mdelay(2000); 1717 skip_post = 0;
1718 word0 = 0; /* This is really setting up word1 */
1620 } 1719 }
1720 to_slim = (uint8_t *) phba->MBslimaddr + sizeof (uint32_t);
1721 writel(*(uint32_t *) mb, to_slim);
1722 readl(to_slim); /* flush */
1621 1723
1622 spin_lock_irqsave(phba->host->host_lock, flags); 1724 lpfc_sli_brdreset(phba);
1623 /* Cleanup preposted buffers on the ELS ring */
1624 pring = &phba->sli.ring[LPFC_ELS_RING];
1625 list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
1626 list_del(&mp->list);
1627 pring->postbufq_cnt--;
1628 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1629 kfree(mp);
1630 }
1631 spin_unlock_irqrestore(phba->host->host_lock, flags);
1632 1725
1633 for (i = 0; i < phba->sli.num_rings; i++) 1726 phba->hba_state = LPFC_INIT_START;
1634 lpfc_sli_abort_iocb_ring(phba, &phba->sli.ring[i]); 1727
1728 spin_unlock_irq(phba->host->host_lock);
1729
1730 if (skip_post)
1731 mdelay(100);
1732 else
1733 mdelay(2000);
1734
1735 lpfc_hba_down_post(phba);
1635 1736
1636 return 0; 1737 return 0;
1637} 1738}
@@ -1691,7 +1792,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
1691 } 1792 }
1692 1793
1693 if (i == 15) { 1794 if (i == 15) {
1694 lpfc_sli_brdreset(phba, 0); 1795 phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
1796 lpfc_sli_brdrestart(phba);
1695 } 1797 }
1696 /* Read the HBA Host Status Register */ 1798 /* Read the HBA Host Status Register */
1697 status = readl(phba->HSregaddr); 1799 status = readl(phba->HSregaddr);
@@ -1735,8 +1837,8 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
1735 } 1837 }
1736 1838
1737 while (resetcount < 2 && !done) { 1839 while (resetcount < 2 && !done) {
1738 phba->hba_state = 0; 1840 phba->hba_state = LPFC_STATE_UNKNOWN;
1739 lpfc_sli_brdreset(phba, 0); 1841 lpfc_sli_brdrestart(phba);
1740 msleep(2500); 1842 msleep(2500);
1741 rc = lpfc_sli_chipset_init(phba); 1843 rc = lpfc_sli_chipset_init(phba);
1742 if (rc) 1844 if (rc)
@@ -1920,6 +2022,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
1920 mb = &pmbox->mb; 2022 mb = &pmbox->mb;
1921 status = MBX_SUCCESS; 2023 status = MBX_SUCCESS;
1922 2024
2025 if (phba->hba_state == LPFC_HBA_ERROR) {
2026 spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
2027
2028 /* Mbox command <mbxCommand> cannot issue */
2029 LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
2030 return (MBX_NOT_FINISHED);
2031 }
2032
1923 if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) { 2033 if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
1924 /* Polling for a mbox command when another one is already active 2034 /* Polling for a mbox command when another one is already active
1925 * is not allowed in SLI. Also, the driver must have established 2035 * is not allowed in SLI. Also, the driver must have established
@@ -2002,7 +2112,8 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
2002 2112
2003 /* If we are not polling, we MUST be in SLI2 mode */ 2113 /* If we are not polling, we MUST be in SLI2 mode */
2004 if (flag != MBX_POLL) { 2114 if (flag != MBX_POLL) {
2005 if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) { 2115 if (!(psli->sli_flag & LPFC_SLI2_ACTIVE) &&
2116 (mb->mbxCommand != MBX_KILL_BOARD)) {
2006 psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; 2117 psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
2007 spin_unlock_irqrestore(phba->host->host_lock, 2118 spin_unlock_irqrestore(phba->host->host_lock,
2008 drvr_flag); 2119 drvr_flag);
@@ -2035,7 +2146,8 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
2035 /* First copy command data to host SLIM area */ 2146 /* First copy command data to host SLIM area */
2036 lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE); 2147 lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE);
2037 } else { 2148 } else {
2038 if (mb->mbxCommand == MBX_CONFIG_PORT) { 2149 if (mb->mbxCommand == MBX_CONFIG_PORT ||
2150 mb->mbxCommand == MBX_KILL_BOARD) {
2039 /* copy command data into host mbox for cmpl */ 2151 /* copy command data into host mbox for cmpl */
2040 lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, 2152 lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx,
2041 MAILBOX_CMD_SIZE); 2153 MAILBOX_CMD_SIZE);
@@ -2086,8 +2198,9 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
2086 ha_copy = readl(phba->HAregaddr); 2198 ha_copy = readl(phba->HAregaddr);
2087 2199
2088 /* Wait for command to complete */ 2200 /* Wait for command to complete */
2089 while (((word0 & OWN_CHIP) == OWN_CHIP) 2201 while (((word0 & OWN_CHIP) == OWN_CHIP) ||
2090 || !(ha_copy & HA_MBATT)) { 2202 (!(ha_copy & HA_MBATT) &&
2203 (phba->hba_state > LPFC_WARM_START))) {
2091 if (i++ >= 100) { 2204 if (i++ >= 100) {
2092 psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; 2205 psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
2093 spin_unlock_irqrestore(phba->host->host_lock, 2206 spin_unlock_irqrestore(phba->host->host_lock,
@@ -2455,15 +2568,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
2455 2568
2456 spin_unlock_irqrestore(phba->host->host_lock, flags); 2569 spin_unlock_irqrestore(phba->host->host_lock, flags);
2457 2570
2458 /*
2459 * Provided the hba is not in an error state, reset it. It is not
2460 * capable of IO anymore.
2461 */
2462 if (phba->hba_state != LPFC_HBA_ERROR) {
2463 phba->hba_state = LPFC_INIT_START;
2464 lpfc_sli_brdreset(phba, 1);
2465 }
2466
2467 return 1; 2571 return 1;
2468} 2572}
2469 2573
@@ -2976,13 +3080,6 @@ lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
2976 /* Clear Chip error bit */ 3080 /* Clear Chip error bit */
2977 writel(HA_ERATT, phba->HAregaddr); 3081 writel(HA_ERATT, phba->HAregaddr);
2978 readl(phba->HAregaddr); /* flush */ 3082 readl(phba->HAregaddr); /* flush */
2979
2980 /*
2981 * Reseting the HBA is the only reliable way
2982 * to shutdown interrupt when there is a
2983 * ERROR.
2984 */
2985 lpfc_sli_send_reset(phba, 1);
2986 } 3083 }
2987 3084
2988 spin_lock(phba->host->host_lock); 3085 spin_lock(phba->host->host_lock);