diff options
-rw-r--r-- | drivers/scsi/pmcraid.c | 129 | ||||
-rw-r--r-- | drivers/scsi/pmcraid.h | 22 |
2 files changed, 129 insertions, 22 deletions
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 4b8765785aeb..cf89091e4c3d 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c | |||
@@ -1594,10 +1594,12 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) | |||
1594 | cfg_entry = &ccn_hcam->cfg_entry; | 1594 | cfg_entry = &ccn_hcam->cfg_entry; |
1595 | fw_version = be16_to_cpu(pinstance->inq_data->fw_version); | 1595 | fw_version = be16_to_cpu(pinstance->inq_data->fw_version); |
1596 | 1596 | ||
1597 | pmcraid_info | 1597 | pmcraid_info("CCN(%x): %x timestamp: %llx type: %x lost: %x flags: %x \ |
1598 | ("CCN(%x): %x type: %x lost: %x flags: %x res: %x:%x:%x:%x\n", | 1598 | res: %x:%x:%x:%x\n", |
1599 | pinstance->ccn.hcam->ilid, | 1599 | pinstance->ccn.hcam->ilid, |
1600 | pinstance->ccn.hcam->op_code, | 1600 | pinstance->ccn.hcam->op_code, |
1601 | ((pinstance->ccn.hcam->timestamp1) | | ||
1602 | ((pinstance->ccn.hcam->timestamp2 & 0xffffffffLL) << 32)), | ||
1601 | pinstance->ccn.hcam->notification_type, | 1603 | pinstance->ccn.hcam->notification_type, |
1602 | pinstance->ccn.hcam->notification_lost, | 1604 | pinstance->ccn.hcam->notification_lost, |
1603 | pinstance->ccn.hcam->flags, | 1605 | pinstance->ccn.hcam->flags, |
@@ -1850,6 +1852,7 @@ static void pmcraid_process_ccn(struct pmcraid_cmd *cmd) | |||
1850 | * none | 1852 | * none |
1851 | */ | 1853 | */ |
1852 | static void pmcraid_initiate_reset(struct pmcraid_instance *); | 1854 | static void pmcraid_initiate_reset(struct pmcraid_instance *); |
1855 | static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd); | ||
1853 | 1856 | ||
1854 | static void pmcraid_process_ldn(struct pmcraid_cmd *cmd) | 1857 | static void pmcraid_process_ldn(struct pmcraid_cmd *cmd) |
1855 | { | 1858 | { |
@@ -1881,6 +1884,10 @@ static void pmcraid_process_ldn(struct pmcraid_cmd *cmd) | |||
1881 | lock_flags); | 1884 | lock_flags); |
1882 | return; | 1885 | return; |
1883 | } | 1886 | } |
1887 | if (fd_ioasc == PMCRAID_IOASC_TIME_STAMP_OUT_OF_SYNC) { | ||
1888 | pinstance->timestamp_error = 1; | ||
1889 | pmcraid_set_timestamp(cmd); | ||
1890 | } | ||
1884 | } else { | 1891 | } else { |
1885 | dev_info(&pinstance->pdev->dev, | 1892 | dev_info(&pinstance->pdev->dev, |
1886 | "Host RCB(LDN) failed with IOASC: 0x%08X\n", ioasc); | 1893 | "Host RCB(LDN) failed with IOASC: 0x%08X\n", ioasc); |
@@ -3363,7 +3370,7 @@ static struct pmcraid_sglist *pmcraid_alloc_sglist(int buflen) | |||
3363 | sg_size = buflen; | 3370 | sg_size = buflen; |
3364 | 3371 | ||
3365 | for (i = 0; i < num_elem; i++) { | 3372 | for (i = 0; i < num_elem; i++) { |
3366 | page = alloc_pages(GFP_KERNEL|GFP_DMA, order); | 3373 | page = alloc_pages(GFP_KERNEL|GFP_DMA|__GFP_ZERO, order); |
3367 | if (!page) { | 3374 | if (!page) { |
3368 | for (j = i - 1; j >= 0; j--) | 3375 | for (j = i - 1; j >= 0; j--) |
3369 | __free_pages(sg_page(&scatterlist[j]), order); | 3376 | __free_pages(sg_page(&scatterlist[j]), order); |
@@ -3739,6 +3746,7 @@ static long pmcraid_ioctl_passthrough( | |||
3739 | unsigned long request_buffer; | 3746 | unsigned long request_buffer; |
3740 | unsigned long request_offset; | 3747 | unsigned long request_offset; |
3741 | unsigned long lock_flags; | 3748 | unsigned long lock_flags; |
3749 | void *ioasa; | ||
3742 | u32 ioasc; | 3750 | u32 ioasc; |
3743 | int request_size; | 3751 | int request_size; |
3744 | int buffer_size; | 3752 | int buffer_size; |
@@ -3780,6 +3788,11 @@ static long pmcraid_ioctl_passthrough( | |||
3780 | rc = __copy_from_user(buffer, | 3788 | rc = __copy_from_user(buffer, |
3781 | (struct pmcraid_passthrough_ioctl_buffer *) arg, | 3789 | (struct pmcraid_passthrough_ioctl_buffer *) arg, |
3782 | sizeof(struct pmcraid_passthrough_ioctl_buffer)); | 3790 | sizeof(struct pmcraid_passthrough_ioctl_buffer)); |
3791 | |||
3792 | ioasa = | ||
3793 | (void *)(arg + | ||
3794 | offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); | ||
3795 | |||
3783 | if (rc) { | 3796 | if (rc) { |
3784 | pmcraid_err("ioctl: can't copy passthrough buffer\n"); | 3797 | pmcraid_err("ioctl: can't copy passthrough buffer\n"); |
3785 | rc = -EFAULT; | 3798 | rc = -EFAULT; |
@@ -3947,22 +3960,14 @@ static long pmcraid_ioctl_passthrough( | |||
3947 | } | 3960 | } |
3948 | 3961 | ||
3949 | out_handle_response: | 3962 | out_handle_response: |
3950 | /* If the command failed for any reason, copy entire IOASA buffer and | 3963 | /* copy entire IOASA buffer and return IOCTL success. |
3951 | * return IOCTL success. If copying IOASA to user-buffer fails, return | 3964 | * If copying IOASA to user-buffer fails, return |
3952 | * EFAULT | 3965 | * EFAULT |
3953 | */ | 3966 | */ |
3954 | if (PMCRAID_IOASC_SENSE_KEY(le32_to_cpu(cmd->ioa_cb->ioasa.ioasc))) { | 3967 | if (copy_to_user(ioasa, &cmd->ioa_cb->ioasa, |
3955 | void *ioasa = | 3968 | sizeof(struct pmcraid_ioasa))) { |
3956 | (void *)(arg + | 3969 | pmcraid_err("failed to copy ioasa buffer to user\n"); |
3957 | offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); | 3970 | rc = -EFAULT; |
3958 | |||
3959 | pmcraid_info("command failed with %x\n", | ||
3960 | le32_to_cpu(cmd->ioa_cb->ioasa.ioasc)); | ||
3961 | if (copy_to_user(ioasa, &cmd->ioa_cb->ioasa, | ||
3962 | sizeof(struct pmcraid_ioasa))) { | ||
3963 | pmcraid_err("failed to copy ioasa buffer to user\n"); | ||
3964 | rc = -EFAULT; | ||
3965 | } | ||
3966 | } | 3971 | } |
3967 | 3972 | ||
3968 | /* If the data transfer was from device, copy the data onto user | 3973 | /* If the data transfer was from device, copy the data onto user |
@@ -5147,6 +5152,16 @@ static void pmcraid_release_buffers(struct pmcraid_instance *pinstance) | |||
5147 | pinstance->inq_data = NULL; | 5152 | pinstance->inq_data = NULL; |
5148 | pinstance->inq_data_baddr = 0; | 5153 | pinstance->inq_data_baddr = 0; |
5149 | } | 5154 | } |
5155 | |||
5156 | if (pinstance->timestamp_data != NULL) { | ||
5157 | pci_free_consistent(pinstance->pdev, | ||
5158 | sizeof(struct pmcraid_timestamp_data), | ||
5159 | pinstance->timestamp_data, | ||
5160 | pinstance->timestamp_data_baddr); | ||
5161 | |||
5162 | pinstance->timestamp_data = NULL; | ||
5163 | pinstance->timestamp_data_baddr = 0; | ||
5164 | } | ||
5150 | } | 5165 | } |
5151 | 5166 | ||
5152 | /** | 5167 | /** |
@@ -5205,6 +5220,20 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance) | |||
5205 | return -ENOMEM; | 5220 | return -ENOMEM; |
5206 | } | 5221 | } |
5207 | 5222 | ||
5223 | /* allocate DMAable memory for set timestamp data buffer */ | ||
5224 | pinstance->timestamp_data = pci_alloc_consistent( | ||
5225 | pinstance->pdev, | ||
5226 | sizeof(struct pmcraid_timestamp_data), | ||
5227 | &pinstance->timestamp_data_baddr); | ||
5228 | |||
5229 | if (pinstance->timestamp_data == NULL) { | ||
5230 | pmcraid_err("couldn't allocate DMA memory for \ | ||
5231 | set time_stamp \n"); | ||
5232 | pmcraid_release_buffers(pinstance); | ||
5233 | return -ENOMEM; | ||
5234 | } | ||
5235 | |||
5236 | |||
5208 | /* Initialize all the command blocks and add them to free pool. No | 5237 | /* Initialize all the command blocks and add them to free pool. No |
5209 | * need to lock (free_pool_lock) as this is done in initialization | 5238 | * need to lock (free_pool_lock) as this is done in initialization |
5210 | * itself | 5239 | * itself |
@@ -5610,6 +5639,68 @@ static void pmcraid_set_supported_devs(struct pmcraid_cmd *cmd) | |||
5610 | } | 5639 | } |
5611 | 5640 | ||
5612 | /** | 5641 | /** |
5642 | * pmcraid_set_timestamp - set the timestamp to IOAFP | ||
5643 | * | ||
5644 | * @cmd: pointer to pmcraid_cmd structure | ||
5645 | * | ||
5646 | * Return Value | ||
5647 | * 0 for success or non-zero for failure cases | ||
5648 | */ | ||
5649 | static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd) | ||
5650 | { | ||
5651 | struct pmcraid_instance *pinstance = cmd->drv_inst; | ||
5652 | struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; | ||
5653 | __be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN); | ||
5654 | struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; | ||
5655 | |||
5656 | struct timeval tv; | ||
5657 | __le64 timestamp; | ||
5658 | |||
5659 | do_gettimeofday(&tv); | ||
5660 | timestamp = tv.tv_sec * 1000; | ||
5661 | |||
5662 | pinstance->timestamp_data->timestamp[0] = (__u8)(timestamp); | ||
5663 | pinstance->timestamp_data->timestamp[1] = (__u8)((timestamp) >> 8); | ||
5664 | pinstance->timestamp_data->timestamp[2] = (__u8)((timestamp) >> 16); | ||
5665 | pinstance->timestamp_data->timestamp[3] = (__u8)((timestamp) >> 24); | ||
5666 | pinstance->timestamp_data->timestamp[4] = (__u8)((timestamp) >> 32); | ||
5667 | pinstance->timestamp_data->timestamp[5] = (__u8)((timestamp) >> 40); | ||
5668 | |||
5669 | pmcraid_reinit_cmdblk(cmd); | ||
5670 | ioarcb->request_type = REQ_TYPE_SCSI; | ||
5671 | ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); | ||
5672 | ioarcb->cdb[0] = PMCRAID_SCSI_SET_TIMESTAMP; | ||
5673 | ioarcb->cdb[1] = PMCRAID_SCSI_SERVICE_ACTION; | ||
5674 | memcpy(&(ioarcb->cdb[6]), &time_stamp_len, sizeof(time_stamp_len)); | ||
5675 | |||
5676 | ioarcb->ioadl_bus_addr = cpu_to_le64((cmd->ioa_cb_bus_addr) + | ||
5677 | offsetof(struct pmcraid_ioarcb, | ||
5678 | add_data.u.ioadl[0])); | ||
5679 | ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc)); | ||
5680 | ioarcb->ioarcb_bus_addr &= ~(0x1FULL); | ||
5681 | |||
5682 | ioarcb->request_flags0 |= NO_LINK_DESCS; | ||
5683 | ioarcb->request_flags0 |= TRANSFER_DIR_WRITE; | ||
5684 | ioarcb->data_transfer_length = | ||
5685 | cpu_to_le32(sizeof(struct pmcraid_timestamp_data)); | ||
5686 | ioadl = &(ioarcb->add_data.u.ioadl[0]); | ||
5687 | ioadl->flags = IOADL_FLAGS_LAST_DESC; | ||
5688 | ioadl->address = cpu_to_le64(pinstance->timestamp_data_baddr); | ||
5689 | ioadl->data_len = cpu_to_le32(sizeof(struct pmcraid_timestamp_data)); | ||
5690 | |||
5691 | if (!pinstance->timestamp_error) { | ||
5692 | pinstance->timestamp_error = 0; | ||
5693 | pmcraid_send_cmd(cmd, pmcraid_set_supported_devs, | ||
5694 | PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler); | ||
5695 | } else { | ||
5696 | pmcraid_send_cmd(cmd, pmcraid_return_cmd, | ||
5697 | PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler); | ||
5698 | return; | ||
5699 | } | ||
5700 | } | ||
5701 | |||
5702 | |||
5703 | /** | ||
5613 | * pmcraid_init_res_table - Initialize the resource table | 5704 | * pmcraid_init_res_table - Initialize the resource table |
5614 | * @cmd: pointer to pmcraid command struct | 5705 | * @cmd: pointer to pmcraid command struct |
5615 | * | 5706 | * |
@@ -5720,7 +5811,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
5720 | 5811 | ||
5721 | /* release the resource list lock */ | 5812 | /* release the resource list lock */ |
5722 | spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags); | 5813 | spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags); |
5723 | pmcraid_set_supported_devs(cmd); | 5814 | pmcraid_set_timestamp(cmd); |
5724 | } | 5815 | } |
5725 | 5816 | ||
5726 | /** | 5817 | /** |
@@ -6054,10 +6145,10 @@ out_init: | |||
6054 | static void __exit pmcraid_exit(void) | 6145 | static void __exit pmcraid_exit(void) |
6055 | { | 6146 | { |
6056 | pmcraid_netlink_release(); | 6147 | pmcraid_netlink_release(); |
6057 | class_destroy(pmcraid_class); | ||
6058 | unregister_chrdev_region(MKDEV(pmcraid_major, 0), | 6148 | unregister_chrdev_region(MKDEV(pmcraid_major, 0), |
6059 | PMCRAID_MAX_ADAPTERS); | 6149 | PMCRAID_MAX_ADAPTERS); |
6060 | pci_unregister_driver(&pmcraid_driver); | 6150 | pci_unregister_driver(&pmcraid_driver); |
6151 | class_destroy(pmcraid_class); | ||
6061 | } | 6152 | } |
6062 | 6153 | ||
6063 | module_init(pmcraid_init); | 6154 | module_init(pmcraid_init); |
diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index dd78f9e8eb9b..1134279604e8 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h | |||
@@ -42,7 +42,7 @@ | |||
42 | */ | 42 | */ |
43 | #define PMCRAID_DRIVER_NAME "PMC MaxRAID" | 43 | #define PMCRAID_DRIVER_NAME "PMC MaxRAID" |
44 | #define PMCRAID_DEVFILE "pmcsas" | 44 | #define PMCRAID_DEVFILE "pmcsas" |
45 | #define PMCRAID_DRIVER_VERSION "2.0.2" | 45 | #define PMCRAID_DRIVER_VERSION "2.0.3" |
46 | #define PMCRAID_DRIVER_DATE __DATE__ | 46 | #define PMCRAID_DRIVER_DATE __DATE__ |
47 | 47 | ||
48 | #define PMCRAID_FW_VERSION_1 0x002 | 48 | #define PMCRAID_FW_VERSION_1 0x002 |
@@ -184,6 +184,7 @@ | |||
184 | #define PMCRAID_IOASC_IR_INVALID_RESOURCE_HANDLE 0x05250000 | 184 | #define PMCRAID_IOASC_IR_INVALID_RESOURCE_HANDLE 0x05250000 |
185 | #define PMCRAID_IOASC_AC_TERMINATED_BY_HOST 0x0B5A0000 | 185 | #define PMCRAID_IOASC_AC_TERMINATED_BY_HOST 0x0B5A0000 |
186 | #define PMCRAID_IOASC_UA_BUS_WAS_RESET 0x06290000 | 186 | #define PMCRAID_IOASC_UA_BUS_WAS_RESET 0x06290000 |
187 | #define PMCRAID_IOASC_TIME_STAMP_OUT_OF_SYNC 0x06908B00 | ||
187 | #define PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER 0x06298000 | 188 | #define PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER 0x06298000 |
188 | 189 | ||
189 | /* Driver defined IOASCs */ | 190 | /* Driver defined IOASCs */ |
@@ -561,6 +562,17 @@ struct pmcraid_inquiry_data { | |||
561 | __u8 reserved3[16]; | 562 | __u8 reserved3[16]; |
562 | }; | 563 | }; |
563 | 564 | ||
565 | #define PMCRAID_TIMESTAMP_LEN 12 | ||
566 | #define PMCRAID_REQ_TM_STR_LEN 6 | ||
567 | #define PMCRAID_SCSI_SET_TIMESTAMP 0xA4 | ||
568 | #define PMCRAID_SCSI_SERVICE_ACTION 0x0F | ||
569 | |||
570 | struct pmcraid_timestamp_data { | ||
571 | __u8 reserved1[4]; | ||
572 | __u8 timestamp[PMCRAID_REQ_TM_STR_LEN]; /* current time value */ | ||
573 | __u8 reserved2[2]; | ||
574 | }; | ||
575 | |||
564 | /* pmcraid_cmd - LLD representation of SCSI command */ | 576 | /* pmcraid_cmd - LLD representation of SCSI command */ |
565 | struct pmcraid_cmd { | 577 | struct pmcraid_cmd { |
566 | 578 | ||
@@ -704,6 +716,9 @@ struct pmcraid_instance { | |||
704 | struct pmcraid_inquiry_data *inq_data; | 716 | struct pmcraid_inquiry_data *inq_data; |
705 | dma_addr_t inq_data_baddr; | 717 | dma_addr_t inq_data_baddr; |
706 | 718 | ||
719 | struct pmcraid_timestamp_data *timestamp_data; | ||
720 | dma_addr_t timestamp_data_baddr; | ||
721 | |||
707 | /* size of configuration table entry, varies based on the firmware */ | 722 | /* size of configuration table entry, varies based on the firmware */ |
708 | u32 config_table_entry_size; | 723 | u32 config_table_entry_size; |
709 | 724 | ||
@@ -790,6 +805,7 @@ struct pmcraid_instance { | |||
790 | #define SHUTDOWN_NONE 0x0 | 805 | #define SHUTDOWN_NONE 0x0 |
791 | #define SHUTDOWN_NORMAL 0x1 | 806 | #define SHUTDOWN_NORMAL 0x1 |
792 | #define SHUTDOWN_ABBREV 0x2 | 807 | #define SHUTDOWN_ABBREV 0x2 |
808 | u32 timestamp_error:1; /* indicate set timestamp for out of sync */ | ||
793 | 809 | ||
794 | }; | 810 | }; |
795 | 811 | ||
@@ -1055,10 +1071,10 @@ struct pmcraid_passthrough_ioctl_buffer { | |||
1055 | #define PMCRAID_PASSTHROUGH_IOCTL 'F' | 1071 | #define PMCRAID_PASSTHROUGH_IOCTL 'F' |
1056 | 1072 | ||
1057 | #define DRV_IOCTL(n, size) \ | 1073 | #define DRV_IOCTL(n, size) \ |
1058 | _IOC(_IOC_READ|_IOC_WRITE, PMCRAID_DRIVER_IOCTL, (n), (size)) | 1074 | _IOC(_IOC_READ|_IOC_WRITE, PMCRAID_DRIVER_IOCTL, (n), (size)) |
1059 | 1075 | ||
1060 | #define FMW_IOCTL(n, size) \ | 1076 | #define FMW_IOCTL(n, size) \ |
1061 | _IOC(_IOC_READ|_IOC_WRITE, PMCRAID_PASSTHROUGH_IOCTL, (n), (size)) | 1077 | _IOC(_IOC_READ|_IOC_WRITE, PMCRAID_PASSTHROUGH_IOCTL, (n), (size)) |
1062 | 1078 | ||
1063 | /* | 1079 | /* |
1064 | * _ARGSIZE: macro that gives size of the argument type passed to an IOCTL cmd. | 1080 | * _ARGSIZE: macro that gives size of the argument type passed to an IOCTL cmd. |