diff options
author | James Smart <james.smart@emulex.com> | 2010-02-12 14:42:33 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-02-17 18:41:04 -0500 |
commit | 84d1b006978e78e27f22beb5cfbc4d349bac6df7 (patch) | |
tree | 0bb3f71b6a5389a8570e49493431d77b6ee5993c /drivers | |
parent | 28baac7492fa084dbff6a1b9c4b42ed0d014b558 (diff) |
[SCSI] lpfc 8.3.9: Changes to sysfs interface for the lpfc driver.
- Convert all sysfs parameters to uint instead of int.
- Add lpfc_supress_link_up parameter.
- Change link_state to writable sysfs parameter.
- Add support to be able to "up" or "down" link from link_state parameter.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 110 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 100 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 1 |
4 files changed, 183 insertions, 33 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index a40a45b8aede..84b696463a58 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -504,6 +504,10 @@ struct lpfc_hba { | |||
504 | (struct lpfc_hba *); | 504 | (struct lpfc_hba *); |
505 | void (*lpfc_stop_port) | 505 | void (*lpfc_stop_port) |
506 | (struct lpfc_hba *); | 506 | (struct lpfc_hba *); |
507 | int (*lpfc_hba_init_link) | ||
508 | (struct lpfc_hba *); | ||
509 | int (*lpfc_hba_down_link) | ||
510 | (struct lpfc_hba *); | ||
507 | 511 | ||
508 | 512 | ||
509 | /* SLI4 specific HBA data structure */ | 513 | /* SLI4 specific HBA data structure */ |
@@ -618,6 +622,7 @@ struct lpfc_hba { | |||
618 | uint32_t cfg_enable_bg; | 622 | uint32_t cfg_enable_bg; |
619 | uint32_t cfg_log_verbose; | 623 | uint32_t cfg_log_verbose; |
620 | uint32_t cfg_aer_support; | 624 | uint32_t cfg_aer_support; |
625 | uint32_t cfg_suppress_link_up; | ||
621 | 626 | ||
622 | lpfc_vpd_t vpd; /* vital product data */ | 627 | lpfc_vpd_t vpd; /* vital product data */ |
623 | 628 | ||
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index a8908e7c368a..c992e8328f9e 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -482,6 +482,41 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr, | |||
482 | } | 482 | } |
483 | 483 | ||
484 | /** | 484 | /** |
485 | * lpfc_link_state_store - Transition the link_state on an HBA port | ||
486 | * @dev: class device that is converted into a Scsi_host. | ||
487 | * @attr: device attribute, not used. | ||
488 | * @buf: one or more lpfc_polling_flags values. | ||
489 | * @count: not used. | ||
490 | * | ||
491 | * Returns: | ||
492 | * -EINVAL if the buffer is not "up" or "down" | ||
493 | * return from link state change function if non-zero | ||
494 | * length of the buf on success | ||
495 | **/ | ||
496 | static ssize_t | ||
497 | lpfc_link_state_store(struct device *dev, struct device_attribute *attr, | ||
498 | const char *buf, size_t count) | ||
499 | { | ||
500 | struct Scsi_Host *shost = class_to_shost(dev); | ||
501 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
502 | struct lpfc_hba *phba = vport->phba; | ||
503 | |||
504 | int status = -EINVAL; | ||
505 | |||
506 | if ((strncmp(buf, "up", sizeof("up") - 1) == 0) && | ||
507 | (phba->link_state == LPFC_LINK_DOWN)) | ||
508 | status = phba->lpfc_hba_init_link(phba); | ||
509 | else if ((strncmp(buf, "down", sizeof("down") - 1) == 0) && | ||
510 | (phba->link_state >= LPFC_LINK_UP)) | ||
511 | status = phba->lpfc_hba_down_link(phba); | ||
512 | |||
513 | if (status == 0) | ||
514 | return strlen(buf); | ||
515 | else | ||
516 | return status; | ||
517 | } | ||
518 | |||
519 | /** | ||
485 | * lpfc_num_discovered_ports_show - Return sum of mapped and unmapped vports | 520 | * lpfc_num_discovered_ports_show - Return sum of mapped and unmapped vports |
486 | * @dev: class device that is converted into a Scsi_host. | 521 | * @dev: class device that is converted into a Scsi_host. |
487 | * @attr: device attribute, not used. | 522 | * @attr: device attribute, not used. |
@@ -1219,7 +1254,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ | |||
1219 | struct Scsi_Host *shost = class_to_shost(dev);\ | 1254 | struct Scsi_Host *shost = class_to_shost(dev);\ |
1220 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ | 1255 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ |
1221 | struct lpfc_hba *phba = vport->phba;\ | 1256 | struct lpfc_hba *phba = vport->phba;\ |
1222 | int val = 0;\ | 1257 | uint val = 0;\ |
1223 | val = phba->cfg_##attr;\ | 1258 | val = phba->cfg_##attr;\ |
1224 | return snprintf(buf, PAGE_SIZE, "%d\n",\ | 1259 | return snprintf(buf, PAGE_SIZE, "%d\n",\ |
1225 | phba->cfg_##attr);\ | 1260 | phba->cfg_##attr);\ |
@@ -1247,7 +1282,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ | |||
1247 | struct Scsi_Host *shost = class_to_shost(dev);\ | 1282 | struct Scsi_Host *shost = class_to_shost(dev);\ |
1248 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ | 1283 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ |
1249 | struct lpfc_hba *phba = vport->phba;\ | 1284 | struct lpfc_hba *phba = vport->phba;\ |
1250 | int val = 0;\ | 1285 | uint val = 0;\ |
1251 | val = phba->cfg_##attr;\ | 1286 | val = phba->cfg_##attr;\ |
1252 | return snprintf(buf, PAGE_SIZE, "%#x\n",\ | 1287 | return snprintf(buf, PAGE_SIZE, "%#x\n",\ |
1253 | phba->cfg_##attr);\ | 1288 | phba->cfg_##attr);\ |
@@ -1274,7 +1309,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ | |||
1274 | **/ | 1309 | **/ |
1275 | #define lpfc_param_init(attr, default, minval, maxval) \ | 1310 | #define lpfc_param_init(attr, default, minval, maxval) \ |
1276 | static int \ | 1311 | static int \ |
1277 | lpfc_##attr##_init(struct lpfc_hba *phba, int val) \ | 1312 | lpfc_##attr##_init(struct lpfc_hba *phba, uint val) \ |
1278 | { \ | 1313 | { \ |
1279 | if (val >= minval && val <= maxval) {\ | 1314 | if (val >= minval && val <= maxval) {\ |
1280 | phba->cfg_##attr = val;\ | 1315 | phba->cfg_##attr = val;\ |
@@ -1309,7 +1344,7 @@ lpfc_##attr##_init(struct lpfc_hba *phba, int val) \ | |||
1309 | **/ | 1344 | **/ |
1310 | #define lpfc_param_set(attr, default, minval, maxval) \ | 1345 | #define lpfc_param_set(attr, default, minval, maxval) \ |
1311 | static int \ | 1346 | static int \ |
1312 | lpfc_##attr##_set(struct lpfc_hba *phba, int val) \ | 1347 | lpfc_##attr##_set(struct lpfc_hba *phba, uint val) \ |
1313 | { \ | 1348 | { \ |
1314 | if (val >= minval && val <= maxval) {\ | 1349 | if (val >= minval && val <= maxval) {\ |
1315 | phba->cfg_##attr = val;\ | 1350 | phba->cfg_##attr = val;\ |
@@ -1350,7 +1385,7 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ | |||
1350 | struct Scsi_Host *shost = class_to_shost(dev);\ | 1385 | struct Scsi_Host *shost = class_to_shost(dev);\ |
1351 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ | 1386 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ |
1352 | struct lpfc_hba *phba = vport->phba;\ | 1387 | struct lpfc_hba *phba = vport->phba;\ |
1353 | int val=0;\ | 1388 | uint val = 0;\ |
1354 | if (!isdigit(buf[0]))\ | 1389 | if (!isdigit(buf[0]))\ |
1355 | return -EINVAL;\ | 1390 | return -EINVAL;\ |
1356 | if (sscanf(buf, "%i", &val) != 1)\ | 1391 | if (sscanf(buf, "%i", &val) != 1)\ |
@@ -1382,7 +1417,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ | |||
1382 | { \ | 1417 | { \ |
1383 | struct Scsi_Host *shost = class_to_shost(dev);\ | 1418 | struct Scsi_Host *shost = class_to_shost(dev);\ |
1384 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ | 1419 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ |
1385 | int val = 0;\ | 1420 | uint val = 0;\ |
1386 | val = vport->cfg_##attr;\ | 1421 | val = vport->cfg_##attr;\ |
1387 | return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\ | 1422 | return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\ |
1388 | } | 1423 | } |
@@ -1409,7 +1444,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ | |||
1409 | { \ | 1444 | { \ |
1410 | struct Scsi_Host *shost = class_to_shost(dev);\ | 1445 | struct Scsi_Host *shost = class_to_shost(dev);\ |
1411 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ | 1446 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ |
1412 | int val = 0;\ | 1447 | uint val = 0;\ |
1413 | val = vport->cfg_##attr;\ | 1448 | val = vport->cfg_##attr;\ |
1414 | return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\ | 1449 | return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\ |
1415 | } | 1450 | } |
@@ -1434,7 +1469,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ | |||
1434 | **/ | 1469 | **/ |
1435 | #define lpfc_vport_param_init(attr, default, minval, maxval) \ | 1470 | #define lpfc_vport_param_init(attr, default, minval, maxval) \ |
1436 | static int \ | 1471 | static int \ |
1437 | lpfc_##attr##_init(struct lpfc_vport *vport, int val) \ | 1472 | lpfc_##attr##_init(struct lpfc_vport *vport, uint val) \ |
1438 | { \ | 1473 | { \ |
1439 | if (val >= minval && val <= maxval) {\ | 1474 | if (val >= minval && val <= maxval) {\ |
1440 | vport->cfg_##attr = val;\ | 1475 | vport->cfg_##attr = val;\ |
@@ -1466,7 +1501,7 @@ lpfc_##attr##_init(struct lpfc_vport *vport, int val) \ | |||
1466 | **/ | 1501 | **/ |
1467 | #define lpfc_vport_param_set(attr, default, minval, maxval) \ | 1502 | #define lpfc_vport_param_set(attr, default, minval, maxval) \ |
1468 | static int \ | 1503 | static int \ |
1469 | lpfc_##attr##_set(struct lpfc_vport *vport, int val) \ | 1504 | lpfc_##attr##_set(struct lpfc_vport *vport, uint val) \ |
1470 | { \ | 1505 | { \ |
1471 | if (val >= minval && val <= maxval) {\ | 1506 | if (val >= minval && val <= maxval) {\ |
1472 | vport->cfg_##attr = val;\ | 1507 | vport->cfg_##attr = val;\ |
@@ -1502,7 +1537,7 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ | |||
1502 | { \ | 1537 | { \ |
1503 | struct Scsi_Host *shost = class_to_shost(dev);\ | 1538 | struct Scsi_Host *shost = class_to_shost(dev);\ |
1504 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ | 1539 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ |
1505 | int val=0;\ | 1540 | uint val = 0;\ |
1506 | if (!isdigit(buf[0]))\ | 1541 | if (!isdigit(buf[0]))\ |
1507 | return -EINVAL;\ | 1542 | return -EINVAL;\ |
1508 | if (sscanf(buf, "%i", &val) != 1)\ | 1543 | if (sscanf(buf, "%i", &val) != 1)\ |
@@ -1515,22 +1550,22 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ | |||
1515 | 1550 | ||
1516 | 1551 | ||
1517 | #define LPFC_ATTR(name, defval, minval, maxval, desc) \ | 1552 | #define LPFC_ATTR(name, defval, minval, maxval, desc) \ |
1518 | static int lpfc_##name = defval;\ | 1553 | static uint lpfc_##name = defval;\ |
1519 | module_param(lpfc_##name, int, 0);\ | 1554 | module_param(lpfc_##name, uint, 0);\ |
1520 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1555 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1521 | lpfc_param_init(name, defval, minval, maxval) | 1556 | lpfc_param_init(name, defval, minval, maxval) |
1522 | 1557 | ||
1523 | #define LPFC_ATTR_R(name, defval, minval, maxval, desc) \ | 1558 | #define LPFC_ATTR_R(name, defval, minval, maxval, desc) \ |
1524 | static int lpfc_##name = defval;\ | 1559 | static uint lpfc_##name = defval;\ |
1525 | module_param(lpfc_##name, int, 0);\ | 1560 | module_param(lpfc_##name, uint, 0);\ |
1526 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1561 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1527 | lpfc_param_show(name)\ | 1562 | lpfc_param_show(name)\ |
1528 | lpfc_param_init(name, defval, minval, maxval)\ | 1563 | lpfc_param_init(name, defval, minval, maxval)\ |
1529 | static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) | 1564 | static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) |
1530 | 1565 | ||
1531 | #define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \ | 1566 | #define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \ |
1532 | static int lpfc_##name = defval;\ | 1567 | static uint lpfc_##name = defval;\ |
1533 | module_param(lpfc_##name, int, 0);\ | 1568 | module_param(lpfc_##name, uint, 0);\ |
1534 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1569 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1535 | lpfc_param_show(name)\ | 1570 | lpfc_param_show(name)\ |
1536 | lpfc_param_init(name, defval, minval, maxval)\ | 1571 | lpfc_param_init(name, defval, minval, maxval)\ |
@@ -1540,16 +1575,16 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\ | |||
1540 | lpfc_##name##_show, lpfc_##name##_store) | 1575 | lpfc_##name##_show, lpfc_##name##_store) |
1541 | 1576 | ||
1542 | #define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \ | 1577 | #define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \ |
1543 | static int lpfc_##name = defval;\ | 1578 | static uint lpfc_##name = defval;\ |
1544 | module_param(lpfc_##name, int, 0);\ | 1579 | module_param(lpfc_##name, uint, 0);\ |
1545 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1580 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1546 | lpfc_param_hex_show(name)\ | 1581 | lpfc_param_hex_show(name)\ |
1547 | lpfc_param_init(name, defval, minval, maxval)\ | 1582 | lpfc_param_init(name, defval, minval, maxval)\ |
1548 | static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) | 1583 | static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) |
1549 | 1584 | ||
1550 | #define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \ | 1585 | #define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \ |
1551 | static int lpfc_##name = defval;\ | 1586 | static uint lpfc_##name = defval;\ |
1552 | module_param(lpfc_##name, int, 0);\ | 1587 | module_param(lpfc_##name, uint, 0);\ |
1553 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1588 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1554 | lpfc_param_hex_show(name)\ | 1589 | lpfc_param_hex_show(name)\ |
1555 | lpfc_param_init(name, defval, minval, maxval)\ | 1590 | lpfc_param_init(name, defval, minval, maxval)\ |
@@ -1559,22 +1594,22 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\ | |||
1559 | lpfc_##name##_show, lpfc_##name##_store) | 1594 | lpfc_##name##_show, lpfc_##name##_store) |
1560 | 1595 | ||
1561 | #define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \ | 1596 | #define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \ |
1562 | static int lpfc_##name = defval;\ | 1597 | static uint lpfc_##name = defval;\ |
1563 | module_param(lpfc_##name, int, 0);\ | 1598 | module_param(lpfc_##name, uint, 0);\ |
1564 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1599 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1565 | lpfc_vport_param_init(name, defval, minval, maxval) | 1600 | lpfc_vport_param_init(name, defval, minval, maxval) |
1566 | 1601 | ||
1567 | #define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \ | 1602 | #define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \ |
1568 | static int lpfc_##name = defval;\ | 1603 | static uint lpfc_##name = defval;\ |
1569 | module_param(lpfc_##name, int, 0);\ | 1604 | module_param(lpfc_##name, uint, 0);\ |
1570 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1605 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1571 | lpfc_vport_param_show(name)\ | 1606 | lpfc_vport_param_show(name)\ |
1572 | lpfc_vport_param_init(name, defval, minval, maxval)\ | 1607 | lpfc_vport_param_init(name, defval, minval, maxval)\ |
1573 | static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) | 1608 | static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) |
1574 | 1609 | ||
1575 | #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \ | 1610 | #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \ |
1576 | static int lpfc_##name = defval;\ | 1611 | static uint lpfc_##name = defval;\ |
1577 | module_param(lpfc_##name, int, 0);\ | 1612 | module_param(lpfc_##name, uint, 0);\ |
1578 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1613 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1579 | lpfc_vport_param_show(name)\ | 1614 | lpfc_vport_param_show(name)\ |
1580 | lpfc_vport_param_init(name, defval, minval, maxval)\ | 1615 | lpfc_vport_param_init(name, defval, minval, maxval)\ |
@@ -1584,16 +1619,16 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\ | |||
1584 | lpfc_##name##_show, lpfc_##name##_store) | 1619 | lpfc_##name##_show, lpfc_##name##_store) |
1585 | 1620 | ||
1586 | #define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \ | 1621 | #define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \ |
1587 | static int lpfc_##name = defval;\ | 1622 | static uint lpfc_##name = defval;\ |
1588 | module_param(lpfc_##name, int, 0);\ | 1623 | module_param(lpfc_##name, uint, 0);\ |
1589 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1624 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1590 | lpfc_vport_param_hex_show(name)\ | 1625 | lpfc_vport_param_hex_show(name)\ |
1591 | lpfc_vport_param_init(name, defval, minval, maxval)\ | 1626 | lpfc_vport_param_init(name, defval, minval, maxval)\ |
1592 | static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) | 1627 | static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) |
1593 | 1628 | ||
1594 | #define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \ | 1629 | #define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \ |
1595 | static int lpfc_##name = defval;\ | 1630 | static uint lpfc_##name = defval;\ |
1596 | module_param(lpfc_##name, int, 0);\ | 1631 | module_param(lpfc_##name, uint, 0);\ |
1597 | MODULE_PARM_DESC(lpfc_##name, desc);\ | 1632 | MODULE_PARM_DESC(lpfc_##name, desc);\ |
1598 | lpfc_vport_param_hex_show(name)\ | 1633 | lpfc_vport_param_hex_show(name)\ |
1599 | lpfc_vport_param_init(name, defval, minval, maxval)\ | 1634 | lpfc_vport_param_init(name, defval, minval, maxval)\ |
@@ -1614,7 +1649,8 @@ static DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL); | |||
1614 | static DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL); | 1649 | static DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL); |
1615 | static DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL); | 1650 | static DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL); |
1616 | static DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL); | 1651 | static DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL); |
1617 | static DEVICE_ATTR(link_state, S_IRUGO, lpfc_link_state_show, NULL); | 1652 | static DEVICE_ATTR(link_state, S_IRUGO | S_IWUSR, lpfc_link_state_show, |
1653 | lpfc_link_state_store); | ||
1618 | static DEVICE_ATTR(option_rom_version, S_IRUGO, | 1654 | static DEVICE_ATTR(option_rom_version, S_IRUGO, |
1619 | lpfc_option_rom_version_show, NULL); | 1655 | lpfc_option_rom_version_show, NULL); |
1620 | static DEVICE_ATTR(num_discovered_ports, S_IRUGO, | 1656 | static DEVICE_ATTR(num_discovered_ports, S_IRUGO, |
@@ -1897,6 +1933,15 @@ static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, | |||
1897 | lpfc_enable_npiv_show, NULL); | 1933 | lpfc_enable_npiv_show, NULL); |
1898 | 1934 | ||
1899 | /* | 1935 | /* |
1936 | # lpfc_suppress_link_up: Bring link up at initialization | ||
1937 | # 0x0 = bring link up (issue MBX_INIT_LINK) | ||
1938 | # 0x1 = do NOT bring link up at initialization(MBX_INIT_LINK) | ||
1939 | # 0x2 = never bring up link | ||
1940 | # Default value is 0. | ||
1941 | */ | ||
1942 | LPFC_ATTR_R(suppress_link_up, 0, 0, 2, "Suppress Link Up at initialization"); | ||
1943 | |||
1944 | /* | ||
1900 | # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear | 1945 | # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear |
1901 | # until the timer expires. Value range is [0,255]. Default value is 30. | 1946 | # until the timer expires. Value range is [0,255]. Default value is 30. |
1902 | */ | 1947 | */ |
@@ -3278,6 +3323,7 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
3278 | &dev_attr_lpfc_prot_sg_seg_cnt, | 3323 | &dev_attr_lpfc_prot_sg_seg_cnt, |
3279 | &dev_attr_lpfc_aer_support, | 3324 | &dev_attr_lpfc_aer_support, |
3280 | &dev_attr_lpfc_aer_state_cleanup, | 3325 | &dev_attr_lpfc_aer_state_cleanup, |
3326 | &dev_attr_lpfc_suppress_link_up, | ||
3281 | NULL, | 3327 | NULL, |
3282 | }; | 3328 | }; |
3283 | 3329 | ||
@@ -4456,7 +4502,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
4456 | lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); | 4502 | lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); |
4457 | lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); | 4503 | lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); |
4458 | lpfc_aer_support_init(phba, lpfc_aer_support); | 4504 | lpfc_aer_support_init(phba, lpfc_aer_support); |
4459 | 4505 | lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); | |
4460 | return; | 4506 | return; |
4461 | } | 4507 | } |
4462 | 4508 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b0b7bb39f054..89d886c72e0a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -544,7 +544,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
544 | mempool_free(pmb, phba->mbox_mem_pool); | 544 | mempool_free(pmb, phba->mbox_mem_pool); |
545 | return -EIO; | 545 | return -EIO; |
546 | } | 546 | } |
547 | } else { | 547 | } else if (phba->cfg_suppress_link_up == 0) { |
548 | lpfc_init_link(phba, pmb, phba->cfg_topology, | 548 | lpfc_init_link(phba, pmb, phba->cfg_topology, |
549 | phba->cfg_link_speed); | 549 | phba->cfg_link_speed); |
550 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 550 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
@@ -603,6 +603,102 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
603 | } | 603 | } |
604 | 604 | ||
605 | /** | 605 | /** |
606 | * lpfc_hba_init_link - Initialize the FC link | ||
607 | * @phba: pointer to lpfc hba data structure. | ||
608 | * | ||
609 | * This routine will issue the INIT_LINK mailbox command call. | ||
610 | * It is available to other drivers through the lpfc_hba data | ||
611 | * structure for use as a delayed link up mechanism with the | ||
612 | * module parameter lpfc_suppress_link_up. | ||
613 | * | ||
614 | * Return code | ||
615 | * 0 - success | ||
616 | * Any other value - error | ||
617 | **/ | ||
618 | int | ||
619 | lpfc_hba_init_link(struct lpfc_hba *phba) | ||
620 | { | ||
621 | struct lpfc_vport *vport = phba->pport; | ||
622 | LPFC_MBOXQ_t *pmb; | ||
623 | MAILBOX_t *mb; | ||
624 | int rc; | ||
625 | |||
626 | pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
627 | if (!pmb) { | ||
628 | phba->link_state = LPFC_HBA_ERROR; | ||
629 | return -ENOMEM; | ||
630 | } | ||
631 | mb = &pmb->u.mb; | ||
632 | pmb->vport = vport; | ||
633 | |||
634 | lpfc_init_link(phba, pmb, phba->cfg_topology, | ||
635 | phba->cfg_link_speed); | ||
636 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
637 | lpfc_set_loopback_flag(phba); | ||
638 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | ||
639 | if (rc != MBX_SUCCESS) { | ||
640 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
641 | "0498 Adapter failed to init, mbxCmd x%x " | ||
642 | "INIT_LINK, mbxStatus x%x\n", | ||
643 | mb->mbxCommand, mb->mbxStatus); | ||
644 | /* Clear all interrupt enable conditions */ | ||
645 | writel(0, phba->HCregaddr); | ||
646 | readl(phba->HCregaddr); /* flush */ | ||
647 | /* Clear all pending interrupts */ | ||
648 | writel(0xffffffff, phba->HAregaddr); | ||
649 | readl(phba->HAregaddr); /* flush */ | ||
650 | phba->link_state = LPFC_HBA_ERROR; | ||
651 | if (rc != MBX_BUSY) | ||
652 | mempool_free(pmb, phba->mbox_mem_pool); | ||
653 | return -EIO; | ||
654 | } | ||
655 | phba->cfg_suppress_link_up = 0; | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | /** | ||
661 | * lpfc_hba_down_link - this routine downs the FC link | ||
662 | * | ||
663 | * This routine will issue the DOWN_LINK mailbox command call. | ||
664 | * It is available to other drivers through the lpfc_hba data | ||
665 | * structure for use to stop the link. | ||
666 | * | ||
667 | * Return code | ||
668 | * 0 - success | ||
669 | * Any other value - error | ||
670 | **/ | ||
671 | int | ||
672 | lpfc_hba_down_link(struct lpfc_hba *phba) | ||
673 | { | ||
674 | LPFC_MBOXQ_t *pmb; | ||
675 | int rc; | ||
676 | |||
677 | pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
678 | if (!pmb) { | ||
679 | phba->link_state = LPFC_HBA_ERROR; | ||
680 | return -ENOMEM; | ||
681 | } | ||
682 | |||
683 | lpfc_printf_log(phba, | ||
684 | KERN_ERR, LOG_INIT, | ||
685 | "0491 Adapter Link is disabled.\n"); | ||
686 | lpfc_down_link(phba, pmb); | ||
687 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
688 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | ||
689 | if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) { | ||
690 | lpfc_printf_log(phba, | ||
691 | KERN_ERR, LOG_INIT, | ||
692 | "2522 Adapter failed to issue DOWN_LINK" | ||
693 | " mbox command rc 0x%x\n", rc); | ||
694 | |||
695 | mempool_free(pmb, phba->mbox_mem_pool); | ||
696 | return -EIO; | ||
697 | } | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | /** | ||
606 | * lpfc_hba_down_prep - Perform lpfc uninitialization prior to HBA reset | 702 | * lpfc_hba_down_prep - Perform lpfc uninitialization prior to HBA reset |
607 | * @phba: pointer to lpfc HBA data structure. | 703 | * @phba: pointer to lpfc HBA data structure. |
608 | * | 704 | * |
@@ -3952,6 +4048,8 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba) | |||
3952 | int | 4048 | int |
3953 | lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) | 4049 | lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) |
3954 | { | 4050 | { |
4051 | phba->lpfc_hba_init_link = lpfc_hba_init_link; | ||
4052 | phba->lpfc_hba_down_link = lpfc_hba_down_link; | ||
3955 | switch (dev_grp) { | 4053 | switch (dev_grp) { |
3956 | case LPFC_PCI_DEV_LP: | 4054 | case LPFC_PCI_DEV_LP: |
3957 | phba->lpfc_hba_down_post = lpfc_hba_down_post_s3; | 4055 | phba->lpfc_hba_down_post = lpfc_hba_down_post_s3; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 8e98c6335e00..7f21b47db791 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -2640,6 +2640,7 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) | |||
2640 | } | 2640 | } |
2641 | phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf; | 2641 | phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf; |
2642 | phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth; | 2642 | phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth; |
2643 | phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; | ||
2643 | return 0; | 2644 | return 0; |
2644 | } | 2645 | } |
2645 | 2646 | ||