aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/advansys.c504
1 files changed, 6 insertions, 498 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 90f05c52be7e..67cdfe6201ce 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -63,11 +63,10 @@
63 * has not occurred then print a message and run in polled mode. 63 * has not occurred then print a message and run in polled mode.
64 * 4. Need to add support for target mode commands, cf. CAM XPT. 64 * 4. Need to add support for target mode commands, cf. CAM XPT.
65 * 5. check DMA mapping functions for failure 65 * 5. check DMA mapping functions for failure
66 * 6. Remove internal queueing 66 * 6. Use scsi_transport_spi
67 * 7. Use scsi_transport_spi 67 * 7. advansys_info is not safe against multiple simultaneous callers
68 * 8. advansys_info is not safe against multiple simultaneous callers 68 * 8. Kill boardp->id
69 * 9. Kill boardp->id 69 * 9. Add module_param to override ISA/VLB ioport array
70 * 10. Add module_param to override ISA/VLB ioport array
71 */ 70 */
72#warning this driver is still not properly converted to the DMA API 71#warning this driver is still not properly converted to the DMA API
73 72
@@ -2514,64 +2513,6 @@ do { \
2514#define HOST_BYTE(byte) ((byte) << 16) 2513#define HOST_BYTE(byte) ((byte) << 16)
2515#define DRIVER_BYTE(byte) ((byte) << 24) 2514#define DRIVER_BYTE(byte) ((byte) << 24)
2516 2515
2517/*
2518 * The following definitions and macros are OS independent interfaces to
2519 * the queue functions:
2520 * REQ - SCSI request structure
2521 * REQP - pointer to SCSI request structure
2522 * REQPTID(reqp) - reqp's target id
2523 * REQPNEXT(reqp) - reqp's next pointer
2524 * REQPNEXTP(reqp) - pointer to reqp's next pointer
2525 * REQPTIME(reqp) - reqp's time stamp value
2526 * REQTIMESTAMP() - system time stamp value
2527 */
2528typedef struct scsi_cmnd REQ, *REQP;
2529#define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble))
2530#define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble))
2531#define REQPTID(reqp) ((reqp)->device->id)
2532#define REQPTIME(reqp) ((reqp)->SCp.this_residual)
2533#define REQTIMESTAMP() (jiffies)
2534
2535#define REQTIMESTAT(function, ascq, reqp, tid) \
2536{ \
2537 /*
2538 * If the request time stamp is less than the system time stamp, then \
2539 * maybe the system time stamp wrapped. Set the request time to zero.\
2540 */ \
2541 if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
2542 REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
2543 } else { \
2544 /* Indicate an error occurred with the assertion. */ \
2545 ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
2546 REQPTIME(reqp) = 0; \
2547 } \
2548 /* Handle first minimum time case without external initialization. */ \
2549 if (((ascq)->q_tot_cnt[tid] == 1) || \
2550 (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
2551 (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
2552 ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
2553 (function), (tid), (ascq)->q_min_tim[tid]); \
2554 } \
2555 if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
2556 (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
2557 ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
2558 (function), tid, (ascq)->q_max_tim[tid]); \
2559 } \
2560 (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
2561 /* Reset the time stamp field. */ \
2562 REQPTIME(reqp) = 0; \
2563}
2564
2565/* asc_enqueue() flags */
2566#define ASC_FRONT 1
2567#define ASC_BACK 2
2568
2569/* asc_dequeue_list() argument */
2570#define ASC_TID_ALL (-1)
2571
2572/* Return non-zero, if the queue is empty. */
2573#define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0)
2574
2575#ifndef ADVANSYS_STATS 2516#ifndef ADVANSYS_STATS
2576#define ASC_STATS(shost, counter) 2517#define ASC_STATS(shost, counter)
2577#define ASC_STATS_ADD(shost, counter, count) 2518#define ASC_STATS_ADD(shost, counter, count)
@@ -2784,23 +2725,6 @@ struct asc_stats {
2784#endif /* ADVANSYS_STATS */ 2725#endif /* ADVANSYS_STATS */
2785 2726
2786/* 2727/*
2787 * Request queuing structure
2788 */
2789typedef struct asc_queue {
2790 ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
2791 REQP q_first[ADV_MAX_TID + 1]; /* first queued request */
2792 REQP q_last[ADV_MAX_TID + 1]; /* last queued request */
2793#ifdef ADVANSYS_STATS
2794 short q_cur_cnt[ADV_MAX_TID + 1]; /* current queue count */
2795 short q_max_cnt[ADV_MAX_TID + 1]; /* maximum queue count */
2796 ADV_DCNT q_tot_cnt[ADV_MAX_TID + 1]; /* total enqueue count */
2797 ADV_DCNT q_tot_tim[ADV_MAX_TID + 1]; /* total time queued */
2798 ushort q_max_tim[ADV_MAX_TID + 1]; /* maximum time queued */
2799 ushort q_min_tim[ADV_MAX_TID + 1]; /* minimum time queued */
2800#endif /* ADVANSYS_STATS */
2801} asc_queue_t;
2802
2803/*
2804 * Adv Library Request Structures 2728 * Adv Library Request Structures
2805 * 2729 *
2806 * The following two structures are used to process Wide Board requests. 2730 * The following two structures are used to process Wide Board requests.
@@ -2851,7 +2775,6 @@ typedef struct asc_board {
2851 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */ 2775 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
2852 } dvc_cfg; 2776 } dvc_cfg;
2853 ushort asc_n_io_port; /* Number I/O ports. */ 2777 ushort asc_n_io_port; /* Number I/O ports. */
2854 asc_queue_t active; /* Active command queue */
2855 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ 2778 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
2856 struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */ 2779 struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */
2857 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */ 2780 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
@@ -2914,14 +2837,10 @@ static int asc_dbglvl = 3;
2914 */ 2837 */
2915 2838
2916static int advansys_slave_configure(struct scsi_device *); 2839static int advansys_slave_configure(struct scsi_device *);
2917static void asc_scsi_done_list(struct scsi_cmnd *);
2918static int asc_execute_scsi_cmnd(struct scsi_cmnd *); 2840static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
2919static int asc_build_req(asc_board_t *, struct scsi_cmnd *); 2841static int asc_build_req(asc_board_t *, struct scsi_cmnd *);
2920static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **); 2842static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **);
2921static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int); 2843static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int);
2922static void asc_enqueue(asc_queue_t *, REQP, int);
2923static REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
2924static int asc_rmqueue(asc_queue_t *, REQP);
2925#ifdef CONFIG_PROC_FS 2844#ifdef CONFIG_PROC_FS
2926static int asc_proc_copy(off_t, off_t, char *, int, char *, int); 2845static int asc_proc_copy(off_t, off_t, char *, int, char *, int);
2927static int asc_prt_board_devices(struct Scsi_Host *, char *, int); 2846static int asc_prt_board_devices(struct Scsi_Host *, char *, int);
@@ -2939,7 +2858,6 @@ static int asc_prt_line(char *, int, char *fmt, ...);
2939#ifdef ADVANSYS_STATS 2858#ifdef ADVANSYS_STATS
2940#ifdef CONFIG_PROC_FS 2859#ifdef CONFIG_PROC_FS
2941static int asc_prt_board_stats(struct Scsi_Host *, char *, int); 2860static int asc_prt_board_stats(struct Scsi_Host *, char *, int);
2942static int asc_prt_target_stats(struct Scsi_Host *, int, char *, int);
2943#endif /* CONFIG_PROC_FS */ 2861#endif /* CONFIG_PROC_FS */
2944#endif /* ADVANSYS_STATS */ 2862#endif /* ADVANSYS_STATS */
2945 2863
@@ -2991,9 +2909,6 @@ advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
2991 int leftlen; 2909 int leftlen;
2992 char *curbuf; 2910 char *curbuf;
2993 off_t advoffset; 2911 off_t advoffset;
2994#ifdef ADVANSYS_STATS
2995 int tgt_id;
2996#endif /* ADVANSYS_STATS */
2997 2912
2998 ASC_DBG(1, "advansys_proc_info: begin\n"); 2913 ASC_DBG(1, "advansys_proc_info: begin\n");
2999 2914
@@ -3123,26 +3038,6 @@ advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
3123 } 3038 }
3124 advoffset += cplen; 3039 advoffset += cplen;
3125 curbuf += cnt; 3040 curbuf += cnt;
3126
3127 /*
3128 * Display driver statistics for each target.
3129 */
3130 for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) {
3131 cp = boardp->prtbuf;
3132 cplen = asc_prt_target_stats(shost, tgt_id, cp,
3133 ASC_PRTBUF_SIZE);
3134 ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
3135 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
3136 cplen);
3137 totcnt += cnt;
3138 leftlen -= cnt;
3139 if (leftlen == 0) {
3140 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3141 return totcnt;
3142 }
3143 advoffset += cplen;
3144 curbuf += cnt;
3145 }
3146#endif /* ADVANSYS_STATS */ 3041#endif /* ADVANSYS_STATS */
3147 3042
3148 /* 3043 /*
@@ -3331,8 +3226,6 @@ static int advansys_reset(struct scsi_cmnd *scp)
3331 ASC_DVC_VAR *asc_dvc_varp; 3226 ASC_DVC_VAR *asc_dvc_varp;
3332 ADV_DVC_VAR *adv_dvc_varp; 3227 ADV_DVC_VAR *adv_dvc_varp;
3333 ulong flags; 3228 ulong flags;
3334 struct scsi_cmnd *done_scp = NULL, *last_scp = NULL;
3335 struct scsi_cmnd *tscp, *new_last_scp;
3336 int status; 3229 int status;
3337 int ret = SUCCESS; 3230 int ret = SUCCESS;
3338 3231
@@ -3423,34 +3316,6 @@ static int advansys_reset(struct scsi_cmnd *scp)
3423 } 3316 }
3424 /* Board lock is held. */ 3317 /* Board lock is held. */
3425 3318
3426 /*
3427 * Dequeue all board 'active' requests for all devices and set
3428 * the request status to DID_RESET. A pointer to the last request
3429 * is returned in 'last_scp'.
3430 */
3431 if (done_scp == NULL) {
3432 done_scp = asc_dequeue_list(&boardp->active, &last_scp,
3433 ASC_TID_ALL);
3434 for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
3435 tscp->result = HOST_BYTE(DID_RESET);
3436 }
3437 } else {
3438 /* Append to 'done_scp' at the end with 'last_scp'. */
3439 ASC_ASSERT(last_scp != NULL);
3440 last_scp->host_scribble =
3441 (unsigned char *)asc_dequeue_list(&boardp->active,
3442 &new_last_scp,
3443 ASC_TID_ALL);
3444 if (new_last_scp != NULL) {
3445 ASC_ASSERT(REQPNEXT(last_scp) != NULL);
3446 for (tscp = REQPNEXT(last_scp); tscp;
3447 tscp = REQPNEXT(tscp)) {
3448 tscp->result = HOST_BYTE(DID_RESET);
3449 }
3450 last_scp = new_last_scp;
3451 }
3452 }
3453
3454 /* Save the time of the most recently completed reset. */ 3319 /* Save the time of the most recently completed reset. */
3455 boardp->last_reset = jiffies; 3320 boardp->last_reset = jiffies;
3456 3321
@@ -3458,12 +3323,6 @@ static int advansys_reset(struct scsi_cmnd *scp)
3458 boardp->flags &= ~ASC_HOST_IN_RESET; 3323 boardp->flags &= ~ASC_HOST_IN_RESET;
3459 spin_unlock_irqrestore(&boardp->lock, flags); 3324 spin_unlock_irqrestore(&boardp->lock, flags);
3460 3325
3461 /*
3462 * Complete all the 'done_scp' requests.
3463 */
3464 if (done_scp)
3465 asc_scsi_done_list(done_scp);
3466
3467 ASC_DBG1(1, "advansys_reset: ret %d\n", ret); 3326 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
3468 3327
3469 return ret; 3328 return ret;
@@ -3795,30 +3654,6 @@ static int advansys_slave_configure(struct scsi_device *sdev)
3795} 3654}
3796 3655
3797/* 3656/*
3798 * Complete all requests on the singly linked list pointed
3799 * to by 'scp'.
3800 *
3801 * Interrupts can be enabled on entry.
3802 */
3803static void asc_scsi_done_list(struct scsi_cmnd *scp)
3804{
3805 struct scsi_cmnd *tscp;
3806
3807 ASC_DBG(2, "asc_scsi_done_list: begin\n");
3808 while (scp != NULL) {
3809 ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp);
3810 tscp = REQPNEXT(scp);
3811 scp->host_scribble = NULL;
3812
3813 asc_scsi_done(scp);
3814
3815 scp = tscp;
3816 }
3817 ASC_DBG(2, "asc_scsi_done_list: done\n");
3818 return;
3819}
3820
3821/*
3822 * Execute a single 'Scsi_Cmnd'. 3657 * Execute a single 'Scsi_Cmnd'.
3823 * 3658 *
3824 * The function 'done' is called when the request has been completed. 3659 * The function 'done' is called when the request has been completed.
@@ -3854,9 +3689,8 @@ static void asc_scsi_done_list(struct scsi_cmnd *scp)
3854 * scsi_done - used to save caller's done function 3689 * scsi_done - used to save caller's done function
3855 * host_scribble - used for pointer to another struct scsi_cmnd 3690 * host_scribble - used for pointer to another struct scsi_cmnd
3856 * 3691 *
3857 * If this function returns ASC_NOERROR the request has been enqueued 3692 * If this function returns ASC_NOERROR the request will be completed
3858 * on the board's 'active' queue and will be completed from the 3693 * from the interrupt handler.
3859 * interrupt handler.
3860 * 3694 *
3861 * If this function returns ASC_ERROR the host error code has been set, 3695 * If this function returns ASC_ERROR the host error code has been set,
3862 * and the called must call asc_scsi_done. 3696 * and the called must call asc_scsi_done.
@@ -3901,10 +3735,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
3901 return ASC_ERROR; 3735 return ASC_ERROR;
3902 } 3736 }
3903 3737
3904 /*
3905 * Execute the command. If there is no error, add the command
3906 * to the active queue.
3907 */
3908 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { 3738 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
3909 case ASC_NOERROR: 3739 case ASC_NOERROR:
3910 ASC_STATS(scp->device->host, exe_noerror); 3740 ASC_STATS(scp->device->host, exe_noerror);
@@ -3913,7 +3743,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
3913 * successful request counter. Wrapping doesn't matter. 3743 * successful request counter. Wrapping doesn't matter.
3914 */ 3744 */
3915 boardp->reqcnt[scp->device->id]++; 3745 boardp->reqcnt[scp->device->id]++;
3916 asc_enqueue(&boardp->active, scp, ASC_BACK);
3917 ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), " 3746 ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), "
3918 "ASC_NOERROR\n"); 3747 "ASC_NOERROR\n");
3919 break; 3748 break;
@@ -3970,10 +3799,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
3970 return ASC_ERROR; 3799 return ASC_ERROR;
3971 } 3800 }
3972 3801
3973 /*
3974 * Execute the command. If there is no error, add the command
3975 * to the active queue.
3976 */
3977 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) { 3802 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
3978 case ASC_NOERROR: 3803 case ASC_NOERROR:
3979 ASC_STATS(scp->device->host, exe_noerror); 3804 ASC_STATS(scp->device->host, exe_noerror);
@@ -3982,7 +3807,6 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
3982 * successful request counter. Wrapping doesn't matter. 3807 * successful request counter. Wrapping doesn't matter.
3983 */ 3808 */
3984 boardp->reqcnt[scp->device->id]++; 3809 boardp->reqcnt[scp->device->id]++;
3985 asc_enqueue(&boardp->active, scp, ASC_BACK);
3986 ASC_DBG(1, "asc_execute_scsi_cmnd: AdvExeScsiQueue(), " 3810 ASC_DBG(1, "asc_execute_scsi_cmnd: AdvExeScsiQueue(), "
3987 "ASC_NOERROR\n"); 3811 "ASC_NOERROR\n");
3988 break; 3812 break;
@@ -4467,19 +4291,8 @@ static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
4467 ASC_STATS(shost, callback); 4291 ASC_STATS(shost, callback);
4468 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost); 4292 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
4469 4293
4470 /*
4471 * If the request isn't found on the active queue, it may
4472 * have been removed to handle a reset request.
4473 * Display a message and return.
4474 */
4475 boardp = ASC_BOARDP(shost); 4294 boardp = ASC_BOARDP(shost);
4476 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var); 4295 ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
4477 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
4478 ASC_PRINT2
4479 ("asc_isr_callback: board %d: scp 0x%lx not on active queue\n",
4480 boardp->id, (ulong)scp);
4481 return;
4482 }
4483 4296
4484 /* 4297 /*
4485 * 'qdonep' contains the command's ending status. 4298 * 'qdonep' contains the command's ending status.
@@ -4624,21 +4437,8 @@ static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
4624 ASC_STATS(shost, callback); 4437 ASC_STATS(shost, callback);
4625 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost); 4438 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
4626 4439
4627 /*
4628 * If the request isn't found on the active queue, it may have been
4629 * removed to handle a reset request. Display a message and return.
4630 *
4631 * Note: Because the structure may still be in use don't attempt
4632 * to free the adv_req_t and adv_sgblk_t, if any, structures.
4633 */
4634 boardp = ASC_BOARDP(shost); 4440 boardp = ASC_BOARDP(shost);
4635 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var); 4441 ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
4636 if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
4637 ASC_PRINT2
4638 ("adv_isr_callback: board %d: scp 0x%lx not on active queue\n",
4639 boardp->id, (ulong)scp);
4640 return;
4641 }
4642 4442
4643 /* 4443 /*
4644 * 'done_status' contains the command's ending status. 4444 * 'done_status' contains the command's ending status.
@@ -4787,225 +4587,6 @@ static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
4787 } 4587 }
4788} 4588}
4789 4589
4790/*
4791 * Add a 'REQP' to the end of specified queue. Set 'tidmask'
4792 * to indicate a command is queued for the device.
4793 *
4794 * 'flag' may be either ASC_FRONT or ASC_BACK.
4795 *
4796 * 'REQPNEXT(reqp)' returns reqp's next pointer.
4797 */
4798static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
4799{
4800 int tid;
4801
4802 ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n",
4803 (ulong)ascq, (ulong)reqp, flag);
4804 ASC_ASSERT(reqp != NULL);
4805 ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
4806 tid = REQPTID(reqp);
4807 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
4808 if (flag == ASC_FRONT) {
4809 reqp->host_scribble = (unsigned char *)ascq->q_first[tid];
4810 ascq->q_first[tid] = reqp;
4811 /* If the queue was empty, set the last pointer. */
4812 if (ascq->q_last[tid] == NULL) {
4813 ascq->q_last[tid] = reqp;
4814 }
4815 } else { /* ASC_BACK */
4816 if (ascq->q_last[tid] != NULL) {
4817 ascq->q_last[tid]->host_scribble =
4818 (unsigned char *)reqp;
4819 }
4820 ascq->q_last[tid] = reqp;
4821 reqp->host_scribble = NULL;
4822 /* If the queue was empty, set the first pointer. */
4823 if (ascq->q_first[tid] == NULL) {
4824 ascq->q_first[tid] = reqp;
4825 }
4826 }
4827 /* The queue has at least one entry, set its bit. */
4828 ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
4829#ifdef ADVANSYS_STATS
4830 /* Maintain request queue statistics. */
4831 ascq->q_tot_cnt[tid]++;
4832 ascq->q_cur_cnt[tid]++;
4833 if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
4834 ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
4835 ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
4836 tid, ascq->q_max_cnt[tid]);
4837 }
4838 REQPTIME(reqp) = REQTIMESTAMP();
4839#endif /* ADVANSYS_STATS */
4840 ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong)reqp);
4841 return;
4842}
4843
4844/*
4845 * Return a pointer to a singly linked list of all the requests queued
4846 * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
4847 *
4848 * If 'lastpp' is not NULL, '*lastpp' will be set to point to the
4849 * the last request returned in the singly linked list.
4850 *
4851 * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
4852 * then all queued requests are concatenated into one list and
4853 * returned.
4854 *
4855 * Note: If 'lastpp' is used to append a new list to the end of
4856 * an old list, only change the old list last pointer if '*lastpp'
4857 * (or the function return value) is not NULL, i.e. use a temporary
4858 * variable for 'lastpp' and check its value after the function return
4859 * before assigning it to the list last pointer.
4860 *
4861 * Unfortunately collecting queuing time statistics adds overhead to
4862 * the function that isn't inherent to the function's algorithm.
4863 */
4864static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
4865{
4866 REQP firstp, lastp;
4867 int i;
4868
4869 ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong)ascq, tid);
4870 ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
4871
4872 /*
4873 * If 'tid' is not ASC_TID_ALL, return requests only for
4874 * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
4875 * requests for all tids.
4876 */
4877 if (tid != ASC_TID_ALL) {
4878 /* Return all requests for the specified 'tid'. */
4879 if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
4880 /* List is empty; Set first and last return pointers to NULL. */
4881 firstp = lastp = NULL;
4882 } else {
4883 firstp = ascq->q_first[tid];
4884 lastp = ascq->q_last[tid];
4885 ascq->q_first[tid] = ascq->q_last[tid] = NULL;
4886 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
4887#ifdef ADVANSYS_STATS
4888 {
4889 REQP reqp;
4890 ascq->q_cur_cnt[tid] = 0;
4891 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
4892 REQTIMESTAT("asc_dequeue_list", ascq,
4893 reqp, tid);
4894 }
4895 }
4896#endif /* ADVANSYS_STATS */
4897 }
4898 } else {
4899 /* Return all requests for all tids. */
4900 firstp = lastp = NULL;
4901 for (i = 0; i <= ADV_MAX_TID; i++) {
4902 if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
4903 if (firstp == NULL) {
4904 firstp = ascq->q_first[i];
4905 lastp = ascq->q_last[i];
4906 } else {
4907 ASC_ASSERT(lastp != NULL);
4908 lastp->host_scribble =
4909 (unsigned char *)ascq->q_first[i];
4910 lastp = ascq->q_last[i];
4911 }
4912 ascq->q_first[i] = ascq->q_last[i] = NULL;
4913 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
4914#ifdef ADVANSYS_STATS
4915 ascq->q_cur_cnt[i] = 0;
4916#endif /* ADVANSYS_STATS */
4917 }
4918 }
4919#ifdef ADVANSYS_STATS
4920 {
4921 REQP reqp;
4922 for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
4923 REQTIMESTAT("asc_dequeue_list", ascq, reqp,
4924 reqp->device->id);
4925 }
4926 }
4927#endif /* ADVANSYS_STATS */
4928 }
4929 if (lastpp) {
4930 *lastpp = lastp;
4931 }
4932 ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp);
4933 return firstp;
4934}
4935
4936/*
4937 * Remove the specified 'REQP' from the specified queue for
4938 * the specified target device. Clear the 'tidmask' bit for the
4939 * device if no more commands are left queued for it.
4940 *
4941 * 'REQPNEXT(reqp)' returns reqp's the next pointer.
4942 *
4943 * Return ASC_TRUE if the command was found and removed,
4944 * otherwise return ASC_FALSE.
4945 */
4946static int asc_rmqueue(asc_queue_t *ascq, REQP reqp)
4947{
4948 REQP currp, prevp;
4949 int tid;
4950 int ret = ASC_FALSE;
4951
4952 ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n",
4953 (ulong)ascq, (ulong)reqp);
4954 ASC_ASSERT(reqp != NULL);
4955
4956 tid = REQPTID(reqp);
4957 ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
4958
4959 /*
4960 * Handle the common case of 'reqp' being the first
4961 * entry on the queue.
4962 */
4963 if (reqp == ascq->q_first[tid]) {
4964 ret = ASC_TRUE;
4965 ascq->q_first[tid] = REQPNEXT(reqp);
4966 /* If the queue is now empty, clear its bit and the last pointer. */
4967 if (ascq->q_first[tid] == NULL) {
4968 ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
4969 ASC_ASSERT(ascq->q_last[tid] == reqp);
4970 ascq->q_last[tid] = NULL;
4971 }
4972 } else if (ascq->q_first[tid] != NULL) {
4973 ASC_ASSERT(ascq->q_last[tid] != NULL);
4974 /*
4975 * Because the case of 'reqp' being the first entry has been
4976 * handled above and it is known the queue is not empty, if
4977 * 'reqp' is found on the queue it is guaranteed the queue will
4978 * not become empty and that 'q_first[tid]' will not be changed.
4979 *
4980 * Set 'prevp' to the first entry, 'currp' to the second entry,
4981 * and search for 'reqp'.
4982 */
4983 for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
4984 currp; prevp = currp, currp = REQPNEXT(currp)) {
4985 if (currp == reqp) {
4986 ret = ASC_TRUE;
4987 prevp->host_scribble =
4988 (unsigned char *)REQPNEXT(currp);
4989 reqp->host_scribble = NULL;
4990 if (ascq->q_last[tid] == reqp) {
4991 ascq->q_last[tid] = prevp;
4992 }
4993 break;
4994 }
4995 }
4996 }
4997#ifdef ADVANSYS_STATS
4998 /* Maintain request queue statistics. */
4999 if (ret == ASC_TRUE) {
5000 ascq->q_cur_cnt[tid]--;
5001 REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
5002 }
5003 ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
5004#endif /* ADVANSYS_STATS */
5005 ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong)reqp, ret);
5006 return ret;
5007}
5008
5009#ifdef CONFIG_PROC_FS 4590#ifdef CONFIG_PROC_FS
5010/* 4591/*
5011 * asc_prt_board_devices() 4592 * asc_prt_board_devices()
@@ -6465,79 +6046,6 @@ static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
6465 6046
6466 return totlen; 6047 return totlen;
6467} 6048}
6468
6469/*
6470 * asc_prt_target_stats()
6471 *
6472 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
6473 * cf. asc_prt_line().
6474 *
6475 * This is separated from asc_prt_board_stats because a full set
6476 * of targets will overflow ASC_PRTBUF_SIZE.
6477 *
6478 * Return the number of characters copied into 'cp'. No more than
6479 * 'cplen' characters will be copied to 'cp'.
6480 */
6481static int
6482asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen)
6483{
6484 int leftlen;
6485 int totlen;
6486 int len;
6487 struct asc_stats *s;
6488 ushort chip_scsi_id;
6489 asc_board_t *boardp;
6490 asc_queue_t *active;
6491
6492 leftlen = cplen;
6493 totlen = len = 0;
6494
6495 boardp = ASC_BOARDP(shost);
6496 s = &boardp->asc_stats;
6497
6498 active = &ASC_BOARDP(shost)->active;
6499
6500 if (ASC_NARROW_BOARD(boardp)) {
6501 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
6502 } else {
6503 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
6504 }
6505
6506 if ((chip_scsi_id == tgt_id) ||
6507 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) {
6508 return 0;
6509 }
6510
6511 do {
6512 if (active->q_tot_cnt[tgt_id] > 0) {
6513 len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id);
6514 ASC_PRT_NEXT();
6515
6516 len = asc_prt_line(cp, leftlen,
6517 " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
6518 active->q_cur_cnt[tgt_id],
6519 active->q_max_cnt[tgt_id],
6520 active->q_tot_cnt[tgt_id],
6521 active->q_min_tim[tgt_id],
6522 active->q_max_tim[tgt_id],
6523 (active->q_tot_cnt[tgt_id] ==
6524 0) ? 0 : (active->
6525 q_tot_tim[tgt_id] /
6526 active->
6527 q_tot_cnt[tgt_id]),
6528 (active->q_tot_cnt[tgt_id] ==
6529 0) ? 0 : ASC_TENTHS(active->
6530 q_tot_tim
6531 [tgt_id],
6532 active->
6533 q_tot_cnt
6534 [tgt_id]));
6535 ASC_PRT_NEXT();
6536 }
6537 } while (0);
6538
6539 return totlen;
6540}
6541#endif /* CONFIG_PROC_FS */ 6049#endif /* CONFIG_PROC_FS */
6542#endif /* ADVANSYS_STATS */ 6050#endif /* ADVANSYS_STATS */
6543 6051