Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
scsi
isci
unsolicited_frame_control.c
Go to the documentation of this file.
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
60
void
sci_unsolicited_frame_control_construct
(
struct
isci_host
*ihost)
61
{
62
struct
sci_unsolicited_frame_control
*uf_control = &ihost->
uf_control
;
63
struct
sci_unsolicited_frame
*uf;
64
dma_addr_t
dma
= ihost->
ufi_dma
;
65
void
*virt = ihost->
ufi_buf
;
66
int
i
;
67
68
/*
69
* The Unsolicited Frame buffers are set at the start of the UF
70
* memory descriptor entry. The headers and address table will be
71
* placed after the buffers.
72
*/
73
74
/*
75
* Program the location of the UF header table into the SCU.
76
* Notes:
77
* - The address must align on a 64-byte boundary. Guaranteed to be
78
* on 64-byte boundary already 1KB boundary for unsolicited frames.
79
* - Program unused header entries to overlap with the last
80
* unsolicited frame. The silicon will never DMA to these unused
81
* headers, since we program the UF address table pointers to
82
* NULL.
83
*/
84
uf_control->
headers
.physical_address = dma +
SCI_UFI_BUF_SIZE
;
85
uf_control->
headers
.array = virt +
SCI_UFI_BUF_SIZE
;
86
87
/*
88
* Program the location of the UF address table into the SCU.
89
* Notes:
90
* - The address must align on a 64-bit boundary. Guaranteed to be on 64
91
* byte boundary already due to above programming headers being on a
92
* 64-bit boundary and headers are on a 64-bytes in size.
93
*/
94
uf_control->
address_table
.physical_address = dma + SCI_UFI_BUF_SIZE +
SCI_UFI_HDR_SIZE
;
95
uf_control->
address_table
.array = virt + SCI_UFI_BUF_SIZE +
SCI_UFI_HDR_SIZE
;
96
uf_control->
get
= 0;
97
98
/*
99
* UF buffer requirements are:
100
* - The last entry in the UF queue is not NULL.
101
* - There is a power of 2 number of entries (NULL or not-NULL)
102
* programmed into the queue.
103
* - Aligned on a 1KB boundary. */
104
105
/*
106
* Program the actual used UF buffers into the UF address table and
107
* the controller's array of UFs.
108
*/
109
for
(i = 0; i <
SCU_MAX_UNSOLICITED_FRAMES
; i++) {
110
uf = &uf_control->
buffers
.array[
i
];
111
112
uf_control->
address_table
.array[
i
] =
dma
;
113
114
uf->
buffer
= virt;
115
uf->
header
= &uf_control->
headers
.array[
i
];
116
uf->
state
=
UNSOLICITED_FRAME_EMPTY
;
117
118
/*
119
* Increment the address of the physical and virtual memory
120
* pointers. Everything is aligned on 1k boundary with an
121
* increment of 1k.
122
*/
123
virt +=
SCU_UNSOLICITED_FRAME_BUFFER_SIZE
;
124
dma +=
SCU_UNSOLICITED_FRAME_BUFFER_SIZE
;
125
}
126
}
127
128
enum
sci_status
sci_unsolicited_frame_control_get_header
(
struct
sci_unsolicited_frame_control
*uf_control,
129
u32
frame_index
,
130
void
**frame_header)
131
{
132
if
(frame_index <
SCU_MAX_UNSOLICITED_FRAMES
) {
133
/* Skip the first word in the frame since this is a controll word used
134
* by the hardware.
135
*/
136
*frame_header = &uf_control->
buffers
.array[
frame_index
].header->data;
137
138
return
SCI_SUCCESS
;
139
}
140
141
return
SCI_FAILURE_INVALID_PARAMETER_VALUE
;
142
}
143
144
enum
sci_status
sci_unsolicited_frame_control_get_buffer
(
struct
sci_unsolicited_frame_control
*uf_control,
145
u32
frame_index
,
146
void
**
frame_buffer
)
147
{
148
if
(frame_index <
SCU_MAX_UNSOLICITED_FRAMES
) {
149
*frame_buffer = uf_control->
buffers
.array[
frame_index
].buffer;
150
151
return
SCI_SUCCESS
;
152
}
153
154
return
SCI_FAILURE_INVALID_PARAMETER_VALUE
;
155
}
156
157
bool
sci_unsolicited_frame_control_release_frame
(
struct
sci_unsolicited_frame_control
*uf_control,
158
u32
frame_index
)
159
{
160
u32
frame_get;
161
u32
frame_cycle;
162
163
frame_get = uf_control->
get
& (
SCU_MAX_UNSOLICITED_FRAMES
- 1);
164
frame_cycle = uf_control->
get
&
SCU_MAX_UNSOLICITED_FRAMES
;
165
166
/*
167
* In the event there are NULL entries in the UF table, we need to
168
* advance the get pointer in order to find out if this frame should
169
* be released (i.e. update the get pointer)
170
*/
171
while
(
lower_32_bits
(uf_control->
address_table
.array[frame_get]) == 0 &&
172
upper_32_bits
(uf_control->
address_table
.array[frame_get]) == 0 &&
173
frame_get <
SCU_MAX_UNSOLICITED_FRAMES
)
174
frame_get++;
175
176
/*
177
* The table has a NULL entry as it's last element. This is
178
* illegal.
179
*/
180
BUG_ON
(frame_get >=
SCU_MAX_UNSOLICITED_FRAMES
);
181
if
(frame_index >=
SCU_MAX_UNSOLICITED_FRAMES
)
182
return
false
;
183
184
uf_control->
buffers
.array[
frame_index
].state =
UNSOLICITED_FRAME_RELEASED
;
185
186
if
(frame_get != frame_index) {
187
/*
188
* Frames remain in use until we advance the get pointer
189
* so there is nothing we can do here
190
*/
191
return
false
;
192
}
193
194
/*
195
* The frame index is equal to the current get pointer so we
196
* can now free up all of the frame entries that
197
*/
198
while
(uf_control->
buffers
.array[frame_get].state ==
UNSOLICITED_FRAME_RELEASED
) {
199
uf_control->
buffers
.array[frame_get].state =
UNSOLICITED_FRAME_EMPTY
;
200
201
if
(frame_get+1 ==
SCU_MAX_UNSOLICITED_FRAMES
-1) {
202
frame_cycle ^=
SCU_MAX_UNSOLICITED_FRAMES
;
203
frame_get = 0;
204
}
else
205
frame_get++;
206
}
207
208
uf_control->
get
=
SCU_UFQGP_GEN_BIT
(ENABLE_BIT) | frame_cycle | frame_get;
209
210
return
true
;
211
}
Generated on Thu Jan 10 2013 14:21:20 for Linux Kernel by
1.8.2