[SCSI] pmcraid: add support for set timestamp command and other fixes

The following are the fixes in this patch:

1. Added support of set timestamp command in the driver
2. Pass all status code to mgmt application. Earlier we were passing
only failed ones.
3. Call class_destroy after unregister_chrdev and pci_unregister_driver

Signed-off-by: Anil Ravindranath <anil_ravindranath@pmc-sierra.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>

authored by Anil Ravindranath and committed by James Bottomley 592488a3 df30e505

+129 -22
+110 -19
drivers/scsi/pmcraid.c
··· 1594 1594 cfg_entry = &ccn_hcam->cfg_entry; 1595 1595 fw_version = be16_to_cpu(pinstance->inq_data->fw_version); 1596 1596 1597 - pmcraid_info 1598 - ("CCN(%x): %x type: %x lost: %x flags: %x res: %x:%x:%x:%x\n", 1597 + pmcraid_info("CCN(%x): %x timestamp: %llx type: %x lost: %x flags: %x \ 1598 + res: %x:%x:%x:%x\n", 1599 1599 pinstance->ccn.hcam->ilid, 1600 1600 pinstance->ccn.hcam->op_code, 1601 + ((pinstance->ccn.hcam->timestamp1) | 1602 + ((pinstance->ccn.hcam->timestamp2 & 0xffffffffLL) << 32)), 1601 1603 pinstance->ccn.hcam->notification_type, 1602 1604 pinstance->ccn.hcam->notification_lost, 1603 1605 pinstance->ccn.hcam->flags, ··· 1852 1850 * none 1853 1851 */ 1854 1852 static void pmcraid_initiate_reset(struct pmcraid_instance *); 1853 + static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd); 1855 1854 1856 1855 static void pmcraid_process_ldn(struct pmcraid_cmd *cmd) 1857 1856 { ··· 1883 1880 spin_unlock_irqrestore(pinstance->host->host_lock, 1884 1881 lock_flags); 1885 1882 return; 1883 + } 1884 + if (fd_ioasc == PMCRAID_IOASC_TIME_STAMP_OUT_OF_SYNC) { 1885 + pinstance->timestamp_error = 1; 1886 + pmcraid_set_timestamp(cmd); 1886 1887 } 1887 1888 } else { 1888 1889 dev_info(&pinstance->pdev->dev, ··· 3370 3363 sg_size = buflen; 3371 3364 3372 3365 for (i = 0; i < num_elem; i++) { 3373 - page = alloc_pages(GFP_KERNEL|GFP_DMA, order); 3366 + page = alloc_pages(GFP_KERNEL|GFP_DMA|__GFP_ZERO, order); 3374 3367 if (!page) { 3375 3368 for (j = i - 1; j >= 0; j--) 3376 3369 __free_pages(sg_page(&scatterlist[j]), order); ··· 3746 3739 unsigned long request_buffer; 3747 3740 unsigned long request_offset; 3748 3741 unsigned long lock_flags; 3742 + void *ioasa; 3749 3743 u32 ioasc; 3750 3744 int request_size; 3751 3745 int buffer_size; ··· 3788 3780 rc = __copy_from_user(buffer, 3789 3781 (struct pmcraid_passthrough_ioctl_buffer *) arg, 3790 3782 sizeof(struct pmcraid_passthrough_ioctl_buffer)); 3783 + 3784 + ioasa = 3785 + (void *)(arg + 3786 + offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); 3787 + 3791 3788 if (rc) { 3792 3789 pmcraid_err("ioctl: can't copy passthrough buffer\n"); 3793 3790 rc = -EFAULT; ··· 3960 3947 } 3961 3948 3962 3949 out_handle_response: 3963 - /* If the command failed for any reason, copy entire IOASA buffer and 3964 - * return IOCTL success. If copying IOASA to user-buffer fails, return 3950 + /* copy entire IOASA buffer and return IOCTL success. 3951 + * If copying IOASA to user-buffer fails, return 3965 3952 * EFAULT 3966 3953 */ 3967 - if (PMCRAID_IOASC_SENSE_KEY(le32_to_cpu(cmd->ioa_cb->ioasa.ioasc))) { 3968 - void *ioasa = 3969 - (void *)(arg + 3970 - offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); 3971 - 3972 - pmcraid_info("command failed with %x\n", 3973 - le32_to_cpu(cmd->ioa_cb->ioasa.ioasc)); 3974 - if (copy_to_user(ioasa, &cmd->ioa_cb->ioasa, 3975 - sizeof(struct pmcraid_ioasa))) { 3976 - pmcraid_err("failed to copy ioasa buffer to user\n"); 3977 - rc = -EFAULT; 3978 - } 3954 + if (copy_to_user(ioasa, &cmd->ioa_cb->ioasa, 3955 + sizeof(struct pmcraid_ioasa))) { 3956 + pmcraid_err("failed to copy ioasa buffer to user\n"); 3957 + rc = -EFAULT; 3979 3958 } 3980 3959 3981 3960 /* If the data transfer was from device, copy the data onto user ··· 5152 5147 pinstance->inq_data = NULL; 5153 5148 pinstance->inq_data_baddr = 0; 5154 5149 } 5150 + 5151 + if (pinstance->timestamp_data != NULL) { 5152 + pci_free_consistent(pinstance->pdev, 5153 + sizeof(struct pmcraid_timestamp_data), 5154 + pinstance->timestamp_data, 5155 + pinstance->timestamp_data_baddr); 5156 + 5157 + pinstance->timestamp_data = NULL; 5158 + pinstance->timestamp_data_baddr = 0; 5159 + } 5155 5160 } 5156 5161 5157 5162 /** ··· 5219 5204 pmcraid_release_buffers(pinstance); 5220 5205 return -ENOMEM; 5221 5206 } 5207 + 5208 + /* allocate DMAable memory for set timestamp data buffer */ 5209 + pinstance->timestamp_data = pci_alloc_consistent( 5210 + pinstance->pdev, 5211 + sizeof(struct pmcraid_timestamp_data), 5212 + &pinstance->timestamp_data_baddr); 5213 + 5214 + if (pinstance->timestamp_data == NULL) { 5215 + pmcraid_err("couldn't allocate DMA memory for \ 5216 + set time_stamp \n"); 5217 + pmcraid_release_buffers(pinstance); 5218 + return -ENOMEM; 5219 + } 5220 + 5222 5221 5223 5222 /* Initialize all the command blocks and add them to free pool. No 5224 5223 * need to lock (free_pool_lock) as this is done in initialization ··· 5639 5610 } 5640 5611 5641 5612 /** 5613 + * pmcraid_set_timestamp - set the timestamp to IOAFP 5614 + * 5615 + * @cmd: pointer to pmcraid_cmd structure 5616 + * 5617 + * Return Value 5618 + * 0 for success or non-zero for failure cases 5619 + */ 5620 + static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd) 5621 + { 5622 + struct pmcraid_instance *pinstance = cmd->drv_inst; 5623 + struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; 5624 + __be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN); 5625 + struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; 5626 + 5627 + struct timeval tv; 5628 + __le64 timestamp; 5629 + 5630 + do_gettimeofday(&tv); 5631 + timestamp = tv.tv_sec * 1000; 5632 + 5633 + pinstance->timestamp_data->timestamp[0] = (__u8)(timestamp); 5634 + pinstance->timestamp_data->timestamp[1] = (__u8)((timestamp) >> 8); 5635 + pinstance->timestamp_data->timestamp[2] = (__u8)((timestamp) >> 16); 5636 + pinstance->timestamp_data->timestamp[3] = (__u8)((timestamp) >> 24); 5637 + pinstance->timestamp_data->timestamp[4] = (__u8)((timestamp) >> 32); 5638 + pinstance->timestamp_data->timestamp[5] = (__u8)((timestamp) >> 40); 5639 + 5640 + pmcraid_reinit_cmdblk(cmd); 5641 + ioarcb->request_type = REQ_TYPE_SCSI; 5642 + ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); 5643 + ioarcb->cdb[0] = PMCRAID_SCSI_SET_TIMESTAMP; 5644 + ioarcb->cdb[1] = PMCRAID_SCSI_SERVICE_ACTION; 5645 + memcpy(&(ioarcb->cdb[6]), &time_stamp_len, sizeof(time_stamp_len)); 5646 + 5647 + ioarcb->ioadl_bus_addr = cpu_to_le64((cmd->ioa_cb_bus_addr) + 5648 + offsetof(struct pmcraid_ioarcb, 5649 + add_data.u.ioadl[0])); 5650 + ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc)); 5651 + ioarcb->ioarcb_bus_addr &= ~(0x1FULL); 5652 + 5653 + ioarcb->request_flags0 |= NO_LINK_DESCS; 5654 + ioarcb->request_flags0 |= TRANSFER_DIR_WRITE; 5655 + ioarcb->data_transfer_length = 5656 + cpu_to_le32(sizeof(struct pmcraid_timestamp_data)); 5657 + ioadl = &(ioarcb->add_data.u.ioadl[0]); 5658 + ioadl->flags = IOADL_FLAGS_LAST_DESC; 5659 + ioadl->address = cpu_to_le64(pinstance->timestamp_data_baddr); 5660 + ioadl->data_len = cpu_to_le32(sizeof(struct pmcraid_timestamp_data)); 5661 + 5662 + if (!pinstance->timestamp_error) { 5663 + pinstance->timestamp_error = 0; 5664 + pmcraid_send_cmd(cmd, pmcraid_set_supported_devs, 5665 + PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler); 5666 + } else { 5667 + pmcraid_send_cmd(cmd, pmcraid_return_cmd, 5668 + PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler); 5669 + return; 5670 + } 5671 + } 5672 + 5673 + 5674 + /** 5642 5675 * pmcraid_init_res_table - Initialize the resource table 5643 5676 * @cmd: pointer to pmcraid command struct 5644 5677 * ··· 5811 5720 5812 5721 /* release the resource list lock */ 5813 5722 spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags); 5814 - pmcraid_set_supported_devs(cmd); 5723 + pmcraid_set_timestamp(cmd); 5815 5724 } 5816 5725 5817 5726 /** ··· 6145 6054 static void __exit pmcraid_exit(void) 6146 6055 { 6147 6056 pmcraid_netlink_release(); 6148 - class_destroy(pmcraid_class); 6149 6057 unregister_chrdev_region(MKDEV(pmcraid_major, 0), 6150 6058 PMCRAID_MAX_ADAPTERS); 6151 6059 pci_unregister_driver(&pmcraid_driver); 6060 + class_destroy(pmcraid_class); 6152 6061 } 6153 6062 6154 6063 module_init(pmcraid_init);
+19 -3
drivers/scsi/pmcraid.h
··· 42 42 */ 43 43 #define PMCRAID_DRIVER_NAME "PMC MaxRAID" 44 44 #define PMCRAID_DEVFILE "pmcsas" 45 - #define PMCRAID_DRIVER_VERSION "2.0.2" 45 + #define PMCRAID_DRIVER_VERSION "2.0.3" 46 46 #define PMCRAID_DRIVER_DATE __DATE__ 47 47 48 48 #define PMCRAID_FW_VERSION_1 0x002 ··· 184 184 #define PMCRAID_IOASC_IR_INVALID_RESOURCE_HANDLE 0x05250000 185 185 #define PMCRAID_IOASC_AC_TERMINATED_BY_HOST 0x0B5A0000 186 186 #define PMCRAID_IOASC_UA_BUS_WAS_RESET 0x06290000 187 + #define PMCRAID_IOASC_TIME_STAMP_OUT_OF_SYNC 0x06908B00 187 188 #define PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER 0x06298000 188 189 189 190 /* Driver defined IOASCs */ ··· 562 561 __u8 reserved3[16]; 563 562 }; 564 563 564 + #define PMCRAID_TIMESTAMP_LEN 12 565 + #define PMCRAID_REQ_TM_STR_LEN 6 566 + #define PMCRAID_SCSI_SET_TIMESTAMP 0xA4 567 + #define PMCRAID_SCSI_SERVICE_ACTION 0x0F 568 + 569 + struct pmcraid_timestamp_data { 570 + __u8 reserved1[4]; 571 + __u8 timestamp[PMCRAID_REQ_TM_STR_LEN]; /* current time value */ 572 + __u8 reserved2[2]; 573 + }; 574 + 565 575 /* pmcraid_cmd - LLD representation of SCSI command */ 566 576 struct pmcraid_cmd { 567 577 ··· 716 704 struct pmcraid_inquiry_data *inq_data; 717 705 dma_addr_t inq_data_baddr; 718 706 707 + struct pmcraid_timestamp_data *timestamp_data; 708 + dma_addr_t timestamp_data_baddr; 709 + 719 710 /* size of configuration table entry, varies based on the firmware */ 720 711 u32 config_table_entry_size; 721 712 ··· 805 790 #define SHUTDOWN_NONE 0x0 806 791 #define SHUTDOWN_NORMAL 0x1 807 792 #define SHUTDOWN_ABBREV 0x2 793 + u32 timestamp_error:1; /* indicate set timestamp for out of sync */ 808 794 809 795 }; 810 796 ··· 1071 1055 #define PMCRAID_PASSTHROUGH_IOCTL 'F' 1072 1056 1073 1057 #define DRV_IOCTL(n, size) \ 1074 - _IOC(_IOC_READ|_IOC_WRITE, PMCRAID_DRIVER_IOCTL, (n), (size)) 1058 + _IOC(_IOC_READ|_IOC_WRITE, PMCRAID_DRIVER_IOCTL, (n), (size)) 1075 1059 1076 1060 #define FMW_IOCTL(n, size) \ 1077 - _IOC(_IOC_READ|_IOC_WRITE, PMCRAID_PASSTHROUGH_IOCTL, (n), (size)) 1061 + _IOC(_IOC_READ|_IOC_WRITE, PMCRAID_PASSTHROUGH_IOCTL, (n), (size)) 1078 1062 1079 1063 /* 1080 1064 * _ARGSIZE: macro that gives size of the argument type passed to an IOCTL cmd.