diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_ctl.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_ctl.c | 197 |
1 files changed, 150 insertions, 47 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 57d724633906..84a124f8e21f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c | |||
@@ -740,7 +740,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
740 | Mpi2SCSIIORequest_t *scsiio_request = | 740 | Mpi2SCSIIORequest_t *scsiio_request = |
741 | (Mpi2SCSIIORequest_t *)mpi_request; | 741 | (Mpi2SCSIIORequest_t *)mpi_request; |
742 | scsiio_request->SenseBufferLowAddress = | 742 | scsiio_request->SenseBufferLowAddress = |
743 | (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid); | 743 | mpt2sas_base_get_sense_buffer_dma(ioc, smid); |
744 | priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid); | 744 | priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid); |
745 | memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE); | 745 | memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE); |
746 | mpt2sas_base_put_smid_scsi_io(ioc, smid, | 746 | mpt2sas_base_put_smid_scsi_io(ioc, smid, |
@@ -848,8 +848,9 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
848 | printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: " | 848 | printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: " |
849 | "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " | 849 | "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " |
850 | "TerminationCount(0x%08x)\n", ioc->name, | 850 | "TerminationCount(0x%08x)\n", ioc->name, |
851 | tm_reply->IOCStatus, tm_reply->IOCLogInfo, | 851 | le16_to_cpu(tm_reply->IOCStatus), |
852 | tm_reply->TerminationCount); | 852 | le32_to_cpu(tm_reply->IOCLogInfo), |
853 | le32_to_cpu(tm_reply->TerminationCount)); | ||
853 | } | 854 | } |
854 | #endif | 855 | #endif |
855 | /* copy out xdata to user */ | 856 | /* copy out xdata to user */ |
@@ -896,6 +897,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
896 | printk(MPT2SAS_INFO_FMT "issue target reset: handle " | 897 | printk(MPT2SAS_INFO_FMT "issue target reset: handle " |
897 | "= (0x%04x)\n", ioc->name, | 898 | "= (0x%04x)\n", ioc->name, |
898 | mpi_request->FunctionDependent1); | 899 | mpi_request->FunctionDependent1); |
900 | mpt2sas_halt_firmware(ioc); | ||
899 | mutex_lock(&ioc->tm_cmds.mutex); | 901 | mutex_lock(&ioc->tm_cmds.mutex); |
900 | mpt2sas_scsih_issue_tm(ioc, | 902 | mpt2sas_scsih_issue_tm(ioc, |
901 | mpi_request->FunctionDependent1, 0, | 903 | mpi_request->FunctionDependent1, 0, |
@@ -1229,7 +1231,7 @@ _ctl_btdh_mapping(void __user *arg) | |||
1229 | /** | 1231 | /** |
1230 | * _ctl_diag_capability - return diag buffer capability | 1232 | * _ctl_diag_capability - return diag buffer capability |
1231 | * @ioc: per adapter object | 1233 | * @ioc: per adapter object |
1232 | * @buffer_type: specifies either TRACE or SNAPSHOT | 1234 | * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED |
1233 | * | 1235 | * |
1234 | * returns 1 when diag buffer support is enabled in firmware | 1236 | * returns 1 when diag buffer support is enabled in firmware |
1235 | */ | 1237 | */ |
@@ -1249,24 +1251,25 @@ _ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type) | |||
1249 | MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) | 1251 | MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) |
1250 | rc = 1; | 1252 | rc = 1; |
1251 | break; | 1253 | break; |
1254 | case MPI2_DIAG_BUF_TYPE_EXTENDED: | ||
1255 | if (ioc->facts.IOCCapabilities & | ||
1256 | MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) | ||
1257 | rc = 1; | ||
1252 | } | 1258 | } |
1253 | 1259 | ||
1254 | return rc; | 1260 | return rc; |
1255 | } | 1261 | } |
1256 | 1262 | ||
1257 | /** | 1263 | /** |
1258 | * _ctl_diag_register - application register with driver | 1264 | * _ctl_diag_register_2 - wrapper for registering diag buffer support |
1259 | * @arg - user space buffer containing ioctl content | 1265 | * @ioc: per adapter object |
1260 | * @state - NON_BLOCKING or BLOCKING | 1266 | * @diag_register: the diag_register struct passed in from user space |
1261 | * | 1267 | * |
1262 | * This will allow the driver to setup any required buffers that will be | ||
1263 | * needed by firmware to communicate with the driver. | ||
1264 | */ | 1268 | */ |
1265 | static long | 1269 | static long |
1266 | _ctl_diag_register(void __user *arg, enum block_state state) | 1270 | _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc, |
1271 | struct mpt2_diag_register *diag_register) | ||
1267 | { | 1272 | { |
1268 | struct mpt2_diag_register karg; | ||
1269 | struct MPT2SAS_ADAPTER *ioc; | ||
1270 | int rc, i; | 1273 | int rc, i; |
1271 | void *request_data = NULL; | 1274 | void *request_data = NULL; |
1272 | dma_addr_t request_data_dma; | 1275 | dma_addr_t request_data_dma; |
@@ -1279,18 +1282,17 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1279 | u16 ioc_status; | 1282 | u16 ioc_status; |
1280 | u8 issue_reset = 0; | 1283 | u8 issue_reset = 0; |
1281 | 1284 | ||
1282 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
1283 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
1284 | __FILE__, __LINE__, __func__); | ||
1285 | return -EFAULT; | ||
1286 | } | ||
1287 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | ||
1288 | return -ENODEV; | ||
1289 | |||
1290 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1285 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
1291 | __func__)); | 1286 | __func__)); |
1292 | 1287 | ||
1293 | buffer_type = karg.buffer_type; | 1288 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { |
1289 | printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", | ||
1290 | ioc->name, __func__); | ||
1291 | rc = -EAGAIN; | ||
1292 | goto out; | ||
1293 | } | ||
1294 | |||
1295 | buffer_type = diag_register->buffer_type; | ||
1294 | if (!_ctl_diag_capability(ioc, buffer_type)) { | 1296 | if (!_ctl_diag_capability(ioc, buffer_type)) { |
1295 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " | 1297 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " |
1296 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | 1298 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); |
@@ -1305,24 +1307,12 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1305 | return -EINVAL; | 1307 | return -EINVAL; |
1306 | } | 1308 | } |
1307 | 1309 | ||
1308 | if (karg.requested_buffer_size % 4) { | 1310 | if (diag_register->requested_buffer_size % 4) { |
1309 | printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size " | 1311 | printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size " |
1310 | "is not 4 byte aligned\n", ioc->name, __func__); | 1312 | "is not 4 byte aligned\n", ioc->name, __func__); |
1311 | return -EINVAL; | 1313 | return -EINVAL; |
1312 | } | 1314 | } |
1313 | 1315 | ||
1314 | if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) | ||
1315 | return -EAGAIN; | ||
1316 | else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) | ||
1317 | return -ERESTARTSYS; | ||
1318 | |||
1319 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { | ||
1320 | printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", | ||
1321 | ioc->name, __func__); | ||
1322 | rc = -EAGAIN; | ||
1323 | goto out; | ||
1324 | } | ||
1325 | |||
1326 | smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); | 1316 | smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); |
1327 | if (!smid) { | 1317 | if (!smid) { |
1328 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | 1318 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", |
@@ -1338,12 +1328,12 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1338 | ioc->ctl_cmds.smid = smid; | 1328 | ioc->ctl_cmds.smid = smid; |
1339 | 1329 | ||
1340 | request_data = ioc->diag_buffer[buffer_type]; | 1330 | request_data = ioc->diag_buffer[buffer_type]; |
1341 | request_data_sz = karg.requested_buffer_size; | 1331 | request_data_sz = diag_register->requested_buffer_size; |
1342 | ioc->unique_id[buffer_type] = karg.unique_id; | 1332 | ioc->unique_id[buffer_type] = diag_register->unique_id; |
1343 | ioc->diag_buffer_status[buffer_type] = 0; | 1333 | ioc->diag_buffer_status[buffer_type] = 0; |
1344 | memcpy(ioc->product_specific[buffer_type], karg.product_specific, | 1334 | memcpy(ioc->product_specific[buffer_type], |
1345 | MPT2_PRODUCT_SPECIFIC_DWORDS); | 1335 | diag_register->product_specific, MPT2_PRODUCT_SPECIFIC_DWORDS); |
1346 | ioc->diagnostic_flags[buffer_type] = karg.diagnostic_flags; | 1336 | ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags; |
1347 | 1337 | ||
1348 | if (request_data) { | 1338 | if (request_data) { |
1349 | request_data_dma = ioc->diag_buffer_dma[buffer_type]; | 1339 | request_data_dma = ioc->diag_buffer_dma[buffer_type]; |
@@ -1373,8 +1363,8 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1373 | } | 1363 | } |
1374 | 1364 | ||
1375 | mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; | 1365 | mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; |
1376 | mpi_request->BufferType = karg.buffer_type; | 1366 | mpi_request->BufferType = diag_register->buffer_type; |
1377 | mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags); | 1367 | mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags); |
1378 | mpi_request->BufferAddress = cpu_to_le64(request_data_dma); | 1368 | mpi_request->BufferAddress = cpu_to_le64(request_data_dma); |
1379 | mpi_request->BufferLength = cpu_to_le32(request_data_sz); | 1369 | mpi_request->BufferLength = cpu_to_le32(request_data_sz); |
1380 | mpi_request->VF_ID = 0; /* TODO */ | 1370 | mpi_request->VF_ID = 0; /* TODO */ |
@@ -1422,7 +1412,7 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1422 | } else { | 1412 | } else { |
1423 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " | 1413 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " |
1424 | "log_info(0x%08x)\n", ioc->name, __func__, | 1414 | "log_info(0x%08x)\n", ioc->name, __func__, |
1425 | ioc_status, mpi_reply->IOCLogInfo); | 1415 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); |
1426 | rc = -EFAULT; | 1416 | rc = -EFAULT; |
1427 | } | 1417 | } |
1428 | 1418 | ||
@@ -1438,6 +1428,83 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1438 | request_data, request_data_dma); | 1428 | request_data, request_data_dma); |
1439 | 1429 | ||
1440 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | 1430 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; |
1431 | return rc; | ||
1432 | } | ||
1433 | |||
1434 | /** | ||
1435 | * mpt2sas_enable_diag_buffer - enabling diag_buffers support driver load time | ||
1436 | * @ioc: per adapter object | ||
1437 | * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1 | ||
1438 | * | ||
1439 | * This is called when command line option diag_buffer_enable is enabled | ||
1440 | * at driver load time. | ||
1441 | */ | ||
1442 | void | ||
1443 | mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register) | ||
1444 | { | ||
1445 | struct mpt2_diag_register diag_register; | ||
1446 | |||
1447 | memset(&diag_register, 0, sizeof(struct mpt2_diag_register)); | ||
1448 | |||
1449 | if (bits_to_register & 1) { | ||
1450 | printk(MPT2SAS_INFO_FMT "registering trace buffer support\n", | ||
1451 | ioc->name); | ||
1452 | diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE; | ||
1453 | /* register for 1MB buffers */ | ||
1454 | diag_register.requested_buffer_size = (1024 * 1024); | ||
1455 | diag_register.unique_id = 0x7075900; | ||
1456 | _ctl_diag_register_2(ioc, &diag_register); | ||
1457 | } | ||
1458 | |||
1459 | if (bits_to_register & 2) { | ||
1460 | printk(MPT2SAS_INFO_FMT "registering snapshot buffer support\n", | ||
1461 | ioc->name); | ||
1462 | diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT; | ||
1463 | /* register for 2MB buffers */ | ||
1464 | diag_register.requested_buffer_size = 2 * (1024 * 1024); | ||
1465 | diag_register.unique_id = 0x7075901; | ||
1466 | _ctl_diag_register_2(ioc, &diag_register); | ||
1467 | } | ||
1468 | |||
1469 | if (bits_to_register & 4) { | ||
1470 | printk(MPT2SAS_INFO_FMT "registering extended buffer support\n", | ||
1471 | ioc->name); | ||
1472 | diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED; | ||
1473 | /* register for 2MB buffers */ | ||
1474 | diag_register.requested_buffer_size = 2 * (1024 * 1024); | ||
1475 | diag_register.unique_id = 0x7075901; | ||
1476 | _ctl_diag_register_2(ioc, &diag_register); | ||
1477 | } | ||
1478 | } | ||
1479 | |||
1480 | /** | ||
1481 | * _ctl_diag_register - application register with driver | ||
1482 | * @arg - user space buffer containing ioctl content | ||
1483 | * @state - NON_BLOCKING or BLOCKING | ||
1484 | * | ||
1485 | * This will allow the driver to setup any required buffers that will be | ||
1486 | * needed by firmware to communicate with the driver. | ||
1487 | */ | ||
1488 | static long | ||
1489 | _ctl_diag_register(void __user *arg, enum block_state state) | ||
1490 | { | ||
1491 | struct mpt2_diag_register karg; | ||
1492 | struct MPT2SAS_ADAPTER *ioc; | ||
1493 | long rc; | ||
1494 | |||
1495 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
1496 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
1497 | __FILE__, __LINE__, __func__); | ||
1498 | return -EFAULT; | ||
1499 | } | ||
1500 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | ||
1501 | return -ENODEV; | ||
1502 | |||
1503 | if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) | ||
1504 | return -EAGAIN; | ||
1505 | else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) | ||
1506 | return -ERESTARTSYS; | ||
1507 | rc = _ctl_diag_register_2(ioc, &karg); | ||
1441 | mutex_unlock(&ioc->ctl_cmds.mutex); | 1508 | mutex_unlock(&ioc->ctl_cmds.mutex); |
1442 | return rc; | 1509 | return rc; |
1443 | } | 1510 | } |
@@ -1600,7 +1667,7 @@ _ctl_diag_query(void __user *arg) | |||
1600 | /** | 1667 | /** |
1601 | * _ctl_send_release - Diag Release Message | 1668 | * _ctl_send_release - Diag Release Message |
1602 | * @ioc: per adapter object | 1669 | * @ioc: per adapter object |
1603 | * @buffer_type - specifies either TRACE or SNAPSHOT | 1670 | * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED |
1604 | * @issue_reset - specifies whether host reset is required. | 1671 | * @issue_reset - specifies whether host reset is required. |
1605 | * | 1672 | * |
1606 | */ | 1673 | */ |
@@ -1690,7 +1757,7 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) | |||
1690 | } else { | 1757 | } else { |
1691 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " | 1758 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " |
1692 | "log_info(0x%08x)\n", ioc->name, __func__, | 1759 | "log_info(0x%08x)\n", ioc->name, __func__, |
1693 | ioc_status, mpi_reply->IOCLogInfo); | 1760 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); |
1694 | rc = -EFAULT; | 1761 | rc = -EFAULT; |
1695 | } | 1762 | } |
1696 | 1763 | ||
@@ -1951,7 +2018,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
1951 | } else { | 2018 | } else { |
1952 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " | 2019 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " |
1953 | "log_info(0x%08x)\n", ioc->name, __func__, | 2020 | "log_info(0x%08x)\n", ioc->name, __func__, |
1954 | ioc_status, mpi_reply->IOCLogInfo); | 2021 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); |
1955 | rc = -EFAULT; | 2022 | rc = -EFAULT; |
1956 | } | 2023 | } |
1957 | 2024 | ||
@@ -2474,6 +2541,43 @@ _ctl_logging_level_store(struct device *cdev, struct device_attribute *attr, | |||
2474 | static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, | 2541 | static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, |
2475 | _ctl_logging_level_show, _ctl_logging_level_store); | 2542 | _ctl_logging_level_show, _ctl_logging_level_store); |
2476 | 2543 | ||
2544 | /* device attributes */ | ||
2545 | /* | ||
2546 | * _ctl_fwfault_debug_show - show/store fwfault_debug | ||
2547 | * @cdev - pointer to embedded class device | ||
2548 | * @buf - the buffer returned | ||
2549 | * | ||
2550 | * mpt2sas_fwfault_debug is command line option | ||
2551 | * A sysfs 'read/write' shost attribute. | ||
2552 | */ | ||
2553 | static ssize_t | ||
2554 | _ctl_fwfault_debug_show(struct device *cdev, | ||
2555 | struct device_attribute *attr, char *buf) | ||
2556 | { | ||
2557 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
2558 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
2559 | |||
2560 | return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug); | ||
2561 | } | ||
2562 | static ssize_t | ||
2563 | _ctl_fwfault_debug_store(struct device *cdev, | ||
2564 | struct device_attribute *attr, const char *buf, size_t count) | ||
2565 | { | ||
2566 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
2567 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
2568 | int val = 0; | ||
2569 | |||
2570 | if (sscanf(buf, "%d", &val) != 1) | ||
2571 | return -EINVAL; | ||
2572 | |||
2573 | ioc->fwfault_debug = val; | ||
2574 | printk(MPT2SAS_INFO_FMT "fwfault_debug=%d\n", ioc->name, | ||
2575 | ioc->fwfault_debug); | ||
2576 | return strlen(buf); | ||
2577 | } | ||
2578 | static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR, | ||
2579 | _ctl_fwfault_debug_show, _ctl_fwfault_debug_store); | ||
2580 | |||
2477 | struct device_attribute *mpt2sas_host_attrs[] = { | 2581 | struct device_attribute *mpt2sas_host_attrs[] = { |
2478 | &dev_attr_version_fw, | 2582 | &dev_attr_version_fw, |
2479 | &dev_attr_version_bios, | 2583 | &dev_attr_version_bios, |
@@ -2487,13 +2591,12 @@ struct device_attribute *mpt2sas_host_attrs[] = { | |||
2487 | &dev_attr_io_delay, | 2591 | &dev_attr_io_delay, |
2488 | &dev_attr_device_delay, | 2592 | &dev_attr_device_delay, |
2489 | &dev_attr_logging_level, | 2593 | &dev_attr_logging_level, |
2594 | &dev_attr_fwfault_debug, | ||
2490 | &dev_attr_fw_queue_depth, | 2595 | &dev_attr_fw_queue_depth, |
2491 | &dev_attr_host_sas_address, | 2596 | &dev_attr_host_sas_address, |
2492 | NULL, | 2597 | NULL, |
2493 | }; | 2598 | }; |
2494 | 2599 | ||
2495 | /* device attributes */ | ||
2496 | |||
2497 | /** | 2600 | /** |
2498 | * _ctl_device_sas_address_show - sas address | 2601 | * _ctl_device_sas_address_show - sas address |
2499 | * @cdev - pointer to embedded class device | 2602 | * @cdev - pointer to embedded class device |