diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_ctl.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_ctl.c | 258 |
1 files changed, 189 insertions, 69 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index c2a51018910f..84a124f8e21f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * controllers | 3 | * controllers |
4 | * | 4 | * |
5 | * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c | 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c |
6 | * Copyright (C) 2007-2008 LSI Corporation | 6 | * Copyright (C) 2007-2009 LSI Corporation |
7 | * (mailto:DL-MPTFusionLinux@lsi.com) | 7 | * (mailto:DL-MPTFusionLinux@lsi.com) |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
@@ -219,23 +219,25 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
219 | * mpt2sas_ctl_done - ctl module completion routine | 219 | * mpt2sas_ctl_done - ctl module completion routine |
220 | * @ioc: per adapter object | 220 | * @ioc: per adapter object |
221 | * @smid: system request message index | 221 | * @smid: system request message index |
222 | * @VF_ID: virtual function id | 222 | * @msix_index: MSIX table index supplied by the OS |
223 | * @reply: reply message frame(lower 32bit addr) | 223 | * @reply: reply message frame(lower 32bit addr) |
224 | * Context: none. | 224 | * Context: none. |
225 | * | 225 | * |
226 | * The callback handler when using ioc->ctl_cb_idx. | 226 | * The callback handler when using ioc->ctl_cb_idx. |
227 | * | 227 | * |
228 | * Return nothing. | 228 | * Return 1 meaning mf should be freed from _base_interrupt |
229 | * 0 means the mf is freed from this function. | ||
229 | */ | 230 | */ |
230 | void | 231 | u8 |
231 | mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | 232 | mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
233 | u32 reply) | ||
232 | { | 234 | { |
233 | MPI2DefaultReply_t *mpi_reply; | 235 | MPI2DefaultReply_t *mpi_reply; |
234 | 236 | ||
235 | if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) | 237 | if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) |
236 | return; | 238 | return 1; |
237 | if (ioc->ctl_cmds.smid != smid) | 239 | if (ioc->ctl_cmds.smid != smid) |
238 | return; | 240 | return 1; |
239 | ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE; | 241 | ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE; |
240 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 242 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
241 | if (mpi_reply) { | 243 | if (mpi_reply) { |
@@ -247,6 +249,7 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
247 | #endif | 249 | #endif |
248 | ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING; | 250 | ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING; |
249 | complete(&ioc->ctl_cmds.done); | 251 | complete(&ioc->ctl_cmds.done); |
252 | return 1; | ||
250 | } | 253 | } |
251 | 254 | ||
252 | /** | 255 | /** |
@@ -328,22 +331,25 @@ mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, | |||
328 | /** | 331 | /** |
329 | * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time) | 332 | * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time) |
330 | * @ioc: per adapter object | 333 | * @ioc: per adapter object |
331 | * @VF_ID: virtual function id | 334 | * @msix_index: MSIX table index supplied by the OS |
332 | * @reply: reply message frame(lower 32bit addr) | 335 | * @reply: reply message frame(lower 32bit addr) |
333 | * Context: interrupt. | 336 | * Context: interrupt. |
334 | * | 337 | * |
335 | * This function merely adds a new work task into ioc->firmware_event_thread. | 338 | * This function merely adds a new work task into ioc->firmware_event_thread. |
336 | * The tasks are worked from _firmware_event_work in user context. | 339 | * The tasks are worked from _firmware_event_work in user context. |
337 | * | 340 | * |
338 | * Return nothing. | 341 | * Return 1 meaning mf should be freed from _base_interrupt |
342 | * 0 means the mf is freed from this function. | ||
339 | */ | 343 | */ |
340 | void | 344 | u8 |
341 | mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | 345 | mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, |
346 | u32 reply) | ||
342 | { | 347 | { |
343 | Mpi2EventNotificationReply_t *mpi_reply; | 348 | Mpi2EventNotificationReply_t *mpi_reply; |
344 | 349 | ||
345 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 350 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
346 | mpt2sas_ctl_add_to_event_log(ioc, mpi_reply); | 351 | mpt2sas_ctl_add_to_event_log(ioc, mpi_reply); |
352 | return 1; | ||
347 | } | 353 | } |
348 | 354 | ||
349 | /** | 355 | /** |
@@ -507,7 +513,7 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, | |||
507 | 513 | ||
508 | handle = le16_to_cpu(tm_request->DevHandle); | 514 | handle = le16_to_cpu(tm_request->DevHandle); |
509 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 515 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
510 | for (i = ioc->request_depth; i && !found; i--) { | 516 | for (i = ioc->scsiio_depth; i && !found; i--) { |
511 | scmd = ioc->scsi_lookup[i - 1].scmd; | 517 | scmd = ioc->scsi_lookup[i - 1].scmd; |
512 | if (scmd == NULL || scmd->device == NULL || | 518 | if (scmd == NULL || scmd->device == NULL || |
513 | scmd->device->hostdata == NULL) | 519 | scmd->device->hostdata == NULL) |
@@ -614,7 +620,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
614 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | 620 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", |
615 | ioc->name, __func__); | 621 | ioc->name, __func__); |
616 | 622 | ||
617 | smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); | 623 | smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL); |
618 | if (!smid) { | 624 | if (!smid) { |
619 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | 625 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", |
620 | ioc->name, __func__); | 626 | ioc->name, __func__); |
@@ -734,10 +740,10 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
734 | Mpi2SCSIIORequest_t *scsiio_request = | 740 | Mpi2SCSIIORequest_t *scsiio_request = |
735 | (Mpi2SCSIIORequest_t *)mpi_request; | 741 | (Mpi2SCSIIORequest_t *)mpi_request; |
736 | scsiio_request->SenseBufferLowAddress = | 742 | scsiio_request->SenseBufferLowAddress = |
737 | (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid); | 743 | mpt2sas_base_get_sense_buffer_dma(ioc, smid); |
738 | priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid); | 744 | priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid); |
739 | memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE); | 745 | memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE); |
740 | mpt2sas_base_put_smid_scsi_io(ioc, smid, 0, | 746 | mpt2sas_base_put_smid_scsi_io(ioc, smid, |
741 | le16_to_cpu(mpi_request->FunctionDependent1)); | 747 | le16_to_cpu(mpi_request->FunctionDependent1)); |
742 | break; | 748 | break; |
743 | } | 749 | } |
@@ -759,8 +765,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
759 | mutex_lock(&ioc->tm_cmds.mutex); | 765 | mutex_lock(&ioc->tm_cmds.mutex); |
760 | mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu( | 766 | mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu( |
761 | tm_request->DevHandle)); | 767 | tm_request->DevHandle)); |
762 | mpt2sas_base_put_smid_hi_priority(ioc, smid, | 768 | mpt2sas_base_put_smid_hi_priority(ioc, smid); |
763 | mpi_request->VF_ID); | ||
764 | break; | 769 | break; |
765 | } | 770 | } |
766 | case MPI2_FUNCTION_SMP_PASSTHROUGH: | 771 | case MPI2_FUNCTION_SMP_PASSTHROUGH: |
@@ -781,7 +786,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
781 | ioc->ioc_link_reset_in_progress = 1; | 786 | ioc->ioc_link_reset_in_progress = 1; |
782 | ioc->ignore_loginfos = 1; | 787 | ioc->ignore_loginfos = 1; |
783 | } | 788 | } |
784 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 789 | mpt2sas_base_put_smid_default(ioc, smid); |
785 | break; | 790 | break; |
786 | } | 791 | } |
787 | case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: | 792 | case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: |
@@ -795,11 +800,11 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
795 | ioc->ioc_link_reset_in_progress = 1; | 800 | ioc->ioc_link_reset_in_progress = 1; |
796 | ioc->ignore_loginfos = 1; | 801 | ioc->ignore_loginfos = 1; |
797 | } | 802 | } |
798 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 803 | mpt2sas_base_put_smid_default(ioc, smid); |
799 | break; | 804 | break; |
800 | } | 805 | } |
801 | default: | 806 | default: |
802 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 807 | mpt2sas_base_put_smid_default(ioc, smid); |
803 | break; | 808 | break; |
804 | } | 809 | } |
805 | 810 | ||
@@ -807,6 +812,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
807 | timeout = MPT2_IOCTL_DEFAULT_TIMEOUT; | 812 | timeout = MPT2_IOCTL_DEFAULT_TIMEOUT; |
808 | else | 813 | else |
809 | timeout = karg.timeout; | 814 | timeout = karg.timeout; |
815 | init_completion(&ioc->ctl_cmds.done); | ||
810 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 816 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, |
811 | timeout*HZ); | 817 | timeout*HZ); |
812 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { | 818 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { |
@@ -842,8 +848,9 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
842 | printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: " | 848 | printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: " |
843 | "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " | 849 | "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " |
844 | "TerminationCount(0x%08x)\n", ioc->name, | 850 | "TerminationCount(0x%08x)\n", ioc->name, |
845 | tm_reply->IOCStatus, tm_reply->IOCLogInfo, | 851 | le16_to_cpu(tm_reply->IOCStatus), |
846 | tm_reply->TerminationCount); | 852 | le32_to_cpu(tm_reply->IOCLogInfo), |
853 | le32_to_cpu(tm_reply->TerminationCount)); | ||
847 | } | 854 | } |
848 | #endif | 855 | #endif |
849 | /* copy out xdata to user */ | 856 | /* copy out xdata to user */ |
@@ -890,6 +897,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
890 | printk(MPT2SAS_INFO_FMT "issue target reset: handle " | 897 | printk(MPT2SAS_INFO_FMT "issue target reset: handle " |
891 | "= (0x%04x)\n", ioc->name, | 898 | "= (0x%04x)\n", ioc->name, |
892 | mpi_request->FunctionDependent1); | 899 | mpi_request->FunctionDependent1); |
900 | mpt2sas_halt_firmware(ioc); | ||
893 | mutex_lock(&ioc->tm_cmds.mutex); | 901 | mutex_lock(&ioc->tm_cmds.mutex); |
894 | mpt2sas_scsih_issue_tm(ioc, | 902 | mpt2sas_scsih_issue_tm(ioc, |
895 | mpi_request->FunctionDependent1, 0, | 903 | mpi_request->FunctionDependent1, 0, |
@@ -1223,7 +1231,7 @@ _ctl_btdh_mapping(void __user *arg) | |||
1223 | /** | 1231 | /** |
1224 | * _ctl_diag_capability - return diag buffer capability | 1232 | * _ctl_diag_capability - return diag buffer capability |
1225 | * @ioc: per adapter object | 1233 | * @ioc: per adapter object |
1226 | * @buffer_type: specifies either TRACE or SNAPSHOT | 1234 | * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED |
1227 | * | 1235 | * |
1228 | * returns 1 when diag buffer support is enabled in firmware | 1236 | * returns 1 when diag buffer support is enabled in firmware |
1229 | */ | 1237 | */ |
@@ -1243,24 +1251,25 @@ _ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type) | |||
1243 | MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) | 1251 | MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) |
1244 | rc = 1; | 1252 | rc = 1; |
1245 | break; | 1253 | break; |
1254 | case MPI2_DIAG_BUF_TYPE_EXTENDED: | ||
1255 | if (ioc->facts.IOCCapabilities & | ||
1256 | MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) | ||
1257 | rc = 1; | ||
1246 | } | 1258 | } |
1247 | 1259 | ||
1248 | return rc; | 1260 | return rc; |
1249 | } | 1261 | } |
1250 | 1262 | ||
1251 | /** | 1263 | /** |
1252 | * _ctl_diag_register - application register with driver | 1264 | * _ctl_diag_register_2 - wrapper for registering diag buffer support |
1253 | * @arg - user space buffer containing ioctl content | 1265 | * @ioc: per adapter object |
1254 | * @state - NON_BLOCKING or BLOCKING | 1266 | * @diag_register: the diag_register struct passed in from user space |
1255 | * | 1267 | * |
1256 | * This will allow the driver to setup any required buffers that will be | ||
1257 | * needed by firmware to communicate with the driver. | ||
1258 | */ | 1268 | */ |
1259 | static long | 1269 | static long |
1260 | _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) | ||
1261 | { | 1272 | { |
1262 | struct mpt2_diag_register karg; | ||
1263 | struct MPT2SAS_ADAPTER *ioc; | ||
1264 | int rc, i; | 1273 | int rc, i; |
1265 | void *request_data = NULL; | 1274 | void *request_data = NULL; |
1266 | dma_addr_t request_data_dma; | 1275 | dma_addr_t request_data_dma; |
@@ -1273,18 +1282,17 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1273 | u16 ioc_status; | 1282 | u16 ioc_status; |
1274 | u8 issue_reset = 0; | 1283 | u8 issue_reset = 0; |
1275 | 1284 | ||
1276 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
1277 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
1278 | __FILE__, __LINE__, __func__); | ||
1279 | return -EFAULT; | ||
1280 | } | ||
1281 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | ||
1282 | return -ENODEV; | ||
1283 | |||
1284 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1285 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
1285 | __func__)); | 1286 | __func__)); |
1286 | 1287 | ||
1287 | 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; | ||
1288 | if (!_ctl_diag_capability(ioc, buffer_type)) { | 1296 | if (!_ctl_diag_capability(ioc, buffer_type)) { |
1289 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " | 1297 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " |
1290 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | 1298 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); |
@@ -1299,24 +1307,12 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1299 | return -EINVAL; | 1307 | return -EINVAL; |
1300 | } | 1308 | } |
1301 | 1309 | ||
1302 | if (karg.requested_buffer_size % 4) { | 1310 | if (diag_register->requested_buffer_size % 4) { |
1303 | printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size " | 1311 | printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size " |
1304 | "is not 4 byte aligned\n", ioc->name, __func__); | 1312 | "is not 4 byte aligned\n", ioc->name, __func__); |
1305 | return -EINVAL; | 1313 | return -EINVAL; |
1306 | } | 1314 | } |
1307 | 1315 | ||
1308 | if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) | ||
1309 | return -EAGAIN; | ||
1310 | else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) | ||
1311 | return -ERESTARTSYS; | ||
1312 | |||
1313 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { | ||
1314 | printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", | ||
1315 | ioc->name, __func__); | ||
1316 | rc = -EAGAIN; | ||
1317 | goto out; | ||
1318 | } | ||
1319 | |||
1320 | smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); | 1316 | smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); |
1321 | if (!smid) { | 1317 | if (!smid) { |
1322 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | 1318 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", |
@@ -1332,12 +1328,12 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1332 | ioc->ctl_cmds.smid = smid; | 1328 | ioc->ctl_cmds.smid = smid; |
1333 | 1329 | ||
1334 | request_data = ioc->diag_buffer[buffer_type]; | 1330 | request_data = ioc->diag_buffer[buffer_type]; |
1335 | request_data_sz = karg.requested_buffer_size; | 1331 | request_data_sz = diag_register->requested_buffer_size; |
1336 | ioc->unique_id[buffer_type] = karg.unique_id; | 1332 | ioc->unique_id[buffer_type] = diag_register->unique_id; |
1337 | ioc->diag_buffer_status[buffer_type] = 0; | 1333 | ioc->diag_buffer_status[buffer_type] = 0; |
1338 | memcpy(ioc->product_specific[buffer_type], karg.product_specific, | 1334 | memcpy(ioc->product_specific[buffer_type], |
1339 | MPT2_PRODUCT_SPECIFIC_DWORDS); | 1335 | diag_register->product_specific, MPT2_PRODUCT_SPECIFIC_DWORDS); |
1340 | ioc->diagnostic_flags[buffer_type] = karg.diagnostic_flags; | 1336 | ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags; |
1341 | 1337 | ||
1342 | if (request_data) { | 1338 | if (request_data) { |
1343 | request_data_dma = ioc->diag_buffer_dma[buffer_type]; | 1339 | request_data_dma = ioc->diag_buffer_dma[buffer_type]; |
@@ -1367,10 +1363,12 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1367 | } | 1363 | } |
1368 | 1364 | ||
1369 | mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; | 1365 | mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; |
1370 | mpi_request->BufferType = karg.buffer_type; | 1366 | mpi_request->BufferType = diag_register->buffer_type; |
1371 | mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags); | 1367 | mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags); |
1372 | mpi_request->BufferAddress = cpu_to_le64(request_data_dma); | 1368 | mpi_request->BufferAddress = cpu_to_le64(request_data_dma); |
1373 | mpi_request->BufferLength = cpu_to_le32(request_data_sz); | 1369 | mpi_request->BufferLength = cpu_to_le32(request_data_sz); |
1370 | mpi_request->VF_ID = 0; /* TODO */ | ||
1371 | mpi_request->VP_ID = 0; | ||
1374 | 1372 | ||
1375 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), " | 1373 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), " |
1376 | "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data, | 1374 | "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data, |
@@ -1380,7 +1378,8 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1380 | mpi_request->ProductSpecific[i] = | 1378 | mpi_request->ProductSpecific[i] = |
1381 | cpu_to_le32(ioc->product_specific[buffer_type][i]); | 1379 | cpu_to_le32(ioc->product_specific[buffer_type][i]); |
1382 | 1380 | ||
1383 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 1381 | mpt2sas_base_put_smid_default(ioc, smid); |
1382 | init_completion(&ioc->ctl_cmds.done); | ||
1384 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 1383 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, |
1385 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); | 1384 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); |
1386 | 1385 | ||
@@ -1413,7 +1412,7 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1413 | } else { | 1412 | } else { |
1414 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " | 1413 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " |
1415 | "log_info(0x%08x)\n", ioc->name, __func__, | 1414 | "log_info(0x%08x)\n", ioc->name, __func__, |
1416 | ioc_status, mpi_reply->IOCLogInfo); | 1415 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); |
1417 | rc = -EFAULT; | 1416 | rc = -EFAULT; |
1418 | } | 1417 | } |
1419 | 1418 | ||
@@ -1429,6 +1428,83 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1429 | request_data, request_data_dma); | 1428 | request_data, request_data_dma); |
1430 | 1429 | ||
1431 | 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); | ||
1432 | mutex_unlock(&ioc->ctl_cmds.mutex); | 1508 | mutex_unlock(&ioc->ctl_cmds.mutex); |
1433 | return rc; | 1509 | return rc; |
1434 | } | 1510 | } |
@@ -1591,7 +1667,7 @@ _ctl_diag_query(void __user *arg) | |||
1591 | /** | 1667 | /** |
1592 | * _ctl_send_release - Diag Release Message | 1668 | * _ctl_send_release - Diag Release Message |
1593 | * @ioc: per adapter object | 1669 | * @ioc: per adapter object |
1594 | * @buffer_type - specifies either TRACE or SNAPSHOT | 1670 | * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED |
1595 | * @issue_reset - specifies whether host reset is required. | 1671 | * @issue_reset - specifies whether host reset is required. |
1596 | * | 1672 | * |
1597 | */ | 1673 | */ |
@@ -1643,8 +1719,11 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) | |||
1643 | 1719 | ||
1644 | mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE; | 1720 | mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE; |
1645 | mpi_request->BufferType = buffer_type; | 1721 | mpi_request->BufferType = buffer_type; |
1722 | mpi_request->VF_ID = 0; /* TODO */ | ||
1723 | mpi_request->VP_ID = 0; | ||
1646 | 1724 | ||
1647 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 1725 | mpt2sas_base_put_smid_default(ioc, smid); |
1726 | init_completion(&ioc->ctl_cmds.done); | ||
1648 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 1727 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, |
1649 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); | 1728 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); |
1650 | 1729 | ||
@@ -1678,7 +1757,7 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) | |||
1678 | } else { | 1757 | } else { |
1679 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " | 1758 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " |
1680 | "log_info(0x%08x)\n", ioc->name, __func__, | 1759 | "log_info(0x%08x)\n", ioc->name, __func__, |
1681 | ioc_status, mpi_reply->IOCLogInfo); | 1760 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); |
1682 | rc = -EFAULT; | 1761 | rc = -EFAULT; |
1683 | } | 1762 | } |
1684 | 1763 | ||
@@ -1902,8 +1981,11 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
1902 | for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) | 1981 | for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) |
1903 | mpi_request->ProductSpecific[i] = | 1982 | mpi_request->ProductSpecific[i] = |
1904 | cpu_to_le32(ioc->product_specific[buffer_type][i]); | 1983 | cpu_to_le32(ioc->product_specific[buffer_type][i]); |
1984 | mpi_request->VF_ID = 0; /* TODO */ | ||
1985 | mpi_request->VP_ID = 0; | ||
1905 | 1986 | ||
1906 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 1987 | mpt2sas_base_put_smid_default(ioc, smid); |
1988 | init_completion(&ioc->ctl_cmds.done); | ||
1907 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 1989 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, |
1908 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); | 1990 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); |
1909 | 1991 | ||
@@ -1936,7 +2018,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
1936 | } else { | 2018 | } else { |
1937 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " | 2019 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " |
1938 | "log_info(0x%08x)\n", ioc->name, __func__, | 2020 | "log_info(0x%08x)\n", ioc->name, __func__, |
1939 | ioc_status, mpi_reply->IOCLogInfo); | 2021 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); |
1940 | rc = -EFAULT; | 2022 | rc = -EFAULT; |
1941 | } | 2023 | } |
1942 | 2024 | ||
@@ -2069,6 +2151,7 @@ static long | |||
2069 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 2151 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
2070 | { | 2152 | { |
2071 | long ret; | 2153 | long ret; |
2154 | |||
2072 | lock_kernel(); | 2155 | lock_kernel(); |
2073 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg); | 2156 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg); |
2074 | unlock_kernel(); | 2157 | unlock_kernel(); |
@@ -2143,6 +2226,7 @@ static long | |||
2143 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) | 2226 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) |
2144 | { | 2227 | { |
2145 | long ret; | 2228 | long ret; |
2229 | |||
2146 | lock_kernel(); | 2230 | lock_kernel(); |
2147 | if (cmd == MPT2COMMAND32) | 2231 | if (cmd == MPT2COMMAND32) |
2148 | ret = _ctl_compat_mpt_command(file, cmd, arg); | 2232 | ret = _ctl_compat_mpt_command(file, cmd, arg); |
@@ -2457,6 +2541,43 @@ _ctl_logging_level_store(struct device *cdev, struct device_attribute *attr, | |||
2457 | static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, | 2541 | static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, |
2458 | _ctl_logging_level_show, _ctl_logging_level_store); | 2542 | _ctl_logging_level_show, _ctl_logging_level_store); |
2459 | 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 | |||
2460 | struct device_attribute *mpt2sas_host_attrs[] = { | 2581 | struct device_attribute *mpt2sas_host_attrs[] = { |
2461 | &dev_attr_version_fw, | 2582 | &dev_attr_version_fw, |
2462 | &dev_attr_version_bios, | 2583 | &dev_attr_version_bios, |
@@ -2470,13 +2591,12 @@ struct device_attribute *mpt2sas_host_attrs[] = { | |||
2470 | &dev_attr_io_delay, | 2591 | &dev_attr_io_delay, |
2471 | &dev_attr_device_delay, | 2592 | &dev_attr_device_delay, |
2472 | &dev_attr_logging_level, | 2593 | &dev_attr_logging_level, |
2594 | &dev_attr_fwfault_debug, | ||
2473 | &dev_attr_fw_queue_depth, | 2595 | &dev_attr_fw_queue_depth, |
2474 | &dev_attr_host_sas_address, | 2596 | &dev_attr_host_sas_address, |
2475 | NULL, | 2597 | NULL, |
2476 | }; | 2598 | }; |
2477 | 2599 | ||
2478 | /* device attributes */ | ||
2479 | |||
2480 | /** | 2600 | /** |
2481 | * _ctl_device_sas_address_show - sas address | 2601 | * _ctl_device_sas_address_show - sas address |
2482 | * @cdev - pointer to embedded class device | 2602 | * @cdev - pointer to embedded class device |