forked from mirrors/linux
		
	advansys: use shared host tag map for command lookup
Convert to use a shared host tag map for command lookup. This saves us having an internal structure and avoid the command pointer abuse. Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: James Bottomley <JBottomley@Odin.com>
This commit is contained in:
		
							parent
							
								
									eac0b0c76f
								
							
						
					
					
						commit
						9c17c62aed
					
				
					 1 changed files with 79 additions and 146 deletions
				
			
		| 
						 | 
					@ -315,7 +315,7 @@ typedef struct asc_scsiq_1 {
 | 
				
			||||||
} ASC_SCSIQ_1;
 | 
					} ASC_SCSIQ_1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct asc_scsiq_2 {
 | 
					typedef struct asc_scsiq_2 {
 | 
				
			||||||
	ASC_VADDR srb_ptr;
 | 
						u32 srb_tag;
 | 
				
			||||||
	uchar target_ix;
 | 
						uchar target_ix;
 | 
				
			||||||
	uchar flag;
 | 
						uchar flag;
 | 
				
			||||||
	uchar cdb_len;
 | 
						uchar cdb_len;
 | 
				
			||||||
| 
						 | 
					@ -592,8 +592,6 @@ typedef struct asc_dvc_var {
 | 
				
			||||||
	uchar min_sdtr_index;
 | 
						uchar min_sdtr_index;
 | 
				
			||||||
	uchar max_sdtr_index;
 | 
						uchar max_sdtr_index;
 | 
				
			||||||
	struct asc_board *drv_ptr;
 | 
						struct asc_board *drv_ptr;
 | 
				
			||||||
	int ptr_map_count;
 | 
					 | 
				
			||||||
	void **ptr_map;
 | 
					 | 
				
			||||||
	ASC_DCNT uc_break;
 | 
						ASC_DCNT uc_break;
 | 
				
			||||||
} ASC_DVC_VAR;
 | 
					} ASC_DVC_VAR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1866,7 +1864,7 @@ typedef struct adv_scsi_req_q {
 | 
				
			||||||
	 * End of microcode structure - 60 bytes. The rest of the structure
 | 
						 * End of microcode structure - 60 bytes. The rest of the structure
 | 
				
			||||||
	 * is used by the Adv Library and ignored by the microcode.
 | 
						 * is used by the Adv Library and ignored by the microcode.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	ADV_VADDR srb_ptr;
 | 
						u32 srb_tag;
 | 
				
			||||||
	ADV_SG_BLOCK *sg_list_ptr;	/* SG list virtual address. */
 | 
						ADV_SG_BLOCK *sg_list_ptr;	/* SG list virtual address. */
 | 
				
			||||||
	char *vdata_addr;	/* Data buffer virtual address. */
 | 
						char *vdata_addr;	/* Data buffer virtual address. */
 | 
				
			||||||
	uchar a_flag;
 | 
						uchar a_flag;
 | 
				
			||||||
| 
						 | 
					@ -1877,9 +1875,9 @@ typedef struct adv_scsi_req_q {
 | 
				
			||||||
 * The following two structures are used to process Wide Board requests.
 | 
					 * The following two structures are used to process Wide Board requests.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
 | 
					 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
 | 
				
			||||||
 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
 | 
					 * and microcode with the ADV_SCSI_REQ_Q field 'srb_tag' set to the
 | 
				
			||||||
 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
 | 
					 * SCSI request tag. The adv_req_t structure 'cmndp' field in turn points
 | 
				
			||||||
 * Mid-Level SCSI request structure.
 | 
					 * to the Mid-Level SCSI request structure.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
 | 
					 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
 | 
				
			||||||
 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
 | 
					 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
 | 
				
			||||||
| 
						 | 
					@ -1942,7 +1940,6 @@ typedef struct adv_dvc_var {
 | 
				
			||||||
	ADV_CARR_T *icq_sp;	/* Initiator command queue stopper pointer. */
 | 
						ADV_CARR_T *icq_sp;	/* Initiator command queue stopper pointer. */
 | 
				
			||||||
	ADV_CARR_T *irq_sp;	/* Initiator response queue stopper pointer. */
 | 
						ADV_CARR_T *irq_sp;	/* Initiator response queue stopper pointer. */
 | 
				
			||||||
	ushort carr_pending_cnt;	/* Count of pending carriers. */
 | 
						ushort carr_pending_cnt;	/* Count of pending carriers. */
 | 
				
			||||||
	struct adv_req *orig_reqp;	/* adv_req_t memory block. */
 | 
					 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Note: The following fields will not be used after initialization. The
 | 
						 * Note: The following fields will not be used after initialization. The
 | 
				
			||||||
	 * driver may discard the buffer after initialization is done.
 | 
						 * driver may discard the buffer after initialization is done.
 | 
				
			||||||
| 
						 | 
					@ -2068,8 +2065,8 @@ do { \
 | 
				
			||||||
    AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
 | 
					    AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
 | 
					 * Abort an SRB in the chip's RISC Memory. The 'srb_tag' argument must
 | 
				
			||||||
 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
 | 
					 * match the ASC_SCSI_REQ_Q 'srb_tag' field.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * If the request has not yet been sent to the device it will simply be
 | 
					 * If the request has not yet been sent to the device it will simply be
 | 
				
			||||||
 * aborted from RISC memory. If the request is disconnected it will be
 | 
					 * aborted from RISC memory. If the request is disconnected it will be
 | 
				
			||||||
| 
						 | 
					@ -2079,9 +2076,9 @@ do { \
 | 
				
			||||||
 *      ADV_TRUE(1) - Queue was successfully aborted.
 | 
					 *      ADV_TRUE(1) - Queue was successfully aborted.
 | 
				
			||||||
 *      ADV_FALSE(0) - Queue was not found on the active queue list.
 | 
					 *      ADV_FALSE(0) - Queue was not found on the active queue list.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define AdvAbortQueue(asc_dvc, scsiq) \
 | 
					#define AdvAbortQueue(asc_dvc, srb_tag) \
 | 
				
			||||||
     AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
 | 
					     AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
 | 
				
			||||||
                       (ADV_DCNT) (scsiq))
 | 
							    (ADV_DCNT) (srb_tag))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Send a Bus Device Reset Message to the specified target ID.
 | 
					 * Send a Bus Device Reset Message to the specified target ID.
 | 
				
			||||||
| 
						 | 
					@ -2345,6 +2342,7 @@ struct asc_stats {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct asc_board {
 | 
					struct asc_board {
 | 
				
			||||||
	struct device *dev;
 | 
						struct device *dev;
 | 
				
			||||||
 | 
						struct Scsi_Host *shost;
 | 
				
			||||||
	uint flags;		/* Board flags */
 | 
						uint flags;		/* Board flags */
 | 
				
			||||||
	unsigned int irq;
 | 
						unsigned int irq;
 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
| 
						 | 
					@ -2599,8 +2597,8 @@ static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
 | 
				
			||||||
	printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
 | 
						printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printk
 | 
						printk
 | 
				
			||||||
	    (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
 | 
						    (" target_ix 0x%x, target_lun %u, srb_tag 0x%x, tag_code 0x%x,\n",
 | 
				
			||||||
	     q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
 | 
						     q->q2.target_ix, q->q1.target_lun, q->q2.srb_tag,
 | 
				
			||||||
	     q->q2.tag_code);
 | 
						     q->q2.tag_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printk
 | 
						printk
 | 
				
			||||||
| 
						 | 
					@ -2633,8 +2631,8 @@ static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
 | 
				
			||||||
static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
 | 
					static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
 | 
						printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
 | 
				
			||||||
	printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
 | 
						printk(" srb_tag 0x%x, target_ix %u, cdb_len %u, tag_code %u,\n",
 | 
				
			||||||
	       (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
 | 
						       q->d2.srb_tag, q->d2.target_ix, q->d2.cdb_len,
 | 
				
			||||||
	       q->d2.tag_code);
 | 
						       q->d2.tag_code);
 | 
				
			||||||
	printk
 | 
						printk
 | 
				
			||||||
	    (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
 | 
						    (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
 | 
				
			||||||
| 
						 | 
					@ -2676,8 +2674,8 @@ static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
 | 
						printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printk("  target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
 | 
						printk("  target_id %u, target_lun %u, srb_tag 0x%x, a_flag 0x%x\n",
 | 
				
			||||||
	       q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
 | 
						       q->target_id, q->target_lun, q->srb_tag, q->a_flag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printk("  cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
 | 
						printk("  cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
 | 
				
			||||||
	       q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
 | 
						       q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
 | 
				
			||||||
| 
						 | 
					@ -2720,59 +2718,6 @@ static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* ADVANSYS_DEBUG */
 | 
					#endif /* ADVANSYS_DEBUG */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * The advansys chip/microcode contains a 32-bit identifier for each command
 | 
					 | 
				
			||||||
 * known as the 'srb'.  I don't know what it stands for.  The driver used
 | 
					 | 
				
			||||||
 * to encode the scsi_cmnd pointer by calling virt_to_bus and retrieve it
 | 
					 | 
				
			||||||
 * with bus_to_virt.  Now the driver keeps a per-host map of integers to
 | 
					 | 
				
			||||||
 * pointers.  It auto-expands when full, unless it can't allocate memory.
 | 
					 | 
				
			||||||
 * Note that an srb of 0 is treated specially by the chip/firmware, hence
 | 
					 | 
				
			||||||
 * the return of i+1 in this routine, and the corresponding subtraction in
 | 
					 | 
				
			||||||
 * the inverse routine.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define BAD_SRB 0
 | 
					 | 
				
			||||||
static u32 advansys_ptr_to_srb(struct asc_dvc_var *asc_dvc, void *ptr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
	void **new_ptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < asc_dvc->ptr_map_count; i++) {
 | 
					 | 
				
			||||||
		if (!asc_dvc->ptr_map[i])
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (asc_dvc->ptr_map_count == 0)
 | 
					 | 
				
			||||||
		asc_dvc->ptr_map_count = 1;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		asc_dvc->ptr_map_count *= 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	new_ptr = krealloc(asc_dvc->ptr_map,
 | 
					 | 
				
			||||||
			asc_dvc->ptr_map_count * sizeof(void *), GFP_ATOMIC);
 | 
					 | 
				
			||||||
	if (!new_ptr)
 | 
					 | 
				
			||||||
		return BAD_SRB;
 | 
					 | 
				
			||||||
	asc_dvc->ptr_map = new_ptr;
 | 
					 | 
				
			||||||
 out:
 | 
					 | 
				
			||||||
	ASC_DBG(3, "Putting ptr %p into array offset %d\n", ptr, i);
 | 
					 | 
				
			||||||
	asc_dvc->ptr_map[i] = ptr;
 | 
					 | 
				
			||||||
	return i + 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void * advansys_srb_to_ptr(struct asc_dvc_var *asc_dvc, u32 srb)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	void *ptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	srb--;
 | 
					 | 
				
			||||||
	if (srb >= asc_dvc->ptr_map_count) {
 | 
					 | 
				
			||||||
		printk("advansys: bad SRB %u, max %u\n", srb,
 | 
					 | 
				
			||||||
							asc_dvc->ptr_map_count);
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ptr = asc_dvc->ptr_map[srb];
 | 
					 | 
				
			||||||
	asc_dvc->ptr_map[srb] = NULL;
 | 
					 | 
				
			||||||
	ASC_DBG(3, "Returning ptr %p from array offset %d\n", ptr, srb);
 | 
					 | 
				
			||||||
	return ptr;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * advansys_info()
 | 
					 * advansys_info()
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -6133,15 +6078,15 @@ static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
 | 
					static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct asc_board *boardp;
 | 
						struct asc_board *boardp = adv_dvc_varp->drv_ptr;
 | 
				
			||||||
 | 
						u32 srb_tag;
 | 
				
			||||||
	adv_req_t *reqp;
 | 
						adv_req_t *reqp;
 | 
				
			||||||
	adv_sgblk_t *sgblkp;
 | 
						adv_sgblk_t *sgblkp;
 | 
				
			||||||
	struct scsi_cmnd *scp;
 | 
						struct scsi_cmnd *scp;
 | 
				
			||||||
	struct Scsi_Host *shost;
 | 
					 | 
				
			||||||
	ADV_DCNT resid_cnt;
 | 
						ADV_DCNT resid_cnt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASC_DBG(1, "adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
 | 
						ASC_DBG(1, "adv_dvc_varp 0x%p, scsiqp 0x%p\n",
 | 
				
			||||||
		 (ulong)adv_dvc_varp, (ulong)scsiqp);
 | 
							adv_dvc_varp, scsiqp);
 | 
				
			||||||
	ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
 | 
						ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -6149,22 +6094,9 @@ static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
 | 
				
			||||||
	 * completed. The adv_req_t structure actually contains the
 | 
						 * completed. The adv_req_t structure actually contains the
 | 
				
			||||||
	 * completed ADV_SCSI_REQ_Q structure.
 | 
						 * completed ADV_SCSI_REQ_Q structure.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
 | 
						srb_tag = le32_to_cpu(scsiqp->srb_tag);
 | 
				
			||||||
	ASC_DBG(1, "reqp 0x%lx\n", (ulong)reqp);
 | 
						scp = scsi_host_find_tag(boardp->shost, scsiqp->srb_tag);
 | 
				
			||||||
	if (reqp == NULL) {
 | 
					 | 
				
			||||||
		ASC_PRINT("adv_isr_callback: reqp is NULL\n");
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
 | 
					 | 
				
			||||||
	 * command that has been completed.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * Note: The adv_req_t request structure and adv_sgblk_t structure,
 | 
					 | 
				
			||||||
	 * if any, are dropped, because a board structure pointer can not be
 | 
					 | 
				
			||||||
	 * determined.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	scp = reqp->cmndp;
 | 
					 | 
				
			||||||
	ASC_DBG(1, "scp 0x%p\n", scp);
 | 
						ASC_DBG(1, "scp 0x%p\n", scp);
 | 
				
			||||||
	if (scp == NULL) {
 | 
						if (scp == NULL) {
 | 
				
			||||||
		ASC_PRINT
 | 
							ASC_PRINT
 | 
				
			||||||
| 
						 | 
					@ -6173,12 +6105,21 @@ static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
 | 
						ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	shost = scp->device->host;
 | 
						reqp = (adv_req_t *)scp->host_scribble;
 | 
				
			||||||
	ASC_STATS(shost, callback);
 | 
						ASC_DBG(1, "reqp 0x%lx\n", (ulong)reqp);
 | 
				
			||||||
	ASC_DBG(1, "shost 0x%p\n", shost);
 | 
						if (reqp == NULL) {
 | 
				
			||||||
 | 
							ASC_PRINT("adv_isr_callback: reqp is NULL\n");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Remove backreferences to avoid duplicate
 | 
				
			||||||
 | 
						 * command completions.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						scp->host_scribble = NULL;
 | 
				
			||||||
 | 
						reqp->cmndp = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	boardp = shost_priv(shost);
 | 
						ASC_STATS(boardp->shost, callback);
 | 
				
			||||||
	BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var);
 | 
						ASC_DBG(1, "shost 0x%p\n", boardp->shost);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * 'done_status' contains the command's ending status.
 | 
						 * 'done_status' contains the command's ending status.
 | 
				
			||||||
| 
						 | 
					@ -6276,13 +6217,6 @@ static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
 | 
				
			||||||
		boardp->adv_sgblkp = sgblkp;
 | 
							boardp->adv_sgblkp = sgblkp;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Free the adv_req_t structure used with the command by adding
 | 
					 | 
				
			||||||
	 * it back to the board free list.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	reqp->next_reqp = boardp->adv_reqp;
 | 
					 | 
				
			||||||
	boardp->adv_reqp = reqp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ASC_DBG(1, "done\n");
 | 
						ASC_DBG(1, "done\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7092,25 +7026,24 @@ _AscCopyLramScsiDoneQ(PortAddr iop_base,
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
 | 
					static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct asc_board *boardp;
 | 
						struct asc_board *boardp = asc_dvc_varp->drv_ptr;
 | 
				
			||||||
 | 
						u32 srb_tag;
 | 
				
			||||||
	struct scsi_cmnd *scp;
 | 
						struct scsi_cmnd *scp;
 | 
				
			||||||
	struct Scsi_Host *shost;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASC_DBG(1, "asc_dvc_varp 0x%p, qdonep 0x%p\n", asc_dvc_varp, qdonep);
 | 
						ASC_DBG(1, "asc_dvc_varp 0x%p, qdonep 0x%p\n", asc_dvc_varp, qdonep);
 | 
				
			||||||
	ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
 | 
						ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	scp = advansys_srb_to_ptr(asc_dvc_varp, qdonep->d2.srb_ptr);
 | 
						/*
 | 
				
			||||||
 | 
						 * Decrease the srb_tag by 1 to find the SCSI command
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						srb_tag = qdonep->d2.srb_tag - 1;
 | 
				
			||||||
 | 
						scp = scsi_host_find_tag(boardp->shost, srb_tag);
 | 
				
			||||||
	if (!scp)
 | 
						if (!scp)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
 | 
						ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	shost = scp->device->host;
 | 
						ASC_STATS(boardp->shost, callback);
 | 
				
			||||||
	ASC_STATS(shost, callback);
 | 
					 | 
				
			||||||
	ASC_DBG(1, "shost 0x%p\n", shost);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	boardp = shost_priv(shost);
 | 
					 | 
				
			||||||
	BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
 | 
						dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
 | 
				
			||||||
			 SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
 | 
								 SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
 | 
				
			||||||
| 
						 | 
					@ -7293,7 +7226,7 @@ static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
 | 
				
			||||||
			scsiq->d3.done_stat = QD_WITH_ERROR;
 | 
								scsiq->d3.done_stat = QD_WITH_ERROR;
 | 
				
			||||||
			goto FATAL_ERR_QDONE;
 | 
								goto FATAL_ERR_QDONE;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if ((scsiq->d2.srb_ptr == 0UL) ||
 | 
							if ((scsiq->d2.srb_tag == 0UL) ||
 | 
				
			||||||
		    ((scsiq->q_status & QS_ABORTED) != 0)) {
 | 
							    ((scsiq->q_status & QS_ABORTED) != 0)) {
 | 
				
			||||||
			return (0x11);
 | 
								return (0x11);
 | 
				
			||||||
		} else if (scsiq->q_status == QS_DONE) {
 | 
							} else if (scsiq->q_status == QS_DONE) {
 | 
				
			||||||
| 
						 | 
					@ -7861,17 +7794,16 @@ static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct asc_dvc_var *asc_dvc = &boardp->dvc_var.asc_dvc_var;
 | 
						struct asc_dvc_var *asc_dvc = &boardp->dvc_var.asc_dvc_var;
 | 
				
			||||||
	int use_sg;
 | 
						int use_sg;
 | 
				
			||||||
 | 
						u32 srb_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(asc_scsi_q, 0, sizeof(*asc_scsi_q));
 | 
						memset(asc_scsi_q, 0, sizeof(*asc_scsi_q));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
 | 
						 * Set the srb_tag to the command tag + 1, as
 | 
				
			||||||
 | 
						 * srb_tag '0' is used internally by the chip.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	asc_scsi_q->q2.srb_ptr = advansys_ptr_to_srb(asc_dvc, scp);
 | 
						srb_tag = scp->request->tag + 1;
 | 
				
			||||||
	if (asc_scsi_q->q2.srb_ptr == BAD_SRB) {
 | 
						asc_scsi_q->q2.srb_tag = srb_tag;
 | 
				
			||||||
		scp->result = HOST_BYTE(DID_SOFT_ERROR);
 | 
					 | 
				
			||||||
		return ASC_ERROR;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Build the ASC_SCSI_Q request.
 | 
						 * Build the ASC_SCSI_Q request.
 | 
				
			||||||
| 
						 | 
					@ -8083,6 +8015,7 @@ static int
 | 
				
			||||||
adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
 | 
					adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
 | 
				
			||||||
	      ADV_SCSI_REQ_Q **adv_scsiqpp)
 | 
						      ADV_SCSI_REQ_Q **adv_scsiqpp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						u32 srb_tag = scp->request->tag;
 | 
				
			||||||
	adv_req_t *reqp;
 | 
						adv_req_t *reqp;
 | 
				
			||||||
	ADV_SCSI_REQ_Q *scsiqp;
 | 
						ADV_SCSI_REQ_Q *scsiqp;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
| 
						 | 
					@ -8093,14 +8026,11 @@ adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
 | 
				
			||||||
	 * Allocate an adv_req_t structure from the board to execute
 | 
						 * Allocate an adv_req_t structure from the board to execute
 | 
				
			||||||
	 * the command.
 | 
						 * the command.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (boardp->adv_reqp == NULL) {
 | 
						reqp = &boardp->adv_reqp[srb_tag];
 | 
				
			||||||
 | 
						if (reqp->cmndp && reqp->cmndp != scp ) {
 | 
				
			||||||
		ASC_DBG(1, "no free adv_req_t\n");
 | 
							ASC_DBG(1, "no free adv_req_t\n");
 | 
				
			||||||
		ASC_STATS(scp->device->host, adv_build_noreq);
 | 
							ASC_STATS(scp->device->host, adv_build_noreq);
 | 
				
			||||||
		return ASC_BUSY;
 | 
							return ASC_BUSY;
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		reqp = boardp->adv_reqp;
 | 
					 | 
				
			||||||
		boardp->adv_reqp = reqp->next_reqp;
 | 
					 | 
				
			||||||
		reqp->next_reqp = NULL;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -8114,14 +8044,15 @@ adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
 | 
				
			||||||
	scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
 | 
						scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
 | 
						 * Set the srb_tag to the command tag.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	scsiqp->srb_ptr = ADV_VADDR_TO_U32(reqp);
 | 
						scsiqp->srb_tag = srb_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
 | 
						 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	reqp->cmndp = scp;
 | 
						reqp->cmndp = scp;
 | 
				
			||||||
 | 
						scp->host_scribble = (void *)reqp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Build the ADV_SCSI_REQ_Q request.
 | 
						 * Build the ADV_SCSI_REQ_Q request.
 | 
				
			||||||
| 
						 | 
					@ -8163,13 +8094,8 @@ adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
 | 
				
			||||||
				   scp->device->host->sg_tablesize);
 | 
									   scp->device->host->sg_tablesize);
 | 
				
			||||||
			scsi_dma_unmap(scp);
 | 
								scsi_dma_unmap(scp);
 | 
				
			||||||
			scp->result = HOST_BYTE(DID_ERROR);
 | 
								scp->result = HOST_BYTE(DID_ERROR);
 | 
				
			||||||
 | 
								reqp->cmndp = NULL;
 | 
				
			||||||
			/*
 | 
								scp->host_scribble = NULL;
 | 
				
			||||||
			 * Free the 'adv_req_t' structure by adding it back
 | 
					 | 
				
			||||||
			 * to the board free list.
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			reqp->next_reqp = boardp->adv_reqp;
 | 
					 | 
				
			||||||
			boardp->adv_reqp = reqp;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return ASC_ERROR;
 | 
								return ASC_ERROR;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -8178,12 +8104,10 @@ adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = adv_get_sglist(boardp, reqp, scp, use_sg);
 | 
							ret = adv_get_sglist(boardp, reqp, scp, use_sg);
 | 
				
			||||||
		if (ret != ADV_SUCCESS) {
 | 
							if (ret != ADV_SUCCESS) {
 | 
				
			||||||
			/*
 | 
								scsi_dma_unmap(scp);
 | 
				
			||||||
			 * Free the adv_req_t structure by adding it back to
 | 
								scp->result = HOST_BYTE(DID_ERROR);
 | 
				
			||||||
			 * the board free list.
 | 
								reqp->cmndp = NULL;
 | 
				
			||||||
			 */
 | 
								scp->host_scribble = NULL;
 | 
				
			||||||
			reqp->next_reqp = boardp->adv_reqp;
 | 
					 | 
				
			||||||
			boardp->adv_reqp = reqp;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -11244,6 +11168,7 @@ static struct scsi_host_template advansys_template = {
 | 
				
			||||||
	 * by enabling clustering, I/O throughput increases as well.
 | 
						 * by enabling clustering, I/O throughput increases as well.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	.use_clustering = ENABLE_CLUSTERING,
 | 
						.use_clustering = ENABLE_CLUSTERING,
 | 
				
			||||||
 | 
						.use_blk_tags = 1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int advansys_wide_init_chip(struct Scsi_Host *shost)
 | 
					static int advansys_wide_init_chip(struct Scsi_Host *shost)
 | 
				
			||||||
| 
						 | 
					@ -11272,7 +11197,7 @@ static int advansys_wide_init_chip(struct Scsi_Host *shost)
 | 
				
			||||||
	 * If the allocation fails decrement and try again.
 | 
						 * If the allocation fails decrement and try again.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	for (req_cnt = adv_dvc->max_host_qng; req_cnt > 0; req_cnt--) {
 | 
						for (req_cnt = adv_dvc->max_host_qng; req_cnt > 0; req_cnt--) {
 | 
				
			||||||
		reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
 | 
							reqp = kzalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ASC_DBG(1, "reqp 0x%p, req_cnt %d, bytes %lu\n", reqp, req_cnt,
 | 
							ASC_DBG(1, "reqp 0x%p, req_cnt %d, bytes %lu\n", reqp, req_cnt,
 | 
				
			||||||
			 (ulong)sizeof(adv_req_t) * req_cnt);
 | 
								 (ulong)sizeof(adv_req_t) * req_cnt);
 | 
				
			||||||
| 
						 | 
					@ -11284,7 +11209,7 @@ static int advansys_wide_init_chip(struct Scsi_Host *shost)
 | 
				
			||||||
	if (!reqp)
 | 
						if (!reqp)
 | 
				
			||||||
		goto kmalloc_failed;
 | 
							goto kmalloc_failed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	adv_dvc->orig_reqp = reqp;
 | 
						board->adv_reqp = reqp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Allocate up to ADV_TOT_SG_BLOCK request structures for
 | 
						 * Allocate up to ADV_TOT_SG_BLOCK request structures for
 | 
				
			||||||
| 
						 | 
					@ -11317,7 +11242,6 @@ static int advansys_wide_init_chip(struct Scsi_Host *shost)
 | 
				
			||||||
	for (; req_cnt > 0; req_cnt--) {
 | 
						for (; req_cnt > 0; req_cnt--) {
 | 
				
			||||||
		reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
 | 
							reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	board->adv_reqp = &reqp[0];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (adv_dvc->chip_type == ADV_CHIP_ASC3550) {
 | 
						if (adv_dvc->chip_type == ADV_CHIP_ASC3550) {
 | 
				
			||||||
		ASC_DBG(2, "AdvInitAsc3550Driver()\n");
 | 
							ASC_DBG(2, "AdvInitAsc3550Driver()\n");
 | 
				
			||||||
| 
						 | 
					@ -11350,8 +11274,8 @@ static void advansys_wide_free_mem(struct asc_board *board)
 | 
				
			||||||
	struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var;
 | 
						struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var;
 | 
				
			||||||
	kfree(adv_dvc->carrier_buf);
 | 
						kfree(adv_dvc->carrier_buf);
 | 
				
			||||||
	adv_dvc->carrier_buf = NULL;
 | 
						adv_dvc->carrier_buf = NULL;
 | 
				
			||||||
	kfree(adv_dvc->orig_reqp);
 | 
						kfree(board->adv_reqp);
 | 
				
			||||||
	adv_dvc->orig_reqp = board->adv_reqp = NULL;
 | 
						board->adv_reqp = NULL;
 | 
				
			||||||
	while (board->adv_sgblkp) {
 | 
						while (board->adv_sgblkp) {
 | 
				
			||||||
		adv_sgblk_t *sgp = board->adv_sgblkp;
 | 
							adv_sgblk_t *sgp = board->adv_sgblkp;
 | 
				
			||||||
		board->adv_sgblkp = sgp->next_sgblkp;
 | 
							board->adv_sgblkp = sgp->next_sgblkp;
 | 
				
			||||||
| 
						 | 
					@ -11651,6 +11575,11 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
 | 
				
			||||||
		/* Set maximum number of queues the adapter can handle. */
 | 
							/* Set maximum number of queues the adapter can handle. */
 | 
				
			||||||
		shost->can_queue = adv_dvc_varp->max_host_qng;
 | 
							shost->can_queue = adv_dvc_varp->max_host_qng;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						ret = scsi_init_shared_tag_map(shost, shost->can_queue);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							shost_printk(KERN_ERR, shost, "init tag map failed\n");
 | 
				
			||||||
 | 
							goto err_free_dma;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Following v1.3.89, 'cmd_per_lun' is no longer needed
 | 
						 * Following v1.3.89, 'cmd_per_lun' is no longer needed
 | 
				
			||||||
| 
						 | 
					@ -11922,6 +11851,7 @@ static int advansys_isa_probe(struct device *dev, unsigned int id)
 | 
				
			||||||
	board = shost_priv(shost);
 | 
						board = shost_priv(shost);
 | 
				
			||||||
	board->irq = advansys_isa_irq_no(iop_base);
 | 
						board->irq = advansys_isa_irq_no(iop_base);
 | 
				
			||||||
	board->dev = dev;
 | 
						board->dev = dev;
 | 
				
			||||||
 | 
						board->shost = shost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = advansys_board_found(shost, iop_base, ASC_IS_ISA);
 | 
						err = advansys_board_found(shost, iop_base, ASC_IS_ISA);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
| 
						 | 
					@ -12004,6 +11934,7 @@ static int advansys_vlb_probe(struct device *dev, unsigned int id)
 | 
				
			||||||
	board = shost_priv(shost);
 | 
						board = shost_priv(shost);
 | 
				
			||||||
	board->irq = advansys_vlb_irq_no(iop_base);
 | 
						board->irq = advansys_vlb_irq_no(iop_base);
 | 
				
			||||||
	board->dev = dev;
 | 
						board->dev = dev;
 | 
				
			||||||
 | 
						board->shost = shost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = advansys_board_found(shost, iop_base, ASC_IS_VL);
 | 
						err = advansys_board_found(shost, iop_base, ASC_IS_VL);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
| 
						 | 
					@ -12111,6 +12042,7 @@ static int advansys_eisa_probe(struct device *dev)
 | 
				
			||||||
		board = shost_priv(shost);
 | 
							board = shost_priv(shost);
 | 
				
			||||||
		board->irq = irq;
 | 
							board->irq = irq;
 | 
				
			||||||
		board->dev = dev;
 | 
							board->dev = dev;
 | 
				
			||||||
 | 
							board->shost = shost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err = advansys_board_found(shost, ioport, ASC_IS_EISA);
 | 
							err = advansys_board_found(shost, ioport, ASC_IS_EISA);
 | 
				
			||||||
		if (!err) {
 | 
							if (!err) {
 | 
				
			||||||
| 
						 | 
					@ -12227,6 +12159,7 @@ static int advansys_pci_probe(struct pci_dev *pdev,
 | 
				
			||||||
	board = shost_priv(shost);
 | 
						board = shost_priv(shost);
 | 
				
			||||||
	board->irq = pdev->irq;
 | 
						board->irq = pdev->irq;
 | 
				
			||||||
	board->dev = &pdev->dev;
 | 
						board->dev = &pdev->dev;
 | 
				
			||||||
 | 
						board->shost = shost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
 | 
						if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
 | 
				
			||||||
	    pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
 | 
						    pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue