aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2010-06-17 04:04:31 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-27 13:02:10 -0400
commitb8d7d7bb37b5e25ea740369eb12de5279fe6ab30 (patch)
tree3f9f6b129b7bec20bbd27a7429a8ea86a796967d
parentd5f491e65851627358b2c1a4e322681b17539550 (diff)
[SCSI] mpt2sas: Added expander phy control support
Added support to send link resets, hard resets, enable/disable phys, and changing link rates for for expanders. This will be exported to attributes within the sas transport layer. A new wrapper function was added for sending SMP passthru to expanders for phy control. Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c305
1 files changed, 275 insertions, 30 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index a96501fdba0c..6c94deeb7be7 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -940,16 +940,6 @@ rphy_to_ioc(struct sas_rphy *rphy)
940 return shost_priv(shost); 940 return shost_priv(shost);
941} 941}
942 942
943static struct _sas_phy *
944_transport_find_local_phy(struct MPT2SAS_ADAPTER *ioc, struct sas_phy *phy)
945{
946 int i;
947
948 for (i = 0; i < ioc->sas_hba.num_phys; i++)
949 if (ioc->sas_hba.phy[i].phy == phy)
950 return(&ioc->sas_hba.phy[i]);
951 return NULL;
952}
953 943
954/* report phy error log structure */ 944/* report phy error log structure */
955struct phy_error_log_request{ 945struct phy_error_log_request{
@@ -1270,32 +1260,260 @@ _transport_get_bay_identifier(struct sas_rphy *rphy)
1270 return sas_device->slot; 1260 return sas_device->slot;
1271} 1261}
1272 1262
1263/* phy control request structure */
1264struct phy_control_request{
1265 u8 smp_frame_type; /* 0x40 */
1266 u8 function; /* 0x91 */
1267 u8 allocated_response_length;
1268 u8 request_length; /* 0x09 */
1269 u16 expander_change_count;
1270 u8 reserved_1[3];
1271 u8 phy_identifier;
1272 u8 phy_operation;
1273 u8 reserved_2[13];
1274 u64 attached_device_name;
1275 u8 programmed_min_physical_link_rate;
1276 u8 programmed_max_physical_link_rate;
1277 u8 reserved_3[6];
1278};
1279
1280/* phy control reply structure */
1281struct phy_control_reply{
1282 u8 smp_frame_type; /* 0x41 */
1283 u8 function; /* 0x11 */
1284 u8 function_result;
1285 u8 response_length;
1286};
1287
1288#define SMP_PHY_CONTROL_LINK_RESET (0x01)
1289#define SMP_PHY_CONTROL_HARD_RESET (0x02)
1290#define SMP_PHY_CONTROL_DISABLE (0x03)
1291
1292/**
1293 * _transport_expander_phy_control - expander phy control
1294 * @ioc: per adapter object
1295 * @phy: The sas phy object
1296 *
1297 * Returns 0 for success, non-zero for failure.
1298 *
1299 */
1300static int
1301_transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
1302 struct sas_phy *phy, u8 phy_operation)
1303{
1304 Mpi2SmpPassthroughRequest_t *mpi_request;
1305 Mpi2SmpPassthroughReply_t *mpi_reply;
1306 struct phy_control_request *phy_control_request;
1307 struct phy_control_reply *phy_control_reply;
1308 int rc;
1309 u16 smid;
1310 u32 ioc_state;
1311 unsigned long timeleft;
1312 void *psge;
1313 u32 sgl_flags;
1314 u8 issue_reset = 0;
1315 void *data_out = NULL;
1316 dma_addr_t data_out_dma;
1317 u32 sz;
1318 u64 *sas_address_le;
1319 u16 wait_state_count;
1320
1321 if (ioc->shost_recovery) {
1322 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1323 __func__, ioc->name);
1324 return -EFAULT;
1325 }
1326
1327 mutex_lock(&ioc->transport_cmds.mutex);
1328
1329 if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1330 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1331 ioc->name, __func__);
1332 rc = -EAGAIN;
1333 goto out;
1334 }
1335 ioc->transport_cmds.status = MPT2_CMD_PENDING;
1336
1337 wait_state_count = 0;
1338 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1339 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1340 if (wait_state_count++ == 10) {
1341 printk(MPT2SAS_ERR_FMT
1342 "%s: failed due to ioc not operational\n",
1343 ioc->name, __func__);
1344 rc = -EFAULT;
1345 goto out;
1346 }
1347 ssleep(1);
1348 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1349 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1350 "operational state(count=%d)\n", ioc->name,
1351 __func__, wait_state_count);
1352 }
1353 if (wait_state_count)
1354 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1355 ioc->name, __func__);
1356
1357 smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1358 if (!smid) {
1359 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1360 ioc->name, __func__);
1361 rc = -EAGAIN;
1362 goto out;
1363 }
1364
1365 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1366 ioc->transport_cmds.smid = smid;
1367
1368 sz = sizeof(struct phy_control_request) +
1369 sizeof(struct phy_control_reply);
1370 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1371 if (!data_out) {
1372 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1373 __LINE__, __func__);
1374 rc = -ENOMEM;
1375 mpt2sas_base_free_smid(ioc, smid);
1376 goto out;
1377 }
1378
1379 rc = -EINVAL;
1380 memset(data_out, 0, sz);
1381 phy_control_request = data_out;
1382 phy_control_request->smp_frame_type = 0x40;
1383 phy_control_request->function = 0x91;
1384 phy_control_request->request_length = 9;
1385 phy_control_request->allocated_response_length = 0;
1386 phy_control_request->phy_identifier = phy->number;
1387 phy_control_request->phy_operation = phy_operation;
1388 phy_control_request->programmed_min_physical_link_rate =
1389 phy->minimum_linkrate << 4;
1390 phy_control_request->programmed_max_physical_link_rate =
1391 phy->maximum_linkrate << 4;
1392
1393 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1394 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1395 mpi_request->PhysicalPort = 0xFF;
1396 mpi_request->VF_ID = 0; /* TODO */
1397 mpi_request->VP_ID = 0;
1398 sas_address_le = (u64 *)&mpi_request->SASAddress;
1399 *sas_address_le = cpu_to_le64(phy->identify.sas_address);
1400 mpi_request->RequestDataLength =
1401 cpu_to_le16(sizeof(struct phy_error_log_request));
1402 psge = &mpi_request->SGL;
1403
1404 /* WRITE sgel first */
1405 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1406 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1407 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1408 ioc->base_add_sg_single(psge, sgl_flags |
1409 sizeof(struct phy_control_request), data_out_dma);
1410
1411 /* incr sgel */
1412 psge += ioc->sge_size;
1413
1414 /* READ sgel last */
1415 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1416 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1417 MPI2_SGE_FLAGS_END_OF_LIST);
1418 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1419 ioc->base_add_sg_single(psge, sgl_flags |
1420 sizeof(struct phy_control_reply), data_out_dma +
1421 sizeof(struct phy_control_request));
1422
1423 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1424 "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name,
1425 (unsigned long long)phy->identify.sas_address, phy->number,
1426 phy_operation));
1427 mpt2sas_base_put_smid_default(ioc, smid);
1428 init_completion(&ioc->transport_cmds.done);
1429 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1430 10*HZ);
1431
1432 if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1433 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1434 ioc->name, __func__);
1435 _debug_dump_mf(mpi_request,
1436 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1437 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1438 issue_reset = 1;
1439 goto issue_host_reset;
1440 }
1441
1442 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1443 "complete\n", ioc->name));
1444
1445 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1446
1447 mpi_reply = ioc->transport_cmds.reply;
1448
1449 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1450 "phy_control - reply data transfer size(%d)\n",
1451 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1452
1453 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1454 sizeof(struct phy_control_reply))
1455 goto out;
1456
1457 phy_control_reply = data_out +
1458 sizeof(struct phy_control_request);
1459
1460 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1461 "phy_control - function_result(%d)\n",
1462 ioc->name, phy_control_reply->function_result));
1463
1464 rc = 0;
1465 } else
1466 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1467 "phy_control - no reply\n", ioc->name));
1468
1469 issue_host_reset:
1470 if (issue_reset)
1471 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1472 FORCE_BIG_HAMMER);
1473 out:
1474 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1475 if (data_out)
1476 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1477
1478 mutex_unlock(&ioc->transport_cmds.mutex);
1479 return rc;
1480}
1481
1273/** 1482/**
1274 * _transport_phy_reset - 1483 * _transport_phy_reset -
1275 * @phy: The sas phy object 1484 * @phy: The sas phy object
1276 * @hard_reset: 1485 * @hard_reset:
1277 * 1486 *
1278 * Only support sas_host direct attached phys.
1279 * Returns 0 for success, non-zero for failure. 1487 * Returns 0 for success, non-zero for failure.
1280 */ 1488 */
1281static int 1489static int
1282_transport_phy_reset(struct sas_phy *phy, int hard_reset) 1490_transport_phy_reset(struct sas_phy *phy, int hard_reset)
1283{ 1491{
1284 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); 1492 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1285 struct _sas_phy *mpt2sas_phy;
1286 Mpi2SasIoUnitControlReply_t mpi_reply; 1493 Mpi2SasIoUnitControlReply_t mpi_reply;
1287 Mpi2SasIoUnitControlRequest_t mpi_request; 1494 Mpi2SasIoUnitControlRequest_t mpi_request;
1495 unsigned long flags;
1288 1496
1289 mpt2sas_phy = _transport_find_local_phy(ioc, phy); 1497 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1290 1498 if (_transport_sas_node_find_by_sas_address(ioc,
1291 if (!mpt2sas_phy) /* this phy not on sas_host */ 1499 phy->identify.sas_address) == NULL) {
1500 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1292 return -EINVAL; 1501 return -EINVAL;
1502 }
1503 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1293 1504
1505 /* handle expander phys */
1506 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1507 return _transport_expander_phy_control(ioc, phy,
1508 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1509 SMP_PHY_CONTROL_LINK_RESET);
1510
1511 /* handle hba phys */
1294 memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t)); 1512 memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
1295 mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; 1513 mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1296 mpi_request.Operation = hard_reset ? 1514 mpi_request.Operation = hard_reset ?
1297 MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET; 1515 MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1298 mpi_request.PhyNum = mpt2sas_phy->phy_id; 1516 mpi_request.PhyNum = phy->number;
1299 1517
1300 if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) { 1518 if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1301 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", 1519 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
@@ -1306,8 +1524,7 @@ _transport_phy_reset(struct sas_phy *phy, int hard_reset)
1306 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) 1524 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1307 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status" 1525 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1308 "(0x%04x), loginfo(0x%08x)\n", ioc->name, 1526 "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1309 mpt2sas_phy->phy_id, 1527 phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1310 le16_to_cpu(mpi_reply.IOCStatus),
1311 le32_to_cpu(mpi_reply.IOCLogInfo)); 1528 le32_to_cpu(mpi_reply.IOCLogInfo));
1312 1529
1313 return 0; 1530 return 0;
@@ -1325,17 +1542,28 @@ static int
1325_transport_phy_enable(struct sas_phy *phy, int enable) 1542_transport_phy_enable(struct sas_phy *phy, int enable)
1326{ 1543{
1327 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); 1544 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1328 struct _sas_phy *mpt2sas_phy;
1329 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; 1545 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1330 Mpi2ConfigReply_t mpi_reply; 1546 Mpi2ConfigReply_t mpi_reply;
1331 u16 ioc_status; 1547 u16 ioc_status;
1332 u16 sz; 1548 u16 sz;
1333 int rc = 0; 1549 int rc = 0;
1550 unsigned long flags;
1334 1551
1335 mpt2sas_phy = _transport_find_local_phy(ioc, phy); 1552 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1336 1553 if (_transport_sas_node_find_by_sas_address(ioc,
1337 if (!mpt2sas_phy) /* this phy not on sas_host */ 1554 phy->identify.sas_address) == NULL) {
1555 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1338 return -EINVAL; 1556 return -EINVAL;
1557 }
1558 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1559
1560 /* handle expander phys */
1561 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1562 return _transport_expander_phy_control(ioc, phy,
1563 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1564 SMP_PHY_CONTROL_DISABLE);
1565
1566 /* handle hba phys */
1339 1567
1340 /* sas_iounit page 1 */ 1568 /* sas_iounit page 1 */
1341 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * 1569 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
@@ -1364,14 +1592,18 @@ _transport_phy_enable(struct sas_phy *phy, int enable)
1364 } 1592 }
1365 1593
1366 if (enable) 1594 if (enable)
1367 sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags 1595 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1368 &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; 1596 &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1369 else 1597 else
1370 sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags 1598 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1371 |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; 1599 |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1372 1600
1373 mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz); 1601 mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1374 1602
1603 /* link reset */
1604 if (enable)
1605 _transport_phy_reset(phy, 0);
1606
1375 out: 1607 out:
1376 kfree(sas_iounit_pg1); 1608 kfree(sas_iounit_pg1);
1377 return rc; 1609 return rc;
@@ -1389,7 +1621,6 @@ static int
1389_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) 1621_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1390{ 1622{
1391 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); 1623 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1392 struct _sas_phy *mpt2sas_phy;
1393 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; 1624 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1394 Mpi2SasPhyPage0_t phy_pg0; 1625 Mpi2SasPhyPage0_t phy_pg0;
1395 Mpi2ConfigReply_t mpi_reply; 1626 Mpi2ConfigReply_t mpi_reply;
@@ -1397,11 +1628,15 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1397 u16 sz; 1628 u16 sz;
1398 int i; 1629 int i;
1399 int rc = 0; 1630 int rc = 0;
1631 unsigned long flags;
1400 1632
1401 mpt2sas_phy = _transport_find_local_phy(ioc, phy); 1633 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1402 1634 if (_transport_sas_node_find_by_sas_address(ioc,
1403 if (!mpt2sas_phy) /* this phy not on sas_host */ 1635 phy->identify.sas_address) == NULL) {
1636 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1404 return -EINVAL; 1637 return -EINVAL;
1638 }
1639 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1405 1640
1406 if (!rates->minimum_linkrate) 1641 if (!rates->minimum_linkrate)
1407 rates->minimum_linkrate = phy->minimum_linkrate; 1642 rates->minimum_linkrate = phy->minimum_linkrate;
@@ -1413,6 +1648,16 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1413 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw) 1648 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1414 rates->maximum_linkrate = phy->maximum_linkrate_hw; 1649 rates->maximum_linkrate = phy->maximum_linkrate_hw;
1415 1650
1651 /* handle expander phys */
1652 if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1653 phy->minimum_linkrate = rates->minimum_linkrate;
1654 phy->maximum_linkrate = rates->maximum_linkrate;
1655 return _transport_expander_phy_control(ioc, phy,
1656 SMP_PHY_CONTROL_LINK_RESET);
1657 }
1658
1659 /* handle hba phys */
1660
1416 /* sas_iounit page 1 */ 1661 /* sas_iounit page 1 */
1417 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * 1662 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1418 sizeof(Mpi2SasIOUnit1PhyData_t)); 1663 sizeof(Mpi2SasIOUnit1PhyData_t));
@@ -1440,7 +1685,7 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1440 } 1685 }
1441 1686
1442 for (i = 0; i < ioc->sas_hba.num_phys; i++) { 1687 for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1443 if (mpt2sas_phy->phy_id != i) { 1688 if (phy->number != i) {
1444 sas_iounit_pg1->PhyData[i].MaxMinLinkRate = 1689 sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1445 (ioc->sas_hba.phy[i].phy->minimum_linkrate + 1690 (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1446 (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4)); 1691 (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
@@ -1464,7 +1709,7 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1464 1709
1465 /* read phy page 0, then update the rates in the sas transport phy */ 1710 /* read phy page 0, then update the rates in the sas transport phy */
1466 if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, 1711 if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1467 mpt2sas_phy->phy_id)) { 1712 phy->number)) {
1468 phy->minimum_linkrate = _transport_convert_phy_link_rate( 1713 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1469 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); 1714 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1470 phy->maximum_linkrate = _transport_convert_phy_link_rate( 1715 phy->maximum_linkrate = _transport_convert_phy_link_rate(