diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:51:45 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:13 -0400 |
commit | 46fa311e6967b526e1fd9b0b44edda6841dcac27 (patch) | |
tree | 939fe8d2023c86b17f0f4ee9f3d627e64e2604de /drivers/scsi/lpfc/lpfc_attr.c | |
parent | 07951076aefa4194e1dbf1d8c89eaff040c45155 (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.c | 83 |
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 | ||
249 | static int | 251 | static int |
250 | lpfc_selective_reset(struct lpfc_hba *phba) | 252 | lpfc_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 | |||
297 | static int | ||
298 | lpfc_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; |