aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_attr.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-04-25 09:51:45 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-05-06 10:33:13 -0400
commit46fa311e6967b526e1fd9b0b44edda6841dcac27 (patch)
tree939fe8d2023c86b17f0f4ee9f3d627e64e2604de /drivers/scsi/lpfc/lpfc_attr.c
parent07951076aefa4194e1dbf1d8c89eaff040c45155 (diff)
[SCSI] lpfc 8.1.12 : Rework offline path to solve HBA reset issues
Rework offline path to solve HBA reset issues Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_attr.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c83
1 files changed, 67 insertions, 16 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 6cc88b198fa3..c0b02b11d88f 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -20,6 +20,7 @@
20 *******************************************************************/ 20 *******************************************************************/
21 21
22#include <linux/ctype.h> 22#include <linux/ctype.h>
23#include <linux/delay.h>
23#include <linux/pci.h> 24#include <linux/pci.h>
24#include <linux/interrupt.h> 25#include <linux/interrupt.h>
25 26
@@ -213,6 +214,7 @@ lpfc_issue_lip(struct Scsi_Host *host)
213 int mbxstatus = MBXERR_ERROR; 214 int mbxstatus = MBXERR_ERROR;
214 215
215 if ((phba->fc_flag & FC_OFFLINE_MODE) || 216 if ((phba->fc_flag & FC_OFFLINE_MODE) ||
217 (phba->fc_flag & FC_BLOCK_MGMT_IO) ||
216 (phba->hba_state != LPFC_HBA_READY)) 218 (phba->hba_state != LPFC_HBA_READY))
217 return -EPERM; 219 return -EPERM;
218 220
@@ -247,19 +249,62 @@ lpfc_issue_lip(struct Scsi_Host *host)
247} 249}
248 250
249static int 251static int
250lpfc_selective_reset(struct lpfc_hba *phba) 252lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
251{ 253{
252 struct completion online_compl; 254 struct completion online_compl;
255 struct lpfc_sli_ring *pring;
256 struct lpfc_sli *psli;
253 int status = 0; 257 int status = 0;
258 int cnt = 0;
259 int i;
254 260
255 init_completion(&online_compl); 261 init_completion(&online_compl);
256 lpfc_workq_post_event(phba, &status, &online_compl, 262 lpfc_workq_post_event(phba, &status, &online_compl,
257 LPFC_EVT_OFFLINE); 263 LPFC_EVT_OFFLINE_PREP);
264 wait_for_completion(&online_compl);
265
266 if (status != 0)
267 return -EIO;
268
269 psli = &phba->sli;
270
271 for (i = 0; i < psli->num_rings; i++) {
272 pring = &psli->ring[i];
273 /* The linkdown event takes 30 seconds to timeout. */
274 while (pring->txcmplq_cnt) {
275 msleep(10);
276 if (cnt++ > 3000) {
277 lpfc_printf_log(phba,
278 KERN_WARNING, LOG_INIT,
279 "%d:0466 Outstanding IO when "
280 "bringing Adapter offline\n",
281 phba->brd_no);
282 break;
283 }
284 }
285 }
286
287 init_completion(&online_compl);
288 lpfc_workq_post_event(phba, &status, &online_compl, type);
258 wait_for_completion(&online_compl); 289 wait_for_completion(&online_compl);
259 290
260 if (status != 0) 291 if (status != 0)
261 return -EIO; 292 return -EIO;
262 293
294 return 0;
295}
296
297static int
298lpfc_selective_reset(struct lpfc_hba *phba)
299{
300 struct completion online_compl;
301 int status = 0;
302
303 status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
304
305 if (status != 0)
306 return status;
307
263 init_completion(&online_compl); 308 init_completion(&online_compl);
264 lpfc_workq_post_event(phba, &status, &online_compl, 309 lpfc_workq_post_event(phba, &status, &online_compl,
265 LPFC_EVT_ONLINE); 310 LPFC_EVT_ONLINE);
@@ -324,23 +369,19 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
324 369
325 init_completion(&online_compl); 370 init_completion(&online_compl);
326 371
327 if(strncmp(buf, "online", sizeof("online") - 1) == 0) 372 if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
328 lpfc_workq_post_event(phba, &status, &online_compl, 373 lpfc_workq_post_event(phba, &status, &online_compl,
329 LPFC_EVT_ONLINE); 374 LPFC_EVT_ONLINE);
330 else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) 375 wait_for_completion(&online_compl);
331 lpfc_workq_post_event(phba, &status, &online_compl, 376 } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
332 LPFC_EVT_OFFLINE); 377 status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
333 else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0) 378 else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
334 lpfc_workq_post_event(phba, &status, &online_compl, 379 status = lpfc_do_offline(phba, LPFC_EVT_WARM_START);
335 LPFC_EVT_WARM_START); 380 else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
336 else if (strncmp(buf, "error", sizeof("error") - 1) == 0) 381 status = lpfc_do_offline(phba, LPFC_EVT_KILL);
337 lpfc_workq_post_event(phba, &status, &online_compl,
338 LPFC_EVT_KILL);
339 else 382 else
340 return -EINVAL; 383 return -EINVAL;
341 384
342 wait_for_completion(&online_compl);
343
344 if (!status) 385 if (!status)
345 return strlen(buf); 386 return strlen(buf);
346 else 387 else
@@ -645,9 +686,7 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
645 dev_printk(KERN_NOTICE, &phba->pcidev->dev, 686 dev_printk(KERN_NOTICE, &phba->pcidev->dev,
646 "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); 687 "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
647 688
648 init_completion(&online_compl); 689 stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
649 lpfc_workq_post_event(phba, &stat1, &online_compl, LPFC_EVT_OFFLINE);
650 wait_for_completion(&online_compl);
651 if (stat1) 690 if (stat1)
652 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 691 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
653 "%d:0463 lpfc_soft_wwpn attribute set failed to reinit " 692 "%d:0463 lpfc_soft_wwpn attribute set failed to reinit "
@@ -1307,6 +1346,12 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
1307 return -EPERM; 1346 return -EPERM;
1308 } 1347 }
1309 1348
1349 if (phba->fc_flag & FC_BLOCK_MGMT_IO) {
1350 sysfs_mbox_idle(phba);
1351 spin_unlock_irq(host->host_lock);
1352 return -EAGAIN;
1353 }
1354
1310 if ((phba->fc_flag & FC_OFFLINE_MODE) || 1355 if ((phba->fc_flag & FC_OFFLINE_MODE) ||
1311 (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){ 1356 (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
1312 1357
@@ -1551,6 +1596,9 @@ lpfc_get_stats(struct Scsi_Host *shost)
1551 unsigned long seconds; 1596 unsigned long seconds;
1552 int rc = 0; 1597 int rc = 0;
1553 1598
1599 if (phba->fc_flag & FC_BLOCK_MGMT_IO)
1600 return NULL;
1601
1554 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 1602 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1555 if (!pmboxq) 1603 if (!pmboxq)
1556 return NULL; 1604 return NULL;
@@ -1651,6 +1699,9 @@ lpfc_reset_stats(struct Scsi_Host *shost)
1651 MAILBOX_t *pmb; 1699 MAILBOX_t *pmb;
1652 int rc = 0; 1700 int rc = 0;
1653 1701
1702 if (phba->fc_flag & FC_BLOCK_MGMT_IO)
1703 return;
1704
1654 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 1705 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1655 if (!pmboxq) 1706 if (!pmboxq)
1656 return; 1707 return;