aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2010-02-12 14:42:33 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-02-17 18:41:04 -0500
commit84d1b006978e78e27f22beb5cfbc4d349bac6df7 (patch)
tree0bb3f71b6a5389a8570e49493431d77b6ee5993c /drivers/scsi/lpfc
parent28baac7492fa084dbff6a1b9c4b42ed0d014b558 (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/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c110
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c100
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c1
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 **/
496static ssize_t
497lpfc_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) \
1276static int \ 1311static int \
1277lpfc_##attr##_init(struct lpfc_hba *phba, int val) \ 1312lpfc_##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) \
1311static int \ 1346static int \
1312lpfc_##attr##_set(struct lpfc_hba *phba, int val) \ 1347lpfc_##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) \
1436static int \ 1471static int \
1437lpfc_##attr##_init(struct lpfc_vport *vport, int val) \ 1472lpfc_##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) \
1468static int \ 1503static int \
1469lpfc_##attr##_set(struct lpfc_vport *vport, int val) \ 1504lpfc_##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) \
1518static int lpfc_##name = defval;\ 1553static uint lpfc_##name = defval;\
1519module_param(lpfc_##name, int, 0);\ 1554module_param(lpfc_##name, uint, 0);\
1520MODULE_PARM_DESC(lpfc_##name, desc);\ 1555MODULE_PARM_DESC(lpfc_##name, desc);\
1521lpfc_param_init(name, defval, minval, maxval) 1556lpfc_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) \
1524static int lpfc_##name = defval;\ 1559static uint lpfc_##name = defval;\
1525module_param(lpfc_##name, int, 0);\ 1560module_param(lpfc_##name, uint, 0);\
1526MODULE_PARM_DESC(lpfc_##name, desc);\ 1561MODULE_PARM_DESC(lpfc_##name, desc);\
1527lpfc_param_show(name)\ 1562lpfc_param_show(name)\
1528lpfc_param_init(name, defval, minval, maxval)\ 1563lpfc_param_init(name, defval, minval, maxval)\
1529static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) 1564static 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) \
1532static int lpfc_##name = defval;\ 1567static uint lpfc_##name = defval;\
1533module_param(lpfc_##name, int, 0);\ 1568module_param(lpfc_##name, uint, 0);\
1534MODULE_PARM_DESC(lpfc_##name, desc);\ 1569MODULE_PARM_DESC(lpfc_##name, desc);\
1535lpfc_param_show(name)\ 1570lpfc_param_show(name)\
1536lpfc_param_init(name, defval, minval, maxval)\ 1571lpfc_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) \
1543static int lpfc_##name = defval;\ 1578static uint lpfc_##name = defval;\
1544module_param(lpfc_##name, int, 0);\ 1579module_param(lpfc_##name, uint, 0);\
1545MODULE_PARM_DESC(lpfc_##name, desc);\ 1580MODULE_PARM_DESC(lpfc_##name, desc);\
1546lpfc_param_hex_show(name)\ 1581lpfc_param_hex_show(name)\
1547lpfc_param_init(name, defval, minval, maxval)\ 1582lpfc_param_init(name, defval, minval, maxval)\
1548static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) 1583static 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) \
1551static int lpfc_##name = defval;\ 1586static uint lpfc_##name = defval;\
1552module_param(lpfc_##name, int, 0);\ 1587module_param(lpfc_##name, uint, 0);\
1553MODULE_PARM_DESC(lpfc_##name, desc);\ 1588MODULE_PARM_DESC(lpfc_##name, desc);\
1554lpfc_param_hex_show(name)\ 1589lpfc_param_hex_show(name)\
1555lpfc_param_init(name, defval, minval, maxval)\ 1590lpfc_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) \
1562static int lpfc_##name = defval;\ 1597static uint lpfc_##name = defval;\
1563module_param(lpfc_##name, int, 0);\ 1598module_param(lpfc_##name, uint, 0);\
1564MODULE_PARM_DESC(lpfc_##name, desc);\ 1599MODULE_PARM_DESC(lpfc_##name, desc);\
1565lpfc_vport_param_init(name, defval, minval, maxval) 1600lpfc_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) \
1568static int lpfc_##name = defval;\ 1603static uint lpfc_##name = defval;\
1569module_param(lpfc_##name, int, 0);\ 1604module_param(lpfc_##name, uint, 0);\
1570MODULE_PARM_DESC(lpfc_##name, desc);\ 1605MODULE_PARM_DESC(lpfc_##name, desc);\
1571lpfc_vport_param_show(name)\ 1606lpfc_vport_param_show(name)\
1572lpfc_vport_param_init(name, defval, minval, maxval)\ 1607lpfc_vport_param_init(name, defval, minval, maxval)\
1573static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) 1608static 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) \
1576static int lpfc_##name = defval;\ 1611static uint lpfc_##name = defval;\
1577module_param(lpfc_##name, int, 0);\ 1612module_param(lpfc_##name, uint, 0);\
1578MODULE_PARM_DESC(lpfc_##name, desc);\ 1613MODULE_PARM_DESC(lpfc_##name, desc);\
1579lpfc_vport_param_show(name)\ 1614lpfc_vport_param_show(name)\
1580lpfc_vport_param_init(name, defval, minval, maxval)\ 1615lpfc_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) \
1587static int lpfc_##name = defval;\ 1622static uint lpfc_##name = defval;\
1588module_param(lpfc_##name, int, 0);\ 1623module_param(lpfc_##name, uint, 0);\
1589MODULE_PARM_DESC(lpfc_##name, desc);\ 1624MODULE_PARM_DESC(lpfc_##name, desc);\
1590lpfc_vport_param_hex_show(name)\ 1625lpfc_vport_param_hex_show(name)\
1591lpfc_vport_param_init(name, defval, minval, maxval)\ 1626lpfc_vport_param_init(name, defval, minval, maxval)\
1592static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) 1627static 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) \
1595static int lpfc_##name = defval;\ 1630static uint lpfc_##name = defval;\
1596module_param(lpfc_##name, int, 0);\ 1631module_param(lpfc_##name, uint, 0);\
1597MODULE_PARM_DESC(lpfc_##name, desc);\ 1632MODULE_PARM_DESC(lpfc_##name, desc);\
1598lpfc_vport_param_hex_show(name)\ 1633lpfc_vport_param_hex_show(name)\
1599lpfc_vport_param_init(name, defval, minval, maxval)\ 1634lpfc_vport_param_init(name, defval, minval, maxval)\
@@ -1614,7 +1649,8 @@ static DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
1614static DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL); 1649static DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
1615static DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL); 1650static DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
1616static DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL); 1651static DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
1617static DEVICE_ATTR(link_state, S_IRUGO, lpfc_link_state_show, NULL); 1652static DEVICE_ATTR(link_state, S_IRUGO | S_IWUSR, lpfc_link_state_show,
1653 lpfc_link_state_store);
1618static DEVICE_ATTR(option_rom_version, S_IRUGO, 1654static DEVICE_ATTR(option_rom_version, S_IRUGO,
1619 lpfc_option_rom_version_show, NULL); 1655 lpfc_option_rom_version_show, NULL);
1620static DEVICE_ATTR(num_discovered_ports, S_IRUGO, 1656static 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*/
1942LPFC_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 **/
618int
619lpfc_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 **/
671int
672lpfc_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)
3952int 4048int
3953lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) 4049lpfc_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