aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/advansys.c
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2007-09-09 10:56:34 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:47:56 -0400
commit349d2c44291d922614a273e9a4e6b43ee17c103d (patch)
treec61309490c7a1647cefe52aee41ab4c7b0752b80 /drivers/scsi/advansys.c
parent6ed1ef0786094f06d2462aeeb6ad7bf9f5f9fc18 (diff)
[SCSI] advansys: Remove `active' queue and all remaining internal queueing code
The `active' list was used in the reset handler -- but the midlayer guarantees that list is empty by the time the reset handler is invoked. It was also checked in the interrupt routines to be sure that this command belonged to this board, but we don't need to check that either. We can then delete the asc_prt_target_stats() function as it will never print anything, along with asc_enqueue(), asc_dequeue_list(), asc_rmqueue(), asc_scsi_done_list(), struct asc_queue, ASC_QUEUE_EMPTY, ASC_TID_ALL, ASC_FRONT, ASC_BACK, and all the REQ* macros. Also remove this item from the todo list. Signed-off-by: Matthew Wilcox <matthew@wil.cx> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/advansys.c')
-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