Commit 592488a3 authored by Anil Ravindranath's avatar Anil Ravindranath Committed by James Bottomley

[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: default avatarAnil Ravindranath <anil_ravindranath@pmc-sierra.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent df30e505
...@@ -1594,10 +1594,12 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) ...@@ -1594,10 +1594,12 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
cfg_entry = &ccn_hcam->cfg_entry; cfg_entry = &ccn_hcam->cfg_entry;
fw_version = be16_to_cpu(pinstance->inq_data->fw_version); fw_version = be16_to_cpu(pinstance->inq_data->fw_version);
pmcraid_info pmcraid_info("CCN(%x): %x timestamp: %llx type: %x lost: %x flags: %x \
("CCN(%x): %x type: %x lost: %x flags: %x res: %x:%x:%x:%x\n", res: %x:%x:%x:%x\n",
pinstance->ccn.hcam->ilid, pinstance->ccn.hcam->ilid,
pinstance->ccn.hcam->op_code, pinstance->ccn.hcam->op_code,
((pinstance->ccn.hcam->timestamp1) |
((pinstance->ccn.hcam->timestamp2 & 0xffffffffLL) << 32)),
pinstance->ccn.hcam->notification_type, pinstance->ccn.hcam->notification_type,
pinstance->ccn.hcam->notification_lost, pinstance->ccn.hcam->notification_lost,
pinstance->ccn.hcam->flags, pinstance->ccn.hcam->flags,
...@@ -1850,6 +1852,7 @@ static void pmcraid_process_ccn(struct pmcraid_cmd *cmd) ...@@ -1850,6 +1852,7 @@ static void pmcraid_process_ccn(struct pmcraid_cmd *cmd)
* none * none
*/ */
static void pmcraid_initiate_reset(struct pmcraid_instance *); static void pmcraid_initiate_reset(struct pmcraid_instance *);
static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd);
static void pmcraid_process_ldn(struct pmcraid_cmd *cmd) static void pmcraid_process_ldn(struct pmcraid_cmd *cmd)
{ {
...@@ -1881,6 +1884,10 @@ static void pmcraid_process_ldn(struct pmcraid_cmd *cmd) ...@@ -1881,6 +1884,10 @@ static void pmcraid_process_ldn(struct pmcraid_cmd *cmd)
lock_flags); lock_flags);
return; return;
} }
if (fd_ioasc == PMCRAID_IOASC_TIME_STAMP_OUT_OF_SYNC) {
pinstance->timestamp_error = 1;
pmcraid_set_timestamp(cmd);
}
} else { } else {
dev_info(&pinstance->pdev->dev, dev_info(&pinstance->pdev->dev,
"Host RCB(LDN) failed with IOASC: 0x%08X\n", ioasc); "Host RCB(LDN) failed with IOASC: 0x%08X\n", ioasc);
...@@ -3363,7 +3370,7 @@ static struct pmcraid_sglist *pmcraid_alloc_sglist(int buflen) ...@@ -3363,7 +3370,7 @@ static struct pmcraid_sglist *pmcraid_alloc_sglist(int buflen)
sg_size = buflen; sg_size = buflen;
for (i = 0; i < num_elem; i++) { for (i = 0; i < num_elem; i++) {
page = alloc_pages(GFP_KERNEL|GFP_DMA, order); page = alloc_pages(GFP_KERNEL|GFP_DMA|__GFP_ZERO, order);
if (!page) { if (!page) {
for (j = i - 1; j >= 0; j--) for (j = i - 1; j >= 0; j--)
__free_pages(sg_page(&scatterlist[j]), order); __free_pages(sg_page(&scatterlist[j]), order);
...@@ -3739,6 +3746,7 @@ static long pmcraid_ioctl_passthrough( ...@@ -3739,6 +3746,7 @@ static long pmcraid_ioctl_passthrough(
unsigned long request_buffer; unsigned long request_buffer;
unsigned long request_offset; unsigned long request_offset;
unsigned long lock_flags; unsigned long lock_flags;
void *ioasa;
u32 ioasc; u32 ioasc;
int request_size; int request_size;
int buffer_size; int buffer_size;
...@@ -3780,6 +3788,11 @@ static long pmcraid_ioctl_passthrough( ...@@ -3780,6 +3788,11 @@ static long pmcraid_ioctl_passthrough(
rc = __copy_from_user(buffer, rc = __copy_from_user(buffer,
(struct pmcraid_passthrough_ioctl_buffer *) arg, (struct pmcraid_passthrough_ioctl_buffer *) arg,
sizeof(struct pmcraid_passthrough_ioctl_buffer)); sizeof(struct pmcraid_passthrough_ioctl_buffer));
ioasa =
(void *)(arg +
offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa));
if (rc) { if (rc) {
pmcraid_err("ioctl: can't copy passthrough buffer\n"); pmcraid_err("ioctl: can't copy passthrough buffer\n");
rc = -EFAULT; rc = -EFAULT;
...@@ -3947,23 +3960,15 @@ static long pmcraid_ioctl_passthrough( ...@@ -3947,23 +3960,15 @@ static long pmcraid_ioctl_passthrough(
} }
out_handle_response: out_handle_response:
/* If the command failed for any reason, copy entire IOASA buffer and /* copy entire IOASA buffer and return IOCTL success.
* return IOCTL success. If copying IOASA to user-buffer fails, return * If copying IOASA to user-buffer fails, return
* EFAULT * EFAULT
*/ */
if (PMCRAID_IOASC_SENSE_KEY(le32_to_cpu(cmd->ioa_cb->ioasa.ioasc))) {
void *ioasa =
(void *)(arg +
offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa));
pmcraid_info("command failed with %x\n",
le32_to_cpu(cmd->ioa_cb->ioasa.ioasc));
if (copy_to_user(ioasa, &cmd->ioa_cb->ioasa, if (copy_to_user(ioasa, &cmd->ioa_cb->ioasa,
sizeof(struct pmcraid_ioasa))) { sizeof(struct pmcraid_ioasa))) {
pmcraid_err("failed to copy ioasa buffer to user\n"); pmcraid_err("failed to copy ioasa buffer to user\n");
rc = -EFAULT; rc = -EFAULT;
} }
}
/* If the data transfer was from device, copy the data onto user /* If the data transfer was from device, copy the data onto user
* buffers * buffers
...@@ -5147,6 +5152,16 @@ static void pmcraid_release_buffers(struct pmcraid_instance *pinstance) ...@@ -5147,6 +5152,16 @@ static void pmcraid_release_buffers(struct pmcraid_instance *pinstance)
pinstance->inq_data = NULL; pinstance->inq_data = NULL;
pinstance->inq_data_baddr = 0; pinstance->inq_data_baddr = 0;
} }
if (pinstance->timestamp_data != NULL) {
pci_free_consistent(pinstance->pdev,
sizeof(struct pmcraid_timestamp_data),
pinstance->timestamp_data,
pinstance->timestamp_data_baddr);
pinstance->timestamp_data = NULL;
pinstance->timestamp_data_baddr = 0;
}
} }
/** /**
...@@ -5205,6 +5220,20 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance) ...@@ -5205,6 +5220,20 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance)
return -ENOMEM; return -ENOMEM;
} }
/* allocate DMAable memory for set timestamp data buffer */
pinstance->timestamp_data = pci_alloc_consistent(
pinstance->pdev,
sizeof(struct pmcraid_timestamp_data),
&pinstance->timestamp_data_baddr);
if (pinstance->timestamp_data == NULL) {
pmcraid_err("couldn't allocate DMA memory for \
set time_stamp \n");
pmcraid_release_buffers(pinstance);
return -ENOMEM;
}
/* Initialize all the command blocks and add them to free pool. No /* Initialize all the command blocks and add them to free pool. No
* need to lock (free_pool_lock) as this is done in initialization * need to lock (free_pool_lock) as this is done in initialization
* itself * itself
...@@ -5609,6 +5638,68 @@ static void pmcraid_set_supported_devs(struct pmcraid_cmd *cmd) ...@@ -5609,6 +5638,68 @@ static void pmcraid_set_supported_devs(struct pmcraid_cmd *cmd)
return; return;
} }
/**
* pmcraid_set_timestamp - set the timestamp to IOAFP
*
* @cmd: pointer to pmcraid_cmd structure
*
* Return Value
* 0 for success or non-zero for failure cases
*/
static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd)
{
struct pmcraid_instance *pinstance = cmd->drv_inst;
struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb;
__be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN);
struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl;
struct timeval tv;
__le64 timestamp;
do_gettimeofday(&tv);
timestamp = tv.tv_sec * 1000;
pinstance->timestamp_data->timestamp[0] = (__u8)(timestamp);
pinstance->timestamp_data->timestamp[1] = (__u8)((timestamp) >> 8);
pinstance->timestamp_data->timestamp[2] = (__u8)((timestamp) >> 16);
pinstance->timestamp_data->timestamp[3] = (__u8)((timestamp) >> 24);
pinstance->timestamp_data->timestamp[4] = (__u8)((timestamp) >> 32);
pinstance->timestamp_data->timestamp[5] = (__u8)((timestamp) >> 40);
pmcraid_reinit_cmdblk(cmd);
ioarcb->request_type = REQ_TYPE_SCSI;
ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE);
ioarcb->cdb[0] = PMCRAID_SCSI_SET_TIMESTAMP;
ioarcb->cdb[1] = PMCRAID_SCSI_SERVICE_ACTION;
memcpy(&(ioarcb->cdb[6]), &time_stamp_len, sizeof(time_stamp_len));
ioarcb->ioadl_bus_addr = cpu_to_le64((cmd->ioa_cb_bus_addr) +
offsetof(struct pmcraid_ioarcb,
add_data.u.ioadl[0]));
ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc));
ioarcb->ioarcb_bus_addr &= ~(0x1FULL);
ioarcb->request_flags0 |= NO_LINK_DESCS;
ioarcb->request_flags0 |= TRANSFER_DIR_WRITE;
ioarcb->data_transfer_length =
cpu_to_le32(sizeof(struct pmcraid_timestamp_data));
ioadl = &(ioarcb->add_data.u.ioadl[0]);
ioadl->flags = IOADL_FLAGS_LAST_DESC;
ioadl->address = cpu_to_le64(pinstance->timestamp_data_baddr);
ioadl->data_len = cpu_to_le32(sizeof(struct pmcraid_timestamp_data));
if (!pinstance->timestamp_error) {
pinstance->timestamp_error = 0;
pmcraid_send_cmd(cmd, pmcraid_set_supported_devs,
PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler);
} else {
pmcraid_send_cmd(cmd, pmcraid_return_cmd,
PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler);
return;
}
}
/** /**
* pmcraid_init_res_table - Initialize the resource table * pmcraid_init_res_table - Initialize the resource table
* @cmd: pointer to pmcraid command struct * @cmd: pointer to pmcraid command struct
...@@ -5720,7 +5811,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) ...@@ -5720,7 +5811,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd)
/* release the resource list lock */ /* release the resource list lock */
spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags); spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags);
pmcraid_set_supported_devs(cmd); pmcraid_set_timestamp(cmd);
} }
/** /**
...@@ -6054,10 +6145,10 @@ static int __init pmcraid_init(void) ...@@ -6054,10 +6145,10 @@ static int __init pmcraid_init(void)
static void __exit pmcraid_exit(void) static void __exit pmcraid_exit(void)
{ {
pmcraid_netlink_release(); pmcraid_netlink_release();
class_destroy(pmcraid_class);
unregister_chrdev_region(MKDEV(pmcraid_major, 0), unregister_chrdev_region(MKDEV(pmcraid_major, 0),
PMCRAID_MAX_ADAPTERS); PMCRAID_MAX_ADAPTERS);
pci_unregister_driver(&pmcraid_driver); pci_unregister_driver(&pmcraid_driver);
class_destroy(pmcraid_class);
} }
module_init(pmcraid_init); module_init(pmcraid_init);
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
*/ */
#define PMCRAID_DRIVER_NAME "PMC MaxRAID" #define PMCRAID_DRIVER_NAME "PMC MaxRAID"
#define PMCRAID_DEVFILE "pmcsas" #define PMCRAID_DEVFILE "pmcsas"
#define PMCRAID_DRIVER_VERSION "2.0.2" #define PMCRAID_DRIVER_VERSION "2.0.3"
#define PMCRAID_DRIVER_DATE __DATE__ #define PMCRAID_DRIVER_DATE __DATE__
#define PMCRAID_FW_VERSION_1 0x002 #define PMCRAID_FW_VERSION_1 0x002
...@@ -184,6 +184,7 @@ ...@@ -184,6 +184,7 @@
#define PMCRAID_IOASC_IR_INVALID_RESOURCE_HANDLE 0x05250000 #define PMCRAID_IOASC_IR_INVALID_RESOURCE_HANDLE 0x05250000
#define PMCRAID_IOASC_AC_TERMINATED_BY_HOST 0x0B5A0000 #define PMCRAID_IOASC_AC_TERMINATED_BY_HOST 0x0B5A0000
#define PMCRAID_IOASC_UA_BUS_WAS_RESET 0x06290000 #define PMCRAID_IOASC_UA_BUS_WAS_RESET 0x06290000
#define PMCRAID_IOASC_TIME_STAMP_OUT_OF_SYNC 0x06908B00
#define PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER 0x06298000 #define PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER 0x06298000
/* Driver defined IOASCs */ /* Driver defined IOASCs */
...@@ -561,6 +562,17 @@ struct pmcraid_inquiry_data { ...@@ -561,6 +562,17 @@ struct pmcraid_inquiry_data {
__u8 reserved3[16]; __u8 reserved3[16];
}; };
#define PMCRAID_TIMESTAMP_LEN 12
#define PMCRAID_REQ_TM_STR_LEN 6
#define PMCRAID_SCSI_SET_TIMESTAMP 0xA4
#define PMCRAID_SCSI_SERVICE_ACTION 0x0F
struct pmcraid_timestamp_data {
__u8 reserved1[4];
__u8 timestamp[PMCRAID_REQ_TM_STR_LEN]; /* current time value */
__u8 reserved2[2];
};
/* pmcraid_cmd - LLD representation of SCSI command */ /* pmcraid_cmd - LLD representation of SCSI command */
struct pmcraid_cmd { struct pmcraid_cmd {
...@@ -704,6 +716,9 @@ struct pmcraid_instance { ...@@ -704,6 +716,9 @@ struct pmcraid_instance {
struct pmcraid_inquiry_data *inq_data; struct pmcraid_inquiry_data *inq_data;
dma_addr_t inq_data_baddr; dma_addr_t inq_data_baddr;
struct pmcraid_timestamp_data *timestamp_data;
dma_addr_t timestamp_data_baddr;
/* size of configuration table entry, varies based on the firmware */ /* size of configuration table entry, varies based on the firmware */
u32 config_table_entry_size; u32 config_table_entry_size;
...@@ -790,6 +805,7 @@ struct pmcraid_instance { ...@@ -790,6 +805,7 @@ struct pmcraid_instance {
#define SHUTDOWN_NONE 0x0 #define SHUTDOWN_NONE 0x0
#define SHUTDOWN_NORMAL 0x1 #define SHUTDOWN_NORMAL 0x1
#define SHUTDOWN_ABBREV 0x2 #define SHUTDOWN_ABBREV 0x2
u32 timestamp_error:1; /* indicate set timestamp for out of sync */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment