aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptspi.c
diff options
context:
space:
mode:
authorEric Moore <eric.moore@lsi.com>2007-01-29 11:43:17 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-02-02 21:49:42 -0500
commit5a9c47b1344b514758d5d7f193c672850390cc36 (patch)
treee51ee96d7984203a8990109d0c3c825668074e56 /drivers/message/fusion/mptspi.c
parent793955f549c710a1b0c18f823d5d710840747b15 (diff)
[SCSI] fusion - move SPI API over to mptspi.c
Move some functions that only apply to the mptspi module over from mptscsih.c Signed-off-by: Eric Moore <Eric.Moore@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/message/fusion/mptspi.c')
-rw-r--r--drivers/message/fusion/mptspi.c268
1 files changed, 267 insertions, 1 deletions
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index aec0c2fe221f..4896d7cc681a 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -95,6 +95,269 @@ static int mptspiDoneCtx = -1;
95static int mptspiTaskCtx = -1; 95static int mptspiTaskCtx = -1;
96static int mptspiInternalCtx = -1; /* Used only for internal commands */ 96static int mptspiInternalCtx = -1; /* Used only for internal commands */
97 97
98/**
99 * mptspi_setTargetNegoParms - Update the target negotiation
100 * parameters based on the the Inquiry data, adapter capabilities,
101 * and NVRAM settings
102 *
103 * @hd: Pointer to a SCSI Host Structure
104 * @vtarget: per target private data
105 * @sdev: SCSI device
106 *
107 **/
108static void
109mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
110 struct scsi_device *sdev)
111{
112 SpiCfgData *pspi_data = &hd->ioc->spi_data;
113 int id = (int) target->id;
114 int nvram;
115 u8 width = MPT_NARROW;
116 u8 factor = MPT_ASYNC;
117 u8 offset = 0;
118 u8 nfactor;
119 u8 noQas = 1;
120
121 target->negoFlags = pspi_data->noQas;
122
123 if (sdev->scsi_level < SCSI_2) {
124 width = 0;
125 factor = MPT_ULTRA2;
126 offset = pspi_data->maxSyncOffset;
127 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
128 } else {
129 if (scsi_device_wide(sdev))
130 width = 1;
131
132 if (scsi_device_sync(sdev)) {
133 factor = pspi_data->minSyncFactor;
134 if (!scsi_device_dt(sdev))
135 factor = MPT_ULTRA2;
136 else {
137 if (!scsi_device_ius(sdev) &&
138 !scsi_device_qas(sdev))
139 factor = MPT_ULTRA160;
140 else {
141 factor = MPT_ULTRA320;
142 if (scsi_device_qas(sdev)) {
143 ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
144 noQas = 0;
145 }
146 if (sdev->type == TYPE_TAPE &&
147 scsi_device_ius(sdev))
148 target->negoFlags |= MPT_TAPE_NEGO_IDP;
149 }
150 }
151 offset = pspi_data->maxSyncOffset;
152
153 /* If RAID, never disable QAS
154 * else if non RAID, do not disable
155 * QAS if bit 1 is set
156 * bit 1 QAS support, non-raid only
157 * bit 0 IU support
158 */
159 if (target->raidVolume == 1)
160 noQas = 0;
161 } else {
162 factor = MPT_ASYNC;
163 offset = 0;
164 }
165 }
166
167 if (!sdev->tagged_supported)
168 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
169
170 /* Update tflags based on NVRAM settings. (SCSI only)
171 */
172 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
173 nvram = pspi_data->nvram[id];
174 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
175
176 if (width)
177 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
178
179 if (offset > 0) {
180 /* Ensure factor is set to the
181 * maximum of: adapter, nvram, inquiry
182 */
183 if (nfactor) {
184 if (nfactor < pspi_data->minSyncFactor )
185 nfactor = pspi_data->minSyncFactor;
186
187 factor = max(factor, nfactor);
188 if (factor == MPT_ASYNC)
189 offset = 0;
190 } else {
191 offset = 0;
192 factor = MPT_ASYNC;
193 }
194 } else {
195 factor = MPT_ASYNC;
196 }
197 }
198
199 /* Make sure data is consistent
200 */
201 if ((!width) && (factor < MPT_ULTRA2))
202 factor = MPT_ULTRA2;
203
204 /* Save the data to the target structure.
205 */
206 target->minSyncFactor = factor;
207 target->maxOffset = offset;
208 target->maxWidth = width;
209
210 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
211
212 /* Disable unused features.
213 */
214 if (!width)
215 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
216
217 if (!offset)
218 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
219
220 if ( factor > MPT_ULTRA320 )
221 noQas = 0;
222
223 if (noQas && (pspi_data->noQas == 0)) {
224 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
225 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
226
227 /* Disable QAS in a mixed configuration case
228 */
229
230 ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
231 }
232}
233
234/**
235 * mptspi_writeIOCPage4 - write IOC Page 4
236 * @hd: Pointer to a SCSI Host Structure
237 * @channel:
238 * @id: write IOC Page4 for this ID & Bus
239 *
240 * Return: -EAGAIN if unable to obtain a Message Frame
241 * or 0 if success.
242 *
243 * Remark: We do not wait for a return, write pages sequentially.
244 **/
245static int
246mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id)
247{
248 MPT_ADAPTER *ioc = hd->ioc;
249 Config_t *pReq;
250 IOCPage4_t *IOCPage4Ptr;
251 MPT_FRAME_HDR *mf;
252 dma_addr_t dataDma;
253 u16 req_idx;
254 u32 frameOffset;
255 u32 flagsLength;
256 int ii;
257
258 /* Get a MF for this command.
259 */
260 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
261 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
262 ioc->name));
263 return -EAGAIN;
264 }
265
266 /* Set the request and the data pointers.
267 * Place data at end of MF.
268 */
269 pReq = (Config_t *)mf;
270
271 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
272 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
273
274 /* Complete the request frame (same for all requests).
275 */
276 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
277 pReq->Reserved = 0;
278 pReq->ChainOffset = 0;
279 pReq->Function = MPI_FUNCTION_CONFIG;
280 pReq->ExtPageLength = 0;
281 pReq->ExtPageType = 0;
282 pReq->MsgFlags = 0;
283 for (ii=0; ii < 8; ii++) {
284 pReq->Reserved2[ii] = 0;
285 }
286
287 IOCPage4Ptr = ioc->spi_data.pIocPg4;
288 dataDma = ioc->spi_data.IocPg4_dma;
289 ii = IOCPage4Ptr->ActiveSEP++;
290 IOCPage4Ptr->SEP[ii].SEPTargetID = id;
291 IOCPage4Ptr->SEP[ii].SEPBus = channel;
292 pReq->Header = IOCPage4Ptr->Header;
293 pReq->PageAddress = cpu_to_le32(id | (channel << 8 ));
294
295 /* Add a SGE to the config request.
296 */
297 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
298 (IOCPage4Ptr->Header.PageLength + ii) * 4;
299
300 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
301
302 ddvprintk((MYIOC_s_INFO_FMT
303 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
304 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
305
306 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
307
308 return 0;
309}
310
311/**
312 * mptspi_initTarget - Target, LUN alloc/free functionality.
313 * @hd: Pointer to MPT_SCSI_HOST structure
314 * @vtarget: per target private data
315 * @sdev: SCSI device
316 *
317 * NOTE: It's only SAFE to call this routine if data points to
318 * sane & valid STANDARD INQUIRY data!
319 *
320 * Allocate and initialize memory for this target.
321 * Save inquiry data.
322 *
323 **/
324static void
325mptspi_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
326 struct scsi_device *sdev)
327{
328
329 /* Is LUN supported? If so, upper 2 bits will be 0
330 * in first byte of inquiry data.
331 */
332 if (sdev->inq_periph_qual != 0)
333 return;
334
335 if (vtarget == NULL)
336 return;
337
338 vtarget->type = sdev->type;
339
340 if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
341 /* Treat all Processors as SAF-TE if
342 * command line option is set */
343 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
344 mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
345 }else if ((sdev->type == TYPE_PROCESSOR) &&
346 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
347 if (sdev->inquiry_len > 49 ) {
348 if (sdev->inquiry[44] == 'S' &&
349 sdev->inquiry[45] == 'A' &&
350 sdev->inquiry[46] == 'F' &&
351 sdev->inquiry[47] == '-' &&
352 sdev->inquiry[48] == 'T' &&
353 sdev->inquiry[49] == 'E' ) {
354 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
355 mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
356 }
357 }
358 }
359 mptspi_setTargetNegoParms(hd, vtarget, sdev);
360}
98 361
99/** 362/**
100 * mptspi_is_raid - Determines whether target is belonging to volume 363 * mptspi_is_raid - Determines whether target is belonging to volume
@@ -408,13 +671,16 @@ static int mptspi_slave_alloc(struct scsi_device *sdev)
408 671
409static int mptspi_slave_configure(struct scsi_device *sdev) 672static int mptspi_slave_configure(struct scsi_device *sdev)
410{ 673{
411 int ret = mptscsih_slave_configure(sdev);
412 struct _MPT_SCSI_HOST *hd = 674 struct _MPT_SCSI_HOST *hd =
413 (struct _MPT_SCSI_HOST *)sdev->host->hostdata; 675 (struct _MPT_SCSI_HOST *)sdev->host->hostdata;
676 VirtTarget *vtarget = scsi_target(sdev)->hostdata;
677 int ret = mptscsih_slave_configure(sdev);
414 678
415 if (ret) 679 if (ret)
416 return ret; 680 return ret;
417 681
682 mptspi_initTarget(hd, vtarget, sdev);
683
418 if ((sdev->channel == 1 || 684 if ((sdev->channel == 1 ||
419 !(mptspi_is_raid(hd, sdev->id))) && 685 !(mptspi_is_raid(hd, sdev->id))) &&
420 !spi_initial_dv(sdev->sdev_target)) 686 !spi_initial_dv(sdev->sdev_target))