diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:53:22 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:16 -0400 |
commit | 47a8617c7df6cc8b8617a3deb5a36bbae1997d13 (patch) | |
tree | ba592dbafd7f3144e3ed0a210cefe7ed89b96058 /drivers | |
parent | ebdbe65f07bb26baf69fcb0ee332702064888018 (diff) |
[SCSI] lpfc 8.1.12 : Add support for async scanning
Add support for async scanning
Notes: This is the async scan patch to our driver from Matthew Wilcox.
The async scan logic is still subject to errors in insmod/rmmod, as
the async scan threads don't get shutdown when the module unloads
underneath them. See http://marc.info/?l=linux-scsi&m=117551999925582&w=2
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 305 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 2 |
3 files changed, 160 insertions, 150 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 9f70b5bc0950..e4454bc37782 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -200,6 +200,9 @@ void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t); | |||
200 | 200 | ||
201 | /* Function prototypes. */ | 201 | /* Function prototypes. */ |
202 | const char* lpfc_info(struct Scsi_Host *); | 202 | const char* lpfc_info(struct Scsi_Host *); |
203 | void lpfc_scan_start(struct Scsi_Host *); | ||
204 | int lpfc_scan_finished(struct Scsi_Host *, unsigned long); | ||
205 | |||
203 | void lpfc_get_cfgparam(struct lpfc_hba *); | 206 | void lpfc_get_cfgparam(struct lpfc_hba *); |
204 | int lpfc_alloc_sysfs_attr(struct lpfc_hba *); | 207 | int lpfc_alloc_sysfs_attr(struct lpfc_hba *); |
205 | void lpfc_free_sysfs_attr(struct lpfc_hba *); | 208 | void lpfc_free_sysfs_attr(struct lpfc_hba *); |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 5e9a839111d2..7cb92c7531ba 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -418,33 +418,6 @@ lpfc_config_port_post(struct lpfc_hba * phba) | |||
418 | return (0); | 418 | return (0); |
419 | } | 419 | } |
420 | 420 | ||
421 | static int | ||
422 | lpfc_discovery_wait(struct lpfc_hba *phba) | ||
423 | { | ||
424 | int i = 0; | ||
425 | |||
426 | while ((phba->hba_state != LPFC_HBA_READY) || | ||
427 | (phba->num_disc_nodes) || (phba->fc_prli_sent) || | ||
428 | ((phba->fc_map_cnt == 0) && (i<2)) || | ||
429 | (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)) { | ||
430 | /* Check every second for 30 retries. */ | ||
431 | i++; | ||
432 | if (i > 30) { | ||
433 | return -ETIMEDOUT; | ||
434 | } | ||
435 | if ((i >= 15) && (phba->hba_state <= LPFC_LINK_DOWN)) { | ||
436 | /* The link is down. Set linkdown timeout */ | ||
437 | return -ETIMEDOUT; | ||
438 | } | ||
439 | |||
440 | /* Delay for 1 second to give discovery time to complete. */ | ||
441 | msleep(1000); | ||
442 | |||
443 | } | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | /************************************************************************/ | 421 | /************************************************************************/ |
449 | /* */ | 422 | /* */ |
450 | /* lpfc_hba_down_prep */ | 423 | /* lpfc_hba_down_prep */ |
@@ -1362,6 +1335,156 @@ lpfc_scsi_free(struct lpfc_hba * phba) | |||
1362 | return 0; | 1335 | return 0; |
1363 | } | 1336 | } |
1364 | 1337 | ||
1338 | void lpfc_remove_device(struct lpfc_hba *phba) | ||
1339 | { | ||
1340 | unsigned long iflag; | ||
1341 | |||
1342 | lpfc_free_sysfs_attr(phba); | ||
1343 | |||
1344 | spin_lock_irqsave(phba->host->host_lock, iflag); | ||
1345 | phba->fc_flag |= FC_UNLOADING; | ||
1346 | |||
1347 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
1348 | |||
1349 | fc_remove_host(phba->host); | ||
1350 | scsi_remove_host(phba->host); | ||
1351 | |||
1352 | kthread_stop(phba->worker_thread); | ||
1353 | |||
1354 | /* | ||
1355 | * Bring down the SLI Layer. This step disable all interrupts, | ||
1356 | * clears the rings, discards all mailbox commands, and resets | ||
1357 | * the HBA. | ||
1358 | */ | ||
1359 | lpfc_sli_hba_down(phba); | ||
1360 | lpfc_sli_brdrestart(phba); | ||
1361 | |||
1362 | /* Release the irq reservation */ | ||
1363 | free_irq(phba->pcidev->irq, phba); | ||
1364 | pci_disable_msi(phba->pcidev); | ||
1365 | |||
1366 | lpfc_cleanup(phba); | ||
1367 | lpfc_stop_timer(phba); | ||
1368 | phba->work_hba_events = 0; | ||
1369 | |||
1370 | /* | ||
1371 | * Call scsi_free before mem_free since scsi bufs are released to their | ||
1372 | * corresponding pools here. | ||
1373 | */ | ||
1374 | lpfc_scsi_free(phba); | ||
1375 | lpfc_mem_free(phba); | ||
1376 | |||
1377 | /* Free resources associated with SLI2 interface */ | ||
1378 | dma_free_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE, | ||
1379 | phba->slim2p, phba->slim2p_mapping); | ||
1380 | |||
1381 | /* unmap adapter SLIM and Control Registers */ | ||
1382 | iounmap(phba->ctrl_regs_memmap_p); | ||
1383 | iounmap(phba->slim_memmap_p); | ||
1384 | |||
1385 | pci_release_regions(phba->pcidev); | ||
1386 | pci_disable_device(phba->pcidev); | ||
1387 | |||
1388 | idr_remove(&lpfc_hba_index, phba->brd_no); | ||
1389 | scsi_host_put(phba->host); | ||
1390 | } | ||
1391 | |||
1392 | void lpfc_scan_start(struct Scsi_Host *host) | ||
1393 | { | ||
1394 | struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; | ||
1395 | |||
1396 | if (lpfc_alloc_sysfs_attr(phba)) | ||
1397 | goto error; | ||
1398 | |||
1399 | phba->MBslimaddr = phba->slim_memmap_p; | ||
1400 | phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET; | ||
1401 | phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET; | ||
1402 | phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET; | ||
1403 | phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET; | ||
1404 | |||
1405 | if (lpfc_sli_hba_setup(phba)) | ||
1406 | goto error; | ||
1407 | |||
1408 | /* | ||
1409 | * hba setup may have changed the hba_queue_depth so we need to adjust | ||
1410 | * the value of can_queue. | ||
1411 | */ | ||
1412 | host->can_queue = phba->cfg_hba_queue_depth - 10; | ||
1413 | return; | ||
1414 | |||
1415 | error: | ||
1416 | lpfc_remove_device(phba); | ||
1417 | } | ||
1418 | |||
1419 | int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) | ||
1420 | { | ||
1421 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; | ||
1422 | |||
1423 | if (!phba->host) | ||
1424 | return 1; | ||
1425 | if (time >= 30 * HZ) | ||
1426 | goto finished; | ||
1427 | |||
1428 | if (phba->hba_state != LPFC_HBA_READY) | ||
1429 | return 0; | ||
1430 | if (phba->num_disc_nodes || phba->fc_prli_sent) | ||
1431 | return 0; | ||
1432 | if ((phba->fc_map_cnt == 0) && (time < 2 * HZ)) | ||
1433 | return 0; | ||
1434 | if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) | ||
1435 | return 0; | ||
1436 | if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ)) | ||
1437 | return 0; | ||
1438 | |||
1439 | finished: | ||
1440 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) { | ||
1441 | spin_lock_irq(shost->host_lock); | ||
1442 | lpfc_poll_start_timer(phba); | ||
1443 | spin_unlock_irq(shost->host_lock); | ||
1444 | } | ||
1445 | |||
1446 | /* | ||
1447 | * set fixed host attributes | ||
1448 | * Must done after lpfc_sli_hba_setup() | ||
1449 | */ | ||
1450 | |||
1451 | fc_host_node_name(shost) = wwn_to_u64(phba->fc_nodename.u.wwn); | ||
1452 | fc_host_port_name(shost) = wwn_to_u64(phba->fc_portname.u.wwn); | ||
1453 | fc_host_supported_classes(shost) = FC_COS_CLASS3; | ||
1454 | |||
1455 | memset(fc_host_supported_fc4s(shost), 0, | ||
1456 | sizeof(fc_host_supported_fc4s(shost))); | ||
1457 | fc_host_supported_fc4s(shost)[2] = 1; | ||
1458 | fc_host_supported_fc4s(shost)[7] = 1; | ||
1459 | |||
1460 | lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost)); | ||
1461 | |||
1462 | fc_host_supported_speeds(shost) = 0; | ||
1463 | if (phba->lmt & LMT_10Gb) | ||
1464 | fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT; | ||
1465 | if (phba->lmt & LMT_4Gb) | ||
1466 | fc_host_supported_speeds(shost) |= FC_PORTSPEED_4GBIT; | ||
1467 | if (phba->lmt & LMT_2Gb) | ||
1468 | fc_host_supported_speeds(shost) |= FC_PORTSPEED_2GBIT; | ||
1469 | if (phba->lmt & LMT_1Gb) | ||
1470 | fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT; | ||
1471 | |||
1472 | fc_host_maxframe_size(shost) = | ||
1473 | ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) | | ||
1474 | (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb); | ||
1475 | |||
1476 | /* This value is also unchanging */ | ||
1477 | memset(fc_host_active_fc4s(shost), 0, | ||
1478 | sizeof(fc_host_active_fc4s(shost))); | ||
1479 | fc_host_active_fc4s(shost)[2] = 1; | ||
1480 | fc_host_active_fc4s(shost)[7] = 1; | ||
1481 | |||
1482 | spin_lock_irq(shost->host_lock); | ||
1483 | phba->fc_flag &= ~FC_LOADING; | ||
1484 | spin_unlock_irq(shost->host_lock); | ||
1485 | |||
1486 | return 1; | ||
1487 | } | ||
1365 | 1488 | ||
1366 | static int __devinit | 1489 | static int __devinit |
1367 | lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | 1490 | lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) |
@@ -1552,13 +1675,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1552 | 1675 | ||
1553 | host->transportt = lpfc_transport_template; | 1676 | host->transportt = lpfc_transport_template; |
1554 | pci_set_drvdata(pdev, host); | 1677 | pci_set_drvdata(pdev, host); |
1555 | error = scsi_add_host(host, &pdev->dev); | ||
1556 | if (error) | ||
1557 | goto out_kthread_stop; | ||
1558 | |||
1559 | error = lpfc_alloc_sysfs_attr(phba); | ||
1560 | if (error) | ||
1561 | goto out_remove_host; | ||
1562 | 1678 | ||
1563 | if (phba->cfg_use_msi) { | 1679 | if (phba->cfg_use_msi) { |
1564 | error = pci_enable_msi(phba->pcidev); | 1680 | error = pci_enable_msi(phba->pcidev); |
@@ -1574,73 +1690,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1574 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 1690 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
1575 | "%d:0451 Enable interrupt handler failed\n", | 1691 | "%d:0451 Enable interrupt handler failed\n", |
1576 | phba->brd_no); | 1692 | phba->brd_no); |
1577 | goto out_free_sysfs_attr; | 1693 | goto out_kthread_stop; |
1578 | } | 1694 | } |
1579 | phba->MBslimaddr = phba->slim_memmap_p; | ||
1580 | phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET; | ||
1581 | phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET; | ||
1582 | phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET; | ||
1583 | phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET; | ||
1584 | 1695 | ||
1585 | error = lpfc_sli_hba_setup(phba); | 1696 | error = scsi_add_host(host, &pdev->dev); |
1586 | if (error) { | 1697 | if (error) |
1587 | error = -ENODEV; | ||
1588 | goto out_free_irq; | 1698 | goto out_free_irq; |
1589 | } | ||
1590 | |||
1591 | /* | ||
1592 | * hba setup may have changed the hba_queue_depth so we need to adjust | ||
1593 | * the value of can_queue. | ||
1594 | */ | ||
1595 | host->can_queue = phba->cfg_hba_queue_depth - 10; | ||
1596 | |||
1597 | lpfc_discovery_wait(phba); | ||
1598 | |||
1599 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) { | ||
1600 | spin_lock_irq(phba->host->host_lock); | ||
1601 | lpfc_poll_start_timer(phba); | ||
1602 | spin_unlock_irq(phba->host->host_lock); | ||
1603 | } | ||
1604 | 1699 | ||
1605 | /* | 1700 | scsi_scan_host(host); |
1606 | * set fixed host attributes | ||
1607 | * Must done after lpfc_sli_hba_setup() | ||
1608 | */ | ||
1609 | |||
1610 | fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.u.wwn); | ||
1611 | fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.u.wwn); | ||
1612 | fc_host_supported_classes(host) = FC_COS_CLASS3; | ||
1613 | |||
1614 | memset(fc_host_supported_fc4s(host), 0, | ||
1615 | sizeof(fc_host_supported_fc4s(host))); | ||
1616 | fc_host_supported_fc4s(host)[2] = 1; | ||
1617 | fc_host_supported_fc4s(host)[7] = 1; | ||
1618 | |||
1619 | lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(host)); | ||
1620 | |||
1621 | fc_host_supported_speeds(host) = 0; | ||
1622 | if (phba->lmt & LMT_10Gb) | ||
1623 | fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT; | ||
1624 | if (phba->lmt & LMT_4Gb) | ||
1625 | fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT; | ||
1626 | if (phba->lmt & LMT_2Gb) | ||
1627 | fc_host_supported_speeds(host) |= FC_PORTSPEED_2GBIT; | ||
1628 | if (phba->lmt & LMT_1Gb) | ||
1629 | fc_host_supported_speeds(host) |= FC_PORTSPEED_1GBIT; | ||
1630 | |||
1631 | fc_host_maxframe_size(host) = | ||
1632 | ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) | | ||
1633 | (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb); | ||
1634 | |||
1635 | /* This value is also unchanging */ | ||
1636 | memset(fc_host_active_fc4s(host), 0, | ||
1637 | sizeof(fc_host_active_fc4s(host))); | ||
1638 | fc_host_active_fc4s(host)[2] = 1; | ||
1639 | fc_host_active_fc4s(host)[7] = 1; | ||
1640 | 1701 | ||
1641 | spin_lock_irq(phba->host->host_lock); | ||
1642 | phba->fc_flag &= ~FC_LOADING; | ||
1643 | spin_unlock_irq(phba->host->host_lock); | ||
1644 | return 0; | 1702 | return 0; |
1645 | 1703 | ||
1646 | out_free_irq: | 1704 | out_free_irq: |
@@ -1648,11 +1706,6 @@ out_free_irq: | |||
1648 | phba->work_hba_events = 0; | 1706 | phba->work_hba_events = 0; |
1649 | free_irq(phba->pcidev->irq, phba); | 1707 | free_irq(phba->pcidev->irq, phba); |
1650 | pci_disable_msi(phba->pcidev); | 1708 | pci_disable_msi(phba->pcidev); |
1651 | out_free_sysfs_attr: | ||
1652 | lpfc_free_sysfs_attr(phba); | ||
1653 | out_remove_host: | ||
1654 | fc_remove_host(phba->host); | ||
1655 | scsi_remove_host(phba->host); | ||
1656 | out_kthread_stop: | 1709 | out_kthread_stop: |
1657 | kthread_stop(phba->worker_thread); | 1710 | kthread_stop(phba->worker_thread); |
1658 | out_free_iocbq: | 1711 | out_free_iocbq: |
@@ -1690,56 +1743,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
1690 | { | 1743 | { |
1691 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 1744 | struct Scsi_Host *host = pci_get_drvdata(pdev); |
1692 | struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; | 1745 | struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; |
1693 | unsigned long iflag; | ||
1694 | |||
1695 | lpfc_free_sysfs_attr(phba); | ||
1696 | |||
1697 | spin_lock_irqsave(phba->host->host_lock, iflag); | ||
1698 | phba->fc_flag |= FC_UNLOADING; | ||
1699 | |||
1700 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
1701 | |||
1702 | fc_remove_host(phba->host); | ||
1703 | scsi_remove_host(phba->host); | ||
1704 | |||
1705 | kthread_stop(phba->worker_thread); | ||
1706 | |||
1707 | /* | ||
1708 | * Bring down the SLI Layer. This step disable all interrupts, | ||
1709 | * clears the rings, discards all mailbox commands, and resets | ||
1710 | * the HBA. | ||
1711 | */ | ||
1712 | lpfc_sli_hba_down(phba); | ||
1713 | lpfc_sli_brdrestart(phba); | ||
1714 | 1746 | ||
1715 | /* Release the irq reservation */ | 1747 | lpfc_remove_device(phba); |
1716 | free_irq(phba->pcidev->irq, phba); | ||
1717 | pci_disable_msi(phba->pcidev); | ||
1718 | |||
1719 | lpfc_cleanup(phba); | ||
1720 | lpfc_stop_timer(phba); | ||
1721 | phba->work_hba_events = 0; | ||
1722 | |||
1723 | /* | ||
1724 | * Call scsi_free before mem_free since scsi bufs are released to their | ||
1725 | * corresponding pools here. | ||
1726 | */ | ||
1727 | lpfc_scsi_free(phba); | ||
1728 | lpfc_mem_free(phba); | ||
1729 | |||
1730 | /* Free resources associated with SLI2 interface */ | ||
1731 | dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, | ||
1732 | phba->slim2p, phba->slim2p_mapping); | ||
1733 | |||
1734 | /* unmap adapter SLIM and Control Registers */ | ||
1735 | iounmap(phba->ctrl_regs_memmap_p); | ||
1736 | iounmap(phba->slim_memmap_p); | ||
1737 | |||
1738 | pci_release_regions(phba->pcidev); | ||
1739 | pci_disable_device(phba->pcidev); | ||
1740 | |||
1741 | idr_remove(&lpfc_hba_index, phba->brd_no); | ||
1742 | scsi_host_put(phba->host); | ||
1743 | 1748 | ||
1744 | pci_set_drvdata(pdev, NULL); | 1749 | pci_set_drvdata(pdev, NULL); |
1745 | } | 1750 | } |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index cc0f845d8b38..f09f3d211438 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -1351,6 +1351,8 @@ struct scsi_host_template lpfc_template = { | |||
1351 | .slave_alloc = lpfc_slave_alloc, | 1351 | .slave_alloc = lpfc_slave_alloc, |
1352 | .slave_configure = lpfc_slave_configure, | 1352 | .slave_configure = lpfc_slave_configure, |
1353 | .slave_destroy = lpfc_slave_destroy, | 1353 | .slave_destroy = lpfc_slave_destroy, |
1354 | .scan_finished = lpfc_scan_finished, | ||
1355 | .scan_start = lpfc_scan_start, | ||
1354 | .this_id = -1, | 1356 | .this_id = -1, |
1355 | .sg_tablesize = LPFC_SG_SEG_CNT, | 1357 | .sg_tablesize = LPFC_SG_SEG_CNT, |
1356 | .cmd_per_lun = LPFC_CMD_PER_LUN, | 1358 | .cmd_per_lun = LPFC_CMD_PER_LUN, |