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