1/* 2 * Copyright (c) 2004-07 Applied Micro Circuits Corporation. 3 * Copyright (c) 2004-05 Vinod Kashyap 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * |
27 * $FreeBSD: head/sys/dev/twa/tw_cl_misc.c 212008 2010-08-30 19:15:04Z delphij $ |
28 */ 29 30/* 31 * AMCC'S 3ware driver for 9000 series storage controllers. 32 * 33 * Author: Vinod Kashyap 34 * Modifications by: Adam Radford 35 * Modifications by: Manjunath Ranganathaiah --- 42 unchanged lines hidden (view full) --- 78tw_cli_drain_complete_queue(struct tw_cli_ctlr_context *ctlr) 79{ 80 struct tw_cli_req_context *req; 81 struct tw_cl_req_packet *req_pkt; 82 83 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 84 85 /* Walk the busy queue. */ |
86 while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) != 87 TW_CL_NULL) { |
88 if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) { 89 /* 90 * It's an internal request. Set the appropriate 91 * error and call the CL internal callback if there's 92 * one. If the request originator is polling for 93 * completion, he should be checking req->error to 94 * determine that the request did not go through. 95 * The request originators are responsible for the 96 * clean-up. 97 */ 98 req->error_code = TW_CL_ERR_REQ_BUS_RESET; 99 if (req->tw_cli_callback) 100 req->tw_cli_callback(req); |
101 } else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) { 102 /* It's a passthru request. Complete it. */ 103 if ((req_pkt = req->orig_req) != TW_CL_NULL) { |
104 req_pkt->status = TW_CL_ERR_REQ_BUS_RESET; |
105 106 if (req_pkt->tw_osl_callback) 107 req_pkt->tw_osl_callback(req->req_handle); |
108 } 109 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); |
110 } else { 111 /* It's an external (SCSI) request. Add it to the reset queue. */ 112 tw_osl_untimeout(req->req_handle); 113 tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q); |
114 } |
115 } /* End of while loop */ |
116} 117 118 119 120/* 121 * Function name: tw_cli_drain_busy_queue 122 * Description: This function gets called during a controller reset. 123 * It errors back to the OS Layer, all those requests that --- 8 unchanged lines hidden (view full) --- 132tw_cli_drain_busy_queue(struct tw_cli_ctlr_context *ctlr) 133{ 134 struct tw_cli_req_context *req; 135 struct tw_cl_req_packet *req_pkt; 136 137 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 138 139 /* Walk the busy queue. */ |
140 while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_BUSY_Q)) != 141 TW_CL_NULL) { |
142 if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) { 143 /* 144 * It's an internal request. Set the appropriate 145 * error and call the CL internal callback if there's 146 * one. If the request originator is polling for 147 * completion, he should be checking req->error to 148 * determine that the request did not go through. 149 * The request originators are responsible for the 150 * clean-up. 151 */ 152 req->error_code = TW_CL_ERR_REQ_BUS_RESET; 153 if (req->tw_cli_callback) 154 req->tw_cli_callback(req); |
155 } else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) { 156 /* It's a passthru request. Complete it. */ 157 if ((req_pkt = req->orig_req) != TW_CL_NULL) { |
158 req_pkt->status = TW_CL_ERR_REQ_BUS_RESET; |
159 160 if (req_pkt->tw_osl_callback) 161 req_pkt->tw_osl_callback(req->req_handle); |
162 } 163 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); |
164 } else { 165 /* It's an external (SCSI) request. Add it to the reset queue. */ 166 tw_osl_untimeout(req->req_handle); 167 tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q); |
168 } |
169 } /* End of while loop */ |
170} 171 172 173 174/* 175 * Function name: tw_cli_drain_pending_queue 176 * Description: This function gets called during a controller reset. 177 * It errors back to the OS Layer, all those requests that --- 10 unchanged lines hidden (view full) --- 188 struct tw_cli_req_context *req; 189 struct tw_cl_req_packet *req_pkt; 190 191 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 192 193 /* 194 * Pull requests off the pending queue, and complete them. 195 */ |
196 while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) != 197 TW_CL_NULL) { |
198 if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) { 199 /* 200 * It's an internal request. Set the appropriate 201 * error and call the CL internal callback if there's 202 * one. If the request originator is polling for 203 * completion, he should be checking req->error to 204 * determine that the request did not go through. 205 * The request originators are responsible for the 206 * clean-up. 207 */ 208 req->error_code = TW_CL_ERR_REQ_BUS_RESET; 209 if (req->tw_cli_callback) 210 req->tw_cli_callback(req); |
211 } else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) { 212 /* It's a passthru request. Complete it. */ 213 if ((req_pkt = req->orig_req) != TW_CL_NULL) { |
214 req_pkt->status = TW_CL_ERR_REQ_BUS_RESET; |
215 216 if (req_pkt->tw_osl_callback) 217 req_pkt->tw_osl_callback(req->req_handle); |
218 } 219 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); |
220 } else { 221 /* It's an external (SCSI) request. Add it to the reset queue. */ 222 tw_osl_untimeout(req->req_handle); 223 tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q); |
224 } |
225 } /* End of while loop */ |
226} 227 228 229 230/* 231 * Function name: tw_cli_drain_response_queue 232 * Description: Drain the controller response queue. 233 * --- 8 unchanged lines hidden (view full) --- 242 TW_UINT32 resp; 243 TW_UINT32 status_reg; 244 245 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 246 247 for (;;) { 248 status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle); 249 |
250 if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY) 251 return(TW_OSL_ESUCCESS); /* no more response queue entries */ 252 253 resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle); 254 } 255} 256 257 --- 15 unchanged lines hidden (view full) --- 273 TW_INT32 resp_id; 274 TW_UINT32 status_reg; 275 276 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 277 278 for (;;) { 279 status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle); 280 |
281 if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY) 282 return(TW_OSL_ENOTTY); /* no more response queue entries */ 283 284 if (ctlr->device_id == TW_CL_DEVICE_ID_9K) { 285 resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle); 286 resp_id = GET_RESP_ID(resp); 287 } else { 288 resp = TW_CLI_READ_LARGE_RESPONSE_QUEUE( --- 64 unchanged lines hidden (view full) --- 353 354 if (req->state != TW_CLI_REQ_STATE_COMPLETE) { 355 error = TW_OSL_ETIMEDOUT; 356 break; 357 } 358 359 if ((error = req->cmd_pkt->command.cmd_pkt_9k.status)) { 360 cmd_hdr = &req->cmd_pkt->cmd_hdr; |
361#if 0 |
362 tw_cli_create_ctlr_event(ctlr, 363 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, 364 cmd_hdr); |
365#endif // 0 |
366 break; 367 } 368 369 aen_code = tw_cli_manage_aen(ctlr, req); 370 if (aen_code == TWA_AEN_QUEUE_EMPTY) 371 break; 372 if (aen_code == TWA_AEN_SYNC_TIME_WITH_HOST) 373 continue; --- 339 unchanged lines hidden (view full) --- 713 tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 714 715 /* Check if the 'micro-controller ready' bit is not set. */ 716 if (!(status_reg & TWA_STATUS_MICROCONTROLLER_READY)) { 717 TW_INT8 desc[200]; 718 719 tw_osl_memzero(desc, 200); 720 if (!(ctlr->reset_phase1_in_progress)) { |
721 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, |
722 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT, 723 0x1301, 0x1, TW_CL_SEVERITY_ERROR_STRING, 724 "Missing expected status bit(s)", 725 "status reg = 0x%x; Missing bits: %s", 726 status_reg, 727 tw_cli_describe_bits( 728 TWA_STATUS_MICROCONTROLLER_READY, 729 desc)); --- 7 unchanged lines hidden (view full) --- 737 738 tw_osl_memzero(desc, 200); 739 740 /* Skip queue error msgs during 9650SE/9690SA reset */ 741 if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) && 742 (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) || 743 (!(ctlr->reset_in_progress)) || 744 ((status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) == 0)) |
745 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, |
746 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT, 747 0x1302, 0x1, TW_CL_SEVERITY_ERROR_STRING, 748 "Unexpected status bit(s)", 749 "status reg = 0x%x Unexpected bits: %s", 750 status_reg & TWA_STATUS_UNEXPECTED_BITS, 751 tw_cli_describe_bits(status_reg & 752 TWA_STATUS_UNEXPECTED_BITS, desc)); 753 754 if (status_reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT) { |
755 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, |
756 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT, 757 0x1303, 0x1, TW_CL_SEVERITY_ERROR_STRING, 758 "PCI parity error: clearing... " 759 "Re-seat/move/replace card", 760 "status reg = 0x%x %s", 761 status_reg, 762 tw_cli_describe_bits(status_reg, desc)); 763 TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle, 764 TWA_CONTROL_CLEAR_PARITY_ERROR); 765 766#ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE 767 tw_osl_write_pci_config(ctlr->ctlr_handle, 768 TW_CLI_PCI_CONFIG_STATUS_OFFSET, 769 TWA_PCI_CONFIG_CLEAR_PARITY_ERROR, 2); 770#endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */ 771 772 } 773 774 if (status_reg & TWA_STATUS_PCI_ABORT_INTERRUPT) { |
775 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, |
776 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT, 777 0x1304, 0x1, TW_CL_SEVERITY_ERROR_STRING, 778 "PCI abort: clearing... ", 779 "status reg = 0x%x %s", 780 status_reg, 781 tw_cli_describe_bits(status_reg, desc)); 782 TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle, 783 TWA_CONTROL_CLEAR_PCI_ABORT); --- 6 unchanged lines hidden (view full) --- 790 791 } 792 793 if (status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) { 794 /* Skip queue error msgs during 9650SE/9690SA reset */ 795 if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) && 796 (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) || 797 (!(ctlr->reset_in_progress))) |
798 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, |
799 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT, 800 0x1305, 0x1, TW_CL_SEVERITY_ERROR_STRING, 801 "Controller queue error: clearing... ", 802 "status reg = 0x%x %s", 803 status_reg, 804 tw_cli_describe_bits(status_reg, desc)); 805 TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle, 806 TWA_CONTROL_CLEAR_QUEUE_ERROR); 807 } |
808 } 809 return(error); 810} 811 812 813 814/* 815 * Function name: tw_cli_describe_bits --- 22 unchanged lines hidden (view full) --- 838 if (reg & TWA_STATUS_COMMAND_INTERRUPT) 839 tw_osl_strcpy(&str[tw_osl_strlen(str)], "CMD_INTR,"); 840 if (reg & TWA_STATUS_ATTENTION_INTERRUPT) 841 tw_osl_strcpy(&str[tw_osl_strlen(str)], "ATTN_INTR,"); 842 if (reg & TWA_STATUS_HOST_INTERRUPT) 843 tw_osl_strcpy(&str[tw_osl_strlen(str)], "HOST_INTR,"); 844 if (reg & TWA_STATUS_PCI_ABORT_INTERRUPT) 845 tw_osl_strcpy(&str[tw_osl_strlen(str)], "PCI_ABRT,"); |
846 if (reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) 847 tw_osl_strcpy(&str[tw_osl_strlen(str)], "Q_ERR,"); 848 if (reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT) 849 tw_osl_strcpy(&str[tw_osl_strlen(str)], "PCI_PERR"); 850 851 tw_osl_strcpy(&str[tw_osl_strlen(str)], "]"); 852 return(str); 853} --- 177 unchanged lines hidden --- |