diff options
Diffstat (limited to 'drivers/scsi/pmcraid.c')
-rw-r--r-- | drivers/scsi/pmcraid.c | 134 |
1 files changed, 114 insertions, 20 deletions
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index ecc45c8b4e6b..5e76a624cb08 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); |
@@ -3471,7 +3478,7 @@ static int pmcraid_copy_sglist( | |||
3471 | * SCSI_MLQUEUE_DEVICE_BUSY if device is busy | 3478 | * SCSI_MLQUEUE_DEVICE_BUSY if device is busy |
3472 | * SCSI_MLQUEUE_HOST_BUSY if host is busy | 3479 | * SCSI_MLQUEUE_HOST_BUSY if host is busy |
3473 | */ | 3480 | */ |
3474 | static int pmcraid_queuecommand( | 3481 | static int pmcraid_queuecommand_lck( |
3475 | struct scsi_cmnd *scsi_cmd, | 3482 | struct scsi_cmnd *scsi_cmd, |
3476 | void (*done) (struct scsi_cmnd *) | 3483 | void (*done) (struct scsi_cmnd *) |
3477 | ) | 3484 | ) |
@@ -3577,6 +3584,8 @@ static int pmcraid_queuecommand( | |||
3577 | return rc; | 3584 | return rc; |
3578 | } | 3585 | } |
3579 | 3586 | ||
3587 | static DEF_SCSI_QCMD(pmcraid_queuecommand) | ||
3588 | |||
3580 | /** | 3589 | /** |
3581 | * pmcraid_open -char node "open" entry, allowed only users with admin access | 3590 | * pmcraid_open -char node "open" entry, allowed only users with admin access |
3582 | */ | 3591 | */ |
@@ -3739,6 +3748,7 @@ static long pmcraid_ioctl_passthrough( | |||
3739 | unsigned long request_buffer; | 3748 | unsigned long request_buffer; |
3740 | unsigned long request_offset; | 3749 | unsigned long request_offset; |
3741 | unsigned long lock_flags; | 3750 | unsigned long lock_flags; |
3751 | void *ioasa; | ||
3742 | u32 ioasc; | 3752 | u32 ioasc; |
3743 | int request_size; | 3753 | int request_size; |
3744 | int buffer_size; | 3754 | int buffer_size; |
@@ -3780,6 +3790,11 @@ static long pmcraid_ioctl_passthrough( | |||
3780 | rc = __copy_from_user(buffer, | 3790 | rc = __copy_from_user(buffer, |
3781 | (struct pmcraid_passthrough_ioctl_buffer *) arg, | 3791 | (struct pmcraid_passthrough_ioctl_buffer *) arg, |
3782 | sizeof(struct pmcraid_passthrough_ioctl_buffer)); | 3792 | sizeof(struct pmcraid_passthrough_ioctl_buffer)); |
3793 | |||
3794 | ioasa = | ||
3795 | (void *)(arg + | ||
3796 | offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); | ||
3797 | |||
3783 | if (rc) { | 3798 | if (rc) { |
3784 | pmcraid_err("ioctl: can't copy passthrough buffer\n"); | 3799 | pmcraid_err("ioctl: can't copy passthrough buffer\n"); |
3785 | rc = -EFAULT; | 3800 | rc = -EFAULT; |
@@ -3947,22 +3962,14 @@ static long pmcraid_ioctl_passthrough( | |||
3947 | } | 3962 | } |
3948 | 3963 | ||
3949 | out_handle_response: | 3964 | out_handle_response: |
3950 | /* If the command failed for any reason, copy entire IOASA buffer and | 3965 | /* copy entire IOASA buffer and return IOCTL success. |
3951 | * return IOCTL success. If copying IOASA to user-buffer fails, return | 3966 | * If copying IOASA to user-buffer fails, return |
3952 | * EFAULT | 3967 | * EFAULT |
3953 | */ | 3968 | */ |
3954 | if (PMCRAID_IOASC_SENSE_KEY(le32_to_cpu(cmd->ioa_cb->ioasa.ioasc))) { | 3969 | if (copy_to_user(ioasa, &cmd->ioa_cb->ioasa, |
3955 | void *ioasa = | 3970 | sizeof(struct pmcraid_ioasa))) { |
3956 | (void *)(arg + | 3971 | pmcraid_err("failed to copy ioasa buffer to user\n"); |
3957 | offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); | 3972 | 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 | } | 3973 | } |
3967 | 3974 | ||
3968 | /* If the data transfer was from device, copy the data onto user | 3975 | /* If the data transfer was from device, copy the data onto user |
@@ -4165,6 +4172,7 @@ static const struct file_operations pmcraid_fops = { | |||
4165 | #ifdef CONFIG_COMPAT | 4172 | #ifdef CONFIG_COMPAT |
4166 | .compat_ioctl = pmcraid_chr_ioctl, | 4173 | .compat_ioctl = pmcraid_chr_ioctl, |
4167 | #endif | 4174 | #endif |
4175 | .llseek = noop_llseek, | ||
4168 | }; | 4176 | }; |
4169 | 4177 | ||
4170 | 4178 | ||
@@ -5146,6 +5154,16 @@ static void pmcraid_release_buffers(struct pmcraid_instance *pinstance) | |||
5146 | pinstance->inq_data = NULL; | 5154 | pinstance->inq_data = NULL; |
5147 | pinstance->inq_data_baddr = 0; | 5155 | pinstance->inq_data_baddr = 0; |
5148 | } | 5156 | } |
5157 | |||
5158 | if (pinstance->timestamp_data != NULL) { | ||
5159 | pci_free_consistent(pinstance->pdev, | ||
5160 | sizeof(struct pmcraid_timestamp_data), | ||
5161 | pinstance->timestamp_data, | ||
5162 | pinstance->timestamp_data_baddr); | ||
5163 | |||
5164 | pinstance->timestamp_data = NULL; | ||
5165 | pinstance->timestamp_data_baddr = 0; | ||
5166 | } | ||
5149 | } | 5167 | } |
5150 | 5168 | ||
5151 | /** | 5169 | /** |
@@ -5204,6 +5222,20 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance) | |||
5204 | return -ENOMEM; | 5222 | return -ENOMEM; |
5205 | } | 5223 | } |
5206 | 5224 | ||
5225 | /* allocate DMAable memory for set timestamp data buffer */ | ||
5226 | pinstance->timestamp_data = pci_alloc_consistent( | ||
5227 | pinstance->pdev, | ||
5228 | sizeof(struct pmcraid_timestamp_data), | ||
5229 | &pinstance->timestamp_data_baddr); | ||
5230 | |||
5231 | if (pinstance->timestamp_data == NULL) { | ||
5232 | pmcraid_err("couldn't allocate DMA memory for \ | ||
5233 | set time_stamp \n"); | ||
5234 | pmcraid_release_buffers(pinstance); | ||
5235 | return -ENOMEM; | ||
5236 | } | ||
5237 | |||
5238 | |||
5207 | /* Initialize all the command blocks and add them to free pool. No | 5239 | /* Initialize all the command blocks and add them to free pool. No |
5208 | * need to lock (free_pool_lock) as this is done in initialization | 5240 | * need to lock (free_pool_lock) as this is done in initialization |
5209 | * itself | 5241 | * itself |
@@ -5609,6 +5641,68 @@ static void pmcraid_set_supported_devs(struct pmcraid_cmd *cmd) | |||
5609 | } | 5641 | } |
5610 | 5642 | ||
5611 | /** | 5643 | /** |
5644 | * pmcraid_set_timestamp - set the timestamp to IOAFP | ||
5645 | * | ||
5646 | * @cmd: pointer to pmcraid_cmd structure | ||
5647 | * | ||
5648 | * Return Value | ||
5649 | * 0 for success or non-zero for failure cases | ||
5650 | */ | ||
5651 | static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd) | ||
5652 | { | ||
5653 | struct pmcraid_instance *pinstance = cmd->drv_inst; | ||
5654 | struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; | ||
5655 | __be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN); | ||
5656 | struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; | ||
5657 | |||
5658 | struct timeval tv; | ||
5659 | __le64 timestamp; | ||
5660 | |||
5661 | do_gettimeofday(&tv); | ||
5662 | timestamp = tv.tv_sec * 1000; | ||
5663 | |||
5664 | pinstance->timestamp_data->timestamp[0] = (__u8)(timestamp); | ||
5665 | pinstance->timestamp_data->timestamp[1] = (__u8)((timestamp) >> 8); | ||
5666 | pinstance->timestamp_data->timestamp[2] = (__u8)((timestamp) >> 16); | ||
5667 | pinstance->timestamp_data->timestamp[3] = (__u8)((timestamp) >> 24); | ||
5668 | pinstance->timestamp_data->timestamp[4] = (__u8)((timestamp) >> 32); | ||
5669 | pinstance->timestamp_data->timestamp[5] = (__u8)((timestamp) >> 40); | ||
5670 | |||
5671 | pmcraid_reinit_cmdblk(cmd); | ||
5672 | ioarcb->request_type = REQ_TYPE_SCSI; | ||
5673 | ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); | ||
5674 | ioarcb->cdb[0] = PMCRAID_SCSI_SET_TIMESTAMP; | ||
5675 | ioarcb->cdb[1] = PMCRAID_SCSI_SERVICE_ACTION; | ||
5676 | memcpy(&(ioarcb->cdb[6]), &time_stamp_len, sizeof(time_stamp_len)); | ||
5677 | |||
5678 | ioarcb->ioadl_bus_addr = cpu_to_le64((cmd->ioa_cb_bus_addr) + | ||
5679 | offsetof(struct pmcraid_ioarcb, | ||
5680 | add_data.u.ioadl[0])); | ||
5681 | ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc)); | ||
5682 | ioarcb->ioarcb_bus_addr &= ~(0x1FULL); | ||
5683 | |||
5684 | ioarcb->request_flags0 |= NO_LINK_DESCS; | ||
5685 | ioarcb->request_flags0 |= TRANSFER_DIR_WRITE; | ||
5686 | ioarcb->data_transfer_length = | ||
5687 | cpu_to_le32(sizeof(struct pmcraid_timestamp_data)); | ||
5688 | ioadl = &(ioarcb->add_data.u.ioadl[0]); | ||
5689 | ioadl->flags = IOADL_FLAGS_LAST_DESC; | ||
5690 | ioadl->address = cpu_to_le64(pinstance->timestamp_data_baddr); | ||
5691 | ioadl->data_len = cpu_to_le32(sizeof(struct pmcraid_timestamp_data)); | ||
5692 | |||
5693 | if (!pinstance->timestamp_error) { | ||
5694 | pinstance->timestamp_error = 0; | ||
5695 | pmcraid_send_cmd(cmd, pmcraid_set_supported_devs, | ||
5696 | PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler); | ||
5697 | } else { | ||
5698 | pmcraid_send_cmd(cmd, pmcraid_return_cmd, | ||
5699 | PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler); | ||
5700 | return; | ||
5701 | } | ||
5702 | } | ||
5703 | |||
5704 | |||
5705 | /** | ||
5612 | * pmcraid_init_res_table - Initialize the resource table | 5706 | * pmcraid_init_res_table - Initialize the resource table |
5613 | * @cmd: pointer to pmcraid command struct | 5707 | * @cmd: pointer to pmcraid command struct |
5614 | * | 5708 | * |
@@ -5719,7 +5813,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
5719 | 5813 | ||
5720 | /* release the resource list lock */ | 5814 | /* release the resource list lock */ |
5721 | spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags); | 5815 | spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags); |
5722 | pmcraid_set_supported_devs(cmd); | 5816 | pmcraid_set_timestamp(cmd); |
5723 | } | 5817 | } |
5724 | 5818 | ||
5725 | /** | 5819 | /** |
@@ -6053,10 +6147,10 @@ out_init: | |||
6053 | static void __exit pmcraid_exit(void) | 6147 | static void __exit pmcraid_exit(void) |
6054 | { | 6148 | { |
6055 | pmcraid_netlink_release(); | 6149 | pmcraid_netlink_release(); |
6056 | class_destroy(pmcraid_class); | ||
6057 | unregister_chrdev_region(MKDEV(pmcraid_major, 0), | 6150 | unregister_chrdev_region(MKDEV(pmcraid_major, 0), |
6058 | PMCRAID_MAX_ADAPTERS); | 6151 | PMCRAID_MAX_ADAPTERS); |
6059 | pci_unregister_driver(&pmcraid_driver); | 6152 | pci_unregister_driver(&pmcraid_driver); |
6153 | class_destroy(pmcraid_class); | ||
6060 | } | 6154 | } |
6061 | 6155 | ||
6062 | module_init(pmcraid_init); | 6156 | module_init(pmcraid_init); |