isci: move core/controller to host
[pandora-kernel.git] / drivers / scsi / isci / unsolicited_frame_control.c
1 /*
2  * This file is provided under a dual BSD/GPLv2 license.  When using or
3  * redistributing this file, you may do so under either license.
4  *
5  * GPL LICENSE SUMMARY
6  *
7  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of version 2 of the GNU General Public License as
11  * published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21  * The full GNU General Public License is included in this distribution
22  * in the file called LICENSE.GPL.
23  *
24  * BSD LICENSE
25  *
26  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27  * All rights reserved.
28  *
29  * Redistribution and use in source and binary forms, with or without
30  * modification, are permitted provided that the following conditions
31  * are met:
32  *
33  *   * Redistributions of source code must retain the above copyright
34  *     notice, this list of conditions and the following disclaimer.
35  *   * Redistributions in binary form must reproduce the above copyright
36  *     notice, this list of conditions and the following disclaimer in
37  *     the documentation and/or other materials provided with the
38  *     distribution.
39  *   * Neither the name of Intel Corporation nor the names of its
40  *     contributors may be used to endorse or promote products derived
41  *     from this software without specific prior written permission.
42  *
43  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54  */
55
56 #include "host.h"
57 #include "unsolicited_frame_control.h"
58 #include "registers.h"
59 #include "sci_util.h"
60
61 /**
62  * This method will program the unsolicited frames (UFs) into the UF address
63  *    table and construct the UF frame structure being modeled in the core.  It
64  *    will handle the case where some of the UFs are not being used and thus
65  *    should have entries programmed to zero in the address table.
66  * @uf_control: This parameter specifies the unsolicted frame control object
67  *    for which to construct the unsolicited frames objects.
68  * @uf_buffer_phys_address: This parameter specifies the physical address for
69  *    the first unsolicited frame buffer.
70  * @uf_buffer_virt_address: This parameter specifies the virtual address for
71  *    the first unsolicited frame buffer.
72  * @unused_uf_header_entries: This parameter specifies the number of unused UF
73  *    headers.  This value can be non-zero when there are a non-power of 2
74  *    number of unsolicited frames being supported.
75  * @used_uf_header_entries: This parameter specifies the number of actually
76  *    utilized UF headers.
77  *
78  */
79 static void scic_sds_unsolicited_frame_control_construct_frames(
80         struct scic_sds_unsolicited_frame_control *uf_control,
81         dma_addr_t uf_buffer_phys_address,
82         void *uf_buffer_virt_address,
83         u32 unused_uf_header_entries,
84         u32 used_uf_header_entries)
85 {
86         u32 index;
87         struct scic_sds_unsolicited_frame *uf;
88
89         /*
90          * Program the unused buffers into the UF address table and the
91          * controller's array of UFs.
92          */
93         for (index = 0; index < unused_uf_header_entries; index++) {
94                 uf = &uf_control->buffers.array[index];
95
96                 sci_cb_make_physical_address(
97                         uf_control->address_table.array[index], 0, 0
98                         );
99                 uf->buffer = NULL;
100                 uf->header = &uf_control->headers.array[index];
101                 uf->state  = UNSOLICITED_FRAME_EMPTY;
102         }
103
104         /*
105          * Program the actual used UF buffers into the UF address table and
106          * the controller's array of UFs.
107          */
108         for (index = unused_uf_header_entries;
109              index < unused_uf_header_entries + used_uf_header_entries;
110              index++) {
111                 uf = &uf_control->buffers.array[index];
112
113                 uf_control->address_table.array[index] = uf_buffer_phys_address;
114
115                 uf->buffer = uf_buffer_virt_address;
116                 uf->header = &uf_control->headers.array[index];
117                 uf->state  = UNSOLICITED_FRAME_EMPTY;
118
119                 /*
120                  * Increment the address of the physical and virtual memory
121                  * pointers. Everything is aligned on 1k boundary with an
122                  * increment of 1k.
123                  */
124                 uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
125                 uf_buffer_phys_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
126         }
127 }
128
129 int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic)
130 {
131         struct scic_sds_unsolicited_frame_control *uf_control = &scic->uf_control;
132         u32 unused_uf_header_entries;
133         u32 used_uf_header_entries;
134         u32 used_uf_buffer_bytes;
135         u32 unused_uf_header_bytes;
136         u32 used_uf_header_bytes;
137         dma_addr_t uf_buffer_phys_address;
138         void *uf_buffer_virt_address;
139         size_t size;
140
141         /*
142          * The UF buffer address table size must be programmed to a power
143          * of 2.  Find the first power of 2 that is equal to or greater then
144          * the number of unsolicited frame buffers to be utilized.
145          */
146         uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES;
147         while (uf_control->address_table.count < uf_control->buffers.count &&
148                uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES)
149                 uf_control->address_table.count <<= 1;
150
151         /*
152          * Prepare all of the memory sizes for the UF headers, UF address
153          * table, and UF buffers themselves.
154          */
155         used_uf_buffer_bytes     = uf_control->buffers.count
156                                    * SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
157         unused_uf_header_entries = uf_control->address_table.count
158                                    - uf_control->buffers.count;
159         used_uf_header_entries   = uf_control->buffers.count;
160         unused_uf_header_bytes   = unused_uf_header_entries
161                                    * sizeof(struct scu_unsolicited_frame_header);
162         used_uf_header_bytes     = used_uf_header_entries
163                                    * sizeof(struct scu_unsolicited_frame_header);
164
165         size = used_uf_buffer_bytes + used_uf_header_bytes +
166                         uf_control->address_table.count * sizeof(dma_addr_t);
167
168
169         /*
170          * The Unsolicited Frame buffers are set at the start of the UF
171          * memory descriptor entry. The headers and address table will be
172          * placed after the buffers.
173          */
174         uf_buffer_virt_address = dmam_alloc_coherent(scic_to_dev(scic), size,
175                                                         &uf_buffer_phys_address, GFP_KERNEL);
176         if (!uf_buffer_virt_address)
177                 return -ENOMEM;
178
179         /*
180          * Program the location of the UF header table into the SCU.
181          * Notes:
182          * - The address must align on a 64-byte boundary. Guaranteed to be
183          *   on 64-byte boundary already 1KB boundary for unsolicited frames.
184          * - Program unused header entries to overlap with the last
185          *   unsolicited frame.  The silicon will never DMA to these unused
186          *   headers, since we program the UF address table pointers to
187          *   NULL.
188          */
189         uf_control->headers.physical_address =
190                                 uf_buffer_phys_address +
191                                 used_uf_buffer_bytes -
192                                 unused_uf_header_bytes;
193
194         uf_control->headers.array =
195                                 uf_buffer_virt_address +
196                                 used_uf_buffer_bytes -
197                                 unused_uf_header_bytes;
198
199         /*
200          * Program the location of the UF address table into the SCU.
201          * Notes:
202          * - The address must align on a 64-bit boundary. Guaranteed to be on 64
203          *   byte boundary already due to above programming headers being on a
204          *   64-bit boundary and headers are on a 64-bytes in size.
205          */
206         uf_control->address_table.physical_address =
207                                 uf_buffer_phys_address +
208                                 used_uf_buffer_bytes +
209                                 used_uf_header_bytes;
210
211         uf_control->address_table.array =
212                                 uf_buffer_virt_address +
213                                 used_uf_buffer_bytes +
214                                 used_uf_header_bytes;
215
216         uf_control->get = 0;
217
218         /*
219          * UF buffer requirements are:
220          * - The last entry in the UF queue is not NULL.
221          * - There is a power of 2 number of entries (NULL or not-NULL)
222          *   programmed into the queue.
223          * - Aligned on a 1KB boundary. */
224
225         /*
226          * If the user provided less then the maximum amount of memory,
227          * then be sure that we programm the first entries in the UF
228          * address table to NULL. */
229         scic_sds_unsolicited_frame_control_construct_frames(
230                 uf_control,
231                 uf_buffer_phys_address,
232                 uf_buffer_virt_address,
233                 unused_uf_header_entries,
234                 used_uf_header_entries
235                 );
236
237         return 0;
238 }
239
240 /**
241  * This method returns the frame header for the specified frame index.
242  * @uf_control:
243  * @frame_index:
244  * @frame_header:
245  *
246  * enum sci_status
247  */
248 enum sci_status scic_sds_unsolicited_frame_control_get_header(
249         struct scic_sds_unsolicited_frame_control *uf_control,
250         u32 frame_index,
251         void **frame_header)
252 {
253         if (frame_index < uf_control->address_table.count) {
254                 /*
255                  * Skip the first word in the frame since this is a controll word used
256                  * by the hardware. */
257                 *frame_header = &uf_control->buffers.array[frame_index].header->data;
258
259                 return SCI_SUCCESS;
260         }
261
262         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
263 }
264
265 /**
266  * This method returns the frame buffer for the specified frame index.
267  * @uf_control:
268  * @frame_index:
269  * @frame_buffer:
270  *
271  * enum sci_status
272  */
273 enum sci_status scic_sds_unsolicited_frame_control_get_buffer(
274         struct scic_sds_unsolicited_frame_control *uf_control,
275         u32 frame_index,
276         void **frame_buffer)
277 {
278         if (frame_index < uf_control->address_table.count) {
279                 *frame_buffer = uf_control->buffers.array[frame_index].buffer;
280
281                 return SCI_SUCCESS;
282         }
283
284         return SCI_FAILURE_INVALID_PARAMETER_VALUE;
285 }
286
287 /**
288  * This method releases the frame once this is done the frame is available for
289  *    re-use by the hardware.  The data contained in the frame header and frame
290  *    buffer is no longer valid.
291  * @uf_control: This parameter specifies the UF control object
292  * @frame_index: This parameter specifies the frame index to attempt to release.
293  *
294  * This method returns an indication to the caller as to whether the
295  * unsolicited frame get pointer should be updated.
296  */
297 bool scic_sds_unsolicited_frame_control_release_frame(
298         struct scic_sds_unsolicited_frame_control *uf_control,
299         u32 frame_index)
300 {
301         u32 frame_get;
302         u32 frame_cycle;
303
304         frame_get   = uf_control->get & (uf_control->address_table.count - 1);
305         frame_cycle = uf_control->get & uf_control->address_table.count;
306
307         /*
308          * In the event there are NULL entries in the UF table, we need to
309          * advance the get pointer in order to find out if this frame should
310          * be released (i.e. update the get pointer). */
311         while (((lower_32_bits(uf_control->address_table.array[frame_get])
312                                         == 0) &&
313                 (upper_32_bits(uf_control->address_table.array[frame_get])
314                                         == 0)) &&
315                (frame_get < uf_control->address_table.count))
316                 frame_get++;
317
318         /*
319          * The table has a NULL entry as it's last element.  This is
320          * illegal. */
321         BUG_ON(frame_get >= uf_control->address_table.count);
322
323         if (frame_index < uf_control->address_table.count) {
324                 uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED;
325
326                 /*
327                  * The frame index is equal to the current get pointer so we
328                  * can now free up all of the frame entries that */
329                 if (frame_get == frame_index) {
330                         while (
331                                 uf_control->buffers.array[frame_get].state
332                                 == UNSOLICITED_FRAME_RELEASED
333                                 ) {
334                                 uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY;
335
336                                 INCREMENT_QUEUE_GET(
337                                         frame_get,
338                                         frame_cycle,
339                                         uf_control->address_table.count - 1,
340                                         uf_control->address_table.count
341                                         );
342                         }
343
344                         uf_control->get =
345                                 (SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get);
346
347                         return true;
348                 } else {
349                         /*
350                          * Frames remain in use until we advance the get pointer
351                          * so there is nothing we can do here */
352                 }
353         }
354
355         return false;
356 }
357