![]() |
|
|||
0001 /* 0002 * This file is provided under a dual BSD/GPLv2 license. When using or 0003 * redistributing this file, you may do so under either license. 0004 * 0005 * GPL LICENSE SUMMARY 0006 * 0007 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 0008 * 0009 * This program is free software; you can redistribute it and/or modify 0010 * it under the terms of version 2 of the GNU General Public License as 0011 * published by the Free Software Foundation. 0012 * 0013 * This program is distributed in the hope that it will be useful, but 0014 * WITHOUT ANY WARRANTY; without even the implied warranty of 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 * General Public License for more details. 0017 * 0018 * You should have received a copy of the GNU General Public License 0019 * along with this program; if not, write to the Free Software 0020 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 0021 * The full GNU General Public License is included in this distribution 0022 * in the file called LICENSE.GPL. 0023 * 0024 * BSD LICENSE 0025 * 0026 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 0027 * All rights reserved. 0028 * 0029 * Redistribution and use in source and binary forms, with or without 0030 * modification, are permitted provided that the following conditions 0031 * are met: 0032 * 0033 * * Redistributions of source code must retain the above copyright 0034 * notice, this list of conditions and the following disclaimer. 0035 * * Redistributions in binary form must reproduce the above copyright 0036 * notice, this list of conditions and the following disclaimer in 0037 * the documentation and/or other materials provided with the 0038 * distribution. 0039 * * Neither the name of Intel Corporation nor the names of its 0040 * contributors may be used to endorse or promote products derived 0041 * from this software without specific prior written permission. 0042 * 0043 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 0044 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 0045 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 0046 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 0047 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 0048 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 0049 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0050 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0051 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0052 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 0053 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0054 */ 0055 0056 #include "host.h" 0057 #include "unsolicited_frame_control.h" 0058 #include "registers.h" 0059 0060 void sci_unsolicited_frame_control_construct(struct isci_host *ihost) 0061 { 0062 struct sci_unsolicited_frame_control *uf_control = &ihost->uf_control; 0063 struct sci_unsolicited_frame *uf; 0064 dma_addr_t dma = ihost->ufi_dma; 0065 void *virt = ihost->ufi_buf; 0066 int i; 0067 0068 /* 0069 * The Unsolicited Frame buffers are set at the start of the UF 0070 * memory descriptor entry. The headers and address table will be 0071 * placed after the buffers. 0072 */ 0073 0074 /* 0075 * Program the location of the UF header table into the SCU. 0076 * Notes: 0077 * - The address must align on a 64-byte boundary. Guaranteed to be 0078 * on 64-byte boundary already 1KB boundary for unsolicited frames. 0079 * - Program unused header entries to overlap with the last 0080 * unsolicited frame. The silicon will never DMA to these unused 0081 * headers, since we program the UF address table pointers to 0082 * NULL. 0083 */ 0084 uf_control->headers.physical_address = dma + SCI_UFI_BUF_SIZE; 0085 uf_control->headers.array = virt + SCI_UFI_BUF_SIZE; 0086 0087 /* 0088 * Program the location of the UF address table into the SCU. 0089 * Notes: 0090 * - The address must align on a 64-bit boundary. Guaranteed to be on 64 0091 * byte boundary already due to above programming headers being on a 0092 * 64-bit boundary and headers are on a 64-bytes in size. 0093 */ 0094 uf_control->address_table.physical_address = dma + SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE; 0095 uf_control->address_table.array = virt + SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE; 0096 uf_control->get = 0; 0097 0098 /* 0099 * UF buffer requirements are: 0100 * - The last entry in the UF queue is not NULL. 0101 * - There is a power of 2 number of entries (NULL or not-NULL) 0102 * programmed into the queue. 0103 * - Aligned on a 1KB boundary. */ 0104 0105 /* 0106 * Program the actual used UF buffers into the UF address table and 0107 * the controller's array of UFs. 0108 */ 0109 for (i = 0; i < SCU_MAX_UNSOLICITED_FRAMES; i++) { 0110 uf = &uf_control->buffers.array[i]; 0111 0112 uf_control->address_table.array[i] = dma; 0113 0114 uf->buffer = virt; 0115 uf->header = &uf_control->headers.array[i]; 0116 uf->state = UNSOLICITED_FRAME_EMPTY; 0117 0118 /* 0119 * Increment the address of the physical and virtual memory 0120 * pointers. Everything is aligned on 1k boundary with an 0121 * increment of 1k. 0122 */ 0123 virt += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; 0124 dma += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; 0125 } 0126 } 0127 0128 enum sci_status sci_unsolicited_frame_control_get_header(struct sci_unsolicited_frame_control *uf_control, 0129 u32 frame_index, 0130 void **frame_header) 0131 { 0132 if (frame_index < SCU_MAX_UNSOLICITED_FRAMES) { 0133 /* Skip the first word in the frame since this is a controll word used 0134 * by the hardware. 0135 */ 0136 *frame_header = &uf_control->buffers.array[frame_index].header->data; 0137 0138 return SCI_SUCCESS; 0139 } 0140 0141 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 0142 } 0143 0144 enum sci_status sci_unsolicited_frame_control_get_buffer(struct sci_unsolicited_frame_control *uf_control, 0145 u32 frame_index, 0146 void **frame_buffer) 0147 { 0148 if (frame_index < SCU_MAX_UNSOLICITED_FRAMES) { 0149 *frame_buffer = uf_control->buffers.array[frame_index].buffer; 0150 0151 return SCI_SUCCESS; 0152 } 0153 0154 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 0155 } 0156 0157 bool sci_unsolicited_frame_control_release_frame(struct sci_unsolicited_frame_control *uf_control, 0158 u32 frame_index) 0159 { 0160 u32 frame_get; 0161 u32 frame_cycle; 0162 0163 frame_get = uf_control->get & (SCU_MAX_UNSOLICITED_FRAMES - 1); 0164 frame_cycle = uf_control->get & SCU_MAX_UNSOLICITED_FRAMES; 0165 0166 /* 0167 * In the event there are NULL entries in the UF table, we need to 0168 * advance the get pointer in order to find out if this frame should 0169 * be released (i.e. update the get pointer) 0170 */ 0171 while (lower_32_bits(uf_control->address_table.array[frame_get]) == 0 && 0172 upper_32_bits(uf_control->address_table.array[frame_get]) == 0 && 0173 frame_get < SCU_MAX_UNSOLICITED_FRAMES) 0174 frame_get++; 0175 0176 /* 0177 * The table has a NULL entry as it's last element. This is 0178 * illegal. 0179 */ 0180 BUG_ON(frame_get >= SCU_MAX_UNSOLICITED_FRAMES); 0181 if (frame_index >= SCU_MAX_UNSOLICITED_FRAMES) 0182 return false; 0183 0184 uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED; 0185 0186 if (frame_get != frame_index) { 0187 /* 0188 * Frames remain in use until we advance the get pointer 0189 * so there is nothing we can do here 0190 */ 0191 return false; 0192 } 0193 0194 /* 0195 * The frame index is equal to the current get pointer so we 0196 * can now free up all of the frame entries that 0197 */ 0198 while (uf_control->buffers.array[frame_get].state == UNSOLICITED_FRAME_RELEASED) { 0199 uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY; 0200 0201 if (frame_get+1 == SCU_MAX_UNSOLICITED_FRAMES-1) { 0202 frame_cycle ^= SCU_MAX_UNSOLICITED_FRAMES; 0203 frame_get = 0; 0204 } else 0205 frame_get++; 0206 } 0207 0208 uf_control->get = SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get; 0209 0210 return true; 0211 }
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |