Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+110 −19
Original line number Original line Diff line number Diff line
@@ -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)
 *   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)
					       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)
	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(
	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(
	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(
	}
	}


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)
		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)
		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)
	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)


	/* 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)
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);
+19 −3
Original line number Original line Diff line number Diff line
@@ -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 @@
#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 {
	__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 {
	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 {
#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 */


};
};