aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/advansys.c105
1 files changed, 79 insertions, 26 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index d35897eaa807..88e7fef18a29 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -90,17 +90,6 @@
90#define ASC_DCNT __u32 /* Unsigned Data count type. */ 90#define ASC_DCNT __u32 /* Unsigned Data count type. */
91#define ASC_SDCNT __s32 /* Signed Data count type. */ 91#define ASC_SDCNT __s32 /* Signed Data count type. */
92 92
93/*
94 * These macros are used to convert a virtual address to a
95 * 32-bit value. This currently can be used on Linux Alpha
96 * which uses 64-bit virtual address but a 32-bit bus address.
97 * This is likely to break in the future, but doing this now
98 * will give us time to change the HW and FW to handle 64-bit
99 * addresses.
100 */
101#define ASC_VADDR_TO_U32 virt_to_bus
102#define ASC_U32_TO_VADDR bus_to_virt
103
104typedef unsigned char uchar; 93typedef unsigned char uchar;
105 94
106#ifndef TRUE 95#ifndef TRUE
@@ -601,6 +590,8 @@ typedef struct asc_dvc_var {
601 uchar min_sdtr_index; 590 uchar min_sdtr_index;
602 uchar max_sdtr_index; 591 uchar max_sdtr_index;
603 struct asc_board *drv_ptr; 592 struct asc_board *drv_ptr;
593 int ptr_map_count;
594 void **ptr_map;
604 ASC_DCNT uc_break; 595 ASC_DCNT uc_break;
605} ASC_DVC_VAR; 596} ASC_DVC_VAR;
606 597
@@ -2748,6 +2739,59 @@ static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
2748#endif /* ADVANSYS_DEBUG */ 2739#endif /* ADVANSYS_DEBUG */
2749 2740
2750/* 2741/*
2742 * The advansys chip/microcode contains a 32-bit identifier for each command
2743 * known as the 'srb'. I don't know what it stands for. The driver used
2744 * to encode the scsi_cmnd pointer by calling virt_to_bus and retrieve it
2745 * with bus_to_virt. Now the driver keeps a per-host map of integers to
2746 * pointers. It auto-expands when full, unless it can't allocate memory.
2747 * Note that an srb of 0 is treated specially by the chip/firmware, hence
2748 * the return of i+1 in this routine, and the corresponding subtraction in
2749 * the inverse routine.
2750 */
2751#define BAD_SRB 0
2752static u32 advansys_ptr_to_srb(struct asc_dvc_var *asc_dvc, void *ptr)
2753{
2754 int i;
2755 void **new_ptr;
2756
2757 for (i = 0; i < asc_dvc->ptr_map_count; i++) {
2758 if (!asc_dvc->ptr_map[i])
2759 goto out;
2760 }
2761
2762 if (asc_dvc->ptr_map_count == 0)
2763 asc_dvc->ptr_map_count = 1;
2764 else
2765 asc_dvc->ptr_map_count *= 2;
2766
2767 new_ptr = krealloc(asc_dvc->ptr_map,
2768 asc_dvc->ptr_map_count * sizeof(void *), GFP_ATOMIC);
2769 if (!new_ptr)
2770 return BAD_SRB;
2771 asc_dvc->ptr_map = new_ptr;
2772 out:
2773 ASC_DBG(3, "Putting ptr %p into array offset %d\n", ptr, i);
2774 asc_dvc->ptr_map[i] = ptr;
2775 return i + 1;
2776}
2777
2778static void * advansys_srb_to_ptr(struct asc_dvc_var *asc_dvc, u32 srb)
2779{
2780 void *ptr;
2781
2782 srb--;
2783 if (srb >= asc_dvc->ptr_map_count) {
2784 printk("advansys: bad SRB %u, max %u\n", srb,
2785 asc_dvc->ptr_map_count);
2786 return NULL;
2787 }
2788 ptr = asc_dvc->ptr_map[srb];
2789 asc_dvc->ptr_map[srb] = NULL;
2790 ASC_DBG(3, "Returning ptr %p from array offset %d\n", ptr, srb);
2791 return ptr;
2792}
2793
2794/*
2751 * advansys_info() 2795 * advansys_info()
2752 * 2796 *
2753 * Return suitable for printing on the console with the argument 2797 * Return suitable for printing on the console with the argument
@@ -9075,17 +9119,10 @@ static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
9075 ASC_DBG(1, "asc_dvc_varp 0x%p, qdonep 0x%p\n", asc_dvc_varp, qdonep); 9119 ASC_DBG(1, "asc_dvc_varp 0x%p, qdonep 0x%p\n", asc_dvc_varp, qdonep);
9076 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); 9120 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
9077 9121
9078 /* 9122 scp = advansys_srb_to_ptr(asc_dvc_varp, qdonep->d2.srb_ptr);
9079 * Get the struct scsi_cmnd structure and Scsi_Host structure for the 9123 if (!scp)
9080 * command that has been completed.
9081 */
9082 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
9083 ASC_DBG(1, "scp 0x%p\n", scp);
9084
9085 if (scp == NULL) {
9086 ASC_PRINT("asc_isr_callback: scp is NULL\n");
9087 return; 9124 return;
9088 } 9125
9089 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); 9126 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
9090 9127
9091 shost = scp->device->host; 9128 shost = scp->device->host;
@@ -9095,6 +9132,8 @@ static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
9095 boardp = shost_priv(shost); 9132 boardp = shost_priv(shost);
9096 BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var); 9133 BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var);
9097 9134
9135 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
9136 sizeof(scp->sense_buffer), DMA_FROM_DEVICE);
9098 /* 9137 /*
9099 * 'qdonep' contains the command's ending status. 9138 * 'qdonep' contains the command's ending status.
9100 */ 9139 */
@@ -9835,9 +9874,20 @@ static int advansys_slave_configure(struct scsi_device *sdev)
9835 return 0; 9874 return 0;
9836} 9875}
9837 9876
9877static __le32 advansys_get_sense_buffer_dma(struct scsi_cmnd *scp)
9878{
9879 struct asc_board *board = shost_priv(scp->device->host);
9880 scp->SCp.dma_handle = dma_map_single(board->dev, scp->sense_buffer,
9881 sizeof(scp->sense_buffer), DMA_FROM_DEVICE);
9882 dma_cache_sync(board->dev, scp->sense_buffer,
9883 sizeof(scp->sense_buffer), DMA_FROM_DEVICE);
9884 return cpu_to_le32(scp->SCp.dma_handle);
9885}
9886
9838static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp, 9887static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
9839 struct asc_scsi_q *asc_scsi_q) 9888 struct asc_scsi_q *asc_scsi_q)
9840{ 9889{
9890 struct asc_dvc_var *asc_dvc = &boardp->dvc_var.asc_dvc_var;
9841 int use_sg; 9891 int use_sg;
9842 9892
9843 memset(asc_scsi_q, 0, sizeof(*asc_scsi_q)); 9893 memset(asc_scsi_q, 0, sizeof(*asc_scsi_q));
@@ -9845,7 +9895,11 @@ static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
9845 /* 9895 /*
9846 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. 9896 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
9847 */ 9897 */
9848 asc_scsi_q->q2.srb_ptr = ASC_VADDR_TO_U32(scp); 9898 asc_scsi_q->q2.srb_ptr = advansys_ptr_to_srb(asc_dvc, scp);
9899 if (asc_scsi_q->q2.srb_ptr == BAD_SRB) {
9900 scp->result = HOST_BYTE(DID_SOFT_ERROR);
9901 return ASC_ERROR;
9902 }
9849 9903
9850 /* 9904 /*
9851 * Build the ASC_SCSI_Q request. 9905 * Build the ASC_SCSI_Q request.
@@ -9856,8 +9910,7 @@ static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
9856 asc_scsi_q->q1.target_lun = scp->device->lun; 9910 asc_scsi_q->q1.target_lun = scp->device->lun;
9857 asc_scsi_q->q2.target_ix = 9911 asc_scsi_q->q2.target_ix =
9858 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); 9912 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
9859 asc_scsi_q->q1.sense_addr = 9913 asc_scsi_q->q1.sense_addr = advansys_get_sense_buffer_dma(scp);
9860 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
9861 asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer); 9914 asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer);
9862 9915
9863 /* 9916 /*
@@ -9871,7 +9924,7 @@ static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
9871 * started request. 9924 * started request.
9872 * 9925 *
9873 */ 9926 */
9874 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && 9927 if ((asc_dvc->cur_dvc_qng[scp->device->id] > 0) &&
9875 (boardp->reqcnt[scp->device->id] % 255) == 0) { 9928 (boardp->reqcnt[scp->device->id] % 255) == 0) {
9876 asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG; 9929 asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG;
9877 } else { 9930 } else {
@@ -10091,7 +10144,7 @@ adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
10091 /* 10144 /*
10092 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. 10145 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
10093 */ 10146 */
10094 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp); 10147 scsiqp->srb_ptr = ADV_VADDR_TO_U32(reqp);
10095 10148
10096 /* 10149 /*
10097 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. 10150 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.