diff options
author | Eric Moore <eric.moore@lsi.com> | 2007-01-29 11:43:17 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-02-02 21:49:42 -0500 |
commit | 5a9c47b1344b514758d5d7f193c672850390cc36 (patch) | |
tree | e51ee96d7984203a8990109d0c3c825668074e56 /drivers/message/fusion/mptspi.c | |
parent | 793955f549c710a1b0c18f823d5d710840747b15 (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.c | 268 |
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; | |||
95 | static int mptspiTaskCtx = -1; | 95 | static int mptspiTaskCtx = -1; |
96 | static int mptspiInternalCtx = -1; /* Used only for internal commands */ | 96 | static 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 | **/ | ||
108 | static void | ||
109 | mptspi_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 | **/ | ||
245 | static int | ||
246 | mptspi_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 | **/ | ||
324 | static void | ||
325 | mptspi_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 | ||
409 | static int mptspi_slave_configure(struct scsi_device *sdev) | 672 | static 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)) |