]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-mpt-fusion.patch
- update SECURITY_DEFAULT_MMAP_MIN_ADDR to match upstream settings
[packages/kernel.git] / kernel-mpt-fusion.patch
1 Subject: Update MPT Fusion driver to v4.00.43.00
2 From: Hannes Reinecke <hare@suse.de>
3 Date: Tue Sep 30 13:38:53 2008 +0200:
4 Git: a958ec0d1685af04282982f2e53b66c947fc7426
5
6 References: bnc#425660
7
8 This patch updates the MPT fusion drivers to v4.00.43.00.
9
10 Signed-off-by: Sathya Prakash <Sathya.Prakash@lsi.com>
11 Signed-off-by: Hannes Reinecke <hare@suse.de>
12
13 ---
14  drivers/message/fusion/Kconfig                       |   16 
15  drivers/message/fusion/Makefile                      |   13 
16  drivers/message/fusion/csmi/csmisas.c                | 5888 ++++++++++++++++++
17  drivers/message/fusion/csmi/csmisas.h                | 1854 +++++
18  drivers/message/fusion/lsi/mpi.h                     |    7 
19  drivers/message/fusion/lsi/mpi_cnfg.h                |   47 
20  drivers/message/fusion/lsi/mpi_fc.h                  |    2 
21  drivers/message/fusion/lsi/mpi_history.txt           |   86 
22  drivers/message/fusion/lsi/mpi_init.h                |    2 
23  drivers/message/fusion/lsi/mpi_ioc.h                 |   22 
24  drivers/message/fusion/lsi/mpi_lan.h                 |    2 
25  drivers/message/fusion/lsi/mpi_log_fc.h              |    2 
26  drivers/message/fusion/lsi/mpi_log_sas.h             |   31 
27  drivers/message/fusion/lsi/mpi_raid.h                |   11 
28  drivers/message/fusion/lsi/mpi_sas.h                 |   18 
29  drivers/message/fusion/lsi/mpi_targ.h                |    2 
30  drivers/message/fusion/lsi/mpi_tool.h                |    2 
31  drivers/message/fusion/lsi/mpi_type.h                |   19 
32  drivers/message/fusion/mptbase.c                     | 2700 +++++---
33  drivers/message/fusion/mptbase.h                     |  291 
34  drivers/message/fusion/mptctl.c                      | 1020 +--
35  drivers/message/fusion/mptctl.h                      |    5 
36  drivers/message/fusion/mptdebug.h                    |   12 
37  drivers/message/fusion/mptfc.c                       |  189 
38  drivers/message/fusion/mptlan.c                      |   56 
39  drivers/message/fusion/mptlan.h                      |    3 
40  drivers/message/fusion/mptsas.c                      | 5921 ++++++++++++-------
41  drivers/message/fusion/mptsas.h                      |   71 
42  drivers/message/fusion/mptscsih.c                    | 2252 +++----
43  drivers/message/fusion/mptscsih.h                    |   13 
44  drivers/message/fusion/mptspi.c                      |  265 
45  drivers/message/fusion/rejected_ioctls/diag_buffer.c |  667 ++
46  drivers/message/fusion/rejected_ioctls/diag_buffer.h |  101 
47  33 files changed, 16615 insertions(+), 4975 deletions(-)
48
49 --- /dev/null
50 +++ b/drivers/message/fusion/csmi/csmisas.c
51 @@ -0,0 +1,5888 @@
52 +/*
53 + *  linux/drivers/message/fusion/csmi/csmisas.c
54 + *      For use with LSI PCI chip/adapter(s)
55 + *      running LSI Fusion MPT (Message Passing Technology) firmware.
56 + *
57 + *  Copyright (c) 1999-2008 LSI Corporation
58 + *  (mailto:DL-MPTFusionLinux@lsi.com)
59 + */
60 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
61 +/*
62 +    This program is free software; you can redistribute it and/or modify
63 +    it under the terms of the GNU General Public License as published by
64 +    the Free Software Foundation; version 2 of the License.
65 +
66 +    This program is distributed in the hope that it will be useful,
67 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
68 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
69 +    GNU General Public License for more details.
70 +
71 +    NO WARRANTY
72 +    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
73 +    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
74 +    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
75 +    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
76 +    solely responsible for determining the appropriateness of using and
77 +    distributing the Program and assumes all risks associated with its
78 +    exercise of rights under this Agreement, including but not limited to
79 +    the risks and costs of program errors, damage to or loss of data,
80 +    programs or equipment, and unavailability or interruption of operations.
81 +
82 +    DISCLAIMER OF LIABILITY
83 +    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
84 +    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85 +    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
86 +    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
87 +    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
88 +    USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
89 +    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
90 +
91 +    You should have received a copy of the GNU General Public License
92 +    along with this program; if not, write to the Free Software
93 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
94 +*/
95 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
96 +
97 +#define MPT_CSMI_DESCRIPTION "LSI Corporation: Fusion MPT Driver "MPT_LINUX_VERSION_COMMON
98 +#define csmisas_is_this_sas_cntr(ioc) (ioc->bus_type == SAS) ? 1 : 0
99 +
100 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
101 +#define __user
102 +#include <asm/div64.h>
103 +#endif
104 +
105 +static int csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus,
106 +    u8 VolumeId, pMpiRaidActionReply_t reply);
107 +static u8  map_sas_status_to_csmi(u8 mpi_sas_status);
108 +
109 +/**
110 + * reverse_byte_order64
111 + *
112 + * @data64
113 + *
114 + **/
115 +static u64
116 +reverse_byte_order64(u64 data64)
117 +{
118 +       int i;
119 +       u64 rc;
120 +       u8  *inWord = (u8*)&data64, *outWord = (u8*)&rc;
121 +
122 +       for (i = 0 ; i < 8 ; i++)
123 +               outWord[i] = inWord[7-i];
124 +
125 +       return rc;
126 +}
127 +
128 +/**
129 + * csmisas_is_sata
130 + *
131 + * @phys_disk
132 + *
133 + **/
134 +static int
135 +csmisas_is_sata(RaidPhysDiskPage0_t *phys_disk)
136 +{
137 +       if ((phys_disk->ExtDiskIdentifier[0] == 'A') &&
138 +           (phys_disk->ExtDiskIdentifier[1] == 'T') &&
139 +           (phys_disk->ExtDiskIdentifier[2] == 'A'))
140 +               return 1;
141 +       else
142 +               return 0;
143 +}
144 +
145 +/**
146 + * csmisas_is_end_device
147 + *
148 + * @attached
149 + *
150 + **/
151 +static inline int
152 +csmisas_is_end_device(struct mptsas_devinfo * attached)
153 +{
154 +       if ((attached->sas_address) &&
155 +           (attached->device_info &
156 +           MPI_SAS_DEVICE_INFO_END_DEVICE) &&
157 +           ((attached->device_info &
158 +           MPI_SAS_DEVICE_INFO_SSP_TARGET) |
159 +           (attached->device_info &
160 +           MPI_SAS_DEVICE_INFO_STP_TARGET) |
161 +           (attached->device_info &
162 +           MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
163 +               return 1;
164 +       else
165 +               return 0;
166 +}
167 +
168 +/**
169 + * csmisas_is_phys_disk
170 + *
171 + * returns (1) success (0) fail - not a phys disk
172 + **/
173 +static int
174 +csmisas_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id)
175 +{
176 +       struct inactive_raid_component_info *component_info;
177 +       int i;
178 +       int rc = 0;
179 +
180 +       if (!ioc->raid_data.pIocPg3)
181 +               goto out;
182 +       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
183 +               if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
184 +                   (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
185 +                       rc = 1;
186 +                       goto out;
187 +               }
188 +       }
189 +
190 +       /*
191 +        * Check inactive list for matching phys disks
192 +        */
193 +       if (list_empty(&ioc->raid_data.inactive_list))
194 +               goto out;
195 +
196 +       down(&ioc->raid_data.inactive_list_mutex);
197 +       list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
198 +           list) {
199 +               if ((component_info->d.PhysDiskID == id) &&
200 +                   (component_info->d.PhysDiskBus == channel))
201 +                       rc = 1;
202 +       }
203 +       up(&ioc->raid_data.inactive_list_mutex);
204 +
205 + out:
206 +       return rc;
207 +}
208 +
209 +/**
210 + * csmisas_raid_id_to_num
211 + *
212 + * Obtains the phys disk num for given H:C:T nexus
213 + *
214 + * input (channel/id)
215 + * output (phys disk number - used by SCSI_IO_PASSTHRU to access hidden component)
216 + *
217 + * returns - signed return means failure
218 + **/
219 +static s8
220 +csmisas_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
221 +{
222 +       struct inactive_raid_component_info *component_info;
223 +       int i;
224 +       s8 rc = -ENXIO;
225 +
226 +       if (!ioc->raid_data.pIocPg3)
227 +               goto out;
228 +       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
229 +               if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
230 +                   (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
231 +                       rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
232 +                       goto out;
233 +               }
234 +       }
235 +
236 +       /*
237 +        * Check inactive list for matching phys disks
238 +        */
239 +       if (list_empty(&ioc->raid_data.inactive_list))
240 +               goto out;
241 +
242 +       down(&ioc->raid_data.inactive_list_mutex);
243 +       list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
244 +           list) {
245 +               if ((component_info->d.PhysDiskID == id) &&
246 +                   (component_info->d.PhysDiskBus == channel))
247 +                       rc = component_info->d.PhysDiskNum;
248 +       }
249 +       up(&ioc->raid_data.inactive_list_mutex);
250 +
251 + out:
252 +       return rc;
253 +}
254 +
255 +/**
256 + * csmisas_get_device_component_by_os
257 + *
258 + * Obtain device component object by operating system mapping
259 + *
260 + * @ioc
261 + * @channel
262 + * @id
263 + *
264 + **/
265 +static struct sas_device_info *
266 +csmisas_get_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
267 +{
268 +       struct sas_device_info *sas_info, *p;
269 +
270 +       sas_info = NULL;
271 +
272 +       down(&ioc->sas_device_info_mutex);
273 +       list_for_each_entry(p, &ioc->sas_device_info_list, list) {
274 +               if (p->os.channel == channel && p->os.id == id) {
275 +                       sas_info = p;
276 +                       goto out;
277 +               }
278 +       }
279 +
280 + out:
281 +       up(&ioc->sas_device_info_mutex);
282 +       return sas_info;
283 +}
284 +
285 +/**
286 + * csmisas_get_device_component
287 + *
288 + * Obtain device component object by firmware system mapping
289 + *
290 + * @ioc
291 + * @channel
292 + * @id
293 + *
294 + **/
295 +static struct sas_device_info *
296 +csmisas_get_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
297 +{
298 +       struct sas_device_info *sas_info, *p;
299 +
300 +       sas_info = NULL;
301 +
302 +       down(&ioc->sas_device_info_mutex);
303 +       list_for_each_entry(p, &ioc->sas_device_info_list, list) {
304 +               if (p->fw.channel == channel && p->fw.id == id) {
305 +                       sas_info = p;
306 +                       goto out;
307 +               }
308 +       }
309 +
310 + out:
311 +       up(&ioc->sas_device_info_mutex);
312 +       return sas_info;
313 +}
314 +
315 +
316 +/**
317 + * csmisas_get_device_component_by_sas_addr
318 + *
319 + * Obtain device component object by sas address
320 + *
321 + * @ioc
322 + * @channel
323 + * @id
324 + *
325 + **/
326 +static struct sas_device_info *
327 +csmisas_get_device_component_by_sas_addr(MPT_ADAPTER *ioc, u64 sas_address)
328 +{
329 +       struct sas_device_info *sas_info, *p;
330 +
331 +       sas_info = NULL;
332 +
333 +       down(&ioc->sas_device_info_mutex);
334 +       list_for_each_entry(p, &ioc->sas_device_info_list, list) {
335 +               if (p->sas_address == sas_address) {
336 +                       sas_info = p;
337 +                       goto out;
338 +               }
339 +       }
340 +
341 + out:
342 +       up(&ioc->sas_device_info_mutex);
343 +       return sas_info;
344 +}
345 +
346 +/**
347 + * csmisas_send_command_wait
348 + *
349 + * Send mf to firmware
350 + *
351 + * @ioc
352 + * @mf
353 + * @timeout - timeout
354 + *
355 + *     Return: 0 for success
356 + *     non-zero, failure
357 + **/
358 +static int
359 +csmisas_send_command_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, unsigned long timeout)
360 +{
361 +       int rc;
362 +       unsigned long timeleft;
363 +
364 +       timeout = max_t(unsigned long, MPT_IOCTL_DEFAULT_TIMEOUT, timeout);
365 +       rc = 0;
366 +       timeleft = 0;
367 +
368 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
369 +
370 +       INITIALIZE_IOCTL_STATUS(ioc->ioctl_cmds.status)
371 +       ioc->ioctl_cmds.wait_done = 0;
372 +       ioc->ioctl_cmds.timer.expires = jiffies + (MPT_JIFFY * timeout);
373 +       ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_TIMER_ACTIVE;
374 +       ADD_TIMER(&ioc->ioctl_cmds.timer);
375 +       mpt_put_msg_frame(mptctl_id, ioc, mf);
376 +       WAIT_EVENT(mptctl_wait, ioc->ioctl_cmds.wait_done);
377 +
378 +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
379 +
380 +       INITIALIZE_IOCTL_STATUS(ioc->ioctl_cmds.status)
381 +       ioc->ioctl_cmds.wait_done = 0;
382 +       mpt_put_msg_frame(mptctl_id, ioc, mf);
383 +
384 +       if ((wait_event_timeout(mptctl_wait,
385 +           ioc->ioctl_cmds.wait_done == 1, HZ * timeout) <=0) &&
386 +           ioc->ioctl_cmds.wait_done != 1 ) {
387 +               mptctl_timeout_expired(ioc,mf);
388 +               mpt_free_msg_frame(ioc, mf);
389 +               rc = -1;
390 +       }
391 +
392 +#else
393 +
394 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
395 +           mf->u.hdr.MsgContext);
396 +       INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
397 +       mpt_put_msg_frame(mptctl_id, ioc, mf);
398 +       timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done, timeout*HZ);
399 +       if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
400 +               rc = -1;
401 +               printk("%s: failed\n", __FUNCTION__);
402 +               if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
403 +                       mpt_free_msg_frame(ioc, mf);
404 +                       CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
405 +                       return rc;
406 +               }
407 +               if (!timeleft)
408 +                       mptctl_timeout_expired(ioc, mf);
409 +       }
410 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
411 +#endif
412 +       return rc;
413 +}
414 +
415 +/**
416 + * csmisas_send_handshake_wait
417 + *
418 + * Handshake a mf to firmware
419 + *
420 + * @ioc
421 + * @mf
422 + * @mf_size
423 + * @timeout - timeout
424 + *
425 + *     Return: 0 for success
426 + *     non-zero, failure
427 + **/
428 +static int
429 +csmisas_send_handshake_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, unsigned long timeout)
430 +{
431 +       int rc;
432 +       unsigned long timeleft;
433 +
434 +       timeout = max_t(unsigned long, MPT_IOCTL_DEFAULT_TIMEOUT, timeout);
435 +       rc = 0;
436 +       timeleft = 0;
437 +
438 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
439 +
440 +       INITIALIZE_IOCTL_STATUS(ioc->taskmgmt_cmds.status)
441 +       ioc->taskmgmt_cmds.timer.expires = jiffies + (MPT_JIFFY*timeout);
442 +       ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_TIMER_ACTIVE;
443 +       ioc->taskmgmt_cmds.wait_done = 0;
444 +       ADD_TIMER(&ioc->taskmgmt_cmds.timer);
445 +       rc = mpt_send_special_message(mptctl_taskmgmt_id, ioc,
446 +           sizeof(SCSITaskMgmt_t), (u32*)mf, timeout, CAN_SLEEP);
447 +       if (rc != 0)
448 +               return rc;
449 +       WAIT_EVENT(mptctl_taskmgmt_wait, ioc->taskmgmt_cmds.wait_done);
450 +
451 +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
452 +
453 +       INITIALIZE_IOCTL_STATUS(ioc->taskmgmt_cmds.status)
454 +       ioc->taskmgmt_cmds.wait_done = 0;
455 +       rc = mpt_send_special_message(mptctl_taskmgmt_id, ioc,
456 +           sizeof(SCSITaskMgmt_t), (u32*)mf, timeout, CAN_SLEEP);
457 +       if (rc != 0)
458 +               return rc;
459 +       if ((wait_event_timeout(mptctl_taskmgmt_wait,
460 +           ioc->taskmgmt_cmds.wait_done == 1, HZ * timeout) <=0) &&
461 +           ioc->taskmgmt_cmds.wait_done != 1 ) {
462 +               mptctl_timeout_expired(ioc, mf);
463 +               mpt_free_msg_frame(ioc, mf);
464 +               rc = -1;
465 +       }
466 +
467 +#else
468 +       INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
469 +       mpt_put_msg_frame_hi_pri(mptctl_taskmgmt_id, ioc, mf);
470 +       timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
471 +       if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
472 +               rc = -1;
473 +               printk("%s: failed\n", __FUNCTION__);
474 +               mpt_clear_taskmgmt_in_progress_flag(ioc);
475 +               if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
476 +                       mpt_free_msg_frame(ioc, mf);
477 +                       CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
478 +                       return rc;
479 +               }
480 +               if (!timeleft)
481 +                       mptctl_timeout_expired(ioc, mf);
482 +       }
483 +#endif
484 +       return rc;
485 +}
486 +
487 +/**
488 + *     csmisas_get_number_hotspares - returns num hot spares in this ioc
489 + *     @ioc: Pointer to MPT_ADAPTER structure
490 + *
491 + *     Return: number of hotspares
492 + *
493 + **/
494 +static int
495 +csmisas_get_number_hotspares(MPT_ADAPTER *ioc)
496 +{
497 +       ConfigPageHeader_t       hdr;
498 +       CONFIGPARMS              cfg;
499 +       IOCPage5_t               *buffer = NULL;
500 +       dma_addr_t               dma_handle;
501 +       int                      data_sz;
502 +       int                      rc;
503 +
504 +       memset(&hdr, 0, sizeof(ConfigPageHeader_t));
505 +       memset(&cfg, 0, sizeof(CONFIGPARMS));
506 +
507 +       rc = 0;
508 +       data_sz = 0;
509 +       hdr.PageNumber = 5;
510 +       hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
511 +       cfg.cfghdr.hdr = &hdr;
512 +       cfg.physAddr = -1;
513 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
514 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
515 +
516 +       if (mpt_config(ioc, &cfg) != 0)
517 +               goto get_ioc_pg5;
518 +
519 +       if (hdr.PageLength == 0)
520 +               goto get_ioc_pg5;
521 +
522 +       data_sz = hdr.PageLength * 4;
523 +       buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
524 +               data_sz, &dma_handle);
525 +       if (!buffer)
526 +               goto get_ioc_pg5;
527 +
528 +       memset((u8 *)buffer, 0, data_sz);
529 +       cfg.physAddr = dma_handle;
530 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
531 +
532 +       if (mpt_config(ioc, &cfg) != 0)
533 +               goto get_ioc_pg5;
534 +
535 +       rc = buffer->NumHotSpares;
536 +
537 + get_ioc_pg5:
538 +
539 +       if (buffer)
540 +               pci_free_consistent(ioc->pcidev, data_sz,
541 +                   (u8 *) buffer, dma_handle);
542 +
543 +       return rc;
544 +}
545 +
546 +
547 +/**
548 + *     csmisas_get_ioc_pg5 - ioc Page 5 hot spares
549 + *     @ioc: Pointer to MPT_ADAPTER structure
550 + *     @pIocPage5: ioc page 5
551 + *     @data_size: expected data size(units=bytes)
552 + *
553 + *     Return: 0 for success
554 + *     -ENOMEM if no memory available
555 + *             -EPERM if not allowed due to ISR context
556 + *             -EAGAIN if no msg frames currently available
557 + *             -EFAULT for non-successful reply or no reply (timeout)
558 + **/
559 +static int
560 +csmisas_get_ioc_pg5(MPT_ADAPTER *ioc, IOCPage5_t *iocPage5, int data_size)
561 +{
562 +       ConfigPageHeader_t       hdr;
563 +       CONFIGPARMS              cfg;
564 +       IOCPage5_t               *buffer = NULL;
565 +       dma_addr_t               dma_handle;
566 +       int                      data_sz;
567 +       int                      rc;
568 +
569 +       memset(&hdr, 0, sizeof(ConfigPageHeader_t));
570 +       memset(&cfg, 0, sizeof(CONFIGPARMS));
571 +
572 +       rc = 0;
573 +       data_sz = 0;
574 +       hdr.PageNumber = 5;
575 +       hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
576 +       cfg.cfghdr.hdr = &hdr;
577 +       cfg.physAddr = -1;
578 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
579 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
580 +
581 +       if ((rc = mpt_config(ioc, &cfg)) != 0)
582 +               goto get_ioc_pg5;
583 +
584 +       if (hdr.PageLength == 0) {
585 +               rc = -EFAULT;
586 +               goto get_ioc_pg5;
587 +       }
588 +
589 +       data_sz = hdr.PageLength * 4;
590 +       buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
591 +               data_sz, &dma_handle);
592 +       if (!buffer) {
593 +               rc = -ENOMEM;
594 +               goto get_ioc_pg5;
595 +       }
596 +
597 +       memset((u8 *)buffer, 0, data_sz);
598 +       cfg.physAddr = dma_handle;
599 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
600 +
601 +       if ((rc = mpt_config(ioc, &cfg)) != 0)
602 +               goto get_ioc_pg5;
603 +
604 +       memcpy(iocPage5, buffer, data_size);
605 +
606 + get_ioc_pg5:
607 +
608 +       if (buffer)
609 +               pci_free_consistent(ioc->pcidev, data_sz,
610 +                   (u8 *) buffer, dma_handle);
611 +
612 +       return rc;
613 +}
614 +
615 +/**
616 + *     csmisas_sas_device_pg0 - sas device page 0
617 + *     @ioc: Pointer to MPT_ADAPTER structure
618 + *     @mptsas_devinfo: structure found in mptsas.h
619 + *     @form, @form_specific - defines the Page Address field in the config page
620 + *             (pls refer to chapter 5.1 in the mpi spec)
621 + *
622 + *     Return: 0 for success
623 + *     -ENOMEM if no memory available
624 + *             -EPERM if not allowed due to ISR context
625 + *             -EAGAIN if no msg frames currently available
626 + *             -EFAULT for non-successful reply or no reply (timeout)
627 + **/
628 +static int
629 +csmisas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
630 +               u32 form, u32 form_specific)
631 +{
632 +       ConfigExtendedPageHeader_t hdr;
633 +       CONFIGPARMS cfg;
634 +       SasDevicePage0_t *buffer;
635 +       dma_addr_t dma_handle;
636 +       u64 sas_address;
637 +       int rc;
638 +
639 +       rc = 0;
640 +       hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
641 +       hdr.ExtPageLength = 0;
642 +       hdr.PageNumber = 0;
643 +       hdr.Reserved1 = 0;
644 +       hdr.Reserved2 = 0;
645 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
646 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
647 +
648 +       cfg.cfghdr.ehdr = &hdr;
649 +       cfg.pageAddr = form + form_specific;
650 +       cfg.physAddr = -1;
651 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
652 +       cfg.dir = 0;    /* read */
653 +       cfg.timeout = 10;
654 +
655 +       memset(device_info, 0, sizeof(struct mptsas_devinfo));
656 +       if ((rc = mpt_config(ioc, &cfg)) != 0)
657 +               goto out;
658 +
659 +       if (!hdr.ExtPageLength) {
660 +               rc = -ENXIO;
661 +               goto out;
662 +       }
663 +
664 +       buffer = pci_alloc_consistent(ioc->pcidev,
665 +           hdr.ExtPageLength * 4, &dma_handle);
666 +       if (!buffer) {
667 +               rc = -ENOMEM;
668 +               goto out;
669 +       }
670 +
671 +       cfg.physAddr = dma_handle;
672 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
673 +
674 +       if ((rc = mpt_config(ioc, &cfg)) != 0)
675 +               goto out_free_consistent;
676 +
677 +       device_info->handle = le16_to_cpu(buffer->DevHandle);
678 +       device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
679 +       device_info->handle_enclosure =
680 +           le16_to_cpu(buffer->EnclosureHandle);
681 +       device_info->slot = le16_to_cpu(buffer->Slot);
682 +       device_info->phy_id = buffer->PhyNum;
683 +       device_info->port_id = buffer->PhysicalPort;
684 +       device_info->id = buffer->TargetID;
685 +       device_info->channel = buffer->Bus;
686 +       memcpy(&sas_address, &buffer->SASAddress, sizeof(u64));
687 +       device_info->sas_address = le64_to_cpu(sas_address);
688 +       device_info->device_info =
689 +           le32_to_cpu(buffer->DeviceInfo);
690 +
691 + out_free_consistent:
692 +       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
693 +                           buffer, dma_handle);
694 + out:
695 +       return rc;
696 +}
697 +
698 +/**
699 + * Routine for the CSMI Sas Get Driver Info command.
700 + *
701 + * Outputs:    None.
702 + * Return:     0 if successful
703 + *             -EFAULT if data unavailable
704 + *             -ENODEV if no such device/adapter
705 + **/
706 +static int
707 +csmisas_get_driver_info(unsigned long arg)
708 +{
709 +
710 +       CSMI_SAS_DRIVER_INFO_BUFFER __user *uarg = (void __user *) arg;
711 +       CSMI_SAS_DRIVER_INFO_BUFFER     karg;
712 +       MPT_ADAPTER     *ioc = NULL;
713 +       int             iocnum;
714 +
715 +       if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
716 +               printk(KERN_ERR "%s@%d::%s - "
717 +             "Unable to read in csmi_sas_get_driver_info_buffer struct @ %p\n",
718 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
719 +               return -EFAULT;
720 +       }
721 +
722 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
723 +           &ioc)) < 0) || (ioc == NULL)) {
724 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
725 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
726 +               return -ENODEV;
727 +       }
728 +
729 +       if (!csmisas_is_this_sas_cntr(ioc)) {
730 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
731 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
732 +               return -ENODEV;
733 +       }
734 +
735 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
736 +
737 +       /* Fill in the data and return the structure to the calling
738 +        * program
739 +        */
740 +       memcpy( karg.Information.szName, MPT_MISCDEV_BASENAME,
741 +           sizeof(MPT_MISCDEV_BASENAME));
742 +       memcpy( karg.Information.szDescription, MPT_CSMI_DESCRIPTION,
743 +           sizeof(MPT_CSMI_DESCRIPTION));
744 +
745 +       karg.Information.usMajorRevision = MPT_LINUX_MAJOR_VERSION;
746 +       karg.Information.usMinorRevision = MPT_LINUX_MINOR_VERSION;
747 +       karg.Information.usBuildRevision = MPT_LINUX_BUILD_VERSION;
748 +       karg.Information.usReleaseRevision = MPT_LINUX_RELEASE_VERSION;
749 +
750 +       karg.Information.usCSMIMajorRevision = CSMI_MAJOR_REVISION;
751 +       karg.Information.usCSMIMinorRevision = CSMI_MINOR_REVISION;
752 +
753 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
754 +
755 +       /* Copy the data from kernel memory to user memory
756 +        */
757 +       if (copy_to_user(uarg, &karg,
758 +               sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
759 +               printk(KERN_ERR "%s@%d::%s - "
760 +                  "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
761 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
762 +               return -EFAULT;
763 +       }
764 +
765 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
766 +       return 0;
767 +}
768 +
769 +/**
770 + * Prototype Routine for the CSMI_SAS_GET_CNTLR_CONFIG command.
771 + *
772 + * Outputs:    None.
773 + * Return:     0 if successful
774 + *             -EFAULT if data unavailable
775 + *             -ENODEV if no such device/adapter
776 + **/
777 +static int
778 +csmisas_get_cntlr_config(unsigned long arg)
779 +{
780 +
781 +       CSMI_SAS_CNTLR_CONFIG_BUFFER __user *uarg = (void __user *) arg;
782 +       CSMI_SAS_CNTLR_CONFIG_BUFFER    karg;
783 +       MPT_ADAPTER     *ioc = NULL;
784 +       int             iocnum;
785 +       u64             mem_phys;
786 +
787 +       if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_CONFIG_BUFFER))) {
788 +               printk(KERN_ERR "%s@%d::%s - "
789 +            "Unable to read in csmi_sas_get_cntlr_config_buffer struct @ %p\n",
790 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
791 +               return -EFAULT;
792 +       }
793 +
794 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
795 +           &ioc)) < 0) || (ioc == NULL)) {
796 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
797 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
798 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
799 +               return -ENODEV;
800 +       }
801 +
802 +       if (!csmisas_is_this_sas_cntr(ioc)) {
803 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
804 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
805 +               return -ENODEV;
806 +       }
807 +
808 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
809 +
810 +       /* Clear the struct before filling in data. */
811 +       memset( &karg.Configuration, 0, sizeof(CSMI_SAS_CNTLR_CONFIG));
812 +
813 +       /* Fill in the data and return the structure to the calling
814 +        * program
815 +        */
816 +
817 +       karg.Configuration.uBaseIoAddress = ioc->pio_mem_phys;
818 +       karg.Configuration.BaseMemoryAddress.uLowPart = ioc->mem_phys;
819 +       if (sizeof(ioc->mem_phys) == sizeof(u64)) {
820 +               mem_phys = ioc->mem_phys;
821 +               karg.Configuration.BaseMemoryAddress.uHighPart =
822 +                   (u32)(mem_phys >> 32);
823 +       }
824 +
825 +       karg.Configuration.uBoardID = (ioc->pcidev->subsystem_device << 16) |
826 +           (ioc->pcidev->subsystem_vendor);
827 +
828 +       karg.Configuration.usSlotNumber =
829 +           (ioc->pci_slot_number = 0xff) ?
830 +           SLOT_NUMBER_UNKNOWN : ioc->pci_slot_number;
831 +       karg.Configuration.bControllerClass = CSMI_SAS_CNTLR_CLASS_HBA;
832 +       karg.Configuration.bIoBusType = CSMI_SAS_BUS_TYPE_PCI;
833 +       karg.Configuration.BusAddress.PciAddress.bBusNumber =
834 +           ioc->pcidev->bus->number;
835 +       karg.Configuration.BusAddress.PciAddress.bDeviceNumber =
836 +           PCI_SLOT(ioc->pcidev->devfn);
837 +       karg.Configuration.BusAddress.PciAddress.bFunctionNumber =
838 +           PCI_FUNC(ioc->pcidev->devfn);
839 +       karg.Configuration.BusAddress.PciAddress.bReserved = 0;
840 +       memcpy( &karg.Configuration.szSerialNumber, ioc->board_tracer, 16 );
841 +       karg.Configuration.usMajorRevision = ioc->facts.FWVersion.Struct.Major;
842 +       karg.Configuration.usMinorRevision = ioc->facts.FWVersion.Struct.Minor;
843 +       karg.Configuration.usBuildRevision = ioc->facts.FWVersion.Struct.Unit;
844 +       karg.Configuration.usReleaseRevision = ioc->facts.FWVersion.Struct.Dev;
845 +       karg.Configuration.usBIOSMajorRevision =
846 +           (ioc->biosVersion & 0xFF000000) >> 24;
847 +       karg.Configuration.usBIOSMinorRevision =
848 +           (ioc->biosVersion & 0x00FF0000) >> 16;
849 +       karg.Configuration.usBIOSBuildRevision =
850 +           (ioc->biosVersion & 0x0000FF00) >> 8;
851 +       karg.Configuration.usBIOSReleaseRevision =
852 +           (ioc->biosVersion & 0x000000FF);
853 +       karg.Configuration.uControllerFlags = CSMI_SAS_CNTLR_SAS_HBA |
854 +           CSMI_SAS_CNTLR_FWD_SUPPORT | CSMI_SAS_CNTLR_FWD_ONLINE |
855 +           CSMI_SAS_CNTLR_FWD_SRESET ;
856 +
857 +       /*
858 +        * Enabling CSMI_SAS_CNTLR_SAS_RAID bit when IR fw detected
859 +        */
860 +       if (ioc->ir_firmware)
861 +               karg.Configuration.uControllerFlags |= CSMI_SAS_CNTLR_SAS_RAID;
862 +
863 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
864 +
865 +       /* All Rrom entries will be zero. Skip them. */
866 +       /* bReserved will also be zeros. */
867 +       /* Copy the data from kernel memory to user memory
868 +        */
869 +       if (copy_to_user(uarg, &karg,
870 +               sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
871 +               printk(KERN_ERR "%s@%d::%s - "
872 +               "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
873 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
874 +               return -EFAULT;
875 +       }
876 +
877 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
878 +       return 0;
879 +}
880 +
881 +/**
882 + * Prototype Routine for the CSMI Sas Get Controller Status command.
883 + *
884 + * Outputs:    None.
885 + * Return:     0 if successful
886 + *             -EFAULT if data unavailable
887 + *             -ENODEV if no such device/adapter
888 + **/
889 +static int
890 +csmisas_get_cntlr_status(unsigned long arg)
891 +{
892 +
893 +       CSMI_SAS_CNTLR_STATUS_BUFFER  __user *uarg = (void __user *) arg;
894 +       MPT_ADAPTER             *ioc = NULL;
895 +       CSMI_SAS_CNTLR_STATUS_BUFFER    karg;
896 +       int                     iocnum;
897 +       int                     rc;
898 +
899 +       if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
900 +               printk(KERN_ERR "%s@%d::%s - "
901 +            "Unable to read in csmi_sas_get_cntlr_status_buffer struct @ %p\n",
902 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
903 +               return -EFAULT;
904 +       }
905 +
906 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
907 +           &ioc)) < 0) || (ioc == NULL)) {
908 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
909 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
910 +               return -ENODEV;
911 +       }
912 +
913 +       if (!csmisas_is_this_sas_cntr(ioc)) {
914 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
915 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
916 +               return -ENODEV;
917 +       }
918 +
919 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
920 +
921 +       /* Fill in the data and return the structure to the calling
922 +        * program
923 +        */
924 +
925 +       rc = mpt_GetIocState(ioc, 1);
926 +       switch (rc) {
927 +       case MPI_IOC_STATE_OPERATIONAL:
928 +               karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_GOOD;
929 +               karg.Status.uOfflineReason = 0;
930 +               break;
931 +
932 +       case MPI_IOC_STATE_FAULT:
933 +               karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_FAILED;
934 +               karg.Status.uOfflineReason = 0;
935 +               break;
936 +
937 +       case MPI_IOC_STATE_RESET:
938 +       case MPI_IOC_STATE_READY:
939 +       default:
940 +               karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_OFFLINE;
941 +               karg.Status.uOfflineReason =
942 +                   CSMI_SAS_OFFLINE_REASON_INITIALIZING;
943 +               break;
944 +       }
945 +
946 +       memset(&karg.Status.bReserved, 0, 28);
947 +
948 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
949 +
950 +       /* Copy the data from kernel memory to user memory
951 +        */
952 +       if (copy_to_user(uarg, &karg,
953 +               sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
954 +               printk(KERN_ERR "%s@%d::%s - "
955 +                   "Unable to write out csmi_sas_get_cntlr_status @ %p\n",
956 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
957 +               return -EFAULT;
958 +       }
959 +
960 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
961 +       return 0;
962 +}
963 +
964 +/**
965 + * Prototype Routine for the CSMI Sas Get Phy Info command.
966 + *
967 + * Outputs:    None.
968 + * Return:     0 if successful
969 + *             -EFAULT if data unavailable
970 + *             -ENODEV if no such device/adapter
971 + **/
972 +static int
973 +csmisas_get_phy_info(unsigned long arg)
974 +{
975 +       CSMI_SAS_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
976 +       CSMI_SAS_PHY_INFO_BUFFER  *karg;
977 +       MPT_ADAPTER             *ioc = NULL;
978 +       ConfigExtendedPageHeader_t  hdr;
979 +       CONFIGPARMS             cfg;
980 +       SasIOUnitPage0_t        *sasIoUnitPg0;
981 +       dma_addr_t              sasIoUnitPg0_dma;
982 +       int                     sasIoUnitPg0_data_sz;
983 +       SasPhyPage0_t           *sasPhyPg0;
984 +       dma_addr_t              sasPhyPg0_dma;
985 +       int                     sasPhyPg0_data_sz;
986 +       u16                     protocol;
987 +       int                     iocnum;
988 +       int                     rc;
989 +       int                     ii;
990 +       u64                     sas_address;
991 +       struct mptsas_devinfo   device_info;
992 +       int                     memory_pages;
993 +
994 +       sasIoUnitPg0=NULL;
995 +       sasPhyPg0=NULL;
996 +       sasIoUnitPg0_data_sz=0;
997 +       sasPhyPg0_data_sz=0;
998 +
999 +       memory_pages = get_order(sizeof(CSMI_SAS_PHY_INFO_BUFFER));
1000 +       karg = (CSMI_SAS_PHY_INFO_BUFFER *)__get_free_pages(
1001 +               GFP_KERNEL, memory_pages);
1002 +       if (!karg){
1003 +               printk(KERN_ERR "%s@%d::%s() - "
1004 +                       "Unable to malloc CSMI_SAS_PHY_INFO_BUFFER "
1005 +                       "malloc_data_sz=%d memory_pages=%d\n",
1006 +                       __FILE__, __LINE__, __FUNCTION__,
1007 +                       (int)sizeof(CSMI_SAS_PHY_INFO_BUFFER), memory_pages);
1008 +               return -ENOMEM;
1009 +       }
1010 +
1011 +       memset(karg, 0, sizeof(*karg));
1012 +
1013 +       if (copy_from_user(karg, uarg, sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
1014 +               printk(KERN_ERR "%s@%d::%s - "
1015 +               "Unable to read in csmisas_get_phy_info_buffer struct @ %p\n",
1016 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1017 +               free_pages((unsigned long)karg, memory_pages);
1018 +               return -EFAULT;
1019 +       }
1020 +
1021 +       if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
1022 +           &ioc)) < 0) || (ioc == NULL)) {
1023 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
1024 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
1025 +               free_pages((unsigned long)karg, memory_pages);
1026 +               return -ENODEV;
1027 +       }
1028 +
1029 +       if (!csmisas_is_this_sas_cntr(ioc)) {
1030 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
1031 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
1032 +               free_pages((unsigned long)karg, memory_pages);
1033 +               return -ENODEV;
1034 +       }
1035 +
1036 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
1037 +
1038 +       /* Fill in the data and return the structure to the calling
1039 +        * program
1040 +        */
1041 +
1042 +       /* Issue a config request to get the number of phys
1043 +        */
1044 +       hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1045 +       hdr.ExtPageLength = 0;
1046 +       hdr.PageNumber = 0;
1047 +       hdr.Reserved1 = 0;
1048 +       hdr.Reserved2 = 0;
1049 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1050 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1051 +
1052 +       cfg.cfghdr.ehdr = &hdr;
1053 +       cfg.physAddr = -1;
1054 +       cfg.pageAddr = 0;
1055 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1056 +       cfg.dir = 0;    /* read */
1057 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
1058 +
1059 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
1060 +               /* Don't check if this failed.  Already in a
1061 +                * failure case.
1062 +                */
1063 +               dcsmisasprintk(ioc, printk(KERN_ERR
1064 +                   ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: HEADER\n"));
1065 +               dcsmisasprintk(ioc, printk(": rc=%x\n",rc));
1066 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1067 +               goto sas_get_phy_info_exit;
1068 +       }
1069 +
1070 +       if (hdr.ExtPageLength == 0) {
1071 +               /* Don't check if this failed.  Already in a
1072 +                * failure case.
1073 +                */
1074 +               dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
1075 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1076 +               goto sas_get_phy_info_exit;
1077 +       }
1078 +
1079 +       sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
1080 +       rc = -ENOMEM;
1081 +
1082 +       sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
1083 +           sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
1084 +
1085 +       if (!sasIoUnitPg0) {
1086 +               dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
1087 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1088 +               goto sas_get_phy_info_exit;
1089 +       }
1090 +
1091 +       memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
1092 +       cfg.physAddr = sasIoUnitPg0_dma;
1093 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1094 +
1095 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
1096 +
1097 +               /* Don't check if this failed.  Already in a
1098 +                * failure case.
1099 +                */
1100 +               dcsmisasprintk(ioc, printk(KERN_ERR
1101 +                   ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: PAGE\n"));
1102 +               dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
1103 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1104 +               goto sas_get_phy_info_exit;
1105 +       }
1106 +
1107 +       /* Number of Phys. */
1108 +       karg->Information.bNumberOfPhys = sasIoUnitPg0->NumPhys;
1109 +
1110 +       /* Fill in information for each phy. */
1111 +       for (ii = 0; ii < karg->Information.bNumberOfPhys; ii++) {
1112 +
1113 +/* EDM : dump IO Unit Page 0 data*/
1114 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "---- IO UNIT PAGE 0 ------------\n"));
1115 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n",
1116 +                   le16_to_cpu(sasIoUnitPg0->PhyData[ii].AttachedDeviceHandle)));
1117 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Controller Handle=0x%X\n",
1118 +                   le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle)));
1119 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Port=0x%X\n",
1120 +                   sasIoUnitPg0->PhyData[ii].Port));
1121 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Port Flags=0x%X\n",
1122 +                   sasIoUnitPg0->PhyData[ii].PortFlags));
1123 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "PHY Flags=0x%X\n",
1124 +                   sasIoUnitPg0->PhyData[ii].PhyFlags));
1125 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n",
1126 +                   sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate));
1127 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Controller PHY Device Info=0x%X\n",
1128 +                   le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)));
1129 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "DiscoveryStatus=0x%X\n",
1130 +                   le32_to_cpu(sasIoUnitPg0->PhyData[ii].DiscoveryStatus)));
1131 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
1132 +/* EDM : debug data */
1133 +
1134 +               /* PHY stuff. */
1135 +               karg->Information.Phy[ii].bPortIdentifier =
1136 +                   sasIoUnitPg0->PhyData[ii].Port;
1137 +
1138 +               /* Get the negotiated link rate for the phy. */
1139 +               switch (sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate) {
1140 +
1141 +               case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
1142 +                       karg->Information.Phy[ii].bNegotiatedLinkRate =
1143 +                           CSMI_SAS_PHY_DISABLED;
1144 +                       break;
1145 +
1146 +               case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
1147 +                       karg->Information.Phy[ii].bNegotiatedLinkRate =
1148 +                           CSMI_SAS_LINK_RATE_FAILED;
1149 +                       break;
1150 +
1151 +               case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1152 +                       break;
1153 +
1154 +               case MPI_SAS_IOUNIT0_RATE_1_5:
1155 +                       karg->Information.Phy[ii].bNegotiatedLinkRate =
1156 +                           CSMI_SAS_LINK_RATE_1_5_GBPS;
1157 +                       break;
1158 +
1159 +               case MPI_SAS_IOUNIT0_RATE_3_0:
1160 +                       karg->Information.Phy[ii].bNegotiatedLinkRate =
1161 +                           CSMI_SAS_LINK_RATE_3_0_GBPS;
1162 +                       break;
1163 +
1164 +               case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1165 +               default:
1166 +                       karg->Information.Phy[ii].bNegotiatedLinkRate =
1167 +                           CSMI_SAS_LINK_RATE_UNKNOWN;
1168 +                       break;
1169 +               }
1170 +
1171 +               if (sasIoUnitPg0->PhyData[ii].PortFlags &
1172 +                   MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS) {
1173 +                       karg->Information.Phy[ii].bAutoDiscover =
1174 +                           CSMI_SAS_DISCOVER_IN_PROGRESS;
1175 +               } else {
1176 +                       karg->Information.Phy[ii].bAutoDiscover =
1177 +                           CSMI_SAS_DISCOVER_COMPLETE;
1178 +               }
1179 +
1180 +               /* Issue a config request to get
1181 +                * phy information.
1182 +                */
1183 +               hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1184 +               hdr.ExtPageLength = 0;
1185 +               hdr.PageNumber = 0;
1186 +               hdr.Reserved1 = 0;
1187 +               hdr.Reserved2 = 0;
1188 +               hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1189 +               hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1190 +
1191 +               cfg.cfghdr.ehdr = &hdr;
1192 +               cfg.physAddr = -1;
1193 +               cfg.pageAddr = ii;
1194 +               cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1195 +               cfg.dir = 0;    /* read */
1196 +               cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
1197 +
1198 +               if ((rc = mpt_config(ioc, &cfg)) != 0) {
1199 +                       dcsmisasprintk(ioc, printk(KERN_ERR
1200 +                           ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
1201 +                       dcsmisasprintk(ioc, printk(": rc=%x\n",rc));
1202 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1203 +                       goto sas_get_phy_info_exit;
1204 +               }
1205 +
1206 +               if (hdr.ExtPageLength == 0) {
1207 +                       dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
1208 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1209 +                       goto sas_get_phy_info_exit;
1210 +               }
1211 +
1212 +               sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
1213 +               rc = -ENOMEM;
1214 +
1215 +               sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(
1216 +                   ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma);
1217 +
1218 +               if (! sasPhyPg0) {
1219 +                       dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
1220 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1221 +                       goto sas_get_phy_info_exit;
1222 +               }
1223 +
1224 +               memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
1225 +               cfg.physAddr = sasPhyPg0_dma;
1226 +               cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1227 +
1228 +               if ((rc = mpt_config(ioc, &cfg)) != 0) {
1229 +                       dcsmisasprintk(ioc, printk(KERN_ERR
1230 +                           ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
1231 +                       dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
1232 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1233 +                       pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
1234 +                           (u8 *) sasPhyPg0, sasPhyPg0_dma);
1235 +                       goto sas_get_phy_info_exit;
1236 +               }
1237 +
1238 +/* EDM : dump PHY Page 0 data*/
1239 +               memcpy(&sas_address, &sasPhyPg0->SASAddress, sizeof(u64));
1240 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 0 ------------\n"));
1241 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n",
1242 +                   le16_to_cpu(sasPhyPg0->AttachedDevHandle)));
1243 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n",
1244 +                   (unsigned long long)sas_address));
1245 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Attached PHY Identifier=0x%X\n",
1246 +                   sasPhyPg0->AttachedPhyIdentifier));
1247 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Attached Device Info=0x%X\n",
1248 +                   le32_to_cpu(sasPhyPg0->AttachedDeviceInfo)));
1249 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n",
1250 +                   sasPhyPg0->ProgrammedLinkRate));
1251 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Hardware Link Rate=0x%X\n",
1252 +                   sasPhyPg0->HwLinkRate));
1253 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "Change Count=0x%X\n",
1254 +                   sasPhyPg0->ChangeCount));
1255 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "PHY Info=0x%X\n",
1256 +                   le32_to_cpu(sasPhyPg0->PhyInfo)));
1257 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
1258 +/* EDM : debug data */
1259 +
1260 +               /* save the data */
1261 +
1262 +               /* Set Max hardware link rate.
1263 +                * This value is hard coded
1264 +                * because the HW link rate
1265 +                * is currently being
1266 +                * overwritten in FW.
1267 +                */
1268 +
1269 +               /* Set Max hardware link rate. */
1270 +               switch (sasPhyPg0->HwLinkRate &
1271 +                   MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1272 +
1273 +               case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
1274 +                       karg->Information.Phy[ii].bMaximumLinkRate =
1275 +                           CSMI_SAS_LINK_RATE_1_5_GBPS;
1276 +                       break;
1277 +
1278 +               case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
1279 +                       karg->Information.Phy[ii].bMaximumLinkRate =
1280 +                           CSMI_SAS_LINK_RATE_3_0_GBPS;
1281 +                       break;
1282 +               default:
1283 +                       break;
1284 +               }
1285 +
1286 +               /* Set Max programmed link rate. */
1287 +               switch (sasPhyPg0->ProgrammedLinkRate &
1288 +                   MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1289 +
1290 +               case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
1291 +                       karg->Information.Phy[ii].bMaximumLinkRate |=
1292 +                           (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
1293 +                       break;
1294 +
1295 +               case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
1296 +                       karg->Information.Phy[ii].bMaximumLinkRate |=
1297 +                           (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
1298 +                       break;
1299 +               default:
1300 +                       break;
1301 +               }
1302 +
1303 +               /* Set Min hardware link rate. */
1304 +               switch (sasPhyPg0->HwLinkRate &
1305 +                   MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1306 +
1307 +               case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
1308 +                       karg->Information.Phy[ii].bMinimumLinkRate =
1309 +                           CSMI_SAS_LINK_RATE_1_5_GBPS;
1310 +                       break;
1311 +
1312 +               case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
1313 +                       karg->Information.Phy[ii].bMinimumLinkRate =
1314 +                           CSMI_SAS_LINK_RATE_3_0_GBPS;
1315 +                       break;
1316 +               default:
1317 +                       break;
1318 +               }
1319 +
1320 +               /* Set Min programmed link rate. */
1321 +               switch (sasPhyPg0->ProgrammedLinkRate &
1322 +                   MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1323 +
1324 +               case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
1325 +                       karg->Information.Phy[ii].bMinimumLinkRate |=
1326 +                           (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
1327 +                       break;
1328 +
1329 +               case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
1330 +                       karg->Information.Phy[ii].bMinimumLinkRate |=
1331 +                           (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
1332 +                       break;
1333 +               default:
1334 +                       break;
1335 +               }
1336 +
1337 +               karg->Information.Phy[ii].bPhyChangeCount = sasPhyPg0->ChangeCount;
1338 +               if( sasPhyPg0->PhyInfo & MPI_SAS_PHY0_PHYINFO_VIRTUAL_PHY )
1339 +                       karg->Information.Phy[ii].bPhyFeatures = CSMI_SAS_PHY_VIRTUAL_SMP;
1340 +
1341 +               /* Fill in Attached Device
1342 +                * Initiator Port Protocol.
1343 +                * Bits 6:3
1344 +                * More than one bit can be set.
1345 +                */
1346 +               protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x78;
1347 +               karg->Information.Phy[ii].Attached.bInitiatorPortProtocol = 0;
1348 +               if (protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1349 +                     karg->Information.Phy[ii].Attached.bInitiatorPortProtocol =
1350 +                           CSMI_SAS_PROTOCOL_SSP;
1351 +               if (protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1352 +                    karg->Information.Phy[ii].Attached.bInitiatorPortProtocol |=
1353 +                           CSMI_SAS_PROTOCOL_STP;
1354 +               if (protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1355 +                    karg->Information.Phy[ii].Attached.bInitiatorPortProtocol |=
1356 +                           CSMI_SAS_PROTOCOL_SMP;
1357 +               if (protocol & MPI_SAS_DEVICE_INFO_SATA_HOST)
1358 +                    karg->Information.Phy[ii].Attached.bInitiatorPortProtocol |=
1359 +                           CSMI_SAS_PROTOCOL_SATA;
1360 +
1361 +               /* Fill in Phy Target Port
1362 +                * Protocol. Bits 10:7
1363 +                * More than one bit can be set.
1364 +                */
1365 +               protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x780;
1366 +               karg->Information.Phy[ii].Attached.bTargetPortProtocol = 0;
1367 +               if (protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1368 +                       karg->Information.Phy[ii].Attached.bTargetPortProtocol |=
1369 +                           CSMI_SAS_PROTOCOL_SSP;
1370 +               if (protocol & MPI_SAS_DEVICE_INFO_STP_TARGET)
1371 +                       karg->Information.Phy[ii].Attached.bTargetPortProtocol |=
1372 +                           CSMI_SAS_PROTOCOL_STP;
1373 +               if (protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1374 +                       karg->Information.Phy[ii].Attached.bTargetPortProtocol |=
1375 +                           CSMI_SAS_PROTOCOL_SMP;
1376 +               if (protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1377 +                       karg->Information.Phy[ii].Attached.bTargetPortProtocol |=
1378 +                           CSMI_SAS_PROTOCOL_SATA;
1379 +
1380 +
1381 +               /* Fill in Attached device type */
1382 +               switch (le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
1383 +                   MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1384 +
1385 +               case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1386 +                       karg->Information.Phy[ii].Attached.bDeviceType =
1387 +                           CSMI_SAS_NO_DEVICE_ATTACHED;
1388 +                       break;
1389 +
1390 +               case MPI_SAS_DEVICE_INFO_END_DEVICE:
1391 +                       karg->Information.Phy[ii].Attached.bDeviceType =
1392 +                           CSMI_SAS_END_DEVICE;
1393 +                       break;
1394 +
1395 +               case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1396 +                       karg->Information.Phy[ii].Attached.bDeviceType =
1397 +                           CSMI_SAS_EDGE_EXPANDER_DEVICE;
1398 +                       break;
1399 +
1400 +               case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1401 +                       karg->Information.Phy[ii].Attached.bDeviceType =
1402 +                           CSMI_SAS_FANOUT_EXPANDER_DEVICE;
1403 +                       break;
1404 +               }
1405 +
1406 +               /* Identify Info. */
1407 +               switch (le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) &
1408 +                   MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1409 +
1410 +               case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1411 +                       karg->Information.Phy[ii].Identify.bDeviceType =
1412 +                           CSMI_SAS_NO_DEVICE_ATTACHED;
1413 +                       break;
1414 +
1415 +               case MPI_SAS_DEVICE_INFO_END_DEVICE:
1416 +                       karg->Information.Phy[ii].Identify.bDeviceType =
1417 +                           CSMI_SAS_END_DEVICE;
1418 +                       break;
1419 +
1420 +               case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1421 +                       karg->Information.Phy[ii].Identify.bDeviceType =
1422 +                           CSMI_SAS_EDGE_EXPANDER_DEVICE;
1423 +                       break;
1424 +
1425 +               case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1426 +                       karg->Information.Phy[ii].Identify.bDeviceType =
1427 +                           CSMI_SAS_FANOUT_EXPANDER_DEVICE;
1428 +                       break;
1429 +               }
1430 +
1431 +               /* Fill in Phy Initiator Port Protocol. Bits 6:3
1432 +                * More than one bit can be set, fall through cases.
1433 +                */
1434 +               protocol = le32_to_cpu(
1435 +                   sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x78;
1436 +               karg->Information.Phy[ii].Identify.bInitiatorPortProtocol = 0;
1437 +               if( protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR )
1438 +                    karg->Information.Phy[ii].Identify.bInitiatorPortProtocol |=
1439 +                           CSMI_SAS_PROTOCOL_SSP;
1440 +               if( protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR )
1441 +                    karg->Information.Phy[ii].Identify.bInitiatorPortProtocol |=
1442 +                           CSMI_SAS_PROTOCOL_STP;
1443 +               if( protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR )
1444 +                    karg->Information.Phy[ii].Identify.bInitiatorPortProtocol |=
1445 +                           CSMI_SAS_PROTOCOL_SMP;
1446 +               if( protocol & MPI_SAS_DEVICE_INFO_SATA_HOST )
1447 +                    karg->Information.Phy[ii].Identify.bInitiatorPortProtocol |=
1448 +                           CSMI_SAS_PROTOCOL_SATA;
1449 +
1450 +               /* Fill in Phy Target Port Protocol. Bits 10:7
1451 +                * More than one bit can be set, fall through cases.
1452 +                */
1453 +               protocol = le32_to_cpu(
1454 +                   sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x780;
1455 +               karg->Information.Phy[ii].Identify.bTargetPortProtocol = 0;
1456 +               if( protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET )
1457 +                       karg->Information.Phy[ii].Identify.bTargetPortProtocol |=
1458 +                           CSMI_SAS_PROTOCOL_SSP;
1459 +               if( protocol & MPI_SAS_DEVICE_INFO_STP_TARGET )
1460 +                       karg->Information.Phy[ii].Identify.bTargetPortProtocol |=
1461 +                           CSMI_SAS_PROTOCOL_STP;
1462 +               if( protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET )
1463 +                       karg->Information.Phy[ii].Identify.bTargetPortProtocol |=
1464 +                           CSMI_SAS_PROTOCOL_SMP;
1465 +               if( protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE )
1466 +                       karg->Information.Phy[ii].Identify.bTargetPortProtocol |=
1467 +                           CSMI_SAS_PROTOCOL_SATA;
1468 +
1469 +               /* Setup SAS Address for the attached device */
1470 +               if (sasPhyPg0->AttachedDevHandle) {
1471 +                       sas_address = reverse_byte_order64(sas_address);
1472 +                       memcpy(karg->Information.Phy[ii].Attached.bSASAddress,
1473 +                           &sas_address, sizeof(u64));
1474 +                       karg->Information.Phy[ii].Attached.bPhyIdentifier =
1475 +                           sasPhyPg0->AttachedPhyIdentifier;
1476 +               }
1477 +
1478 +               /* Setup SAS Address for the parent device */
1479 +               csmisas_sas_device_pg0(ioc, &device_info,
1480 +                   (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1481 +                   MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1482 +                   sasIoUnitPg0->PhyData[ii].ControllerDevHandle);
1483 +               sas_address = reverse_byte_order64(device_info.sas_address);
1484 +               memcpy(karg->Information.Phy[ii].Identify.bSASAddress,
1485 +                   &sas_address, sizeof(u64));
1486 +               karg->Information.Phy[ii].Identify.bPhyIdentifier = ii;
1487 +
1488 +               pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
1489 +                   (u8 *) sasPhyPg0, sasPhyPg0_dma);
1490 +       }
1491 +
1492 +sas_get_phy_info_exit:
1493 +
1494 +       if (sasIoUnitPg0)
1495 +               pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
1496 +                   (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
1497 +
1498 +       /* Copy the data from kernel memory to user memory
1499 +        */
1500 +       if (copy_to_user(uarg, karg,
1501 +           sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
1502 +               printk(KERN_ERR "%s@%d::%s - "
1503 +                   "Unable to write out csmisas_get_phy_info_buffer @ %p\n",
1504 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1505 +               free_pages((unsigned long)karg, memory_pages);
1506 +               return -EFAULT;
1507 +       }
1508 +
1509 +       free_pages((unsigned long)karg, memory_pages);
1510 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
1511 +       return 0;
1512 +}
1513 +
1514 +/**
1515 + * Prototype Routine for the CSMI SAS Set PHY Info command.
1516 + *
1517 + * Outputs:    None.
1518 + * Return:     0 if successful
1519 + *             -EFAULT if data unavailable
1520 + *             -ENODEV if no such device/adapter
1521 + **/
1522 +static int
1523 +csmisas_set_phy_info(unsigned long arg)
1524 +{
1525 +       CSMI_SAS_SET_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
1526 +       CSMI_SAS_SET_PHY_INFO_BUFFER     karg;
1527 +       MPT_ADAPTER                     *ioc = NULL;
1528 +       int                             iocnum;
1529 +
1530 +       if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
1531 +               printk(KERN_ERR "%s@%d::%s() - "
1532 +                   "Unable to read in csmi_sas_set_phy_info struct @ %p\n",
1533 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1534 +               return -EFAULT;
1535 +       }
1536 +
1537 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
1538 +           &ioc)) < 0) || (ioc == NULL)) {
1539 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
1540 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
1541 +               return -ENODEV;
1542 +       }
1543 +
1544 +       if (!csmisas_is_this_sas_cntr(ioc)) {
1545 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
1546 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
1547 +               return -ENODEV;
1548 +       }
1549 +
1550 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
1551 +
1552 +/* TODO - implement IOCTL here */
1553 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
1554 +       dcsmisasprintk(ioc, printk(KERN_DEBUG ": not implemented\n"));
1555 +
1556 +// cim_set_phy_info_exit:
1557 +
1558 +       /* Copy the data from kernel memory to user memory
1559 +        */
1560 +       if (copy_to_user(uarg, &karg,
1561 +                               sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
1562 +               printk(KERN_ERR "%s@%d::%s() - "
1563 +                       "Unable to write out csmi_sas_set_phy_info @ %p\n",
1564 +                               __FILE__, __LINE__, __FUNCTION__, uarg);
1565 +               return -EFAULT;
1566 +       }
1567 +
1568 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
1569 +       return 0;
1570 +
1571 +}
1572 +
1573 +/**
1574 + * Prototype Routine for the CSMI Sas Get SCSI Address command.
1575 + *
1576 + * Outputs:    None.
1577 + * Return:     0 if successful
1578 + *             -EFAULT if data unavailable
1579 + *             -ENODEV if no such device/adapter
1580 + **/
1581 +static int
1582 +csmisas_get_scsi_address(unsigned long arg)
1583 +{
1584 +       CSMI_SAS_GET_SCSI_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
1585 +       CSMI_SAS_GET_SCSI_ADDRESS_BUFFER         karg;
1586 +       MPT_ADAPTER             *ioc = NULL;
1587 +       int                     iocnum;
1588 +       u64                     sas_address;
1589 +       struct sas_device_info  *sas_info;
1590 +
1591 +       if (copy_from_user(&karg, uarg,
1592 +           sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
1593 +               printk(KERN_ERR "%s@%d::%s() - "
1594 +                   "Unable to read in csmi_sas_get_scsi_address struct @ %p\n",
1595 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1596 +               return -EFAULT;
1597 +       }
1598 +
1599 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
1600 +           &ioc)) < 0) || (ioc == NULL)) {
1601 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
1602 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
1603 +               return -ENODEV;
1604 +       }
1605 +
1606 +       if (!csmisas_is_this_sas_cntr(ioc)) {
1607 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
1608 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
1609 +               return -ENODEV;
1610 +       }
1611 +
1612 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
1613 +
1614 +       /* reverse byte order the sas address */
1615 +       memcpy(&sas_address, karg.bSASAddress, sizeof(u64));
1616 +       sas_address = reverse_byte_order64(sas_address);
1617 +
1618 +       /* Search the list for the matching SAS address. */
1619 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SCSI_ADDRESS;
1620 +       karg.bPathId = 0;
1621 +       karg.bTargetId = 0;
1622 +       karg.bLun = 0;
1623 +
1624 +       sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
1625 +       if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
1626 +               goto csmisas_get_scsi_address_exit;
1627 +
1628 +       karg.bPathId = sas_info->os.channel;
1629 +       karg.bTargetId = sas_info->os.id;
1630 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
1631 +
1632 + csmisas_get_scsi_address_exit:
1633 +
1634 +       /* Copy the data from kernel memory to user memory
1635 +        */
1636 +       if (copy_to_user(uarg, &karg,
1637 +           sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
1638 +               printk(KERN_ERR "%s@%d::%s() - "
1639 +                   "Unable to write out csmi_sas_get_scsi_address @ %p\n",
1640 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1641 +               return -EFAULT;
1642 +       }
1643 +
1644 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
1645 +       return 0;
1646 +}
1647 +
1648 +/**
1649 + * Prototype Routine for the CSMI Sas Get SCSI Address command.
1650 + *
1651 + * Outputs:    None.
1652 + * Return:     0 if successful
1653 + *             -EFAULT if data unavailable
1654 + *             -ENODEV if no such device/adapter
1655 + **/
1656 +static int
1657 +csmisas_get_sata_signature(unsigned long arg)
1658 +{
1659 +       CSMI_SAS_SATA_SIGNATURE_BUFFER  __user *uarg = (void __user *) arg;
1660 +       CSMI_SAS_SATA_SIGNATURE_BUFFER   karg;
1661 +       MPT_ADAPTER                     *ioc = NULL;
1662 +       int                             iocnum;
1663 +       int                             rc, jj;
1664 +       ConfigExtendedPageHeader_t      hdr;
1665 +       CONFIGPARMS                     cfg;
1666 +       SasPhyPage0_t                   *sasPhyPg0;
1667 +       dma_addr_t                      sasPhyPg0_dma;
1668 +       int                             sasPhyPg0_data_sz;
1669 +       SasDevicePage1_t                *sasDevicePg1;
1670 +       dma_addr_t                      sasDevicePg1_dma;
1671 +       int                             sasDevicePg1_data_sz;
1672 +       u8                              phyId;
1673 +       u64                             sas_address;
1674 +
1675 +       sasPhyPg0=NULL;
1676 +       sasPhyPg0_data_sz=0;
1677 +       sasDevicePg1=NULL;
1678 +       sasDevicePg1_data_sz=0;
1679 +
1680 +       if (copy_from_user(&karg, uarg,
1681 +            sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
1682 +               printk(KERN_ERR "%s@%d::%s() - "
1683 +                   "Unable to read in csmi_sas_sata_signature struct @ %p\n",
1684 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1685 +               return -EFAULT;
1686 +       }
1687 +
1688 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
1689 +           &ioc)) < 0) || (ioc == NULL)) {
1690 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
1691 +                    __FILE__, __FUNCTION__, __LINE__, iocnum);
1692 +               return -ENODEV;
1693 +       }
1694 +
1695 +       if (!csmisas_is_this_sas_cntr(ioc)) {
1696 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
1697 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
1698 +               return -ENODEV;
1699 +       }
1700 +
1701 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
1702 +       phyId = karg.Signature.bPhyIdentifier;
1703 +       if (phyId >= ioc->num_ports) {
1704 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
1705 +               dcsmisasprintk(ioc, printk(KERN_WARNING ": phyId >= ioc->num_ports\n"));
1706 +               goto cim_sata_signature_exit;
1707 +       }
1708 +
1709 +       /* Default to success.*/
1710 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
1711 +
1712 +       /* Issue a config request to get the devHandle of the attached device
1713 +        */
1714 +
1715 +       /* Issue a config request to get phy information. */
1716 +       hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1717 +       hdr.ExtPageLength = 0;
1718 +       hdr.PageNumber = 0;
1719 +       hdr.Reserved1 = 0;
1720 +       hdr.Reserved2 = 0;
1721 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1722 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1723 +
1724 +       cfg.cfghdr.ehdr = &hdr;
1725 +       cfg.physAddr = -1;
1726 +       cfg.pageAddr = phyId;
1727 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1728 +       cfg.dir = 0;    /* read */
1729 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
1730 +
1731 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
1732 +               /* Don't check if this failed.  Already in a
1733 +                * failure case.
1734 +                */
1735 +               dcsmisasprintk(ioc, printk(KERN_ERR
1736 +                   ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
1737 +               dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
1738 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1739 +               goto cim_sata_signature_exit;
1740 +       }
1741 +
1742 +       if (hdr.ExtPageLength == 0) {
1743 +               /* Don't check if this failed.  Already in a
1744 +                * failure case.
1745 +                */
1746 +               dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
1747 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1748 +               goto cim_sata_signature_exit;
1749 +       }
1750 +
1751 +
1752 +       sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
1753 +       rc = -ENOMEM;
1754 +
1755 +       sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(ioc->pcidev,
1756 +           sasPhyPg0_data_sz, &sasPhyPg0_dma);
1757 +
1758 +       if (! sasPhyPg0) {
1759 +               dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
1760 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1761 +               goto cim_sata_signature_exit;
1762 +       }
1763 +
1764 +       memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
1765 +       cfg.physAddr = sasPhyPg0_dma;
1766 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1767 +
1768 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
1769 +               /* Don't check if this failed.  Already in a
1770 +                * failure case.
1771 +                */
1772 +               dcsmisasprintk(ioc, printk(KERN_ERR
1773 +                   ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
1774 +               dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
1775 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1776 +               goto cim_sata_signature_exit;
1777 +       }
1778 +
1779 +       /* Make sure a SATA device is attached. */
1780 +       if ((le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
1781 +           MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0) {
1782 +               dcsmisasprintk(ioc, printk(KERN_WARNING ": NOT A SATA DEVICE\n"));
1783 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SATA_DEVICE;
1784 +               goto cim_sata_signature_exit;
1785 +       }
1786 +
1787 +       /* Get device page 1 for FIS  signature. */
1788 +       hdr.PageVersion = MPI_SASDEVICE1_PAGEVERSION;
1789 +       hdr.ExtPageLength = 0;
1790 +       hdr.PageNumber = 1 /* page number 1 */;
1791 +       hdr.Reserved1 = 0;
1792 +       hdr.Reserved2 = 0;
1793 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1794 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1795 +
1796 +       cfg.cfghdr.ehdr = &hdr;
1797 +       cfg.physAddr = -1;
1798 +
1799 +       cfg.pageAddr = ((MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1800 +           MPI_SAS_DEVICE_PGAD_FORM_SHIFT) |
1801 +           le16_to_cpu(sasPhyPg0->AttachedDevHandle));
1802 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1803 +       cfg.dir = 0;    /* read */
1804 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
1805 +
1806 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
1807 +               dcsmisasprintk(ioc, printk(KERN_ERR
1808 +                   ": FAILED: MPI_SASDEVICE1_PAGEVERSION: HEADER\n"));
1809 +               dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
1810 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1811 +               goto cim_sata_signature_exit;
1812 +       }
1813 +
1814 +       if (hdr.ExtPageLength == 0) {
1815 +               dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
1816 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1817 +               goto cim_sata_signature_exit;
1818 +       }
1819 +
1820 +       sasDevicePg1_data_sz = hdr.ExtPageLength * 4;
1821 +       rc = -ENOMEM;
1822 +
1823 +       sasDevicePg1 = (SasDevicePage1_t *) pci_alloc_consistent
1824 +           (ioc->pcidev, sasDevicePg1_data_sz, &sasDevicePg1_dma);
1825 +
1826 +       if (! sasDevicePg1) {
1827 +               dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
1828 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1829 +               goto cim_sata_signature_exit;
1830 +       }
1831 +
1832 +       memset((u8 *)sasDevicePg1, 0, sasDevicePg1_data_sz);
1833 +       cfg.physAddr = sasDevicePg1_dma;
1834 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1835 +
1836 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
1837 +               dcsmisasprintk(ioc, printk(KERN_ERR
1838 +                   ": FAILED: MPI_SASDEVICE1_PAGEVERSION: PAGE\n"));
1839 +               dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
1840 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
1841 +               goto cim_sata_signature_exit;
1842 +       }
1843 +
1844 +/* EDM : dump Device Page 1 data*/
1845 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "---- SAS DEVICE PAGE 1 ---------\n"));
1846 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "Handle=0x%x\n",sasDevicePg1->DevHandle));
1847 +       memcpy(&sas_address, &sasDevicePg1->SASAddress, sizeof(u64));
1848 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n",
1849 +           (unsigned long long)sas_address));
1850 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
1851 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "Target ID=0x%x\n",sasDevicePg1->TargetID));
1852 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "Bus=0x%x\n",sasDevicePg1->Bus));
1853 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "Initial Reg Device FIS="));
1854 +       for(jj=0;jj<20;jj++)
1855 +               dcsmisasprintk(ioc, printk("%02x ",
1856 +               ((u8 *)&sasDevicePg1->InitialRegDeviceFIS)[jj]));
1857 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "\n\n"));
1858 +/* EDM : debug data */
1859 +
1860 +       memcpy(karg.Signature.bSignatureFIS,
1861 +               sasDevicePg1->InitialRegDeviceFIS,20);
1862 +
1863 + cim_sata_signature_exit:
1864 +
1865 +       if (sasPhyPg0)
1866 +               pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
1867 +                   (u8 *) sasPhyPg0, sasPhyPg0_dma);
1868 +
1869 +       if (sasDevicePg1)
1870 +               pci_free_consistent(ioc->pcidev, sasDevicePg1_data_sz,
1871 +                   (u8 *) sasDevicePg1, sasDevicePg1_dma);
1872 +
1873 +       /* Copy the data from kernel memory to user memory
1874 +        */
1875 +       if (copy_to_user(uarg, &karg,
1876 +           sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
1877 +               printk(KERN_ERR "%s@%d::%s() - "
1878 +                   "Unable to write out csmi_sas_sata_signature @ %p\n",
1879 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1880 +               return -EFAULT;
1881 +       }
1882 +
1883 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
1884 +       return 0;
1885 +}
1886 +
1887 +/**
1888 + * Prototype Routine for the CSMI Sas Get SCSI Address command.
1889 + *
1890 + * Outputs:    None.
1891 + * Return:     0 if successful
1892 + *             -EFAULT if data unavailable
1893 + *             -ENODEV if no such device/adapter
1894 + **/
1895 +static int
1896 +csmisas_get_device_address(unsigned long arg)
1897 +{
1898 +       CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
1899 +       CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER       karg;
1900 +       MPT_ADAPTER             *ioc = NULL;
1901 +       int                     iocnum;
1902 +       struct sas_device_info  *sas_info;
1903 +       u64                     sas_address;
1904 +
1905 +       if (copy_from_user(&karg, uarg,
1906 +           sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
1907 +               printk(KERN_ERR "%s@%d::%s() - "
1908 +          "Unable to read in csmi_sas_get_device_address_buffer struct @ %p\n",
1909 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1910 +               return -EFAULT;
1911 +       }
1912 +
1913 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
1914 +           &ioc)) < 0) || (ioc == NULL)) {
1915 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
1916 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
1917 +               return -ENODEV;
1918 +       }
1919 +
1920 +       if (!csmisas_is_this_sas_cntr(ioc)) {
1921 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
1922 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
1923 +               return -ENODEV;
1924 +       }
1925 +
1926 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
1927 +
1928 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_DEVICE_ADDRESS;
1929 +       memset(karg.bSASAddress, 0, sizeof(u64));
1930 +       memset(karg.bSASLun, 0, sizeof(karg.bSASLun));
1931 +
1932 +       /* Search the list for the matching SAS address. */
1933 +       sas_info = csmisas_get_device_component_by_os(ioc, karg.bPathId,
1934 +           karg.bTargetId);
1935 +       if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
1936 +               goto csmisas_get_device_address_exit;
1937 +
1938 +       sas_address = reverse_byte_order64(sas_info->sas_address);
1939 +       memcpy(karg.bSASAddress, &sas_address, sizeof(u64));
1940 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
1941 +
1942 + csmisas_get_device_address_exit:
1943 +
1944 +       /* Copy the data from kernel memory to user memory
1945 +        */
1946 +       if (copy_to_user(uarg, &karg,
1947 +           sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
1948 +               printk(KERN_ERR "%s@%d::%s() - "
1949 +               "Unable to write out csmi_sas_get_device_address_buffer @ %p\n",
1950 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1951 +               return -EFAULT;
1952 +       }
1953 +
1954 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
1955 +       return 0;
1956 +}
1957 +
1958 +/**
1959 + * Prototype Routine for the CSMI Sas Get Link Errors command.
1960 + *
1961 + * Outputs:    None.
1962 + * Return:     0 if successful
1963 + *             -EFAULT if data unavailable
1964 + *             -ENODEV if no such device/adapter
1965 + **/
1966 +static int
1967 +csmisas_get_link_errors(unsigned long arg)
1968 +{
1969 +       CSMI_SAS_LINK_ERRORS_BUFFER __user *uarg = (void __user *) arg;
1970 +       CSMI_SAS_LINK_ERRORS_BUFFER      karg;
1971 +       MPT_ADAPTER                     *ioc = NULL;
1972 +       MPT_FRAME_HDR                   *mf = NULL;
1973 +       MPIHeader_t                     *mpi_hdr;
1974 +       int                             iocnum;
1975 +       int                             rc;
1976 +       ConfigExtendedPageHeader_t      hdr;
1977 +       CONFIGPARMS                     cfg;
1978 +       SasPhyPage1_t                   *sasPhyPage1;
1979 +       dma_addr_t                      sasPhyPage1_dma;
1980 +       int                             sasPhyPage1_data_sz;
1981 +       SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
1982 +       SasIoUnitControlReply_t         *sasIoUnitCntrReply;
1983 +       u8                              phyId;
1984 +       u16                             ioc_status;
1985 +       u32                             MsgContext;
1986 +
1987 +       sasPhyPage1=NULL;
1988 +       sasPhyPage1_data_sz=0;
1989 +
1990 +       if (copy_from_user(&karg, uarg,
1991 +            sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
1992 +               printk(KERN_ERR "%s@%d::%s() - "
1993 +                   "Unable to read in csmisas_get_link_errors struct @ %p\n",
1994 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
1995 +               return -EFAULT;
1996 +       }
1997 +
1998 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
1999 +           &ioc)) < 0) || (ioc == NULL)) {
2000 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
2001 +                    __FILE__, __FUNCTION__, __LINE__, iocnum);
2002 +               return -ENODEV;
2003 +       }
2004 +
2005 +       if (!csmisas_is_this_sas_cntr(ioc)) {
2006 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
2007 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
2008 +               return -ENODEV;
2009 +       }
2010 +
2011 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
2012 +       phyId = karg.Information.bPhyIdentifier;
2013 +       if (phyId >= ioc->num_ports) {
2014 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
2015 +               dcsmisasprintk(ioc, printk(KERN_WARNING ": phyId >= ioc->num_ports\n"));
2016 +               goto cim_get_link_errors_exit;
2017 +       }
2018 +
2019 +       /* Default to success.*/
2020 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
2021 +
2022 +       /* Issue a config request to get the devHandle of the attached device
2023 +        */
2024 +
2025 +       /* Issue a config request to get phy information. */
2026 +       hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
2027 +       hdr.ExtPageLength = 0;
2028 +       hdr.PageNumber = 1 /* page number 1*/;
2029 +       hdr.Reserved1 = 0;
2030 +       hdr.Reserved2 = 0;
2031 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2032 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2033 +
2034 +       cfg.cfghdr.ehdr = &hdr;
2035 +       cfg.physAddr = -1;
2036 +       cfg.pageAddr = phyId;
2037 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2038 +       cfg.dir = 0;    /* read */
2039 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
2040 +
2041 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
2042 +               /* Don't check if this failed.  Already in a
2043 +                * failure case.
2044 +                */
2045 +               dcsmisasprintk(ioc, printk(KERN_ERR
2046 +                   ": FAILED: MPI_SASPHY1_PAGEVERSION: HEADER\n"));
2047 +               dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
2048 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2049 +               goto cim_get_link_errors_exit;
2050 +       }
2051 +
2052 +       if (hdr.ExtPageLength == 0) {
2053 +               /* Don't check if this failed.  Already in a
2054 +                * failure case.
2055 +                */
2056 +               dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
2057 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2058 +               goto cim_get_link_errors_exit;
2059 +       }
2060 +
2061 +
2062 +       sasPhyPage1_data_sz = hdr.ExtPageLength * 4;
2063 +       rc = -ENOMEM;
2064 +
2065 +       sasPhyPage1 = (SasPhyPage1_t *) pci_alloc_consistent(ioc->pcidev,
2066 +           sasPhyPage1_data_sz, &sasPhyPage1_dma);
2067 +
2068 +       if (! sasPhyPage1) {
2069 +               dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
2070 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2071 +               goto cim_get_link_errors_exit;
2072 +       }
2073 +
2074 +       memset((u8 *)sasPhyPage1, 0, sasPhyPage1_data_sz);
2075 +       cfg.physAddr = sasPhyPage1_dma;
2076 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2077 +
2078 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
2079 +               /* Don't check if this failed.  Already in a
2080 +                * failure case.
2081 +                */
2082 +               dcsmisasprintk(ioc, printk(KERN_ERR ": FAILED: MPI_SASPHY1_PAGEVERSION: PAGE\n"));
2083 +               dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
2084 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2085 +               goto cim_get_link_errors_exit;
2086 +       }
2087 +
2088 +/* EDM : dump PHY Page 1 data*/
2089 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 1 ------------\n"));
2090 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "Invalid Dword Count=0x%x\n",
2091 +           sasPhyPage1->InvalidDwordCount));
2092 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "Running Disparity Error Count=0x%x\n",
2093 +           sasPhyPage1->RunningDisparityErrorCount));
2094 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "Loss Dword Synch Count=0x%x\n",
2095 +           sasPhyPage1->LossDwordSynchCount));
2096 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "PHY Reset Problem Count=0x%x\n",
2097 +           sasPhyPage1->PhyResetProblemCount));
2098 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "\n\n"));
2099 +/* EDM : debug data */
2100 +
2101 +       karg.Information.uInvalidDwordCount =
2102 +               le32_to_cpu(sasPhyPage1->InvalidDwordCount);
2103 +       karg.Information.uRunningDisparityErrorCount =
2104 +               le32_to_cpu(sasPhyPage1->RunningDisparityErrorCount);
2105 +       karg.Information.uLossOfDwordSyncCount =
2106 +               le32_to_cpu(sasPhyPage1->LossDwordSynchCount);
2107 +       karg.Information.uPhyResetProblemCount =
2108 +               le32_to_cpu(sasPhyPage1->PhyResetProblemCount);
2109 +
2110 +       if (karg.Information.bResetCounts ==
2111 +           CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS ) {
2112 +               goto cim_get_link_errors_exit;
2113 +       }
2114 +
2115 +       /* Clear Error log
2116 +        *
2117 +        * Issue IOUNIT Control Reqeust Message
2118 +        */
2119 +
2120 +       /* Get a MF for this command.
2121 +        */
2122 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
2123 +               dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
2124 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2125 +               goto cim_get_link_errors_exit;
2126 +        }
2127 +
2128 +       mpi_hdr = (MPIHeader_t *) mf;
2129 +       MsgContext = mpi_hdr->MsgContext;
2130 +       sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
2131 +       memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
2132 +       sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
2133 +       sasIoUnitCntrReq->MsgContext = MsgContext;
2134 +       sasIoUnitCntrReq->PhyNum = phyId;
2135 +       sasIoUnitCntrReq->Operation = MPI_SAS_OP_PHY_CLEAR_ERROR_LOG;
2136 +
2137 +       if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) {
2138 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2139 +               goto cim_get_link_errors_exit;
2140 +       }
2141 +
2142 +       /* process the completed Reply Message Frame */
2143 +       if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
2144 +
2145 +               sasIoUnitCntrReply =
2146 +                   (SasIoUnitControlReply_t *)ioc->ioctl_cmds.reply;
2147 +               ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus)
2148 +                   & MPI_IOCSTATUS_MASK;
2149 +
2150 +               if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
2151 +                       dcsmisasprintk(ioc, printk(KERN_DEBUG ": SAS IO Unit Control: "));
2152 +                       dcsmisasprintk(ioc, printk("IOCStatus=0x%X IOCLogInfo=0x%X\n",
2153 +                           sasIoUnitCntrReply->IOCStatus,
2154 +                           sasIoUnitCntrReply->IOCLogInfo));
2155 +               }
2156 +       }
2157 +
2158 + cim_get_link_errors_exit:
2159 +
2160 +       if (sasPhyPage1)
2161 +               pci_free_consistent(ioc->pcidev, sasPhyPage1_data_sz,
2162 +                   (u8 *) sasPhyPage1, sasPhyPage1_dma);
2163 +
2164 +       /* Copy the data from kernel memory to user memory
2165 +        */
2166 +       if (copy_to_user(uarg, &karg,
2167 +           sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
2168 +               printk(KERN_ERR "%s@%d::%s() - "
2169 +                   "Unable to write out csmisas_get_link_errors @ %p\n",
2170 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
2171 +               return -EFAULT;
2172 +       }
2173 +
2174 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
2175 +       return 0;
2176 +
2177 +}
2178 +
2179 +/**
2180 + * Prototype Routine for the CSMI SAS SMP Passthru command.
2181 + *
2182 + * Outputs:    None.
2183 + * Return:     0 if successful
2184 + *             -EFAULT if data unavailable
2185 + *             -ENODEV if no such device/adapter
2186 + **/
2187 +static int
2188 +csmisas_smp_passthru(unsigned long arg)
2189 +{
2190 +       CSMI_SAS_SMP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
2191 +       MPT_ADAPTER                     *ioc;
2192 +       CSMI_SAS_SMP_PASSTHRU_BUFFER     *karg;
2193 +       pSmpPassthroughRequest_t        smpReq;
2194 +       pSmpPassthroughReply_t          smpReply;
2195 +       MPT_FRAME_HDR                   *mf = NULL;
2196 +       MPIHeader_t                     *mpi_hdr;
2197 +       char                            *psge;
2198 +       int                             iocnum, flagsLength;
2199 +       void *                          request_data;
2200 +       dma_addr_t                      request_data_dma;
2201 +       u32                             request_data_sz;
2202 +       void *                          response_data;
2203 +       dma_addr_t                      response_data_dma;
2204 +       u32                             response_data_sz;
2205 +       u16                             ioc_status;
2206 +       u64                             sas_address;
2207 +       u32                             MsgContext;
2208 +       int                             malloc_data_sz;
2209 +       int                             memory_pages;
2210 +
2211 +       malloc_data_sz = sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER);
2212 +       memory_pages = get_order(malloc_data_sz);
2213 +       karg = (CSMI_SAS_SMP_PASSTHRU_BUFFER *)__get_free_pages(
2214 +               GFP_KERNEL, memory_pages);
2215 +       if (!karg){
2216 +               printk(KERN_ERR "%s@%d::%s() - "
2217 +                       "Unable to malloc CSMI_SAS_SMP_PASSTHRU_BUFFER "
2218 +                       "malloc_data_sz=%d memory_pages=%d\n",
2219 +                       __FILE__, __LINE__, __FUNCTION__,
2220 +                       malloc_data_sz, memory_pages);
2221 +               return -ENOMEM;
2222 +       }
2223 +
2224 +       if (copy_from_user(karg, uarg, sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
2225 +               printk(KERN_ERR "%s@%d::%s() - "
2226 +                   "Unable to read in csmi_sas_smp_passthru struct @ %p\n",
2227 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
2228 +               free_pages((unsigned long)karg, memory_pages);
2229 +               return -EFAULT;
2230 +       }
2231 +
2232 +       request_data = NULL;
2233 +       response_data = NULL;
2234 +       response_data_sz = sizeof(CSMI_SAS_SMP_RESPONSE);
2235 +       request_data_sz  = karg->Parameters.uRequestLength;
2236 +
2237 +       if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
2238 +           &ioc)) < 0) || (ioc == NULL)) {
2239 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
2240 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
2241 +               free_pages((unsigned long)karg, memory_pages);
2242 +               return -ENODEV;
2243 +       }
2244 +
2245 +       if (ioc->ioc_reset_in_progress) {
2246 +               printk(KERN_ERR "%s@%d::%s - "
2247 +                   "Busy with IOC Reset \n",
2248 +                   __FILE__, __LINE__,__FUNCTION__);
2249 +               free_pages((unsigned long)karg, memory_pages);
2250 +               return -EBUSY;
2251 +       }
2252 +
2253 +       if (!csmisas_is_this_sas_cntr(ioc)) {
2254 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
2255 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
2256 +               free_pages((unsigned long)karg, memory_pages);
2257 +               return -ENODEV;
2258 +       }
2259 +
2260 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
2261 +
2262 +       /* Default to success.*/
2263 +       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
2264 +
2265 +       /* Do some error checking on the request. */
2266 +       if (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
2267 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
2268 +               goto cim_smp_passthru_exit;
2269 +       }
2270 +
2271 +       if ((request_data_sz > 0xFFFF) || (!request_data_sz)) {
2272 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2273 +               goto cim_smp_passthru_exit;
2274 +       }
2275 +
2276 +       /* Get a free request frame and save the message context.
2277 +        */
2278 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
2279 +               dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
2280 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2281 +               goto cim_smp_passthru_exit;
2282 +        }
2283 +
2284 +       mpi_hdr = (MPIHeader_t *) mf;
2285 +       MsgContext = mpi_hdr->MsgContext;
2286 +       smpReq = (pSmpPassthroughRequest_t ) mf;
2287 +
2288 +       memset(smpReq,0,ioc->req_sz);
2289 +
2290 +       memcpy(&sas_address, karg->Parameters.bDestinationSASAddress,
2291 +           sizeof(u64));
2292 +       sas_address = cpu_to_le64(reverse_byte_order64(sas_address));
2293 +       memcpy(&smpReq->SASAddress, &sas_address, sizeof(u64));
2294 +
2295 +       /* Fill in smp request. */
2296 +       smpReq->PhysicalPort = karg->Parameters.bPortIdentifier;
2297 +       smpReq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2298 +       smpReq->RequestDataLength = cpu_to_le16(request_data_sz);
2299 +       smpReq->ConnectionRate = karg->Parameters.bConnectionRate;
2300 +       smpReq->MsgContext = MsgContext;
2301 +       smpReq->Reserved2 = 0;
2302 +       smpReq->Reserved3 = 0;
2303 +
2304 +       /*
2305 +        * Prepare the necessary pointers to run
2306 +        * through the SGL generation
2307 +        */
2308 +
2309 +       psge = (char *)&smpReq->SGL;
2310 +
2311 +       /* setup the *Request* payload SGE */
2312 +       flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2313 +               MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2314 +               MPI_SGE_FLAGS_HOST_TO_IOC |
2315 +               MPI_SGE_FLAGS_END_OF_BUFFER;
2316 +
2317 +       flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2318 +       flagsLength |= request_data_sz;
2319 +
2320 +       request_data = pci_alloc_consistent(
2321 +           ioc->pcidev, request_data_sz, &request_data_dma);
2322 +
2323 +       if (!request_data) {
2324 +               dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
2325 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2326 +               mpt_free_msg_frame(ioc, mf);
2327 +               goto cim_smp_passthru_exit;
2328 +       }
2329 +
2330 +       ioc->add_sge(psge, flagsLength, request_data_dma);
2331 +       psge += ioc->SGE_size;
2332 +
2333 +       memcpy(request_data, &karg->Parameters.Request, request_data_sz);
2334 +
2335 +       /* setup the *Response* payload SGE */
2336 +       response_data = pci_alloc_consistent(
2337 +           ioc->pcidev, response_data_sz, &response_data_dma);
2338 +
2339 +       if (!response_data) {
2340 +               dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
2341 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2342 +               mpt_free_msg_frame(ioc, mf);
2343 +               goto cim_smp_passthru_exit;
2344 +       }
2345 +
2346 +       flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2347 +               MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2348 +               MPI_SGE_FLAGS_IOC_TO_HOST |
2349 +               MPI_SGE_FLAGS_END_OF_BUFFER;
2350 +
2351 +       flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2352 +       flagsLength |= response_data_sz;
2353 +
2354 +       ioc->add_sge(psge, flagsLength, response_data_dma);
2355 +
2356 +       if (csmisas_send_command_wait(ioc, mf, karg->IoctlHeader.Timeout) != 0) {
2357 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2358 +               goto cim_smp_passthru_exit;
2359 +       }
2360 +
2361 +       if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
2362 +               dcsmisasprintk(ioc, printk(KERN_DEBUG ": SMP Passthru: oh no, there is no reply!!"));
2363 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2364 +               goto cim_smp_passthru_exit;
2365 +       }
2366 +
2367 +       /* process the completed Reply Message Frame */
2368 +       smpReply = (pSmpPassthroughReply_t )ioc->ioctl_cmds.reply;
2369 +       ioc_status = le16_to_cpu(smpReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2370 +
2371 +       if ((ioc_status != MPI_IOCSTATUS_SUCCESS) &&
2372 +           (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
2373 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2374 +               dcsmisasprintk(ioc, printk(KERN_DEBUG ": SMP Passthru: "));
2375 +               dcsmisasprintk(ioc, printk("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
2376 +                   le16_to_cpu(smpReply->IOCStatus),
2377 +                   le32_to_cpu(smpReply->IOCLogInfo),
2378 +                   smpReply->SASStatus));
2379 +               goto cim_smp_passthru_exit;
2380 +       }
2381 +
2382 +       karg->Parameters.bConnectionStatus =
2383 +           map_sas_status_to_csmi(smpReply->SASStatus);
2384 +
2385 +
2386 +       if (le16_to_cpu(smpReply->ResponseDataLength)) {
2387 +               karg->Parameters.uResponseBytes = le16_to_cpu(smpReply->ResponseDataLength);
2388 +               memcpy(&karg->Parameters.Response,
2389 +                   response_data, le16_to_cpu(smpReply->ResponseDataLength));
2390 +       }
2391 +
2392 + cim_smp_passthru_exit:
2393 +
2394 +       if (request_data)
2395 +               pci_free_consistent(ioc->pcidev, request_data_sz,
2396 +                   (u8 *)request_data, request_data_dma);
2397 +
2398 +       if (response_data)
2399 +               pci_free_consistent(ioc->pcidev, response_data_sz,
2400 +                   (u8 *)response_data, response_data_dma);
2401 +
2402 +
2403 +       /* Copy the data from kernel memory to user memory
2404 +        */
2405 +       if (copy_to_user(uarg, karg,
2406 +           sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
2407 +               printk(KERN_ERR "%s@%d::%s() - "
2408 +                       "Unable to write out csmi_sas_smp_passthru @ %p\n",
2409 +                               __FILE__, __LINE__, __FUNCTION__, uarg);
2410 +               free_pages((unsigned long)karg, memory_pages);
2411 +               return -EFAULT;
2412 +       }
2413 +
2414 +       free_pages((unsigned long)karg, memory_pages);
2415 +       dcsmisasprintk(ioc, printk(KERN_DEBUG ": %s exit.\n",__FUNCTION__));
2416 +       return 0;
2417 +}
2418 +
2419 +/**
2420 + * Prototype Routine for the CSMI SAS SSP Passthru command.
2421 + *
2422 + * Outputs:    None.
2423 + * Return:     0 if successful
2424 + *             -EFAULT if data unavailable
2425 + *             -ENODEV if no such device/adapter
2426 + **/
2427 +static int csmisas_ssp_passthru(unsigned long arg)
2428 +{
2429 +       CSMI_SAS_SSP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
2430 +       CSMI_SAS_SSP_PASSTHRU_BUFFER     karg_hdr, * karg;
2431 +       MPT_ADAPTER                     *ioc = NULL;
2432 +       pSCSIIORequest_t                pScsiRequest;
2433 +       pSCSIIOReply_t                  pScsiReply;
2434 +       MPT_FRAME_HDR                   *mf = NULL;
2435 +       MPIHeader_t                     *mpi_hdr;
2436 +       int                             iocnum,ii;
2437 +       u64                             sas_address;
2438 +       u16                             req_idx;
2439 +       char                            *psge;
2440 +       int                             flagsLength;
2441 +       void *                          request_data;
2442 +       dma_addr_t                      request_data_dma;
2443 +       u32                             request_data_sz;
2444 +       int                             malloc_data_sz;
2445 +       int                             memory_pages;
2446 +       u16                             ioc_status;
2447 +       u8                              volume_id;
2448 +       u8                              volume_bus;
2449 +       u8                              is_hidden_raid_component;
2450 +       u8                              channel;
2451 +       u8                              id;
2452 +       struct sas_device_info          *sas_info;
2453 +       u8                              skey, asc, ascq;
2454 +       u32                             MsgContext;
2455 +
2456 +       if (copy_from_user(&karg_hdr, uarg, sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER))) {
2457 +               printk(KERN_ERR "%s@%d::%s() - "
2458 +                   "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
2459 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
2460 +               return -EFAULT;
2461 +       }
2462 +
2463 +       request_data = NULL;
2464 +       request_data_sz = karg_hdr.Parameters.uDataLength;
2465 +       channel = 0;
2466 +       id = 0;
2467 +       volume_id = 0;
2468 +       volume_bus = 0;
2469 +       is_hidden_raid_component = 0;
2470 +
2471 +       malloc_data_sz = (request_data_sz +
2472 +           offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER, bDataBuffer));
2473 +       memory_pages = get_order(malloc_data_sz);
2474 +       karg = (CSMI_SAS_SSP_PASSTHRU_BUFFER *)__get_free_pages(
2475 +               GFP_KERNEL, memory_pages);
2476 +       if (!karg){
2477 +               printk(KERN_ERR "%s@%d::%s() - "
2478 +                       "Unable to malloc SAS_SSP_PASSTHRU_BUFFER "
2479 +                       "malloc_data_sz=%d memory_pages=%d\n",
2480 +                       __FILE__, __LINE__, __FUNCTION__,
2481 +                       malloc_data_sz, memory_pages);
2482 +               return -ENOMEM;
2483 +       }
2484 +
2485 +       memset(karg, 0, sizeof(*karg));
2486 +
2487 +       if (copy_from_user(karg, uarg, request_data_sz +
2488 +           offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer))) {
2489 +               printk(KERN_ERR "%s@%d::%s() - "
2490 +                   "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
2491 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
2492 +               free_pages((unsigned long)karg, memory_pages);
2493 +               return -EFAULT;
2494 +       }
2495 +
2496 +       /*
2497 +        * some checks of the incoming frame
2498 +        */
2499 +       if ( offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer) +
2500 +           request_data_sz - sizeof(IOCTL_HEADER) >
2501 +           karg->IoctlHeader.Length ) {
2502 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
2503 +               dcsmisasprintk(ioc, printk(KERN_ERR
2504 +                   "%s::%s()"
2505 +                   " @%d - expected datalen incorrect!\n",
2506 +                   __FILE__, __FUNCTION__, __LINE__));
2507 +               goto cim_ssp_passthru_exit;
2508 +       }
2509 +
2510 +       if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
2511 +           &ioc)) < 0) || (ioc == NULL)) {
2512 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
2513 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
2514 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
2515 +               goto cim_ssp_passthru_exit;
2516 +       }
2517 +
2518 +       if (ioc->ioc_reset_in_progress) {
2519 +               printk(KERN_ERR "%s@%d::%s - "
2520 +                   "Busy with IOC Reset \n",
2521 +                   __FILE__, __LINE__,__FUNCTION__);
2522 +               return -EBUSY;
2523 +       }
2524 +
2525 +       if (!csmisas_is_this_sas_cntr(ioc)) {
2526 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
2527 +               printk(KERN_ERR "%s::%s()@%d - ioc%d not SAS controller!\n",
2528 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
2529 +               goto cim_ssp_passthru_exit;
2530 +       }
2531 +
2532 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
2533 +
2534 +       /* Default to success.
2535 +        */
2536 +       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
2537 +
2538 +       /* Neither a phy nor a port has been selected.
2539 +        */
2540 +       if ((karg->Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
2541 +               (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
2542 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
2543 +               dcsmisasprintk(ioc, printk(KERN_ERR
2544 +                   "%s::%s()"
2545 +                   " @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
2546 +                   __FILE__, __FUNCTION__, __LINE__));
2547 +               goto cim_ssp_passthru_exit;
2548 +       }
2549 +
2550 +       /* A phy has been selected. Verify that it's valid.
2551 +        */
2552 +       if (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
2553 +
2554 +               /* Is the phy in range? */
2555 +               if (karg->Parameters.bPhyIdentifier >= ioc->num_ports) {
2556 +                       dcsmisasprintk(ioc, printk(KERN_WARNING ": phyId >= ioc->num_ports (%d %d)\n",
2557 +                           karg->Parameters.bPhyIdentifier,
2558 +                           ioc->num_ports));
2559 +                       karg->IoctlHeader.ReturnCode =
2560 +                           CSMI_SAS_PHY_DOES_NOT_EXIST;
2561 +                       goto cim_ssp_passthru_exit;
2562 +               }
2563 +       }
2564 +
2565 +       if(karg->Parameters.bAdditionalCDBLength) {
2566 +       /* TODO - SCSI IO (32) Request Message support
2567 +        */
2568 +               dcsmisasprintk(ioc, printk(KERN_DEBUG ": greater than 16-byte cdb "
2569 +                   "is not supported!\n"));
2570 +                   karg->IoctlHeader.ReturnCode =
2571 +                       CSMI_SAS_STATUS_INVALID_PARAMETER;
2572 +               goto cim_ssp_passthru_exit;
2573 +       }
2574 +
2575 +       /* we will use SAS address to resolve the scsi adddressing
2576 +        */
2577 +       memcpy(&sas_address, karg->Parameters.bDestinationSASAddress,
2578 +           sizeof(u64));
2579 +       sas_address = reverse_byte_order64(sas_address);
2580 +
2581 +       /* Search the list for the matching SAS address.
2582 +        */
2583 +       sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
2584 +       if (!sas_info || sas_info->is_cached) {
2585 +               /*
2586 +                *Invalid SAS address
2587 +                */
2588 +               karg->IoctlHeader.ReturnCode =
2589 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
2590 +               dcsmisasprintk(ioc, printk(KERN_ERR
2591 +                   "%s::%s() @%d - couldn't find associated "
2592 +                   "SASAddress=%llX!\n", __FILE__, __FUNCTION__, __LINE__,
2593 +                   (unsigned long long)sas_address));
2594 +               goto cim_ssp_passthru_exit;
2595 +       }
2596 +
2597 +       id = sas_info->fw.id;
2598 +       channel = sas_info->fw.channel;
2599 +
2600 +       if (csmisas_is_phys_disk(ioc, channel, id)) {
2601 +               id = csmisas_raid_id_to_num(ioc, channel, id);
2602 +               channel = 0;
2603 +               is_hidden_raid_component = 1;
2604 +       }
2605 +
2606 +       /* Get a free request frame and save the message context.
2607 +        */
2608 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
2609 +               dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
2610 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2611 +               goto cim_ssp_passthru_exit;
2612 +        }
2613 +
2614 +       mpi_hdr = (MPIHeader_t *) mf;
2615 +       MsgContext = mpi_hdr->MsgContext;
2616 +       pScsiRequest = (pSCSIIORequest_t) mf;
2617 +       req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2618 +
2619 +       memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
2620 +
2621 +       /* Fill in SCSI IO (16) request.
2622 +        */
2623 +
2624 +       pScsiRequest->Function = (is_hidden_raid_component == 1) ?
2625 +           MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : MPI_FUNCTION_SCSI_IO_REQUEST;
2626 +       pScsiRequest->TargetID = id;
2627 +       pScsiRequest->Bus = channel;
2628 +       memcpy(pScsiRequest->LUN, &karg->Parameters.bLun, 8);
2629 +       pScsiRequest->CDBLength = karg->Parameters.bCDBLength;
2630 +       pScsiRequest->DataLength = cpu_to_le32(request_data_sz);
2631 +       pScsiRequest->MsgContext = MsgContext;
2632 +       memcpy(pScsiRequest->CDB, karg->Parameters.bCDB,
2633 +           pScsiRequest->CDBLength);
2634 +
2635 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "\tchannel = %d id = %d ",
2636 +           sas_info->fw.channel, sas_info->fw.id));
2637 +       dcsmisasprintk(ioc, if(is_hidden_raid_component)
2638 +           printk(KERN_DEBUG "num_id = %d ", id));
2639 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
2640 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "\tcdb_len = %d request_len = %d\n",
2641 +           pScsiRequest->CDBLength, request_data_sz));
2642 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "\t"));
2643 +       dcsmisasprintk(ioc, for (ii = 0; ii < pScsiRequest->CDBLength; ++ii)
2644 +           printk(" %02x", pScsiRequest->CDB[ii]));
2645 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
2646 +
2647 +       /* direction
2648 +        */
2649 +       if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) {
2650 +               pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
2651 +       } else if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
2652 +               pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_WRITE);
2653 +       } else if ((karg->Parameters.uFlags & CSMI_SAS_SSP_UNSPECIFIED) &&
2654 +           (!karg->Parameters.uDataLength)) {
2655 +               /* no data transfer
2656 +                */
2657 +               pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_NODATATRANSFER);
2658 +       } else {
2659 +               /* no direction specified
2660 +                */
2661 +               pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
2662 +               pScsiRequest->MsgFlags =
2663 +                   MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR;
2664 +       }
2665 +
2666 +       pScsiRequest->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
2667 +       if (ioc->sg_addr_size == sizeof(u64))
2668 +               pScsiRequest->MsgFlags |= MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64;
2669 +
2670 +       /* task attributes
2671 +        */
2672 +       if((karg->Parameters.uFlags && 0xFF) == 0) {
2673 +               pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
2674 +       } else if (karg->Parameters.uFlags &
2675 +           CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE) {
2676 +               pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_HEADOFQ);
2677 +       } else if (karg->Parameters.uFlags &
2678 +           CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED) {
2679 +               pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ORDEREDQ);
2680 +       } else if (karg->Parameters.uFlags &
2681 +           CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA) {
2682 +               pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ACAQ);
2683 +       } else {
2684 +               pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_UNTAGGED);
2685 +       }
2686 +
2687 +       /* setup sense
2688 +        */
2689 +       pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2690 +       pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
2691 +           (req_idx * MPT_SENSE_BUFFER_ALLOC));
2692 +
2693 +       /* setup databuffer sg, assuming we fit everything one contiguous buffer
2694 +        */
2695 +       psge = (char *)&pScsiRequest->SGL;
2696 +
2697 +       if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
2698 +               flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
2699 +       } else if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) {
2700 +               flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
2701 +       }else {
2702 +               flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2703 +                               MPI_SGE_FLAGS_DIRECTION )
2704 +                               << MPI_SGE_FLAGS_SHIFT;
2705 +       }
2706 +       flagsLength |= request_data_sz;
2707 +
2708 +       if ( request_data_sz > 0) {
2709 +               request_data = pci_alloc_consistent(
2710 +                   ioc->pcidev, request_data_sz, &request_data_dma);
2711 +
2712 +               if (request_data == NULL) {
2713 +                       dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED "
2714 +                           "request_data_sz=%d\n", request_data_sz));
2715 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2716 +                       mpt_free_msg_frame(ioc, mf);
2717 +                       goto cim_ssp_passthru_exit;
2718 +               }
2719 +
2720 +               ioc->add_sge(psge, flagsLength, request_data_dma);
2721 +               if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE)
2722 +                       memcpy(request_data, karg->bDataBuffer, request_data_sz);
2723 +       } else {
2724 +               ioc->add_sge(psge, flagsLength, (dma_addr_t) -1);
2725 +       }
2726 +
2727 +       if (csmisas_send_command_wait(ioc, mf, karg->IoctlHeader.Timeout) != 0) {
2728 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2729 +               goto cim_ssp_passthru_exit;
2730 +       }
2731 +
2732 +       memset(&karg->Status,0,sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
2733 +       karg->Status.bConnectionStatus = CSMI_SAS_OPEN_ACCEPT;
2734 +       karg->Status.bDataPresent = CSMI_SAS_SSP_NO_DATA_PRESENT;
2735 +       karg->Status.bStatus = GOOD;
2736 +       karg->Status.bResponseLength[0] = 0;
2737 +       karg->Status.bResponseLength[1] = 0;
2738 +       karg->Status.uDataBytes = request_data_sz;
2739 +
2740 +       /* process the completed Reply Message Frame */
2741 +       if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
2742 +
2743 +               pScsiReply = (pSCSIIOReply_t ) ioc->ioctl_cmds.reply;
2744 +               karg->Status.bStatus = pScsiReply->SCSIStatus;
2745 +               karg->Status.uDataBytes = min(le32_to_cpu(pScsiReply->TransferCount),
2746 +                   request_data_sz);
2747 +               ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2748 +
2749 +               if (pScsiReply->SCSIState ==
2750 +                   MPI_SCSI_STATE_AUTOSENSE_VALID) {
2751 +                       karg->Status.bConnectionStatus =
2752 +                           CSMI_SAS_SSP_SENSE_DATA_PRESENT;
2753 +                       karg->Status.bResponseLength[0] =
2754 +                               (u8)le32_to_cpu(pScsiReply->SenseCount) & 0xFF;
2755 +                       memcpy(karg->Status.bResponse,
2756 +                           ioc->ioctl_cmds.sense, le32_to_cpu(pScsiReply->SenseCount));
2757 +
2758 +                       skey = ioc->ioctl_cmds.sense[2] & 0x0F;
2759 +                       asc = ioc->ioctl_cmds.sense[12];
2760 +                       ascq = ioc->ioctl_cmds.sense[13];
2761 +
2762 +                       dcsmisasprintk(ioc, printk(KERN_DEBUG "\t [sense_key,asc,ascq]: "
2763 +                           "[0x%02x,0x%02x,0x%02x]\n",
2764 +                           skey, asc, ascq));
2765 +
2766 +               } else if(pScsiReply->SCSIState ==
2767 +                   MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
2768 +                       karg->Status.bDataPresent =
2769 +                           CSMI_SAS_SSP_RESPONSE_DATA_PRESENT;
2770 +                       karg->Status.bResponseLength[0] =
2771 +                               sizeof(pScsiReply->ResponseInfo);
2772 +                       for (ii=0;ii<sizeof(pScsiReply->ResponseInfo);ii++) {
2773 +                               karg->Status.bResponse[ii] =
2774 +                               ((u8*)&pScsiReply->ResponseInfo)[
2775 +                                   (sizeof(pScsiReply->ResponseInfo)-1)-ii];
2776 +                       }
2777 +               } else if ((ioc_status != MPI_IOCSTATUS_SUCCESS) &&
2778 +                   (ioc_status !=  MPI_IOCSTATUS_SCSI_RECOVERED_ERROR) &&
2779 +                   (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
2780 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2781 +                       dcsmisasprintk(ioc, printk(KERN_DEBUG ": SCSI IO : "));
2782 +                       dcsmisasprintk(ioc, printk("IOCStatus=0x%X IOCLogInfo=0x%X\n",
2783 +                           pScsiReply->IOCStatus,
2784 +                           pScsiReply->IOCLogInfo));
2785 +               }
2786 +       }
2787 +
2788 +       if ((karg->Status.uDataBytes) && (request_data) &&
2789 +           (karg->Parameters.uFlags & CSMI_SAS_SSP_READ)) {
2790 +               if (copy_to_user((void __user *)uarg->bDataBuffer,
2791 +                   request_data, karg->Status.uDataBytes)) {
2792 +                       printk(KERN_ERR "%s@%d::%s - "
2793 +                           "Unable to write data to user %p\n",
2794 +                           __FILE__, __LINE__,__FUNCTION__,
2795 +                           (void*)karg->bDataBuffer);
2796 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
2797 +               }
2798 +       }
2799 +
2800 + cim_ssp_passthru_exit:
2801 +
2802 +
2803 +       if (request_data)
2804 +               pci_free_consistent(ioc->pcidev, request_data_sz,
2805 +                   (u8 *)request_data, request_data_dma);
2806 +
2807 +       /* Copy the data from kernel memory to user memory
2808 +        */
2809 +       if (copy_to_user(uarg, karg,
2810 +           offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER, bDataBuffer))) {
2811 +               printk(KERN_ERR "%s@%d::%s() - "
2812 +                       "Unable to write out csmi_sas_ssp_passthru @ %p\n",
2813 +                               __FILE__, __LINE__, __FUNCTION__, uarg);
2814 +               free_pages((unsigned long)karg, memory_pages);
2815 +               return -EFAULT;
2816 +       }
2817 +
2818 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
2819 +       free_pages((unsigned long)karg, memory_pages);
2820 +       return 0;
2821 +}
2822 +
2823 +/**
2824 + * Prototype Routine for the CSMI SAS STP Passthru command.
2825 + *
2826 + * Outputs:    None.
2827 + * Return:     0 if successful
2828 + *             -EFAULT if data unavailable
2829 + *             -ENODEV if no such device/adapter
2830 + **/
2831 +static int
2832 +csmisas_stp_passthru(unsigned long arg)
2833 +{
2834 +       CSMI_SAS_STP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
2835 +       CSMI_SAS_STP_PASSTHRU_BUFFER    karg_hdr, *karg;
2836 +       MPT_ADAPTER                     *ioc = NULL;
2837 +       pSataPassthroughRequest_t       pSataRequest;
2838 +       pSataPassthroughReply_t         pSataReply;
2839 +       MPT_FRAME_HDR                   *mf = NULL;
2840 +       MPIHeader_t                     *mpi_hdr;
2841 +       int                             iocnum;
2842 +       u32                             data_sz;
2843 +       u64                             sas_address;
2844 +       u16                             req_idx;
2845 +       char                            *psge;
2846 +       int                             flagsLength;
2847 +       void *                          request_data;
2848 +       dma_addr_t                      request_data_dma;
2849 +       u32                             request_data_sz;
2850 +       int                             malloc_data_sz;
2851 +       int                             memory_pages;
2852 +       u8                              channel;
2853 +       u8                              id;
2854 +       u8                              volume_id;
2855 +       u8                              volume_bus;
2856 +       struct sas_device_info          *sas_info;
2857 +       u16                             ioc_status;
2858 +       u32                             MsgContext;
2859 +
2860 +       if (copy_from_user(&karg_hdr, uarg, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER))) {
2861 +               printk(KERN_ERR "%s@%d::%s() - "
2862 +                   "Unable to read struct @ %p\n",
2863 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
2864 +               return -EFAULT;
2865 +       }
2866 +
2867 +       request_data=NULL;
2868 +       request_data_sz = karg_hdr.Parameters.uDataLength;
2869 +       volume_id = 0;
2870 +       volume_bus = 0;
2871 +       channel = 0;
2872 +       id = 0;
2873 +
2874 +       malloc_data_sz = (request_data_sz +
2875 +           offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER, bDataBuffer));
2876 +       memory_pages = get_order(malloc_data_sz);
2877 +       karg = (CSMI_SAS_STP_PASSTHRU_BUFFER *)__get_free_pages(
2878 +               GFP_KERNEL, memory_pages);
2879 +       if (!karg){
2880 +               printk(KERN_ERR "%s@%d::%s() - "
2881 +                       "Unable to malloc CSMI_SAS_STP_PASSTHRU_BUFFER "
2882 +                       "malloc_data_sz=%d memory_pages=%d\n",
2883 +                       __FILE__, __LINE__, __FUNCTION__,
2884 +                       malloc_data_sz, memory_pages);
2885 +               return -ENOMEM;
2886 +       }
2887 +
2888 +       memset(karg, 0, sizeof(*karg));
2889 +
2890 +       if (copy_from_user(karg, uarg, malloc_data_sz)) {
2891 +               printk(KERN_ERR "%s@%d::%s() - "
2892 +                   "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
2893 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
2894 +               free_pages((unsigned long)karg, memory_pages);
2895 +               return -EFAULT;
2896 +       }
2897 +
2898 +       if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
2899 +           &ioc)) < 0) || (ioc == NULL)) {
2900 +               printk(KERN_ERR "%s::%s @%d - ioc%d not found!\n",
2901 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
2902 +               free_pages((unsigned long)karg, memory_pages);
2903 +               return -ENODEV;
2904 +       }
2905 +
2906 +       if (ioc->ioc_reset_in_progress) {
2907 +               printk(KERN_ERR "%s@%d::%s - "
2908 +                   "Busy with IOC Reset \n",
2909 +                   __FILE__, __LINE__,__FUNCTION__);
2910 +               free_pages((unsigned long)karg, memory_pages);
2911 +               return -EBUSY;
2912 +       }
2913 +
2914 +       if (!csmisas_is_this_sas_cntr(ioc)) {
2915 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
2916 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
2917 +               free_pages((unsigned long)karg, memory_pages);
2918 +               return -ENODEV;
2919 +       }
2920 +
2921 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
2922 +
2923 +       /* Default to success.
2924 +        */
2925 +       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
2926 +
2927 +       /* Neither a phy nor a port has been selected.
2928 +        */
2929 +       if ((karg->Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
2930 +               (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
2931 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
2932 +               dcsmisasprintk(ioc, printk(KERN_ERR
2933 +                   "%s::%s() @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
2934 +                   __FILE__,__FUNCTION__, __LINE__));
2935 +               goto cim_stp_passthru_exit;
2936 +       }
2937 +
2938 +       /* A phy has been selected. Verify that it's valid.
2939 +        */
2940 +       if (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
2941 +
2942 +               /* Is the phy in range? */
2943 +               if (karg->Parameters.bPhyIdentifier >= ioc->num_ports) {
2944 +                       karg->IoctlHeader.ReturnCode =
2945 +                           CSMI_SAS_PHY_DOES_NOT_EXIST;
2946 +                       goto cim_stp_passthru_exit;
2947 +               }
2948 +       }
2949 +
2950 +       data_sz = sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) -
2951 +           sizeof(IOCTL_HEADER) - sizeof(u8*) +
2952 +           request_data_sz;
2953 +
2954 +       if ( data_sz > karg->IoctlHeader.Length ) {
2955 +               karg->IoctlHeader.ReturnCode =
2956 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
2957 +               dcsmisasprintk(ioc, printk(KERN_ERR
2958 +                   "%s::%s() @%d - expected datalen incorrect!\n",
2959 +                   __FILE__, __FUNCTION__,__LINE__));
2960 +               goto cim_stp_passthru_exit;
2961 +       }
2962 +
2963 +
2964 +       /* we will use SAS address to resolve the scsi adddressing
2965 +        */
2966 +       memcpy(&sas_address, karg->Parameters.bDestinationSASAddress,
2967 +           sizeof(u64));
2968 +       sas_address = reverse_byte_order64(sas_address);
2969 +
2970 +       /* Search the list for the matching SAS address.
2971 +        */
2972 +       sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
2973 +       if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume) {
2974 +               /*
2975 +                *Invalid SAS address
2976 +                */
2977 +               karg->IoctlHeader.ReturnCode =
2978 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
2979 +               dcsmisasprintk(ioc, printk(KERN_ERR
2980 +                   "%s::%s() @%d - couldn't find associated "
2981 +                   "SASAddress=%llX!\n", __FILE__, __FUNCTION__, __LINE__,
2982 +                   (unsigned long long)sas_address));
2983 +               goto cim_stp_passthru_exit;
2984 +       }
2985 +
2986 +       id = sas_info->fw.id;
2987 +       channel = sas_info->fw.channel;
2988 +
2989 +       /* check that this is an STP or SATA target device
2990 +        */
2991 +       if ( !(sas_info->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET ) &&
2992 +            !(sas_info->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE )) {
2993 +               karg->IoctlHeader.ReturnCode =
2994 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
2995 +               goto cim_stp_passthru_exit;
2996 +       }
2997 +
2998 +       /* Get a free request frame and save the message context.
2999 +        */
3000 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
3001 +               dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
3002 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3003 +               goto cim_stp_passthru_exit;
3004 +        }
3005 +
3006 +       mpi_hdr = (MPIHeader_t *) mf;
3007 +       MsgContext = mpi_hdr->MsgContext;
3008 +       pSataRequest = (pSataPassthroughRequest_t) mf;
3009 +       req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3010 +
3011 +       memset(pSataRequest,0,sizeof(pSataPassthroughRequest_t));
3012 +
3013 +       pSataRequest->TargetID = id;
3014 +       pSataRequest->Bus = channel;
3015 +       pSataRequest->Function = MPI_FUNCTION_SATA_PASSTHROUGH;
3016 +       pSataRequest->PassthroughFlags = cpu_to_le16(karg->Parameters.uFlags);
3017 +       pSataRequest->ConnectionRate = karg->Parameters.bConnectionRate;
3018 +       pSataRequest->MsgContext = MsgContext;
3019 +       pSataRequest->DataLength = cpu_to_le32(request_data_sz);
3020 +       pSataRequest->MsgFlags = 0;
3021 +       memcpy( pSataRequest->CommandFIS,karg->Parameters.bCommandFIS, 20);
3022 +
3023 +       psge = (char *)&pSataRequest->SGL;
3024 +       if (karg->Parameters.uFlags & CSMI_SAS_STP_WRITE) {
3025 +               flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
3026 +       } else if (karg->Parameters.uFlags & CSMI_SAS_STP_READ) {
3027 +               flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
3028 +       }else {
3029 +               flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3030 +                               MPI_SGE_FLAGS_DIRECTION )
3031 +                               << MPI_SGE_FLAGS_SHIFT;
3032 +       }
3033 +
3034 +       flagsLength |= request_data_sz;
3035 +       if (request_data_sz > 0) {
3036 +               request_data = pci_alloc_consistent(
3037 +                   ioc->pcidev, request_data_sz, &request_data_dma);
3038 +
3039 +               if (request_data == NULL) {
3040 +                       dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
3041 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3042 +                       mpt_free_msg_frame(ioc, mf);
3043 +                       goto cim_stp_passthru_exit;
3044 +               }
3045 +
3046 +               ioc->add_sge(psge, flagsLength, request_data_dma);
3047 +               if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE)
3048 +                       memcpy(request_data, karg->bDataBuffer, request_data_sz);
3049 +       } else {
3050 +               ioc->add_sge(psge, flagsLength, (dma_addr_t) -1);
3051 +       }
3052 +
3053 +       if (csmisas_send_command_wait(ioc, mf, karg->IoctlHeader.Timeout) != 0) {
3054 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3055 +               goto cim_stp_passthru_exit;
3056 +       }
3057 +
3058 +       memset(&karg->Status,0,sizeof(CSMI_SAS_STP_PASSTHRU_STATUS));
3059 +
3060 +       if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
3061 +               dcsmisasprintk(ioc, printk(KERN_DEBUG  ": STP Passthru: oh no, there is no reply!!"));
3062 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3063 +               goto cim_stp_passthru_exit;
3064 +       }
3065 +
3066 +       /* process the completed Reply Message Frame */
3067 +       pSataReply = (pSataPassthroughReply_t ) ioc->ioctl_cmds.reply;
3068 +       ioc_status = le16_to_cpu(pSataReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3069 +
3070 +       if (ioc_status != MPI_IOCSTATUS_SUCCESS &&
3071 +           ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) {
3072 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3073 +               dcsmisasprintk(ioc, printk(KERN_DEBUG ": STP Passthru: "));
3074 +               dcsmisasprintk(ioc, printk("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
3075 +                   le16_to_cpu(pSataReply->IOCStatus),
3076 +                   le32_to_cpu(pSataReply->IOCLogInfo),
3077 +                   pSataReply->SASStatus));
3078 +       }
3079 +
3080 +       karg->Status.bConnectionStatus =
3081 +           map_sas_status_to_csmi(pSataReply->SASStatus);
3082 +
3083 +       memcpy(karg->Status.bStatusFIS,pSataReply->StatusFIS, 20);
3084 +
3085 +       /*
3086 +        * for now, just zero out uSCR array,
3087 +        * then copy the one dword returned
3088 +        * in the reply frame into uSCR[0]
3089 +        */
3090 +       memset( karg->Status.uSCR, 0, 64);
3091 +       karg->Status.uSCR[0] = le32_to_cpu(pSataReply->StatusControlRegisters);
3092 +
3093 +       if((le32_to_cpu(pSataReply->TransferCount)) && (request_data) &&
3094 +           (karg->Parameters.uFlags & CSMI_SAS_STP_READ)) {
3095 +               karg->Status.uDataBytes =
3096 +                   min(le32_to_cpu(pSataReply->TransferCount),request_data_sz);
3097 +               if (copy_to_user((void __user *)uarg->bDataBuffer,
3098 +                   request_data, karg->Status.uDataBytes)) {
3099 +                       printk(KERN_ERR "%s::%s() @%d - "
3100 +                           "Unable to write data to user %p\n",
3101 +                           __FILE__, __FUNCTION__, __LINE__,
3102 +                           (void*)karg->bDataBuffer);
3103 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3104 +               }
3105 +       }
3106 +
3107 + cim_stp_passthru_exit:
3108 +
3109 +       if (request_data)
3110 +               pci_free_consistent(ioc->pcidev, request_data_sz,
3111 +                   (u8 *)request_data, request_data_dma);
3112 +
3113 +       /* Copy th data from kernel memory to user memory
3114 +        */
3115 +       if (copy_to_user(uarg, karg,
3116 +           offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER, bDataBuffer))) {
3117 +               printk(KERN_ERR "%s@%d::%s() - "
3118 +                       "Unable to write out csmi_sas_ssp_passthru @ %p\n",
3119 +                               __FILE__, __LINE__, __FUNCTION__, uarg);
3120 +               free_pages((unsigned long)karg, memory_pages);
3121 +               return -EFAULT;
3122 +       }
3123 +
3124 +       free_pages((unsigned long)karg, memory_pages);
3125 +       dcsmisasprintk(ioc, printk(KERN_DEBUG ": %s exit.\n",__FUNCTION__));
3126 +       return 0;
3127 +}
3128 +
3129 +/**
3130 + * Prototype Routine for the CSMI SAS Firmware Download command.
3131 + *
3132 + * Outputs:    None.
3133 + * Return:     0 if successful
3134 + *             -EFAULT if data unavailable
3135 + *             -ENODEV if no such device/adapter
3136 + **/
3137 +static int
3138 +csmisas_firmware_download(unsigned long arg)
3139 +{
3140 +       CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER __user *uarg = (void __user *) arg;
3141 +       CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER        karg;
3142 +       MPT_ADAPTER                     *ioc = NULL;
3143 +       int                             iocnum;
3144 +       pMpiFwHeader_t                  pFwHeader=NULL;
3145 +
3146 +       if (copy_from_user(&karg, uarg,
3147 +               sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
3148 +               printk(KERN_ERR "%s@%d::%s() - "
3149 +                   "Unable to read in csmi_sas_firmware_download struct @ %p\n",
3150 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
3151 +               return -EFAULT;
3152 +       }
3153 +
3154 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
3155 +           &ioc)) < 0) || (ioc == NULL)) {
3156 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
3157 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
3158 +               return -ENODEV;
3159 +       }
3160 +
3161 +       if (!csmisas_is_this_sas_cntr(ioc)) {
3162 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
3163 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
3164 +               return -ENODEV;
3165 +       }
3166 +
3167 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
3168 +
3169 +       /* Default to success.*/
3170 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
3171 +       karg.Information.usStatus = CSMI_SAS_FWD_SUCCESS;
3172 +       karg.Information.usSeverity = CSMI_SAS_FWD_INFORMATION;
3173 +
3174 +       /* some checks of the incoming frame */
3175 +       if ((karg.Information.uBufferLength +
3176 +           sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD)) >
3177 +           karg.IoctlHeader.Length) {
3178 +               karg.IoctlHeader.ReturnCode =
3179 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
3180 +               karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
3181 +               goto cim_firmware_download_exit;
3182 +       }
3183 +
3184 +       if ( karg.Information.uDownloadFlags &
3185 +           (CSMI_SAS_FWD_SOFT_RESET | CSMI_SAS_FWD_VALIDATE)) {
3186 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3187 +               karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
3188 +               karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
3189 +               goto cim_firmware_download_exit;
3190 +       }
3191 +
3192 +       /* now we need to alloc memory so we can pull in the
3193 +        * fw image attached to end of incoming packet.
3194 +        */
3195 +       pFwHeader = kmalloc(karg.Information.uBufferLength, GFP_KERNEL);
3196 +       if (!pFwHeader){
3197 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3198 +               karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
3199 +               karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
3200 +               goto cim_firmware_download_exit;
3201 +       }
3202 +       memset(pFwHeader, 0, sizeof(*pFwHeader));
3203 +
3204 +       if (copy_from_user(pFwHeader, uarg->bDataBuffer,
3205 +               karg.Information.uBufferLength)) {
3206 +               printk(KERN_ERR "%s@%d::%s() - "
3207 +                   "Unable to read in pFwHeader @ %p\n",
3208 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
3209 +               return -EFAULT;
3210 +       }
3211 +
3212 +       if ( !((pFwHeader->Signature0 == MPI_FW_HEADER_SIGNATURE_0) &&
3213 +           (pFwHeader->Signature1 == MPI_FW_HEADER_SIGNATURE_1) &&
3214 +           (pFwHeader->Signature2 == MPI_FW_HEADER_SIGNATURE_2))) {
3215 +               // the signature check failed
3216 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3217 +               karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
3218 +               karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
3219 +               goto cim_firmware_download_exit;
3220 +       }
3221 +
3222 +       if ( mptctl_do_fw_download(karg.IoctlHeader.IOControllerNumber,
3223 +           uarg->bDataBuffer, karg.Information.uBufferLength)
3224 +           != 0) {
3225 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3226 +               karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
3227 +               karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
3228 +               goto cim_firmware_download_exit;
3229 +       }
3230 +
3231 +       if((karg.Information.uDownloadFlags & CSMI_SAS_FWD_SOFT_RESET) ||
3232 +           (karg.Information.uDownloadFlags & CSMI_SAS_FWD_HARD_RESET)) {
3233 +               if (mpt_HardResetHandler(ioc, CAN_SLEEP) != 0) {
3234 +                       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3235 +                       karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
3236 +                       karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
3237 +               }
3238 +       }
3239 +
3240 + cim_firmware_download_exit:
3241 +
3242 +       if(pFwHeader)
3243 +               kfree(pFwHeader);
3244 +
3245 +       /* Copy the data from kernel memory to user memory
3246 +        */
3247 +       if (copy_to_user(uarg, &karg,
3248 +                               sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
3249 +               printk(KERN_ERR "%s@%d::%s() - "
3250 +                       "Unable to write out csmi_sas_firmware_download @ %p\n",
3251 +                               __FILE__, __LINE__, __FUNCTION__, uarg);
3252 +               return -EFAULT;
3253 +       }
3254 +
3255 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
3256 +       return 0;
3257 +}
3258 +
3259 +/**
3260 + * Prototype Routine for the CSMI SAS Get RAID Info command.
3261 + *
3262 + * Outputs:    None.
3263 + * Return:     0 if successful
3264 + *             -EFAULT if data unavailable
3265 + *             -ENODEV if no such device/adapter
3266 + **/
3267 +static int
3268 +csmisas_get_raid_info(unsigned long arg)
3269 +{
3270 +       CSMI_SAS_RAID_INFO_BUFFER __user *uarg =  (void __user *) arg;
3271 +       CSMI_SAS_RAID_INFO_BUFFER        karg;
3272 +       MPT_ADAPTER                     *ioc = NULL;
3273 +       int                             iocnum;
3274 +       u32                             raidFlags;
3275 +       u8                              maxRaidTypes;
3276 +       u8                              maxDrivesPerSet;
3277 +
3278 +       if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
3279 +               printk(KERN_ERR "%s@%d::%s() - "
3280 +                   "Unable to read in csmi_sas_get_raid_info struct @ %p\n",
3281 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
3282 +               return -EFAULT;
3283 +       }
3284 +
3285 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
3286 +           &ioc)) < 0) || (ioc == NULL)) {
3287 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
3288 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
3289 +               return -ENODEV;
3290 +       }
3291 +
3292 +       if (!csmisas_is_this_sas_cntr(ioc)) {
3293 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
3294 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
3295 +               return -ENODEV;
3296 +       }
3297 +
3298 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
3299 +
3300 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3301 +       if (!ioc->raid_data.pIocPg2)
3302 +               goto csmisas_get_raid_info_out;
3303 +       karg.Information.uNumRaidSets =
3304 +           ioc->raid_data.pIocPg2->NumActiveVolumes;
3305 +       karg.Information.uMaxRaidSets = ioc->raid_data.pIocPg2->MaxVolumes;
3306 +       if( ioc->raid_data.pIocPg6 ) {
3307 +               // get absolute maximum for all RAID sets
3308 +               maxDrivesPerSet = ioc->raid_data.pIocPg6->MaxDrivesIS;
3309 +               maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIM,
3310 +                   maxDrivesPerSet);
3311 +               maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIME,
3312 +                   maxDrivesPerSet);
3313 +               karg.Information.uMaxDrivesPerSet = maxDrivesPerSet;
3314 +       }
3315 +       else
3316 +               karg.Information.uMaxDrivesPerSet = 8;
3317 +       // For bMaxRaidSets, count bits set in bits 0-6 of CapabilitiesFlags
3318 +       raidFlags = ioc->raid_data.pIocPg2->CapabilitiesFlags & 0x0000007F;
3319 +       for( maxRaidTypes=0; raidFlags; maxRaidTypes++ )
3320 +               raidFlags &= raidFlags - 1;
3321 +       karg.Information.bMaxRaidTypes = maxRaidTypes;
3322 +       // ulMinRaidSetBlocks hard coded to 1MB until available from config page
3323 +       karg.Information.ulMinRaidSetBlocks.uLowPart = 2048;
3324 +       karg.Information.ulMinRaidSetBlocks.uHighPart = 0;
3325 +       karg.Information.ulMaxRaidSetBlocks.uLowPart = 0xffffffff;
3326 +       if( ioc->raid_data.pIocPg2->CapabilitiesFlags &
3327 +           MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING )
3328 +               karg.Information.ulMaxRaidSetBlocks.uHighPart = 0xffffffff;
3329 +       else
3330 +               karg.Information.ulMaxRaidSetBlocks.uHighPart = 0;
3331 +       karg.Information.uMaxPhysicalDrives =
3332 +           ioc->raid_data.pIocPg2->MaxPhysDisks;
3333 +       karg.Information.uMaxExtents = 1;
3334 +       karg.Information.uMaxModules = 0;
3335 +       karg.Information.uMaxTransformationMemory = 0;
3336 +       karg.Information.uChangeCount = ioc->csmi_change_count;
3337 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
3338 +
3339 +csmisas_get_raid_info_out:
3340 +
3341 +       /* Copy the data from kernel memory to user memory
3342 +        */
3343 +       if (copy_to_user(uarg, &karg,
3344 +                               sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
3345 +               printk(KERN_ERR "%s@%d::%s() - "
3346 +                       "Unable to write out csmi_sas_get_raid_info @ %p\n",
3347 +                               __FILE__, __LINE__, __FUNCTION__, uarg);
3348 +               return -EFAULT;
3349 +       }
3350 +
3351 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
3352 +       return 0;
3353 +}
3354 +
3355 +/**
3356 + *     csmisas_do_raid - Format and Issue a RAID volume request message.
3357 + *     @ioc: Pointer to MPT_ADAPTER structure
3358 + *     @action: What do be done.
3359 + *     @PhysDiskNum: Logical target id.
3360 + *     @VolumeBus: Target locations bus.
3361 + *     @VolumeId: Volume id
3362 + *
3363 + *     Returns: < 0 on a fatal error
3364 + *             0 on success
3365 + *
3366 + *     Remark: Wait to return until reply processed by the ISR.
3367 + **/
3368 +static int
3369 +csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, u8 VolumeId, pMpiRaidActionReply_t reply)
3370 +{
3371 +       MpiRaidActionRequest_t  *pReq;
3372 +       MpiRaidActionReply_t    *pReply;
3373 +       MPT_FRAME_HDR           *mf;
3374 +
3375 +       /* Get and Populate a free Frame
3376 +        */
3377 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
3378 +               dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
3379 +               return -EAGAIN;
3380 +       }
3381 +       pReq = (MpiRaidActionRequest_t *)mf;
3382 +       pReq->Action = action;
3383 +       pReq->Reserved1 = 0;
3384 +       pReq->ChainOffset = 0;
3385 +       pReq->Function = MPI_FUNCTION_RAID_ACTION;
3386 +       pReq->VolumeID = VolumeId;
3387 +       pReq->VolumeBus = VolumeBus;
3388 +       pReq->PhysDiskNum = PhysDiskNum;
3389 +       pReq->MsgFlags = 0;
3390 +       pReq->Reserved2 = 0;
3391 +       pReq->ActionDataWord = 0; /* Reserved for this action */
3392 +       //pReq->ActionDataSGE = 0;
3393 +
3394 +       ioc->add_sge((char *)&pReq->ActionDataSGE,
3395 +               MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
3396 +
3397 +       if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0)
3398 +               return -ENODATA;
3399 +
3400 +       if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) &&
3401 +           (reply != NULL)){
3402 +               pReply = (MpiRaidActionReply_t *)&(ioc->ioctl_cmds.reply);
3403 +               memcpy(reply, pReply,
3404 +                       min(ioc->reply_sz,
3405 +                       4*pReply->MsgLength));
3406 +       }
3407 +
3408 +       return 0;
3409 +}
3410 +
3411 +/**
3412 + * csmisas_raid_inq
3413 + * @ioc = per host instance
3414 + * @opcode = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH or
3415 + *          MPI_FUNCTION_SCSI_IO_REQUEST
3416 + * @id = target id
3417 + * @bus = target bus
3418 + * @inq_vpd = inquiry data, returned
3419 + * @inq_vpd_sz = maximum size of inquiry data
3420 + *
3421 + * Return = 0(sucess), non-zero(failure)
3422 + **/
3423 +static int
3424 +csmisas_raid_inq(MPT_ADAPTER *ioc, u8 opcode, u8 bus, u8 id, u8 inq_vpd_page,
3425 +    u8 * inq_vpd, u32 inq_vpd_sz)
3426 +{
3427 +       MPT_FRAME_HDR           *mf = NULL;
3428 +       MPIHeader_t             *mpi_hdr;
3429 +       pSCSIIORequest_t        pScsiRequest;
3430 +       u16                     req_idx;
3431 +       char                    *psge;
3432 +       u8                      inq_vpd_cdb[6];
3433 +       u8                      *request_data=NULL;
3434 +       dma_addr_t              request_data_dma;
3435 +       u32                     request_data_sz;
3436 +       int                     rc = 0;
3437 +       u32                     MsgContext;
3438 +
3439 +       request_data_sz = inq_vpd_sz;
3440 +
3441 +       /* fill-in cdb */
3442 +       memset(inq_vpd_cdb, 0, sizeof(inq_vpd_cdb));
3443 +       inq_vpd_cdb[0] = 0x12;
3444 +       if (inq_vpd_page) {
3445 +               inq_vpd_cdb[1] = 0x01; /* evpd bit */
3446 +               inq_vpd_cdb[2] = inq_vpd_page;
3447 +       }
3448 +       inq_vpd_cdb[3] = (u8)(request_data_sz >> 8);
3449 +       inq_vpd_cdb[4] = (u8)request_data_sz;
3450 +
3451 +       /* Get a free request frame and save the message context.
3452 +        */
3453 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
3454 +               dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
3455 +               goto csmisas_raid_inq_exit;
3456 +       }
3457 +
3458 +       mpi_hdr = (MPIHeader_t *) mf;
3459 +       MsgContext = mpi_hdr->MsgContext;
3460 +       pScsiRequest = (pSCSIIORequest_t) mf;
3461 +       req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3462 +
3463 +       memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
3464 +       pScsiRequest->Function = opcode;
3465 +       pScsiRequest->TargetID = id;
3466 +       pScsiRequest->Bus = bus;
3467 +       pScsiRequest->CDBLength = 6;
3468 +       pScsiRequest->DataLength = cpu_to_le32(request_data_sz);
3469 +       pScsiRequest->MsgContext = MsgContext;
3470 +       memcpy(pScsiRequest->CDB,inq_vpd_cdb,pScsiRequest->CDBLength);
3471 +       pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
3472 +       pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
3473 +       pScsiRequest->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
3474 +       if (ioc->sg_addr_size == sizeof(u64))
3475 +               pScsiRequest->MsgFlags |= MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64;
3476 +
3477 +       /* setup sense
3478 +        */
3479 +       pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3480 +       pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
3481 +           (req_idx * MPT_SENSE_BUFFER_ALLOC));
3482 +
3483 +       request_data = pci_alloc_consistent(
3484 +           ioc->pcidev, request_data_sz, &request_data_dma);
3485 +
3486 +       if (request_data == NULL) {
3487 +               mpt_free_msg_frame(ioc, mf);
3488 +               rc=-1;
3489 +               goto csmisas_raid_inq_exit;
3490 +       }
3491 +
3492 +       memset(request_data,0,request_data_sz);
3493 +       psge = (char *)&pScsiRequest->SGL;
3494 +       ioc->add_sge(psge, (MPT_SGE_FLAGS_SSIMPLE_READ | 0xFC) ,
3495 +           request_data_dma);
3496 +
3497 +       if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0) {
3498 +               rc=-1;
3499 +               goto csmisas_raid_inq_exit;
3500 +       }
3501 +
3502 +       /* copy the request_data */
3503 +       memcpy(inq_vpd, request_data, request_data_sz);
3504 +
3505 + csmisas_raid_inq_exit:
3506 +
3507 +       if (request_data)
3508 +               pci_free_consistent(ioc->pcidev, request_data_sz,
3509 +                   request_data, request_data_dma);
3510 +
3511 +       return rc;
3512 +}
3513 +
3514 +/**
3515 + * Prototype Routine for the CSMI SAS Get RAID Config command.
3516 + *
3517 + * Outputs:    None.
3518 + * Return:     0 if successful
3519 + *             -EFAULT if data unavailable
3520 + *             -ENODEV if no such device/adapter
3521 + **/
3522 +static int
3523 +csmisas_get_raid_config(unsigned long arg)
3524 +{
3525 +       CSMI_SAS_RAID_CONFIG_BUFFER __user *uarg = (void __user *) arg;
3526 +       CSMI_SAS_RAID_CONFIG_BUFFER      karg,*pKarg=NULL;
3527 +       CONFIGPARMS                     cfg;
3528 +       ConfigPageHeader_t              header;
3529 +       MPT_ADAPTER                     *ioc = NULL;
3530 +       int                             iocnum;
3531 +       u8                              volumeID, VolumeBus;
3532 +       u8                              physDiskNum, physDiskNumMax;
3533 +       int                             volumepage0sz = 0;
3534 +       int                             physdiskpage0sz = 0, ioc_page5_sz = 0;
3535 +       dma_addr_t                      volume0_dma, physdisk0_dma;
3536 +       dma_addr_t                      ioc_page5_dma = 0;
3537 +       pRaidVolumePage0_t              pVolume0 = NULL;
3538 +       pRaidPhysDiskPage0_t            pPhysDisk0 = NULL;
3539 +       pMpiRaidActionReply_t           pRaidActionReply = NULL;
3540 +       u32                             device_info = 0;
3541 +       pIOCPage5_t                     pIocPage5 = NULL;
3542 +       int                             i, idx, csmi_sas_raid_config_buffer_sz;
3543 +       int                             memory_pages;
3544 +       int                             copy_buffer_sz = 0;
3545 +       u64                             totalMaxLBA, tmpTotalMaxLBA;
3546 +       u64                             sas_address;
3547 +       struct sas_device_info          *sas_info;
3548 +
3549 +       if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
3550 +               printk(KERN_ERR "%s@%d::%s() - "
3551 +                   "Unable to read in csmisas_get_raid_config struct @ %p\n",
3552 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
3553 +               return -EFAULT;
3554 +       }
3555 +
3556 +       csmi_sas_raid_config_buffer_sz = karg.IoctlHeader.Length;
3557 +       memory_pages = get_order(csmi_sas_raid_config_buffer_sz);
3558 +       pKarg = (CSMI_SAS_RAID_CONFIG_BUFFER *)__get_free_pages(
3559 +               GFP_KERNEL, memory_pages);
3560 +       if (!pKarg){
3561 +               printk(KERN_ERR "%s@%d::%s() - "
3562 +                   "Unable to malloc RAID_CONFIG_BUFFER "
3563 +                       "csmi_sas_raid_config_buffer_sz=%d memory_pages=%d\n",
3564 +                       __FILE__, __LINE__, __FUNCTION__,
3565 +                       csmi_sas_raid_config_buffer_sz, memory_pages);
3566 +               return -ENOMEM;
3567 +       }
3568 +       memset(pKarg, 0, sizeof(*pKarg));
3569 +
3570 +       if (copy_from_user(pKarg, uarg, csmi_sas_raid_config_buffer_sz)) {
3571 +               printk(KERN_ERR "%s@%d::%s() - "
3572 +                   "Unable to read in csmisas_get_raid_config struct @ %p\n",
3573 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
3574 +               free_pages((unsigned long)pKarg, memory_pages);
3575 +               return -EFAULT;
3576 +       }
3577 +
3578 +       if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
3579 +           &ioc)) < 0) || (ioc == NULL)) {
3580 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
3581 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
3582 +               free_pages((unsigned long)pKarg, memory_pages);
3583 +               return -ENODEV;
3584 +       }
3585 +
3586 +       if (!csmisas_is_this_sas_cntr(ioc)) {
3587 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
3588 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
3589 +               free_pages((unsigned long)pKarg, memory_pages);
3590 +               return -ENODEV;
3591 +       }
3592 +
3593 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
3594 +
3595 +       if (pKarg->Configuration.uChangeCount != 0 &&
3596 +               pKarg->Configuration.uChangeCount != ioc->csmi_change_count ) {
3597 +               pKarg->IoctlHeader.ReturnCode =
3598 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
3599 +               pKarg->Configuration.uFailureCode =
3600 +                   CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
3601 +               goto cim_get_raid_config_exit;
3602 +       }
3603 +
3604 +       if (!ioc->raid_data.pIocPg2) {
3605 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3606 +               goto cim_get_raid_config_exit;
3607 +       }
3608 +
3609 +       /*
3610 +        * Check to see if the input uRaidSetIndex is
3611 +        * greater than the number of RAID sets
3612 +        */
3613 +       if (pKarg->Configuration.uRaidSetIndex >=
3614 +           ioc->raid_data.pIocPg2->NumActiveVolumes) {
3615 +               pKarg->IoctlHeader.ReturnCode = CSMI_SAS_RAID_SET_OUT_OF_RANGE;
3616 +               goto cim_get_raid_config_exit;
3617 +       }
3618 +
3619 +       /*
3620 +        * get RAID Volume Page 0
3621 +        */
3622 +       volumeID = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeID;
3623 +       VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeBus;
3624 +
3625 +       header.PageVersion = 0;
3626 +       header.PageLength = 0;
3627 +       header.PageNumber = 0;
3628 +       header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
3629 +       cfg.cfghdr.hdr = &header;
3630 +       cfg.physAddr = -1;
3631 +       cfg.pageAddr = (VolumeBus << 8) + volumeID;
3632 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3633 +       cfg.dir = 0;
3634 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
3635 +       if (mpt_config(ioc, &cfg) != 0) {
3636 +               pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3637 +               goto cim_get_raid_config_exit;
3638 +       }
3639 +
3640 +       if (header.PageLength == 0) {
3641 +               pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3642 +               goto cim_get_raid_config_exit;
3643 +       }
3644 +
3645 +       volumepage0sz = header.PageLength * 4;
3646 +       pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
3647 +           &volume0_dma);
3648 +       if (!pVolume0) {
3649 +               pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3650 +               goto cim_get_raid_config_exit;
3651 +       }
3652 +
3653 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3654 +       cfg.physAddr = volume0_dma;
3655 +       if (mpt_config(ioc, &cfg) != 0) {
3656 +               pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3657 +               goto cim_get_raid_config_exit;
3658 +       }
3659 +
3660 +       totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) |
3661 +           ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32;
3662 +       tmpTotalMaxLBA = totalMaxLBA + 1;
3663 +       do_div(tmpTotalMaxLBA, 2048);
3664 +       pKarg->Configuration.bDriveCount = 0;
3665 +       pKarg->Configuration.uCapacity = tmpTotalMaxLBA;
3666 +       pKarg->Configuration.uStripeSize =
3667 +               le32_to_cpu(pVolume0->StripeSize)/2;
3668 +
3669 +       switch(pVolume0->VolumeType) {
3670 +       case MPI_RAID_VOL_TYPE_IS:
3671 +               pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_0;
3672 +               break;
3673 +       case MPI_RAID_VOL_TYPE_IME:
3674 +               pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_10;
3675 +               break;
3676 +       case MPI_RAID_VOL_TYPE_IM:
3677 +               pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_1;
3678 +               break;
3679 +       default:
3680 +               pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_OTHER;
3681 +               break;
3682 +       }
3683 +
3684 +       switch (pVolume0->VolumeStatus.State) {
3685 +       case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
3686 +               pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OK;
3687 +               break;
3688 +       case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
3689 +               /* Volume is degraded, check if Resyncing or Inactive */
3690 +               pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_DEGRADED;
3691 +               break;
3692 +       case MPI_RAIDVOL0_STATUS_STATE_FAILED:
3693 +               pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_FAILED;
3694 +               break;
3695 +       }
3696 +
3697 +       /* check flags */
3698 +       if (pVolume0->VolumeStatus.Flags &
3699 +           MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)
3700 +               pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OFFLINE;
3701 +       else if (pVolume0->VolumeStatus.Flags &
3702 +           MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)
3703 +               pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_REBUILDING;
3704 +
3705 +       pKarg->Configuration.bInformation = 0;  /* default */
3706 +       if(pVolume0->VolumeStatus.Flags &
3707 +           MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ) {
3708 +
3709 +               uint64_t        * ptrUint64;
3710 +               uint64_t        totalBlocks64, blocksRemaining64;
3711 +               uint32_t        totalBlocks32, blocksRemaining32;
3712 +
3713 +               /* get percentage complete */
3714 +               pRaidActionReply = kmalloc( sizeof(MPI_RAID_VOL_INDICATOR) +
3715 +                   offsetof(MSG_RAID_ACTION_REPLY,ActionData),
3716 +                   GFP_KERNEL);
3717 +
3718 +               if (!pRaidActionReply){
3719 +                       printk(KERN_ERR "%s@%d::%s() - "
3720 +                           "Unable to malloc @ %p\n",
3721 +                           __FILE__, __LINE__, __FUNCTION__,pKarg);
3722 +                       goto cim_get_raid_config_exit;
3723 +               }
3724 +               memset(pRaidActionReply, 0, sizeof(*pRaidActionReply));
3725 +
3726 +               csmisas_do_raid(ioc,
3727 +                   MPI_RAID_ACTION_INDICATOR_STRUCT,
3728 +                   0, VolumeBus, volumeID, pRaidActionReply);
3729 +
3730 +               ptrUint64       = (uint64_t *)&pRaidActionReply->ActionData;
3731 +               totalBlocks64     = *ptrUint64;
3732 +               ptrUint64++;
3733 +               blocksRemaining64 = *ptrUint64;
3734 +               while(totalBlocks64 > 0xFFFFFFFFUL){
3735 +                       totalBlocks64 = totalBlocks64 >> 1;
3736 +                       blocksRemaining64 = blocksRemaining64 >> 1;
3737 +               }
3738 +               totalBlocks32 = (uint32_t)totalBlocks64;
3739 +               blocksRemaining32 = (uint32_t)blocksRemaining64;
3740 +
3741 +               if(totalBlocks32)
3742 +                       pKarg->Configuration.bInformation =
3743 +                           (totalBlocks32 - blocksRemaining32) /
3744 +                           (totalBlocks32 / 100);
3745 +
3746 +               kfree(pRaidActionReply);
3747 +       }
3748 +
3749 +       /* fill-in more information depending on data type */
3750 +       if (pKarg->Configuration.bDataType ==
3751 +           CSMI_SAS_RAID_DATA_ADDITIONAL_DATA) {
3752 +               pKarg->Configuration.Data->bLabel[0] = '\0';
3753 +               pKarg->Configuration.Data->bRaidSetLun[1] = 0;
3754 +               pKarg->Configuration.Data->bWriteProtection =
3755 +                       CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN;
3756 +               pKarg->Configuration.Data->bCacheSetting =
3757 +                       CSMI_SAS_RAID_SET_CACHE_UNKNOWN;
3758 +               pKarg->Configuration.Data->bCacheRatio = 0;
3759 +               pKarg->Configuration.Data->usBlockSize = 512;
3760 +               pKarg->Configuration.Data->ulRaidSetExtentOffset.uLowPart = 0;
3761 +               pKarg->Configuration.Data->ulRaidSetExtentOffset.uHighPart = 0;
3762 +               pKarg->Configuration.Data->ulRaidSetBlocks.uLowPart =
3763 +                   le32_to_cpu(pVolume0->MaxLBA);
3764 +               pKarg->Configuration.Data->ulRaidSetBlocks.uHighPart =
3765 +                   le32_to_cpu(pVolume0->MaxLBAHigh);
3766 +               if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS ||
3767 +                   pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME ) {
3768 +                       pKarg->Configuration.Data->uStripeSizeInBlocks =
3769 +                           le32_to_cpu(pVolume0->StripeSize);
3770 +               } else {
3771 +                       pKarg->Configuration.Data->uStripeSizeInBlocks = 0;
3772 +               }
3773 +               pKarg->Configuration.Data->uSectorsPerTrack = 128;
3774 +               for (i=0; i<16; i++) {
3775 +                       // unsupported
3776 +                       pKarg->Configuration.Data->bApplicationScratchPad[i] =
3777 +                           0xFF;
3778 +               }
3779 +               pKarg->Configuration.Data->uNumberOfHeads = 16;
3780 +
3781 +               tmpTotalMaxLBA = totalMaxLBA;
3782 +               do_div(tmpTotalMaxLBA,
3783 +                   (pKarg->Configuration.Data->uNumberOfHeads *
3784 +                    pKarg->Configuration.Data->uSectorsPerTrack));
3785 +               pKarg->Configuration.Data->uNumberOfTracks = tmpTotalMaxLBA;
3786 +       } else if ( pKarg->Configuration.bDataType ==
3787 +           CSMI_SAS_RAID_DATA_DEVICE_ID ) {
3788 +               /* Send inquiry to get VPD Page 0x83 */
3789 +               u32 vpd_page_sz;
3790 +               vpd_page_sz = csmi_sas_raid_config_buffer_sz -
3791 +                   offsetof(CSMI_SAS_RAID_CONFIG,DeviceId);
3792 +               if (csmisas_raid_inq(ioc, MPI_FUNCTION_SCSI_IO_REQUEST,
3793 +                       VolumeBus, volumeID, 0x83,
3794 +                       (u8*)&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage,
3795 +                       vpd_page_sz) != 0) {
3796 +                       pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3797 +                       goto cim_get_raid_config_exit;
3798 +               }
3799 +       } else {
3800 +               /* suppress drive information */
3801 +               if (pKarg->Configuration.bDriveCount ==
3802 +                       CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) {
3803 +                       pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
3804 +                       goto cim_get_raid_config_exit;
3805 +               }
3806 +       }
3807 +
3808 +       /* get hotspare info, used later in this function */
3809 +       if (pVolume0->VolumeSettings.HotSparePool) {
3810 +               /* Read and save IOC Page 5
3811 +                */
3812 +               header.PageVersion = 0;
3813 +               header.PageLength = 0;
3814 +               header.PageNumber = 5;
3815 +               header.PageType = MPI_CONFIG_PAGETYPE_IOC;
3816 +               cfg.cfghdr.hdr = &header;
3817 +               cfg.physAddr = -1;
3818 +               cfg.pageAddr = 0;
3819 +               cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3820 +               cfg.dir = 0;
3821 +               cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
3822 +               if ((mpt_config(ioc, &cfg) == 0) && (header.PageLength)) {
3823 +                       ioc_page5_sz = header.PageLength * 4;
3824 +                       pIocPage5 = pci_alloc_consistent(ioc->pcidev,
3825 +                           ioc_page5_sz,
3826 +                           &ioc_page5_dma);
3827 +                       memset(pIocPage5,0,ioc_page5_sz);
3828 +                       if (ioc_page5_dma) {
3829 +                               cfg.physAddr = ioc_page5_dma;
3830 +                               cfg.action =
3831 +                                   MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3832 +                               mpt_config(ioc, &cfg);
3833 +                       }
3834 +               }
3835 +       }
3836 +
3837 +       /*
3838 +        * get RAID Physical Disk Page 0
3839 +        */
3840 +       header.PageVersion = 0;
3841 +       header.PageLength = 0;
3842 +       header.PageNumber = 0;
3843 +       header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
3844 +       cfg.cfghdr.hdr = &header;
3845 +       cfg.physAddr = -1;
3846 +       cfg.pageAddr = 0;
3847 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3848 +       cfg.dir = 0;
3849 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
3850 +       if (mpt_config(ioc, &cfg) != 0) {
3851 +               pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3852 +               goto cim_get_raid_config_exit;
3853 +       }
3854 +
3855 +       if (header.PageLength == 0) {
3856 +               pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3857 +               goto cim_get_raid_config_exit;
3858 +       }
3859 +
3860 +       physdiskpage0sz = header.PageLength * 4;
3861 +       pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
3862 +           &physdisk0_dma);
3863 +       if (!pPhysDisk0) {
3864 +               pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3865 +               goto cim_get_raid_config_exit;
3866 +       }
3867 +       cfg.physAddr = physdisk0_dma;
3868 +
3869 +       physDiskNumMax = (csmi_sas_raid_config_buffer_sz -
3870 +           offsetof(CSMI_SAS_RAID_CONFIG,Drives))
3871 +           / sizeof(CSMI_SAS_RAID_DRIVES);
3872 +
3873 +       tmpTotalMaxLBA = totalMaxLBA;
3874 +       if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS) {
3875 +               do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
3876 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "IS Volume tmpTotalMaxLBA=%llX\n",
3877 +               (unsigned long long)tmpTotalMaxLBA));
3878 +       }
3879 +       else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME) {
3880 +               do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks * 2);
3881 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "IME Volume tmpTotalMaxLBA=%llX\n",
3882 +               (unsigned long long)tmpTotalMaxLBA));
3883 +       } else {
3884 +               dcsmisasprintk(ioc, printk(KERN_DEBUG "IM Volume tmpTotalMaxLBA=%llX\n",
3885 +               (unsigned long long)tmpTotalMaxLBA));
3886 +       }
3887 +
3888 +       for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
3889 +
3890 +               physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum;
3891 +               cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3892 +               cfg.pageAddr = physDiskNum;
3893 +               if (mpt_config(ioc, &cfg) != 0){
3894 +                       pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
3895 +                       goto cim_get_raid_config_exit;
3896 +               }
3897 +
3898 +               pKarg->Configuration.bDriveCount++;
3899 +               if (pKarg->Configuration.bDataType != CSMI_SAS_RAID_DATA_DRIVES)
3900 +                       continue;
3901 +
3902 +               /* Search the list for the matching SAS address. */
3903 +               sas_info = csmisas_get_device_component_by_fw(ioc, pPhysDisk0->PhysDiskBus,
3904 +                   pPhysDisk0->PhysDiskID);
3905 +               if (sas_info) {
3906 +                       sas_address = reverse_byte_order64(sas_info->sas_address);
3907 +                       memcpy(pKarg->Configuration.Drives[i].bSASAddress,
3908 +                          &sas_address,sizeof(u64));
3909 +                       if (!device_info)
3910 +                               device_info = sas_info->device_info;
3911 +               }
3912 +
3913 +               memcpy(pKarg->Configuration.Drives[i].bModel,
3914 +                   pPhysDisk0->InquiryData.VendorID,
3915 +                   offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
3916 +               memcpy(pKarg->Configuration.Drives[i].bFirmware,
3917 +                       pPhysDisk0->InquiryData.ProductRevLevel,
3918 +                       sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
3919 +               if (csmisas_is_sata(pPhysDisk0)) {
3920 +                       memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
3921 +                               &pPhysDisk0->ExtDiskIdentifier[4],
3922 +                               4);
3923 +                       memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
3924 +                               &pPhysDisk0->DiskIdentifier,
3925 +                               sizeof(pPhysDisk0->DiskIdentifier));
3926 +               } else {
3927 +                       memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
3928 +                               pPhysDisk0->DiskIdentifier,
3929 +                               sizeof(pPhysDisk0->DiskIdentifier));
3930 +               }
3931 +
3932 +               pKarg->Configuration.Drives[i].bDriveUsage =
3933 +                   (pPhysDisk0->PhysDiskStatus.Flags &
3934 +                   MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) ?
3935 +                   CSMI_SAS_DRIVE_CONFIG_NOT_USED :
3936 +                   CSMI_SAS_DRIVE_CONFIG_MEMBER;
3937 +
3938 +               pKarg->Configuration.Drives[i].bDriveStatus =
3939 +                   CSMI_SAS_DRIVE_STATUS_OK;
3940 +               if (pPhysDisk0->PhysDiskStatus.State ==
3941 +                   MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED) {
3942 +                       pKarg->Configuration.Drives[i].bDriveStatus =
3943 +                           CSMI_SAS_DRIVE_STATUS_OFFLINE;
3944 +               } else if(pPhysDisk0->PhysDiskStatus.State) {
3945 +                       pKarg->Configuration.Drives[i].bDriveStatus =
3946 +                           CSMI_SAS_DRIVE_STATUS_FAILED;
3947 +                       if(pKarg->Configuration.bStatus ==
3948 +                           CSMI_SAS_RAID_SET_STATUS_DEGRADED)
3949 +                               pKarg->Configuration.bInformation = i;
3950 +               } else if((pVolume0->VolumeStatus.Flags &
3951 +                   MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) &&
3952 +                   (pPhysDisk0->PhysDiskStatus.Flags &
3953 +                   MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
3954 +                       pKarg->Configuration.Drives[i].bDriveStatus =
3955 +                           CSMI_SAS_DRIVE_STATUS_REBUILDING;
3956 +               else if(pPhysDisk0->ErrorData.SmartCount ||
3957 +                   (pPhysDisk0->PhysDiskStatus.Flags &
3958 +                   MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
3959 +                       pKarg->Configuration.Drives[i].bDriveStatus =
3960 +                       CSMI_SAS_DRIVE_STATUS_DEGRADED;
3961 +
3962 +               memset(pKarg->Configuration.Drives[i].bSASLun,
3963 +                   0, sizeof(pKarg->Configuration.Drives[i].bSASLun));
3964 +               if (csmisas_is_sata(pPhysDisk0)) {
3965 +                       pKarg->Configuration.Drives[i].bDriveType =
3966 +                       CSMI_SAS_DRIVE_TYPE_SATA;
3967 +               } else { /* drive in a volume can only be SAS/SATA */
3968 +                       pKarg->Configuration.Drives[i].bDriveType =
3969 +                               CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
3970 +                       if (mpt_raid_phys_disk_get_num_paths(ioc,
3971 +                           pVolume0->PhysDisk[i].PhysDiskNum) > 1)
3972 +                                       pKarg->Configuration.Drives[i].bDriveType =
3973 +                                           CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS;
3974 +               }
3975 +
3976 +               pKarg->Configuration.Drives[i].usBlockSize = 512;
3977 +                       pKarg->Configuration.Drives[i].uDriveIndex =
3978 +                           pPhysDisk0->PhysDiskNum;
3979 +               pKarg->Configuration.Drives[i].ulTotalUserBlocks.uLowPart =
3980 +                   (u32)tmpTotalMaxLBA;
3981 +               pKarg->Configuration.Drives[i].ulTotalUserBlocks.uHighPart =
3982 +                   (u32)(tmpTotalMaxLBA >> 32);
3983 +       }
3984 +
3985 +       /* adding hot spare info at the end */
3986 +       if ((pVolume0->VolumeSettings.HotSparePool) && (pIocPage5) &&
3987 +           (pVolume0->VolumeType != MPI_RAID_VOL_TYPE_IS)) {
3988 +               for (idx = 0, i = pVolume0->NumPhysDisks ;
3989 +                   idx < pIocPage5->NumHotSpares ; idx++) {
3990 +                       if (i >= physDiskNumMax)
3991 +                               break;
3992 +                       if ((pVolume0->VolumeSettings.HotSparePool &
3993 +                           pIocPage5->HotSpare[idx].HotSparePool) == 0)
3994 +                               continue;
3995 +                       if(pIocPage5->HotSpare[idx].Flags !=
3996 +                           MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE)
3997 +                           continue;
3998 +                       physDiskNum = pIocPage5->HotSpare[idx].PhysDiskNum;
3999 +                       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4000 +                       cfg.pageAddr = physDiskNum;
4001 +                       if (mpt_config(ioc, &cfg) != 0)
4002 +                               continue;
4003 +
4004 +                       /* don't mix SSP hot spare
4005 +                        * in SATA volume
4006 +                        */
4007 +                       if (!csmisas_is_sata(pPhysDisk0) &&
4008 +                           (device_info &
4009 +                           MPI_SAS_DEVICE_INFO_SATA_DEVICE))
4010 +                               continue;
4011 +
4012 +                       /* don't mix SATA hot spare
4013 +                        * in SSP volume
4014 +                        */
4015 +                       if (csmisas_is_sata(pPhysDisk0) &&
4016 +                           (device_info &
4017 +                           MPI_SAS_DEVICE_INFO_SSP_TARGET))
4018 +                               continue;
4019 +
4020 +                       /* capacity check for IM volumes*/
4021 +                       if ((pVolume0->VolumeType ==
4022 +                           MPI_RAID_VOL_TYPE_IM) &&
4023 +                           (totalMaxLBA +
4024 +                           (64*2*1024) /* metadata = 64MB*/ >
4025 +                           le32_to_cpu(pPhysDisk0->MaxLBA)))
4026 +                               continue;
4027 +
4028 +                       tmpTotalMaxLBA = totalMaxLBA;
4029 +                       do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
4030 +                       /* capacity check for IME volumes*/
4031 +                       if ((pVolume0->VolumeType ==
4032 +                           MPI_RAID_VOL_TYPE_IME) &&
4033 +                           (((totalMaxLBA +
4034 +                           pVolume0->NumPhysDisks) * 2) +
4035 +                           (64*2*1024 ) /*metadata = 64MB*/ >
4036 +                           le32_to_cpu(pPhysDisk0->MaxLBA)))
4037 +                               continue;
4038 +
4039 +                       pKarg->Configuration.bDriveCount++;
4040 +                       if (pKarg->Configuration.bDataType !=
4041 +                           CSMI_SAS_RAID_DATA_DRIVES) {
4042 +                               i++;
4043 +                               continue;
4044 +                       }
4045 +
4046 +                       /* Search the list for the matching SAS address. */
4047 +                       sas_info = csmisas_get_device_component_by_fw(ioc,
4048 +                           pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
4049 +                       if (sas_info) {
4050 +                               sas_address = reverse_byte_order64(sas_info->sas_address);
4051 +                               memcpy(pKarg->Configuration.Drives[i].bSASAddress,
4052 +                                  &sas_address,sizeof(u64));
4053 +                       }
4054 +
4055 +                       memcpy(pKarg->Configuration.Drives[i].bModel,
4056 +                           pPhysDisk0->InquiryData.VendorID,
4057 +                           offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
4058 +                       memcpy(pKarg->Configuration.Drives[i].bFirmware,
4059 +                               pPhysDisk0->InquiryData.ProductRevLevel,
4060 +                               sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
4061 +                       if (csmisas_is_sata(pPhysDisk0)) {
4062 +                               memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
4063 +                                       &pPhysDisk0->ExtDiskIdentifier[4],
4064 +                                       4);
4065 +                               memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
4066 +                                       &pPhysDisk0->DiskIdentifier,
4067 +                                       sizeof(pPhysDisk0->DiskIdentifier));
4068 +                       } else {
4069 +                               memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
4070 +                                       pPhysDisk0->DiskIdentifier,
4071 +                                       sizeof(pPhysDisk0->DiskIdentifier));
4072 +                       }
4073 +                       pKarg->Configuration.Drives[i].bDriveStatus =
4074 +                           CSMI_SAS_DRIVE_STATUS_OK;
4075 +                       if(pPhysDisk0->PhysDiskStatus.State)
4076 +                               pKarg->Configuration.Drives[i].bDriveStatus =
4077 +                                   CSMI_SAS_DRIVE_STATUS_FAILED;
4078 +                       else if(pPhysDisk0->ErrorData.SmartCount)
4079 +                               pKarg->Configuration.Drives[i].bDriveStatus =
4080 +                                   CSMI_SAS_DRIVE_STATUS_DEGRADED;
4081 +                       pKarg->Configuration.Drives[i].bDriveUsage =
4082 +                           CSMI_SAS_DRIVE_CONFIG_SPARE;
4083 +                       pKarg->Configuration.Drives[i].usBlockSize = 512;
4084 +                       pKarg->Configuration.Drives[i].uDriveIndex =
4085 +                           pPhysDisk0->PhysDiskNum;
4086 +                       if (csmisas_is_sata(pPhysDisk0)) {
4087 +                               pKarg->Configuration.Drives[i].bDriveType =
4088 +                               CSMI_SAS_DRIVE_TYPE_SATA;
4089 +                       } else { /* drive in a volume can only be SAS/SATA */
4090 +                               pKarg->Configuration.Drives[i].bDriveType =
4091 +                                       CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
4092 +                               if (mpt_raid_phys_disk_get_num_paths(ioc,
4093 +                                   pVolume0->PhysDisk[i].PhysDiskNum) > 1)
4094 +                                       pKarg->Configuration.Drives[i].bDriveType =
4095 +                                           CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS;
4096 +                       }
4097 +                       i++;
4098 +               }
4099 +       }
4100 +
4101 +       // Only return data on the first 240 drives
4102 +       if( pKarg->Configuration.bDriveCount > 0xF0 )
4103 +               pKarg->Configuration.bDriveCount =
4104 +                   CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG;
4105 +
4106 +       pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
4107 +
4108 + cim_get_raid_config_exit:
4109 +
4110 +       if (pVolume0 != NULL)
4111 +               pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
4112 +                   volume0_dma);
4113 +
4114 +       if(pPhysDisk0 != NULL)
4115 +               pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
4116 +                   physdisk0_dma);
4117 +
4118 +       if(pIocPage5 != NULL)
4119 +               pci_free_consistent(ioc->pcidev, ioc_page5_sz, pIocPage5,
4120 +                   ioc_page5_dma);
4121 +
4122 +       /* Copy the data from kernel memory to user memory
4123 +        */
4124 +
4125 +       /* find the buffer size to copy depending on how much is filled-in */
4126 +       switch (pKarg->Configuration.bDataType) {
4127 +       case CSMI_SAS_RAID_DATA_ADDITIONAL_DATA:
4128 +               copy_buffer_sz = sizeof(IOCTL_HEADER) +
4129 +                   offsetof(CSMI_SAS_RAID_CONFIG,Data) +
4130 +                   sizeof(CSMI_SAS_RAID_SET_ADDITIONAL_DATA);
4131 +               break;
4132 +       case CSMI_SAS_RAID_DATA_DRIVES:
4133 +               if (pKarg->Configuration.bDriveCount ==
4134 +                   CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED)
4135 +                       copy_buffer_sz = sizeof(IOCTL_HEADER) +
4136 +                           offsetof(CSMI_SAS_RAID_CONFIG,Drives);
4137 +               else
4138 +                       copy_buffer_sz = sizeof(IOCTL_HEADER) +
4139 +                           offsetof(CSMI_SAS_RAID_CONFIG,Drives) +
4140 +                           (pKarg->Configuration.bDriveCount *
4141 +                           sizeof(CSMI_SAS_RAID_DRIVES));
4142 +               break;
4143 +       case CSMI_SAS_RAID_DATA_DEVICE_ID:
4144 +               copy_buffer_sz = csmi_sas_raid_config_buffer_sz;
4145 +               break;
4146 +       }
4147 +
4148 +       if (copy_to_user(uarg, pKarg, copy_buffer_sz)) {
4149 +               printk(KERN_ERR "%s@%d::%s() - "
4150 +                      "Unable to write out csmi_sas_get_raid_config @ %p\n",
4151 +                          __FILE__, __LINE__, __FUNCTION__, uarg);
4152 +               free_pages((unsigned long)pKarg, memory_pages);
4153 +               return -EFAULT;
4154 +       }
4155 +
4156 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
4157 +       free_pages((unsigned long)pKarg, memory_pages);
4158 +       return 0;
4159 +}
4160 +
4161 +/**
4162 + * Prototype Routine for the CSMI SAS Get RAID Features command.
4163 + *
4164 + * Outputs:    None.
4165 + * Return:     0 if successful
4166 + *             -EFAULT if data unavailable
4167 + *             -ENODEV if no such device/adapter
4168 + **/
4169 +static int
4170 +csmisas_get_raid_features(unsigned long arg)
4171 +{
4172 +       CSMI_SAS_RAID_FEATURES_BUFFER __user *uarg = (void __user *) arg;
4173 +       CSMI_SAS_RAID_FEATURES_BUFFER karg, *pKarg=NULL;
4174 +       int csmi_sas_raid_features_buffer_sz, iocnum;
4175 +       int                             memory_pages;
4176 +       MPT_ADAPTER             *ioc = NULL;
4177 +
4178 +       if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
4179 +               printk(KERN_ERR "%s@%d::%s() - "
4180 +                   "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
4181 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
4182 +               return -EFAULT;
4183 +       }
4184 +
4185 +       csmi_sas_raid_features_buffer_sz = karg.IoctlHeader.Length;
4186 +       memory_pages = get_order(csmi_sas_raid_features_buffer_sz);
4187 +       pKarg = (CSMI_SAS_RAID_FEATURES_BUFFER *)__get_free_pages(
4188 +               GFP_KERNEL, memory_pages);
4189 +       if (!pKarg){
4190 +               printk(KERN_ERR "%s@%d::%s() - "
4191 +                   "Unable to malloc RAID_FEATURES_BUFFER "
4192 +                       "csmi_sas_raid_features_buffer_sz=%d memory_pages=%d\n",
4193 +                       __FILE__, __LINE__, __FUNCTION__,
4194 +                       csmi_sas_raid_features_buffer_sz, memory_pages);
4195 +               return -ENOMEM;
4196 +       }
4197 +       memset(pKarg, 0, sizeof(*pKarg));
4198 +
4199 +       if (copy_from_user(pKarg, uarg, csmi_sas_raid_features_buffer_sz)) {
4200 +               printk(KERN_ERR "%s@%d::%s() - "
4201 +                   "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
4202 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
4203 +               free_pages((unsigned long)pKarg, memory_pages);
4204 +               return -EFAULT;
4205 +       }
4206 +
4207 +       if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
4208 +           &ioc)) < 0) || (ioc == NULL)) {
4209 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
4210 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4211 +               free_pages((unsigned long)pKarg, memory_pages);
4212 +               return -ENODEV;
4213 +       }
4214 +
4215 +       if (!csmisas_is_this_sas_cntr(ioc)) {
4216 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
4217 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4218 +               free_pages((unsigned long)pKarg, memory_pages);
4219 +               return -ENODEV;
4220 +       }
4221 +
4222 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
4223 +
4224 +       if (pKarg->Information.uChangeCount != 0 &&
4225 +           pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
4226 +               pKarg->IoctlHeader.ReturnCode =
4227 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
4228 +               pKarg->Information.uFailureCode =
4229 +                   CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
4230 +               goto cim_get_raid_features_exit;
4231 +       }
4232 +
4233 +       pKarg->Information.uFeatures = CSMI_SAS_RAID_FEATURE_REBUILD |
4234 +           CSMI_SAS_RAID_FEATURE_SURFACE_SCAN |
4235 +           CSMI_SAS_RAID_FEATURE_SPARES_SHARED;
4236 +       pKarg->Information.bDefaultTransformPriority =
4237 +           CSMI_SAS_PRIORITY_UNKNOWN;
4238 +       pKarg->Information.bTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN;
4239 +       pKarg->Information.bDefaultRebuildPriority = CSMI_SAS_PRIORITY_UNKNOWN;
4240 +       pKarg->Information.bRebuildPriority =
4241 +           pKarg->Information.bDefaultRebuildPriority;
4242 +       pKarg->Information.bDefaultSurfaceScanPriority =
4243 +           CSMI_SAS_PRIORITY_UNKNOWN;
4244 +       pKarg->Information.bSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN;
4245 +       pKarg->Information.uRaidSetTransformationRules = 0;
4246 +
4247 +        /* IS */
4248 +       pKarg->Information.RaidType[0].bRaidType = CSMI_SAS_RAID_TYPE_0;
4249 +       pKarg->Information.RaidType[0].uSupportedStripeSizeMap = 0x80;
4250 +
4251 +       /* IM */
4252 +       pKarg->Information.RaidType[1].bRaidType = CSMI_SAS_RAID_TYPE_1;
4253 +       pKarg->Information.RaidType[1].uSupportedStripeSizeMap = 0;
4254 +
4255 +       /* IME */
4256 +       pKarg->Information.RaidType[2].bRaidType = CSMI_SAS_RAID_TYPE_1E;
4257 +       pKarg->Information.RaidType[2].uSupportedStripeSizeMap = 0x80;
4258 +
4259 +       pKarg->Information.RaidType[3].bRaidType = CSMI_SAS_RAID_TYPE_END;
4260 +       pKarg->Information.bCacheRatiosSupported[0] =
4261 +           CSMI_SAS_RAID_CACHE_RATIO_END;
4262 +
4263 + cim_get_raid_features_exit:
4264 +
4265 +       /*
4266 +        * Copy the data from kernel memory to user memory
4267 +        */
4268 +       if (copy_to_user(uarg, pKarg,
4269 +           sizeof(CSMI_SAS_RAID_FEATURES_BUFFER))) {
4270 +               printk(KERN_ERR "%s@%d::%s() - "
4271 +               "Unable to write out csmi_sas_get_raid_features @ %p\n",
4272 +               __FILE__, __LINE__, __FUNCTION__, uarg);
4273 +               free_pages((unsigned long)pKarg, memory_pages);
4274 +               return -EFAULT;
4275 +       }
4276 +
4277 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
4278 +       free_pages((unsigned long)pKarg, memory_pages);
4279 +       return 0;
4280 +}
4281 +
4282 +/**
4283 + * Prototype Routine for the CSMI SAS Set RAID Control command.
4284 + *
4285 + * Outputs:    None.
4286 + * Return:     0 if successful
4287 + *             -EFAULT if data unavailable
4288 + *             -ENODEV if no such device/adapter
4289 + **/
4290 +static int
4291 +csmisas_set_raid_control(unsigned long arg)
4292 +{
4293 +       CSMI_SAS_RAID_CONTROL_BUFFER __user *uarg = (void __user *) arg;
4294 +       CSMI_SAS_RAID_CONTROL_BUFFER karg, *pKarg=NULL;
4295 +       int csmi_sas_raid_control_buffer_sz, iocnum;
4296 +       int                             memory_pages;
4297 +       MPT_ADAPTER     *ioc = NULL;
4298 +
4299 +       if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
4300 +               printk(KERN_ERR "%s@%d::%s() - "
4301 +                   "Unable to read in csmi_sas_set_raid_control struct @ %p\n",
4302 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
4303 +               return -EFAULT;
4304 +       }
4305 +
4306 +       csmi_sas_raid_control_buffer_sz = karg.IoctlHeader.Length;
4307 +       memory_pages = get_order(csmi_sas_raid_control_buffer_sz);
4308 +       pKarg = (CSMI_SAS_RAID_CONTROL_BUFFER *)__get_free_pages(
4309 +               GFP_KERNEL, memory_pages);
4310 +       if (!pKarg){
4311 +               printk(KERN_ERR "%s@%d::%s() - "
4312 +                   "Unable to malloc RAID_CONTROL_BUFFER "
4313 +                       "csmi_sas_raid_control_buffer_sz=%d memory_pages=%d\n",
4314 +                       __FILE__, __LINE__, __FUNCTION__,
4315 +                       csmi_sas_raid_control_buffer_sz, memory_pages);
4316 +               return -ENOMEM;
4317 +       }
4318 +       memset(pKarg, 0, sizeof(*pKarg));
4319 +
4320 +       if (copy_from_user(pKarg, uarg, csmi_sas_raid_control_buffer_sz)) {
4321 +               printk(KERN_ERR "%s@%d::%s() - "
4322 +                   "Unable to read in csmi_sas_set_raid_control struct @ %p\n",
4323 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
4324 +               free_pages((unsigned long)pKarg, memory_pages);
4325 +               return -EFAULT;
4326 +       }
4327 +
4328 +       if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
4329 +           &ioc)) < 0) || (ioc == NULL)) {
4330 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
4331 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4332 +               free_pages((unsigned long)pKarg, memory_pages);
4333 +               return -ENODEV;
4334 +       }
4335 +
4336 +       if (!csmisas_is_this_sas_cntr(ioc)) {
4337 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
4338 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4339 +               free_pages((unsigned long)pKarg, memory_pages);
4340 +               return -ENODEV;
4341 +       }
4342 +
4343 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
4344 +
4345 +       if (pKarg->Information.uChangeCount != 0 &&
4346 +               pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
4347 +               pKarg->IoctlHeader.ReturnCode =
4348 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
4349 +               pKarg->Information.uFailureCode =
4350 +                   CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
4351 +               goto cim_set_raid_control_exit;
4352 +       }
4353 +
4354 +       if (pKarg->Information.bTransformPriority !=
4355 +           CSMI_SAS_PRIORITY_UNCHANGED) {
4356 +               pKarg->IoctlHeader.ReturnCode =
4357 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
4358 +               pKarg->Information.uFailureCode =
4359 +                   CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID;
4360 +               goto cim_set_raid_control_exit;
4361 +       }
4362 +
4363 +       if (pKarg->Information.bRebuildPriority !=
4364 +           CSMI_SAS_PRIORITY_AUTO &&
4365 +               pKarg->Information.bRebuildPriority !=
4366 +               CSMI_SAS_PRIORITY_UNCHANGED) {
4367 +               pKarg->IoctlHeader.ReturnCode =
4368 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
4369 +               pKarg->Information.uFailureCode =
4370 +                   CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID;
4371 +               goto cim_set_raid_control_exit;
4372 +       }
4373 +
4374 +       if (pKarg->Information.bCacheRatioFlag ==
4375 +           CSMI_SAS_RAID_CACHE_RATIO_DISABLE) {
4376 +               pKarg->IoctlHeader.ReturnCode =
4377 +                   CSMI_SAS_STATUS_INVALID_PARAMETER;
4378 +               pKarg->Information.uFailureCode =
4379 +                   CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID;
4380 +               goto cim_set_raid_control_exit;
4381 +       }
4382 +
4383 +       if( !strcmp(pKarg->Information.bClearConfiguration,
4384 +               CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE) ) {
4385 +               pKarg->IoctlHeader.ReturnCode =
4386 +                       CSMI_SAS_STATUS_INVALID_PARAMETER;
4387 +               pKarg->Information.uFailureCode =
4388 +                       CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID;
4389 +               goto cim_set_raid_control_exit;
4390 +       }
4391 +
4392 +       pKarg->Information.bFailureDescription[0] = '\0';
4393 +
4394 + cim_set_raid_control_exit:
4395 +
4396 +       /*
4397 +        * Copy the data from kernel memory to user memory
4398 +        */
4399 +       if (copy_to_user(uarg, pKarg,
4400 +               sizeof(CSMI_SAS_RAID_CONTROL_BUFFER))) {
4401 +               printk(KERN_ERR "%s@%d::%s() - "
4402 +               "Unable to write out csmi_sas_set_raid_control @ %p\n",
4403 +               __FILE__, __LINE__, __FUNCTION__, uarg);
4404 +               free_pages((unsigned long)pKarg, memory_pages);
4405 +               return -EFAULT;
4406 +       }
4407 +
4408 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
4409 +       free_pages((unsigned long)pKarg, memory_pages);
4410 +       return 0;
4411 +}
4412 +
4413 +/**
4414 + * Prototype Routine for the CSMI SAS Get Raid Element.
4415 + *
4416 + * Outputs:    None.
4417 + * Return:     0 if successful
4418 + *             -EFAULT if data unavailable
4419 + *             -ENODEV if no such device/adapter
4420 + **/
4421 +static int
4422 +csmisas_get_raid_element(unsigned long arg)
4423 +{
4424 +       CSMI_SAS_RAID_ELEMENT_BUFFER __user *uarg = (void __user *) arg;
4425 +       CSMI_SAS_RAID_ELEMENT_BUFFER     karg;
4426 +       MPT_ADAPTER                     *ioc = NULL;
4427 +       int                             iocnum;
4428 +
4429 +       if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) {
4430 +               printk(KERN_ERR "%s@%d::%s() - "
4431 +                   "Unable to read in csmisas_get_raid_element struct @ %p\n",
4432 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
4433 +               return -EFAULT;
4434 +       }
4435 +
4436 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
4437 +           &ioc)) < 0) || (ioc == NULL)) {
4438 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
4439 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4440 +               return -ENODEV;
4441 +       }
4442 +
4443 +       if (!csmisas_is_this_sas_cntr(ioc)) {
4444 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
4445 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4446 +               return -ENODEV;
4447 +       }
4448 +
4449 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
4450 +
4451 +/* TODO - implement IOCTL here */
4452 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
4453 +       dcsmisasprintk(ioc, printk(KERN_DEBUG ": not implemented\n"));
4454 +
4455 +// csmisas_get_raid_element_exit:
4456 +
4457 +       /* Copy the data from kernel memory to user memory
4458 +        */
4459 +       if (copy_to_user(uarg, &karg,
4460 +                               sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) {
4461 +               printk(KERN_ERR "%s@%d::%s() - "
4462 +                       "Unable to write out csmisas_get_raid_element @ %p\n",
4463 +                               __FILE__, __LINE__, __FUNCTION__, uarg);
4464 +               return -EFAULT;
4465 +       }
4466 +
4467 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
4468 +       return 0;
4469 +
4470 +}
4471 +
4472 +/**
4473 + * Prototype Routine for the CSMI SAS Set Raid Operation
4474 + *
4475 + * Outputs:    None.
4476 + * Return:     0 if successful
4477 + *             -EFAULT if data unavailable
4478 + *             -ENODEV if no such device/adapter
4479 + **/
4480 +static int
4481 +csmisas_set_raid_operation(unsigned long arg)
4482 +{
4483 +       CSMI_SAS_RAID_SET_OPERATION_BUFFER __user *uarg = (void __user *) arg;
4484 +       CSMI_SAS_RAID_SET_OPERATION_BUFFER       karg;
4485 +       MPT_ADAPTER                     *ioc = NULL;
4486 +       int                             iocnum;
4487 +
4488 +       if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) {
4489 +               printk(KERN_ERR "%s@%d::%s() - "
4490 +                   "Unable to read in csmi_set_raid_operation struct @ %p\n",
4491 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
4492 +               return -EFAULT;
4493 +       }
4494 +
4495 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
4496 +           &ioc)) < 0) || (ioc == NULL)) {
4497 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
4498 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4499 +               return -ENODEV;
4500 +       }
4501 +
4502 +       if (!csmisas_is_this_sas_cntr(ioc)) {
4503 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
4504 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4505 +               return -ENODEV;
4506 +       }
4507 +
4508 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
4509 +
4510 +/* TODO - implement IOCTL here */
4511 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
4512 +       dcsmisasprintk(ioc, printk(KERN_DEBUG ": not implemented\n"));
4513 +
4514 +// cim_set_raid_operation:
4515 +
4516 +       /* Copy the data from kernel memory to user memory
4517 +        */
4518 +       if (copy_to_user(uarg, &karg,
4519 +                               sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) {
4520 +               printk(KERN_ERR "%s@%d::%s() - "
4521 +                       "Unable to write out csmi_set_raid_operation @ %p\n",
4522 +                               __FILE__, __LINE__, __FUNCTION__, uarg);
4523 +               return -EFAULT;
4524 +       }
4525 +
4526 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
4527 +       return 0;
4528 +
4529 +}
4530 +
4531 +
4532 +/**
4533 + * Prototype Routine for the CSMI SAS Task Managment Config command.
4534 + *
4535 + * Outputs:    None.
4536 + * Return:     0 if successful
4537 + *             -EFAULT if data unavailable
4538 + *             -ENODEV if no such device/adapter
4539 + **/
4540 +static int
4541 +csmisas_task_managment(unsigned long arg)
4542 +{
4543 +       CSMI_SAS_SSP_TASK_IU_BUFFER __user *uarg = (void __user *) arg;
4544 +       CSMI_SAS_SSP_TASK_IU_BUFFER      karg;
4545 +       pSCSITaskMgmt_t                 pScsiTm;
4546 +       pSCSITaskMgmtReply_t            pScsiTmReply;
4547 +       MPT_ADAPTER                     *ioc = NULL;
4548 +       MPT_SCSI_HOST                   *hd;
4549 +       MPT_FRAME_HDR                   *mf = NULL;
4550 +       MPIHeader_t                     *mpi_hdr;
4551 +       int                             iocnum;
4552 +       u8                              taskType;
4553 +       u8                              channel;
4554 +       u8                              id;
4555 +       u8                              queueTag;
4556 +       u32                             TaskMsgContext = 0;
4557 +       int                             i;
4558 +       u8                              found_qtag;
4559 +       struct sas_device_info          *sas_info;
4560 +       u16                             ioc_status;
4561 +       u32                             MsgContext;
4562 +
4563 +       if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
4564 +               printk(KERN_ERR "%s@%d::%s() - "
4565 +                   "Unable to read in csmi_sas_task_managment struct @ %p\n",
4566 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
4567 +               return -EFAULT;
4568 +       }
4569 +
4570 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
4571 +           &ioc)) < 0) || (ioc == NULL)) {
4572 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
4573 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4574 +               return -ENODEV;
4575 +       }
4576 +
4577 +       if (!csmisas_is_this_sas_cntr(ioc)) {
4578 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
4579 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4580 +               return -ENODEV;
4581 +       }
4582 +
4583 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
4584 +
4585 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
4586 +
4587 +       sas_info = csmisas_get_device_component_by_os(ioc,
4588 +           karg.Parameters.bPathId, karg.Parameters.bTargetId);
4589 +       if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
4590 +               goto cim_get_task_managment_exit;
4591 +
4592 +       channel = sas_info->fw.channel;
4593 +       id = sas_info->fw.id;
4594 +       queueTag = (u8)karg.Parameters.uQueueTag & 0xFF;
4595 +       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4596 +
4597 +       /* try to catch an error
4598 +        */
4599 +       if ((karg.Parameters.uFlags & CSMI_SAS_TASK_IU) &&
4600 +           (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE))
4601 +               goto cim_get_task_managment_exit;
4602 +
4603 +       if (karg.Parameters.uFlags & CSMI_SAS_TASK_IU) {
4604 +               switch (karg.Parameters.bTaskManagementFunction) {
4605 +
4606 +               case CSMI_SAS_SSP_ABORT_TASK:
4607 +                       taskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
4608 +                       break;
4609 +               case CSMI_SAS_SSP_ABORT_TASK_SET:
4610 +                       taskType = MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET;
4611 +                       break;
4612 +               case CSMI_SAS_SSP_CLEAR_TASK_SET:
4613 +                       taskType = MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET;
4614 +                       break;
4615 +               case CSMI_SAS_SSP_LOGICAL_UNIT_RESET:
4616 +                       taskType = MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET;
4617 +                       break;
4618 +               case CSMI_SAS_SSP_CLEAR_ACA:
4619 +               case CSMI_SAS_SSP_QUERY_TASK:
4620 +               default:
4621 +                       goto cim_get_task_managment_exit;
4622 +               }
4623 +       } else if (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE)
4624 +               taskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
4625 +       else
4626 +               goto cim_get_task_managment_exit;
4627 +
4628 +       switch (karg.Parameters.uInformation) {
4629 +               case CSMI_SAS_SSP_TEST:
4630 +                       dcsmisasprintk(ioc, printk(KERN_DEBUG "TM request for test purposes\n"));
4631 +                       break;
4632 +               case CSMI_SAS_SSP_EXCEEDED:
4633 +                       dcsmisasprintk(ioc, printk(KERN_DEBUG "TM request due to timeout\n"));
4634 +                       break;
4635 +               case CSMI_SAS_SSP_DEMAND:
4636 +                       dcsmisasprintk(ioc, printk(KERN_DEBUG "TM request demanded by app\n"));
4637 +                       break;
4638 +               case CSMI_SAS_SSP_TRIGGER:
4639 +                       dcsmisasprintk(ioc, printk(KERN_DEBUG "TM request sent to trigger event\n"));
4640 +                       break;
4641 +       }
4642 +
4643 +       switch (taskType) {
4644 +
4645 +       case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
4646 +       /*
4647 +        * look up qtag in the ScsiLookup[] table
4648 +        */
4649 +               for (i = 0, found_qtag = 0; i < hd->ioc->req_depth; i++) {
4650 +                       if ((ioc->ScsiLookup[i]) &&
4651 +                           (ioc->ScsiLookup[i]->tag == queueTag)) {
4652 +                               mf = MPT_INDEX_2_MFPTR(hd->ioc, i);
4653 +                               TaskMsgContext =
4654 +                                   mf->u.frame.hwhdr.msgctxu.MsgContext;
4655 +                               found_qtag=1;
4656 +                               break;
4657 +                       }
4658 +               }
4659 +
4660 +               if(!found_qtag)
4661 +                       goto cim_get_task_managment_exit;
4662 +
4663 +       case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
4664 +       case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
4665 +       case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
4666 +       /* for now, this should work
4667 +        */
4668 +       case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
4669 +
4670 +               /* Single threading ....
4671 +                */
4672 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15))
4673 +               mutex_lock(&ioc->taskmgmt_cmds.mutex);
4674 +               if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
4675 +                       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4676 +                       karg.IoctlHeader.ReturnCode =
4677 +                           CSMI_SAS_STATUS_FAILED;
4678 +                       goto cim_get_task_managment_exit;
4679 +               }
4680 +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
4681 +               if (mptctl_set_tm_flags(hd) != 0) {
4682 +                       karg.IoctlHeader.ReturnCode =
4683 +                           CSMI_SAS_STATUS_FAILED;
4684 +                       goto cim_get_task_managment_exit;
4685 +               }
4686 +#endif
4687 +               /* Send request
4688 +                */
4689 +               if ((mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc)) == NULL) {
4690 +                       dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
4691 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15))
4692 +                       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4693 +                       mpt_clear_taskmgmt_in_progress_flag(ioc);
4694 +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
4695 +                       mptctl_free_tm_flags(ioc);
4696 +#endif
4697 +                       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
4698 +                       goto cim_get_task_managment_exit;
4699 +               }
4700 +
4701 +               mpi_hdr = (MPIHeader_t *) mf;
4702 +               MsgContext = mpi_hdr->MsgContext;
4703 +               pScsiTm = (pSCSITaskMgmt_t ) mf;
4704 +
4705 +               memset(pScsiTm,0,sizeof(SCSITaskMgmt_t));
4706 +               pScsiTm->TaskType = taskType;
4707 +               pScsiTm->Bus = channel;
4708 +               pScsiTm->TargetID = id;
4709 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15))
4710 +               int_to_scsilun(karg.Parameters.bLun,
4711 +                   (struct scsi_lun *)pScsiTm->LUN);
4712 +#else
4713 +               pScsiTm->LUN[1] = karg.Parameters.bLun;
4714 +#endif
4715 +               pScsiTm->MsgContext = MsgContext;
4716 +               pScsiTm->TaskMsgContext = TaskMsgContext;
4717 +               pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
4718 +
4719 +               if (csmisas_send_handshake_wait(ioc, mf,
4720 +                   karg.IoctlHeader.Timeout) != 0)  {
4721 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15))
4722 +                       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4723 +#endif
4724 +                       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
4725 +                       goto cim_get_task_managment_exit;
4726 +               }
4727 +
4728 +               if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
4729 +
4730 +                       pScsiTmReply =
4731 +                           (pSCSITaskMgmtReply_t ) ioc->ioctl_cmds.reply;
4732 +
4733 +                       ioc_status = le16_to_cpu(pScsiTmReply->IOCStatus)
4734 +                           & MPI_IOCSTATUS_MASK;
4735 +
4736 +                       memset(&karg.Status,0,
4737 +                           sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
4738 +
4739 +                       if(ioc_status == MPI_IOCSTATUS_SUCCESS) {
4740 +                               karg.IoctlHeader.ReturnCode =
4741 +                                   CSMI_SAS_STATUS_SUCCESS;
4742 +                               karg.Status.bSSPStatus =
4743 +                                   CSMI_SAS_SSP_STATUS_COMPLETED;
4744 +                       }else if(ioc_status == MPI_IOCSTATUS_INSUFFICIENT_RESOURCES) {
4745 +                               karg.IoctlHeader.ReturnCode =
4746 +                                   CSMI_SAS_STATUS_SUCCESS;
4747 +                               karg.Status.bSSPStatus =
4748 +                                   CSMI_SAS_SSP_STATUS_RETRY;
4749 +                       }else {
4750 +                               karg.IoctlHeader.ReturnCode =
4751 +                                   CSMI_SAS_STATUS_FAILED;
4752 +                               karg.Status.bSSPStatus =
4753 +                                   CSMI_SAS_SSP_STATUS_FATAL_ERROR;
4754 +                       }
4755 +               } else
4756 +                       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
4757 +
4758 +               break;
4759 +
4760 +       default:
4761 +               karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
4762 +               break;
4763 +       }
4764 +
4765 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15))
4766 +       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4767 +#endif
4768 +
4769 + cim_get_task_managment_exit:
4770 +
4771 +       /* Copy the data from kernel memory to user memory
4772 +        */
4773 +       if (copy_to_user(uarg, &karg,
4774 +                               sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
4775 +               printk(KERN_ERR "%s@%d::%s() - "
4776 +                       "Unable to write out csmi_sas_task_managment @ %p\n",
4777 +                               __FILE__, __LINE__, __FUNCTION__, uarg);
4778 +               return -EFAULT;
4779 +       }
4780 +
4781 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
4782 +       return 0;
4783 +}
4784 +
4785 +/**
4786 + *     map_sas_status_to_csmi - Conversion  for Connection Status
4787 + *     @mpi_sas_status: Sas status returned by the firmware
4788 + *
4789 + *     Returns converted connection status
4790 + *
4791 + **/
4792 +static u8
4793 +map_sas_status_to_csmi(u8 mpi_sas_status)
4794 +{
4795 +       u8  csmi_connect_status;
4796 +
4797 +       switch (mpi_sas_status) {
4798 +
4799 +       case MPI_SASSTATUS_SUCCESS:
4800 +               csmi_connect_status = CSMI_SAS_OPEN_ACCEPT;
4801 +               break;
4802 +
4803 +       case MPI_SASSTATUS_UTC_BAD_DEST:
4804 +               csmi_connect_status = CSMI_SAS_OPEN_REJECT_BAD_DESTINATION;
4805 +               break;
4806 +
4807 +       case MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED:
4808 +               csmi_connect_status = CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED;
4809 +               break;
4810 +
4811 +       case MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED:
4812 +               csmi_connect_status =
4813 +                   CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED;
4814 +               break;
4815 +
4816 +       case MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY:
4817 +               csmi_connect_status = CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY;
4818 +               break;
4819 +
4820 +       case MPI_SASSTATUS_UTC_WRONG_DESTINATION:
4821 +               csmi_connect_status = CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION;
4822 +               break;
4823 +
4824 +       case MPI_SASSTATUS_SDSF_NAK_RECEIVED:
4825 +               csmi_connect_status = CSMI_SAS_OPEN_REJECT_RETRY;
4826 +               break;
4827 +
4828 +       case MPI_SASSTATUS_SDSF_CONNECTION_FAILED:
4829 +               csmi_connect_status = CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED;
4830 +               break;
4831 +
4832 +       case MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT:
4833 +               csmi_connect_status =  CSMI_SAS_OPEN_REJECT_NO_DESTINATION;
4834 +               break;
4835 +
4836 +       case MPI_SASSTATUS_UNKNOWN_ERROR:
4837 +       case MPI_SASSTATUS_INVALID_FRAME:
4838 +       case MPI_SASSTATUS_UTC_BREAK_RECEIVED:
4839 +       case MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST:
4840 +       case MPI_SASSTATUS_SHORT_INFORMATION_UNIT:
4841 +       case MPI_SASSTATUS_LONG_INFORMATION_UNIT:
4842 +       case MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA:
4843 +       case MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR:
4844 +       case MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED:
4845 +       case MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH:
4846 +       case MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA:
4847 +       case MPI_SASSTATUS_DATA_OFFSET_ERROR:
4848 +               csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
4849 +               break;
4850 +
4851 +       default:
4852 +               csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
4853 +               break;
4854 +       }
4855 +
4856 +       return csmi_connect_status;
4857 +}
4858 +
4859 +/**
4860 + *                      csmisas_phy_reset
4861 + *     Issues a phy link reset or phy hard reset
4862 + *
4863 + *     @ioc - Pointer to MPT_ADAPTER structure
4864 + *     @PhyNum - phy number
4865 + *     @opcode - {MPI_SAS_OP_PHY_LINK_RESET,MPI_SAS_OP_PHY_HARD_RESET}
4866 + *
4867 + *     Returns: 0 for success, non-zero error
4868 + **/
4869 +static int
4870 +csmisas_phy_reset(MPT_ADAPTER *ioc, u8 PhyNum, u8 opcode)
4871 +{
4872 +       SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
4873 +       SasIoUnitControlReply_t         *sasIoUnitCntrReply;
4874 +       MPT_FRAME_HDR                   *mf = NULL;
4875 +       MPIHeader_t                     *mpi_hdr;
4876 +       u16                             ioc_status;
4877 +       u32                             MsgContext;
4878 +
4879 +       if ((opcode != MPI_SAS_OP_PHY_LINK_RESET) &&
4880 +           (opcode != MPI_SAS_OP_PHY_HARD_RESET))
4881 +           return -1;
4882 +
4883 +       /* Get a MF for this command.
4884 +        */
4885 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
4886 +               dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
4887 +               return -1;
4888 +        }
4889 +
4890 +       mpi_hdr = (MPIHeader_t *) mf;
4891 +       MsgContext =  mpi_hdr->MsgContext;
4892 +       sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4893 +       memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4894 +       sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4895 +       sasIoUnitCntrReq->MsgContext = MsgContext;
4896 +       sasIoUnitCntrReq->Operation = opcode;
4897 +       sasIoUnitCntrReq->PhyNum = PhyNum;
4898 +
4899 +       if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0)
4900 +               return -1;
4901 +
4902 +       if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0)
4903 +               return -1;
4904 +
4905 +       /* process the completed Reply Message Frame */
4906 +       sasIoUnitCntrReply = (SasIoUnitControlReply_t *)ioc->ioctl_cmds.reply;
4907 +       ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus)
4908 +           & MPI_IOCSTATUS_MASK;
4909 +       if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
4910 +               printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4911 +                   __FUNCTION__,
4912 +                   sasIoUnitCntrReply->IOCStatus,
4913 +                   sasIoUnitCntrReply->IOCLogInfo);
4914 +               return -1;
4915 +       }
4916 +       return 0;
4917 +}
4918 +
4919 +/** Prototype Routine for the CSMI SAS Phy Control command.
4920 + *
4921 + * Outputs:    None.
4922 + * Return:     0 if successful
4923 + *             -EFAULT if data unavailable
4924 + *             -ENODEV if no such device/adapter
4925 + **/
4926 +static int
4927 +csmisas_phy_control(unsigned long arg)
4928 +{
4929 +       CSMI_SAS_PHY_CONTROL_BUFFER __user *uarg = (void __user *) arg;
4930 +       IOCTL_HEADER                    ioctl_header;
4931 +       PCSMI_SAS_PHY_CONTROL_BUFFER    karg;
4932 +       SasIOUnitPage0_t                *sasIoUnitPg0=NULL;
4933 +       dma_addr_t                      sasIoUnitPg0_dma;
4934 +       int                             sasIoUnitPg0_data_sz=0;
4935 +       SasIOUnitPage1_t                *sasIoUnitPg1=NULL;
4936 +       dma_addr_t                      sasIoUnitPg1_dma;
4937 +       int                             sasIoUnitPg1_data_sz=0;
4938 +       ConfigExtendedPageHeader_t      hdr;
4939 +       CONFIGPARMS                     cfg;
4940 +       MPT_ADAPTER                     *ioc = NULL;
4941 +       int                             iocnum;
4942 +       int                             csmi_sas_phy_control_buffer_sz;
4943 +       int                             memory_pages;
4944 +
4945 +       if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
4946 +               printk(KERN_ERR "%s@%d::%s() - "
4947 +                   "Unable to read in IOCTL_HEADER"
4948 +                   "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
4949 +               return -EFAULT;
4950 +       }
4951 +
4952 +       csmi_sas_phy_control_buffer_sz = ioctl_header.Length;
4953 +       memory_pages = get_order(csmi_sas_phy_control_buffer_sz);
4954 +       karg = (PCSMI_SAS_PHY_CONTROL_BUFFER)__get_free_pages(
4955 +               GFP_KERNEL, memory_pages);
4956 +       if (!karg){
4957 +               printk(KERN_ERR "%s@%d::%s() - "
4958 +                   "Unable to malloc SAS_PHY_CONTROL_BUFFER "
4959 +                       "csmi_sas_phy_control_buffer_sz=%d memory_pages=%d\n",
4960 +                       __FILE__, __LINE__, __FUNCTION__,
4961 +                       csmi_sas_phy_control_buffer_sz, memory_pages);
4962 +               return -ENOMEM;
4963 +       }
4964 +       memset(karg, 0, sizeof(*karg));
4965 +
4966 +       if (copy_from_user(karg, uarg, csmi_sas_phy_control_buffer_sz)) {
4967 +               printk(KERN_ERR "%s@%d::%s() - "
4968 +                   "Unable to read in csmi_sas_phy_control_buffer "
4969 +                   "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
4970 +               free_pages((unsigned long)karg, memory_pages);
4971 +               return -EFAULT;
4972 +       }
4973 +
4974 +       if (((iocnum = mpt_verify_adapter(ioctl_header.IOControllerNumber,
4975 +           &ioc)) < 0) || (ioc == NULL)) {
4976 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
4977 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4978 +               free_pages((unsigned long)karg, memory_pages);
4979 +               return -ENODEV;
4980 +       }
4981 +
4982 +       if (!csmisas_is_this_sas_cntr(ioc)) {
4983 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
4984 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
4985 +               free_pages((unsigned long)karg, memory_pages);
4986 +               return -ENODEV;
4987 +       }
4988 +
4989 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
4990 +
4991 +       if (karg->bPhyIdentifier >= ioc->num_ports) {
4992 +               karg->IoctlHeader.ReturnCode =
4993 +                  CSMI_SAS_STATUS_INVALID_PARAMETER;
4994 +               goto cim_sas_phy_control_exit;
4995 +       }
4996 +
4997 +       /*
4998 +        *  Retreive SAS IOUNIT PAGE 0
4999 +        */
5000 +
5001 +       hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
5002 +       hdr.ExtPageLength = 0;
5003 +       hdr.PageNumber = 0;
5004 +       hdr.Reserved1 = 0;
5005 +       hdr.Reserved2 = 0;
5006 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5007 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
5008 +
5009 +       cfg.cfghdr.ehdr = &hdr;
5010 +       cfg.physAddr = -1;
5011 +       cfg.pageAddr = 0;
5012 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5013 +       cfg.dir = 0;    /* read */
5014 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
5015 +
5016 +       if (mpt_config(ioc, &cfg) != 0) {
5017 +               dcsmisasprintk(ioc, printk(KERN_ERR
5018 +                   ": FAILED: READ MPI_SASIOUNITPAGE0: HEADER\n"));
5019 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5020 +               goto cim_sas_phy_control_exit;
5021 +       }
5022 +
5023 +       if (hdr.ExtPageLength == 0) {
5024 +               dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
5025 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5026 +               goto cim_sas_phy_control_exit;
5027 +       }
5028 +
5029 +       sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
5030 +       sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
5031 +           sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
5032 +
5033 +       if (!sasIoUnitPg0) {
5034 +               dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
5035 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5036 +               goto cim_sas_phy_control_exit;
5037 +       }
5038 +
5039 +       memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
5040 +       cfg.physAddr = sasIoUnitPg0_dma;
5041 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5042 +
5043 +       if (mpt_config(ioc, &cfg) != 0) {
5044 +               dcsmisasprintk(ioc, printk(KERN_ERR
5045 +                   ": FAILED: READ MPI_SASIOUNITPAGE0: CURRENT\n"));
5046 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5047 +               goto cim_sas_phy_control_exit;
5048 +       }
5049 +
5050 +       /*
5051 +        *  Retreive SAS IOUNIT PAGE 1
5052 +        */
5053 +
5054 +       hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
5055 +       hdr.ExtPageLength = 0;
5056 +       hdr.PageNumber = 1;
5057 +       hdr.Reserved1 = 0;
5058 +       hdr.Reserved2 = 0;
5059 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5060 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
5061 +
5062 +       cfg.cfghdr.ehdr = &hdr;
5063 +       cfg.physAddr = -1;
5064 +       cfg.pageAddr = 0;
5065 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5066 +       cfg.dir = 0;    /* read */
5067 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
5068 +
5069 +       if (mpt_config(ioc, &cfg) != 0) {
5070 +               dcsmisasprintk(ioc, printk(KERN_ERR
5071 +                   ": FAILED: READ MPI_SASIOUNITPAGE1: HEADER\n"));
5072 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5073 +               goto cim_sas_phy_control_exit;
5074 +       }
5075 +
5076 +       if (hdr.ExtPageLength == 0) {
5077 +               dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
5078 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5079 +               goto cim_sas_phy_control_exit;
5080 +       }
5081 +
5082 +       sasIoUnitPg1_data_sz = hdr.ExtPageLength * 4;
5083 +       sasIoUnitPg1 = (SasIOUnitPage1_t *) pci_alloc_consistent(ioc->pcidev,
5084 +           sasIoUnitPg1_data_sz, &sasIoUnitPg1_dma);
5085 +
5086 +       if (!sasIoUnitPg1) {
5087 +               dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
5088 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5089 +               goto cim_sas_phy_control_exit;
5090 +       }
5091 +
5092 +       memset((u8 *)sasIoUnitPg1, 0, sasIoUnitPg1_data_sz);
5093 +       cfg.physAddr = sasIoUnitPg1_dma;
5094 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5095 +
5096 +       if (mpt_config(ioc, &cfg) != 0) {
5097 +               dcsmisasprintk(ioc, printk(KERN_ERR
5098 +                   ": FAILED:  READ MPI_SASIOUNITPAGE1: CURRENT\n"));
5099 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5100 +               goto cim_sas_phy_control_exit;
5101 +       }
5102 +
5103 +       switch (karg->uFunction) {
5104 +
5105 +       case CSMI_SAS_PC_LINK_RESET:
5106 +       case CSMI_SAS_PC_HARD_RESET:
5107 +       {
5108 +               u8 opcode = (karg->uFunction==CSMI_SAS_PC_LINK_RESET) ?
5109 +                   MPI_SAS_OP_PHY_LINK_RESET : MPI_SAS_OP_PHY_HARD_RESET;
5110 +
5111 +               if((karg->uLinkFlags & CSMI_SAS_PHY_ACTIVATE_CONTROL) &&
5112 +                   (karg->usLengthOfControl >= sizeof(CSMI_SAS_PHY_CONTROL)) &&
5113 +                   (karg->bNumberOfControls > 0)){
5114 +                       if(karg->Control[0].bRate ==
5115 +                          CSMI_SAS_LINK_RATE_1_5_GBPS) {
5116 +                               sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
5117 +                               MPI_SAS_IOUNIT1_MAX_RATE_1_5 |
5118 +                               MPI_SAS_IOUNIT1_MIN_RATE_1_5;
5119 +                       }
5120 +                       else if(karg->Control[0].bRate ==
5121 +                          CSMI_SAS_LINK_RATE_3_0_GBPS) {
5122 +                               sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
5123 +                               MPI_SAS_IOUNIT1_MAX_RATE_3_0 |
5124 +                               MPI_SAS_IOUNIT1_MIN_RATE_3_0;
5125 +                       }
5126 +                       sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags &=
5127 +                           ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
5128 +                       cfg.dir = 1;
5129 +                       cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5130 +                       if (mpt_config(ioc, &cfg) != 0) {
5131 +                               dcsmisasprintk(ioc, printk(KERN_ERR
5132 +                           ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
5133 +                               karg->IoctlHeader.ReturnCode =
5134 +                                  CSMI_SAS_STATUS_FAILED;
5135 +                               goto cim_sas_phy_control_exit;
5136 +                       }
5137 +                       cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5138 +                       if (mpt_config(ioc, &cfg) != 0) {
5139 +                               dcsmisasprintk(ioc, printk(KERN_ERR
5140 +                        ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
5141 +                               karg->IoctlHeader.ReturnCode =
5142 +                                  CSMI_SAS_STATUS_FAILED;
5143 +                               goto cim_sas_phy_control_exit;
5144 +                       }
5145 +               }
5146 +               if (csmisas_phy_reset(ioc,
5147 +                   karg->bPhyIdentifier, opcode) != 0) {
5148 +                       dcsmisasprintk(ioc, printk(KERN_ERR
5149 +                           ": FAILED: csmisas_phy_reset\n"));
5150 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5151 +                       goto cim_sas_phy_control_exit;
5152 +               }
5153 +               break;
5154 +
5155 +       }
5156 +       case CSMI_SAS_PC_PHY_DISABLE:
5157 +               if(karg->usLengthOfControl || karg->bNumberOfControls) {
5158 +                       karg->IoctlHeader.ReturnCode =
5159 +                           CSMI_SAS_STATUS_INVALID_PARAMETER;
5160 +                       break;
5161 +               }
5162 +               sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags |=
5163 +                   MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
5164 +               cfg.dir = 1;
5165 +               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5166 +               if (mpt_config(ioc, &cfg) != 0) {
5167 +                       dcsmisasprintk(ioc, printk(KERN_ERR
5168 +                           ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
5169 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5170 +                       goto cim_sas_phy_control_exit;
5171 +               }
5172 +               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5173 +               if (mpt_config(ioc, &cfg) != 0) {
5174 +                       dcsmisasprintk(ioc, printk(KERN_ERR
5175 +                           ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
5176 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5177 +                       goto cim_sas_phy_control_exit;
5178 +               }
5179 +               if (csmisas_phy_reset(ioc,
5180 +                   karg->bPhyIdentifier, MPI_SAS_OP_PHY_HARD_RESET) != 0) {
5181 +                       dcsmisasprintk(ioc, printk(KERN_ERR
5182 +                           ": FAILED: csmisas_phy_reset\n"));
5183 +                       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5184 +                       goto cim_sas_phy_control_exit;
5185 +               }
5186 +               break;
5187 +
5188 +       case CSMI_SAS_PC_GET_PHY_SETTINGS:
5189 +               if(karg->usLengthOfControl || karg->bNumberOfControls) {
5190 +                       karg->IoctlHeader.ReturnCode =
5191 +                           CSMI_SAS_STATUS_INVALID_PARAMETER;
5192 +                       break;
5193 +               }
5194 +               if(csmi_sas_phy_control_buffer_sz <
5195 +                   offsetof(CSMI_SAS_PHY_CONTROL_BUFFER,Control) +
5196 +                   (4* sizeof(CSMI_SAS_PHY_CONTROL))) {
5197 +                       karg->IoctlHeader.ReturnCode =
5198 +                           CSMI_SAS_STATUS_INVALID_PARAMETER;
5199 +                       break;
5200 +               }
5201 +               karg->usLengthOfControl = sizeof(CSMI_SAS_PHY_CONTROL);
5202 +               karg->bNumberOfControls = 4;
5203 +               karg->Control[0].bType = CSMI_SAS_SAS;
5204 +               karg->Control[0].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
5205 +               karg->Control[1].bType = CSMI_SAS_SAS;
5206 +               karg->Control[1].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
5207 +               karg->Control[2].bType = CSMI_SAS_SATA;
5208 +               karg->Control[2].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
5209 +               karg->Control[3].bType = CSMI_SAS_SATA;
5210 +               karg->Control[3].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
5211 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
5212 +               break;
5213 +       default:
5214 +               break;
5215 +       }
5216 +
5217 + cim_sas_phy_control_exit:
5218 +
5219 +       if (sasIoUnitPg0)
5220 +               pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
5221 +                   (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
5222 +
5223 +       if (sasIoUnitPg1)
5224 +               pci_free_consistent(ioc->pcidev, sasIoUnitPg1_data_sz,
5225 +                   (u8 *) sasIoUnitPg1, sasIoUnitPg1_dma);
5226 +
5227 +       /* Copy the data from kernel memory to user memory
5228 +        */
5229 +       if (copy_to_user(uarg, karg,csmi_sas_phy_control_buffer_sz)) {
5230 +               printk(KERN_ERR "%s@%d::%s() - "
5231 +                   "Unable to write out csmi_sas_phy_control_buffer @ %p\n",
5232 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
5233 +               free_pages((unsigned long)karg, memory_pages);
5234 +               return -EFAULT;
5235 +       }
5236 +
5237 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
5238 +       free_pages((unsigned long)karg, memory_pages);
5239 +       return 0;
5240 +}
5241 +
5242 +/**
5243 + *     csmisas_get_manuf_pg_7 - Fetch Manufacturing config Page7.
5244 + * @ioc: Pointer to MPT_ADAPTER structure
5245 + * @mfgpage7_buffer: pointer to ManufacturingPage7_t that returns config
5246 + *                    page data
5247 + * @mfg_size - max size of buffer
5248 + *
5249 + *     Return: 0 for success
5250 + *     -ENOMEM if no memory available
5251 + *             -EPERM if not allowed due to ISR context
5252 + *             -EAGAIN if no msg frames currently available
5253 + *             -EFAULT for non-successful reply or no reply (timeout)
5254 + **/
5255 +static int
5256 +csmisas_get_manuf_pg_7(MPT_ADAPTER *ioc, ManufacturingPage7_t *mfgpage7_buffer, int mfg_size)
5257 +{
5258 +       ConfigPageHeader_t hdr;
5259 +       CONFIGPARMS     cfg;
5260 +       ManufacturingPage7_t *mfgPage7 = NULL;
5261 +       dma_addr_t      mfgPage7_dma;
5262 +       int             data_sz = 0;
5263 +       int             rc;
5264 +
5265 +       /* Get Manufacturing Page 7 header */
5266 +       hdr.PageVersion = MPI_MANUFACTURING0_PAGEVERSION;
5267 +       hdr.PageLength = 0;
5268 +       hdr.PageNumber = 7;
5269 +       hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
5270 +       cfg.cfghdr.hdr = &hdr;
5271 +       cfg.physAddr = -1;
5272 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5273 +       cfg.dir = 0;
5274 +       cfg.pageAddr = 0;
5275 +       cfg.timeout = 0;
5276 +
5277 +       if ((rc = mpt_config(ioc, &cfg)) != 0)
5278 +               goto csmisas_get_manuf_pg_7_exit;
5279 +
5280 +       if (hdr.PageLength == 0) {
5281 +               rc = -EFAULT;
5282 +               goto csmisas_get_manuf_pg_7_exit;
5283 +       }
5284 +
5285 +       data_sz = hdr.PageLength * 4;
5286 +       mfgPage7 = pci_alloc_consistent(ioc->pcidev, data_sz, &mfgPage7_dma);
5287 +       if (!mfgPage7) {
5288 +               rc = -ENOMEM;
5289 +               goto csmisas_get_manuf_pg_7_exit;
5290 +       }
5291 +
5292 +       memset((u8 *)mfgPage7, 0, data_sz);
5293 +       cfg.physAddr = mfgPage7_dma;
5294 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5295 +
5296 +       if ((rc = mpt_config(ioc, &cfg)) != 0)
5297 +               goto csmisas_get_manuf_pg_7_exit;
5298 +
5299 +       /* copy buffer back to user */
5300 +       memcpy(mfgpage7_buffer, mfgPage7, min(data_sz, mfg_size));
5301 +
5302 + csmisas_get_manuf_pg_7_exit:
5303 +
5304 +       if (mfgPage7)
5305 +               pci_free_consistent(ioc->pcidev, data_sz, (u8 *)mfgPage7,
5306 +                   mfgPage7_dma);
5307 +
5308 +       return rc;
5309 +}
5310 +
5311 +/**
5312 + * Prototype Routine for the CSMI SAS Get Connector info command.
5313 + *
5314 + * Outputs:    None.
5315 + * Return:     0 if successful
5316 + *             -EFAULT if data unavailable
5317 + *             -ENODEV if no such device/adapter
5318 + **/
5319 +static int
5320 +csmisas_get_connector_info(unsigned long arg)
5321 +{
5322 +       CSMI_SAS_CONNECTOR_INFO_BUFFER __user *uarg = (void __user *) arg;
5323 +       CSMI_SAS_CONNECTOR_INFO_BUFFER   karg;
5324 +       MPT_ADAPTER                     *ioc = NULL;
5325 +       ManufacturingPage7_t            *mfgPg7 = NULL;
5326 +       int                             mfgPg7_sz;
5327 +       int                             iocnum;
5328 +       int                             i;
5329 +
5330 +       if (copy_from_user(&karg, uarg,
5331 +               sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
5332 +               printk(KERN_ERR "%s@%d::%s() - "
5333 +                  "Unable to read in csmi_sas_connector_info_buffer"
5334 +                  " struct @ %p\n",
5335 +                  __FILE__, __LINE__, __FUNCTION__, uarg);
5336 +               return -EFAULT;
5337 +       }
5338 +
5339 +       if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
5340 +           &ioc)) < 0) || (ioc == NULL)) {
5341 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
5342 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
5343 +               return -ENODEV;
5344 +       }
5345 +
5346 +       if (!csmisas_is_this_sas_cntr(ioc)) {
5347 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
5348 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
5349 +               return -ENODEV;
5350 +       }
5351 +
5352 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
5353 +
5354 +       karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
5355 +
5356 +       /* `32` is the sizeof MPI_MANPAGE7_CONNECTOR_INFO */
5357 +       for (i = 0; i < 32; i++) {
5358 +               karg.Reference[i].uPinout = CSMI_SAS_CON_UNKNOWN;
5359 +               strcpy(karg.Reference[i].bConnector,"");
5360 +               karg.Reference[i].bLocation = CSMI_SAS_CON_UNKNOWN;
5361 +       }
5362 +
5363 +       mfgPg7_sz = offsetof(CONFIG_PAGE_MANUFACTURING_7,ConnectorInfo) +
5364 +           (ioc->num_ports * sizeof(MPI_MANPAGE7_CONNECTOR_INFO));
5365 +       mfgPg7 = kmalloc(mfgPg7_sz, GFP_KERNEL);
5366 +       if (!mfgPg7){
5367 +               printk(KERN_ERR "%s@%d::%s() - "
5368 +                   "Unable to malloc @ %p\n",
5369 +                   __FILE__, __LINE__, __FUNCTION__, mfgPg7);
5370 +               return -EFAULT;
5371 +       }
5372 +       memset(mfgPg7, 0, mfgPg7_sz);
5373 +
5374 +       if (!csmisas_get_manuf_pg_7(ioc, mfgPg7, mfgPg7_sz)) {
5375 +               for (i = 0; i < ioc->num_ports; i++) {
5376 +                       karg.Reference[i].uPinout =
5377 +                           le32_to_cpu(mfgPg7->ConnectorInfo[i].Pinout);
5378 +                       /*endian conversion , this is u8 * 16 ?? */
5379 +                       strncpy(karg.Reference[i].bConnector,
5380 +                           mfgPg7->ConnectorInfo[i].Connector, 16);
5381 +                       karg.Reference[i].bLocation =
5382 +                           mfgPg7->ConnectorInfo[i].Location;
5383 +               }
5384 +       }
5385 +
5386 +       kfree(mfgPg7);
5387 +
5388 +       /* Copy the data from kernel memory to user memory
5389 +        */
5390 +       if (copy_to_user(uarg, &karg,
5391 +               sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
5392 +               printk(KERN_ERR "%s@%d::%s() - "
5393 +               "Unable to write out csmi_sas_connector_info_buffer @"
5394 +              "%p\n",
5395 +               __FILE__, __LINE__, __FUNCTION__, uarg);
5396 +               return -EFAULT;
5397 +       }
5398 +
5399 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
5400 +       return 0;
5401 +}
5402 +
5403 +/**
5404 + *                 csmisas_fill_location_data
5405 + *
5406 + * Outputs:    None.
5407 + * Return:     0 if successful
5408 + **/
5409 +static int
5410 +csmisas_fill_location_data(MPT_ADAPTER *ioc, u8 bus, u8 id, u8 opcode,
5411 +       CSMI_SAS_LOCATION_IDENTIFIER * location_ident)
5412 +{
5413 +
5414 +       ConfigExtendedPageHeader_t      hdr;
5415 +       CONFIGPARMS                     cfg;
5416 +       int                             rc;
5417 +       SasDevicePage0_t                *sasDevicePg0=NULL;
5418 +       SasEnclosurePage0_t             *sasEnclosurePg0=NULL;
5419 +       dma_addr_t                      sasDevicePg0_dma,sasEnclosurePg0_dma;
5420 +       int                             sasDevicePg0_data_sz=0;
5421 +       int                             sasEnclosurePg0_data_sz=0;
5422 +       u64                             sas_address;
5423 +
5424 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
5425 +       memset (location_ident, 0, sizeof(*location_ident));
5426 +
5427 +       /* SAS Device Page 0 */
5428 +       hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
5429 +       hdr.ExtPageLength = 0;
5430 +       hdr.PageNumber = 0;
5431 +       hdr.Reserved1 = 0;
5432 +       hdr.Reserved2 = 0;
5433 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5434 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
5435 +
5436 +       cfg.cfghdr.ehdr = &hdr;
5437 +       cfg.physAddr = -1;
5438 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5439 +       cfg.dir = 0;    /* read */
5440 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
5441 +
5442 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
5443 +               rc=-1;
5444 +               goto fill_location_data_exit;
5445 +       }
5446 +
5447 +       if (hdr.ExtPageLength == 0) {
5448 +               rc=-1;
5449 +               goto fill_location_data_exit;
5450 +       }
5451 +
5452 +       sasDevicePg0_data_sz = hdr.ExtPageLength * 4;
5453 +       sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent(
5454 +           ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma);
5455 +       if (!sasDevicePg0) {
5456 +               rc=-1;
5457 +               goto fill_location_data_exit;
5458 +       }
5459 +
5460 +       memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz);
5461 +       cfg.physAddr = sasDevicePg0_dma;
5462 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5463 +       cfg.pageAddr = (bus << 8) + id
5464 +           + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
5465 +               MPI_SAS_DEVICE_PGAD_FORM_SHIFT);
5466 +
5467 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
5468 +               rc=-1;
5469 +               goto fill_location_data_exit;
5470 +       }
5471 +
5472 +       location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_ADDRESS_VALID;
5473 +       memcpy(&sas_address, &sasDevicePg0->SASAddress, sizeof(u64));
5474 +       sas_address = reverse_byte_order64(sas_address);
5475 +       memcpy(location_ident->bSASAddress, &sas_address, sizeof(u64));
5476 +
5477 +       location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_LUN_VALID;
5478 +       memset(location_ident->bSASLun, 0, sizeof(location_ident->bSASLun));
5479 +
5480 +       /* SAS Enclosure Page 0 */
5481 +       hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
5482 +       hdr.ExtPageLength = 0;
5483 +       hdr.PageNumber = 0;
5484 +       hdr.Reserved1 = 0;
5485 +       hdr.Reserved2 = 0;
5486 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5487 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
5488 +
5489 +       cfg.cfghdr.ehdr = &hdr;
5490 +       cfg.physAddr = -1;
5491 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5492 +       cfg.dir = 0;    /* read */
5493 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
5494 +
5495 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
5496 +               rc=0;
5497 +               goto fill_location_data_exit;
5498 +       }
5499 +
5500 +       if (hdr.ExtPageLength == 0) {
5501 +               rc=0;
5502 +               goto fill_location_data_exit;
5503 +       }
5504 +
5505 +       sasEnclosurePg0_data_sz = hdr.ExtPageLength * 4;
5506 +       sasEnclosurePg0 = (SasEnclosurePage0_t *) pci_alloc_consistent(
5507 +           ioc->pcidev, sasEnclosurePg0_data_sz, &sasEnclosurePg0_dma);
5508 +       if (!sasEnclosurePg0) {
5509 +               rc=0;
5510 +               goto fill_location_data_exit;
5511 +       }
5512 +       cfg.physAddr = sasEnclosurePg0_dma;
5513 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5514 +       cfg.pageAddr = sasDevicePg0->EnclosureHandle
5515 +           + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << MPI_SAS_ENCLOS_PGAD_FORM_SHIFT);
5516 +
5517 +       if ((rc = mpt_config(ioc, &cfg)) != 0) {
5518 +               rc=0;
5519 +               goto fill_location_data_exit;
5520 +       }
5521 +
5522 +       location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID;
5523 +       memcpy(&sas_address, &sasEnclosurePg0->EnclosureLogicalID, sizeof(u64));
5524 +       sas_address = reverse_byte_order64(sas_address);
5525 +       if (sas_address)
5526 +               memcpy(location_ident->bEnclosureIdentifier, &sas_address, sizeof(u64));
5527 +       else
5528 +               strcpy(location_ident->bEnclosureIdentifier,"Internal");
5529 +
5530 +// bBayPrefix - not supported
5531 +
5532 +// TODO - We need to look at sasEnclosurePg0-.Flags , to determine
5533 +//     whether SEP BUS/TargetID is valid.  Ifs its a SES device, then
5534 +//     issue internal inquiry to (bus/id) to gather the Enclosure name.
5535 +//     If the device is SMP, then issue SMP_MANUFACTURING to get enclosure name
5536 +//     If its direct attached, there is no enclosure name
5537 +       location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID;
5538 +       strcpy(location_ident->bEnclosureName,"Not Supported");
5539 +
5540 +       location_ident->bLocationFlags |= CSMI_SAS_LOCATE_LOCATION_STATE_VALID;
5541 +       location_ident->bLocationState = CSMI_SAS_LOCATE_UNKNOWN;
5542 +
5543 +       location_ident->bLocationFlags |= CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID;
5544 +       location_ident->bBayIdentifier = le16_to_cpu(sasDevicePg0->Slot);
5545 +
5546 +
5547 +// TODO - illuminating LEDs,
5548 +// karg->bIdentify = CSMI_SAS_LOCATE_FORCE_OFF, CSMI_SAS_LOCATE_FORCE_ON
5549 +// We can enable/disable LEDs by SCSI Enclosure Processor MPI request message
5550 +// printk("Flags=0x%x\n",sasEnclosurePg0->Flags);
5551 +
5552 +/* check sasEnclosurePg0->Flags -
5553 + * to validate whether we need to send the SEPRequest
5554 + * bit:5 should be set
5555 + * bit:3-0 any bit should be set.  If zero, then SEPRequest will fail
5556 +*/
5557 +
5558 +/* MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR
5559 + * Look in mpi_init.h
5560 + * SEPRequest_t = structure
5561 + *
5562 + * SEPRequest_t->Action should be set to MPI_SEP_REQ_ACTION_WRITE_STATUS
5563 + *
5564 + * SEPRequest_t->Flags should be set to
5565 + * MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS, to pass along enclosure/slot ids
5566 + *
5567 + * SEPRequest_t->SlotStatus |= MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST - this
5568 + * will illuminate the LEDs
5569 + */
5570 +
5571 +fill_location_data_exit:
5572 +
5573 +       if (sasDevicePg0 != NULL)
5574 +               pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
5575 +                   sasDevicePg0, sasDevicePg0_dma);
5576 +
5577 +       if (sasEnclosurePg0 != NULL)
5578 +               pci_free_consistent(ioc->pcidev, sasEnclosurePg0_data_sz,
5579 +                   sasEnclosurePg0, sasEnclosurePg0_dma);
5580 +
5581 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
5582 +       return rc;
5583 +}
5584 +
5585 +static int
5586 +csmisas_fill_location_data_raid(MPT_ADAPTER *ioc, PCSMI_SAS_GET_LOCATION_BUFFER karg, u8 VolumeBus,
5587 +       u8 volumeID)
5588 +{
5589 +       pRaidVolumePage0_t              pVolume0 = NULL;
5590 +       pRaidPhysDiskPage0_t            pPhysDisk0 = NULL;
5591 +       CONFIGPARMS                     cfg;
5592 +       ConfigPageHeader_t              header;
5593 +       u8                              physDiskNumMax;
5594 +       int                             volumepage0sz = 0, physdiskpage0sz = 0;
5595 +       dma_addr_t                      volume0_dma, physdisk0_dma;
5596 +       int                             csmi_sas_get_location_sz;
5597 +       int                             rc = 0, i, idx;
5598 +       int                             num_hotpares;
5599 +       u64                             totalMaxLBA, tmpTotalMaxLBA;
5600 +       IOCPage5_t                      *iocPage5 = NULL;
5601 +       u32                             device_info = 0;
5602 +       struct sas_device_info          *sas_info;
5603 +
5604 +       int                             sz;
5605 +
5606 +       csmi_sas_get_location_sz = karg->IoctlHeader.Length;
5607 +       physDiskNumMax = (csmi_sas_get_location_sz -
5608 +           offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location))
5609 +           / sizeof(CSMI_SAS_LOCATION_IDENTIFIER);
5610 +       karg->bNumberOfLocationIdentifiers=0;
5611 +
5612 +       /*
5613 +        * get RAID Volume Page 0
5614 +        */
5615 +
5616 +       header.PageVersion = 0;
5617 +       header.PageLength = 0;
5618 +       header.PageNumber = 0;
5619 +       header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
5620 +       cfg.cfghdr.hdr = &header;
5621 +       cfg.physAddr = -1;
5622 +       cfg.pageAddr = (VolumeBus << 8) + volumeID;
5623 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5624 +       cfg.dir = 0;
5625 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
5626 +       if (mpt_config(ioc, &cfg) != 0) {
5627 +               rc = -1;
5628 +               goto sas_fill_location_data_raid_exit;
5629 +       }
5630 +
5631 +       if (header.PageLength == 0) {
5632 +               rc = -1;
5633 +               goto sas_fill_location_data_raid_exit;
5634 +       }
5635 +
5636 +       volumepage0sz = header.PageLength * 4;
5637 +       pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
5638 +           &volume0_dma);
5639 +       if (!pVolume0) {
5640 +               rc = -1;
5641 +               goto sas_fill_location_data_raid_exit;
5642 +       }
5643 +
5644 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5645 +       cfg.physAddr = volume0_dma;
5646 +       if (mpt_config(ioc, &cfg) != 0){
5647 +               rc = -1;
5648 +               goto sas_fill_location_data_raid_exit;
5649 +       }
5650 +
5651 +       totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) |
5652 +           ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32;
5653 +
5654 +       /*
5655 +        * get RAID Physical Disk Page 0
5656 +        */
5657 +       header.PageVersion = 0;
5658 +       header.PageLength = 0;
5659 +       header.PageNumber = 0;
5660 +       header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5661 +       cfg.cfghdr.hdr = &header;
5662 +       cfg.physAddr = -1;
5663 +       cfg.pageAddr = 0;
5664 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5665 +       cfg.dir = 0;
5666 +       cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
5667 +       if (mpt_config(ioc, &cfg) != 0) {
5668 +               rc = -1;
5669 +               goto sas_fill_location_data_raid_exit;
5670 +       }
5671 +
5672 +       if (header.PageLength == 0) {
5673 +               rc = -1;
5674 +               goto sas_fill_location_data_raid_exit;
5675 +       }
5676 +
5677 +       physdiskpage0sz = header.PageLength * 4;
5678 +       pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
5679 +           &physdisk0_dma);
5680 +       if (!pPhysDisk0) {
5681 +               rc = -1;
5682 +               goto sas_fill_location_data_raid_exit;
5683 +       }
5684 +       cfg.physAddr = physdisk0_dma;
5685 +
5686 +       for (i=0; i < min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
5687 +
5688 +               /* obtain a refresh of pPhysDisk0 */
5689 +               cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5690 +               cfg.pageAddr = pVolume0->PhysDisk[i].PhysDiskNum;
5691 +               if (mpt_config(ioc, &cfg) != 0){
5692 +                       rc = -1;
5693 +                       goto sas_fill_location_data_raid_exit;
5694 +               }
5695 +
5696 +               if((csmisas_fill_location_data(ioc, pPhysDisk0->PhysDiskBus,
5697 +                   pPhysDisk0->PhysDiskID, karg->bIdentify,
5698 +                   &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
5699 +                       karg->bNumberOfLocationIdentifiers++;
5700 +
5701 +               if (device_info)
5702 +                       continue;
5703 +               sas_info = csmisas_get_device_component_by_fw(ioc,
5704 +                   pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
5705 +               if (!sas_info || sas_info->is_cached)
5706 +                       continue;
5707 +               device_info = sas_info->device_info;
5708 +       }
5709 +
5710 +       if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS)
5711 +               goto sas_fill_location_data_raid_exit;
5712 +
5713 +       /*
5714 +        * hot spare support
5715 +        *
5716 +        */
5717 +
5718 +       num_hotpares = csmisas_get_number_hotspares(ioc);
5719 +
5720 +       if (num_hotpares) {
5721 +
5722 +               sz = offsetof(IOCPage5_t, HotSpare) +
5723 +                   num_hotpares * sizeof(IOC_5_HOT_SPARE);
5724 +               iocPage5 = kmalloc(sz, GFP_KERNEL);
5725 +
5726 +               if (!iocPage5)
5727 +                       goto sas_fill_location_data_raid_exit;
5728 +               memset(iocPage5, 0, sizeof(*iocPage5));
5729 +
5730 +               if (csmisas_get_ioc_pg5(ioc, iocPage5, sz) != 0)
5731 +                       goto sas_fill_location_data_raid_exit;
5732 +
5733 +               for(i = 0, idx = pVolume0->NumPhysDisks ; i < num_hotpares;
5734 +                   i++, idx++) {
5735 +
5736 +                       if (idx >= physDiskNumMax)
5737 +                               break;
5738 +
5739 +                       /* obtain a refresh of pPhysDisk0 */
5740 +                       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5741 +                       cfg.pageAddr = iocPage5->HotSpare[i].PhysDiskNum;
5742 +                       if (mpt_config(ioc, &cfg) != 0)
5743 +                               goto sas_fill_location_data_raid_exit;
5744 +
5745 +                       /* Search the list for the matching SAS address. */
5746 +                       sas_info = csmisas_get_device_component_by_fw(ioc,
5747 +                           pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
5748 +
5749 +                       if (!sas_info || sas_info->is_cached)
5750 +                               continue;
5751 +
5752 +                       /* don't mix SSP hot spare
5753 +                        * in SATA volume
5754 +                        */
5755 +                       if (!csmisas_is_sata(pPhysDisk0) &&
5756 +                           (device_info &
5757 +                           MPI_SAS_DEVICE_INFO_SATA_DEVICE))
5758 +                               continue;
5759 +
5760 +                       /* don't mix SATA hot spare
5761 +                        * in SSP volume
5762 +                        */
5763 +                       if (csmisas_is_sata(pPhysDisk0) &&
5764 +                           (device_info &
5765 +                           MPI_SAS_DEVICE_INFO_SSP_TARGET))
5766 +                               continue;
5767 +
5768 +                       /* capacity check for IM volumes*/
5769 +                       if ((pVolume0->VolumeType ==
5770 +                           MPI_RAID_VOL_TYPE_IM) &&
5771 +                           (totalMaxLBA +
5772 +                           (64*2*1024) /* metadata = 64MB*/ >
5773 +                           le32_to_cpu(pPhysDisk0->MaxLBA)))
5774 +                               continue;
5775 +
5776 +                       tmpTotalMaxLBA = totalMaxLBA;
5777 +                       do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
5778 +                       /* capacity check for IME volumes*/
5779 +                       if ((pVolume0->VolumeType ==
5780 +                               MPI_RAID_VOL_TYPE_IME) &&
5781 +                           ((tmpTotalMaxLBA * 2) +
5782 +                            (64*2*1024 ) /*metadata = 64MB*/ >
5783 +                           le32_to_cpu(pPhysDisk0->MaxLBA)))
5784 +                               continue;
5785 +
5786 +                       if((csmisas_fill_location_data(ioc,
5787 +                           pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID,
5788 +                           karg->bIdentify,
5789 +                           &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
5790 +                               karg->bNumberOfLocationIdentifiers++;
5791 +               }
5792 +       }
5793 +
5794 +
5795 + sas_fill_location_data_raid_exit:
5796 +
5797 +       kfree(iocPage5);
5798 +
5799 +       if (pVolume0)
5800 +               pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
5801 +                   volume0_dma);
5802 +
5803 +       if(pPhysDisk0)
5804 +               pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
5805 +                   physdisk0_dma);
5806 +
5807 +       return rc;
5808 +}
5809 +
5810 +/**
5811 + * Prototype Routine for the CSMI SAS Get location command.
5812 + *
5813 + * Outputs:    None.
5814 + * Return:     0 if successful
5815 + *             -EFAULT if data unavailable
5816 + *             -ENODEV if no such device/adapter
5817 + */
5818 +static int
5819 +csmisas_get_location(unsigned long arg)
5820 +{
5821 +       CSMI_SAS_GET_LOCATION_BUFFER __user *uarg = (void __user *) arg;
5822 +       PCSMI_SAS_GET_LOCATION_BUFFER   karg;
5823 +       IOCTL_HEADER                    ioctl_header;
5824 +       MPT_ADAPTER                     *ioc = NULL;
5825 +       int                             iocnum,i;
5826 +       int                             csmi_sas_get_location_sz;
5827 +       int                             memory_pages;
5828 +       struct sas_device_info          *sas_info;
5829 +
5830 +       if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
5831 +               printk(KERN_ERR "%s@%d::%s() - "
5832 +                   "Unable to read in IOCTL_HEADER"
5833 +                   "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
5834 +               return -EFAULT;
5835 +       }
5836 +
5837 +       csmi_sas_get_location_sz = ioctl_header.Length;
5838 +       memory_pages = get_order(csmi_sas_get_location_sz);
5839 +       karg = (PCSMI_SAS_GET_LOCATION_BUFFER)__get_free_pages(
5840 +               GFP_KERNEL, memory_pages);
5841 +       if (!karg){
5842 +               printk(KERN_ERR "%s@%d::%s() - "
5843 +                       "Unable to malloc GET_LOCATION_BUFFER "
5844 +                       "csmi_sas_get_location_sz=%d memory_pages=%d\n",
5845 +                       __FILE__, __LINE__, __FUNCTION__,
5846 +                       csmi_sas_get_location_sz, memory_pages);
5847 +               return -ENOMEM;
5848 +       }
5849 +       memset(karg, 0, sizeof(*karg));
5850 +
5851 +       if (copy_from_user(karg, uarg, csmi_sas_get_location_sz)) {
5852 +               printk(KERN_ERR "%s@%d::%s() - "
5853 +                   "Unable to read in csmi_sas_phy_control_buffer "
5854 +                   "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
5855 +               free_pages((unsigned long)karg, memory_pages);
5856 +               return -EFAULT;
5857 +       }
5858 +
5859 +       if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
5860 +           &ioc)) < 0) || (ioc == NULL)) {
5861 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
5862 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
5863 +               free_pages((unsigned long)karg, memory_pages);
5864 +               return -ENODEV;
5865 +       }
5866 +
5867 +       if (!csmisas_is_this_sas_cntr(ioc)) {
5868 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
5869 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
5870 +               free_pages((unsigned long)karg, memory_pages);
5871 +               return -ENODEV;
5872 +       }
5873 +
5874 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
5875 +
5876 +       karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
5877 +       if(karg->bLengthOfLocationIdentifier !=
5878 +           sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
5879 +               goto cim_sas_get_location_exit;
5880 +
5881 +       sas_info = csmisas_get_device_component_by_os(ioc, karg->bPathId,
5882 +           karg->bTargetId);
5883 +       if (!sas_info)
5884 +               goto cim_sas_get_location_exit;
5885 +
5886 +       /* RAID SUPPORT */
5887 +       if (ioc->raid_data.pIocPg2 && sas_info->is_logical_volume) {
5888 +               for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){
5889 +                       if (sas_info->fw.id ==
5890 +                           ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID &&
5891 +                           sas_info->fw.channel ==
5892 +                           ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus) {
5893 +                               if(csmisas_fill_location_data_raid(ioc, karg,
5894 +                                   ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus,
5895 +                                   ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) == 0)
5896 +                                       karg->IoctlHeader.ReturnCode =
5897 +                                           CSMI_SAS_STATUS_SUCCESS;
5898 +                               else
5899 +                                       karg->IoctlHeader.ReturnCode =
5900 +                                           CSMI_SAS_STATUS_FAILED;
5901 +                               goto cim_sas_get_location_exit;
5902 +                       }
5903 +               }
5904 +       }
5905 +
5906 +       /* NON-RAID SUPPORT */
5907 +       if (sas_info->is_cached || sas_info->is_logical_volume)
5908 +               goto cim_sas_get_location_exit;
5909 +
5910 +       /* make sure there's enough room to populate the Location[] struct */
5911 +       if ((csmi_sas_get_location_sz -
5912 +           offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) <
5913 +           sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
5914 +               goto cim_sas_get_location_exit;
5915 +
5916 +       karg->bNumberOfLocationIdentifiers=1;
5917 +       karg->Location[0].bLocationFlags=0;
5918 +       if((csmisas_fill_location_data(ioc, sas_info->fw.channel,
5919 +           sas_info->fw.id, karg->bIdentify, &karg->Location[0])) == 0)
5920 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
5921 +       else
5922 +               karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
5923 +
5924 + cim_sas_get_location_exit:
5925 +
5926 +       /* Copy the data from kernel memory to user memory
5927 +        */
5928 +       if (copy_to_user(uarg, karg, csmi_sas_get_location_sz)) {
5929 +               printk(KERN_ERR "%s@%d::%s() - "
5930 +                   "Unable to write out csmi_sas_get_location_buffer "
5931 +                   "@ %p\n",__FILE__, __LINE__, __FUNCTION__, uarg);
5932 +               free_pages((unsigned long)karg, memory_pages);
5933 +               return -EFAULT;
5934 +       }
5935 +
5936 +       dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
5937 +       free_pages((unsigned long)karg, memory_pages);
5938 +       return 0;
5939 +}
5940 --- /dev/null
5941 +++ b/drivers/message/fusion/csmi/csmisas.h
5942 @@ -0,0 +1,1854 @@
5943 +/**************************************************************************
5944 +
5945 +Module Name:
5946 +
5947 +   CSMISAS.H
5948 +
5949 +
5950 +Abstract:
5951 +
5952 +   This file contains constants and data structure definitions used by drivers
5953 +   that support the Common Storage Management Interface specification for
5954 +   SAS or SATA in either the Windows or Linux.
5955 +
5956 +   This should be considered as a reference implementation only.  Changes may
5957 +   be necessary to accommodate a specific build environment or target OS.
5958 +
5959 +Revision History:
5960 +
5961 +   001  SEF   8/12/03  Initial release.
5962 +   002  SEF   8/20/03  Cleanup to match documentation.
5963 +   003  SEF   9/12/03  Additional cleanup, created combined header
5964 +   004  SEF   9/23/03  Changed base types to match linux defaults
5965 +                       Added RAID signature
5966 +                       Added bControllerFlags to CSMI_SAS_CNTLR_CONFIG
5967 +                       Changed CSMI_SAS_BEGIN_PACK to 8 for common structures
5968 +                       Fixed other typos identified in first compilation test
5969 +   005  SEF  10/03/03  Additions to match first version of CSMI document
5970 +   006  SEF  10/14/03  Fixed typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER
5971 +                       Added defines for bConnectionRate
5972 +   007  SEF  10/15/03  Added Firmware Download Control Code and support
5973 +                       Added CSMI revision support
5974 +   008  SEF  10/30/03  No functional change, just updated version to track
5975 +                       spec changes
5976 +   009  SEF  12/09/03  No functional change, just updated version to track
5977 +                       spec changes
5978 +   010  SEF   3/11/04  Fixed typedef struct CSMI_SAS_RAID_DRIVES to include the
5979 +                       bFirmware member that is defined in the spec, but
5980 +                       was missing in this file,
5981 +                       added CC_CSMI_SAS_TASK_MANAGEMENT
5982 +   011  SEF   4/02/04  No functional change, added comment line before
5983 +                       CC_CSMI_SAS_TASK_MANAGEMENT
5984 +   012  SEF   4/16/04  Added IOControllerNumber to linux header,
5985 +                       Modified linux control codes to have upper word of
5986 +                       0xCC77.... to indicate CSMI version 77
5987 +                       Added bSignalClass to CC_CSMI_SET_PHY_INFO
5988 +                       Added CC_CSMI_SAS_PHY_CONTROL support
5989 +   013  SEF   5/14/04  Added CC_CSMI_SAS_GET_CONNECTOR_INFO support
5990 +   014  SEF   5/24/04  No functional change, just updated version to track spec
5991 +                       changes
5992 +   015  SEF   6/16/04  changed bPinout to uPinout to reflect proper size,
5993 +                       changed width of bLocation defines to reflect size
5994 +   016  SEF   6/17/04  changed bLengthOfControls in CSMI_SAS_PHY_CONTROL
5995 +                       to be proper size
5996 +   017  SEF   9/17/04  added CSMI_SAS_SATA_PORT_SELECTOR,
5997 +                       CSMI_SAS_LINK_VIRTUAL, CSMI_SAS_CON_NOT_PRESENT, and
5998 +                       CSMI_SAS_CON_NOT_CONNECTED
5999 +   018  SEF   9/20/04  added CSMI_SAS_PHY_USER_PATTERN,
6000 +                       changed definition of CSMI_SAS_PHY_FIXED_PATTERN to not
6001 +                       conflict with activate definition
6002 +   019  SEF  12/06/04  added CSMI_SAS_GET_LOCATION
6003 +                       added bSSPStatus to CSMI_SAS_SSP_PASSTHRU_STATUS
6004 +                       structure
6005 +   020  SEF   5/25/05  added CSMI_SAS_PHY_VIRTUAL_SMP, and changes to
6006 +                       CSMI_SAS_GET_LOCATION
6007 +   021  SEF  11/03/05  added new RAID creation functionality
6008 +   022  SEF   2/01/06  corrected typo bNegotitiatedLInkRate
6009 +                       Added two more RAID_TYPES, 7 and 8
6010 +   023  SEF   4/04/06  added CSMI_RAID_TYPE_1E
6011 +                       changed structures that contained surface scan
6012 +                       to priority approach rather than time, causes
6013 +                       0.89 to incompatible with 0.87, so a version
6014 +                       check is necessary when interpreting the
6015 +                       raid structures
6016 +                       Added netware section
6017 +   024 DRG    5/22/06  Added uFailureCode to CSMI_SAS_RAID_CONFIG and
6018 +                       CSMI_SAS_RAID_FEATURES
6019 +                       Changed __u64 fields to high and low __u32 fields in
6020 +                       order to avoid backward compatibility issues with
6021 +                       packing and alignment.
6022 +                       Fixed alignment problem in CSMI_SAS_RAID_DRIVES.
6023 +                       Added CSMI_SAS_CNTLR_SMART_ARRAY to uControllerFlags
6024 +                       Reassigned the value of CSMI_SAS_CNTLR_RAID_CFG_SUPPORT
6025 +                       to avoid a conflict.
6026 +
6027 +**************************************************************************/
6028 +
6029 +#ifndef _CSMI_SAS_H_
6030 +#define _CSMI_SAS_H_
6031 +
6032 +// CSMI Specification Revision, the intent is that all versions of the
6033 +// specification will be backward compatible after the 1.00 release.
6034 +// Major revision number, corresponds to xxxx. of CSMI specification
6035 +// Minor revision number, corresponds to .xxxx of CSMI specification
6036 +#define CSMI_MAJOR_REVISION   0
6037 +#define CSMI_MINOR_REVISION   90
6038 +
6039 +/*************************************************************************/
6040 +/* PATCHES FOR TYPOS                                                     */
6041 +/*************************************************************************/
6042 +
6043 +#define bNegotitiatedLInkRate bNegotiatedLinkRate
6044 +
6045 +/*************************************************************************/
6046 +/* TARGET OS LINUX SPECIFIC CODE                                         */
6047 +/*************************************************************************/
6048 +
6049 +// EDM #ifdef _linux
6050 +#ifdef __KERNEL__
6051 +
6052 +// Linux base types
6053 +
6054 +#include <linux/types.h>
6055 +
6056 +#define __i8    char
6057 +
6058 +// pack definition
6059 +
6060 +// EDM #define CSMI_SAS_BEGIN_PACK(x)    pack(x)
6061 +// EDM #define CSMI_SAS_END_PACK         pack()
6062 +
6063 +// IOCTL Control Codes
6064 +// (IoctlHeader.ControlCode)
6065 +
6066 +// Control Codes prior to 0.77
6067 +
6068 +// Control Codes requiring CSMI_ALL_SIGNATURE
6069 +
6070 +// #define CC_CSMI_SAS_GET_DRIVER_INFO    0x12345678
6071 +// #define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x23456781
6072 +// #define CC_CSMI_SAS_GET_CNTLR_STATUS   0x34567812
6073 +// #define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x92345678
6074 +
6075 +// Control Codes requiring CSMI_RAID_SIGNATURE
6076 +
6077 +// #define CC_CSMI_SAS_GET_RAID_INFO      0x45678123
6078 +// #define CC_CSMI_SAS_GET_RAID_CONFIG    0x56781234
6079 +
6080 +// Control Codes requiring CSMI_SAS_SIGNATURE
6081 +
6082 +// #define CC_CSMI_SAS_GET_PHY_INFO       0x67812345
6083 +// #define CC_CSMI_SAS_SET_PHY_INFO       0x78123456
6084 +// #define CC_CSMI_SAS_GET_LINK_ERRORS    0x81234567
6085 +// #define CC_CSMI_SAS_SMP_PASSTHRU       0xA1234567
6086 +// #define CC_CSMI_SAS_SSP_PASSTHRU       0xB1234567
6087 +// #define CC_CSMI_SAS_STP_PASSTHRU       0xC1234567
6088 +// #define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xD1234567
6089 +// #define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xE1234567
6090 +// #define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xF1234567
6091 +// #define CC_CSMI_SAS_TASK_MANAGEMENT    0xA2345678
6092 +
6093 +// Control Codes for 0.77 and later
6094 +
6095 +// Control Codes requiring CSMI_ALL_SIGNATURE
6096 +
6097 +#define CC_CSMI_SAS_GET_DRIVER_INFO    0xCC770001
6098 +#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0xCC770002
6099 +#define CC_CSMI_SAS_GET_CNTLR_STATUS   0xCC770003
6100 +#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0xCC770004
6101 +
6102 +// Control Codes requiring CSMI_RAID_SIGNATURE
6103 +
6104 +#define CC_CSMI_SAS_GET_RAID_INFO      0xCC77000A
6105 +#define CC_CSMI_SAS_GET_RAID_CONFIG    0xCC77000B
6106 +#define CC_CSMI_SAS_GET_RAID_FEATURES  0xCC77000C
6107 +#define CC_CSMI_SAS_SET_RAID_CONTROL   0xCC77000D
6108 +#define CC_CSMI_SAS_GET_RAID_ELEMENT   0xCC77000E
6109 +#define CC_CSMI_SAS_SET_RAID_OPERATION 0xCC77000F
6110 +
6111 +// Control Codes requiring CSMI_SAS_SIGNATURE
6112 +
6113 +#define CC_CSMI_SAS_GET_PHY_INFO       0xCC770014
6114 +#define CC_CSMI_SAS_SET_PHY_INFO       0xCC770015
6115 +#define CC_CSMI_SAS_GET_LINK_ERRORS    0xCC770016
6116 +#define CC_CSMI_SAS_SMP_PASSTHRU       0xCC770017
6117 +#define CC_CSMI_SAS_SSP_PASSTHRU       0xCC770018
6118 +#define CC_CSMI_SAS_STP_PASSTHRU       0xCC770019
6119 +#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xCC770020
6120 +#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xCC770021
6121 +#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xCC770022
6122 +#define CC_CSMI_SAS_TASK_MANAGEMENT    0xCC770023
6123 +#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0xCC770024
6124 +#define CC_CSMI_SAS_GET_LOCATION       0xCC770025
6125 +
6126 +
6127 +// Control Codes requiring CSMI_PHY_SIGNATURE
6128 +
6129 +#define CC_CSMI_SAS_PHY_CONTROL        0xCC77003C
6130 +
6131 +// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
6132 +#pragma pack(8)
6133 +
6134 +// IOCTL_HEADER
6135 +typedef struct _IOCTL_HEADER {
6136 +    __u32 IOControllerNumber;
6137 +    __u32 Length;
6138 +    __u32 ReturnCode;
6139 +    __u32 Timeout;
6140 +    __u16 Direction;
6141 +} IOCTL_HEADER,
6142 +  *PIOCTL_HEADER;
6143 +
6144 +// EDM #pragma CSMI_SAS_END_PACK
6145 +#pragma pack()
6146 +
6147 +#endif
6148 +
6149 +/*************************************************************************/
6150 +/* TARGET OS WINDOWS SPECIFIC CODE                                       */
6151 +/*************************************************************************/
6152 +
6153 +#ifdef _WIN32
6154 +
6155 +// windows IOCTL definitions
6156 +
6157 +#ifndef _NTDDSCSIH_
6158 +#include <ntddscsi.h>
6159 +#endif
6160 +
6161 +// pack definition
6162 +
6163 +#if defined _MSC_VER
6164 +   #define CSMI_SAS_BEGIN_PACK(x)    pack(push,x)
6165 +   #define CSMI_SAS_END_PACK         pack(pop)
6166 +#elif defined __BORLANDC__
6167 +   #define CSMI_SAS_BEGIN_PACK(x)    option -a##x
6168 +   #define CSMI_SAS_END_PACK         option -a.
6169 +#else
6170 +   #error "CSMISAS.H - Must externally define a pack compiler designator."
6171 +#endif
6172 +
6173 +// base types
6174 +
6175 +#define __u8    unsigned char
6176 +#define __u16   unsigned short
6177 +#define __u32   unsigned long
6178 +#define __u64   unsigned __int64
6179 +
6180 +#define __i8    char
6181 +
6182 +// IOCTL Control Codes
6183 +// (IoctlHeader.ControlCode)
6184 +
6185 +// Control Codes requiring CSMI_ALL_SIGNATURE
6186 +
6187 +#define CC_CSMI_SAS_GET_DRIVER_INFO    1
6188 +#define CC_CSMI_SAS_GET_CNTLR_CONFIG   2
6189 +#define CC_CSMI_SAS_GET_CNTLR_STATUS   3
6190 +#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  4
6191 +
6192 +// Control Codes requiring CSMI_RAID_SIGNATURE
6193 +
6194 +#define CC_CSMI_SAS_GET_RAID_INFO      10
6195 +#define CC_CSMI_SAS_GET_RAID_CONFIG    11
6196 +#define CC_CSMI_SAS_GET_RAID_FEATURES  12
6197 +#define CC_CSMI_SAS_SET_RAID_CONTROL   13
6198 +#define CC_CSMI_SAS_GET_RAID_ELEMENT   14
6199 +#define CC_CSMI_SAS_SET_RAID_OPERATION 15
6200 +
6201 +// Control Codes requiring CSMI_SAS_SIGNATURE
6202 +
6203 +#define CC_CSMI_SAS_GET_PHY_INFO       20
6204 +#define CC_CSMI_SAS_SET_PHY_INFO       21
6205 +#define CC_CSMI_SAS_GET_LINK_ERRORS    22
6206 +#define CC_CSMI_SAS_SMP_PASSTHRU       23
6207 +#define CC_CSMI_SAS_SSP_PASSTHRU       24
6208 +#define CC_CSMI_SAS_STP_PASSTHRU       25
6209 +#define CC_CSMI_SAS_GET_SATA_SIGNATURE 26
6210 +#define CC_CSMI_SAS_GET_SCSI_ADDRESS   27
6211 +#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 28
6212 +#define CC_CSMI_SAS_TASK_MANAGEMENT    29
6213 +#define CC_CSMI_SAS_GET_CONNECTOR_INFO 30
6214 +#define CC_CSMI_SAS_GET_LOCATION       31
6215 +
6216 +// Control Codes requiring CSMI_PHY_SIGNATURE
6217 +
6218 +#define CC_CSMI_SAS_PHY_CONTROL        60
6219 +
6220 +#define IOCTL_HEADER SRB_IO_CONTROL
6221 +#define PIOCTL_HEADER PSRB_IO_CONTROL
6222 +
6223 +#endif
6224 +
6225 +/*************************************************************************/
6226 +/* TARGET OS NETWARE SPECIFIC CODE                                       */
6227 +/*************************************************************************/
6228 +
6229 +#ifdef _NETWARE
6230 +
6231 +// NetWare IOCTL definitions
6232 +
6233 +#define CSMI_SAS_BEGIN_PACK(x)    pack(x)
6234 +#define CSMI_SAS_END_PACK         pack()
6235 +
6236 +#ifndef LONG
6237 +typedef unsigned long LONG;
6238 +#endif
6239 +
6240 +#ifndef WORD
6241 +typedef unsigned short WORD;
6242 +#endif
6243 +
6244 +#ifndef BYTE
6245 +typedef unsigned char BYTE;
6246 +#endif
6247 +
6248 +/* Need to have these definitions for Netware */
6249 +#define __u8    unsigned char
6250 +#define __u16   unsigned short
6251 +#define __u32   unsigned long
6252 +#define __u64   unsigned __int64
6253 +
6254 +#define __i8    char
6255 +
6256 +
6257 +// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
6258 +#pragma pack(8)
6259 +
6260 +// IOCTL_HEADER
6261 +typedef struct _IOCTL_HEADER {
6262 +    __u32 Length;
6263 +    __u32 ReturnCode;
6264 +} IOCTL_HEADER,
6265 +  *PIOCTL_HEADER;
6266 +
6267 +// EDM #pragma CSMI_SAS_END_PACK
6268 +#pragma pack()
6269 +
6270 +// IOCTL Control Codes
6271 +// (IoctlHeader.ControlCode)
6272 +
6273 +// Control Codes requiring CSMI_ALL_SIGNATURE
6274 +
6275 +#define CC_CSMI_SAS_GET_DRIVER_INFO    0x01FF0001
6276 +#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x01FF0002
6277 +#define CC_CSMI_SAS_GET_CNTLR_STATUS   0x01FF0003
6278 +#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x01FF0004
6279 +
6280 +// Control Codes requiring CSMI_RAID_SIGNATURE
6281 +
6282 +#define CC_CSMI_SAS_GET_RAID_INFO      0x01FF000A
6283 +#define CC_CSMI_SAS_GET_RAID_CONFIG    0x01FF000B
6284 +#define CC_CSMI_SAS_GET_RAID_FEATURES  0x01FF000C
6285 +#define CC_CSMI_SAS_SET_RAID_CONTROL   0x01FF000D
6286 +#define CC_CSMI_SAS_GET_RAID_ELEMENT   0x01FF000E
6287 +#define CC_CSMI_SAS_SET_RAID_OPERATION 0x01FF000F
6288 +
6289 +// Control Codes requiring CSMI_SAS_SIGNATURE
6290 +
6291 +#define CC_CSMI_SAS_GET_PHY_INFO       0x01FF0014
6292 +#define CC_CSMI_SAS_SET_PHY_INFO       0x01FF0015
6293 +#define CC_CSMI_SAS_GET_LINK_ERRORS    0x01FF0016
6294 +#define CC_CSMI_SAS_SMP_PASSTHRU       0x01FF0017
6295 +#define CC_CSMI_SAS_SSP_PASSTHRU       0x01FF0018
6296 +#define CC_CSMI_SAS_STP_PASSTHRU       0x01FF0019
6297 +#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0x01FF001A
6298 +#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0x01FF001B
6299 +#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0x01FF001C
6300 +#define CC_CSMI_SAS_TASK_MANAGEMENT    0x01FF001D
6301 +#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0x01FF001E
6302 +#define CC_CSMI_SAS_GET_LOCATION       0x01FF001F
6303 +
6304 +// Control Codes requiring CSMI_PHY_SIGNATURE
6305 +
6306 +#define CC_CSMI_SAS_PHY_CONTROL        60
6307 +
6308 +#endif
6309 +
6310 +/*************************************************************************/
6311 +/* TARGET OS NOT DEFINED ERROR                                           */
6312 +/*************************************************************************/
6313 +
6314 +// EDM
6315 +//#if (!_WIN32 && !_linux && !_NETWARE)
6316 +//   #error "Unknown target OS."
6317 +//#endif
6318 +
6319 +/*************************************************************************/
6320 +/* OS INDEPENDENT CODE                                                   */
6321 +/*************************************************************************/
6322 +
6323 +/* * * * * * * * * * Class Independent IOCTL Constants * * * * * * * * * */
6324 +
6325 +// Return codes for all IOCTL's regardless of class
6326 +// (IoctlHeader.ReturnCode)
6327 +
6328 +#define CSMI_SAS_STATUS_SUCCESS              0
6329 +#define CSMI_SAS_STATUS_FAILED               1
6330 +#define CSMI_SAS_STATUS_BAD_CNTL_CODE        2
6331 +#define CSMI_SAS_STATUS_INVALID_PARAMETER    3
6332 +#define CSMI_SAS_STATUS_WRITE_ATTEMPTED      4
6333 +
6334 +// Signature value
6335 +// (IoctlHeader.Signature)
6336 +
6337 +#define CSMI_ALL_SIGNATURE    "CSMIALL"
6338 +
6339 +// Timeout value default of 60 seconds
6340 +// (IoctlHeader.Timeout)
6341 +
6342 +#define CSMI_ALL_TIMEOUT      60
6343 +
6344 +//  Direction values for data flow on this IOCTL
6345 +// (IoctlHeader.Direction, Linux only)
6346 +#define CSMI_SAS_DATA_READ    0
6347 +#define CSMI_SAS_DATA_WRITE   1
6348 +
6349 +// I/O Bus Types
6350 +// ISA and EISA bus types are not supported
6351 +// (bIoBusType)
6352 +
6353 +#define CSMI_SAS_BUS_TYPE_PCI       3
6354 +#define CSMI_SAS_BUS_TYPE_PCMCIA    4
6355 +
6356 +// Controller Status
6357 +// (uStatus)
6358 +
6359 +#define CSMI_SAS_CNTLR_STATUS_GOOD     1
6360 +#define CSMI_SAS_CNTLR_STATUS_FAILED   2
6361 +#define CSMI_SAS_CNTLR_STATUS_OFFLINE  3
6362 +#define CSMI_SAS_CNTLR_STATUS_POWEROFF 4
6363 +
6364 +// Offline Status Reason
6365 +// (uOfflineReason)
6366 +
6367 +#define CSMI_SAS_OFFLINE_REASON_NO_REASON             0
6368 +#define CSMI_SAS_OFFLINE_REASON_INITIALIZING          1
6369 +#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_DEGRADED 2
6370 +#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_FAILURE  3
6371 +
6372 +// Controller Class
6373 +// (bControllerClass)
6374 +
6375 +#define CSMI_SAS_CNTLR_CLASS_HBA    5
6376 +
6377 +// Controller Flag bits
6378 +// (uControllerFlags)
6379 +
6380 +#define CSMI_SAS_CNTLR_SAS_HBA          0x00000001
6381 +#define CSMI_SAS_CNTLR_SAS_RAID         0x00000002
6382 +#define CSMI_SAS_CNTLR_SATA_HBA         0x00000004
6383 +#define CSMI_SAS_CNTLR_SATA_RAID        0x00000008
6384 +#define CSMI_SAS_CNTLR_SMART_ARRAY      0x00000010
6385 +
6386 +// for firmware download
6387 +#define CSMI_SAS_CNTLR_FWD_SUPPORT      0x00010000
6388 +#define CSMI_SAS_CNTLR_FWD_ONLINE       0x00020000
6389 +#define CSMI_SAS_CNTLR_FWD_SRESET       0x00040000
6390 +#define CSMI_SAS_CNTLR_FWD_HRESET       0x00080000
6391 +#define CSMI_SAS_CNTLR_FWD_RROM         0x00100000
6392 +
6393 +// for RAID configuration supported
6394 +#define CSMI_SAS_CNTLR_RAID_CFG_SUPPORT 0x01000000
6395 +
6396 +// Download Flag bits
6397 +// (uDownloadFlags)
6398 +#define CSMI_SAS_FWD_VALIDATE       0x00000001
6399 +#define CSMI_SAS_FWD_SOFT_RESET     0x00000002
6400 +#define CSMI_SAS_FWD_HARD_RESET     0x00000004
6401 +
6402 +// Firmware Download Status
6403 +// (usStatus)
6404 +#define CSMI_SAS_FWD_SUCCESS        0
6405 +#define CSMI_SAS_FWD_FAILED         1
6406 +#define CSMI_SAS_FWD_USING_RROM     2
6407 +#define CSMI_SAS_FWD_REJECT         3
6408 +#define CSMI_SAS_FWD_DOWNREV        4
6409 +
6410 +// Firmware Download Severity
6411 +// (usSeverity>
6412 +#define CSMI_SAS_FWD_INFORMATION    0
6413 +#define CSMI_SAS_FWD_WARNING        1
6414 +#define CSMI_SAS_FWD_ERROR          2
6415 +#define CSMI_SAS_FWD_FATAL          3
6416 +
6417 +/* * * * * * * * * * SAS RAID Class IOCTL Constants  * * * * * * * * */
6418 +
6419 +// Return codes for the RAID IOCTL's regardless of class
6420 +// (IoctlHeader.ReturnCode)
6421 +
6422 +#define CSMI_SAS_RAID_SET_OUT_OF_RANGE       1000
6423 +#define CSMI_SAS_RAID_SET_BUFFER_TOO_SMALL   1001
6424 +#define CSMI_SAS_RAID_SET_DATA_CHANGED       1002
6425 +
6426 +// Signature value
6427 +// (IoctlHeader.Signature)
6428 +
6429 +#define CSMI_RAID_SIGNATURE    "CSMIARY"
6430 +
6431 +// Timeout value default of 60 seconds
6432 +// (IoctlHeader.Timeout)
6433 +
6434 +#define CSMI_RAID_TIMEOUT      60
6435 +
6436 +// RAID Types
6437 +// (bRaidType)
6438 +#define CSMI_SAS_RAID_TYPE_NONE     0
6439 +#define CSMI_SAS_RAID_TYPE_0        1
6440 +#define CSMI_SAS_RAID_TYPE_1        2
6441 +#define CSMI_SAS_RAID_TYPE_10       3
6442 +#define CSMI_SAS_RAID_TYPE_5        4
6443 +#define CSMI_SAS_RAID_TYPE_15       5
6444 +#define CSMI_SAS_RAID_TYPE_6        6
6445 +#define CSMI_SAS_RAID_TYPE_50       7
6446 +#define CSMI_SAS_RAID_TYPE_VOLUME   8
6447 +#define CSMI_SAS_RAID_TYPE_1E       9
6448 +#define CSMI_SAS_RAID_TYPE_OTHER    255
6449 +// the last value 255 was already defined for other
6450 +// so end is defined as 254
6451 +#define CSMI_SAS_RAID_TYPE_END      254
6452 +
6453 +// RAID Status
6454 +// (bStatus)
6455 +#define CSMI_SAS_RAID_SET_STATUS_OK             0
6456 +#define CSMI_SAS_RAID_SET_STATUS_DEGRADED       1
6457 +#define CSMI_SAS_RAID_SET_STATUS_REBUILDING     2
6458 +#define CSMI_SAS_RAID_SET_STATUS_FAILED         3
6459 +#define CSMI_SAS_RAID_SET_STATUS_OFFLINE        4
6460 +#define CSMI_SAS_RAID_SET_STATUS_TRANSFORMING   5
6461 +#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_REBUILD         6
6462 +#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_TRANSFORMATION  7
6463 +
6464 +// RAID Drive Count
6465 +// (bDriveCount, 0xF1 to 0xFF are reserved)
6466 +#define CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG   0xF1
6467 +#define CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED 0xF2
6468 +
6469 +// RAID Data Type
6470 +// (bDataType)
6471 +#define CSMI_SAS_RAID_DATA_DRIVES           0
6472 +#define CSMI_SAS_RAID_DATA_DEVICE_ID        1
6473 +#define CSMI_SAS_RAID_DATA_ADDITIONAL_DATA  2
6474 +
6475 +// RAID Drive Status
6476 +// (bDriveStatus)
6477 +#define CSMI_SAS_DRIVE_STATUS_OK          0
6478 +#define CSMI_SAS_DRIVE_STATUS_REBUILDING  1
6479 +#define CSMI_SAS_DRIVE_STATUS_FAILED      2
6480 +#define CSMI_SAS_DRIVE_STATUS_DEGRADED    3
6481 +#define CSMI_SAS_DRIVE_STATUS_OFFLINE     4
6482 +#define CSMI_SAS_DRIVE_STATUS_QUEUED_FOR_REBUILD 5
6483 +
6484 +// RAID Drive Usage
6485 +// (bDriveUsage)
6486 +#define CSMI_SAS_DRIVE_CONFIG_NOT_USED      0
6487 +#define CSMI_SAS_DRIVE_CONFIG_MEMBER        1
6488 +#define CSMI_SAS_DRIVE_CONFIG_SPARE         2
6489 +#define CSMI_SAS_DRIVE_CONFIG_SPARE_ACTIVE  3
6490 +
6491 +// RAID Drive Type
6492 +// (bDriveType)
6493 +#define CSMI_SAS_DRIVE_TYPE_UNKNOWN         0
6494 +#define CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS 1
6495 +#define CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS   2
6496 +#define CSMI_SAS_DRIVE_TYPE_SATA            3
6497 +#define CSMI_SAS_DRIVE_TYPE_SATA_PS         4
6498 +#define CSMI_SAS_DRIVE_TYPE_OTHER           255
6499 +
6500 +// RAID Write Protect
6501 +// (bWriteProtect)
6502 +#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN     0
6503 +#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNCHANGED   0
6504 +#define CSMI_SAS_RAID_SET_WRITE_PROTECT_ENABLED     1
6505 +#define CSMI_SAS_RAID_SET_WRITE_PROTECT_DISABLED    2
6506 +
6507 +// RAID Cache Setting
6508 +// (bCacheSetting)
6509 +#define CSMI_SAS_RAID_SET_CACHE_UNKNOWN             0
6510 +#define CSMI_SAS_RAID_SET_CACHE_UNCHANGED           0
6511 +#define CSMI_SAS_RAID_SET_CACHE_ENABLED             1
6512 +#define CSMI_SAS_RAID_SET_CACHE_DISABLED            2
6513 +#define CSMI_SAS_RAID_SET_CACHE_CORRUPT             3
6514 +
6515 +// RAID Features
6516 +// (uFeatures)
6517 +#define CSMI_SAS_RAID_FEATURE_TRANSFORMATION    0x00000001
6518 +#define CSMI_SAS_RAID_FEATURE_REBUILD           0x00000002
6519 +#define CSMI_SAS_RAID_FEATURE_SPLIT_MIRROR      0x00000004
6520 +#define CSMI_SAS_RAID_FEATURE_MERGE_MIRROR      0x00000008
6521 +#define CSMI_SAS_RAID_FEATURE_LUN_RENUMBER      0x00000010
6522 +#define CSMI_SAS_RAID_FEATURE_SURFACE_SCAN      0x00000020
6523 +#define CSMI_SAS_RAID_FEATURE_SPARES_SHARED     0x00000040
6524 +
6525 +// RAID Priority
6526 +// (bDefaultTransformPriority, etc.)
6527 +#define CSMI_SAS_PRIORITY_UNKNOWN   0
6528 +#define CSMI_SAS_PRIORITY_UNCHANGED 0
6529 +#define CSMI_SAS_PRIORITY_AUTO      1
6530 +#define CSMI_SAS_PRIORITY_OFF       2
6531 +#define CSMI_SAS_PRIORITY_LOW       3
6532 +#define CSMI_SAS_PRIORITY_MEDIUM    4
6533 +#define CSMI_SAS_PRIORITY_HIGH      5
6534 +
6535 +// RAID Transformation Rules
6536 +// (uRaidSetTransformationRules)
6537 +#define CSMI_SAS_RAID_RULE_AVAILABLE_MEMORY     0x00000001
6538 +#define CSMI_SAS_RAID_RULE_OVERLAPPED_EXTENTS   0x00000002
6539 +
6540 +// RAID Cache Ratios Supported
6541 +// (bCacheRatiosSupported)
6542 +// from 0 to 100 defines the write to read ratio, 0 is 100% write
6543 +#define CSMI_SAS_RAID_CACHE_RATIO_RANGE     101
6544 +#define CSMI_SAS_RAID_CACHE_RATIO_FIXED     102
6545 +#define CSMI_SAS_RAID_CACHE_RATIO_AUTO      103
6546 +#define CSMI_SAS_RAID_CACHE_RATIO_END       255
6547 +
6548 +// RAID Cache Ratio Flag
6549 +// (bCacheRatioFlag)
6550 +#define CSMI_SAS_RAID_CACHE_RATIO_DISABLE   0
6551 +#define CSMI_SAS_RAID_CACHE_RATIO_ENABLE    1
6552 +
6553 +// RAID Clear Configuration Signature
6554 +// (bClearConfiguration)
6555 +#define CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE "RAIDCLR"
6556 +
6557 +// RAID Failure Codes
6558 +// (uFailureCode)
6559 +#define CSMI_SAS_FAIL_CODE_OK                           0
6560 +#define CSMI_SAS_FAIL_CODE_PARAMETER_INVALID            1000
6561 +#define CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID   1001
6562 +#define CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID     1002
6563 +#define CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID          1003
6564 +#define CSMI_SAS_FAIL_CODE_SURFACE_SCAN_INVALID         1004
6565 +#define CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID  1005
6566 +#define CSMI_SAS_FAIL_CODE_ELEMENT_INDEX_INVALID        1006
6567 +#define CSMI_SAS_FAIL_CODE_SUBELEMENT_INDEX_INVALID     1007
6568 +#define CSMI_SAS_FAIL_CODE_EXTENT_INVALID               1008
6569 +#define CSMI_SAS_FAIL_CODE_BLOCK_COUNT_INVALID          1009
6570 +#define CSMI_SAS_FAIL_CODE_DRIVE_INDEX_INVALID          1010
6571 +#define CSMI_SAS_FAIL_CODE_EXISTING_LUN_INVALID         1011
6572 +#define CSMI_SAS_FAIL_CODE_RAID_TYPE_INVALID            1012
6573 +#define CSMI_SAS_FAIL_CODE_STRIPE_SIZE_INVALID          1013
6574 +#define CSMI_SAS_FAIL_CODE_TRANSFORMATION_INVALID       1014
6575 +#define CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID         1015
6576 +#define CSMI_SAS_FAIL_CODE_ENUMERATION_TYPE_INVALID     1016
6577 +
6578 +#define CSMI_SAS_FAIL_CODE_EXCEEDED_RAID_SET_COUNT      2000
6579 +#define CSMI_SAS_FAIL_CODE_DUPLICATE_LUN                2001
6580 +
6581 +#define CSMI_SAS_FAIL_CODE_WAIT_FOR_OPERATION           3000
6582 +
6583 +// RAID Enumeration Types
6584 +// (uEnumerationType)
6585 +#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE                0
6586 +#define CSMI_SAS_RAID_ELEMENT_TYPE_MODULE               1
6587 +#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE_RAID_SET       2
6588 +#define CSMI_SAS_RAID_ELEMENT_TYPE_EXTENT_DRIVE         3
6589 +
6590 +// RAID Extent Types
6591 +// (bExtentType)
6592 +#define CSMI_SAS_RAID_EXTENT_RESERVED       0
6593 +#define CSMI_SAS_RAID_EXTENT_METADATA       1
6594 +#define CSMI_SAS_RAID_EXTENT_ALLOCATED      2
6595 +#define CSMI_SAS_RAID_EXTENT_UNALLOCATED    3
6596 +
6597 +// RAID Operation Types
6598 +// (uOperationType)
6599 +#define CSMI_SAS_RAID_SET_CREATE            0
6600 +#define CSMI_SAS_RAID_SET_LABEL             1
6601 +#define CSMI_SAS_RAID_SET_TRANSFORM         2
6602 +#define CSMI_SAS_RAID_SET_DELETE            3
6603 +#define CSMI_SAS_RAID_SET_WRITE_PROTECT     4
6604 +#define CSMI_SAS_RAID_SET_CACHE             5
6605 +#define CSMI_SAS_RAID_SET_ONLINE_STATE      6
6606 +#define CSMI_SAS_RAID_SET_SPARE             7
6607 +
6608 +// RAID Transform Types
6609 +// (bTransformType)
6610 +#define CSMI_SAS_RAID_SET_TRANSFORM_SPLIT_MIRROR    0
6611 +#define CSMI_SAS_RAID_SET_TRANSFORM_MERGE_RAID_0    1
6612 +#define CSMI_SAS_RAID_SET_TRANSFORM_LUN_RENUMBER    2
6613 +#define CSMI_SAS_RAID_SET_TRANSFORM_RAID_SET        3
6614 +
6615 +// RAID Online State
6616 +// (bOnlineState)
6617 +#define CSMI_SAS_RAID_SET_STATE_UNKNOWN     0
6618 +#define CSMI_SAS_RAID_SET_STATE_ONLINE      1
6619 +#define CSMI_SAS_RAID_SET_STATE_OFFLINE     2
6620 +
6621 +/* * * * * * * * * * SAS HBA Class IOCTL Constants * * * * * * * * * */
6622 +
6623 +// Return codes for SAS IOCTL's
6624 +// (IoctlHeader.ReturnCode)
6625 +
6626 +#define CSMI_SAS_PHY_INFO_CHANGED            CSMI_SAS_STATUS_SUCCESS
6627 +#define CSMI_SAS_PHY_INFO_NOT_CHANGEABLE     2000
6628 +#define CSMI_SAS_LINK_RATE_OUT_OF_RANGE      2001
6629 +
6630 +#define CSMI_SAS_PHY_DOES_NOT_EXIST          2002
6631 +#define CSMI_SAS_PHY_DOES_NOT_MATCH_PORT     2003
6632 +#define CSMI_SAS_PHY_CANNOT_BE_SELECTED      2004
6633 +#define CSMI_SAS_SELECT_PHY_OR_PORT          2005
6634 +#define CSMI_SAS_PORT_DOES_NOT_EXIST         2006
6635 +#define CSMI_SAS_PORT_CANNOT_BE_SELECTED     2007
6636 +#define CSMI_SAS_CONNECTION_FAILED           2008
6637 +
6638 +#define CSMI_SAS_NO_SATA_DEVICE              2009
6639 +#define CSMI_SAS_NO_SATA_SIGNATURE           2010
6640 +#define CSMI_SAS_SCSI_EMULATION              2011
6641 +#define CSMI_SAS_NOT_AN_END_DEVICE           2012
6642 +#define CSMI_SAS_NO_SCSI_ADDRESS             2013
6643 +#define CSMI_SAS_NO_DEVICE_ADDRESS           2014
6644 +
6645 +// Signature value
6646 +// (IoctlHeader.Signature)
6647 +
6648 +#define CSMI_SAS_SIGNATURE    "CSMISAS"
6649 +
6650 +// Timeout value default of 60 seconds
6651 +// (IoctlHeader.Timeout)
6652 +
6653 +#define CSMI_SAS_TIMEOUT      60
6654 +
6655 +// Device types
6656 +// (bDeviceType)
6657 +
6658 +#define CSMI_SAS_PHY_UNUSED               0x00
6659 +#define CSMI_SAS_NO_DEVICE_ATTACHED       0x00
6660 +#define CSMI_SAS_END_DEVICE               0x10
6661 +#define CSMI_SAS_EDGE_EXPANDER_DEVICE     0x20
6662 +#define CSMI_SAS_FANOUT_EXPANDER_DEVICE   0x30
6663 +
6664 +// Protocol options
6665 +// (bInitiatorPortProtocol, bTargetPortProtocol)
6666 +
6667 +#define CSMI_SAS_PROTOCOL_SATA   0x01
6668 +#define CSMI_SAS_PROTOCOL_SMP    0x02
6669 +#define CSMI_SAS_PROTOCOL_STP    0x04
6670 +#define CSMI_SAS_PROTOCOL_SSP    0x08
6671 +
6672 +// Negotiated and hardware link rates
6673 +// (bNegotiatedLinkRate, bMinimumLinkRate, bMaximumLinkRate)
6674 +
6675 +#define CSMI_SAS_LINK_RATE_UNKNOWN  0x00
6676 +#define CSMI_SAS_PHY_DISABLED       0x01
6677 +#define CSMI_SAS_LINK_RATE_FAILED   0x02
6678 +#define CSMI_SAS_SATA_SPINUP_HOLD   0x03
6679 +#define CSMI_SAS_SATA_PORT_SELECTOR 0x04
6680 +#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08
6681 +#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09
6682 +#define CSMI_SAS_LINK_VIRTUAL       0x10
6683 +
6684 +// Discover state
6685 +// (bAutoDiscover)
6686 +
6687 +#define CSMI_SAS_DISCOVER_NOT_SUPPORTED   0x00
6688 +#define CSMI_SAS_DISCOVER_NOT_STARTED     0x01
6689 +#define CSMI_SAS_DISCOVER_IN_PROGRESS     0x02
6690 +#define CSMI_SAS_DISCOVER_COMPLETE        0x03
6691 +#define CSMI_SAS_DISCOVER_ERROR           0x04
6692 +
6693 +// Phy features
6694 +
6695 +#define CSMI_SAS_PHY_VIRTUAL_SMP          0x01
6696 +
6697 +// Programmed link rates
6698 +// (bMinimumLinkRate, bMaximumLinkRate)
6699 +// (bProgrammedMinimumLinkRate, bProgrammedMaximumLinkRate)
6700 +
6701 +#define CSMI_SAS_PROGRAMMED_LINK_RATE_UNCHANGED 0x00
6702 +#define CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS  0x08
6703 +#define CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS  0x09
6704 +
6705 +// Link rate
6706 +// (bNegotiatedLinkRate in CSMI_SAS_SET_PHY_INFO)
6707 +
6708 +#define CSMI_SAS_LINK_RATE_NEGOTIATE      0x00
6709 +#define CSMI_SAS_LINK_RATE_PHY_DISABLED   0x01
6710 +
6711 +// Signal class
6712 +// (bSignalClass in CSMI_SAS_SET_PHY_INFO)
6713 +
6714 +#define CSMI_SAS_SIGNAL_CLASS_UNKNOWN     0x00
6715 +#define CSMI_SAS_SIGNAL_CLASS_DIRECT      0x01
6716 +#define CSMI_SAS_SIGNAL_CLASS_SERVER      0x02
6717 +#define CSMI_SAS_SIGNAL_CLASS_ENCLOSURE   0x03
6718 +
6719 +// Link error reset
6720 +// (bResetCounts)
6721 +
6722 +#define CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS   0x00
6723 +#define CSMI_SAS_LINK_ERROR_RESET_COUNTS        0x01
6724 +
6725 +// Phy identifier
6726 +// (bPhyIdentifier)
6727 +
6728 +#define CSMI_SAS_USE_PORT_IDENTIFIER   0xFF
6729 +
6730 +// Port identifier
6731 +// (bPortIdentifier)
6732 +
6733 +#define CSMI_SAS_IGNORE_PORT           0xFF
6734 +
6735 +// Programmed link rates
6736 +// (bConnectionRate)
6737 +
6738 +#define CSMI_SAS_LINK_RATE_NEGOTIATED  0x00
6739 +#define CSMI_SAS_LINK_RATE_1_5_GBPS    0x08
6740 +#define CSMI_SAS_LINK_RATE_3_0_GBPS    0x09
6741 +
6742 +// Connection status
6743 +// (bConnectionStatus)
6744 +
6745 +#define CSMI_SAS_OPEN_ACCEPT                          0
6746 +#define CSMI_SAS_OPEN_REJECT_BAD_DESTINATION          1
6747 +#define CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED       2
6748 +#define CSMI_SAS_OPEN_REJECT_NO_DESTINATION           3
6749 +#define CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED          4
6750 +#define CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED   5
6751 +#define CSMI_SAS_OPEN_REJECT_RESERVE_ABANDON          6
6752 +#define CSMI_SAS_OPEN_REJECT_RESERVE_CONTINUE         7
6753 +#define CSMI_SAS_OPEN_REJECT_RESERVE_INITIALIZE       8
6754 +#define CSMI_SAS_OPEN_REJECT_RESERVE_STOP             9
6755 +#define CSMI_SAS_OPEN_REJECT_RETRY                    10
6756 +#define CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY       11
6757 +#define CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION        12
6758 +
6759 +// SSP Status
6760 +// (bSSPStatus)
6761 +
6762 +#define CSMI_SAS_SSP_STATUS_UNKNOWN     0x00
6763 +#define CSMI_SAS_SSP_STATUS_WAITING     0x01
6764 +#define CSMI_SAS_SSP_STATUS_COMPLETED   0x02
6765 +#define CSMI_SAS_SSP_STATUS_FATAL_ERROR 0x03
6766 +#define CSMI_SAS_SSP_STATUS_RETRY       0x04
6767 +#define CSMI_SAS_SSP_STATUS_NO_TAG      0x05
6768 +
6769 +// SSP Flags
6770 +// (uFlags)
6771 +
6772 +#define CSMI_SAS_SSP_READ           0x00000001
6773 +#define CSMI_SAS_SSP_WRITE          0x00000002
6774 +#define CSMI_SAS_SSP_UNSPECIFIED    0x00000004
6775 +
6776 +#define CSMI_SAS_SSP_TASK_ATTRIBUTE_SIMPLE         0x00000000
6777 +#define CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE  0x00000010
6778 +#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED        0x00000020
6779 +#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA            0x00000040
6780 +
6781 +// SSP Data present
6782 +// (bDataPresent)
6783 +
6784 +#define CSMI_SAS_SSP_NO_DATA_PRESENT         0x00
6785 +#define CSMI_SAS_SSP_RESPONSE_DATA_PRESENT   0x01
6786 +#define CSMI_SAS_SSP_SENSE_DATA_PRESENT      0x02
6787 +
6788 +// STP Flags
6789 +// (uFlags)
6790 +
6791 +#define CSMI_SAS_STP_READ           0x00000001
6792 +#define CSMI_SAS_STP_WRITE          0x00000002
6793 +#define CSMI_SAS_STP_UNSPECIFIED    0x00000004
6794 +#define CSMI_SAS_STP_PIO            0x00000010
6795 +#define CSMI_SAS_STP_DMA            0x00000020
6796 +#define CSMI_SAS_STP_PACKET         0x00000040
6797 +#define CSMI_SAS_STP_DMA_QUEUED     0x00000080
6798 +#define CSMI_SAS_STP_EXECUTE_DIAG   0x00000100
6799 +#define CSMI_SAS_STP_RESET_DEVICE   0x00000200
6800 +
6801 +// Task Management Flags
6802 +// (uFlags)
6803 +
6804 +#define CSMI_SAS_TASK_IU               0x00000001
6805 +#define CSMI_SAS_HARD_RESET_SEQUENCE   0x00000002
6806 +#define CSMI_SAS_SUPPRESS_RESULT       0x00000004
6807 +
6808 +// Task Management Functions
6809 +// (bTaskManagement)
6810 +
6811 +#define CSMI_SAS_SSP_ABORT_TASK           0x01
6812 +#define CSMI_SAS_SSP_ABORT_TASK_SET       0x02
6813 +#define CSMI_SAS_SSP_CLEAR_TASK_SET       0x04
6814 +#define CSMI_SAS_SSP_LOGICAL_UNIT_RESET   0x08
6815 +#define CSMI_SAS_SSP_CLEAR_ACA            0x40
6816 +#define CSMI_SAS_SSP_QUERY_TASK           0x80
6817 +
6818 +// Task Management Information
6819 +// (uInformation)
6820 +
6821 +#define CSMI_SAS_SSP_TEST           1
6822 +#define CSMI_SAS_SSP_EXCEEDED       2
6823 +#define CSMI_SAS_SSP_DEMAND         3
6824 +#define CSMI_SAS_SSP_TRIGGER        4
6825 +
6826 +// Connector Pinout Information
6827 +// (uPinout)
6828 +
6829 +#define CSMI_SAS_CON_UNKNOWN              0x00000001
6830 +#define CSMI_SAS_CON_SFF_8482             0x00000002
6831 +#define CSMI_SAS_CON_SFF_8470_LANE_1      0x00000100
6832 +#define CSMI_SAS_CON_SFF_8470_LANE_2      0x00000200
6833 +#define CSMI_SAS_CON_SFF_8470_LANE_3      0x00000400
6834 +#define CSMI_SAS_CON_SFF_8470_LANE_4      0x00000800
6835 +#define CSMI_SAS_CON_SFF_8484_LANE_1      0x00010000
6836 +#define CSMI_SAS_CON_SFF_8484_LANE_2      0x00020000
6837 +#define CSMI_SAS_CON_SFF_8484_LANE_3      0x00040000
6838 +#define CSMI_SAS_CON_SFF_8484_LANE_4      0x00080000
6839 +
6840 +// Connector Location Information
6841 +// (bLocation)
6842 +
6843 +// same as uPinout above...
6844 +// #define CSMI_SAS_CON_UNKNOWN              0x01
6845 +#define CSMI_SAS_CON_INTERNAL             0x02
6846 +#define CSMI_SAS_CON_EXTERNAL             0x04
6847 +#define CSMI_SAS_CON_SWITCHABLE           0x08
6848 +#define CSMI_SAS_CON_AUTO                 0x10
6849 +#define CSMI_SAS_CON_NOT_PRESENT          0x20
6850 +#define CSMI_SAS_CON_NOT_CONNECTED        0x80
6851 +
6852 +// Device location identification
6853 +// (bIdentify)
6854 +
6855 +#define CSMI_SAS_LOCATE_UNKNOWN           0x00
6856 +#define CSMI_SAS_LOCATE_FORCE_OFF         0x01
6857 +#define CSMI_SAS_LOCATE_FORCE_ON          0x02
6858 +
6859 +// Location Valid flags
6860 +// (uLocationFlags)
6861 +
6862 +#define CSMI_SAS_LOCATE_SAS_ADDRESS_VALID           0x00000001
6863 +#define CSMI_SAS_LOCATE_SAS_LUN_VALID               0x00000002
6864 +#define CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID  0x00000004
6865 +#define CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID        0x00000008
6866 +#define CSMI_SAS_LOCATE_BAY_PREFIX_VALID            0x00000010
6867 +#define CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID        0x00000020
6868 +#define CSMI_SAS_LOCATE_LOCATION_STATE_VALID        0x00000040
6869 +
6870 +/* * * * * * * * SAS Phy Control Class IOCTL Constants * * * * * * * * */
6871 +
6872 +// Return codes for SAS Phy Control IOCTL's
6873 +// (IoctlHeader.ReturnCode)
6874 +
6875 +// Signature value
6876 +// (IoctlHeader.Signature)
6877 +
6878 +#define CSMI_PHY_SIGNATURE    "CSMIPHY"
6879 +
6880 +// Phy Control Functions
6881 +// (bFunction)
6882 +
6883 +// values 0x00 to 0xFF are consistent in definition with the SMP PHY CONTROL
6884 +// function defined in the SAS spec
6885 +#define CSMI_SAS_PC_NOP                   0x00000000
6886 +#define CSMI_SAS_PC_LINK_RESET            0x00000001
6887 +#define CSMI_SAS_PC_HARD_RESET            0x00000002
6888 +#define CSMI_SAS_PC_PHY_DISABLE           0x00000003
6889 +// 0x04 to 0xFF reserved...
6890 +#define CSMI_SAS_PC_GET_PHY_SETTINGS      0x00000100
6891 +
6892 +// Link Flags
6893 +#define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
6894 +#define CSMI_SAS_PHY_UPDATE_SPINUP_RATE   0x00000002
6895 +#define CSMI_SAS_PHY_AUTO_COMWAKE         0x00000004
6896 +
6897 +// Device Types for Phy Settings
6898 +// (bType)
6899 +#define CSMI_SAS_UNDEFINED 0x00
6900 +#define CSMI_SAS_SATA      0x01
6901 +#define CSMI_SAS_SAS       0x02
6902 +
6903 +// Transmitter Flags
6904 +// (uTransmitterFlags)
6905 +#define CSMI_SAS_PHY_PREEMPHASIS_DISABLED    0x00000001
6906 +
6907 +// Receiver Flags
6908 +// (uReceiverFlags)
6909 +#define CSMI_SAS_PHY_EQUALIZATION_DISABLED   0x00000001
6910 +
6911 +// Pattern Flags
6912 +// (uPatternFlags)
6913 +// #define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
6914 +#define CSMI_SAS_PHY_DISABLE_SCRAMBLING      0x00000002
6915 +#define CSMI_SAS_PHY_DISABLE_ALIGN           0x00000004
6916 +#define CSMI_SAS_PHY_DISABLE_SSC             0x00000008
6917 +
6918 +#define CSMI_SAS_PHY_FIXED_PATTERN           0x00000010
6919 +#define CSMI_SAS_PHY_USER_PATTERN            0x00000020
6920 +
6921 +// Fixed Patterns
6922 +// (bFixedPattern)
6923 +#define CSMI_SAS_PHY_CJPAT                   0x00000001
6924 +#define CSMI_SAS_PHY_ALIGN                   0x00000002
6925 +
6926 +// Type Flags
6927 +// (bTypeFlags)
6928 +#define CSMI_SAS_PHY_POSITIVE_DISPARITY      0x01
6929 +#define CSMI_SAS_PHY_NEGATIVE_DISPARITY      0x02
6930 +#define CSMI_SAS_PHY_CONTROL_CHARACTER       0x04
6931 +
6932 +// Miscellaneous
6933 +#define SLOT_NUMBER_UNKNOWN   0xFFFF
6934 +
6935 +/*************************************************************************/
6936 +/* DATA STRUCTURES                                                       */
6937 +/*************************************************************************/
6938 +
6939 +/* * * * * * * * * * Class Independent Structures * * * * * * * * * */
6940 +
6941 +// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
6942 +#pragma pack(8)
6943 +
6944 +// CC_CSMI_SAS_DRIVER_INFO
6945 +
6946 +typedef struct _CSMI_SAS_DRIVER_INFO {
6947 +   __u8  szName[81];
6948 +   __u8  szDescription[81];
6949 +   __u16 usMajorRevision;
6950 +   __u16 usMinorRevision;
6951 +   __u16 usBuildRevision;
6952 +   __u16 usReleaseRevision;
6953 +   __u16 usCSMIMajorRevision;
6954 +   __u16 usCSMIMinorRevision;
6955 +} CSMI_SAS_DRIVER_INFO,
6956 +  *PCSMI_SAS_DRIVER_INFO;
6957 +
6958 +typedef struct _CSMI_SAS_DRIVER_INFO_BUFFER {
6959 +   IOCTL_HEADER IoctlHeader;
6960 +   CSMI_SAS_DRIVER_INFO Information;
6961 +} CSMI_SAS_DRIVER_INFO_BUFFER,
6962 +  *PCSMI_SAS_DRIVER_INFO_BUFFER;
6963 +
6964 +// CC_CSMI_SAS_CNTLR_CONFIGURATION
6965 +
6966 +typedef struct _CSMI_SAS_PCI_BUS_ADDRESS {
6967 +   __u8  bBusNumber;
6968 +   __u8  bDeviceNumber;
6969 +   __u8  bFunctionNumber;
6970 +   __u8  bReserved;
6971 +} CSMI_SAS_PCI_BUS_ADDRESS,
6972 +  *PCSMI_SAS_PCI_BUS_ADDRESS;
6973 +
6974 +typedef union _CSMI_SAS_IO_BUS_ADDRESS {
6975 +   CSMI_SAS_PCI_BUS_ADDRESS PciAddress;
6976 +   __u8  bReserved[32];
6977 +} CSMI_SAS_IO_BUS_ADDRESS,
6978 +  *PCSMI_SAS_IO_BUS_ADDRESS;
6979 +
6980 +typedef struct _CSMI_SAS_CNTLR_CONFIG {
6981 +   __u32 uBaseIoAddress;
6982 +   struct {
6983 +      __u32 uLowPart;
6984 +      __u32 uHighPart;
6985 +   } BaseMemoryAddress;
6986 +   __u32 uBoardID;
6987 +   __u16 usSlotNumber;
6988 +   __u8  bControllerClass;
6989 +   __u8  bIoBusType;
6990 +   CSMI_SAS_IO_BUS_ADDRESS BusAddress;
6991 +   __u8  szSerialNumber[81];
6992 +   __u16 usMajorRevision;
6993 +   __u16 usMinorRevision;
6994 +   __u16 usBuildRevision;
6995 +   __u16 usReleaseRevision;
6996 +   __u16 usBIOSMajorRevision;
6997 +   __u16 usBIOSMinorRevision;
6998 +   __u16 usBIOSBuildRevision;
6999 +   __u16 usBIOSReleaseRevision;
7000 +   __u32 uControllerFlags;
7001 +   __u16 usRromMajorRevision;
7002 +   __u16 usRromMinorRevision;
7003 +   __u16 usRromBuildRevision;
7004 +   __u16 usRromReleaseRevision;
7005 +   __u16 usRromBIOSMajorRevision;
7006 +   __u16 usRromBIOSMinorRevision;
7007 +   __u16 usRromBIOSBuildRevision;
7008 +   __u16 usRromBIOSReleaseRevision;
7009 +   __u8  bReserved[7];
7010 +} CSMI_SAS_CNTLR_CONFIG,
7011 +  *PCSMI_SAS_CNTLR_CONFIG;
7012 +
7013 +typedef struct _CSMI_SAS_CNTLR_CONFIG_BUFFER {
7014 +   IOCTL_HEADER IoctlHeader;
7015 +   CSMI_SAS_CNTLR_CONFIG Configuration;
7016 +} CSMI_SAS_CNTLR_CONFIG_BUFFER,
7017 +  *PCSMI_SAS_CNTLR_CONFIG_BUFFER;
7018 +
7019 +// CC_CSMI_SAS_CNTLR_STATUS
7020 +
7021 +typedef struct _CSMI_SAS_CNTLR_STATUS {
7022 +   __u32 uStatus;
7023 +   __u32 uOfflineReason;
7024 +   __u8  bReserved[28];
7025 +} CSMI_SAS_CNTLR_STATUS,
7026 +  *PCSMI_SAS_CNTLR_STATUS;
7027 +
7028 +typedef struct _CSMI_SAS_CNTLR_STATUS_BUFFER {
7029 +   IOCTL_HEADER IoctlHeader;
7030 +   CSMI_SAS_CNTLR_STATUS Status;
7031 +} CSMI_SAS_CNTLR_STATUS_BUFFER,
7032 +  *PCSMI_SAS_CNTLR_STATUS_BUFFER;
7033 +
7034 +// CC_CSMI_SAS_FIRMWARE_DOWNLOAD
7035 +
7036 +typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD {
7037 +   __u32 uBufferLength;
7038 +   __u32 uDownloadFlags;
7039 +   __u8  bReserved[32];
7040 +   __u16 usStatus;
7041 +   __u16 usSeverity;
7042 +} CSMI_SAS_FIRMWARE_DOWNLOAD,
7043 +  *PCSMI_SAS_FIRMWARE_DOWNLOAD;
7044 +
7045 +typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER {
7046 +   IOCTL_HEADER IoctlHeader;
7047 +   CSMI_SAS_FIRMWARE_DOWNLOAD Information;
7048 +   __u8  bDataBuffer[1];
7049 +} CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER,
7050 +  *PCSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER;
7051 +
7052 +// CC_CSMI_SAS_RAID_INFO
7053 +
7054 +typedef struct _CSMI_SAS_RAID_INFO {
7055 +   __u32 uNumRaidSets;
7056 +   __u32 uMaxDrivesPerSet;
7057 +   __u32 uMaxRaidSets;
7058 +   __u8  bMaxRaidTypes;
7059 +   __u8  bReservedByteFields[7];
7060 +   struct
7061 +   {
7062 +      __u32 uLowPart;
7063 +      __u32 uHighPart;
7064 +   } ulMinRaidSetBlocks;
7065 +   struct
7066 +   {
7067 +      __u32 uLowPart;
7068 +      __u32 uHighPart;
7069 +   } ulMaxRaidSetBlocks;
7070 +   __u32 uMaxPhysicalDrives;
7071 +   __u32 uMaxExtents;
7072 +   __u32 uMaxModules;
7073 +   __u32 uMaxTransformationMemory;
7074 +   __u32 uChangeCount;
7075 +   __u8  bReserved[44];
7076 +} CSMI_SAS_RAID_INFO,
7077 +  *PCSMI_SAS_RAID_INFO;
7078 +
7079 +typedef struct _CSMI_SAS_RAID_INFO_BUFFER {
7080 +   IOCTL_HEADER IoctlHeader;
7081 +   CSMI_SAS_RAID_INFO Information;
7082 +} CSMI_SAS_RAID_INFO_BUFFER,
7083 +  *PCSMI_SAS_RAID_INFO_BUFFER;
7084 +
7085 +// CC_CSMI_SAS_GET_RAID_CONFIG
7086 +
7087 +typedef struct _CSMI_SAS_RAID_DRIVES {
7088 +   __u8  bModel[40];
7089 +   __u8  bFirmware[8];
7090 +   __u8  bSerialNumber[40];
7091 +   __u8  bSASAddress[8];
7092 +   __u8  bSASLun[8];
7093 +   __u8  bDriveStatus;
7094 +   __u8  bDriveUsage;
7095 +   __u16 usBlockSize;
7096 +   __u8  bDriveType;
7097 +   __u8  bReserved[15];
7098 +   __u32 uDriveIndex;
7099 +   struct
7100 +   {
7101 +      __u32 uLowPart;
7102 +      __u32 uHighPart;
7103 +   } ulTotalUserBlocks;
7104 +} CSMI_SAS_RAID_DRIVES,
7105 +  *PCSMI_SAS_RAID_DRIVES;
7106 +
7107 +typedef struct _CSMI_SAS_RAID_DEVICE_ID {
7108 +   __u8  bDeviceIdentificationVPDPage[1];
7109 +} CSMI_SAS_RAID_DEVICE_ID,
7110 +  *PCSMI_SAS_RAID_DEVICE_ID;
7111 +
7112 +typedef struct _CSMI_SAS_RAID_SET_ADDITIONAL_DATA {
7113 +   __u8  bLabel[16];
7114 +   __u8  bRaidSetLun[8];
7115 +   __u8  bWriteProtection;
7116 +   __u8  bCacheSetting;
7117 +   __u8  bCacheRatio;
7118 +   __u16 usBlockSize;
7119 +   __u8  bReservedBytes[11];
7120 +   struct
7121 +   {
7122 +      __u32 uLowPart;
7123 +      __u32 uHighPart;
7124 +   } ulRaidSetExtentOffset;
7125 +   struct
7126 +   {
7127 +      __u32 uLowPart;
7128 +      __u32 uHighPart;
7129 +   } ulRaidSetBlocks;
7130 +   __u32 uStripeSizeInBlocks;
7131 +   __u32 uSectorsPerTrack;
7132 +   __u8  bApplicationScratchPad[16];
7133 +   __u32 uNumberOfHeads;
7134 +   __u32 uNumberOfTracks;
7135 +   __u8  bReserved[24];
7136 +} CSMI_SAS_RAID_SET_ADDITIONAL_DATA,
7137 +  *PCSMI_SAS_RAID_SET_ADDITIONAL_DATA;
7138 +
7139 +typedef struct _CSMI_SAS_RAID_CONFIG {
7140 +   __u32 uRaidSetIndex;
7141 +   __u32 uCapacity;
7142 +   __u32 uStripeSize;
7143 +   __u8  bRaidType;
7144 +   __u8  bStatus;
7145 +   __u8  bInformation;
7146 +   __u8  bDriveCount;
7147 +   __u8  bDataType;
7148 +   __u8  bReserved[11];
7149 +   __u32 uFailureCode;
7150 +   __u32 uChangeCount;
7151 +   union {
7152 +      CSMI_SAS_RAID_DRIVES Drives[1];
7153 +      CSMI_SAS_RAID_DEVICE_ID DeviceId[1];
7154 +      CSMI_SAS_RAID_SET_ADDITIONAL_DATA Data[1];
7155 +   };
7156 +} CSMI_SAS_RAID_CONFIG,
7157 +   *PCSMI_SAS_RAID_CONFIG;
7158 +
7159 +typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER {
7160 +   IOCTL_HEADER IoctlHeader;
7161 +   CSMI_SAS_RAID_CONFIG Configuration;
7162 +} CSMI_SAS_RAID_CONFIG_BUFFER,
7163 +  *PCSMI_SAS_RAID_CONFIG_BUFFER;
7164 +
7165 +// CC_CSMI_SAS_GET_RAID_FEATURES
7166 +
7167 +typedef struct _CSMI_SAS_RAID_TYPE_DESCRIPTION {
7168 +  __u8  bRaidType;
7169 +  __u8  bReservedBytes[7];
7170 +  __u32 uSupportedStripeSizeMap;
7171 +  __u8  bReserved[24];
7172 +} CSMI_SAS_RAID_TYPE_DESCRIPTION,
7173 +  *PCSMI_SAS_RAID_TYPE_DESCRIPTION;
7174 +
7175 +typedef struct _CSMI_SAS_RAID_FEATURES {
7176 +   __u32 uFeatures;
7177 +   __u8  bReservedFeatures[32];
7178 +   __u8  bDefaultTransformPriority;
7179 +   __u8  bTransformPriority;
7180 +   __u8  bDefaultRebuildPriority;
7181 +   __u8  bRebuildPriority;
7182 +   __u8  bDefaultSurfaceScanPriority;
7183 +   __u8  bSurfaceScanPriority;
7184 +   __u16 usReserved;
7185 +   __u32 uRaidSetTransformationRules;
7186 +   __u32 uReserved[11];
7187 +   CSMI_SAS_RAID_TYPE_DESCRIPTION RaidType[24];
7188 +   __u8  bCacheRatiosSupported[104];
7189 +   __u32 uChangeCount;
7190 +   __u32 uFailureCode;
7191 +   __u8  bReserved[120];
7192 +} CSMI_SAS_RAID_FEATURES,
7193 +  *PCSMI_SAS_RAID_FEATURES;
7194 +
7195 +typedef struct _CSMI_SAS_RAID_FEATURES_BUFFER {
7196 +   IOCTL_HEADER IoctlHeader;
7197 +   CSMI_SAS_RAID_FEATURES Information;
7198 +} CSMI_SAS_RAID_FEATURES_BUFFER,
7199 +  *PCSMI_SAS_RAID_FEATURES_BUFFER;
7200 +
7201 +// CC_CSMI_SAS_SET_RAID_CONTROL
7202 +
7203 +typedef struct _CSMI_SAS_RAID_CONTROL {
7204 +   __u8  bTransformPriority;
7205 +   __u8  bRebuildPriority;
7206 +   __u8  bCacheRatioFlag;
7207 +   __u8  bCacheRatio;
7208 +   __u8  bSurfaceScanPriority;
7209 +   __u8  bReservedBytes[15];
7210 +   __u8  bClearConfiguration[8];
7211 +   __u32 uChangeCount;
7212 +   __u8  bReserved[88];
7213 +   __u32 uFailureCode;
7214 +   __u8  bFailureDescription[80];
7215 +} CSMI_SAS_RAID_CONTROL,
7216 +  *PCSMI_SAS_RAID_CONTROL;
7217 +
7218 +typedef struct _CSMI_SAS_RAID_CONTROL_BUFFER {
7219 +   IOCTL_HEADER IoctlHeader;
7220 +   CSMI_SAS_RAID_CONTROL Information;
7221 +} CSMI_SAS_RAID_CONTROL_BUFFER,
7222 +  *PCSMI_SAS_RAID_CONTROL_BUFFER;
7223 +
7224 +// CC_CSMI_SAS_GET_RAID_ELEMENT
7225 +
7226 +typedef struct _CSMI_SAS_DRIVE_EXTENT_INFO {
7227 +   __u32 uDriveIndex;
7228 +   __u8  bExtentType;
7229 +   __u8  bReservedBytes[7];
7230 +   struct
7231 +   {
7232 +      __u32 uLowPart;
7233 +      __u32 uHighPart;
7234 +   } ulExtentOffset;
7235 +   struct
7236 +   {
7237 +      __u32 uLowPart;
7238 +      __u32 uHighPart;
7239 +   } ulExtentBlocks;
7240 +   __u32 uRaidSetIndex;
7241 +   __u8  bReserved[96];
7242 +} CSMI_SAS_DRIVE_EXTENT_INFO,
7243 +  *PCSMI_SAS_DRIVE_EXTENT_INFO;
7244 +
7245 +typedef struct _CSMI_SAS_RAID_MODULE_INFO {
7246 +   __u8  bReserved[128];
7247 +} CSMI_SAS_RAID_MODULE_INFO,
7248 +  *PCSMI_SAS_RAID_MODULE_INFO;
7249 +
7250 +typedef struct _CSMI_SAS_DRIVE_LOCATION {
7251 +   __u8  bConnector[16];
7252 +   __u8  bBoxName[16];
7253 +   __u32 uBay;
7254 +   __u8  bReservedBytes[4];
7255 +   __u8  bAttachedSASAddress[8];
7256 +   __u8  bAttachedPhyIdentifier;
7257 +   __u8  bReserved[79];
7258 +} CSMI_SAS_DRIVE_LOCATION,
7259 +  *PCSMI_SAS_DRIVE_LOCATION;
7260 +
7261 +typedef struct _CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA {
7262 +   __u8  bNegotiatedLinkRate[2];
7263 +   __u8  bReserved[126];
7264 +} CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA,
7265 +  *PCSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA;
7266 +
7267 +typedef struct _CSMI_SAS_DRIVE_INFO {
7268 +   CSMI_SAS_RAID_DRIVES Device;
7269 +   CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA Data;
7270 +   CSMI_SAS_DRIVE_LOCATION Location;
7271 +   __u8  bReserved[16];
7272 +} CSMI_SAS_DRIVE_INFO,
7273 +  *PCSMI_SAS_DRIVE_INFO;
7274 +
7275 +typedef struct _CSMI_SAS_RAID_ELEMENT {
7276 +   __u32 uEnumerationType;
7277 +   __u32 uElementIndex;
7278 +   __u32 uNumElements;
7279 +   __u32 uChangeCount;
7280 +   __u32 uSubElementIndex;
7281 +   __u8  bReserved[32];
7282 +   __u32 uFailureCode;
7283 +   __u8  bFailureDescription[80];
7284 +   union {
7285 +       CSMI_SAS_DRIVE_INFO Drive;
7286 +       CSMI_SAS_RAID_MODULE_INFO Module;
7287 +       CSMI_SAS_DRIVE_EXTENT_INFO Extent;
7288 +   } Element;
7289 +} CSMI_SAS_RAID_ELEMENT,
7290 +  *PCSMI_SAS_RAID_ELEMENT;
7291 +
7292 +typedef struct _CSMI_SAS_RAID_ELEMENT_BUFFER {
7293 +   IOCTL_HEADER IoctlHeader;
7294 +   CSMI_SAS_RAID_ELEMENT Information;
7295 +} CSMI_SAS_RAID_ELEMENT_BUFFER,
7296 +  *PCSMI_SAS_RAID_ELEMENT_BUFFER;
7297 +
7298 +// CC_CSMI_SAS_SET_RAID_OPERATION
7299 +
7300 +typedef struct _CSMI_SAS_RAID_SET_LIST {
7301 +   __u32 uRaidSetIndex;
7302 +   __u8  bExistingLun[8];
7303 +   __u8  bNewLun[8];
7304 +   __u8  bReserved[12];
7305 +} CSMI_SAS_RAID_SET_LIST,
7306 +  *PCSMI_SAS_RAID_SET_LIST;
7307 +
7308 +typedef struct _CSMI_SAS_RAID_SET_DRIVE_LIST {
7309 +   __u32 uDriveIndex;
7310 +   __u8  bDriveUsage;
7311 +   __u8  bReserved[27];
7312 +} CSMI_SAS_RAID_SET_DRIVE_LIST,
7313 +  *PCSMI_SAS_RAID_SET_DRIVE_LIST;
7314 +
7315 +typedef struct _CSMI_SAS_RAID_SET_SPARE_INFO {
7316 +   __u32 uRaidSetIndex;
7317 +   __u32 uDriveCount;
7318 +   __u8  bApplicationScratchPad[16];
7319 +   __u8  bReserved[104];
7320 +} CSMI_SAS_RAID_SET_SPARE_INFO,
7321 +  *PCSMI_SAS_RAID_SET_SPARE_INFO;
7322 +
7323 +typedef struct _CSMI_SAS_RAID_SET_ONLINE_STATE_INFO {
7324 +   __u32 uRaidSetIndex;
7325 +   __u8  bOnlineState;
7326 +   __u8  bReserved[123];
7327 +} CSMI_SAS_RAID_SET_ONLINE_STATE_INFO,
7328 +  *PCSMI_SAS_RAID_SET_ONLINE_STATE_INFO;
7329 +
7330 +typedef struct _CSMI_SAS_RAID_SET_CACHE_INFO {
7331 +   __u32 uRaidSetIndex;
7332 +   __u8  bCacheSetting;
7333 +   __u8  bCacheRatioFlag;
7334 +   __u8  bCacheRatio;
7335 +   __u8  bReserved[121];
7336 +} CSMI_SAS_RAID_SET_CACHE_INFO,
7337 +  *PCSMI_SAS_RAID_SET_CACHE_INFO;
7338 +
7339 +typedef struct _CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO {
7340 +   __u32 uRaidSetIndex;
7341 +   __u8  bWriteProtectSetting;
7342 +   __u8  bReserved[123];
7343 +} CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO,
7344 +  *PCSMI_SAS_RAID_SET_WRITE_PROTECT_INFO;
7345 +
7346 +typedef struct _CSMI_SAS_RAID_SET_DELETE_INFO {
7347 +   __u32 uRaidSetIndex;
7348 +   __u8  bReserved[124];
7349 +} CSMI_SAS_RAID_SET_DELETE_INFO,
7350 +  *PCSMI_SAS_RAID_SET_DELETE_INFO;
7351 +
7352 +typedef struct _CSMI_SAS_RAID_SET_MODIFY_INFO {
7353 +   __u8  bRaidType;
7354 +   __u8  bReservedBytes[7];
7355 +   __u32 uStripeSize;
7356 +   struct
7357 +   {
7358 +      __u32 uLowPart;
7359 +      __u32 uHighPart;
7360 +   } ulRaidSetBlocks;
7361 +   struct
7362 +   {
7363 +      __u32 uLowPart;
7364 +      __u32 uHighPart;
7365 +   } ulRaidSetExtentOffset;
7366 +   __u32 uDriveCount;
7367 +   __u8  bReserved[96];
7368 +} CSMI_SAS_RAID_SET_MODIFY_INFO,
7369 +  *PCSMI_SAS_RAID_SET_MODIFY_INFO;
7370 +
7371 +typedef struct _CSMI_SAS_RAID_SET_TRANSFORM_INFO {
7372 +   __u8  bTransformType;
7373 +   __u8  bReservedBytes[3];
7374 +   __u32 uRaidSetIndex;
7375 +   __u8  bRaidType;
7376 +   __u8  bReservedBytes2[11];
7377 +   __u32 uAdditionalRaidSetIndex;
7378 +   __u32 uRaidSetCount;
7379 +   __u8  bApplicationScratchPad[16];
7380 +   CSMI_SAS_RAID_SET_MODIFY_INFO Modify;
7381 +   __u8  bReserved[80];
7382 +} CSMI_SAS_RAID_SET_TRANSFORM_INFO,
7383 +  *PCSMI_SAS_RAID_SET_TRANSFORM_INFO;
7384 +
7385 +typedef struct _CSMI_SAS_RAID_SET_LABEL_INFO {
7386 +   __u32 uRaidSetIndex;
7387 +   __u8  bLabel[16];
7388 +   __u8  bReserved[108];
7389 +} CSMI_SAS_RAID_SET_LABEL_INFO,
7390 +  *PCSMI_SAS_RAID_SET_LABEL_INFO;
7391 +
7392 +typedef struct _CSMI_SAS_RAID_SET_CREATE_INFO {
7393 +   __u8  bRaidType;
7394 +   __u8  bReservedBytes[7];
7395 +   __u32 uStripeSize;
7396 +   __u32 uTrackSectorCount;
7397 +   struct
7398 +   {
7399 +      __u32 uLowPart;
7400 +      __u32 uHighPart;
7401 +   } ulRaidSetBlocks;
7402 +   struct
7403 +   {
7404 +      __u32 uLowPart;
7405 +      __u32 uHighPart;
7406 +   } ulRaidSetExtentOffset;
7407 +   __u32 uDriveCount;
7408 +   __u8  bLabel[16];
7409 +   __u32 uRaidSetIndex;
7410 +   __u8  bApplicationScratchPad[16];
7411 +   __u32 uNumberOfHeads;
7412 +   __u32 uNumberOfTracks;
7413 +   __u8  bReserved[48];
7414 +} CSMI_SAS_RAID_SET_CREATE_INFO,
7415 +  *PCSMI_SAS_RAID_SET_CREATE_INFO;
7416 +
7417 +typedef struct _CSMI_SAS_RAID_SET_OPERATION {
7418 +   __u32 uOperationType;
7419 +   __u32 uChangeCount;
7420 +   __u32 uFailureCode;
7421 +   __u8  bFailureDescription[80];
7422 +   __u8  bReserved[28];
7423 +   union {
7424 +       CSMI_SAS_RAID_SET_CREATE_INFO Create;
7425 +       CSMI_SAS_RAID_SET_LABEL_INFO Label;
7426 +       CSMI_SAS_RAID_SET_TRANSFORM_INFO Transform;
7427 +       CSMI_SAS_RAID_SET_DELETE_INFO Delete;
7428 +       CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO Protect;
7429 +       CSMI_SAS_RAID_SET_CACHE_INFO Cache;
7430 +       CSMI_SAS_RAID_SET_ONLINE_STATE_INFO State;
7431 +       CSMI_SAS_RAID_SET_SPARE_INFO Spare;
7432 +   } Operation;
7433 +   union {
7434 +       CSMI_SAS_RAID_SET_DRIVE_LIST DriveList[1];
7435 +       CSMI_SAS_RAID_SET_LIST RaidSetList[1];
7436 +   } Parameters;
7437 +} CSMI_SAS_RAID_SET_OPERATION,
7438 +  *PCSMI_SAS_RAID_SET_OPERATION;
7439 +
7440 +typedef struct _CSMI_SAS_RAID_SET_OPERATION_BUFFER {
7441 +   IOCTL_HEADER IoctlHeader;
7442 +   CSMI_SAS_RAID_SET_OPERATION Information;
7443 +} CSMI_SAS_RAID_SET_OPERATION_BUFFER,
7444 +  *PCSMI_SAS_RAID_SET_OPERATION_BUFFER;
7445 +
7446 +/* * * * * * * * * * SAS HBA Class Structures * * * * * * * * * */
7447 +
7448 +// CC_CSMI_SAS_GET_PHY_INFO
7449 +
7450 +typedef struct _CSMI_SAS_IDENTIFY {
7451 +   __u8  bDeviceType;
7452 +   __u8  bRestricted;
7453 +   __u8  bInitiatorPortProtocol;
7454 +   __u8  bTargetPortProtocol;
7455 +   __u8  bRestricted2[8];
7456 +   __u8  bSASAddress[8];
7457 +   __u8  bPhyIdentifier;
7458 +   __u8  bSignalClass;
7459 +   __u8  bReserved[6];
7460 +} CSMI_SAS_IDENTIFY,
7461 +  *PCSMI_SAS_IDENTIFY;
7462 +
7463 +typedef struct _CSMI_SAS_PHY_ENTITY {
7464 +   CSMI_SAS_IDENTIFY Identify;
7465 +   __u8  bPortIdentifier;
7466 +   __u8  bNegotiatedLinkRate;
7467 +   __u8  bMinimumLinkRate;
7468 +   __u8  bMaximumLinkRate;
7469 +   __u8  bPhyChangeCount;
7470 +   __u8  bAutoDiscover;
7471 +   __u8  bPhyFeatures;
7472 +   __u8  bReserved;
7473 +   CSMI_SAS_IDENTIFY Attached;
7474 +} CSMI_SAS_PHY_ENTITY,
7475 +  *PCSMI_SAS_PHY_ENTITY;
7476 +
7477 +typedef struct _CSMI_SAS_PHY_INFO {
7478 +   __u8  bNumberOfPhys;
7479 +   __u8  bReserved[3];
7480 +   CSMI_SAS_PHY_ENTITY Phy[32];
7481 +} CSMI_SAS_PHY_INFO,
7482 +  *PCSMI_SAS_PHY_INFO;
7483 +
7484 +typedef struct _CSMI_SAS_PHY_INFO_BUFFER {
7485 +   IOCTL_HEADER IoctlHeader;
7486 +   CSMI_SAS_PHY_INFO Information;
7487 +} CSMI_SAS_PHY_INFO_BUFFER,
7488 +  *PCSMI_SAS_PHY_INFO_BUFFER;
7489 +
7490 +// CC_CSMI_SAS_SET_PHY_INFO
7491 +
7492 +typedef struct _CSMI_SAS_SET_PHY_INFO {
7493 +   __u8  bPhyIdentifier;
7494 +   __u8  bNegotiatedLinkRate;
7495 +   __u8  bProgrammedMinimumLinkRate;
7496 +   __u8  bProgrammedMaximumLinkRate;
7497 +   __u8  bSignalClass;
7498 +   __u8  bReserved[3];
7499 +} CSMI_SAS_SET_PHY_INFO,
7500 +  *PCSMI_SAS_SET_PHY_INFO;
7501 +
7502 +typedef struct _CSMI_SAS_SET_PHY_INFO_BUFFER {
7503 +   IOCTL_HEADER IoctlHeader;
7504 +   CSMI_SAS_SET_PHY_INFO Information;
7505 +} CSMI_SAS_SET_PHY_INFO_BUFFER,
7506 +  *PCSMI_SAS_SET_PHY_INFO_BUFFER;
7507 +
7508 +// CC_CSMI_SAS_GET_LINK_ERRORS
7509 +
7510 +typedef struct _CSMI_SAS_LINK_ERRORS {
7511 +   __u8  bPhyIdentifier;
7512 +   __u8  bResetCounts;
7513 +   __u8  bReserved[2];
7514 +   __u32 uInvalidDwordCount;
7515 +   __u32 uRunningDisparityErrorCount;
7516 +   __u32 uLossOfDwordSyncCount;
7517 +   __u32 uPhyResetProblemCount;
7518 +} CSMI_SAS_LINK_ERRORS,
7519 +  *PCSMI_SAS_LINK_ERRORS;
7520 +
7521 +typedef struct _CSMI_SAS_LINK_ERRORS_BUFFER {
7522 +   IOCTL_HEADER IoctlHeader;
7523 +   CSMI_SAS_LINK_ERRORS Information;
7524 +} CSMI_SAS_LINK_ERRORS_BUFFER,
7525 +  *PCSMI_SAS_LINK_ERRORS_BUFFER;
7526 +
7527 +// CC_CSMI_SAS_SMP_PASSTHRU
7528 +
7529 +typedef struct _CSMI_SAS_SMP_REQUEST {
7530 +   __u8  bFrameType;
7531 +   __u8  bFunction;
7532 +   __u8  bReserved[2];
7533 +   __u8  bAdditionalRequestBytes[1016];
7534 +} CSMI_SAS_SMP_REQUEST,
7535 +  *PCSMI_SAS_SMP_REQUEST;
7536 +
7537 +typedef struct _CSMI_SAS_SMP_RESPONSE {
7538 +   __u8  bFrameType;
7539 +   __u8  bFunction;
7540 +   __u8  bFunctionResult;
7541 +   __u8  bReserved;
7542 +   __u8  bAdditionalResponseBytes[1016];
7543 +} CSMI_SAS_SMP_RESPONSE,
7544 +  *PCSMI_SAS_SMP_RESPONSE;
7545 +
7546 +typedef struct _CSMI_SAS_SMP_PASSTHRU {
7547 +   __u8  bPhyIdentifier;
7548 +   __u8  bPortIdentifier;
7549 +   __u8  bConnectionRate;
7550 +   __u8  bReserved;
7551 +   __u8  bDestinationSASAddress[8];
7552 +   __u32 uRequestLength;
7553 +   CSMI_SAS_SMP_REQUEST Request;
7554 +   __u8  bConnectionStatus;
7555 +   __u8  bReserved2[3];
7556 +   __u32 uResponseBytes;
7557 +   CSMI_SAS_SMP_RESPONSE Response;
7558 +} CSMI_SAS_SMP_PASSTHRU,
7559 +  *PCSMI_SAS_SMP_PASSTHRU;
7560 +
7561 +typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER {
7562 +   IOCTL_HEADER IoctlHeader;
7563 +   CSMI_SAS_SMP_PASSTHRU Parameters;
7564 +} CSMI_SAS_SMP_PASSTHRU_BUFFER,
7565 +  *PCSMI_SAS_SMP_PASSTHRU_BUFFER;
7566 +
7567 +// CC_CSMI_SAS_SSP_PASSTHRU
7568 +
7569 +typedef struct _CSMI_SAS_SSP_PASSTHRU {
7570 +   __u8  bPhyIdentifier;
7571 +   __u8  bPortIdentifier;
7572 +   __u8  bConnectionRate;
7573 +   __u8  bReserved;
7574 +   __u8  bDestinationSASAddress[8];
7575 +   __u8  bLun[8];
7576 +   __u8  bCDBLength;
7577 +   __u8  bAdditionalCDBLength;
7578 +   __u8  bReserved2[2];
7579 +   __u8  bCDB[16];
7580 +   __u32 uFlags;
7581 +   __u8  bAdditionalCDB[24];
7582 +   __u32 uDataLength;
7583 +} CSMI_SAS_SSP_PASSTHRU,
7584 +  *PCSMI_SAS_SSP_PASSTHRU;
7585 +
7586 +typedef struct _CSMI_SAS_SSP_PASSTHRU_STATUS {
7587 +   __u8  bConnectionStatus;
7588 +   __u8  bSSPStatus;
7589 +   __u8  bReserved[2];
7590 +   __u8  bDataPresent;
7591 +   __u8  bStatus;
7592 +   __u8  bResponseLength[2];
7593 +   __u8  bResponse[256];
7594 +   __u32 uDataBytes;
7595 +} CSMI_SAS_SSP_PASSTHRU_STATUS,
7596 +  *PCSMI_SAS_SSP_PASSTHRU_STATUS;
7597 +
7598 +typedef struct _CSMI_SAS_SSP_PASSTHRU_BUFFER {
7599 +   IOCTL_HEADER IoctlHeader;
7600 +   CSMI_SAS_SSP_PASSTHRU Parameters;
7601 +   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
7602 +   __u8  bDataBuffer[1];
7603 +} CSMI_SAS_SSP_PASSTHRU_BUFFER,
7604 +  *PCSMI_SAS_SSP_PASSTHRU_BUFFER;
7605 +
7606 +// CC_CSMI_SAS_STP_PASSTHRU
7607 +
7608 +typedef struct _CSMI_SAS_STP_PASSTHRU {
7609 +   __u8  bPhyIdentifier;
7610 +   __u8  bPortIdentifier;
7611 +   __u8  bConnectionRate;
7612 +   __u8  bReserved;
7613 +   __u8  bDestinationSASAddress[8];
7614 +   __u8  bReserved2[4];
7615 +   __u8  bCommandFIS[20];
7616 +   __u32 uFlags;
7617 +   __u32 uDataLength;
7618 +} CSMI_SAS_STP_PASSTHRU,
7619 +  *PCSMI_SAS_STP_PASSTHRU;
7620 +
7621 +typedef struct _CSMI_SAS_STP_PASSTHRU_STATUS {
7622 +   __u8  bConnectionStatus;
7623 +   __u8  bReserved[3];
7624 +   __u8  bStatusFIS[20];
7625 +   __u32 uSCR[16];
7626 +   __u32 uDataBytes;
7627 +} CSMI_SAS_STP_PASSTHRU_STATUS,
7628 +  *PCSMI_SAS_STP_PASSTHRU_STATUS;
7629 +
7630 +typedef struct _CSMI_SAS_STP_PASSTHRU_BUFFER {
7631 +   IOCTL_HEADER IoctlHeader;
7632 +   CSMI_SAS_STP_PASSTHRU Parameters;
7633 +   CSMI_SAS_STP_PASSTHRU_STATUS Status;
7634 +   __u8  bDataBuffer[1];
7635 +} CSMI_SAS_STP_PASSTHRU_BUFFER,
7636 +  *PCSMI_SAS_STP_PASSTHRU_BUFFER;
7637 +
7638 +// CC_CSMI_SAS_GET_SATA_SIGNATURE
7639 +
7640 +typedef struct _CSMI_SAS_SATA_SIGNATURE {
7641 +   __u8  bPhyIdentifier;
7642 +   __u8  bReserved[3];
7643 +   __u8  bSignatureFIS[20];
7644 +} CSMI_SAS_SATA_SIGNATURE,
7645 +  *PCSMI_SAS_SATA_SIGNATURE;
7646 +
7647 +typedef struct _CSMI_SAS_SATA_SIGNATURE_BUFFER {
7648 +   IOCTL_HEADER IoctlHeader;
7649 +   CSMI_SAS_SATA_SIGNATURE Signature;
7650 +} CSMI_SAS_SATA_SIGNATURE_BUFFER,
7651 +  *PCSMI_SAS_SATA_SIGNATURE_BUFFER;
7652 +
7653 +// CC_CSMI_SAS_GET_SCSI_ADDRESS
7654 +
7655 +typedef struct _CSMI_SAS_GET_SCSI_ADDRESS_BUFFER {
7656 +   IOCTL_HEADER IoctlHeader;
7657 +   __u8  bSASAddress[8];
7658 +   __u8  bSASLun[8];
7659 +   __u8  bHostIndex;
7660 +   __u8  bPathId;
7661 +   __u8  bTargetId;
7662 +   __u8  bLun;
7663 +} CSMI_SAS_GET_SCSI_ADDRESS_BUFFER,
7664 +   *PCSMI_SAS_GET_SCSI_ADDRESS_BUFFER;
7665 +
7666 +// CC_CSMI_SAS_GET_DEVICE_ADDRESS
7667 +
7668 +typedef struct _CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER {
7669 +   IOCTL_HEADER IoctlHeader;
7670 +   __u8  bHostIndex;
7671 +   __u8  bPathId;
7672 +   __u8  bTargetId;
7673 +   __u8  bLun;
7674 +   __u8  bSASAddress[8];
7675 +   __u8  bSASLun[8];
7676 +} CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER,
7677 +  *PCSMI_SAS_GET_DEVICE_ADDRESS_BUFFER;
7678 +
7679 +// CC_CSMI_SAS_TASK_MANAGEMENT
7680 +
7681 +typedef struct _CSMI_SAS_SSP_TASK_IU {
7682 +   __u8  bHostIndex;
7683 +   __u8  bPathId;
7684 +   __u8  bTargetId;
7685 +   __u8  bLun;
7686 +   __u32 uFlags;
7687 +   __u32 uQueueTag;
7688 +   __u32 uReserved;
7689 +   __u8  bTaskManagementFunction;
7690 +   __u8  bReserved[7];
7691 +   __u32 uInformation;
7692 +} CSMI_SAS_SSP_TASK_IU,
7693 +  *PCSMI_SAS_SSP_TASK_IU;
7694 +
7695 +typedef struct _CSMI_SAS_SSP_TASK_IU_BUFFER {
7696 +   IOCTL_HEADER IoctlHeader;
7697 +   CSMI_SAS_SSP_TASK_IU Parameters;
7698 +   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
7699 +} CSMI_SAS_SSP_TASK_IU_BUFFER,
7700 +  *PCSMI_SAS_SSP_TASK_IU_BUFFER;
7701 +
7702 +// CC_CSMI_SAS_GET_CONNECTOR_INFO
7703 +
7704 +typedef struct _CSMI_SAS_GET_CONNECTOR_INFO {
7705 +   __u32 uPinout;
7706 +   __u8  bConnector[16];
7707 +   __u8  bLocation;
7708 +   __u8  bReserved[15];
7709 +} CSMI_SAS_CONNECTOR_INFO,
7710 +  *PCSMI_SAS_CONNECTOR_INFO;
7711 +
7712 +typedef struct _CSMI_SAS_CONNECTOR_INFO_BUFFER {
7713 +   IOCTL_HEADER IoctlHeader;
7714 +   CSMI_SAS_CONNECTOR_INFO Reference[32];
7715 +} CSMI_SAS_CONNECTOR_INFO_BUFFER,
7716 +  *PCSMI_SAS_CONNECTOR_INFO_BUFFER;
7717 +
7718 +// CC_CSMI_SAS_GET_LOCATION
7719 +
7720 +typedef struct _CSMI_SAS_LOCATION_IDENTIFIER {
7721 +   __u32 bLocationFlags;
7722 +   __u8  bSASAddress[8];
7723 +   __u8  bSASLun[8];
7724 +   __u8  bEnclosureIdentifier[8];
7725 +   __u8  bEnclosureName[32];
7726 +   __u8  bBayPrefix[32];
7727 +   __u8  bBayIdentifier;
7728 +   __u8  bLocationState;
7729 +   __u8  bReserved[2];
7730 +} CSMI_SAS_LOCATION_IDENTIFIER,
7731 +  *PCSMI_SAS_LOCATION_IDENTIFIER;
7732 +
7733 +typedef struct _CSMI_SAS_GET_LOCATION_BUFFER {
7734 +   IOCTL_HEADER IoctlHeader;
7735 +   __u8  bHostIndex;
7736 +   __u8  bPathId;
7737 +   __u8  bTargetId;
7738 +   __u8  bLun;
7739 +   __u8  bIdentify;
7740 +   __u8  bNumberOfLocationIdentifiers;
7741 +   __u8  bLengthOfLocationIdentifier;
7742 +   CSMI_SAS_LOCATION_IDENTIFIER Location[1];
7743 +} CSMI_SAS_GET_LOCATION_BUFFER,
7744 +  *PCSMI_SAS_GET_LOCATION_BUFFER;
7745 +
7746 +// CC_CSMI_SAS_PHY_CONTROL
7747 +
7748 +typedef struct _CSMI_SAS_CHARACTER {
7749 +   __u8  bTypeFlags;
7750 +   __u8  bValue;
7751 +} CSMI_SAS_CHARACTER,
7752 +  *PCSMI_SAS_CHARACTER;
7753 +
7754 +typedef struct _CSMI_SAS_PHY_CONTROL {
7755 +   __u8  bType;
7756 +   __u8  bRate;
7757 +   __u8  bReserved[6];
7758 +   __u32 uVendorUnique[8];
7759 +   __u32 uTransmitterFlags;
7760 +   __i8  bTransmitAmplitude;
7761 +   __i8  bTransmitterPreemphasis;
7762 +   __i8  bTransmitterSlewRate;
7763 +   __i8  bTransmitterReserved[13];
7764 +   __u8  bTransmitterVendorUnique[64];
7765 +   __u32 uReceiverFlags;
7766 +   __i8  bReceiverThreshold;
7767 +   __i8  bReceiverEqualizationGain;
7768 +   __i8  bReceiverReserved[14];
7769 +   __u8  bReceiverVendorUnique[64];
7770 +   __u32 uPatternFlags;
7771 +   __u8  bFixedPattern;
7772 +   __u8  bUserPatternLength;
7773 +   __u8  bPatternReserved[6];
7774 +   CSMI_SAS_CHARACTER UserPatternBuffer[16];
7775 +} CSMI_SAS_PHY_CONTROL,
7776 +  *PCSMI_SAS_PHY_CONTROL;
7777 +
7778 +typedef struct _CSMI_SAS_PHY_CONTROL_BUFFER {
7779 +   IOCTL_HEADER IoctlHeader;
7780 +   __u32 uFunction;
7781 +   __u8  bPhyIdentifier;
7782 +   __u16 usLengthOfControl;
7783 +   __u8  bNumberOfControls;
7784 +   __u8  bReserved[4];
7785 +   __u32 uLinkFlags;
7786 +   __u8  bSpinupRate;
7787 +   __u8  bLinkReserved[7];
7788 +   __u32 uVendorUnique[8];
7789 +   CSMI_SAS_PHY_CONTROL Control[1];
7790 +} CSMI_SAS_PHY_CONTROL_BUFFER,
7791 +  *PCSMI_SAS_PHY_CONTROL_BUFFER;
7792 +
7793 +//EDM #pragma CSMI_SAS_END_PACK
7794 +#pragma pack()
7795 +
7796 +#endif // _CSMI_SAS_H_
7797 --- a/drivers/message/fusion/Kconfig
7798 +++ b/drivers/message/fusion/Kconfig
7799 @@ -61,13 +61,25 @@ config FUSION_SAS
7800           LSISAS1078
7801  
7802  config FUSION_MAX_SGE
7803 -       int "Maximum number of scatter gather entries (16 - 128)"
7804 +       int "Maximum number of scatter gather entries for SAS and SPI (16 - 128)"
7805         default "128"
7806         range 16 128
7807         help
7808           This option allows you to specify the maximum number of scatter-
7809           gather entries per I/O. The driver default is 128, which matches
7810 -         SCSI_MAX_PHYS_SEGMENTS. However, it may decreased down to 16.
7811 +         SAFE_PHYS_SEGMENTS.  However, it may decreased down to 16.
7812 +         Decreasing this parameter will reduce memory requirements
7813 +         on a per controller instance.
7814 +
7815 +config FUSION_MAX_FC_SGE
7816 +       int "Maximum number of scatter gather entries for FC (16 - 256)"
7817 +       depends on FUSION_FC
7818 +       default "256"
7819 +       range 16 256
7820 +       help
7821 +         This option allows you to specify the maximum number of scatter-
7822 +         gather entries per I/O. The driver default is 256, which matches
7823 +         MAX_PHYS_SEGMENTS.  However, it may decreased down to 16.
7824           Decreasing this parameter will reduce memory requirements
7825           on a per controller instance.
7826  
7827 --- a/drivers/message/fusion/lsi/mpi_cnfg.h
7828 +++ b/drivers/message/fusion/lsi/mpi_cnfg.h
7829 @@ -6,7 +6,7 @@
7830   *          Title:  MPI Config message, structures, and Pages
7831   *  Creation Date:  July 27, 2000
7832   *
7833 - *    mpi_cnfg.h Version:  01.05.15
7834 + *    mpi_cnfg.h Version:  01.05.18
7835   *
7836   *  Version History
7837   *  ---------------
7838 @@ -308,6 +308,20 @@
7839   *                      Expander Page 0 Flags field.
7840   *                      Fixed define for
7841   *                      MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
7842 + *  08-07-07  01.05.16  Added MPI_IOCPAGE6_CAP_FLAGS_MULTIPORT_DRIVE_SUPPORT
7843 + *                      define.
7844 + *                      Added BIOS Page 4 structure.
7845 + *                      Added MPI_RAID_PHYS_DISK1_PATH_MAX define for RAID
7846 + *                      Physcial Disk Page 1.
7847 + *  01-15-07  01.05.17  Added additional bit defines for ExtFlags field of
7848 + *                      Manufacturing Page 4.
7849 + *                      Added Solid State Drives Supported bit to IOC Page 6
7850 + *                      Capabilities Flags.
7851 + *                      Added new value for AccessStatus field of SAS Device
7852 + *                      Page 0 (_SATA_NEEDS_INITIALIZATION).
7853 + *  03-28-08  01.05.18  Defined new bits in Manufacturing Page 4 ExtFlags field
7854 + *                      to control coercion size and the mixing of SAS and SATA
7855 + *                      SSD drives.
7856   *  --------------------------------------------------------------------------
7857   */
7858  
7859 @@ -686,6 +700,14 @@ typedef struct _CONFIG_PAGE_MANUFACTURIN
7860  #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
7861  
7862  /* defines for the ExtFlags field */
7863 +#define MPI_MANPAGE4_EXTFLAGS_MASK_COERCION_SIZE        (0x0180)
7864 +#define MPI_MANPAGE4_EXTFLAGS_SHIFT_COERCION_SIZE       (7)
7865 +#define MPI_MANPAGE4_EXTFLAGS_1GB_COERCION_SIZE         (0)
7866 +#define MPI_MANPAGE4_EXTFLAGS_128MB_COERCION_SIZE       (1)
7867 +
7868 +#define MPI_MANPAGE4_EXTFLAGS_NO_MIX_SSD_SAS_SATA       (0x0040)
7869 +#define MPI_MANPAGE4_EXTFLAGS_MIX_SSD_AND_NON_SSD       (0x0020)
7870 +#define MPI_MANPAGE4_EXTFLAGS_DUAL_PORT_SUPPORT         (0x0010)
7871  #define MPI_MANPAGE4_EXTFLAGS_HIDE_NON_IR_METADATA      (0x0008)
7872  #define MPI_MANPAGE4_EXTFLAGS_SAS_CACHE_DISABLE         (0x0004)
7873  #define MPI_MANPAGE4_EXTFLAGS_SATA_CACHE_DISABLE        (0x0002)
7874 @@ -1159,6 +1181,8 @@ typedef struct _CONFIG_PAGE_IOC_6
7875  
7876  /* IOC Page 6 Capabilities Flags */
7877  
7878 +#define MPI_IOCPAGE6_CAP_FLAGS_SSD_SUPPORT              (0x00000020)
7879 +#define MPI_IOCPAGE6_CAP_FLAGS_MULTIPORT_DRIVE_SUPPORT  (0x00000010)
7880  #define MPI_IOCPAGE6_CAP_FLAGS_DISABLE_SMART_POLLING    (0x00000008)
7881  
7882  #define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE       (0x00000006)
7883 @@ -1428,6 +1452,15 @@ typedef struct _CONFIG_PAGE_BIOS_2
7884  #define MPI_BIOSPAGE2_FORM_SAS_WWN                      (0x05)
7885  #define MPI_BIOSPAGE2_FORM_ENCLOSURE_SLOT               (0x06)
7886  
7887 +typedef struct _CONFIG_PAGE_BIOS_4
7888 +{
7889 +    CONFIG_PAGE_HEADER      Header;                     /* 00h */
7890 +    U64                     ReassignmentBaseWWID;       /* 04h */
7891 +} CONFIG_PAGE_BIOS_4, MPI_POINTER PTR_CONFIG_PAGE_BIOS_4,
7892 +  BIOSPage4_t, MPI_POINTER pBIOSPage4_t;
7893 +
7894 +#define MPI_BIOSPAGE4_PAGEVERSION                       (0x00)
7895 +
7896  
7897  /****************************************************************************
7898  *   SCSI Port Config Pages
7899 @@ -2419,6 +2452,15 @@ typedef struct _RAID_PHYS_DISK1_PATH
7900  #define MPI_RAID_PHYSDISK1_FLAG_BROKEN          (0x0002)
7901  #define MPI_RAID_PHYSDISK1_FLAG_INVALID         (0x0001)
7902  
7903 +
7904 +/*
7905 + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
7906 + * one and check Header.PageLength or NumPhysDiskPaths at runtime.
7907 + */
7908 +#ifndef MPI_RAID_PHYS_DISK1_PATH_MAX
7909 +#define MPI_RAID_PHYS_DISK1_PATH_MAX    (1)
7910 +#endif
7911 +
7912  typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_1
7913  {
7914      CONFIG_PAGE_HEADER              Header;             /* 00h */
7915 @@ -2426,7 +2468,7 @@ typedef struct _CONFIG_PAGE_RAID_PHYS_DI
7916      U8                              PhysDiskNum;        /* 05h */
7917      U16                             Reserved2;          /* 06h */
7918      U32                             Reserved1;          /* 08h */
7919 -    RAID_PHYS_DISK1_PATH            Path[1];            /* 0Ch */
7920 +    RAID_PHYS_DISK1_PATH            Path[MPI_RAID_PHYS_DISK1_PATH_MAX];/* 0Ch */
7921  } CONFIG_PAGE_RAID_PHYS_DISK_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_1,
7922    RaidPhysDiskPage1_t, MPI_POINTER pRaidPhysDiskPage1_t;
7923  
7924 @@ -2844,6 +2886,7 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_0
7925  #define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED            (0x01)
7926  #define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED      (0x02)
7927  #define MPI_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT   (0x03)
7928 +#define MPI_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION   (0x04)
7929  /* specific values for SATA Init failures */
7930  #define MPI_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN                 (0x10)
7931  #define MPI_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT    (0x11)
7932 --- a/drivers/message/fusion/lsi/mpi_fc.h
7933 +++ b/drivers/message/fusion/lsi/mpi_fc.h
7934 @@ -1,5 +1,5 @@
7935  /*
7936 - *  Copyright (c) 2000-2004 LSI Corporation.
7937 + *  Copyright (c) 2000-2008 LSI Corporation.
7938   *
7939   *
7940   *           Name:  mpi_fc.h
7941 --- a/drivers/message/fusion/lsi/mpi.h
7942 +++ b/drivers/message/fusion/lsi/mpi.h
7943 @@ -6,7 +6,7 @@
7944   *          Title:  MPI Message independent structures and definitions
7945   *  Creation Date:  July 27, 2000
7946   *
7947 - *    mpi.h Version:  01.05.13
7948 + *    mpi.h Version:  01.05.16
7949   *
7950   *  Version History
7951   *  ---------------
7952 @@ -79,6 +79,9 @@
7953   *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
7954   *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
7955   *  05-24-07  01.05.13  Bumped MPI_HEADER_VERSION_UNIT.
7956 + *  08-07-07  01.05.14  Bumped MPI_HEADER_VERSION_UNIT.
7957 + *  01-15-08  01.05.15  Bumped MPI_HEADER_VERSION_UNIT.
7958 + *  03-28-08  01.05.16  Bumped MPI_HEADER_VERSION_UNIT.
7959   *  --------------------------------------------------------------------------
7960   */
7961  
7962 @@ -109,7 +112,7 @@
7963  /* Note: The major versions of 0xe0 through 0xff are reserved */
7964  
7965  /* versioning for this MPI header set */
7966 -#define MPI_HEADER_VERSION_UNIT             (0x10)
7967 +#define MPI_HEADER_VERSION_UNIT             (0x13)
7968  #define MPI_HEADER_VERSION_DEV              (0x00)
7969  #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
7970  #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
7971 --- a/drivers/message/fusion/lsi/mpi_history.txt
7972 +++ b/drivers/message/fusion/lsi/mpi_history.txt
7973 @@ -3,28 +3,28 @@
7974   MPI Header File Change History
7975   ==============================
7976  
7977 - Copyright (c) 2000-2007 LSI Corporation.
7978 + Copyright (c) 2000-2008 LSI Corporation.
7979  
7980   ---------------------------------------
7981 - Header Set Release Version:    01.05.16
7982 - Header Set Release Date:       05-24-07
7983 + Header Set Release Version:    01.05.19
7984 + Header Set Release Date:       03-28-08
7985   ---------------------------------------
7986  
7987   Filename               Current version     Prior version
7988   ----------             ---------------     -------------
7989 - mpi.h                  01.05.13            01.05.12
7990 - mpi_ioc.h              01.05.14            01.05.13
7991 - mpi_cnfg.h             01.05.15            01.05.14
7992 + mpi.h                  01.05.16            01.05.15
7993 + mpi_ioc.h              01.05.16            01.05.15
7994 + mpi_cnfg.h             01.05.18            01.05.17
7995   mpi_init.h             01.05.09            01.05.09
7996   mpi_targ.h             01.05.06            01.05.06
7997   mpi_fc.h               01.05.01            01.05.01
7998   mpi_lan.h              01.05.01            01.05.01
7999 - mpi_raid.h             01.05.03            01.05.03
8000 + mpi_raid.h             01.05.05            01.05.05
8001   mpi_tool.h             01.05.03            01.05.03
8002   mpi_inb.h              01.05.01            01.05.01
8003 - mpi_sas.h              01.05.04            01.05.04
8004 + mpi_sas.h              01.05.05            01.05.05
8005   mpi_type.h             01.05.02            01.05.02
8006 - mpi_history.txt        01.05.14            01.05.14
8007 + mpi_history.txt        01.05.19            01.05.18
8008  
8009  
8010   *  Date      Version   Description
8011 @@ -96,6 +96,9 @@ mpi.h
8012   *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
8013   *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
8014   *  05-24-07  01.05.13  Bumped MPI_HEADER_VERSION_UNIT.
8015 + *  08-07-07  01.05.14  Bumped MPI_HEADER_VERSION_UNIT.
8016 + *  01-15-08  01.05.15  Bumped MPI_HEADER_VERSION_UNIT.
8017 + *  03-28-08  01.05.16  Bumped MPI_HEADER_VERSION_UNIT.
8018   *  --------------------------------------------------------------------------
8019  
8020  mpi_ioc.h
8021 @@ -127,7 +130,7 @@ mpi_ioc.h
8022   *  08-08-01  01.02.01  Original release for v1.2 work.
8023   *                      New format for FWVersion and ProductId in
8024   *                      MSG_IOC_FACTS_REPLY and MPI_FW_HEADER.
8025 - *  08-31-01  01.02.02  Added event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
8026 + *  08-31-01  01.02.02  Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
8027   *                      related structure and defines.
8028   *                      Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED.
8029   *                      Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE.
8030 @@ -187,7 +190,7 @@ mpi_ioc.h
8031   *  10-11-06  01.05.12  Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
8032   *                      Added MaxInitiators field to PortFacts reply.
8033   *                      Added SAS Device Status Change ReasonCode for
8034 - *                      asynchronous notification.
8035 + *                      asynchronous notificaiton.
8036   *                      Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
8037   *                      data structure.
8038   *                      Added new ImageType values for FWDownload and FWUpload
8039 @@ -199,6 +202,16 @@ mpi_ioc.h
8040   *                      added _MULTI_PORT_DOMAIN.
8041   *  05-24-07  01.05.14  Added Common Boot Block type to FWDownload Request.
8042   *                      Added Common Boot Block type to FWUpload Request.
8043 + *  08-07-07  01.05.15  Added MPI_EVENT_SAS_INIT_RC_REMOVED define.
8044 + *                      Added MPI_EVENT_IR2_RC_DUAL_PORT_ADDED and
8045 + *                      MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED for IR2 event data.
8046 + *                      Added SASAddress field to SAS Initiator Device Table
8047 + *                      Overflow event data structure.
8048 + *  03-28-08  01.05.16  Added two new ReasonCode values to SAS Device Status
8049 + *                      Change Event data to indicate completion of internally
8050 + *                      generated task management.
8051 + *                      Added MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE define.
8052 + *                      Added MPI_EVENT_SAS_INIT_RC_INACCESSIBLE define.
8053   *  --------------------------------------------------------------------------
8054  
8055  mpi_cnfg.h
8056 @@ -213,7 +226,7 @@ mpi_cnfg.h
8057   *                      Added _RESPONSE_ID_MASK definition to SCSI_PORT_1
8058   *                      page and updated the page version.
8059   *                      Added Information field and _INFO_PARAMS_NEGOTIATED
8060 - *                      definition to SCSI_DEVICE_0 page.
8061 + *                      definitionto SCSI_DEVICE_0 page.
8062   *  06-22-00  01.00.03  Removed batch controls from LAN_0 page and updated the
8063   *                      page version.
8064   *                      Added BucketsRemaining to LAN_1 page, redefined the
8065 @@ -496,6 +509,20 @@ mpi_cnfg.h
8066   *                      Expander Page 0 Flags field.
8067   *                      Fixed define for
8068   *                      MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
8069 + *  08-07-07  01.05.16  Added MPI_IOCPAGE6_CAP_FLAGS_MULTIPORT_DRIVE_SUPPORT
8070 + *                      define.
8071 + *                      Added BIOS Page 4 structure.
8072 + *                      Added MPI_RAID_PHYS_DISK1_PATH_MAX define for RAID
8073 + *                      Physcial Disk Page 1.
8074 + *  01-15-07  01.05.17  Added additional bit defines for ExtFlags field of
8075 + *                      Manufacturing Page 4.
8076 + *                      Added Solid State Drives Supported bit to IOC Page 6
8077 + *                      Capabilities Flags.
8078 + *                      Added new value for AccessStatus field of SAS Device
8079 + *                      Page 0 (_SATA_NEEDS_INITIALIZATION).
8080 + *  03-28-08  01.05.18  Defined new bits in Manufacturing Page 4 ExtFlags field
8081 + *                      to control coercion size and the mixing of SAS and SATA
8082 + *                      SSD drives.
8083   *  --------------------------------------------------------------------------
8084  
8085  mpi_init.h
8086 @@ -661,6 +688,9 @@ mpi_raid.h
8087   *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
8088   *  02-28-07  01.05.03  Added new RAID Action, Device FW Update Mode, and
8089   *                      associated defines.
8090 + *  08-07-07  01.05.04  Added Disable Full Rebuild bit to the ActionDataWord
8091 + *                      for the RAID Action MPI_RAID_ACTION_DISABLE_VOLUME.
8092 + *  01-15-08  01.05.05  Added define for MPI_RAID_ACTION_SET_VOLUME_NAME.
8093   *  --------------------------------------------------------------------------
8094  
8095  mpi_tool.h
8096 @@ -694,6 +724,10 @@ mpi_sas.h
8097   *                      reply.
8098   *  10-11-06  01.05.04  Fixed the name of a define for Operation field of SAS IO
8099   *                      Unit Control request.
8100 + *  01-15-08  01.05.05  Added support for MPI_SAS_OP_SET_IOC_PARAMETER,
8101 + *                      including adding IOCParameter and IOCParameter value
8102 + *                      fields to SAS IO Unit Control Request.
8103 + *                      Added MPI_SAS_DEVICE_INFO_PRODUCT_SPECIFIC define.
8104   *  --------------------------------------------------------------------------
8105  
8106  mpi_type.h
8107 @@ -709,20 +743,20 @@ mpi_type.h
8108  
8109  mpi_history.txt         Parts list history
8110  
8111 -Filename    01.05.15   01.05.15
8112 -----------  --------   --------
8113 -mpi.h       01.05.12   01.05.13
8114 -mpi_ioc.h   01.05.13   01.05.14
8115 -mpi_cnfg.h  01.05.14   01.05.15
8116 -mpi_init.h  01.05.09   01.05.09
8117 -mpi_targ.h  01.05.06   01.05.06
8118 -mpi_fc.h    01.05.01   01.05.01
8119 -mpi_lan.h   01.05.01   01.05.01
8120 -mpi_raid.h  01.05.03   01.05.03
8121 -mpi_tool.h  01.05.03   01.05.03
8122 -mpi_inb.h   01.05.01   01.05.01
8123 -mpi_sas.h   01.05.04   01.05.04
8124 -mpi_type.h  01.05.02   01.05.02
8125 +Filename    01.05.19   01.05.18   01.05.17   01.05.16   01.05.15
8126 +----------  --------   --------   --------   --------   --------
8127 +mpi.h       01.05.16   01.05.15   01.05.14   01.05.13   01.05.12
8128 +mpi_ioc.h   01.05.16   01.05.15   01.05.15   01.05.14   01.05.13
8129 +mpi_cnfg.h  01.05.18   01.05.17   01.05.16   01.05.15   01.05.14
8130 +mpi_init.h  01.05.09   01.05.09   01.05.09   01.05.09   01.05.09
8131 +mpi_targ.h  01.05.06   01.05.06   01.05.06   01.05.06   01.05.06
8132 +mpi_fc.h    01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
8133 +mpi_lan.h   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
8134 +mpi_raid.h  01.05.05   01.05.05   01.05.04   01.05.03   01.05.03
8135 +mpi_tool.h  01.05.03   01.05.03   01.05.03   01.05.03   01.05.03
8136 +mpi_inb.h   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
8137 +mpi_sas.h   01.05.05   01.05.05   01.05.04   01.05.04   01.05.04
8138 +mpi_type.h  01.05.02   01.05.02   01.05.02   01.05.02   01.05.02
8139  
8140  Filename    01.05.14   01.05.13   01.05.12   01.05.11   01.05.10   01.05.09
8141  ----------  --------   --------   --------   --------   --------   --------
8142 --- a/drivers/message/fusion/lsi/mpi_init.h
8143 +++ b/drivers/message/fusion/lsi/mpi_init.h
8144 @@ -1,5 +1,5 @@
8145  /*
8146 - *  Copyright (c) 2000-2007 LSI Corporation.
8147 + *  Copyright (c) 2000-2008 LSI Corporation.
8148   *
8149   *
8150   *           Name:  mpi_init.h
8151 --- a/drivers/message/fusion/lsi/mpi_ioc.h
8152 +++ b/drivers/message/fusion/lsi/mpi_ioc.h
8153 @@ -1,12 +1,12 @@
8154  /*
8155 - *  Copyright (c) 2000-2007 LSI Corporation.
8156 + *  Copyright (c) 2000-2008 LSI Corporation.
8157   *
8158   *
8159   *           Name:  mpi_ioc.h
8160   *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
8161   *  Creation Date:  August 11, 2000
8162   *
8163 - *    mpi_ioc.h Version:  01.05.14
8164 + *    mpi_ioc.h Version:  01.05.16
8165   *
8166   *  Version History
8167   *  ---------------
8168 @@ -113,6 +113,16 @@
8169   *                      added _MULTI_PORT_DOMAIN.
8170   *  05-24-07  01.05.14  Added Common Boot Block type to FWDownload Request.
8171   *                      Added Common Boot Block type to FWUpload Request.
8172 + *  08-07-07  01.05.15  Added MPI_EVENT_SAS_INIT_RC_REMOVED define.
8173 + *                      Added MPI_EVENT_IR2_RC_DUAL_PORT_ADDED and
8174 + *                      MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED for IR2 event data.
8175 + *                      Added SASAddress field to SAS Initiator Device Table
8176 + *                      Overflow event data structure.
8177 + *  03-28-08  01.05.16  Added two new ReasonCode values to SAS Device Status
8178 + *                      Change Event data to indicate completion of internally
8179 + *                      generated task management.
8180 + *                      Added MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE define.
8181 + *                      Added MPI_EVENT_SAS_INIT_RC_INACCESSIBLE define.
8182   *  --------------------------------------------------------------------------
8183   */
8184  
8185 @@ -612,6 +622,8 @@ typedef struct _EVENT_DATA_SAS_DEVICE_ST
8186  #define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL   (0x0B)
8187  #define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL       (0x0C)
8188  #define MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION        (0x0D)
8189 +#define MPI_EVENT_SAS_DEV_STAT_RC_CMPL_INTERNAL_DEV_RESET   (0x0E)
8190 +#define MPI_EVENT_SAS_DEV_STAT_RC_CMPL_TASK_ABORT_INTERNAL  (0x0F)
8191  
8192  
8193  /* SCSI Event data for Queue Full event */
8194 @@ -708,6 +720,8 @@ typedef struct _MPI_EVENT_DATA_IR2
8195  #define MPI_EVENT_IR2_RC_PD_REMOVED                 (0x05)
8196  #define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED       (0x06)
8197  #define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR       (0x07)
8198 +#define MPI_EVENT_IR2_RC_DUAL_PORT_ADDED            (0x08)
8199 +#define MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED          (0x09)
8200  
8201  /* defines for logical disk states */
8202  #define MPI_LD_STATE_OPTIMAL                        (0x00)
8203 @@ -867,6 +881,7 @@ typedef struct _EVENT_DATA_DISCOVERY_ERR
8204  #define MPI_EVENT_DSCVRY_ERR_DS_UNSUPPORTED_DEVICE          (0x00000800)
8205  #define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS            (0x00001000)
8206  #define MPI_EVENT_DSCVRY_ERR_DS_MULTI_PORT_DOMAIN           (0x00002000)
8207 +#define MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE           (0x00004000)
8208  
8209  /* SAS SMP Error Event data */
8210  
8211 @@ -902,6 +917,8 @@ typedef struct _EVENT_DATA_SAS_INIT_DEV_
8212  
8213  /* defines for the ReasonCode field of the SAS Initiator Device Status Change event */
8214  #define MPI_EVENT_SAS_INIT_RC_ADDED                 (0x01)
8215 +#define MPI_EVENT_SAS_INIT_RC_REMOVED               (0x02)
8216 +#define MPI_EVENT_SAS_INIT_RC_INACCESSIBLE          (0x03)
8217  
8218  /* SAS Initiator Device Table Overflow Event data */
8219  
8220 @@ -910,6 +927,7 @@ typedef struct _EVENT_DATA_SAS_INIT_TABL
8221      U8                      MaxInit;                    /* 00h */
8222      U8                      CurrentInit;                /* 01h */
8223      U16                     Reserved1;                  /* 02h */
8224 +    U64                     SASAddress;                 /* 04h */
8225  } EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
8226    MPI_POINTER PTR_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
8227    MpiEventDataSasInitTableOverflow_t,
8228 --- a/drivers/message/fusion/lsi/mpi_lan.h
8229 +++ b/drivers/message/fusion/lsi/mpi_lan.h
8230 @@ -1,5 +1,5 @@
8231  /*
8232 - *  Copyright (c) 2000-2004 LSI Corporation.
8233 + *  Copyright (c) 2000-2008 LSI Corporation.
8234   *
8235   *
8236   *           Name:  mpi_lan.h
8237 --- a/drivers/message/fusion/lsi/mpi_log_fc.h
8238 +++ b/drivers/message/fusion/lsi/mpi_log_fc.h
8239 @@ -1,5 +1,5 @@
8240  /*
8241 - *  Copyright (c) 2000-2001 LSI Corporation. All rights reserved.
8242 + *  Copyright (c) 2000-2008 LSI Corporation. All rights reserved.
8243   *
8244   *  NAME:           fc_log.h
8245   *  SUMMARY:        MPI IocLogInfo definitions for the SYMFC9xx chips
8246 --- a/drivers/message/fusion/lsi/mpi_log_sas.h
8247 +++ b/drivers/message/fusion/lsi/mpi_log_sas.h
8248 @@ -1,6 +1,6 @@
8249  /***************************************************************************
8250   *                                                                         *
8251 - *  Copyright 2003 LSI Corporation.  All rights reserved.            *
8252 + *  Copyright (c) 2000-2008 LSI Corporation.  All rights reserved.         *
8253   *                                                                         *
8254   * Description                                                             *
8255   * ------------                                                            *
8256 @@ -73,6 +73,8 @@
8257  #define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO          (0x00070004)
8258  #define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ      (0x00070005)
8259  
8260 +#define IOP_LOGINFO_CODE_LOG_TIMESTAMP_EVENT                 (0x00080000)
8261 +
8262  /****************************************************************************/
8263  /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL            */
8264  /****************************************************************************/
8265 @@ -92,7 +94,7 @@
8266  #define PL_LOGINFO_SUB_CODE_OPEN_FAIL_OPEN_TIMEOUT_EXP       (0x0000000C)
8267  #define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0D              (0x0000000D)
8268  #define PL_LOGINFO_SUB_CODE_OPEN_FAIL_DVTBLE_ACCSS_FAIL      (0x0000000E)
8269 -#define PL_LOGINFO_SUB CODE_OPEN_FAIL_BAD_DEST               (0x00000011)
8270 +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_BAD_DEST               (0x00000011)
8271  #define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RATE_NOT_SUPP          (0x00000012)
8272  #define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PROT_NOT_SUPP          (0x00000013)
8273  #define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON0      (0x00000014)
8274 @@ -162,7 +164,7 @@
8275  #define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR                 (0x00000400) /* Bits 0-3 encode Transport Status Register (offset 0x08) */
8276                                                                            /* Bit 0 is Status Bit 0: FrameXferErr */
8277                                                                            /* Bit 1 & 2 are Status Bits 16 and 17: FrameXmitErrStatus */
8278 -                                                                          /* Bit 3 is Status Bit 18 WriteDataLengthGTDataLengthErr */
8279 +                                                                          /* Bit 3 is Status Bit 18 WriteDataLenghtGTDataLengthErr */
8280  
8281  #define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW              (0x00000500)
8282  #define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET      (0x00000600)
8283 @@ -177,6 +179,10 @@
8284  #define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET       (0x00000E01)
8285  #define PL_LOGINFO_SUB_CODE_SECOND_OPEN                      (0x00000F00)
8286  #define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT         (0x00001000)
8287 +#define PL_LOGINFO_SUB_CODE_BREAK_ON_SATA_CONNECTION            (0x00002000) /* not currently used in mainline */
8288 +#define PL_LOGINFO_SUB_CODE_BREAK_ON_STUCK_LINK              (0x00003000)
8289 +#define PL_LOGINFO_SUB_CODE_BREAK_ON_STUCK_LINK_AIP          (0x00004000)
8290 +#define PL_LOGINFO_SUB_CODE_BREAK_ON_INCOMPLETE_BREAK_RCVD   (0x00005000)
8291  
8292  #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE          (0x00200000) /* Can't get SMP Frame */
8293  #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR             (0x00200010) /* Error occured on SMP Read */
8294 @@ -243,6 +249,8 @@
8295  #define IR_LOGINFO_VOLUME_ACTIVATE_VOLUME_FAILED               (0x00010014)
8296  /* Activation failed trying to import the volume */
8297  #define IR_LOGINFO_VOLUME_ACTIVATING_IMPORT_VOLUME_FAILED      (0x00010015)
8298 +/* Activation failed trying to import the volume */
8299 +#define IR_LOGINFO_VOLUME_ACTIVATING_TOO_MANY_PHYS_DISKS       (0x00010016)
8300  
8301  /* Phys Disk failed, too many phys disks */
8302  #define IR_LOGINFO_PHYSDISK_CREATE_TOO_MANY_DISKS              (0x00010020)
8303 @@ -285,6 +293,23 @@
8304  /* Compatibility Error : IME size limited to < 2TB */
8305  #define IR_LOGINFO_COMPAT_ERROR_IME_VOL_NOT_CURRENTLY_SUPPORTED (0x0001003D)
8306  
8307 +/* Device Firmware Update: DFU can only be started once */
8308 +#define IR_LOGINFO_DEV_FW_UPDATE_ERR_DFU_IN_PROGRESS            (0x00010050)
8309 +/* Device Firmware Update: Volume must be Optimal/Active/non-Quiesced */
8310 +#define IR_LOGINFO_DEV_FW_UPDATE_ERR_DEVICE_IN_INVALID_STATE    (0x00010051)
8311 +/* Device Firmware Update: DFU Timeout cannot be zero */
8312 +#define IR_LOGINFO_DEV_FW_UPDATE_ERR_INVALID_TIMEOUT            (0x00010052)
8313 +/* Device Firmware Update: CREATE TIMER FAILED */
8314 +#define IR_LOGINFO_DEV_FW_UPDATE_ERR_NO_TIMERS                  (0x00010053)
8315 +/* Device Firmware Update: Failed to read SAS_IO_UNIT_PG_1 */
8316 +#define IR_LOGINFO_DEV_FW_UPDATE_ERR_READING_CFG_PAGE           (0x00010054)
8317 +/* Device Firmware Update: Invalid SAS_IO_UNIT_PG_1 value(s) */
8318 +#define IR_LOGINFO_DEV_FW_UPDATE_ERR_PORT_IO_TIMEOUTS_REQUIRED  (0x00010055)
8319 +/* Device Firmware Update: Unable to allocate memory for page */
8320 +#define IR_LOGINFO_DEV_FW_UPDATE_ERR_ALLOC_CFG_PAGE             (0x00010056)
8321 +/* Device Firmware Update:  */
8322 +//#define IR_LOGINFO_DEV_FW_UPDATE_ERR_                         (0x00010054)
8323 +
8324  
8325  /****************************************************************************/
8326  /* Defines for convenience                                                  */
8327 --- a/drivers/message/fusion/lsi/mpi_raid.h
8328 +++ b/drivers/message/fusion/lsi/mpi_raid.h
8329 @@ -1,12 +1,12 @@
8330  /*
8331 - *  Copyright (c) 2001-2007 LSI Corporation.
8332 + *  Copyright (c) 2001-2008 LSI Corporation.
8333   *
8334   *
8335   *           Name:  mpi_raid.h
8336   *          Title:  MPI RAID message and structures
8337   *  Creation Date:  February 27, 2001
8338   *
8339 - *    mpi_raid.h Version:  01.05.03
8340 + *    mpi_raid.h Version:  01.05.05
8341   *
8342   *  Version History
8343   *  ---------------
8344 @@ -34,6 +34,9 @@
8345   *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
8346   *  02-28-07  01.05.03  Added new RAID Action, Device FW Update Mode, and
8347   *                      associated defines.
8348 + *  08-07-07  01.05.04  Added Disable Full Rebuild bit to the ActionDataWord
8349 + *                      for the RAID Action MPI_RAID_ACTION_DISABLE_VOLUME.
8350 + *  01-15-08  01.05.05  Added define for MPI_RAID_ACTION_SET_VOLUME_NAME.
8351   *  --------------------------------------------------------------------------
8352   */
8353  
8354 @@ -93,6 +96,7 @@ typedef struct _MSG_RAID_ACTION
8355  #define MPI_RAID_ACTION_SET_RESYNC_RATE             (0x13)
8356  #define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE         (0x14)
8357  #define MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE       (0x15)
8358 +#define MPI_RAID_ACTION_SET_VOLUME_NAME             (0x16)
8359  
8360  /* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */
8361  #define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC           (0x00000001)
8362 @@ -105,6 +109,9 @@ typedef struct _MSG_RAID_ACTION
8363  #define MPI_RAID_ACTION_ADATA_KEEP_LBA0             (0x00000000)
8364  #define MPI_RAID_ACTION_ADATA_ZERO_LBA0             (0x00000002)
8365  
8366 +/* ActionDataWord defines for use with MPI_RAID_ACTION_DISABLE_VOLUME action */
8367 +#define MPI_RAID_ACTION_ADATA_DISABLE_FULL_REBUILD  (0x00000001)
8368 +
8369  /* ActionDataWord defines for use with MPI_RAID_ACTION_ACTIVATE_VOLUME action */
8370  #define MPI_RAID_ACTION_ADATA_INACTIVATE_ALL        (0x00000001)
8371  
8372 --- a/drivers/message/fusion/lsi/mpi_sas.h
8373 +++ b/drivers/message/fusion/lsi/mpi_sas.h
8374 @@ -1,12 +1,12 @@
8375  /*
8376 - *  Copyright (c) 2004-2006 LSI Corporation.
8377 + *  Copyright (c) 2004-2008 LSI Corporation.
8378   *
8379   *
8380   *           Name:  mpi_sas.h
8381   *          Title:  MPI Serial Attached SCSI structures and definitions
8382   *  Creation Date:  August 19, 2004
8383   *
8384 - *    mpi_sas.h Version:  01.05.04
8385 + *    mpi_sas.h Version:  01.05.05
8386   *
8387   *  Version History
8388   *  ---------------
8389 @@ -23,6 +23,10 @@
8390   *                      reply.
8391   *  10-11-06  01.05.04  Fixed the name of a define for Operation field of SAS IO
8392   *                      Unit Control request.
8393 + *  01-15-08  01.05.05  Added support for MPI_SAS_OP_SET_IOC_PARAMETER,
8394 + *                      including adding IOCParameter and IOCParameter value
8395 + *                      fields to SAS IO Unit Control Request.
8396 + *                      Added MPI_SAS_DEVICE_INFO_PRODUCT_SPECIFIC define.
8397   *  --------------------------------------------------------------------------
8398   */
8399  
8400 @@ -60,6 +64,8 @@
8401   * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
8402   * data and SAS IO Unit Configuration pages.
8403   */
8404 +#define MPI_SAS_DEVICE_INFO_PRODUCT_SPECIFIC    (0xF0000000)
8405 +
8406  #define MPI_SAS_DEVICE_INFO_SEP                 (0x00004000)
8407  #define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE        (0x00002000)
8408  #define MPI_SAS_DEVICE_INFO_LSI_DEVICE          (0x00001000)
8409 @@ -216,7 +222,7 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_R
8410      U8                      ChainOffset;        /* 02h */
8411      U8                      Function;           /* 03h */
8412      U16                     DevHandle;          /* 04h */
8413 -    U8                      Reserved3;          /* 06h */
8414 +    U8                      IOCParameter;       /* 06h */
8415      U8                      MsgFlags;           /* 07h */
8416      U32                     MsgContext;         /* 08h */
8417      U8                      TargetID;           /* 0Ch */
8418 @@ -225,7 +231,7 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_R
8419      U8                      PrimFlags;          /* 0Fh */
8420      U32                     Primitive;          /* 10h */
8421      U64                     SASAddress;         /* 14h */
8422 -    U32                     Reserved4;          /* 1Ch */
8423 +    U32                     IOCParameterValue;  /* 1Ch */
8424  } MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
8425    SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
8426  
8427 @@ -241,6 +247,8 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_R
8428  #define MPI_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL  (0x0C)
8429  #define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE       (0x0D)  /* obsolete name */
8430  #define MPI_SAS_OP_REMOVE_DEVICE                (0x0D)
8431 +#define MPI_SAS_OP_SET_IOC_PARAMETER            (0x0E)
8432 +#define MPI_SAS_OP_PRODUCT_SPECIFIC_MIN         (0x80)
8433  
8434  /* values for the PrimFlags field */
8435  #define MPI_SAS_PRIMFLAGS_SINGLE                (0x08)
8436 @@ -256,7 +264,7 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_R
8437      U8                      MsgLength;          /* 02h */
8438      U8                      Function;           /* 03h */
8439      U16                     DevHandle;          /* 04h */
8440 -    U8                      Reserved3;          /* 06h */
8441 +    U8                      IOCParameter;       /* 06h */
8442      U8                      MsgFlags;           /* 07h */
8443      U32                     MsgContext;         /* 08h */
8444      U16                     Reserved4;          /* 0Ch */
8445 --- a/drivers/message/fusion/lsi/mpi_targ.h
8446 +++ b/drivers/message/fusion/lsi/mpi_targ.h
8447 @@ -1,5 +1,5 @@
8448  /*
8449 - *  Copyright (c) 2000-2004 LSI Corporation.
8450 + *  Copyright (c) 2000-2008 LSI Corporation.
8451   *
8452   *
8453   *           Name:  mpi_targ.h
8454 --- a/drivers/message/fusion/lsi/mpi_tool.h
8455 +++ b/drivers/message/fusion/lsi/mpi_tool.h
8456 @@ -1,5 +1,5 @@
8457  /*
8458 - *  Copyright (c) 2001-2005 LSI Corporation.
8459 + *  Copyright (c) 2001-2008 LSI Corporation.
8460   *
8461   *
8462   *           Name:  mpi_tool.h
8463 --- a/drivers/message/fusion/lsi/mpi_type.h
8464 +++ b/drivers/message/fusion/lsi/mpi_type.h
8465 @@ -1,12 +1,12 @@
8466  /*
8467 - *  Copyright (c) 2000-2004 LSI Corporation.
8468 + *  Copyright (c) 2000-2008 LSI Corporation.
8469   *
8470   *
8471   *           Name:  mpi_type.h
8472   *          Title:  MPI Basic type definitions
8473   *  Creation Date:  June 6, 2000
8474   *
8475 - *    mpi_type.h Version:  01.05.01
8476 + *    mpi_type.h Version:  01.05.02
8477   *
8478   *  Version History
8479   *  ---------------
8480 @@ -20,6 +20,7 @@
8481   *  08-08-01  01.02.01  Original release for v1.2 work.
8482   *  05-11-04  01.03.01  Original release for MPI v1.3.
8483   *  08-19-04  01.05.01  Original release for MPI v1.5.
8484 + *  08-30-05  01.05.02  Added PowerPC option to #ifdef's.
8485   *  --------------------------------------------------------------------------
8486   */
8487  
8488 @@ -49,8 +50,18 @@ typedef signed   short  S16;
8489  typedef unsigned short  U16;
8490  
8491  
8492 -typedef int32_t   S32;
8493 -typedef u_int32_t U32;
8494 +#if defined(unix) || defined(__arm) || defined(ALPHA) || defined(__PPC__) || defined(__ppc)
8495 +
8496 +    typedef signed   int   S32;
8497 +    typedef unsigned int   U32;
8498 +
8499 +#else
8500 +
8501 +    typedef signed   long  S32;
8502 +    typedef unsigned long  U32;
8503 +
8504 +#endif
8505 +
8506  
8507  typedef struct _S64
8508  {
8509 --- a/drivers/message/fusion/Makefile
8510 +++ b/drivers/message/fusion/Makefile
8511 @@ -1,12 +1,17 @@
8512 -# Fusion MPT drivers; recognized debug defines...
8513 +#
8514 +# LSI mpt fusion
8515 +#
8516 +
8517 +# csmi ioctls enable
8518 +EXTRA_CFLAGS += -DCPQ_CIM
8519 +EXTRA_CFLAGS += -DDIAG_BUFFER_SUPPORT
8520 +
8521 +EXTRA_CFLAGS += -DCONFIG_FUSION_LOGGING
8522  
8523  # enable verbose logging
8524  # CONFIG_FUSION_LOGGING needs to be enabled in Kconfig
8525  #EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE
8526  
8527 -
8528 -#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
8529 -
8530  obj-$(CONFIG_FUSION_SPI)       += mptbase.o mptscsih.o mptspi.o
8531  obj-$(CONFIG_FUSION_FC)                += mptbase.o mptscsih.o mptfc.o
8532  obj-$(CONFIG_FUSION_SAS)       += mptbase.o mptscsih.o mptsas.o
8533 --- a/drivers/message/fusion/mptbase.c
8534 +++ b/drivers/message/fusion/mptbase.c
8535 @@ -58,6 +58,7 @@
8536  #include <linux/delay.h>
8537  #include <linux/interrupt.h>           /* needed for in_interrupt() proto */
8538  #include <linux/dma-mapping.h>
8539 +#include <linux/sort.h>
8540  #include <asm/io.h>
8541  #ifdef CONFIG_MTRR
8542  #include <asm/mtrr.h>
8543 @@ -79,19 +80,38 @@ MODULE_VERSION(my_VERSION);
8544  /*
8545   *  cmd line parameters
8546   */
8547 -static int mpt_msi_enable = -1;
8548 -module_param(mpt_msi_enable, int, 0);
8549 -MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
8550 +
8551 +static int mpt_msi_enable_spi;
8552 +module_param(mpt_msi_enable_spi, int, 0);
8553 +MODULE_PARM_DESC(mpt_msi_enable_spi, " Enable MSI Support for SPI controllers (default=0)");
8554 +
8555 +static int mpt_msi_enable_fc;
8556 +module_param(mpt_msi_enable_fc, int, 0);
8557 +MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC controllers (default=0)");
8558 +
8559 +static int mpt_msi_enable_sas = 1;
8560 +module_param(mpt_msi_enable_sas, int, 0);
8561 +MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS controllers (default=1)");
8562 +
8563  
8564  static int mpt_channel_mapping;
8565  module_param(mpt_channel_mapping, int, 0);
8566  MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
8567  
8568 -static int mpt_debug_level;
8569 +int mpt_debug_level;
8570  static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
8571  module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
8572                   &mpt_debug_level, 0600);
8573  MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h - (default=0)");
8574 +EXPORT_SYMBOL(mpt_debug_level);
8575 +
8576 +int mpt_fwfault_debug;
8577 +module_param_call(mpt_fwfault_debug, param_set_int, param_get_int,
8578 +                 &mpt_fwfault_debug, 0600);
8579 +MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault"
8580 +               " and halt Firmware on fault - (default=0)");
8581 +EXPORT_SYMBOL(mpt_fwfault_debug);
8582 +
8583  
8584  #ifdef MFCNT
8585  static int mfcounter = 0;
8586 @@ -102,8 +122,7 @@ static int mfcounter = 0;
8587  /*
8588   *  Public data...
8589   */
8590 -
8591 -static struct proc_dir_entry *mpt_proc_root_dir;
8592 +struct proc_dir_entry *mpt_proc_root_dir;
8593  
8594  #define WHOINIT_UNKNOWN                0xAA
8595  
8596 @@ -125,6 +144,8 @@ static struct mpt_pci_driver        *MptDevice
8597  
8598  static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
8599  
8600 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8601 +
8602  /*
8603   *  Driver Callback Index's
8604   */
8605 @@ -135,8 +156,7 @@ static u8 last_drv_idx;
8606  /*
8607   *  Forward protos...
8608   */
8609 -static irqreturn_t mpt_interrupt(int irq, void *bus_id);
8610 -static int     mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
8611 +static int     mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
8612  static int     mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
8613                         u32 *req, int replyBytes, u16 *u16reply, int maxwait,
8614                         int sleepFlag);
8615 @@ -167,9 +187,8 @@ static int  mpt_GetScsiPortSettings(MPT_A
8616  static int     mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
8617  static void    mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
8618  static void    mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
8619 -static void    mpt_timer_expired(unsigned long data);
8620  static void    mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
8621 -static int     SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
8622 +static int     SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag);
8623  static int     SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
8624  static int     mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
8625  static int     mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
8626 @@ -184,7 +203,6 @@ static int  procmpt_iocinfo_read(char *bu
8627  #endif
8628  static void    mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
8629  
8630 -//int          mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
8631  static int     ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
8632  static void    mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
8633  static void    mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
8634 @@ -193,6 +211,7 @@ static void mpt_sas_log_info(MPT_ADAPTER
8635  static int     mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
8636  static void    mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
8637  
8638 +
8639  /* module entry point */
8640  static int  __init    fusion_init  (void);
8641  static void __exit    fusion_exit  (void);
8642 @@ -223,7 +242,16 @@ pci_enable_io_access(struct pci_dev *pde
8643         pci_write_config_word(pdev, PCI_COMMAND, command_reg);
8644  }
8645  
8646 -static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
8647 +/**
8648 + *     mpt_set_debug_level - global setting of the mpt_debug_level
8649 + *     found via /sys/module/mptbase/parameters/mpt_debug_level
8650 + *     @val:
8651 + *     @kp:
8652 + *
8653 + *     Returns
8654 + **/
8655 +static int
8656 +mpt_set_debug_level(const char *val, struct kernel_param *kp)
8657  {
8658         int ret = param_set_int(val, kp);
8659         MPT_ADAPTER *ioc;
8660 @@ -254,6 +282,56 @@ mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
8661  }
8662  
8663  /**
8664 + * mpt_is_discovery_complete - determine if discovery has completed
8665 + * @ioc: per adatper instance
8666 + *
8667 + * Returns 1 when discovery completed, else zero.
8668 + */
8669 +static int
8670 +mpt_is_discovery_complete(MPT_ADAPTER *ioc)
8671 +{
8672 +       ConfigExtendedPageHeader_t hdr;
8673 +       CONFIGPARMS cfg;
8674 +       SasIOUnitPage0_t *buffer;
8675 +       dma_addr_t dma_handle;
8676 +       int rc = 0;
8677 +
8678 +       memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
8679 +       memset(&cfg, 0, sizeof(CONFIGPARMS));
8680 +       hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
8681 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
8682 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
8683 +       cfg.cfghdr.ehdr = &hdr;
8684 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
8685 +
8686 +       if ((mpt_config(ioc, &cfg)))
8687 +               goto out;
8688 +       if (!hdr.ExtPageLength)
8689 +               goto out;
8690 +
8691 +       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
8692 +           &dma_handle);
8693 +       if (!buffer)
8694 +               goto out;
8695 +
8696 +       cfg.physAddr = dma_handle;
8697 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
8698 +
8699 +       if ((mpt_config(ioc, &cfg)))
8700 +               goto out_free_consistent;
8701 +
8702 +       if (!(buffer->PhyData[0].PortFlags &
8703 +           MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS))
8704 +               rc = 1;
8705 +
8706 + out_free_consistent:
8707 +       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
8708 +           buffer, dma_handle);
8709 + out:
8710 +       return rc;
8711 +}
8712 +
8713 +/**
8714   *     mpt_fault_reset_work - work performed on workq after ioc fault
8715   *     @work: input argument, used to derive ioc
8716   *
8717 @@ -267,23 +345,29 @@ mpt_fault_reset_work(struct work_struct 
8718         int              rc;
8719         unsigned long    flags;
8720  
8721 -       if (ioc->diagPending || !ioc->active)
8722 +       if (ioc->ioc_reset_in_progress || !ioc->active)
8723                 goto out;
8724  
8725         ioc_raw_state = mpt_GetIocState(ioc, 0);
8726         if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
8727                 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
8728 -                      ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
8729 +                   ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
8730                 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
8731 -                      ioc->name, __func__);
8732 +                   ioc->name, __FUNCTION__);
8733                 rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
8734                 printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
8735 -                      __func__, (rc == 0) ? "success" : "failed");
8736 +                   __FUNCTION__, (rc == 0) ? "success" : "failed");
8737                 ioc_raw_state = mpt_GetIocState(ioc, 0);
8738                 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
8739                         printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
8740                             "reset (%04xh)\n", ioc->name, ioc_raw_state &
8741                             MPI_DOORBELL_DATA_MASK);
8742 +       } else if (ioc->bus_type == SAS && ioc->sas_discovery_quiesce_io) {
8743 +               if ((mpt_is_discovery_complete(ioc))) {
8744 +                       devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "clearing "
8745 +                           "discovery_quiesce_io flag\n", ioc->name));
8746 +                       ioc->sas_discovery_quiesce_io = 0;
8747 +               }
8748         }
8749  
8750   out:
8751 @@ -294,14 +378,13 @@ mpt_fault_reset_work(struct work_struct 
8752                 ioc = ioc->alt_ioc;
8753  
8754         /* rearm the timer */
8755 -       spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
8756 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
8757         if (ioc->reset_work_q)
8758                 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
8759                         msecs_to_jiffies(MPT_POLLING_INTERVAL));
8760 -       spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
8761 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
8762  }
8763  
8764 -
8765  /*
8766   *  Process turbo (context) reply...
8767   */
8768 @@ -354,9 +437,9 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa
8769  
8770         /*  Check for (valid) IO callback!  */
8771         if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
8772 -               MptCallbacks[cb_idx] == NULL) {
8773 +           MptCallbacks[cb_idx] == NULL) {
8774                 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
8775 -                               __func__, ioc->name, cb_idx);
8776 +                               __FUNCTION__, ioc->name, cb_idx);
8777                 goto out;
8778         }
8779  
8780 @@ -398,6 +481,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
8781  
8782         dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
8783                         ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
8784 +
8785         DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr);
8786  
8787          /*  Check/log IOC log info
8788 @@ -413,14 +497,17 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
8789                         mpt_sas_log_info(ioc, log_info);
8790         }
8791  
8792 +       /* TODO - add shost_attrs, or command line option, and
8793 +        * extend this to SAS/FC
8794 +        */
8795         if (ioc_stat & MPI_IOCSTATUS_MASK)
8796                 mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
8797  
8798         /*  Check for (valid) IO callback!  */
8799         if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
8800 -               MptCallbacks[cb_idx] == NULL) {
8801 +           MptCallbacks[cb_idx] == NULL) {
8802                 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
8803 -                               __func__, ioc->name, cb_idx);
8804 +                               __FUNCTION__, ioc->name, cb_idx);
8805                 freeme = 0;
8806                 goto out;
8807         }
8808 @@ -436,11 +523,11 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
8809         mb();
8810  }
8811  
8812 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8813  /**
8814   *     mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
8815   *     @irq: irq number (not used)
8816   *     @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
8817 + *     @r: pt_regs pointer (not used)
8818   *
8819   *     This routine is registered via the request_irq() kernel API call,
8820   *     and handles all interrupts generated from a specific MPT adapter
8821 @@ -452,7 +539,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
8822   *     This routine handles register-level access of the adapter but
8823   *     dispatches (calls) a protocol-specific callback routine to handle
8824   *     the protocol-specific details of the MPT request completion.
8825 - */
8826 + **/
8827  static irqreturn_t
8828  mpt_interrupt(int irq, void *bus_id)
8829  {
8830 @@ -478,9 +565,9 @@ mpt_interrupt(int irq, void *bus_id)
8831  
8832  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8833  /**
8834 - *     mpt_base_reply - MPT base driver's callback routine
8835 + *     mptbase_reply - MPT base driver's callback routine
8836   *     @ioc: Pointer to MPT_ADAPTER structure
8837 - *     @mf: Pointer to original MPT request frame
8838 + *     @req: Pointer to original MPT request frame
8839   *     @reply: Pointer to MPT reply frame (NULL if TurboReply)
8840   *
8841   *     MPT base driver's callback routine; all base driver
8842 @@ -491,122 +578,49 @@ mpt_interrupt(int irq, void *bus_id)
8843   *     should be freed, or 0 if it shouldn't.
8844   */
8845  static int
8846 -mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
8847 +mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
8848  {
8849 +       EventNotificationReply_t *pEventReply;
8850 +       u8 event;
8851 +       int evHandlers;
8852         int freereq = 1;
8853 -       u8 func;
8854 -
8855 -       dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply() called\n", ioc->name));
8856 -#ifdef CONFIG_FUSION_LOGGING
8857 -       if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) &&
8858 -                       !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
8859 -               dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n",
8860 -                   ioc->name, mf));
8861 -               DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf);
8862 -       }
8863 -#endif
8864 -
8865 -       func = reply->u.hdr.Function;
8866 -       dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n",
8867 -                       ioc->name, func));
8868 -
8869 -       if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
8870 -               EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
8871 -               int evHandlers = 0;
8872 -               int results;
8873 -
8874 -               results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
8875 -               if (results != evHandlers) {
8876 -                       /* CHECKME! Any special handling needed here? */
8877 -                       devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
8878 -                                       ioc->name, evHandlers, results));
8879 -               }
8880  
8881 -               /*
8882 -                *      Hmmm...  It seems that EventNotificationReply is an exception
8883 -                *      to the rule of one reply per request.
8884 -                */
8885 -               if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
8886 +       switch (reply->u.hdr.Function) {
8887 +       case MPI_FUNCTION_EVENT_NOTIFICATION:
8888 +               pEventReply = (EventNotificationReply_t *)reply;
8889 +               evHandlers = 0;
8890 +               ProcessEventNotification(ioc, pEventReply, &evHandlers);
8891 +               event = le32_to_cpu(pEventReply->Event) & 0xFF;
8892 +               if (pEventReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
8893                         freereq = 0;
8894 -               } else {
8895 -                       devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
8896 -                               ioc->name, pEvReply));
8897 -               }
8898 -
8899 -#ifdef CONFIG_PROC_FS
8900 -//             LogEvent(ioc, pEvReply);
8901 -#endif
8902 -
8903 -       } else if (func == MPI_FUNCTION_EVENT_ACK) {
8904 -               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n",
8905 -                               ioc->name));
8906 -       } else if (func == MPI_FUNCTION_CONFIG) {
8907 -               CONFIGPARMS *pCfg;
8908 -               unsigned long flags;
8909 -
8910 -               dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "config_complete (mf=%p,mr=%p)\n",
8911 -                               ioc->name, mf, reply));
8912 -
8913 -               pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
8914 -
8915 -               if (pCfg) {
8916 -                       /* disable timer and remove from linked list */
8917 -                       del_timer(&pCfg->timer);
8918 -
8919 -                       spin_lock_irqsave(&ioc->FreeQlock, flags);
8920 -                       list_del(&pCfg->linkage);
8921 -                       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
8922 -
8923 -                       /*
8924 -                        *      If IOC Status is SUCCESS, save the header
8925 -                        *      and set the status code to GOOD.
8926 -                        */
8927 -                       pCfg->status = MPT_CONFIG_ERROR;
8928 -                       if (reply) {
8929 -                               ConfigReply_t   *pReply = (ConfigReply_t *)reply;
8930 -                               u16              status;
8931 -
8932 -                               status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
8933 -                               dcprintk(ioc, printk(MYIOC_s_NOTE_FMT "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",
8934 -                                    ioc->name, status, le32_to_cpu(pReply->IOCLogInfo)));
8935 -
8936 -                               pCfg->status = status;
8937 -                               if (status == MPI_IOCSTATUS_SUCCESS) {
8938 -                                       if ((pReply->Header.PageType &
8939 -                                           MPI_CONFIG_PAGETYPE_MASK) ==
8940 -                                           MPI_CONFIG_PAGETYPE_EXTENDED) {
8941 -                                               pCfg->cfghdr.ehdr->ExtPageLength =
8942 -                                                   le16_to_cpu(pReply->ExtPageLength);
8943 -                                               pCfg->cfghdr.ehdr->ExtPageType =
8944 -                                                   pReply->ExtPageType;
8945 -                                       }
8946 -                                       pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
8947 -
8948 -                                       /* If this is a regular header, save PageLength. */
8949 -                                       /* LMP Do this better so not using a reserved field! */
8950 -                                       pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
8951 -                                       pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
8952 -                                       pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
8953 -                               }
8954 -                       }
8955 -
8956 -                       /*
8957 -                        *      Wake up the original calling thread
8958 -                        */
8959 -                       pCfg->wait_done = 1;
8960 -                       wake_up(&mpt_waitq);
8961 -               }
8962 -       } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
8963 -               /* we should be always getting a reply frame */
8964 -               memcpy(ioc->persist_reply_frame, reply,
8965 -                   min(MPT_DEFAULT_FRAME_SIZE,
8966 -                   4*reply->u.reply.MsgLength));
8967 -               del_timer(&ioc->persist_timer);
8968 -               ioc->persist_wait_done = 1;
8969 -               wake_up(&mpt_waitq);
8970 -       } else {
8971 -               printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
8972 -                               ioc->name, func);
8973 +               if (event != MPI_EVENT_EVENT_CHANGE)
8974 +                       break;
8975 +       case MPI_FUNCTION_CONFIG:
8976 +       case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
8977 +               ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
8978 +               if (reply) {
8979 +                       ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
8980 +                       memcpy(ioc->mptbase_cmds.reply, reply,
8981 +                           min(MPT_DEFAULT_FRAME_SIZE,
8982 +                               4 * reply->u.reply.MsgLength));
8983 +               }
8984 +               if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
8985 +                       ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
8986 +                       complete(&ioc->mptbase_cmds.done);
8987 +               } else
8988 +                       freereq = 0;
8989 +               if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_FREE_MF)
8990 +                       freereq = 1;
8991 +               break;
8992 +       case MPI_FUNCTION_EVENT_ACK:
8993 +               devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
8994 +                   "EventAck reply received\n", ioc->name));
8995 +               break;
8996 +       default:
8997 +               printk(MYIOC_s_ERR_FMT
8998 +                   "Unexpected msg function (=%02Xh) reply received!\n",
8999 +                   ioc->name, reply->u.hdr.Function);
9000 +               break;
9001         }
9002  
9003         /*
9004 @@ -616,7 +630,6 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
9005         return freereq;
9006  }
9007  
9008 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9009  /**
9010   *     mpt_register - Register protocol-specific main callback handler.
9011   *     @cbfunc: callback function pointer
9012 @@ -635,7 +648,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
9013   *     {N,...,7,6,5,...,1} if successful.
9014   *     A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
9015   *     considered an error by the caller.
9016 - */
9017 + **/
9018  u8
9019  mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
9020  {
9021 @@ -659,14 +672,13 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DR
9022         return last_drv_idx;
9023  }
9024  
9025 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9026  /**
9027   *     mpt_deregister - Deregister a protocol drivers resources.
9028   *     @cb_idx: previously registered callback handle
9029   *
9030   *     Each protocol-specific driver should call this routine when its
9031   *     module is unloaded.
9032 - */
9033 + **/
9034  void
9035  mpt_deregister(u8 cb_idx)
9036  {
9037 @@ -679,9 +691,9 @@ mpt_deregister(u8 cb_idx)
9038         }
9039  }
9040  
9041 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9042  /**
9043 - *     mpt_event_register - Register protocol-specific event callback handler.
9044 + *     mpt_event_register - Register protocol-specific event callback
9045 + *     handler.
9046   *     @cb_idx: previously registered (via mpt_register) callback handle
9047   *     @ev_cbfunc: callback function
9048   *
9049 @@ -689,7 +701,7 @@ mpt_deregister(u8 cb_idx)
9050   *     if/when they choose to be notified of MPT events.
9051   *
9052   *     Returns 0 for success.
9053 - */
9054 + **/
9055  int
9056  mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc)
9057  {
9058 @@ -700,15 +712,15 @@ mpt_event_register(u8 cb_idx, MPT_EVHAND
9059         return 0;
9060  }
9061  
9062 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9063  /**
9064 - *     mpt_event_deregister - Deregister protocol-specific event callback handler
9065 + *     mpt_event_deregister - Deregister protocol-specific event callback
9066 + *     handler.
9067   *     @cb_idx: previously registered callback handle
9068   *
9069   *     Each protocol-specific driver should call this routine
9070   *     when it does not (or can no longer) handle events,
9071   *     or when its module is unloaded.
9072 - */
9073 + **/
9074  void
9075  mpt_event_deregister(u8 cb_idx)
9076  {
9077 @@ -718,7 +730,6 @@ mpt_event_deregister(u8 cb_idx)
9078         MptEvHandlers[cb_idx] = NULL;
9079  }
9080  
9081 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9082  /**
9083   *     mpt_reset_register - Register protocol-specific IOC reset handler.
9084   *     @cb_idx: previously registered (via mpt_register) callback handle
9085 @@ -728,7 +739,7 @@ mpt_event_deregister(u8 cb_idx)
9086   *     if/when they choose to be notified of IOC resets.
9087   *
9088   *     Returns 0 for success.
9089 - */
9090 + **/
9091  int
9092  mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func)
9093  {
9094 @@ -739,7 +750,6 @@ mpt_reset_register(u8 cb_idx, MPT_RESETH
9095         return 0;
9096  }
9097  
9098 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9099  /**
9100   *     mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
9101   *     @cb_idx: previously registered callback handle
9102 @@ -747,7 +757,7 @@ mpt_reset_register(u8 cb_idx, MPT_RESETH
9103   *     Each protocol-specific driver should call this routine
9104   *     when it does not (or can no longer) handle IOC reset handling,
9105   *     or when its module is unloaded.
9106 - */
9107 + **/
9108  void
9109  mpt_reset_deregister(u8 cb_idx)
9110  {
9111 @@ -757,12 +767,11 @@ mpt_reset_deregister(u8 cb_idx)
9112         MptResetHandlers[cb_idx] = NULL;
9113  }
9114  
9115 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9116  /**
9117   *     mpt_device_driver_register - Register device driver hooks
9118   *     @dd_cbfunc: driver callbacks struct
9119   *     @cb_idx: MPT protocol driver index
9120 - */
9121 + **/
9122  int
9123  mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx)
9124  {
9125 @@ -776,20 +785,21 @@ mpt_device_driver_register(struct mpt_pc
9126  
9127         /* call per pci device probe entry point */
9128         list_for_each_entry(ioc, &ioc_list, list) {
9129 +               if (!pci_get_drvdata(ioc->pcidev))
9130 +                       continue;
9131                 id = ioc->pcidev->driver ?
9132                     ioc->pcidev->driver->id_table : NULL;
9133                 if (dd_cbfunc->probe)
9134                         dd_cbfunc->probe(ioc->pcidev, id);
9135 -        }
9136 +       }
9137  
9138         return 0;
9139  }
9140  
9141 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9142  /**
9143   *     mpt_device_driver_deregister - DeRegister device driver hooks
9144   *     @cb_idx: MPT protocol driver index
9145 - */
9146 + **/
9147  void
9148  mpt_device_driver_deregister(u8 cb_idx)
9149  {
9150 @@ -809,19 +819,15 @@ mpt_device_driver_deregister(u8 cb_idx)
9151         MptDeviceDriverHandlers[cb_idx] = NULL;
9152  }
9153  
9154 -
9155 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9156  /**
9157 - *     mpt_get_msg_frame - Obtain an MPT request frame from the pool
9158 + *     mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
9159 + *     allocated per MPT adapter.
9160   *     @cb_idx: Handle of registered MPT protocol driver
9161   *     @ioc: Pointer to MPT adapter structure
9162   *
9163 - *     Obtain an MPT request frame from the pool (of 1024) that are
9164 - *     allocated per MPT adapter.
9165 - *
9166   *     Returns pointer to a MPT request frame or %NULL if none are available
9167   *     or IOC is not active.
9168 - */
9169 + **/
9170  MPT_FRAME_HDR*
9171  mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc)
9172  {
9173 @@ -851,7 +857,6 @@ mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER
9174                 mf->u.frame.linkage.arg1 = 0;
9175                 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;  /* byte */
9176                 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
9177 -                                                               /* u16! */
9178                 req_idx = req_offset / ioc->req_sz;
9179                 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
9180                 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
9181 @@ -881,16 +886,16 @@ mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER
9182         return mf;
9183  }
9184  
9185 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9186  /**
9187 - *     mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC
9188 + *     mpt_put_msg_frame - Send a protocol specific MPT request frame
9189 + *     to a IOC.
9190   *     @cb_idx: Handle of registered MPT protocol driver
9191   *     @ioc: Pointer to MPT adapter structure
9192   *     @mf: Pointer to MPT request frame
9193   *
9194 - *     This routine posts an MPT request frame to the request post FIFO of a
9195 + *     This routine posts a MPT request frame to the request post FIFO of a
9196   *     specific MPT adapter.
9197 - */
9198 + **/
9199  void
9200  mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
9201  {
9202 @@ -901,14 +906,14 @@ mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER
9203         /* ensure values are reset properly! */
9204         mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;          /* byte */
9205         req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
9206 -                                                               /* u16! */
9207         req_idx = req_offset / ioc->req_sz;
9208         mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
9209         mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
9210  
9211         DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
9212  
9213 -       mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
9214 +       mf_dma_addr = (ioc->req_frames_low_dma + req_offset) |
9215 +           ioc->RequestNB[req_idx];
9216         dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
9217             "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
9218             ioc->RequestNB[req_idx]));
9219 @@ -916,15 +921,13 @@ mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER
9220  }
9221  
9222  /**
9223 - *     mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame
9224 + *     mpt_put_msg_frame_hi_pri - Send a protocol specific MPT request frame
9225 + *     to a IOC using hi priority request queue.
9226   *     @cb_idx: Handle of registered MPT protocol driver
9227   *     @ioc: Pointer to MPT adapter structure
9228   *     @mf: Pointer to MPT request frame
9229   *
9230 - *     Send a protocol-specific MPT request frame to an IOC using
9231 - *     hi-priority request queue.
9232 - *
9233 - *     This routine posts an MPT request frame to the request post FIFO of a
9234 + *     This routine posts a MPT request frame to the request post FIFO of a
9235   *     specific MPT adapter.
9236   **/
9237  void
9238 @@ -949,7 +952,6 @@ mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_
9239         CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr);
9240  }
9241  
9242 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9243  /**
9244   *     mpt_free_msg_frame - Place MPT request frame back on FreeQ.
9245   *     @handle: Handle of registered MPT protocol driver
9246 @@ -958,7 +960,7 @@ mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_
9247   *
9248   *     This routine places a MPT request frame back on the MPT adapter's
9249   *     FreeQ.
9250 - */
9251 + **/
9252  void
9253  mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
9254  {
9255 @@ -966,43 +968,144 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT
9256  
9257         /*  Put Request back on FreeQ!  */
9258         spin_lock_irqsave(&ioc->FreeQlock, flags);
9259 -       mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
9260 +       if (cpu_to_le32(mf->u.frame.linkage.arg1) == 0xdeadbeaf)
9261 +               goto out;
9262 +       mf->u.frame.linkage.arg1 = cpu_to_le32(0xdeadbeaf); /* signature to know if this mf is freed */
9263         list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
9264  #ifdef MFCNT
9265         ioc->mfcnt--;
9266  #endif
9267 + out:
9268         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
9269  }
9270  
9271 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9272  /**
9273 - *     mpt_add_sge - Place a simple SGE at address pAddr.
9274 + *     mpt_add_sge - Place a simple 32 bit SGE at address pAddr.
9275   *     @pAddr: virtual address for SGE
9276   *     @flagslength: SGE flags and data transfer length
9277   *     @dma_addr: Physical address
9278   *
9279   *     This routine places a MPT request frame back on the MPT adapter's
9280   *     FreeQ.
9281 - */
9282 -void
9283 + **/
9284 +static void
9285  mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
9286  {
9287 -       if (sizeof(dma_addr_t) == sizeof(u64)) {
9288 -               SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
9289 -               u32 tmp = dma_addr & 0xFFFFFFFF;
9290 +       SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
9291 +       pSge->FlagsLength = cpu_to_le32(flagslength);
9292 +       pSge->Address = cpu_to_le32(dma_addr);
9293 +}
9294  
9295 -               pSge->FlagsLength = cpu_to_le32(flagslength);
9296 -               pSge->Address.Low = cpu_to_le32(tmp);
9297 -               tmp = (u32) ((u64)dma_addr >> 32);
9298 -               pSge->Address.High = cpu_to_le32(tmp);
9299  
9300 -       } else {
9301 -               SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
9302 -               pSge->FlagsLength = cpu_to_le32(flagslength);
9303 -               pSge->Address = cpu_to_le32(dma_addr);
9304 +/**
9305 + *     mpt_add_sge_64bit - Place a simple 64 bit SGE at address pAddr.
9306 + *     @pAddr: virtual address for SGE
9307 + *     @flagslength: SGE flags and data transfer length
9308 + *     @dma_addr: Physical address
9309 + *
9310 + *     This routine places a MPT request frame back on the MPT adapter's
9311 + *     FreeQ.
9312 + **/
9313 +static void
9314 +mpt_add_sge_64bit(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
9315 +{
9316 +       SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
9317 +       u32 tmp;
9318 +
9319 +       tmp = dma_addr & 0xFFFFFFFF;
9320 +       pSge->Address.Low = cpu_to_le32(tmp);
9321 +       tmp = (u32) ((u64)dma_addr >> 32);
9322 +       pSge->Address.High = cpu_to_le32(tmp);
9323 +       pSge->FlagsLength = cpu_to_le32(
9324 +               (flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
9325 +}
9326 +
9327 +
9328 +/**
9329 + *     mpt_add_sge_64bit_1078 - Place a simple 64 bit SGE at address pAddr
9330 + *     (1078 workaround).
9331 + *     @pAddr: virtual address for SGE
9332 + *     @flagslength: SGE flags and data transfer length
9333 + *     @dma_addr: Physical address
9334 + *
9335 + *     This routine places a MPT request frame back on the MPT adapter's
9336 + *     FreeQ.
9337 + **/
9338 +static void
9339 +mpt_add_sge_64bit_1078(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
9340 +{
9341 +       SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
9342 +       u32 tmp;
9343 +
9344 +       tmp = dma_addr & 0xFFFFFFFF;
9345 +       pSge->Address.Low = cpu_to_le32(tmp);
9346 +       tmp = (u32) ((u64)dma_addr >> 32);
9347 +
9348 +       /*
9349 +        * 1078 errata workaround for the 36GB limitation
9350 +        */
9351 +       if ((((u64)dma_addr + MPI_SGE_LENGTH(flagslength)) >> 32)  == 9) {
9352 +               flagslength |=
9353 +                   MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LOCAL_ADDRESS);
9354 +               tmp |= (1<<31);
9355 +               if (mpt_debug_level & MPT_DEBUG_36GB_MEM)
9356 +                       printk(KERN_DEBUG "1078 P0M2 addressing for "
9357 +                           "addr = 0x%llx len = %d\n",
9358 +                           (unsigned long long)dma_addr,
9359 +                           MPI_SGE_LENGTH(flagslength));
9360         }
9361 +
9362 +       pSge->Address.High = cpu_to_le32(tmp);
9363 +       pSge->FlagsLength = cpu_to_le32(
9364 +               (flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
9365 +}
9366 +
9367 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9368 +/**
9369 + *     mpt_add_chain - Place a 32 bit chain SGE at address pAddr.
9370 + *     @pAddr: virtual address for SGE
9371 + *     @next: nextChainOffset value (u32's)
9372 + *     @length: length of next SGL segment
9373 + *     @dma_addr: Physical address
9374 + *
9375 + */
9376 +static void
9377 +mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
9378 +{
9379 +               SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
9380 +               pChain->Length = cpu_to_le16(length);
9381 +               pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
9382 +               pChain->NextChainOffset = next;
9383 +               pChain->Address = cpu_to_le32(dma_addr);
9384 +}
9385 +
9386 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9387 +/**
9388 + *     mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr.
9389 + *     @pAddr: virtual address for SGE
9390 + *     @next: nextChainOffset value (u32's)
9391 + *     @length: length of next SGL segment
9392 + *     @dma_addr: Physical address
9393 + *
9394 + */
9395 +static void
9396 +mpt_add_chain_64bit(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
9397 +{
9398 +               SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
9399 +               u32 tmp = dma_addr & 0xFFFFFFFF;
9400 +
9401 +               pChain->Length = cpu_to_le16(length);
9402 +               pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT |
9403 +                                MPI_SGE_FLAGS_64_BIT_ADDRESSING);
9404 +
9405 +               pChain->NextChainOffset = next;
9406 +
9407 +               pChain->Address.Low = cpu_to_le32(tmp);
9408 +               tmp = (u32) ((u64)dma_addr >> 32);
9409 +               pChain->Address.High = cpu_to_le32(tmp);
9410  }
9411  
9412 +
9413  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9414  /**
9415   *     mpt_send_handshake_request - Send MPT request via doorbell handshake method.
9416 @@ -1019,11 +1122,11 @@ mpt_add_sge(char *pAddr, u32 flagslength
9417   *     request which are greater than 1 byte in size.
9418   *
9419   *     Returns 0 for success, non-zero for failure.
9420 - */
9421 + **/
9422  int
9423  mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
9424  {
9425 -       int     r = 0;
9426 +       int      r = 0;
9427         u8      *req_as_bytes;
9428         int      ii;
9429  
9430 @@ -1038,7 +1141,7 @@ mpt_send_handshake_request(u8 cb_idx, MP
9431          * is in proper (pre-alloc'd) request buffer range...
9432          */
9433         ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
9434 -       if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
9435 +       if (ii >= 0 && ii < ioc->req_depth) {
9436                 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
9437                 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
9438                 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
9439 @@ -1096,7 +1199,6 @@ mpt_send_handshake_request(u8 cb_idx, MP
9440         return r;
9441  }
9442  
9443 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9444  /**
9445   * mpt_host_page_access_control - control the IOC's Host Page Buffer access
9446   * @ioc: Pointer to MPT adapter structure
9447 @@ -1113,8 +1215,7 @@ mpt_send_handshake_request(u8 cb_idx, MP
9448   * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
9449   *
9450   * Returns 0 for success, non-zero for failure.
9451 - */
9452 -
9453 + **/
9454  static int
9455  mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
9456  {
9457 @@ -1139,7 +1240,6 @@ mpt_host_page_access_control(MPT_ADAPTER
9458                 return 0;
9459  }
9460  
9461 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9462  /**
9463   *     mpt_host_page_alloc - allocate system memory for the fw
9464   *     @ioc: Pointer to pointer to IOC adapter
9465 @@ -1147,7 +1247,7 @@ mpt_host_page_access_control(MPT_ADAPTER
9466   *
9467   *     If we already allocated memory in past, then resend the same pointer.
9468   *     Returns 0 for success, non-zero for failure.
9469 - */
9470 + **/
9471  static int
9472  mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
9473  {
9474 @@ -1171,7 +1271,7 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pI
9475                             host_page_buffer_sz,
9476                             &ioc->HostPageBuffer_dma)) != NULL) {
9477  
9478 -                               dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
9479 +                               dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
9480                                     "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
9481                                     ioc->name, ioc->HostPageBuffer,
9482                                     (u32)ioc->HostPageBuffer_dma,
9483 @@ -1195,21 +1295,16 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pI
9484         psge = (char *)&ioc_init->HostPageBufferSGE;
9485         flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
9486             MPI_SGE_FLAGS_SYSTEM_ADDRESS |
9487 -           MPI_SGE_FLAGS_32_BIT_ADDRESSING |
9488             MPI_SGE_FLAGS_HOST_TO_IOC |
9489             MPI_SGE_FLAGS_END_OF_BUFFER;
9490 -       if (sizeof(dma_addr_t) == sizeof(u64)) {
9491 -           flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
9492 -       }
9493         flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
9494         flags_length |= ioc->HostPageBuffer_sz;
9495 -       mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
9496 +       ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
9497         ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
9498  
9499  return 0;
9500  }
9501  
9502 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9503  /**
9504   *     mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
9505   *     @iocid: IOC unique identifier (integer)
9506 @@ -1220,7 +1315,7 @@ return 0;
9507   *
9508   *     Returns iocid and sets iocpp if iocid is found.
9509   *     Returns -1 if iocid is not found.
9510 - */
9511 + **/
9512  int
9513  mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
9514  {
9515 @@ -1493,7 +1588,6 @@ mpt_mapresources(MPT_ADAPTER *ioc)
9516         unsigned long    port;
9517         u32              msize;
9518         u32              psize;
9519 -       u8               revision;
9520         int              r = -ENODEV;
9521         struct pci_dev *pdev;
9522  
9523 @@ -1509,24 +1603,39 @@ mpt_mapresources(MPT_ADAPTER *ioc)
9524                     "MEM failed\n", ioc->name);
9525                 return r;
9526         }
9527 +       if (sizeof(dma_addr_t) > 4) {
9528 +               const uint64_t required_mask = dma_get_required_mask(&pdev->dev);
9529 +               if (required_mask > DMA_32BIT_MASK
9530 +                   && !pci_set_dma_mask(pdev, DMA_64BIT_MASK)
9531 +                   && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
9532 +                       ioc->dma_mask = DMA_64BIT_MASK;
9533 +                       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
9534 +                           ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
9535 +                           ioc->name));
9536 +               } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
9537 +                   && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
9538 +                       ioc->dma_mask = DMA_32BIT_MASK;
9539 +                       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
9540 +                           ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
9541 +                           ioc->name));
9542 +               } else {
9543 +                       printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
9544 +                           ioc->name, pci_name(pdev));
9545 +                       return r;
9546 +               }
9547  
9548 -       pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
9549 -
9550 -       if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)
9551 -           && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
9552 -               dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
9553 -                   ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
9554 -                   ioc->name));
9555 -       } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
9556 -           && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
9557 -               dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
9558 -                   ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
9559 -                   ioc->name));
9560         } else {
9561 -               printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
9562 -                   ioc->name, pci_name(pdev));
9563 -               pci_release_selected_regions(pdev, ioc->bars);
9564 -               return r;
9565 +               if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
9566 +                   && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
9567 +                       ioc->dma_mask = DMA_32BIT_MASK;
9568 +                       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
9569 +                           ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
9570 +                           ioc->name));
9571 +               } else {
9572 +                       printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
9573 +                           ioc->name, pci_name(pdev));
9574 +                       return r;
9575 +               }
9576         }
9577  
9578         mem_phys = msize = 0;
9579 @@ -1554,7 +1663,7 @@ mpt_mapresources(MPT_ADAPTER *ioc)
9580         mem = ioremap(mem_phys, msize);
9581         if (mem == NULL) {
9582                 printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
9583 -                       " memory!\n", ioc->name);
9584 +                      "memory!\n", ioc->name);
9585                 return -EINVAL;
9586         }
9587         ioc->memmap = mem;
9588 @@ -1565,13 +1674,15 @@ mpt_mapresources(MPT_ADAPTER *ioc)
9589         ioc->chip = (SYSIF_REGS __iomem *)mem;
9590  
9591         /* Save Port IO values in case we need to do downloadboot */
9592 -       ioc->pio_mem_phys = port;
9593 -       ioc->pio_chip = (SYSIF_REGS __iomem *)port;
9594 +       {
9595 +               u8 *pmem = (u8*)port;
9596 +               ioc->pio_mem_phys = port;
9597 +               ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
9598 +       }
9599  
9600         return 0;
9601  }
9602  
9603 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9604  /**
9605   *     mpt_attach - Install a PCI intelligent MPT adapter.
9606   *     @pdev: Pointer to pci_dev structure
9607 @@ -1588,7 +1699,7 @@ mpt_mapresources(MPT_ADAPTER *ioc)
9608   *     Returns 0 for success, non-zero for failure.
9609   *
9610   *     TODO: Add support for polled controllers
9611 - */
9612 + **/
9613  int
9614  mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
9615  {
9616 @@ -1610,6 +1721,7 @@ mpt_attach(struct pci_dev *pdev, const s
9617  
9618         ioc->id = mpt_ids++;
9619         sprintf(ioc->name, "ioc%d", ioc->id);
9620 +       dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n"));
9621  
9622         /*
9623          * set initial debug level
9624 @@ -1620,7 +1732,6 @@ mpt_attach(struct pci_dev *pdev, const s
9625         if (mpt_debug_level)
9626                 printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
9627  
9628 -       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
9629  
9630         ioc->pcidev = pdev;
9631         if (mpt_mapresources(ioc)) {
9632 @@ -1628,14 +1739,34 @@ mpt_attach(struct pci_dev *pdev, const s
9633                 return r;
9634         }
9635  
9636 +       /*
9637 +        * Setting up proper handlers for scatter gather handling
9638 +        */
9639 +       if (ioc->dma_mask == DMA_64BIT_MASK) {
9640 +               if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
9641 +                       ioc->add_sge = &mpt_add_sge_64bit_1078;
9642 +               else
9643 +                       ioc->add_sge = &mpt_add_sge_64bit;
9644 +               ioc->add_chain = &mpt_add_chain_64bit;
9645 +               ioc->sg_addr_size = 8;
9646 +       } else {
9647 +               ioc->add_sge = &mpt_add_sge;
9648 +               ioc->add_chain = &mpt_add_chain;
9649 +               ioc->sg_addr_size = 4;
9650 +       }
9651 +       ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
9652 +
9653         ioc->alloc_total = sizeof(MPT_ADAPTER);
9654         ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;           /* avoid div by zero! */
9655         ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
9656  
9657 -       ioc->pcidev = pdev;
9658 -       ioc->diagPending = 0;
9659 -       spin_lock_init(&ioc->diagLock);
9660 -       spin_lock_init(&ioc->initializing_hba_lock);
9661 +       spin_lock_init(&ioc->taskmgmt_lock);
9662 +       mutex_init(&ioc->internal_cmds.mutex);
9663 +       init_completion(&ioc->internal_cmds.done);
9664 +       mutex_init(&ioc->mptbase_cmds.mutex);
9665 +       init_completion(&ioc->mptbase_cmds.done);
9666 +       mutex_init(&ioc->taskmgmt_cmds.mutex);
9667 +       init_completion(&ioc->taskmgmt_cmds.done);
9668  
9669         /* Initialize the event logging.
9670          */
9671 @@ -1648,16 +1779,13 @@ mpt_attach(struct pci_dev *pdev, const s
9672         ioc->mfcnt = 0;
9673  #endif
9674  
9675 +       ioc->sh = NULL;
9676         ioc->cached_fw = NULL;
9677  
9678         /* Initilize SCSI Config Data structure
9679          */
9680         memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
9681  
9682 -       /* Initialize the running configQ head.
9683 -        */
9684 -       INIT_LIST_HEAD(&ioc->configQ);
9685 -
9686         /* Initialize the fc rport list head.
9687          */
9688         INIT_LIST_HEAD(&ioc->fc_rports);
9689 @@ -1665,11 +1793,10 @@ mpt_attach(struct pci_dev *pdev, const s
9690         /* Find lookup slot. */
9691         INIT_LIST_HEAD(&ioc->list);
9692  
9693 -
9694 -       /* Initialize workqueue */
9695 +       /* Initialize work */
9696         INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
9697 -       spin_lock_init(&ioc->fault_reset_work_lock);
9698  
9699 +       /* Initialize workqueue */
9700         snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name),
9701                  "mpt_poll_%d", ioc->id);
9702         ioc->reset_work_q =
9703 @@ -1682,8 +1809,8 @@ mpt_attach(struct pci_dev *pdev, const s
9704                 return -ENOMEM;
9705         }
9706  
9707 -       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
9708 -           ioc->name, &ioc->facts, &ioc->pfacts[0]));
9709 +       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts @ %p, pfacts[0] @ %p\n",
9710 +               ioc->name, &ioc->facts, &ioc->pfacts[0]));
9711  
9712         pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
9713         mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
9714 @@ -1703,14 +1830,14 @@ mpt_attach(struct pci_dev *pdev, const s
9715         case MPI_MANUFACTPAGE_DEVICEID_FC929X:
9716                 if (revision < XL_929) {
9717                         /* 929X Chip Fix. Set Split transactions level
9718 -                       * for PCIX. Set MOST bits to zero.
9719 -                       */
9720 +                       * for PCIX. Set MOST bits to zero.
9721 +                       */
9722                         pci_read_config_byte(pdev, 0x6a, &pcixcmd);
9723                         pcixcmd &= 0x8F;
9724                         pci_write_config_byte(pdev, 0x6a, pcixcmd);
9725                 } else {
9726                         /* 929XL Chip Fix. Set MMRBC to 0x08.
9727 -                       */
9728 +                       */
9729                         pci_read_config_byte(pdev, 0x6a, &pcixcmd);
9730                         pcixcmd |= 0x08;
9731                         pci_write_config_byte(pdev, 0x6a, pcixcmd);
9732 @@ -1728,6 +1855,7 @@ mpt_attach(struct pci_dev *pdev, const s
9733                 ioc->bus_type = FC;
9734                 break;
9735  
9736 +
9737         case MPI_MANUFACTPAGE_DEVID_53C1030:
9738                 /* 1030 Chip Fix. Disable Split transactions
9739                  * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
9740 @@ -1745,22 +1873,33 @@ mpt_attach(struct pci_dev *pdev, const s
9741         case MPI_MANUFACTPAGE_DEVID_SAS1064:
9742         case MPI_MANUFACTPAGE_DEVID_SAS1068:
9743                 ioc->errata_flag_1064 = 1;
9744 +               ioc->bus_type = SAS;
9745 +               break;
9746  
9747         case MPI_MANUFACTPAGE_DEVID_SAS1064E:
9748         case MPI_MANUFACTPAGE_DEVID_SAS1068E:
9749         case MPI_MANUFACTPAGE_DEVID_SAS1078:
9750                 ioc->bus_type = SAS;
9751 +               break;
9752         }
9753  
9754 -       if (mpt_msi_enable == -1) {
9755 -               /* Enable on SAS, disable on FC and SPI */
9756 -               if (ioc->bus_type == SAS)
9757 -                       ioc->msi_enable = 1;
9758 -               else
9759 -                       ioc->msi_enable = 0;
9760 -       } else
9761 -               /* follow flag: 0 - disable; 1 - enable */
9762 -               ioc->msi_enable = mpt_msi_enable;
9763 +       switch (ioc->bus_type) {
9764 +       case SAS:
9765 +               ioc->msi_enable = mpt_msi_enable_sas;
9766 +               break;
9767 +
9768 +       case SPI:
9769 +               ioc->msi_enable = mpt_msi_enable_spi;
9770 +               break;
9771 +
9772 +       case FC:
9773 +               ioc->msi_enable = mpt_msi_enable_fc;
9774 +               break;
9775 +
9776 +       default:
9777 +               ioc->msi_enable = 0;
9778 +               break;
9779 +       }
9780  
9781         if (ioc->errata_flag_1064)
9782                 pci_disable_io_access(pdev);
9783 @@ -1772,9 +1911,6 @@ mpt_attach(struct pci_dev *pdev, const s
9784         ioc->active = 0;
9785         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
9786  
9787 -       /* Set IOC ptr in the pcidev's driver data. */
9788 -       pci_set_drvdata(ioc->pcidev, ioc);
9789 -
9790         /* Set lookup ptr. */
9791         list_add_tail(&ioc->list, &ioc_list);
9792  
9793 @@ -1782,10 +1918,17 @@ mpt_attach(struct pci_dev *pdev, const s
9794          */
9795         mpt_detect_bound_ports(ioc, pdev);
9796  
9797 +
9798 +       INIT_LIST_HEAD(&ioc->fw_event_list);
9799 +       spin_lock_init(&ioc->fw_event_lock);
9800 +       snprintf(ioc->fw_event_q_name, sizeof(ioc->fw_event_q_name),
9801 +                "mpt/%d", ioc->id);
9802 +       ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name);
9803 +
9804         if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
9805             CAN_SLEEP)) != 0){
9806                 printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
9807 -                   ioc->name, r);
9808 +                      ioc->name, r);
9809  
9810                 list_del(&ioc->list);
9811                 if (ioc->alt_ioc)
9812 @@ -1796,7 +1939,8 @@ mpt_attach(struct pci_dev *pdev, const s
9813  
9814                 destroy_workqueue(ioc->reset_work_q);
9815                 ioc->reset_work_q = NULL;
9816 -
9817 +               destroy_workqueue(ioc->fw_event_q);
9818 +               ioc->fw_event_q = NULL;
9819                 kfree(ioc);
9820                 pci_set_drvdata(pdev, NULL);
9821                 return r;
9822 @@ -1832,35 +1976,37 @@ mpt_attach(struct pci_dev *pdev, const s
9823         if (!ioc->alt_ioc)
9824                 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
9825                         msecs_to_jiffies(MPT_POLLING_INTERVAL));
9826 -
9827         return 0;
9828  }
9829  
9830 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9831  /**
9832   *     mpt_detach - Remove a PCI intelligent MPT adapter.
9833   *     @pdev: Pointer to pci_dev structure
9834 - */
9835 -
9836 + **/
9837  void
9838  mpt_detach(struct pci_dev *pdev)
9839  {
9840         MPT_ADAPTER     *ioc = pci_get_drvdata(pdev);
9841         char pname[32];
9842         u8 cb_idx;
9843 -       unsigned long flags;
9844 +       unsigned long    flags;
9845         struct workqueue_struct *wq;
9846  
9847         /*
9848          * Stop polling ioc for fault condition
9849          */
9850 -       spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
9851 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
9852         wq = ioc->reset_work_q;
9853         ioc->reset_work_q = NULL;
9854 -       spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
9855 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
9856         cancel_delayed_work(&ioc->fault_reset_work);
9857         destroy_workqueue(wq);
9858  
9859 +       spin_lock_irqsave(&ioc->fw_event_lock, flags);
9860 +       wq = ioc->fw_event_q;
9861 +       ioc->fw_event_q = NULL;
9862 +       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
9863 +       destroy_workqueue(wq);
9864  
9865         sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
9866         remove_proc_entry(pname, NULL);
9867 @@ -1877,32 +2023,18 @@ mpt_detach(struct pci_dev *pdev)
9868                 }
9869         }
9870  
9871 -       /* Disable interrupts! */
9872 -       CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
9873 -
9874 -       ioc->active = 0;
9875 -       synchronize_irq(pdev->irq);
9876 -
9877 -       /* Clear any lingering interrupt */
9878 -       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
9879 -
9880 -       CHIPREG_READ32(&ioc->chip->IntStatus);
9881 -
9882 -       mpt_adapter_dispose(ioc);
9883 -
9884 -       pci_set_drvdata(pdev, NULL);
9885 -}
9886 +       mpt_adapter_dispose(ioc);
9887 +}
9888  
9889  /**************************************************************************
9890   * Power Management
9891   */
9892  #ifdef CONFIG_PM
9893 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9894  /**
9895   *     mpt_suspend - Fusion MPT base driver suspend routine.
9896   *     @pdev: Pointer to pci_dev structure
9897   *     @state: new state to enter
9898 - */
9899 + **/
9900  int
9901  mpt_suspend(struct pci_dev *pdev, pm_message_t state)
9902  {
9903 @@ -1923,7 +2055,6 @@ mpt_suspend(struct pci_dev *pdev, pm_mes
9904         /* disable interrupts */
9905         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
9906         ioc->active = 0;
9907 -
9908         /* Clear any lingering interrupt */
9909         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
9910  
9911 @@ -1938,11 +2069,10 @@ mpt_suspend(struct pci_dev *pdev, pm_mes
9912         return 0;
9913  }
9914  
9915 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9916  /**
9917   *     mpt_resume - Fusion MPT base driver resume routine.
9918   *     @pdev: Pointer to pci_dev structure
9919 - */
9920 + **/
9921  int
9922  mpt_resume(struct pci_dev *pdev)
9923  {
9924 @@ -1962,6 +2092,22 @@ mpt_resume(struct pci_dev *pdev)
9925         err = mpt_mapresources(ioc);
9926         if (err)
9927                 return err;
9928 +
9929 +       if (ioc->dma_mask == DMA_64BIT_MASK) {
9930 +               if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
9931 +                       ioc->add_sge = &mpt_add_sge_64bit_1078;
9932 +               else
9933 +                       ioc->add_sge = &mpt_add_sge_64bit;
9934 +               ioc->add_chain = &mpt_add_chain_64bit;
9935 +               ioc->sg_addr_size = 8;
9936 +       } else {
9937 +
9938 +               ioc->add_sge = &mpt_add_sge;
9939 +               ioc->add_chain = &mpt_add_chain;
9940 +               ioc->sg_addr_size = 4;
9941 +       }
9942 +       ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
9943 +
9944  
9945         printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
9946             ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
9947 @@ -1986,9 +2132,7 @@ mpt_resume(struct pci_dev *pdev)
9948  
9949         /* bring ioc to operational state */
9950         printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
9951 -       recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
9952 -                                                CAN_SLEEP);
9953 -       if (recovery_state != 0)
9954 +       if ((recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0)
9955                 printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
9956                     "error:[%x]\n", ioc->name, recovery_state);
9957         else
9958 @@ -1996,7 +2140,6 @@ mpt_resume(struct pci_dev *pdev)
9959                     "pci-resume: success\n", ioc->name);
9960   out:
9961         return 0;
9962 -
9963  }
9964  #endif
9965  
9966 @@ -2015,7 +2158,6 @@ mpt_signal_reset(u8 index, MPT_ADAPTER *
9967         return (MptResetHandlers[index])(ioc, reset_phase);
9968  }
9969  
9970 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9971  /**
9972   *     mpt_do_ioc_recovery - Initialize or recover MPT adapter.
9973   *     @ioc: Pointer to MPT adapter structure
9974 @@ -2034,9 +2176,7 @@ mpt_signal_reset(u8 index, MPT_ADAPTER *
9975   *             -2 if READY but IOCFacts Failed
9976   *             -3 if READY but PrimeIOCFifos Failed
9977   *             -4 if READY but IOCInit Failed
9978 - *             -5 if failed to enable_device and/or request_selected_regions
9979 - *             -6 if failed to upload firmware
9980 - */
9981 + **/
9982  static int
9983  mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
9984  {
9985 @@ -2045,14 +2185,12 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
9986         int      hard;
9987         int      rc=0;
9988         int      ii;
9989 -       u8       cb_idx;
9990 -       int      handlers;
9991         int      ret = 0;
9992         int      reset_alt_ioc_active = 0;
9993         int      irq_allocated = 0;
9994         u8      *a;
9995  
9996 -       printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
9997 +       printk(MYIOC_s_DEBUG_FMT "Initiating %s\n", ioc->name,
9998             reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
9999  
10000         /* Disable reply interrupts (also blocks FreeQ) */
10001 @@ -2060,7 +2198,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10002         ioc->active = 0;
10003  
10004         if (ioc->alt_ioc) {
10005 -               if (ioc->alt_ioc->active)
10006 +               if (ioc->alt_ioc->active || reason == MPT_HOSTEVENT_IOC_RECOVER)
10007                         reset_alt_ioc_active = 1;
10008  
10009                 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
10010 @@ -2079,16 +2217,17 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10011  
10012                         if (reset_alt_ioc_active && ioc->alt_ioc) {
10013                                 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
10014 -                               dprintk(ioc, printk(MYIOC_s_INFO_FMT
10015 -                                   "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
10016 +                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": alt-ioc reply irq re-enabled\n",
10017 +                                   ioc->alt_ioc->name));
10018                                 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
10019                                 ioc->alt_ioc->active = 1;
10020                         }
10021  
10022                 } else {
10023 -                       printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name);
10024 +                       printk(MYIOC_s_WARN_FMT "NOT READY WARNING!\n", ioc->name);
10025                 }
10026 -               return -1;
10027 +               ret = -1;
10028 +               goto out;
10029         }
10030  
10031         /* hard_reset_done = 0 if a soft reset was performed
10032 @@ -2098,7 +2237,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10033                 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
10034                         alt_ioc_ready = 1;
10035                 else
10036 -                       printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name);
10037 +                       printk(MYIOC_s_WARN_FMT
10038 +                           ": alt-ioc Not ready WARNING!\n", ioc->alt_ioc->name);
10039         }
10040  
10041         for (ii=0; ii<5; ii++) {
10042 @@ -2156,23 +2296,28 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10043                 if (ioc->pcidev->irq) {
10044                         if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
10045                                 printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
10046 -                                   ioc->name);
10047 +                                       ioc->name);
10048                         else
10049                                 ioc->msi_enable = 0;
10050 +
10051                         rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
10052                             IRQF_SHARED, ioc->name, ioc);
10053                         if (rc < 0) {
10054                                 printk(MYIOC_s_ERR_FMT "Unable to allocate "
10055 -                                   "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
10056 +                                       "interrupt %d!\n", ioc->name,
10057 +                                       ioc->pcidev->irq);
10058                                 if (ioc->msi_enable)
10059                                         pci_disable_msi(ioc->pcidev);
10060 -                               return -EBUSY;
10061 +                               ret = -EBUSY;
10062 +                               goto out;
10063                         }
10064                         irq_allocated = 1;
10065                         ioc->pci_irq = ioc->pcidev->irq;
10066                         pci_set_master(ioc->pcidev);            /* ?? */
10067 -                       dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt "
10068 -                           "%d\n", ioc->name, ioc->pcidev->irq));
10069 +                       pci_set_drvdata(ioc->pcidev, ioc);
10070 +                       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
10071 +                           "installed at interrupt %d\n", ioc->name,
10072 +                           ioc->pcidev->irq));
10073                 }
10074         }
10075  
10076 @@ -2181,18 +2326,22 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10077          * init as upper addresses are needed for init.
10078          * If fails, continue with alt-ioc processing
10079          */
10080 +       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "PrimeIocFifos\n",
10081 +           ioc->name));
10082         if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
10083                 ret = -3;
10084  
10085         /* May need to check/upload firmware & data here!
10086          * If fails, continue with alt-ioc processing
10087          */
10088 +       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendIocInit\n",
10089 +           ioc->name));
10090         if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
10091                 ret = -4;
10092  // NEW!
10093         if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
10094 -               printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n",
10095 -                   ioc->alt_ioc->name, rc);
10096 +               printk(MYIOC_s_WARN_FMT ": alt-ioc (%d) FIFO mgmt alloc WARNING!\n",
10097 +                               ioc->alt_ioc->name, rc);
10098                 alt_ioc_ready = 0;
10099                 reset_alt_ioc_active = 0;
10100         }
10101 @@ -2201,15 +2350,16 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10102                 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
10103                         alt_ioc_ready = 0;
10104                         reset_alt_ioc_active = 0;
10105 -                       printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n",
10106 -                           ioc->alt_ioc->name, rc);
10107 +                       printk(MYIOC_s_WARN_FMT
10108 +                               ": alt-ioc: (%d) init failure WARNING!\n",
10109 +                                       ioc->alt_ioc->name, rc);
10110                 }
10111         }
10112  
10113         if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
10114                 if (ioc->upload_fw) {
10115                         ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
10116 -                           "firmware upload required!\n", ioc->name));
10117 +                               "firmware upload required!\n", ioc->name));
10118  
10119                         /* Controller is not operational, cannot do upload
10120                          */
10121 @@ -2232,34 +2382,39 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10122                                 } else {
10123                                         printk(MYIOC_s_WARN_FMT
10124                                             "firmware upload failure!\n", ioc->name);
10125 -                                       ret = -6;
10126 +                                       ret = -5;
10127                                 }
10128                         }
10129                 }
10130         }
10131  
10132 +       /*  Enable MPT base driver management of EventNotification
10133 +        *  and EventAck handling.
10134 +        */
10135 +       if ((ret == 0) && (!ioc->facts.EventState)) {
10136 +               dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendEventNotification\n",
10137 +                   ioc->name));
10138 +               ret = SendEventNotification(ioc, 1, sleepFlag); /* 1=Enable */
10139 +       }
10140 +
10141 +       if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
10142 +               rc = SendEventNotification(ioc->alt_ioc, 1, sleepFlag);
10143 +
10144         if (ret == 0) {
10145                 /* Enable! (reply interrupt) */
10146                 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
10147                 ioc->active = 1;
10148         }
10149 -
10150 -       if (reset_alt_ioc_active && ioc->alt_ioc) {
10151 -               /* (re)Enable alt-IOC! (reply interrupt) */
10152 -               dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n",
10153 -                   ioc->alt_ioc->name));
10154 -               CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
10155 -               ioc->alt_ioc->active = 1;
10156 +       if (rc == 0) {  /* alt ioc */
10157 +               if (reset_alt_ioc_active && ioc->alt_ioc) {
10158 +                       /* (re)Enable alt-IOC! (reply interrupt) */
10159 +                       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "alt-ioc reply irq re-enabled\n",
10160 +                               ioc->alt_ioc->name));
10161 +                       CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
10162 +                       ioc->alt_ioc->active = 1;
10163 +               }
10164         }
10165  
10166 -       /*  Enable MPT base driver management of EventNotification
10167 -        *  and EventAck handling.
10168 -        */
10169 -       if ((ret == 0) && (!ioc->facts.EventState))
10170 -               (void) SendEventNotification(ioc, 1);   /* 1=Enable EventNotification */
10171 -
10172 -       if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
10173 -               (void) SendEventNotification(ioc->alt_ioc, 1);  /* 1=Enable EventNotification */
10174  
10175         /*      Add additional "reason" check before call to GetLanConfigPages
10176          *      (combined with GetIoUnitPage2 call).  This prevents a somewhat
10177 @@ -2272,11 +2427,12 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10178                 /*
10179                  * Initalize link list for inactive raid volumes.
10180                  */
10181 -               mutex_init(&ioc->raid_data.inactive_list_mutex);
10182 +               init_MUTEX(&ioc->raid_data.inactive_list_mutex);
10183                 INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
10184  
10185 -               if (ioc->bus_type == SAS) {
10186 +               switch (ioc->bus_type) {
10187  
10188 +               case SAS:
10189                         /* clear persistency table */
10190                         if(ioc->facts.IOCExceptions &
10191                             MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
10192 @@ -2290,8 +2446,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10193                          */
10194                         mpt_findImVolumes(ioc);
10195  
10196 -               } else if (ioc->bus_type == FC) {
10197 -                       if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
10198 +                       /* Check, and possibly reset, the coalescing value
10199 +                        */
10200 +                       mpt_read_ioc_pg_1(ioc);
10201 +
10202 +                       break;
10203 +
10204 +               case FC:
10205 +                       if ((ioc->pfacts[0].ProtocolFlags &
10206 +                               MPI_PORTFACTS_PROTOCOL_LAN) &&
10207                             (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
10208                                 /*
10209                                  *  Pre-fetch the ports LAN MAC address!
10210 @@ -2300,11 +2463,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10211                                 (void) GetLanConfigPages(ioc);
10212                                 a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
10213                                 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
10214 -                                   "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
10215 -                                   ioc->name, a[5], a[4], a[3], a[2], a[1], a[0]));
10216 -
10217 +                                       "LanAddr = %02X:%02X:%02X"
10218 +                                       ":%02X:%02X:%02X\n",
10219 +                                       ioc->name, a[5], a[4],
10220 +                                       a[3], a[2], a[1], a[0]));
10221                         }
10222 -               } else {
10223 +                       break;
10224 +
10225 +               case SPI:
10226                         /* Get NVRAM and adapter maximums from SPP 0 and 2
10227                          */
10228                         mpt_GetScsiPortSettings(ioc, 0);
10229 @@ -2323,41 +2489,16 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10230                         mpt_read_ioc_pg_1(ioc);
10231  
10232                         mpt_read_ioc_pg_4(ioc);
10233 +
10234 +                       break;
10235                 }
10236  
10237                 GetIoUnitPage2(ioc);
10238                 mpt_get_manufacturing_pg_0(ioc);
10239         }
10240  
10241 -       /*
10242 -        * Call each currently registered protocol IOC reset handler
10243 -        * with post-reset indication.
10244 -        * NOTE: If we're doing _IOC_BRINGUP, there can be no
10245 -        * MptResetHandlers[] registered yet.
10246 -        */
10247 -       if (hard_reset_done) {
10248 -               rc = handlers = 0;
10249 -               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
10250 -                       if ((ret == 0) && MptResetHandlers[cb_idx]) {
10251 -                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
10252 -                                   "Calling IOC post_reset handler #%d\n",
10253 -                                   ioc->name, cb_idx));
10254 -                               rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
10255 -                               handlers++;
10256 -                       }
10257 -
10258 -                       if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
10259 -                               drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
10260 -                                   "Calling IOC post_reset handler #%d\n",
10261 -                                   ioc->alt_ioc->name, cb_idx));
10262 -                               rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
10263 -                               handlers++;
10264 -                       }
10265 -               }
10266 -               /* FIXME?  Examine results here? */
10267 -       }
10268 -
10269   out:
10270 +
10271         if ((ret != 0) && irq_allocated) {
10272                 free_irq(ioc->pci_irq, ioc);
10273                 if (ioc->msi_enable)
10274 @@ -2366,7 +2507,6 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10275         return ret;
10276  }
10277  
10278 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10279  /**
10280   *     mpt_detect_bound_ports - Search for matching PCI bus/dev_function
10281   *     @ioc: Pointer to MPT adapter structure
10282 @@ -2378,7 +2518,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
10283   *
10284   *     If match on PCI dev_function +/-1 is found, bind the two MPT adapters
10285   *     using alt_ioc pointer fields in their %MPT_ADAPTER structures.
10286 - */
10287 + **/
10288  static void
10289  mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
10290  {
10291 @@ -2389,8 +2529,8 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc,
10292  
10293         dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
10294             " searching for devfn match on %x or %x\n",
10295 -           ioc->name, pci_name(pdev), pdev->bus->number,
10296 -           pdev->devfn, func-1, func+1));
10297 +               ioc->name, pci_name(pdev), pdev->bus->number,
10298 +               pdev->devfn, func-1, func+1));
10299  
10300         peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
10301         if (!peer) {
10302 @@ -2404,16 +2544,16 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc,
10303                 if (_pcidev == peer) {
10304                         /* Paranoia checks */
10305                         if (ioc->alt_ioc != NULL) {
10306 -                               printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
10307 -                                       ioc->name, ioc->alt_ioc->name);
10308 +                               printk(MYIOC_s_WARN_FMT "Oops, already bound (%s <==> %s)!\n",
10309 +                                       ioc->name, ioc->name, ioc->alt_ioc->name);
10310                                 break;
10311                         } else if (ioc_srch->alt_ioc != NULL) {
10312 -                               printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
10313 -                                       ioc_srch->name, ioc_srch->alt_ioc->name);
10314 +                               printk(MYIOC_s_WARN_FMT "Oops, already bound (%s <==> %s)!\n",
10315 +                                       ioc_srch->name, ioc_srch->name, ioc_srch->alt_ioc->name);
10316                                 break;
10317                         }
10318 -                       dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n",
10319 -                               ioc->name, ioc_srch->name));
10320 +                       dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FOUND! binding %s <==> %s\n",
10321 +                               ioc->name, ioc->name, ioc_srch->name));
10322                         ioc_srch->alt_ioc = ioc;
10323                         ioc->alt_ioc = ioc_srch;
10324                 }
10325 @@ -2421,11 +2561,10 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc,
10326         pci_dev_put(peer);
10327  }
10328  
10329 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10330  /**
10331   *     mpt_adapter_disable - Disable misbehaving MPT adapter.
10332   *     @ioc: Pointer to MPT adapter structure
10333 - */
10334 + **/
10335  static void
10336  mpt_adapter_disable(MPT_ADAPTER *ioc)
10337  {
10338 @@ -2433,26 +2572,43 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
10339         int ret;
10340  
10341         if (ioc->cached_fw != NULL) {
10342 -               ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
10343 -                   "adapter\n", __func__, ioc->name));
10344 +               ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_adapter_disable: "
10345 +                       "Pushing FW onto adapter\n", ioc->name));
10346                 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
10347                     ioc->cached_fw, CAN_SLEEP)) < 0) {
10348                         printk(MYIOC_s_WARN_FMT
10349 -                           ": firmware downloadboot failure (%d)!\n",
10350 -                           ioc->name, ret);
10351 +                           ": firmware downloadboot failure (%d)!\n", ioc->name, ret);
10352                 }
10353         }
10354  
10355 +       /*
10356 +        * Put the controller into ready state (if its not already)
10357 +        */
10358 +       if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) {
10359 +               if(!SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET,
10360 +                   CAN_SLEEP)) {
10361 +                       if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY)
10362 +                               printk(MYIOC_s_ERR_FMT "%s:  IOC msg unit "
10363 +                                   "reset failed to put ioc in ready state!\n",
10364 +                                   ioc->name, __FUNCTION__);
10365 +               } else
10366 +                       printk(MYIOC_s_ERR_FMT "%s:  IOC msg unit reset "
10367 +                           "failed!\n", ioc->name, __FUNCTION__);
10368 +       }
10369 +
10370         /* Disable adapter interrupts! */
10371 +       synchronize_irq(ioc->pcidev->irq);
10372         CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
10373         ioc->active = 0;
10374 +
10375         /* Clear any lingering interrupt */
10376         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
10377 +       CHIPREG_READ32(&ioc->chip->IntStatus);
10378  
10379         if (ioc->alloc != NULL) {
10380                 sz = ioc->alloc_sz;
10381 -               dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free  @ %p, sz=%d bytes\n",
10382 -                   ioc->name, ioc->alloc, ioc->alloc_sz));
10383 +               dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free  @ %p, sz=%d bytes\n",
10384 +                       ioc->name, ioc->alloc, ioc->alloc_sz));
10385                 pci_free_consistent(ioc->pcidev, sz,
10386                                 ioc->alloc, ioc->alloc_dma);
10387                 ioc->reply_frames = NULL;
10388 @@ -2482,8 +2638,10 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
10389         mpt_inactive_raid_list_free(ioc);
10390         kfree(ioc->raid_data.pIocPg2);
10391         kfree(ioc->raid_data.pIocPg3);
10392 +       kfree(ioc->raid_data.pIocPg6);
10393         ioc->spi_data.nvram = NULL;
10394         ioc->raid_data.pIocPg3 = NULL;
10395 +       ioc->raid_data.pIocPg6 = NULL;
10396  
10397         if (ioc->spi_data.pIocPg4 != NULL) {
10398                 sz = ioc->spi_data.IocPg4Sz;
10399 @@ -2507,27 +2665,29 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
10400                 if((ret = mpt_host_page_access_control(ioc,
10401                     MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
10402                         printk(MYIOC_s_ERR_FMT
10403 -                          "host page buffers free failed (%d)!\n",
10404 -                           ioc->name, ret);
10405 +                          ": %s: host page buffers free failed (%d)!\n",
10406 +                           ioc->name, __FUNCTION__, ret);
10407                 }
10408 -               dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free  @ %p, sz=%d bytes\n",
10409 +               dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HostPageBuffer free  @ %p, sz=%d bytes\n",
10410                         ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
10411                 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
10412 -                   ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
10413 +                               ioc->HostPageBuffer,
10414 +                               ioc->HostPageBuffer_dma);
10415                 ioc->HostPageBuffer = NULL;
10416                 ioc->HostPageBuffer_sz = 0;
10417                 ioc->alloc_total -= ioc->HostPageBuffer_sz;
10418         }
10419 +
10420 +       pci_set_drvdata(ioc->pcidev, NULL);
10421  }
10422  
10423 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10424  /**
10425   *     mpt_adapter_dispose - Free all resources associated with an MPT adapter
10426   *     @ioc: Pointer to MPT adapter structure
10427   *
10428   *     This routine unregisters h/w resources and frees all alloc'd memory
10429   *     associated with a MPT adapter structure.
10430 - */
10431 + **/
10432  static void
10433  mpt_adapter_dispose(MPT_ADAPTER *ioc)
10434  {
10435 @@ -2558,7 +2718,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
10436  #if defined(CONFIG_MTRR) && 0
10437         if (ioc->mtrr_reg > 0) {
10438                 mtrr_del(ioc->mtrr_reg, 0, 0);
10439 -               dprintk(ioc, printk(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name));
10440 +               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MTRR region de-registered\n", ioc->name));
10441         }
10442  #endif
10443  
10444 @@ -2566,8 +2726,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
10445         list_del(&ioc->list);
10446  
10447         sz_last = ioc->alloc_total;
10448 -       dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
10449 -           ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
10450 +       dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free'd %d of %d bytes\n",
10451 +                       ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
10452  
10453         if (ioc->alt_ioc)
10454                 ioc->alt_ioc->alt_ioc = NULL;
10455 @@ -2575,11 +2735,10 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
10456         kfree(ioc);
10457  }
10458  
10459 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10460  /**
10461   *     MptDisplayIocCapabilities - Disply IOC's capabilities.
10462   *     @ioc: Pointer to MPT adapter structure
10463 - */
10464 + **/
10465  static void
10466  MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
10467  {
10468 @@ -2618,7 +2777,6 @@ MptDisplayIocCapabilities(MPT_ADAPTER *i
10469         printk("}\n");
10470  }
10471  
10472 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10473  /**
10474   *     MakeIocReady - Get IOC to a READY state, using KickStart if needed.
10475   *     @ioc: Pointer to MPT_ADAPTER structure
10476 @@ -2632,7 +2790,7 @@ MptDisplayIocCapabilities(MPT_ADAPTER *i
10477   *             -2 - Msg Unit Reset Failed
10478   *             -3 - IO Unit Reset Failed
10479   *             -4 - IOC owned by a PEER
10480 - */
10481 + **/
10482  static int
10483  MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
10484  {
10485 @@ -2646,7 +2804,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
10486  
10487         /* Get current [raw] IOC state  */
10488         ioc_state = mpt_GetIocState(ioc, 0);
10489 -       dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
10490 +       dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MakeIocReady, [raw] state=%08x\n", ioc->name, ioc_state));
10491  
10492         /*
10493          *      Check to see if IOC got left/stuck in doorbell handshake
10494 @@ -2659,8 +2817,11 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
10495         }
10496  
10497         /* Is it already READY? */
10498 -       if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
10499 +       if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) {
10500 +               dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "IOC is in READY state\n",
10501 +                   ioc->name));
10502                 return 0;
10503 +       }
10504  
10505         /*
10506          *      Check to see if IOC is in FAULT state.
10507 @@ -2668,9 +2829,9 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
10508         if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
10509                 statefault = 2;
10510                 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
10511 -                   ioc->name);
10512 -               printk(MYIOC_s_WARN_FMT "           FAULT code = %04xh\n",
10513 -                   ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
10514 +                               ioc->name);
10515 +               printk(KERN_WARNING "           FAULT code = %04xh\n",
10516 +                               ioc_state & MPI_DOORBELL_DATA_MASK);
10517         }
10518  
10519         /*
10520 @@ -2686,7 +2847,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
10521                  * Else, fall through to KickStart case
10522                  */
10523                 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
10524 -               dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
10525 +               dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
10526                         "whoinit 0x%x statefault %d force %d\n",
10527                         ioc->name, whoinit, statefault, force));
10528                 if (whoinit == MPI_WHOINIT_PCI_PEER)
10529 @@ -2733,15 +2894,15 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
10530  
10531                 ii++; cntdn--;
10532                 if (!cntdn) {
10533 -                       printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
10534 -                                       ioc->name, (int)((ii+5)/HZ));
10535 +                       printk(MYIOC_s_ERR_FMT "Wait IOC_READY state (0x%x) timeout(%d)!\n",
10536 +                                       ioc->name, ioc_state, (int)((ii+5)/HZ));
10537                         return -ETIME;
10538                 }
10539  
10540                 if (sleepFlag == CAN_SLEEP) {
10541                         msleep(1);
10542                 } else {
10543 -                       mdelay (1);     /* 1 msec delay */
10544 +                       mdelay(1);      /* 1 msec delay */
10545                 }
10546  
10547         }
10548 @@ -2755,7 +2916,6 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
10549         return hard_reset_done;
10550  }
10551  
10552 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10553  /**
10554   *     mpt_GetIocState - Get the current state of a MPT adapter.
10555   *     @ioc: Pointer to MPT_ADAPTER structure
10556 @@ -2763,7 +2923,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
10557   *
10558   *     Returns all IOC Doorbell register bits if cooked==0, else just the
10559   *     Doorbell bits in MPI_IOC_STATE_MASK.
10560 - */
10561 + **/
10562  u32
10563  mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
10564  {
10565 @@ -2779,7 +2939,6 @@ mpt_GetIocState(MPT_ADAPTER *ioc, int co
10566         return cooked ? sc : s;
10567  }
10568  
10569 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10570  /**
10571   *     GetIocFacts - Send IOCFacts request to MPT adapter.
10572   *     @ioc: Pointer to MPT_ADAPTER structure
10573 @@ -2787,7 +2946,7 @@ mpt_GetIocState(MPT_ADAPTER *ioc, int co
10574   *     @reason: If recovery, only update facts.
10575   *
10576   *     Returns 0 for success, non-zero for failure.
10577 - */
10578 + **/
10579  static int
10580  GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
10581  {
10582 @@ -2802,8 +2961,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
10583  
10584         /* IOC *must* NOT be in RESET state! */
10585         if (ioc->last_state == MPI_IOC_STATE_RESET) {
10586 -               printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n",
10587 -                   ioc->name, ioc->last_state );
10588 +               printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
10589 +                               ioc->name,
10590 +                               ioc->last_state );
10591                 return -44;
10592         }
10593  
10594 @@ -2820,7 +2980,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
10595         get_facts.Function = MPI_FUNCTION_IOC_FACTS;
10596         /* Assert: All other get_facts fields are zero! */
10597  
10598 -       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
10599 +       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
10600             "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
10601             ioc->name, req_sz, reply_sz));
10602  
10603 @@ -2850,6 +3010,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
10604                 }
10605  
10606                 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
10607 +               if (facts->MsgVersion == MPI_VERSION_01_05)
10608 +                       facts->HeaderVersion = le16_to_cpu(facts->HeaderVersion);
10609                 facts->MsgContext = le32_to_cpu(facts->MsgContext);
10610                 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
10611                 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
10612 @@ -2865,7 +3027,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
10613                  *      Old: u16{Major(4),Minor(4),SubMinor(8)}
10614                  *      New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
10615                  */
10616 -               if (facts->MsgVersion < 0x0102) {
10617 +               if (facts->MsgVersion < MPI_VERSION_01_02) {
10618                         /*
10619                          *      Handle old FC f/w style, convert to new...
10620                          */
10621 @@ -2877,9 +3039,11 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
10622                         facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
10623  
10624                 facts->ProductID = le16_to_cpu(facts->ProductID);
10625 +
10626                 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
10627                     > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
10628                         ioc->ir_firmware = 1;
10629 +
10630                 facts->CurrentHostMfaHighAddr =
10631                                 le32_to_cpu(facts->CurrentHostMfaHighAddr);
10632                 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
10633 @@ -2895,7 +3059,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
10634                  * to 14 in MPI-1.01.0x.
10635                  */
10636                 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
10637 -                   facts->MsgVersion > 0x0100) {
10638 +                   facts->MsgVersion > MPI_VERSION_01_00) {
10639                         facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
10640                 }
10641  
10642 @@ -2956,7 +3120,6 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
10643         return 0;
10644  }
10645  
10646 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10647  /**
10648   *     GetPortFacts - Send PortFacts request to MPT adapter.
10649   *     @ioc: Pointer to MPT_ADAPTER structure
10650 @@ -2964,7 +3127,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
10651   *     @sleepFlag: Specifies whether the process can sleep
10652   *
10653   *     Returns 0 for success, non-zero for failure.
10654 - */
10655 + **/
10656  static int
10657  GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
10658  {
10659 @@ -2977,8 +3140,8 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn
10660  
10661         /* IOC *must* NOT be in RESET state! */
10662         if (ioc->last_state == MPI_IOC_STATE_RESET) {
10663 -               printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
10664 -                   ioc->name, ioc->last_state );
10665 +               printk(MYIOC_s_ERR_FMT "Can't get PortFacts, "
10666 +                  " NOT READY! (%08x)\n", ioc->name, ioc->last_state );
10667                 return -4;
10668         }
10669  
10670 @@ -2996,14 +3159,14 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn
10671         get_pfacts.PortNumber = portnum;
10672         /* Assert: All other get_pfacts fields are zero! */
10673  
10674 -       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
10675 -                       ioc->name, portnum));
10676 +       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
10677 +               ioc->name, portnum));
10678  
10679         /* No non-zero fields in the get_pfacts request are greater than
10680          * 1 byte in size, so we can just fire it off as is.
10681          */
10682         ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
10683 -                               reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
10684 +               reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
10685         if (ii != 0)
10686                 return ii;
10687  
10688 @@ -3038,7 +3201,6 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn
10689         return 0;
10690  }
10691  
10692 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10693  /**
10694   *     SendIocInit - Send IOCInit request to MPT adapter.
10695   *     @ioc: Pointer to MPT_ADAPTER structure
10696 @@ -3047,7 +3209,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn
10697   *     Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
10698   *
10699   *     Returns 0 for success, non-zero for failure.
10700 - */
10701 + **/
10702  static int
10703  SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
10704  {
10705 @@ -3077,7 +3239,8 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
10706  
10707         ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
10708         ioc_init.MaxBuses = (U8)ioc->number_of_buses;
10709 -       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
10710 +
10711 +       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
10712                    ioc->name, ioc->facts.MsgVersion));
10713         if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
10714                 // set MsgVersion and HeaderVersion host driver was built with
10715 @@ -3091,7 +3254,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
10716         }
10717         ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);   /* in BYTES */
10718  
10719 -       if (sizeof(dma_addr_t) == sizeof(u64)) {
10720 +       if (ioc->sg_addr_size == sizeof(u64)) {
10721                 /* Save the upper 32-bits of the request
10722                  * (reply) and sense buffers.
10723                  */
10724 @@ -3160,7 +3323,6 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
10725         return r;
10726  }
10727  
10728 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10729  /**
10730   *     SendPortEnable - Send PortEnable request to MPT adapter port.
10731   *     @ioc: Pointer to MPT_ADAPTER structure
10732 @@ -3170,7 +3332,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
10733   *     Send PortEnable to bring IOC to OPERATIONAL state.
10734   *
10735   *     Returns 0 for success, non-zero for failure.
10736 - */
10737 + **/
10738  static int
10739  SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
10740  {
10741 @@ -3193,7 +3355,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int por
10742  /*     port_enable.MsgFlags = 0;               */
10743  /*     port_enable.MsgContext = 0;             */
10744  
10745 -       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
10746 +       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
10747                         ioc->name, portnum, &port_enable));
10748  
10749         /* RAID FW may take a long time to enable
10750 @@ -3273,7 +3435,6 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
10751         ioc->cached_fw = NULL;
10752  }
10753  
10754 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10755  /**
10756   *     mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
10757   *     @ioc: Pointer to MPT_ADAPTER structure
10758 @@ -3286,7 +3447,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
10759   *     on the bound IOC, the second image is discarded
10760   *     and memory is free'd. Both channels must upload to prevent
10761   *     IOC from running in degraded mode.
10762 - */
10763 + **/
10764  static int
10765  mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
10766  {
10767 @@ -3294,22 +3455,19 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
10768         FWUpload_t              *prequest;
10769         FWUploadReply_t         *preply;
10770         FWUploadTCSGE_t         *ptcsge;
10771 -       int                      sgeoffset;
10772         u32                      flagsLength;
10773 -       int                      ii, sz, reply_sz;
10774 +       int                      ii, reply_sz;
10775         int                      cmdStatus;
10776 +       int                      request_size;
10777  
10778         /* If the image size is 0, we are done.
10779          */
10780 -       if ((sz = ioc->facts.FWImageSize) == 0)
10781 +       if (!ioc->facts.FWImageSize)
10782                 return 0;
10783  
10784         if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
10785                 return -ENOMEM;
10786  
10787 -       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
10788 -           ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
10789 -
10790         prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
10791             kzalloc(ioc->req_sz, GFP_KERNEL);
10792         if (!prequest) {
10793 @@ -3326,49 +3484,47 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
10794  
10795         prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
10796         prequest->Function = MPI_FUNCTION_FW_UPLOAD;
10797 -
10798         ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
10799         ptcsge->DetailsLength = 12;
10800         ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
10801 -       ptcsge->ImageSize = cpu_to_le32(sz);
10802 +       ptcsge->ImageSize = cpu_to_le32(ioc->facts.FWImageSize);
10803         ptcsge++;
10804  
10805 -       sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
10806 -
10807 -       flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
10808 -       mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
10809 -
10810 -       sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
10811 -       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
10812 -           ioc->name, prequest, sgeoffset));
10813 +       flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | ioc->facts.FWImageSize;
10814 +       ioc->add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
10815 +       request_size = offsetof(FWUpload_t, SGL) + sizeof(FWUploadTCSGE_t) +
10816 +           ioc->SGE_size;
10817 +       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload "
10818 +           " (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest,
10819 +           ioc->facts.FWImageSize, request_size));
10820         DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
10821  
10822 -       ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
10823 -                               reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
10824 +       ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32*)prequest,
10825 +           reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
10826  
10827 -       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii));
10828 +       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Upload completed "
10829 +           "rc=%x \n", ioc->name, ii));
10830  
10831         cmdStatus = -EFAULT;
10832         if (ii == 0) {
10833                 /* Handshake transfer was complete and successful.
10834                  * Check the Reply Frame.
10835                  */
10836 -               int status, transfer_sz;
10837 -               status = le16_to_cpu(preply->IOCStatus);
10838 -               if (status == MPI_IOCSTATUS_SUCCESS) {
10839 -                       transfer_sz = le32_to_cpu(preply->ActualImageSize);
10840 -                       if (transfer_sz == sz)
10841 -                               cmdStatus = 0;
10842 -               }
10843 +               int status;
10844 +               status = le16_to_cpu(preply->IOCStatus) &
10845 +                   MPI_IOCSTATUS_MASK;
10846 +               if (status == MPI_IOCSTATUS_SUCCESS &&
10847 +                   ioc->facts.FWImageSize ==
10848 +                   le32_to_cpu(preply->ActualImageSize));
10849 +                       cmdStatus = 0;
10850         }
10851 -       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
10852 -                       ioc->name, cmdStatus));
10853 +       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "do_upload cmdStatus=%d \n",
10854 +               ioc->name, cmdStatus));
10855  
10856  
10857         if (cmdStatus) {
10858 -
10859 -               ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n",
10860 -                       ioc->name));
10861 +               ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed, "
10862 +                   "freeing image \n", ioc->name));
10863                 mpt_free_fw_memory(ioc);
10864         }
10865         kfree(prequest);
10866 @@ -3376,7 +3532,6 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
10867         return cmdStatus;
10868  }
10869  
10870 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10871  /**
10872   *     mpt_downloadboot - DownloadBoot code
10873   *     @ioc: Pointer to MPT_ADAPTER structure
10874 @@ -3389,7 +3544,7 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
10875   *             -1 FW Image size is 0
10876   *             -2 No valid cached_fw Pointer
10877   *             <0 for fw upload failure.
10878 - */
10879 + **/
10880  static int
10881  mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
10882  {
10883 @@ -3401,10 +3556,10 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
10884         u32                      diagRwData;
10885         u32                      nextImage;
10886         u32                      load_addr;
10887 -       u32                      ioc_state=0;
10888 +       u32                      doorbell;
10889  
10890         ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
10891 -                               ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
10892 +           ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
10893  
10894         CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
10895         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
10896 @@ -3416,11 +3571,10 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
10897         CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
10898  
10899         /* wait 1 msec */
10900 -       if (sleepFlag == CAN_SLEEP) {
10901 +       if (sleepFlag == CAN_SLEEP)
10902                 msleep(1);
10903 -       } else {
10904 -               mdelay (1);
10905 -       }
10906 +       else
10907 +               mdelay(1);
10908  
10909         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
10910         CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
10911 @@ -3433,11 +3587,10 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
10912                         break;
10913                 }
10914                 /* wait .1 sec */
10915 -               if (sleepFlag == CAN_SLEEP) {
10916 +               if (sleepFlag == CAN_SLEEP)
10917                         msleep (100);
10918 -               } else {
10919 +               else
10920                         mdelay (100);
10921 -               }
10922         }
10923  
10924         if ( count == 30 ) {
10925 @@ -3455,6 +3608,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
10926         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
10927  
10928         /* Set the DiagRwEn and Disable ARM bits */
10929 +       diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
10930         CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
10931  
10932         fwSize = (pFwHeader->ImageSize + 3)/4;
10933 @@ -3468,13 +3622,12 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
10934  
10935         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
10936         ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
10937 -               ioc->name, pFwHeader->LoadStartAddress));
10938 +           ioc->name, pFwHeader->LoadStartAddress));
10939  
10940         ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
10941 -                               ioc->name, fwSize*4, ptrFw));
10942 -       while (fwSize--) {
10943 +           ioc->name, fwSize*4, ptrFw));
10944 +       while (fwSize--)
10945                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
10946 -       }
10947  
10948         nextImage = pFwHeader->NextImageHeaderOffset;
10949         while (nextImage) {
10950 @@ -3486,21 +3639,22 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
10951                 ptrFw = (u32 *)pExtImage;
10952  
10953                 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
10954 -                                               ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
10955 +                   ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
10956                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
10957  
10958 -               while (fwSize--) {
10959 +               while (fwSize--)
10960                         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
10961 -               }
10962                 nextImage = pExtImage->NextImageHeaderOffset;
10963         }
10964  
10965         /* Write the IopResetVectorRegAddr */
10966 -       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name,  pFwHeader->IopResetRegAddr));
10967 +       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n",
10968 +           ioc->name, pFwHeader->IopResetRegAddr));
10969         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
10970  
10971         /* Write the IopResetVectorValue */
10972 -       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
10973 +       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n",
10974 +           ioc->name, pFwHeader->IopResetVectorValue));
10975         CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
10976  
10977         /* Clear the internal flash bad bit - autoincrementing register,
10978 @@ -3517,75 +3671,75 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
10979                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
10980                 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
10981  
10982 -       } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
10983 -               diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
10984 -               CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
10985 -                   MPI_DIAG_CLEAR_FLASH_BAD_SIG);
10986 -
10987 -               /* wait 1 msec */
10988 -               if (sleepFlag == CAN_SLEEP) {
10989 -                       msleep (1);
10990 -               } else {
10991 -                       mdelay (1);
10992 -               }
10993         }
10994  
10995         if (ioc->errata_flag_1064)
10996                 pci_disable_io_access(ioc->pcidev);
10997  
10998         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
10999 -       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
11000 -               "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
11001 -               ioc->name, diag0val));
11002 -       diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
11003 -       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
11004 -               ioc->name, diag0val));
11005 +       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "diag0val=%x, turning off"
11006 +           " PREVENT_IOC_BOOT and DISABLE_ARM\n", ioc->name, diag0val));
11007 +       diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
11008 +       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "diag0val=%x\n",
11009 +           ioc->name, diag0val));
11010         CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
11011  
11012 -       /* Write 0xFF to reset the sequencer */
11013 -       CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
11014 +       if (ioc->bus_type == SAS ) {
11015 +               /* wait 1 sec */
11016 +               if (sleepFlag == CAN_SLEEP)
11017 +                       msleep(1000);
11018 +               else
11019 +                       mdelay(1000);
11020  
11021 -       if (ioc->bus_type == SAS) {
11022 -               ioc_state = mpt_GetIocState(ioc, 0);
11023 -               if ( (GetIocFacts(ioc, sleepFlag,
11024 -                               MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
11025 -                       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
11026 -                                       ioc->name, ioc_state));
11027 -                       return -EFAULT;
11028 +               diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
11029 +               ddlprintk(ioc, printk (MYIOC_s_DEBUG_FMT
11030 +                   "diag0val=%x, turning off RW_ENABLE\n", ioc->name,
11031 +                   diag0val));
11032 +               diag0val &= ~(MPI_DIAG_RW_ENABLE);
11033 +               ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11034 +                   "now diag0val=%x\n", ioc->name, diag0val));
11035 +               CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
11036 +
11037 +               diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
11038 +               if (diag0val & MPI_DIAG_FLASH_BAD_SIG) {
11039 +                       diag0val |= MPI_DIAG_CLEAR_FLASH_BAD_SIG;
11040 +                       CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
11041 +                       diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
11042                 }
11043 +               diag0val &= ~(MPI_DIAG_DISABLE_ARM);
11044 +               CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
11045 +               diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
11046 +               CHIPREG_WRITE32(&ioc->chip->DiagRwAddress, 0x3f000004);
11047         }
11048  
11049 -       for (count=0; count<HZ*20; count++) {
11050 -               if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
11051 -                       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11052 -                               "downloadboot successful! (count=%d) IocState=%x\n",
11053 -                               ioc->name, count, ioc_state));
11054 -                       if (ioc->bus_type == SAS) {
11055 +       /* Write 0xFF to reset the sequencer */
11056 +       CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
11057 +
11058 +       for (count = 0; count < 30; count ++) {
11059 +               doorbell = CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_IOC_STATE_MASK;
11060 +               if (doorbell == MPI_IOC_STATE_READY) {
11061 +                       if (ioc->bus_type == SAS)
11062                                 return 0;
11063 -                       }
11064                         if ((SendIocInit(ioc, sleepFlag)) != 0) {
11065 -                               ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11066 -                                       "downloadboot: SendIocInit failed\n",
11067 -                                       ioc->name));
11068 +                               ddlprintk(ioc, printk(MYIOC_s_WARN_FMT
11069 +                                   "SendIocInit failed\n", ioc->name));
11070                                 return -EFAULT;
11071                         }
11072                         ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11073 -                                       "downloadboot: SendIocInit successful\n",
11074 -                                       ioc->name));
11075 +                           "SendIocInit successful\n", ioc->name));
11076                         return 0;
11077                 }
11078 -               if (sleepFlag == CAN_SLEEP) {
11079 -                       msleep (10);
11080 -               } else {
11081 -                       mdelay (10);
11082 -               }
11083 +               ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "looking for READY STATE:"
11084 +                   " doorbell=%x count=%d\n", ioc->name, doorbell, count));
11085 +               if (sleepFlag == CAN_SLEEP)
11086 +                       msleep(1000);
11087 +               else
11088 +                       mdelay(1000);
11089         }
11090 -       ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11091 -               "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
11092 +       ddlprintk(ioc, printk(MYIOC_s_WARN_FMT "downloadboot failed! count=%d\n", ioc->name, count));
11093         return -EFAULT;
11094  }
11095  
11096 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11097  /**
11098   *     KickStart - Perform hard reset of MPT adapter.
11099   *     @ioc: Pointer to MPT_ADAPTER structure
11100 @@ -3610,7 +3764,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
11101   *                  OR reset but failed to come READY
11102   *             -2 - no reset, could not enter DIAG mode
11103   *             -3 - reset but bad FW bit
11104 - */
11105 + **/
11106  static int
11107  KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
11108  {
11109 @@ -3618,7 +3772,7 @@ KickStart(MPT_ADAPTER *ioc, int force, i
11110         u32 ioc_state=0;
11111         int cnt,cntdn;
11112  
11113 -       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
11114 +       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": KickStart\n", ioc->name));
11115         if (ioc->bus_type == SPI) {
11116                 /* Always issue a Msg Unit Reset first. This will clear some
11117                  * SCSI bus hang conditions.
11118 @@ -3636,14 +3790,15 @@ KickStart(MPT_ADAPTER *ioc, int force, i
11119         if (hard_reset_done < 0)
11120                 return hard_reset_done;
11121  
11122 -       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
11123 -               ioc->name));
11124 +       /* may not have worked but hard_reset_done doesn't always signal failure */
11125 +       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "Diagnostic reset completed!\n",
11126 +                       ioc->name));
11127  
11128         cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;     /* 2 seconds */
11129         for (cnt=0; cnt<cntdn; cnt++) {
11130                 ioc_state = mpt_GetIocState(ioc, 1);
11131                 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
11132 -                       dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
11133 +                       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
11134                                         ioc->name, cnt));
11135                         return hard_reset_done;
11136                 }
11137 @@ -3655,11 +3810,10 @@ KickStart(MPT_ADAPTER *ioc, int force, i
11138         }
11139  
11140         dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
11141 -               ioc->name, mpt_GetIocState(ioc, 0)));
11142 +                       ioc->name, mpt_GetIocState(ioc, 0)));
11143         return -1;
11144  }
11145  
11146 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11147  /**
11148   *     mpt_diag_reset - Perform hard reset of the adapter.
11149   *     @ioc: Pointer to MPT_ADAPTER structure
11150 @@ -3677,30 +3831,46 @@ KickStart(MPT_ADAPTER *ioc, int force, i
11151   *               0  no reset performed because reset history bit set
11152   *              -2  enabling diagnostic mode failed
11153   *              -3  diagnostic reset failed
11154 - */
11155 + **/
11156  static int
11157  mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
11158  {
11159         u32 diag0val;
11160 -       u32 doorbell;
11161 +       u32 doorbell = 0;
11162         int hard_reset_done = 0;
11163         int count = 0;
11164         u32 diag1val = 0;
11165         MpiFwHeader_t *cached_fw;       /* Pointer to FW */
11166 +       u8       cb_idx;
11167  
11168         /* Clear any existing interrupts */
11169         CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
11170  
11171         if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
11172 +
11173 +               if (!ignore)
11174 +                       return 0;
11175 +
11176                 drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
11177 -                       "address=%p\n",  ioc->name, __func__,
11178 -                       &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
11179 +                   "address=%p\n",  ioc->name, __FUNCTION__, &ioc->chip->Doorbell,
11180 +                   &ioc->chip->Reset_1078));
11181                 CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
11182                 if (sleepFlag == CAN_SLEEP)
11183                         msleep(1);
11184                 else
11185                         mdelay(1);
11186  
11187 +               /*
11188 +                * Call each currently registered protocol IOC reset handler
11189 +                * with pre-reset indication.
11190 +                * NOTE: If we're doing _IOC_BRINGUP, there can be no
11191 +                * MptResetHandlers[] registered yet.
11192 +                */
11193 +               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
11194 +                       if (MptResetHandlers[cb_idx])
11195 +                               (*(MptResetHandlers[cb_idx]))(ioc, MPT_IOC_PRE_RESET);
11196 +               }
11197 +
11198                 for (count = 0; count < 60; count ++) {
11199                         doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
11200                         doorbell &= MPI_IOC_STATE_MASK;
11201 @@ -3709,9 +3879,15 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11202                                 "looking for READY STATE: doorbell=%x"
11203                                 " count=%d\n",
11204                                 ioc->name, doorbell, count));
11205 -                       if (doorbell == MPI_IOC_STATE_READY) {
11206 +
11207 +                       if (doorbell == MPI_IOC_STATE_READY)
11208                                 return 1;
11209 -                       }
11210 +
11211 +                       /*
11212 +                        * Early out for hard fault
11213 +                        */
11214 +                       if (count && doorbell == MPI_IOC_STATE_FAULT)
11215 +                               break;
11216  
11217                         /* wait 1 sec */
11218                         if (sleepFlag == CAN_SLEEP)
11219 @@ -3719,16 +3895,20 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11220                         else
11221                                 mdelay(1000);
11222                 }
11223 +
11224 +               if (doorbell != MPI_IOC_STATE_READY)
11225 +                       printk(MYIOC_s_ERR_FMT "Failed to come READY after "
11226 +                           "reset! IocState=%x", ioc->name, doorbell);
11227                 return -1;
11228         }
11229  
11230         /* Use "Diagnostic reset" method! (only thing available!) */
11231         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
11232  
11233 -       if (ioc->debug_level & MPT_DEBUG) {
11234 +       if (ioc->debug_level & MPT_DEBUG_RESET) {
11235                 if (ioc->alt_ioc)
11236                         diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
11237 -               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
11238 +               drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
11239                         ioc->name, diag0val, diag1val));
11240         }
11241  
11242 @@ -3748,11 +3928,10 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11243                         CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
11244  
11245                         /* wait 100 msec */
11246 -                       if (sleepFlag == CAN_SLEEP) {
11247 +                       if (sleepFlag == CAN_SLEEP)
11248                                 msleep (100);
11249 -                       } else {
11250 +                       else
11251                                 mdelay (100);
11252 -                       }
11253  
11254                         count++;
11255                         if (count > 20) {
11256 @@ -3764,14 +3943,14 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11257  
11258                         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
11259  
11260 -                       dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
11261 +                       drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
11262                                         ioc->name, diag0val));
11263                 }
11264  
11265 -               if (ioc->debug_level & MPT_DEBUG) {
11266 +               if (ioc->debug_level & MPT_DEBUG_RESET) {
11267                         if (ioc->alt_ioc)
11268                                 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
11269 -                       dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
11270 +                       drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
11271                                 ioc->name, diag0val, diag1val));
11272                 }
11273                 /*
11274 @@ -3787,7 +3966,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11275                  */
11276                 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
11277                 hard_reset_done = 1;
11278 -               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
11279 +               drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
11280                                 ioc->name));
11281  
11282                 /*
11283 @@ -3796,25 +3975,13 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11284                  * NOTE: If we're doing _IOC_BRINGUP, there can be no
11285                  * MptResetHandlers[] registered yet.
11286                  */
11287 -               {
11288 -                       u8       cb_idx;
11289 -                       int      r = 0;
11290 -
11291 -                       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
11292 -                               if (MptResetHandlers[cb_idx]) {
11293 -                                       dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11294 -                                               "Calling IOC pre_reset handler #%d\n",
11295 -                                               ioc->name, cb_idx));
11296 -                                       r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
11297 -                                       if (ioc->alt_ioc) {
11298 -                                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11299 -                                                       "Calling alt-%s pre_reset handler #%d\n",
11300 -                                                       ioc->name, ioc->alt_ioc->name, cb_idx));
11301 -                                               r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
11302 -                                       }
11303 +               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
11304 +                       if (MptResetHandlers[cb_idx]) {
11305 +                               mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
11306 +                               if (ioc->alt_ioc) {
11307 +                                       mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
11308                                 }
11309                         }
11310 -                       /* FIXME?  Examine results here? */
11311                 }
11312  
11313                 if (ioc->cached_fw)
11314 @@ -3834,20 +4001,18 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11315                                         break;
11316                                 }
11317  
11318 -                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
11319 +                               drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
11320                                         ioc->name, diag0val, count));
11321                                 /* wait 1 sec */
11322 -                               if (sleepFlag == CAN_SLEEP) {
11323 +                               if (sleepFlag == CAN_SLEEP)
11324                                         msleep (1000);
11325 -                               } else {
11326 +                               else
11327                                         mdelay (1000);
11328 -                               }
11329                         }
11330                         if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
11331                                 printk(MYIOC_s_WARN_FMT
11332                                         "firmware downloadboot failure (%d)!\n", ioc->name, count);
11333                         }
11334 -
11335                 } else {
11336                         /* Wait for FW to reload and for board
11337                          * to go to the READY state.
11338 @@ -3859,25 +4024,38 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11339                                 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
11340                                 doorbell &= MPI_IOC_STATE_MASK;
11341  
11342 -                               if (doorbell == MPI_IOC_STATE_READY) {
11343 +                               drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11344 +                                   "looking for READY STATE: doorbell=%x"
11345 +                                   " count=%d\n", ioc->name, doorbell, count));
11346 +
11347 +                               if (doorbell == MPI_IOC_STATE_READY)
11348 +                                       break;
11349 +
11350 +                               /*
11351 +                                * Early out for hard fault
11352 +                                */
11353 +                               if (count && doorbell == MPI_IOC_STATE_FAULT)
11354                                         break;
11355 -                               }
11356  
11357                                 /* wait 1 sec */
11358 -                               if (sleepFlag == CAN_SLEEP) {
11359 +                               if (sleepFlag == CAN_SLEEP)
11360                                         msleep (1000);
11361 -                               } else {
11362 +                               else
11363                                         mdelay (1000);
11364 -                               }
11365                         }
11366 +
11367 +                       if (doorbell != MPI_IOC_STATE_READY)
11368 +                               printk(MYIOC_s_ERR_FMT "Failed to come READY "
11369 +                                   "after reset! IocState=%x", ioc->name,
11370 +                                   doorbell);
11371                 }
11372         }
11373  
11374         diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
11375 -       if (ioc->debug_level & MPT_DEBUG) {
11376 +       if (ioc->debug_level & MPT_DEBUG_RESET) {
11377                 if (ioc->alt_ioc)
11378                         diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
11379 -               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
11380 +               drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
11381                         ioc->name, diag0val, diag1val));
11382         }
11383  
11384 @@ -3898,11 +4076,10 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11385                 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
11386  
11387                 /* wait 100 msec */
11388 -               if (sleepFlag == CAN_SLEEP) {
11389 +               if (sleepFlag == CAN_SLEEP)
11390                         msleep (100);
11391 -               } else {
11392 +               else
11393                         mdelay (100);
11394 -               }
11395  
11396                 count++;
11397                 if (count > 20) {
11398 @@ -3933,11 +4110,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11399                 return -3;
11400         }
11401  
11402 -       if (ioc->debug_level & MPT_DEBUG) {
11403 +       if (ioc->debug_level & MPT_DEBUG_RESET) {
11404                 if (ioc->alt_ioc)
11405                         diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
11406 -               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
11407 -                       ioc->name, diag0val, diag1val));
11408 +               drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
11409 +                               ioc->name, diag0val, diag1val));
11410         }
11411  
11412         /*
11413 @@ -3951,7 +4128,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11414         return hard_reset_done;
11415  }
11416  
11417 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11418  /**
11419   *     SendIocReset - Send IOCReset request to MPT adapter.
11420   *     @ioc: Pointer to MPT_ADAPTER structure
11421 @@ -3962,7 +4138,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
11422   *     Send IOCReset request to the MPT adapter.
11423   *
11424   *     Returns 0 for success, non-zero for failure.
11425 - */
11426 + **/
11427  static int
11428  SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
11429  {
11430 @@ -3973,7 +4149,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_
11431         drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
11432                         ioc->name, reset_type));
11433         CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
11434 -       if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
11435 +       if ((r = WaitForDoorbellAck(ioc, 15, sleepFlag)) < 0)
11436                 return r;
11437  
11438         /* FW ACK'd request, wait for READY state
11439 @@ -3988,15 +4164,15 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_
11440                         if (sleepFlag != CAN_SLEEP)
11441                                 count *= 10;
11442  
11443 -                       printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
11444 -                           ioc->name, (int)((count+5)/HZ));
11445 +                       printk(MYIOC_s_ERR_FMT "Wait IOC_READY state (0x%x) timeout(%d)!\n",
11446 +                                       ioc->name, state, (int)((count+5)/HZ));
11447                         return -ETIME;
11448                 }
11449  
11450                 if (sleepFlag == CAN_SLEEP) {
11451                         msleep(1);
11452                 } else {
11453 -                       mdelay (1);     /* 1 msec delay */
11454 +                       mdelay(1);      /* 1 msec delay */
11455                 }
11456         }
11457  
11458 @@ -4010,14 +4186,13 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_
11459         return 0;
11460  }
11461  
11462 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11463  /**
11464   *     initChainBuffers - Allocate memory for and initialize chain buffers
11465   *     @ioc: Pointer to MPT_ADAPTER structure
11466   *
11467   *     Allocates memory for and initializes chain buffers,
11468   *     chain buffer control arrays and spinlock.
11469 - */
11470 + **/
11471  static int
11472  initChainBuffers(MPT_ADAPTER *ioc)
11473  {
11474 @@ -4059,24 +4234,30 @@ initChainBuffers(MPT_ADAPTER *ioc)
11475          * num_sge = num sge in request frame + last chain buffer
11476          * scale = num sge per chain buffer if no chain element
11477          */
11478 -       scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
11479 -       if (sizeof(dma_addr_t) == sizeof(u64))
11480 -               num_sge =  scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
11481 +       scale = ioc->req_sz/ ioc->SGE_size;
11482 +       if (ioc->sg_addr_size == sizeof(u64))
11483 +               num_sge =  scale + (ioc->req_sz - 60) / ioc->SGE_size;
11484         else
11485 -               num_sge =  1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
11486 +               num_sge =  1+ scale + (ioc->req_sz - 64) / ioc->SGE_size;
11487  
11488 -       if (sizeof(dma_addr_t) == sizeof(u64)) {
11489 +       if (ioc->sg_addr_size == sizeof(u64)) {
11490                 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
11491 -                       (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
11492 +                       (ioc->req_sz - 60) / ioc->SGE_size;
11493         } else {
11494                 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
11495 -                       (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
11496 +                       (ioc->req_sz - 64) / ioc->SGE_size;
11497         }
11498         dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
11499                 ioc->name, num_sge, numSGE));
11500  
11501 -       if ( numSGE > MPT_SCSI_SG_DEPTH )
11502 -               numSGE = MPT_SCSI_SG_DEPTH;
11503 +       if (ioc->bus_type == FC) {
11504 +               if (numSGE > MPT_SCSI_FC_SG_DEPTH)
11505 +                       numSGE = MPT_SCSI_FC_SG_DEPTH;
11506 +       }
11507 +       else {
11508 +               if (numSGE > MPT_SCSI_SG_DEPTH)
11509 +                       numSGE = MPT_SCSI_SG_DEPTH;
11510 +       }
11511  
11512         num_chain = 1;
11513         while (numSGE - num_sge > 0) {
11514 @@ -4111,7 +4292,6 @@ initChainBuffers(MPT_ADAPTER *ioc)
11515         return num_chain;
11516  }
11517  
11518 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11519  /**
11520   *     PrimeIocFifos - Initialize IOC request and reply FIFOs.
11521   *     @ioc: Pointer to MPT_ADAPTER structure
11522 @@ -4121,7 +4301,7 @@ initChainBuffers(MPT_ADAPTER *ioc)
11523   *     reply frames.
11524   *
11525   *     Returns 0 for success, non-zero for failure.
11526 - */
11527 + **/
11528  static int
11529  PrimeIocFifos(MPT_ADAPTER *ioc)
11530  {
11531 @@ -4130,13 +4310,36 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
11532         dma_addr_t alloc_dma;
11533         u8 *mem;
11534         int i, reply_sz, sz, total_size, num_chain;
11535 +       u64     dma_mask;
11536  
11537 -       /*  Prime reply FIFO...  */
11538 +       dma_mask = 0;
11539  
11540 +       /*  Prime reply FIFO...  */
11541         if (ioc->reply_frames == NULL) {
11542                 if ( (num_chain = initChainBuffers(ioc)) < 0)
11543                         return -1;
11544  
11545 +               /*
11546 +                * 1078 errata workaround for the 36GB limitation
11547 +                */
11548 +               if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078 &&
11549 +                   ioc->dma_mask > MPT_DMA_35BIT_MASK) {
11550 +                       if (!pci_set_dma_mask(ioc->pcidev, DMA_32BIT_MASK)
11551 +                           && !pci_set_consistent_dma_mask(ioc->pcidev,
11552 +                           DMA_32BIT_MASK)) {
11553 +                               dma_mask = MPT_DMA_35BIT_MASK;
11554 +                               d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11555 +                                   "setting 35 bit addressing for "
11556 +                                   "Request/Reply/Chain and Sense Buffers\n",
11557 +                                   ioc->name));
11558 +                       } else {
11559 +                               d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11560 +                                   "failed setting 35 bit addressing for "
11561 +                                   "Request/Reply/Chain and Sense Buffers\n",
11562 +                                   ioc->name));
11563 +                       }
11564 +               }
11565 +
11566                 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
11567                 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
11568                                 ioc->name, ioc->reply_sz, ioc->reply_depth));
11569 @@ -4274,9 +4477,16 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
11570                 alloc_dma += ioc->reply_sz;
11571         }
11572  
11573 +       if (dma_mask == MPT_DMA_35BIT_MASK && !pci_set_dma_mask(ioc->pcidev,
11574 +           ioc->dma_mask) && !pci_set_consistent_dma_mask(ioc->pcidev,
11575 +           ioc->dma_mask))
11576 +               d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11577 +                   "restoring 64 bit addressing\n", ioc->name));
11578 +
11579         return 0;
11580  
11581  out_fail:
11582 +
11583         if (ioc->alloc != NULL) {
11584                 sz = ioc->alloc_sz;
11585                 pci_free_consistent(ioc->pcidev,
11586 @@ -4293,10 +4503,16 @@ out_fail:
11587                                 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
11588                 ioc->sense_buf_pool = NULL;
11589         }
11590 +
11591 +       if (dma_mask == MPT_DMA_35BIT_MASK && !pci_set_dma_mask(ioc->pcidev,
11592 +           DMA_64BIT_MASK) && !pci_set_consistent_dma_mask(ioc->pcidev,
11593 +           DMA_64BIT_MASK))
11594 +               d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11595 +                   "restoring 64 bit addressing\n", ioc->name));
11596 +
11597         return -1;
11598  }
11599  
11600 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11601  /**
11602   *     mpt_handshake_req_reply_wait - Send MPT request to and receive reply
11603   *     from IOC via doorbell handshake method.
11604 @@ -4314,7 +4530,7 @@ out_fail:
11605   *     greater than 1 byte in size.
11606   *
11607   *     Returns 0 for success, non-zero for failure.
11608 - */
11609 + **/
11610  static int
11611  mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
11612                 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
11613 @@ -4408,7 +4624,6 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER
11614         return -failcnt;
11615  }
11616  
11617 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11618  /**
11619   *     WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
11620   *     @ioc: Pointer to MPT_ADAPTER structure
11621 @@ -4420,7 +4635,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER
11622   *     bit in its IntStatus register being clear.
11623   *
11624   *     Returns a negative value on failure, else wait loop count.
11625 - */
11626 + **/
11627  static int
11628  WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
11629  {
11630 @@ -4459,7 +4674,6 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int
11631         return -1;
11632  }
11633  
11634 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11635  /**
11636   *     WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
11637   *     @ioc: Pointer to MPT_ADAPTER structure
11638 @@ -4470,7 +4684,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int
11639   *     (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
11640   *
11641   *     Returns a negative value on failure, else wait loop count.
11642 - */
11643 + **/
11644  static int
11645  WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
11646  {
11647 @@ -4481,18 +4695,18 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
11648         cntdn = 1000 * howlong;
11649         if (sleepFlag == CAN_SLEEP) {
11650                 while (--cntdn) {
11651 +                       msleep(1);
11652                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
11653                         if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
11654                                 break;
11655 -                       msleep(1);
11656                         count++;
11657                 }
11658         } else {
11659                 while (--cntdn) {
11660 +                       udelay (1000);
11661                         intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
11662                         if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
11663                                 break;
11664 -                       udelay (1000);
11665                         count++;
11666                 }
11667         }
11668 @@ -4508,7 +4722,6 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
11669         return -1;
11670  }
11671  
11672 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11673  /**
11674   *     WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
11675   *     @ioc: Pointer to MPT_ADAPTER structure
11676 @@ -4520,7 +4733,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
11677   *     of 128 bytes of reply data.
11678   *
11679   *     Returns a negative value on failure, else size of reply in WORDS.
11680 - */
11681 + **/
11682  static int
11683  WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
11684  {
11685 @@ -4594,7 +4807,6 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, i
11686         return u16cnt/2;
11687  }
11688  
11689 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11690  /**
11691   *     GetLanConfigPages - Fetch LANConfig pages.
11692   *     @ioc: Pointer to MPT_ADAPTER structure
11693 @@ -4604,7 +4816,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, i
11694   *             -EPERM if not allowed due to ISR context
11695   *             -EAGAIN if no msg frames currently available
11696   *             -EFAULT for non-successful reply or no reply (timeout)
11697 - */
11698 + **/
11699  static int
11700  GetLanConfigPages(MPT_ADAPTER *ioc)
11701  {
11702 @@ -4705,7 +4917,6 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
11703         return rc;
11704  }
11705  
11706 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11707  /**
11708   *     mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
11709   *     @ioc: Pointer to MPT_ADAPTER structure
11710 @@ -4718,9 +4929,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
11711   *     NOTE: Don't use not this function during interrupt time.
11712   *
11713   *     Returns 0 for success, non-zero error
11714 - */
11715 -
11716 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11717 + **/
11718  int
11719  mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
11720  {
11721 @@ -4728,7 +4937,14 @@ mptbase_sas_persist_operation(MPT_ADAPTE
11722         SasIoUnitControlReply_t         *sasIoUnitCntrReply;
11723         MPT_FRAME_HDR                   *mf = NULL;
11724         MPIHeader_t                     *mpi_hdr;
11725 +       int                             ret = 0;
11726 +       unsigned long                   timeleft;
11727 +
11728 +       mutex_lock(&ioc->mptbase_cmds.mutex);
11729  
11730 +       /* init the internal cmd struct */
11731 +       memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
11732 +       INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
11733  
11734         /* insure garbage is not sent to fw */
11735         switch(persist_opcode) {
11736 @@ -4738,17 +4954,18 @@ mptbase_sas_persist_operation(MPT_ADAPTE
11737                 break;
11738  
11739         default:
11740 -               return -1;
11741 -               break;
11742 +               ret = -1;
11743 +               goto out;
11744         }
11745  
11746 -       printk("%s: persist_opcode=%x\n",__func__, persist_opcode);
11747 +       printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
11748  
11749         /* Get a MF for this command.
11750          */
11751         if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
11752 -               printk("%s: no msg frames!\n",__func__);
11753 -               return -1;
11754 +               printk("%s: no msg frames!\n",__FUNCTION__);
11755 +               ret = -1;
11756 +               goto out;
11757          }
11758  
11759         mpi_hdr = (MPIHeader_t *) mf;
11760 @@ -4758,31 +4975,44 @@ mptbase_sas_persist_operation(MPT_ADAPTE
11761         sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
11762         sasIoUnitCntrReq->Operation = persist_opcode;
11763  
11764 -       init_timer(&ioc->persist_timer);
11765 -       ioc->persist_timer.data = (unsigned long) ioc;
11766 -       ioc->persist_timer.function = mpt_timer_expired;
11767 -       ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
11768 -       ioc->persist_wait_done=0;
11769 -       add_timer(&ioc->persist_timer);
11770         mpt_put_msg_frame(mpt_base_index, ioc, mf);
11771 -       wait_event(mpt_waitq, ioc->persist_wait_done);
11772 +       timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 10*HZ);
11773 +       if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
11774 +               ret = -ETIME;
11775 +               printk("%s: failed\n", __FUNCTION__);
11776 +               if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
11777 +                       goto out;
11778 +               if (!timeleft) {
11779 +                       printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
11780 +                           ioc->name, __FUNCTION__);
11781 +                       if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
11782 +                               mpt_HardResetHandler(ioc, CAN_SLEEP);
11783 +                       mpt_free_msg_frame(ioc, mf);
11784 +               }
11785 +               goto out;
11786 +       }
11787 +
11788 +       if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
11789 +               ret = -1;
11790 +               goto out;
11791 +       }
11792  
11793         sasIoUnitCntrReply =
11794 -           (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
11795 +           (SasIoUnitControlReply_t *)ioc->mptbase_cmds.reply;
11796         if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
11797 -               printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
11798 -                   __func__,
11799 -                   sasIoUnitCntrReply->IOCStatus,
11800 -                   sasIoUnitCntrReply->IOCLogInfo);
11801 -               return -1;
11802 -       }
11803 +               printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", __FUNCTION__,
11804 +                   sasIoUnitCntrReply->IOCStatus, sasIoUnitCntrReply->IOCLogInfo);
11805 +               printk("%s: failed\n",__FUNCTION__);
11806 +               ret = -1;
11807 +       } else
11808 +               printk("%s: success\n",__FUNCTION__);
11809 + out:
11810  
11811 -       printk("%s: success\n",__func__);
11812 -       return 0;
11813 +       CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
11814 +       mutex_unlock(&ioc->mptbase_cmds.mutex);
11815 +       return ret;
11816  }
11817  
11818 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11819 -
11820  static void
11821  mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
11822      MpiEventDataRaid_t * pRaidEventData)
11823 @@ -4913,7 +5143,6 @@ mptbase_raid_process_event_data(MPT_ADAP
11824         }
11825  }
11826  
11827 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11828  /**
11829   *     GetIoUnitPage2 - Retrieve BIOS version and boot order information.
11830   *     @ioc: Pointer to MPT_ADAPTER structure
11831 @@ -4923,7 +5152,7 @@ mptbase_raid_process_event_data(MPT_ADAP
11832   *             -EPERM if not allowed due to ISR context
11833   *             -EAGAIN if no msg frames currently available
11834   *             -EFAULT for non-successful reply or no reply (timeout)
11835 - */
11836 + **/
11837  static int
11838  GetIoUnitPage2(MPT_ADAPTER *ioc)
11839  {
11840 @@ -4971,7 +5200,6 @@ GetIoUnitPage2(MPT_ADAPTER *ioc)
11841         return rc;
11842  }
11843  
11844 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11845  /**
11846   *     mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
11847   *     @ioc: Pointer to a Adapter Strucutre
11848 @@ -4991,7 +5219,7 @@ GetIoUnitPage2(MPT_ADAPTER *ioc)
11849   *             Both valid
11850   *             Return 0
11851   *     CHECK - what type of locking mechanisms should be used????
11852 - */
11853 + **/
11854  static int
11855  mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
11856  {
11857 @@ -5051,8 +5279,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
11858                                 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
11859                                 rc = 1;
11860                                 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11861 -                                       "Unable to read PortPage0 minSyncFactor=%x\n",
11862 -                                       ioc->name, ioc->spi_data.minSyncFactor));
11863 +                                   "Unable to read PortPage0 minSyncFactor=%x\n",
11864 +                                   ioc->name, ioc->spi_data.minSyncFactor));
11865                         } else {
11866                                 /* Save the Port Page 0 data
11867                                  */
11868 @@ -5062,8 +5290,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
11869  
11870                                 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
11871                                         ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
11872 -                                       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11873 -                                               "noQas due to Capabilities=%x\n",
11874 +                                       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "noQas due to Capabilities=%x\n",
11875                                                 ioc->name, pPP0->Capabilities));
11876                                 }
11877                                 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
11878 @@ -5072,8 +5299,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
11879                                         ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
11880                                         data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
11881                                         ioc->spi_data.minSyncFactor = (u8) (data >> 8);
11882 -                                       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11883 -                                               "PortPage0 minSyncFactor=%x\n",
11884 +                                       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PortPage0 minSyncFactor=%x\n",
11885                                                 ioc->name, ioc->spi_data.minSyncFactor));
11886                                 } else {
11887                                         ioc->spi_data.maxSyncOffset = 0;
11888 @@ -5089,8 +5315,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
11889  
11890                                         if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
11891                                                 ioc->spi_data.minSyncFactor = MPT_ULTRA;
11892 -                                               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
11893 -                                                       "HVD or SE detected, minSyncFactor=%x\n",
11894 +                                               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HVD or SE detected, minSyncFactor=%x\n",
11895                                                         ioc->name, ioc->spi_data.minSyncFactor));
11896                                         }
11897                                 }
11898 @@ -5195,7 +5420,6 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
11899         return rc;
11900  }
11901  
11902 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11903  /**
11904   *     mpt_readScsiDevicePageHeaders - save version and length of SDP1
11905   *     @ioc: Pointer to a Adapter Strucutre
11906 @@ -5203,7 +5427,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
11907   *
11908   *     Return: -EFAULT if read of config page header fails
11909   *             or 0 if success.
11910 - */
11911 + **/
11912  static int
11913  mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
11914  {
11915 @@ -5246,9 +5470,73 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTE
11916         return 0;
11917  }
11918  
11919 +static void
11920 +mpt_read_ioc_pg_6(MPT_ADAPTER *ioc)
11921 +{
11922 +       CONFIGPARMS              cfg;
11923 +       ConfigPageHeader_t       header;
11924 +       IOCPage6_t              *pIoc6=NULL;
11925 +       dma_addr_t               ioc6_dma;
11926 +       int                      iocpage6sz;
11927 +       void                    *mem;
11928 +
11929 +       /* Free the old page
11930 +        */
11931 +       if (ioc->raid_data.pIocPg6) {
11932 +               kfree(ioc->raid_data.pIocPg6);
11933 +               ioc->raid_data.pIocPg6 = NULL;
11934 +       }
11935 +
11936 +       /* There is at least one physical disk.
11937 +        * Read and save IOC Page 3
11938 +        */
11939 +       header.PageVersion = 0;
11940 +       header.PageLength = 0;
11941 +       header.PageNumber = 6;
11942 +       header.PageType = MPI_CONFIG_PAGETYPE_IOC;
11943 +       cfg.cfghdr.hdr = &header;
11944 +       cfg.physAddr = -1;
11945 +       cfg.pageAddr = 0;
11946 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
11947 +       cfg.dir = 0;
11948 +       cfg.timeout = 0;
11949 +       if (mpt_config(ioc, &cfg) != 0)
11950 +               goto out;
11951 +
11952 +       if (header.PageLength == 0)
11953 +               goto out;
11954 +
11955 +       /* Read Header good, alloc memory
11956 +        */
11957 +       iocpage6sz = header.PageLength * 4;
11958 +       pIoc6 = pci_alloc_consistent(ioc->pcidev, iocpage6sz, &ioc6_dma);
11959 +       if (!pIoc6)
11960 +               goto out;
11961 +
11962 +       /* Read the Page and save the data
11963 +        * into malloc'd memory.
11964 +        */
11965 +       cfg.physAddr = ioc6_dma;
11966 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
11967 +       if (mpt_config(ioc, &cfg) != 0)
11968 +               goto out;
11969 +
11970 +       mem = kmalloc(iocpage6sz, GFP_ATOMIC);
11971 +       if (!mem)
11972 +               goto out;
11973 +
11974 +       memcpy(mem, pIoc6, iocpage6sz);
11975 +       ioc->raid_data.pIocPg6 = mem;
11976 +
11977 + out:
11978 +       if (pIoc6)
11979 +               pci_free_consistent(ioc->pcidev, iocpage6sz, pIoc6, ioc6_dma);
11980 +}
11981 +
11982  /**
11983 - * mpt_inactive_raid_list_free - This clears this link list.
11984 - * @ioc : pointer to per adapter structure
11985 +  * mpt_inactive_raid_list_free - This clears this link list.
11986 +  * @ioc : pointer to per adapter structure
11987 +  *
11988   **/
11989  static void
11990  mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
11991 @@ -5258,21 +5546,23 @@ mpt_inactive_raid_list_free(MPT_ADAPTER 
11992         if (list_empty(&ioc->raid_data.inactive_list))
11993                 return;
11994  
11995 -       mutex_lock(&ioc->raid_data.inactive_list_mutex);
11996 +       down(&ioc->raid_data.inactive_list_mutex);
11997         list_for_each_entry_safe(component_info, pNext,
11998             &ioc->raid_data.inactive_list, list) {
11999                 list_del(&component_info->list);
12000                 kfree(component_info);
12001         }
12002 -       mutex_unlock(&ioc->raid_data.inactive_list_mutex);
12003 +       up(&ioc->raid_data.inactive_list_mutex);
12004  }
12005  
12006  /**
12007 - * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
12008 - *
12009 - * @ioc : pointer to per adapter structure
12010 - * @channel : volume channel
12011 - * @id : volume target id
12012 +  * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums
12013 +  * for devices belonging in an inactive volume
12014 +  *
12015 +  * @ioc : pointer to per adapter structure
12016 +  * @channel : volume channel
12017 +  * @id : volume target id
12018 +  *
12019   **/
12020  static void
12021  mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
12022 @@ -5281,10 +5571,12 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *i
12023         ConfigPageHeader_t              hdr;
12024         dma_addr_t                      dma_handle;
12025         pRaidVolumePage0_t              buffer = NULL;
12026 -       int                             i;
12027 +       int                             i, j;
12028         RaidPhysDiskPage0_t             phys_disk;
12029 +       RaidPhysDiskPage1_t             *phys_disk_1;
12030         struct inactive_raid_component_info *component_info;
12031         int                             handle_inactive_volumes;
12032 +       int                             num_paths, device_is_online;
12033  
12034         memset(&cfg, 0 , sizeof(CONFIGPARMS));
12035         memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
12036 @@ -5323,14 +5615,37 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *i
12037         if (!handle_inactive_volumes)
12038                 goto out;
12039  
12040 -       mutex_lock(&ioc->raid_data.inactive_list_mutex);
12041 +       down(&ioc->raid_data.inactive_list_mutex);
12042         for (i = 0; i < buffer->NumPhysDisks; i++) {
12043                 if(mpt_raid_phys_disk_pg0(ioc,
12044                     buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
12045                         continue;
12046  
12047 +               if (phys_disk.PhysDiskStatus.State !=
12048 +                   MPI_PHYSDISK0_STATUS_ONLINE)
12049 +                       continue;
12050 +
12051 +               /* check to see if device is online by checking phys_disk_pg1 */
12052 +               device_is_online = 0;
12053 +               num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
12054 +                   buffer->PhysDisk[i].PhysDiskNum);
12055 +               if (num_paths < 2)
12056 +                       continue;
12057 +               phys_disk_1 = kzalloc(offsetof(RaidPhysDiskPage1_t,Path) +
12058 +                  (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
12059 +               if (!phys_disk_1)
12060 +                       continue;
12061 +               mpt_raid_phys_disk_pg1(ioc, buffer->PhysDisk[i].PhysDiskNum,
12062 +                   phys_disk_1);
12063 +               for (j = 0; j < num_paths && !device_is_online; j++)
12064 +                       if (!phys_disk_1->Path[j].Flags)
12065 +                               device_is_online = 1;
12066 +               kfree(phys_disk_1);
12067 +               if (!device_is_online)
12068 +                       continue;
12069 +
12070                 if ((component_info = kmalloc(sizeof (*component_info),
12071 -                GFP_KERNEL)) == NULL)
12072 +                   GFP_KERNEL)) == NULL)
12073                         continue;
12074  
12075                 component_info->volumeID = id;
12076 @@ -5343,7 +5658,7 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *i
12077                 list_add_tail(&component_info->list,
12078                     &ioc->raid_data.inactive_list);
12079         }
12080 -       mutex_unlock(&ioc->raid_data.inactive_list_mutex);
12081 +       up(&ioc->raid_data.inactive_list_mutex);
12082  
12083   out:
12084         if (buffer)
12085 @@ -5363,7 +5678,7 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *i
12086   *     -ENOMEM if pci_alloc failed
12087   **/
12088  int
12089 -mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
12090 +mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, RaidPhysDiskPage0_t *phys_disk)
12091  {
12092         CONFIGPARMS                     cfg;
12093         ConfigPageHeader_t              hdr;
12094 @@ -5373,7 +5688,9 @@ mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc,
12095  
12096         memset(&cfg, 0 , sizeof(CONFIGPARMS));
12097         memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
12098 +       memset(phys_disk, 0, sizeof(RaidPhysDiskPage0_t));
12099  
12100 +       hdr.PageVersion = MPI_RAIDPHYSDISKPAGE0_PAGEVERSION;
12101         hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
12102         cfg.cfghdr.hdr = &hdr;
12103         cfg.physAddr = -1;
12104 @@ -5420,6 +5737,181 @@ mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc,
12105  }
12106  
12107  /**
12108 + *     mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num
12109 + *     @ioc: Pointer to a Adapter Structure
12110 + *     @phys_disk_num: io unit unique phys disk num generated by the ioc
12111 + *
12112 + *     Return:
12113 + *     returns number paths
12114 + **/
12115 +int
12116 +mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num)
12117 +{
12118 +       CONFIGPARMS                     cfg;
12119 +       ConfigPageHeader_t              hdr;
12120 +       dma_addr_t                      dma_handle;
12121 +       pRaidPhysDiskPage1_t            buffer = NULL;
12122 +       int                             rc;
12123 +
12124 +       memset(&cfg, 0 , sizeof(CONFIGPARMS));
12125 +       memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
12126 +
12127 +       hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
12128 +       hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
12129 +       hdr.PageNumber = 1;
12130 +       cfg.cfghdr.hdr = &hdr;
12131 +       cfg.physAddr = -1;
12132 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
12133 +
12134 +       if (mpt_config(ioc, &cfg) != 0) {
12135 +               rc = 0;
12136 +               goto out;
12137 +       }
12138 +
12139 +       if (!hdr.PageLength) {
12140 +               rc = 0;
12141 +               goto out;
12142 +       }
12143 +
12144 +       buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
12145 +           &dma_handle);
12146 +
12147 +       if (!buffer) {
12148 +               rc = 0;
12149 +               goto out;
12150 +       }
12151 +
12152 +       cfg.physAddr = dma_handle;
12153 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
12154 +       cfg.pageAddr = phys_disk_num;
12155 +
12156 +       if (mpt_config(ioc, &cfg) != 0) {
12157 +               rc = 0;
12158 +               goto out;
12159 +       }
12160 +
12161 +       rc = buffer->NumPhysDiskPaths;
12162 + out:
12163 +
12164 +       if (buffer)
12165 +               pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
12166 +                   dma_handle);
12167 +
12168 +       return rc;
12169 +}
12170 +
12171 +/**
12172 + *     mpt_raid_phys_disk_pg1 - returns phys disk page 1
12173 + *     @ioc: Pointer to a Adapter Structure
12174 + *     @phys_disk_num: io unit unique phys disk num generated by the ioc
12175 + *     @phys_disk: requested payload data returned
12176 + *
12177 + *     Return:
12178 + *     0 on success
12179 + *     -EFAULT if read of config page header fails or data pointer not NULL
12180 + *     -ENOMEM if pci_alloc failed
12181 + **/
12182 +int
12183 +mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, RaidPhysDiskPage1_t *phys_disk)
12184 +{
12185 +       CONFIGPARMS                     cfg;
12186 +       ConfigPageHeader_t              hdr;
12187 +       dma_addr_t                      dma_handle;
12188 +       pRaidPhysDiskPage1_t            buffer = NULL;
12189 +       int                             rc;
12190 +       int                             i;
12191 +       __le64                          sas_address;
12192 +
12193 +       memset(&cfg, 0 , sizeof(CONFIGPARMS));
12194 +       memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
12195 +       rc = 0;
12196 +
12197 +       hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
12198 +       hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
12199 +       hdr.PageNumber = 1;
12200 +       cfg.cfghdr.hdr = &hdr;
12201 +       cfg.physAddr = -1;
12202 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
12203 +
12204 +       if (mpt_config(ioc, &cfg) != 0) {
12205 +               rc = -EFAULT;
12206 +               goto out;
12207 +       }
12208 +
12209 +       if (!hdr.PageLength) {
12210 +               rc = -EFAULT;
12211 +               goto out;
12212 +       }
12213 +
12214 +       buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
12215 +           &dma_handle);
12216 +
12217 +       if (!buffer) {
12218 +               rc = -ENOMEM;
12219 +               goto out;
12220 +       }
12221 +
12222 +       cfg.physAddr = dma_handle;
12223 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
12224 +       cfg.pageAddr = phys_disk_num;
12225 +
12226 +       if (mpt_config(ioc, &cfg) != 0) {
12227 +               rc = -EFAULT;
12228 +               goto out;
12229 +       }
12230 +
12231 +       phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths;
12232 +       phys_disk->PhysDiskNum = phys_disk_num;
12233 +       for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) {
12234 +               phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID;
12235 +               phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus;
12236 +               phys_disk->Path[i].OwnerIdentifier = buffer->Path[i].OwnerIdentifier;
12237 +               phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags);
12238 +               memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64));
12239 +               sas_address = le64_to_cpu(sas_address);
12240 +               memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64));
12241 +               memcpy(&sas_address, &buffer->Path[i].OwnerWWID, sizeof(__le64));
12242 +               sas_address = le64_to_cpu(sas_address);
12243 +               memcpy(&phys_disk->Path[i].OwnerWWID, &sas_address, sizeof(__le64));
12244 +       }
12245 +
12246 + out:
12247 +
12248 +       if (buffer)
12249 +               pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
12250 +                   dma_handle);
12251 +
12252 +       return rc;
12253 +}
12254 +
12255 +/**
12256 + *     mpt_sort_ioc_pg2 - compare function for sorting volumes
12257 + *     in ascending order
12258 + *     @a: ioc_pg2 raid volume page
12259 + *     @b: ioc_pg2 raid volume page
12260 + *
12261 + *     Return:
12262 + *     0 same, 1 (a is bigger), -1 (b is bigger)
12263 + **/
12264 +static int
12265 +mpt_sort_ioc_pg2(const void *a, const void *b)
12266 +{
12267 +       ConfigPageIoc2RaidVol_t * volume_a = (ConfigPageIoc2RaidVol_t *)a;
12268 +       ConfigPageIoc2RaidVol_t * volume_b = (ConfigPageIoc2RaidVol_t *)b;
12269 +
12270 +       if (volume_a->VolumeBus == volume_b->VolumeBus) {
12271 +               if (volume_a->VolumeID == volume_b->VolumeID)
12272 +                       return 0;
12273 +               if (volume_a->VolumeID < volume_b->VolumeID)
12274 +                       return -1;
12275 +               return 1;
12276 +       }
12277 +       if (volume_a->VolumeBus < volume_b->VolumeBus)
12278 +               return -1;
12279 +       return 1;
12280 +}
12281 +
12282 +/**
12283   *     mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
12284   *     @ioc: Pointer to a Adapter Strucutre
12285   *     @portnum: IOC port number
12286 @@ -5482,16 +5974,22 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
12287         if (!mem)
12288                 goto out;
12289  
12290 +       /*
12291 +        * sort volumes in ascending order
12292 +        */
12293 +       sort(pIoc2->RaidVolume, pIoc2->NumActiveVolumes,
12294 +           sizeof(ConfigPageIoc2RaidVol_t), mpt_sort_ioc_pg2, NULL);
12295         memcpy(mem, (u8 *)pIoc2, iocpage2sz);
12296         ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
12297  
12298 -       mpt_read_ioc_pg_3(ioc);
12299 -
12300         for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
12301                 mpt_inactive_raid_volumes(ioc,
12302                     pIoc2->RaidVolume[i].VolumeBus,
12303                     pIoc2->RaidVolume[i].VolumeID);
12304  
12305 +       mpt_read_ioc_pg_3(ioc);
12306 +       mpt_read_ioc_pg_6(ioc);
12307 +
12308   out:
12309         pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
12310  
12311 @@ -5651,6 +6149,9 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
12312         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
12313         if (mpt_config(ioc, &cfg) == 0) {
12314  
12315 +#if defined(CPQ_CIM)
12316 +               ioc->pci_slot_number = pIoc1->PCISlotNum;
12317 +#endif
12318                 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
12319                 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
12320                         tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
12321 @@ -5671,19 +6172,16 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
12322  
12323                                         cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
12324                                         if (mpt_config(ioc, &cfg) == 0) {
12325 -                                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12326 -                                                               "Reset NVRAM Coalescing Timeout to = %d\n",
12327 +                                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
12328                                                                 ioc->name, MPT_COALESCING_TIMEOUT));
12329                                         } else {
12330 -                                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12331 -                                                               "Reset NVRAM Coalescing Timeout Failed\n",
12332 -                                                               ioc->name));
12333 +                                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset NVRAM Coalescing Timeout Failed\n",
12334 +                                                                       ioc->name));
12335                                         }
12336  
12337                                 } else {
12338 -                                       dprintk(ioc, printk(MYIOC_s_WARN_FMT
12339 -                                               "Reset of Current Coalescing Timeout Failed!\n",
12340 -                                               ioc->name));
12341 +                                       dprintk(ioc, printk(MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
12342 +                                                               ioc->name));
12343                                 }
12344                         }
12345  
12346 @@ -5740,43 +6238,39 @@ mpt_get_manufacturing_pg_0(MPT_ADAPTER *
12347                 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
12348  }
12349  
12350 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12351  /**
12352   *     SendEventNotification - Send EventNotification (on or off) request to adapter
12353   *     @ioc: Pointer to MPT_ADAPTER structure
12354   *     @EvSwitch: Event switch flags
12355 - */
12356 + *     @sleepFlag: Specifies whether the process can sleep
12357 + **/
12358  static int
12359 -SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
12360 +SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag)
12361  {
12362 -       EventNotification_t     *evnp;
12363 -
12364 -       evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
12365 -       if (evnp == NULL) {
12366 -               devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
12367 -                               ioc->name));
12368 -               return 0;
12369 -       }
12370 -       memset(evnp, 0, sizeof(*evnp));
12371 +       EventNotification_t     evn;
12372 +       MPIDefaultReply_t       reply_buf;
12373  
12374 -       devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
12375 +       memset(&evn, 0, sizeof(EventNotification_t));
12376 +       memset(&reply_buf, 0, sizeof(MPIDefaultReply_t));
12377  
12378 -       evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
12379 -       evnp->ChainOffset = 0;
12380 -       evnp->MsgFlags = 0;
12381 -       evnp->Switch = EvSwitch;
12382 +       evn.Function = MPI_FUNCTION_EVENT_NOTIFICATION;
12383 +       evn.Switch = EvSwitch;
12384 +       evn.MsgContext = cpu_to_le32(mpt_base_index << 16);
12385  
12386 -       mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
12387 +       devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12388 +           "Sending EventNotification (%d) request %p\n",
12389 +           ioc->name, EvSwitch, &evn));
12390  
12391 -       return 0;
12392 +       return mpt_handshake_req_reply_wait(ioc, sizeof(EventNotification_t),
12393 +           (u32*)&evn, sizeof(MPIDefaultReply_t), (u16*)&reply_buf, 30,
12394 +           sleepFlag);
12395  }
12396  
12397 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12398  /**
12399   *     SendEventAck - Send EventAck request to MPT adapter.
12400   *     @ioc: Pointer to MPT_ADAPTER structure
12401   *     @evnp: Pointer to original EventNotification request
12402 - */
12403 + **/
12404  static int
12405  SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
12406  {
12407 @@ -5784,7 +6278,7 @@ SendEventAck(MPT_ADAPTER *ioc, EventNoti
12408  
12409         if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
12410                 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
12411 -                   ioc->name,__func__));
12412 +                   ioc->name,__FUNCTION__));
12413                 return -1;
12414         }
12415  
12416 @@ -5803,7 +6297,6 @@ SendEventAck(MPT_ADAPTER *ioc, EventNoti
12417         return 0;
12418  }
12419  
12420 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12421  /**
12422   *     mpt_config - Generic function to issue config message
12423   *     @ioc:   Pointer to an adapter structure
12424 @@ -5816,35 +6309,62 @@ SendEventAck(MPT_ADAPTER *ioc, EventNoti
12425   *     -EPERM if not allowed due to ISR context
12426   *     -EAGAIN if no msg frames currently available
12427   *     -EFAULT for non-successful reply or no reply (timeout)
12428 - */
12429 + **/
12430  int
12431  mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
12432  {
12433         Config_t        *pReq;
12434 +       ConfigReply_t   *pReply;
12435         ConfigExtendedPageHeader_t  *pExtHdr = NULL;
12436         MPT_FRAME_HDR   *mf;
12437 -       unsigned long    flags;
12438 -       int              ii, rc;
12439 +       int              ii;
12440         int              flagsLength;
12441 -       int              in_isr;
12442 +       long             timeout;
12443 +       int              ret;
12444 +       u8               page_type = 0, extend_page;
12445 +       unsigned long    timeleft;
12446 +       unsigned long    flags;
12447 +       u8               issue_hard_reset = 0;
12448 +       u8               retry_count = 0;
12449  
12450 -       /*      Prevent calling wait_event() (below), if caller happens
12451 -        *      to be in ISR context, because that is fatal!
12452 -        */
12453 -       in_isr = in_interrupt();
12454 -       if (in_isr) {
12455 -               dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
12456 -                               ioc->name));
12457 +       if (in_interrupt())
12458                 return -EPERM;
12459 +
12460 +       /* don't send a config page during diag reset */
12461 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
12462 +       if (ioc->ioc_reset_in_progress) {
12463 +               dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12464 +                   "%s: busy with host reset\n", ioc->name, __FUNCTION__));
12465 +               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
12466 +               return -EBUSY;
12467 +       }
12468 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
12469 +
12470 +       /* don't send if no chance of success */
12471 +       if (!ioc->active ||
12472 +           mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_OPERATIONAL) {
12473 +               dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12474 +                   "%s: ioc not operational, %d, %xh\n",
12475 +                   ioc->name, __FUNCTION__, ioc->active,
12476 +                   mpt_GetIocState(ioc, 0)));
12477 +               return -EFAULT;
12478         }
12479  
12480 + retry_config:
12481 +       mutex_lock(&ioc->mptbase_cmds.mutex);
12482 +       /* init the internal cmd struct */
12483 +       memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
12484 +       INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
12485 +
12486         /* Get and Populate a free Frame
12487          */
12488         if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
12489 -               dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
12490 -                               ioc->name));
12491 -               return -EAGAIN;
12492 +               dcprintk(ioc, printk(MYIOC_s_WARN_FMT
12493 +               "mpt_config: no msg frames!\n", ioc->name));
12494 +               ret = -EAGAIN;
12495 +               goto out;
12496         }
12497 +
12498         pReq = (Config_t *)mf;
12499         pReq->Action = pCfg->action;
12500         pReq->Reserved = 0;
12501 @@ -5870,7 +6390,9 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
12502                 pReq->ExtPageType = pExtHdr->ExtPageType;
12503                 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
12504  
12505 -               /* Page Length must be treated as a reserved field for the extended header. */
12506 +               /* Page Length must be treated as a reserved field for the
12507 +                * extended header.
12508 +                */
12509                 pReq->Header.PageLength = 0;
12510         }
12511  
12512 @@ -5883,126 +6405,126 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
12513         else
12514                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
12515  
12516 -       if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
12517 +       if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) ==
12518 +           MPI_CONFIG_PAGETYPE_EXTENDED) {
12519                 flagsLength |= pExtHdr->ExtPageLength * 4;
12520 -
12521 -               dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
12522 -                       ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
12523 -       }
12524 -       else {
12525 +               page_type = pReq->ExtPageType;
12526 +               extend_page = 1;
12527 +       } else {
12528                 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
12529 -
12530 -               dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
12531 -                       ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
12532 +               page_type = pReq->Header.PageType;
12533 +               extend_page = 0;
12534         }
12535  
12536 -       mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
12537 +       dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12538 +           "Sending Config request type 0x%x, page 0x%x and action %d\n",
12539 +           ioc->name, page_type, pReq->Header.PageNumber, pReq->Action));
12540  
12541 -       /* Append pCfg pointer to end of mf
12542 -        */
12543 -       *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
12544 -
12545 -       /* Initalize the timer
12546 -        */
12547 -       init_timer(&pCfg->timer);
12548 -       pCfg->timer.data = (unsigned long) ioc;
12549 -       pCfg->timer.function = mpt_timer_expired;
12550 -       pCfg->wait_done = 0;
12551 -
12552 -       /* Set the timer; ensure 10 second minimum */
12553 -       if (pCfg->timeout < 10)
12554 -               pCfg->timer.expires = jiffies + HZ*10;
12555 -       else
12556 -               pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
12557 -
12558 -       /* Add to end of Q, set timer and then issue this command */
12559 -       spin_lock_irqsave(&ioc->FreeQlock, flags);
12560 -       list_add_tail(&pCfg->linkage, &ioc->configQ);
12561 -       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
12562 -
12563 -       add_timer(&pCfg->timer);
12564 +       ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
12565 +       timeout = (pCfg->timeout < 15) ? HZ*15 : HZ*pCfg->timeout;
12566         mpt_put_msg_frame(mpt_base_index, ioc, mf);
12567 -       wait_event(mpt_waitq, pCfg->wait_done);
12568 -
12569 -       /* mf has been freed - do not access */
12570 -
12571 -       rc = pCfg->status;
12572 +       timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, timeout);
12573 +       if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
12574 +               ret = -ETIME;
12575 +               dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12576 +                   "Failed Sending Config request type 0x%x, page 0x%x,"
12577 +                   " action %d, status %xh, time left %ld\n\n",
12578 +                       ioc->name, page_type, pReq->Header.PageNumber,
12579 +                       pReq->Action, ioc->mptbase_cmds.status, timeleft));
12580 +               if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
12581 +                       goto out;
12582 +               if (!timeleft)
12583 +                       issue_hard_reset = 1;
12584 +               goto out;
12585 +       }
12586  
12587 -       return rc;
12588 -}
12589 +       if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
12590 +               ret = -1;
12591 +               goto out;
12592 +       }
12593 +       pReply = (ConfigReply_t *)ioc->mptbase_cmds.reply;
12594 +       ret = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
12595 +       if (ret == MPI_IOCSTATUS_SUCCESS) {
12596 +               if (extend_page) {
12597 +                       pCfg->cfghdr.ehdr->ExtPageLength =
12598 +                           le16_to_cpu(pReply->ExtPageLength);
12599 +                       pCfg->cfghdr.ehdr->ExtPageType =
12600 +                           pReply->ExtPageType;
12601 +               }
12602 +               pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
12603 +               pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
12604 +               pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
12605 +               pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
12606  
12607 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12608 -/**
12609 - *     mpt_timer_expired - Callback for timer process.
12610 - *     Used only internal config functionality.
12611 - *     @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
12612 - */
12613 -static void
12614 -mpt_timer_expired(unsigned long data)
12615 -{
12616 -       MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
12617 +       }
12618  
12619 -       dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name));
12620 +       if (retry_count)
12621 +               printk(MYIOC_s_INFO_FMT "Retry completed ret=0x%x timeleft=%ld\n",
12622 +                   ioc->name, ret, timeleft);
12623  
12624 -       /* Perform a FW reload */
12625 -       if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
12626 -               printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
12627 +       dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n",
12628 +            ret, le32_to_cpu(pReply->IOCLogInfo)));
12629  
12630 -       /* No more processing.
12631 -        * Hard reset clean-up will wake up
12632 -        * process and free all resources.
12633 -        */
12634 -       dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name));
12635 + out:
12636  
12637 -       return;
12638 +       CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
12639 +       mutex_unlock(&ioc->mptbase_cmds.mutex);
12640 +       if (issue_hard_reset) {
12641 +               issue_hard_reset = 0;
12642 +               printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
12643 +                   ioc->name, __FUNCTION__);
12644 +               if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
12645 +                       mpt_HardResetHandler(ioc, CAN_SLEEP);
12646 +               mpt_free_msg_frame(ioc, mf);
12647 +               /* attempt one retry for a timed out command */
12648 +               if (!retry_count) {
12649 +                       printk(MYIOC_s_INFO_FMT
12650 +                           "Attempting Retry Config request type 0x%x, page 0x%x,"
12651 +                           " action %d\n", ioc->name, page_type,
12652 +                           pCfg->cfghdr.hdr->PageNumber, pCfg->action);
12653 +                       retry_count++;
12654 +                       goto retry_config;
12655 +               }
12656 +       }
12657 +       return ret;
12658  }
12659  
12660 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12661 -/**
12662 - *     mpt_ioc_reset - Base cleanup for hard reset
12663 - *     @ioc: Pointer to the adapter structure
12664 - *     @reset_phase: Indicates pre- or post-reset functionality
12665 - *
12666 - *     Remark: Frees resources with internally generated commands.
12667 - */
12668 -static int
12669 -mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
12670 -{
12671 -       CONFIGPARMS *pCfg;
12672 -       unsigned long flags;
12673 -
12674 -       dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12675 -           ": IOC %s_reset routed to MPT base driver!\n",
12676 -           ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
12677 -           reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
12678 -
12679 -       if (reset_phase == MPT_IOC_SETUP_RESET) {
12680 -               ;
12681 -       } else if (reset_phase == MPT_IOC_PRE_RESET) {
12682 -               /* If the internal config Q is not empty -
12683 -                * delete timer. MF resources will be freed when
12684 -                * the FIFO's are primed.
12685 -                */
12686 -               spin_lock_irqsave(&ioc->FreeQlock, flags);
12687 -               list_for_each_entry(pCfg, &ioc->configQ, linkage)
12688 -                       del_timer(&pCfg->timer);
12689 -               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
12690 -
12691 -       } else {
12692 -               CONFIGPARMS *pNext;
12693 -
12694 -               /* Search the configQ for internal commands.
12695 -                * Flush the Q, and wake up all suspended threads.
12696 -                */
12697 -               spin_lock_irqsave(&ioc->FreeQlock, flags);
12698 -               list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
12699 -                       list_del(&pCfg->linkage);
12700 -
12701 -                       pCfg->status = MPT_CONFIG_ERROR;
12702 -                       pCfg->wait_done = 1;
12703 -                       wake_up(&mpt_waitq);
12704 +/**
12705 + *     mpt_ioc_reset - Base cleanup for hard reset
12706 + *     @ioc: Pointer to the adapter structure
12707 + *     @reset_phase: Indicates pre- or post-reset functionality
12708 + *
12709 + *     Remark: Frees resources with internally generated commands.
12710 + **/
12711 +static int
12712 +mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
12713 +{
12714 +       switch(reset_phase) {
12715 +       case MPT_IOC_SETUP_RESET:
12716 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12717 +                   "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __FUNCTION__));
12718 +               ioc->taskmgmt_quiesce_io = 1;
12719 +               break;
12720 +       case MPT_IOC_PRE_RESET:
12721 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12722 +                   "%s: MPT_IOC_PRE_RESET\n", ioc->name, __FUNCTION__));
12723 +               break;
12724 +       case MPT_IOC_POST_RESET:
12725 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12726 +                   "%s: MPT_IOC_POST_RESET\n",  ioc->name, __FUNCTION__));
12727 +/* wake up mptbase_cmds */
12728 +               if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
12729 +                       ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_DID_IOCRESET;
12730 +                       complete(&ioc->mptbase_cmds.done);
12731 +               }
12732 +/* wake up taskmgmt_cmds */
12733 +               if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
12734 +                       ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_DID_IOCRESET;
12735 +                       complete(&ioc->taskmgmt_cmds.done);
12736                 }
12737 -               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
12738 +               break;
12739 +       default:
12740 +               break;
12741         }
12742  
12743         return 1;               /* currently means nothing really */
12744 @@ -6010,16 +6532,11 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int rese
12745  
12746  
12747  #ifdef CONFIG_PROC_FS          /* { */
12748 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12749 -/*
12750 - *     procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
12751 - */
12752 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12753  /**
12754   *     procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
12755   *
12756   *     Returns 0 for success, non-zero for failure.
12757 - */
12758 + **/
12759  static int
12760  procmpt_create(void)
12761  {
12762 @@ -6040,12 +6557,11 @@ procmpt_create(void)
12763         return 0;
12764  }
12765  
12766 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12767  /**
12768   *     procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
12769   *
12770   *     Returns 0 for success, non-zero for failure.
12771 - */
12772 + **/
12773  static void
12774  procmpt_destroy(void)
12775  {
12776 @@ -6054,7 +6570,6 @@ procmpt_destroy(void)
12777         remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
12778  }
12779  
12780 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12781  /**
12782   *     procmpt_summary_read - Handle read request of a summary file
12783   *     @buf: Pointer to area to write information
12784 @@ -6066,7 +6581,7 @@ procmpt_destroy(void)
12785   *
12786   *     Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
12787   *     Returns number of characters written to process performing the read.
12788 - */
12789 + **/
12790  static int
12791  procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
12792  {
12793 @@ -6098,7 +6613,6 @@ procmpt_summary_read(char *buf, char **s
12794         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
12795  }
12796  
12797 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12798  /**
12799   *     procmpt_version_read - Handle read request from /proc/mpt/version.
12800   *     @buf: Pointer to area to write information
12801 @@ -6109,7 +6623,7 @@ procmpt_summary_read(char *buf, char **s
12802   *     @data: Pointer
12803   *
12804   *     Returns number of characters written to process performing the read.
12805 - */
12806 + **/
12807  static int
12808  procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
12809  {
12810 @@ -6154,7 +6668,6 @@ procmpt_version_read(char *buf, char **s
12811         MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
12812  }
12813  
12814 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12815  /**
12816   *     procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
12817   *     @buf: Pointer to area to write information
12818 @@ -6165,7 +6678,7 @@ procmpt_version_read(char *buf, char **s
12819   *     @data: Pointer
12820   *
12821   *     Returns number of characters written to process performing the read.
12822 - */
12823 + **/
12824  static int
12825  procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
12826  {
12827 @@ -6251,7 +6764,6 @@ procmpt_iocinfo_read(char *buf, char **s
12828  
12829  #endif         /* CONFIG_PROC_FS } */
12830  
12831 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12832  static void
12833  mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
12834  {
12835 @@ -6267,7 +6779,6 @@ mpt_get_fw_exp_ver(char *buf, MPT_ADAPTE
12836         }
12837  }
12838  
12839 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12840  /**
12841   *     mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
12842   *     @ioc: Pointer to MPT_ADAPTER structure
12843 @@ -6278,7 +6789,7 @@ mpt_get_fw_exp_ver(char *buf, MPT_ADAPTE
12844   *
12845   *     This routine writes (english readable) ASCII text, which represents
12846   *     a summary of IOC information, to a buffer.
12847 - */
12848 + **/
12849  void
12850  mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
12851  {
12852 @@ -6319,6 +6830,220 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, 
12853  /*
12854   *     Reset Handling
12855   */
12856 +
12857 +/**
12858 + *     mpt_set_taskmgmt_in_progress_flag - set flags associated with task managment
12859 + *     @ioc: Pointer to MPT_ADAPTER structure
12860 + *
12861 + *     Returns 0 for SUCCESS or -1 if FAILED.
12862 + *
12863 + *     If -1 is return, then it was not possible to set the flags
12864 + **/
12865 +int
12866 +mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
12867 +{
12868 +       unsigned long    flags;
12869 +       int              retval;
12870 +
12871 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
12872 +       if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress ||
12873 +           (ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) {
12874 +               retval = -1;
12875 +               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
12876 +               goto out;
12877 +       }
12878 +       retval = 0;
12879 +       ioc->taskmgmt_in_progress = 1;
12880 +       ioc->taskmgmt_quiesce_io = 1;
12881 +       if (ioc->alt_ioc) {
12882 +               ioc->alt_ioc->taskmgmt_in_progress = 1;
12883 +               ioc->alt_ioc->taskmgmt_quiesce_io = 1;
12884 +       }
12885 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
12886 +
12887 + out:
12888 +       return retval;
12889 +}
12890 +
12891 +/**
12892 + *     mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task managment
12893 + *     @ioc: Pointer to MPT_ADAPTER structure
12894 + *
12895 + **/
12896 +void
12897 +mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
12898 +{
12899 +       unsigned long    flags;
12900 +
12901 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
12902 +       ioc->taskmgmt_in_progress = 0;
12903 +       ioc->taskmgmt_quiesce_io = 0;
12904 +       if (ioc->alt_ioc) {
12905 +               ioc->alt_ioc->taskmgmt_in_progress = 0;
12906 +               ioc->alt_ioc->taskmgmt_quiesce_io = 0;
12907 +       }
12908 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
12909 +}
12910 +
12911 +/**
12912 + *     mpt_halt_firmware - Halts the firmware if it is operational and panic
12913 + *     the kernel
12914 + *     @ioc: Pointer to MPT_ADAPTER structure
12915 + *
12916 + **/
12917 +void
12918 +mpt_halt_firmware(MPT_ADAPTER *ioc)
12919 +{
12920 +       u32      ioc_raw_state;
12921 +
12922 +       ioc_raw_state = mpt_GetIocState(ioc, 0);
12923 +
12924 +       if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
12925 +               printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n",
12926 +                       ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
12927 +               if(mpt_fwfault_debug == 2)
12928 +                       for(;;);
12929 +               else
12930 +                       panic("%s: IOC Fault (%04xh)!!!\n",ioc->name,
12931 +                               ioc_raw_state & MPI_DOORBELL_DATA_MASK);
12932 +       } else {
12933 +               CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00);
12934 +               if(mpt_fwfault_debug == 2) {
12935 +                       printk("%s: Firmware is halted due to command timeout\n"
12936 +                                       ,ioc->name);
12937 +                       for(;;);
12938 +               }
12939 +               else
12940 +                       panic("%s: Firmware is halted due to command timeout\n",
12941 +                                       ioc->name);
12942 +       }
12943 +}
12944 +
12945 +/**
12946 + *     mpt_SoftResetHandler - Issues a less expensive reset
12947 + *     @ioc: Pointer to MPT_ADAPTER structure
12948 + *     @sleepFlag: Indicates if sleep or schedule must be called.
12949 +
12950 + *
12951 + *     Returns 0 for SUCCESS or -1 if FAILED.
12952 + *
12953 + *     Message Unit Reset - instructs the IOC to reset the Reply Post and
12954 + *     Free FIFO's. All the Message Frames on Reply Free FIFO are discarded.
12955 + *     All posted buffers are freed, and event notification is turned off.
12956 + *     IOC doesnt reply to any outstanding request. This will transfer IOC
12957 + *     to READY state.
12958 + **/
12959 +int
12960 +mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
12961 +{
12962 +       int              rc;
12963 +       int              ii;
12964 +       u8               cb_idx;
12965 +       unsigned long    flags;
12966 +       u32              ioc_state;
12967 +       unsigned long    time_count;
12968 +
12969 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n", ioc->name));
12970 +
12971 +       ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
12972 +
12973 +       if(mpt_fwfault_debug)
12974 +               mpt_halt_firmware(ioc);
12975 +
12976 +       if (ioc_state == MPI_IOC_STATE_FAULT || ioc_state == MPI_IOC_STATE_RESET) {
12977 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
12978 +                   "skipping, either in FAULT or RESET state!\n", ioc->name));
12979 +               return -1;
12980 +       }
12981 +
12982 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
12983 +       if (ioc->ioc_reset_in_progress) {
12984 +               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
12985 +               return -1;
12986 +       }
12987 +       ioc->ioc_reset_in_progress = 1;
12988 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
12989 +
12990 +       rc = -1;
12991 +
12992 +       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
12993 +               if (MptResetHandlers[cb_idx])
12994 +                       mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
12995 +       }
12996 +
12997 +       /* Disable reply interrupts (also blocks FreeQ) */
12998 +       CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
12999 +       ioc->active = 0;
13000 +       time_count = jiffies;
13001 +
13002 +       rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
13003 +
13004 +       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
13005 +               if (MptResetHandlers[cb_idx])
13006 +                       mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
13007 +       }
13008 +
13009 +       if (rc)
13010 +               goto out;
13011 +
13012 +       ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
13013 +       if (ioc_state != MPI_IOC_STATE_READY)
13014 +               goto out;
13015 +
13016 +       for (ii = 0; ii < 5; ii++) {
13017 +               /* Get IOC facts! Allow 5 retries */
13018 +               if ((rc = GetIocFacts(ioc, sleepFlag,
13019 +                           MPT_HOSTEVENT_IOC_RECOVER)) == 0)
13020 +                       break;
13021 +               if (sleepFlag == CAN_SLEEP) {
13022 +                       msleep(100);
13023 +               } else {
13024 +                       mdelay(100);
13025 +               }
13026 +       }
13027 +       if (ii == 5)
13028 +               goto out;
13029 +
13030 +       if ((rc = PrimeIocFifos(ioc)) != 0)
13031 +               goto out;
13032 +
13033 +       if ((rc = SendIocInit(ioc, sleepFlag)) != 0)
13034 +               goto out;
13035 +
13036 +       if ((rc = SendEventNotification(ioc, 1, sleepFlag)) != 0)
13037 +               goto out;
13038 +
13039 +       if (ioc->hard_resets < -1)
13040 +               ioc->hard_resets++;
13041 +
13042 +       /*
13043 +        * At this point, we know soft reset succeeded.
13044 +        */
13045 +
13046 +       ioc->active = 1;
13047 +       CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
13048 +
13049 + out:
13050 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
13051 +       ioc->ioc_reset_in_progress = 0;
13052 +       ioc->taskmgmt_quiesce_io = 0;
13053 +       ioc->taskmgmt_in_progress = 0;
13054 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
13055 +
13056 +       if (ioc->active) {      /* otherwise, hard reset coming */
13057 +               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
13058 +                       if (MptResetHandlers[cb_idx])
13059 +                               mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
13060 +               }
13061 +       }
13062 +
13063 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler: completed (%d seconds): %s\n",
13064 +           ioc->name, jiffies_to_msecs(jiffies - time_count)/1000,
13065 +           ((rc == 0) ? "SUCCESS" : "FAILED")));
13066 +
13067 +       return rc;
13068 +}
13069 +
13070  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13071  /**
13072   *     mpt_HardResetHandler - Generic reset handler
13073 @@ -6335,12 +7060,14 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, 
13074   *     FW reload/initialization failed.
13075   *
13076   *     Returns 0 for SUCCESS or -1 if FAILED.
13077 - */
13078 + **/
13079  int
13080  mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
13081  {
13082 -       int              rc;
13083 +       int      rc;
13084 +       u8       cb_idx;
13085         unsigned long    flags;
13086 +       unsigned long    time_count;
13087  
13088         dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
13089  #ifdef MFCNT
13090 @@ -6348,67 +7075,82 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
13091         printk("MF count 0x%x !\n", ioc->mfcnt);
13092  #endif
13093  
13094 +       if(mpt_fwfault_debug)
13095 +               mpt_halt_firmware(ioc);
13096 +
13097         /* Reset the adapter. Prevent more than 1 call to
13098          * mpt_do_ioc_recovery at any instant in time.
13099          */
13100 -       spin_lock_irqsave(&ioc->diagLock, flags);
13101 -       if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
13102 -               spin_unlock_irqrestore(&ioc->diagLock, flags);
13103 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
13104 +       if (ioc->ioc_reset_in_progress) {
13105 +               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
13106                 return 0;
13107 -       } else {
13108 -               ioc->diagPending = 1;
13109         }
13110 -       spin_unlock_irqrestore(&ioc->diagLock, flags);
13111 +       ioc->ioc_reset_in_progress = 1;
13112 +       if (ioc->alt_ioc)
13113 +           ioc->alt_ioc->ioc_reset_in_progress = 1;
13114 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
13115  
13116 -       /* FIXME: If do_ioc_recovery fails, repeat....
13117 -        */
13118  
13119         /* The SCSI driver needs to adjust timeouts on all current
13120          * commands prior to the diagnostic reset being issued.
13121          * Prevents timeouts occurring during a diagnostic reset...very bad.
13122          * For all other protocol drivers, this is a no-op.
13123          */
13124 -       {
13125 -               u8       cb_idx;
13126 -               int      r = 0;
13127 -
13128 -               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
13129 -                       if (MptResetHandlers[cb_idx]) {
13130 -                               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n",
13131 -                                               ioc->name, cb_idx));
13132 -                               r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
13133 -                               if (ioc->alt_ioc) {
13134 -                                       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n",
13135 -                                                       ioc->name, ioc->alt_ioc->name, cb_idx));
13136 -                                       r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
13137 -                               }
13138 -                       }
13139 +       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
13140 +               if (MptResetHandlers[cb_idx]) {
13141 +                       mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
13142 +                       if (ioc->alt_ioc)
13143 +                               mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
13144                 }
13145         }
13146  
13147 +       time_count = jiffies;
13148         if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
13149 -               printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc);
13150 +               printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
13151 +                       rc, ioc->name);
13152 +       } else {
13153 +               if (ioc->hard_resets < -1)
13154 +                       ioc->hard_resets++;
13155         }
13156 -       ioc->reload_fw = 0;
13157 -       if (ioc->alt_ioc)
13158 -               ioc->alt_ioc->reload_fw = 0;
13159  
13160 -       spin_lock_irqsave(&ioc->diagLock, flags);
13161 -       ioc->diagPending = 0;
13162 -       if (ioc->alt_ioc)
13163 -               ioc->alt_ioc->diagPending = 0;
13164 -       spin_unlock_irqrestore(&ioc->diagLock, flags);
13165 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
13166 +       ioc->ioc_reset_in_progress = 0;
13167 +       ioc->taskmgmt_quiesce_io = 0;
13168 +       ioc->taskmgmt_in_progress = 0;
13169 +       if (ioc->alt_ioc) {
13170 +           ioc->alt_ioc->ioc_reset_in_progress = 0;
13171 +           ioc->alt_ioc->taskmgmt_quiesce_io = 0;
13172 +           ioc->alt_ioc->taskmgmt_in_progress = 0;
13173 +       }
13174 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
13175  
13176 -       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
13177 +       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
13178 +               if (MptResetHandlers[cb_idx]) {
13179 +                       mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
13180 +                       if (ioc->alt_ioc)
13181 +                               mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
13182 +               }
13183 +       }
13184  
13185 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler: completed (%d seconds): %s\n",
13186 +           ioc->name, jiffies_to_msecs(jiffies - time_count)/1000,
13187 +           ((rc == 0) ? "SUCCESS" : "FAILED")));
13188         return rc;
13189  }
13190  
13191 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13192 +#ifdef CONFIG_FUSION_LOGGING
13193  static void
13194 -EventDescriptionStr(u8 event, u32 evData0, char *evStr)
13195 +mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
13196  {
13197         char *ds = NULL;
13198 +       u32 evData0;
13199 +       int ii;
13200 +       u8 event;
13201 +       char *evStr = ioc->evStr;
13202 +
13203 +       event = le32_to_cpu(pEventReply->Event) & 0xFF;
13204 +       evData0 = le32_to_cpu(pEventReply->Data[0]);
13205  
13206         switch(event) {
13207         case MPI_EVENT_NONE:
13208 @@ -6442,9 +7184,9 @@ EventDescriptionStr(u8 event, u32 evData
13209                 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
13210                         ds = "Loop State(LIP) Change";
13211                 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
13212 -                       ds = "Loop State(LPE) Change";          /* ??? */
13213 +                       ds = "Loop State(LPE) Change";
13214                 else
13215 -                       ds = "Loop State(LPB) Change";          /* ??? */
13216 +                       ds = "Loop State(LPB) Change";
13217                 break;
13218         case MPI_EVENT_LOGOUT:
13219                 ds = "Logout";
13220 @@ -6540,6 +7282,11 @@ EventDescriptionStr(u8 event, u32 evData
13221                             "SAS Device Status Change: Internal Device "
13222                             "Reset : id=%d channel=%d", id, channel);
13223                         break;
13224 +               case MPI_EVENT_SAS_DEV_STAT_RC_CMPL_INTERNAL_DEV_RESET:
13225 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13226 +                           "SAS Device Status Change: Internal Device "
13227 +                           "Reset Completed: id=%d channel=%d", id, channel);
13228 +                       break;
13229                 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
13230                         snprintf(evStr, EVENT_DESCR_STR_SZ,
13231                             "SAS Device Status Change: Internal Task "
13232 @@ -6560,6 +7307,11 @@ EventDescriptionStr(u8 event, u32 evData
13233                             "SAS Device Status Change: Internal Query "
13234                             "Task : id=%d channel=%d", id, channel);
13235                         break;
13236 +               case MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
13237 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13238 +                           "SAS Device Status Change: Async Notification "
13239 +                           "Task : id=%d channel=%d", id, channel);
13240 +                       break;
13241                 default:
13242                         snprintf(evStr, EVENT_DESCR_STR_SZ,
13243                             "SAS Device Status Change: Unknown: "
13244 @@ -6644,28 +7396,65 @@ EventDescriptionStr(u8 event, u32 evData
13245         }
13246         case MPI_EVENT_IR2:
13247         {
13248 +               u8 id = (u8)(evData0);
13249 +               u8 channel = (u8)(evData0 >> 8);
13250 +               u8 phys_num = (u8)(evData0 >> 24);
13251                 u8 ReasonCode = (u8)(evData0 >> 16);
13252 +
13253                 switch (ReasonCode) {
13254                 case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
13255 -                       ds = "IR2: LD State Changed";
13256 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13257 +                           "IR2: LD State Changed: "
13258 +                           "id=%d channel=%d phys_num=%d",
13259 +                           id, channel, phys_num);
13260                         break;
13261                 case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
13262 -                       ds = "IR2: PD State Changed";
13263 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13264 +                           "IR2: PD State Changed "
13265 +                           "id=%d channel=%d phys_num=%d",
13266 +                           id, channel, phys_num);
13267                         break;
13268                 case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
13269 -                       ds = "IR2: Bad Block Table Full";
13270 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13271 +                           "IR2: Bad Block Table Full: "
13272 +                           "id=%d channel=%d phys_num=%d",
13273 +                           id, channel, phys_num);
13274                         break;
13275                 case MPI_EVENT_IR2_RC_PD_INSERTED:
13276 -                       ds = "IR2: PD Inserted";
13277 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13278 +                           "IR2: PD Inserted: "
13279 +                           "id=%d channel=%d phys_num=%d",
13280 +                           id, channel, phys_num);
13281                         break;
13282                 case MPI_EVENT_IR2_RC_PD_REMOVED:
13283 -                       ds = "IR2: PD Removed";
13284 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13285 +                           "IR2: PD Removed: "
13286 +                           "id=%d channel=%d phys_num=%d",
13287 +                           id, channel, phys_num);
13288                         break;
13289                 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
13290 -                       ds = "IR2: Foreign CFG Detected";
13291 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13292 +                           "IR2: Foreign CFG Detected: "
13293 +                           "id=%d channel=%d phys_num=%d",
13294 +                           id, channel, phys_num);
13295                         break;
13296                 case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
13297 -                       ds = "IR2: Rebuild Medium Error";
13298 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13299 +                           "IR2: Rebuild Medium Error: "
13300 +                           "id=%d channel=%d phys_num=%d",
13301 +                           id, channel, phys_num);
13302 +                       break;
13303 +               case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
13304 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13305 +                           "IR2: Dual Port Added: "
13306 +                           "id=%d channel=%d phys_num=%d",
13307 +                           id, channel, phys_num);
13308 +                       break;
13309 +               case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
13310 +                       snprintf(evStr, EVENT_DESCR_STR_SZ,
13311 +                           "IR2: Dual Port Removed: "
13312 +                           "id=%d channel=%d phys_num=%d",
13313 +                           id, channel, phys_num);
13314                         break;
13315                 default:
13316                         ds = "IR2";
13317 @@ -6689,25 +7478,46 @@ EventDescriptionStr(u8 event, u32 evData
13318         {
13319                 u8 phy_num = (u8)(evData0);
13320                 u8 port_num = (u8)(evData0 >> 8);
13321 -               u8 port_width = (u8)(evData0 >> 16);
13322 +               u8 num_phys = (u8)(evData0 >> 16);
13323                 u8 primative = (u8)(evData0 >> 24);
13324 +               char *primative_str = NULL;
13325 +
13326 +               switch (primative) {
13327 +               case MPI_EVENT_PRIMITIVE_CHANGE:
13328 +                       primative_str = "change";
13329 +                       break;
13330 +               case MPI_EVENT_PRIMITIVE_EXPANDER:
13331 +                       primative_str = "expander";
13332 +                       break;
13333 +               case MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT:
13334 +                       primative_str = "asyn event";
13335 +                       break;
13336 +               default:
13337 +                       primative_str = "reserved";
13338 +                       break;
13339 +               }
13340                 snprintf(evStr, EVENT_DESCR_STR_SZ,
13341 -                   "SAS Broadcase Primative: phy=%d port=%d "
13342 -                   "width=%d primative=0x%02x",
13343 -                   phy_num, port_num, port_width, primative);
13344 +                   "SAS Broadcast Primative: phy=%d port=%d "
13345 +                   "num_phys=%d primative=%s (0x%02x)",
13346 +                   phy_num, port_num, num_phys, primative_str, primative);
13347                 break;
13348         }
13349  
13350         case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
13351         {
13352                 u8 reason = (u8)(evData0);
13353 -               u8 port_num = (u8)(evData0 >> 8);
13354 -               u16 handle = le16_to_cpu(evData0 >> 16);
13355  
13356 -               snprintf(evStr, EVENT_DESCR_STR_SZ,
13357 -                   "SAS Initiator Device Status Change: reason=0x%02x "
13358 -                   "port=%d handle=0x%04x",
13359 -                   reason, port_num, handle);
13360 +               switch (reason) {
13361 +               case MPI_EVENT_SAS_INIT_RC_ADDED:
13362 +                       ds = "SAS Initiator Status Change: Added";
13363 +                       break;
13364 +               case MPI_EVENT_SAS_INIT_RC_REMOVED:
13365 +                       ds = "SAS Initiator Status Change: Deleted";
13366 +                       break;
13367 +               default:
13368 +                       ds = "SAS Initiator Status Change";
13369 +                       break;
13370 +               }
13371                 break;
13372         }
13373  
13374 @@ -6755,6 +7565,24 @@ EventDescriptionStr(u8 event, u32 evData
13375                 break;
13376         }
13377  
13378 +       case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
13379 +       {
13380 +               u8 reason = (u8)(evData0);
13381 +
13382 +               switch (reason) {
13383 +               case MPI_EVENT_SAS_EXP_RC_ADDED:
13384 +                       ds = "Expander Status Change: Added";
13385 +                       break;
13386 +               case MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING:
13387 +                       ds = "Expander Status Change: Deleted";
13388 +                       break;
13389 +               default:
13390 +                       ds = "Expander Status Change";
13391 +                       break;
13392 +               }
13393 +               break;
13394 +       }
13395 +
13396         /*
13397          *  MPT base "custom" events may be added here...
13398          */
13399 @@ -6764,9 +7592,21 @@ EventDescriptionStr(u8 event, u32 evData
13400         }
13401         if (ds)
13402                 strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
13403 +
13404 +
13405 +       devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
13406 +           "MPT event:(%02Xh) : %s\n",
13407 +           ioc->name, event, evStr));
13408 +
13409 +       devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM
13410 +           ": Event data:\n"));
13411 +       for (ii = 0; ii < le16_to_cpu(pEventReply->EventDataLength); ii++)
13412 +               devtverboseprintk(ioc, printk(" %08x",
13413 +                   le32_to_cpu(pEventReply->Data[ii])));
13414 +       devtverboseprintk(ioc, printk(KERN_DEBUG "\n"));
13415  }
13416 +#endif
13417  
13418 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13419  /**
13420   *     ProcessEventNotification - Route EventNotificationReply to all event handlers
13421   *     @ioc: Pointer to MPT_ADAPTER structure
13422 @@ -6776,43 +7616,30 @@ EventDescriptionStr(u8 event, u32 evData
13423   *     Routes a received EventNotificationReply to all currently registered
13424   *     event handlers.
13425   *     Returns sum of event handlers return values.
13426 - */
13427 + **/
13428  static int
13429  ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
13430  {
13431         u16 evDataLen;
13432         u32 evData0 = 0;
13433 -//     u32 evCtx;
13434         int ii;
13435         u8 cb_idx;
13436         int r = 0;
13437         int handlers = 0;
13438 -       char evStr[EVENT_DESCR_STR_SZ];
13439         u8 event;
13440  
13441 +
13442         /*
13443          *  Do platform normalization of values
13444          */
13445         event = le32_to_cpu(pEventReply->Event) & 0xFF;
13446 -//     evCtx = le32_to_cpu(pEventReply->EventContext);
13447         evDataLen = le16_to_cpu(pEventReply->EventDataLength);
13448 -       if (evDataLen) {
13449 +       if (evDataLen)
13450                 evData0 = le32_to_cpu(pEventReply->Data[0]);
13451 -       }
13452 -
13453 -       EventDescriptionStr(event, evData0, evStr);
13454 -       devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event:(%02Xh) : %s\n",
13455 -                       ioc->name,
13456 -                       event,
13457 -                       evStr));
13458  
13459  #ifdef CONFIG_FUSION_LOGGING
13460 -       devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
13461 -           ": Event data:\n", ioc->name));
13462 -       for (ii = 0; ii < evDataLen; ii++)
13463 -               devtverboseprintk(ioc, printk(" %08x",
13464 -                   le32_to_cpu(pEventReply->Data[ii])));
13465 -       devtverboseprintk(ioc, printk("\n"));
13466 +       if (evDataLen)
13467 +               mpt_display_event_info(ioc, pEventReply);
13468  #endif
13469  
13470         /*
13471 @@ -6867,8 +7694,8 @@ ProcessEventNotification(MPT_ADAPTER *io
13472          */
13473         for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
13474                 if (MptEvHandlers[cb_idx]) {
13475 -                       devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n",
13476 -                                       ioc->name, cb_idx));
13477 +                       devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
13478 +                           "Routing Event to event handler #%d\n", ioc->name, cb_idx));
13479                         r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
13480                         handlers++;
13481                 }
13482 @@ -6935,7 +7762,6 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 lo
13483                         ioc->name, log_info, desc, (log_info & 0xFFFFFF));
13484  }
13485  
13486 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13487  /**
13488   *     mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
13489   *     @ioc: Pointer to MPT_ADAPTER structure
13490 @@ -6943,7 +7769,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 lo
13491   *     @log_info: U32 LogInfo word from the IOC
13492   *
13493   *     Refer to lsi/sp_log.h.
13494 - */
13495 + **/
13496  static void
13497  mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
13498  {
13499 @@ -6953,8 +7779,6 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 l
13500         switch (info) {
13501         case 0x00010000:
13502                 desc = "bug! MID not found";
13503 -               if (ioc->reload_fw == 0)
13504 -                       ioc->reload_fw++;
13505                 break;
13506  
13507         case 0x00020000:
13508 @@ -7149,7 +7973,6 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 l
13509                 "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
13510         };
13511  
13512 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13513  /**
13514   *     mpt_sas_log_info - Log information returned from SAS IOC.
13515   *     @ioc: Pointer to MPT_ADAPTER structure
13516 @@ -7229,7 +8052,6 @@ union loginfo_type {
13517                         sas_loginfo.dw.code, sas_loginfo.dw.subcode);
13518  }
13519  
13520 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13521  /**
13522   *     mpt_iocstatus_info_config - IOCSTATUS information for config pages
13523   *     @ioc: Pointer to MPT_ADAPTER structure
13524 @@ -7531,8 +8353,7 @@ mpt_iocstatus_info(MPT_ADAPTER *ioc, u32
13525         if (!desc)
13526                 return;
13527  
13528 -       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
13529 -           ioc->name, status, desc));
13530 +       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc));
13531  }
13532  
13533  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13534 @@ -7543,6 +8364,7 @@ EXPORT_SYMBOL(mpt_resume);
13535  EXPORT_SYMBOL(mpt_suspend);
13536  #endif
13537  EXPORT_SYMBOL(ioc_list);
13538 +EXPORT_SYMBOL(mpt_proc_root_dir);
13539  EXPORT_SYMBOL(mpt_register);
13540  EXPORT_SYMBOL(mpt_deregister);
13541  EXPORT_SYMBOL(mpt_event_register);
13542 @@ -7555,25 +8377,29 @@ EXPORT_SYMBOL(mpt_get_msg_frame);
13543  EXPORT_SYMBOL(mpt_put_msg_frame);
13544  EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
13545  EXPORT_SYMBOL(mpt_free_msg_frame);
13546 -EXPORT_SYMBOL(mpt_add_sge);
13547  EXPORT_SYMBOL(mpt_send_handshake_request);
13548  EXPORT_SYMBOL(mpt_verify_adapter);
13549  EXPORT_SYMBOL(mpt_GetIocState);
13550  EXPORT_SYMBOL(mpt_print_ioc_summary);
13551  EXPORT_SYMBOL(mpt_HardResetHandler);
13552 +EXPORT_SYMBOL(mpt_SoftResetHandler);
13553  EXPORT_SYMBOL(mpt_config);
13554  EXPORT_SYMBOL(mpt_findImVolumes);
13555  EXPORT_SYMBOL(mpt_alloc_fw_memory);
13556  EXPORT_SYMBOL(mpt_free_fw_memory);
13557  EXPORT_SYMBOL(mptbase_sas_persist_operation);
13558  EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
13559 +EXPORT_SYMBOL(mpt_raid_phys_disk_pg1);
13560 +EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths);
13561 +EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag);
13562 +EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag);
13563 +EXPORT_SYMBOL(mpt_halt_firmware);
13564  
13565 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13566  /**
13567   *     fusion_init - Fusion MPT base driver initialization routine.
13568   *
13569   *     Returns 0 for success, non-zero for failure.
13570 - */
13571 + **/
13572  static int __init
13573  fusion_init(void)
13574  {
13575 @@ -7592,7 +8418,7 @@ fusion_init(void)
13576         /*  Register ourselves (mptbase) in order to facilitate
13577          *  EventNotification handling.
13578          */
13579 -       mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
13580 +       mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER);
13581  
13582         /* Register for hard reset handling callbacks.
13583          */
13584 @@ -7604,17 +8430,15 @@ fusion_init(void)
13585         return 0;
13586  }
13587  
13588 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13589  /**
13590   *     fusion_exit - Perform driver unload cleanup.
13591   *
13592   *     This routine frees all resources associated with each MPT adapter
13593   *     and removes all %MPT_PROCFS_MPTBASEDIR entries.
13594 - */
13595 + **/
13596  static void __exit
13597  fusion_exit(void)
13598  {
13599 -
13600         mpt_reset_deregister(mpt_base_index);
13601  
13602  #ifdef CONFIG_PROC_FS
13603 --- a/drivers/message/fusion/mptbase.h
13604 +++ b/drivers/message/fusion/mptbase.h
13605 @@ -49,10 +49,6 @@
13606  #define MPTBASE_H_INCLUDED
13607  /*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13608  
13609 -#include <linux/kernel.h>
13610 -#include <linux/pci.h>
13611 -#include <linux/mutex.h>
13612 -
13613  #include "lsi/mpi_type.h"
13614  #include "lsi/mpi.h"           /* Fusion MPI(nterface) basic defs */
13615  #include "lsi/mpi_ioc.h"       /* Fusion MPT IOC(ontroller) defs */
13616 @@ -76,9 +72,13 @@
13617  #define COPYRIGHT      "Copyright (c) 1999-2008 " MODULEAUTHOR
13618  #endif
13619  
13620 -#define MPT_LINUX_VERSION_COMMON       "3.04.07"
13621 -#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.04.07"
13622 +#define MPT_LINUX_VERSION_COMMON       "4.00.43.00"
13623 +#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-4.00.43.00"
13624  #define WHAT_MAGIC_STRING              "@" "(" "#" ")"
13625 +#define MPT_LINUX_MAJOR_VERSION                4
13626 +#define MPT_LINUX_MINOR_VERSION                00
13627 +#define MPT_LINUX_BUILD_VERSION                43
13628 +#define MPT_LINUX_RELEASE_VERSION      00
13629  
13630  #define show_mptmod_ver(s,ver)  \
13631         printk(KERN_INFO "%s %s\n", s, ver);
13632 @@ -87,6 +87,8 @@
13633  /*
13634   *  Fusion MPT(linux) driver configurable stuff...
13635   */
13636 +#define MPT_POLLING_INTERVAL           1000    /* in milliseconds */
13637 +
13638  #define MPT_MAX_ADAPTERS               18
13639  #define MPT_MAX_PROTOCOL_DRIVERS       16
13640  #define MPT_MAX_BUS                    1       /* Do not change */
13641 @@ -134,6 +136,8 @@
13642  
13643  #define MPT_COALESCING_TIMEOUT         0x10
13644  
13645 +#define MPT_DMA_35BIT_MASK  0x00000007ffffffffULL
13646 +
13647  /*
13648   * SCSI transfer rate defines.
13649   */
13650 @@ -173,10 +177,21 @@
13651  #define MPT_SCSI_SG_DEPTH      40
13652  #endif
13653  
13654 +#ifdef  CONFIG_FUSION_MAX_FC_SGE
13655 +#if     CONFIG_FUSION_MAX_FC_SGE  < 16
13656 +#define MPT_SCSI_FC_SG_DEPTH   16
13657 +#elif   CONFIG_FUSION_MAX_FC_SGE  > 256
13658 +#define MPT_SCSI_FC_SG_DEPTH   256
13659 +#else
13660 +#define MPT_SCSI_FC_SG_DEPTH   CONFIG_FUSION_MAX_FC_SGE
13661 +#endif
13662 +#else
13663 +#define MPT_SCSI_FC_SG_DEPTH   40
13664 +#endif
13665 +
13666  /* debug print string length used for events and iocstatus */
13667 -# define EVENT_DESCR_STR_SZ             100
13668 +# define EVENT_DESCR_STR_SZ            100
13669  
13670 -#define MPT_POLLING_INTERVAL           1000    /* in milliseconds */
13671  
13672  #ifdef __KERNEL__      /* { */
13673  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13674 @@ -224,7 +239,6 @@ typedef struct _ATTO_CONFIG_PAGE_SCSI_PO
13675  } fATTO_CONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_ATTO_CONFIG_PAGE_SCSI_PORT_2,
13676    ATTO_SCSIPortPage2_t, MPI_POINTER pATTO_SCSIPortPage2_t;
13677  
13678 -
13679  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13680  /*
13681   *  MPT protocol driver defs...
13682 @@ -372,8 +386,8 @@ typedef struct _VirtTarget {
13683         struct scsi_target      *starget;
13684         u8                       tflags;
13685         u8                       ioc_id;
13686 -       u8                       id;
13687 -       u8                       channel;
13688 +       u8                       id;            /* logical target id */
13689 +       u8                       channel;       /* logical channel number */
13690         u8                       minSyncFactor; /* 0xFF is async */
13691         u8                       maxOffset;     /* 0 if async */
13692         u8                       maxWidth;      /* 0 if narrow, 1 if wide */
13693 @@ -381,7 +395,7 @@ typedef struct _VirtTarget {
13694         u8                       raidVolume;    /* set, if RAID Volume */
13695         u8                       type;          /* byte 0 of Inquiry data */
13696         u8                       deleted;       /* target in process of being removed */
13697 -       u32                      num_luns;
13698 +       int                      num_luns;
13699  } VirtTarget;
13700  
13701  typedef struct _VirtDevice {
13702 @@ -427,42 +441,33 @@ do { \
13703  } while (0)
13704  
13705  
13706 -/*
13707 - *     IOCTL structure and associated defines
13708 - */
13709 -
13710 -#define MPT_IOCTL_STATUS_DID_IOCRESET  0x01    /* IOC Reset occurred on the current*/
13711 -#define MPT_IOCTL_STATUS_RF_VALID      0x02    /* The Reply Frame is VALID */
13712 -#define MPT_IOCTL_STATUS_TIMER_ACTIVE  0x04    /* The timer is running */
13713 -#define MPT_IOCTL_STATUS_SENSE_VALID   0x08    /* Sense data is valid */
13714 -#define MPT_IOCTL_STATUS_COMMAND_GOOD  0x10    /* Command Status GOOD */
13715 -#define MPT_IOCTL_STATUS_TMTIMER_ACTIVE        0x20    /* The TM timer is running */
13716 -#define MPT_IOCTL_STATUS_TM_FAILED     0x40    /* User TM request failed */
13717 -
13718 -#define MPTCTL_RESET_OK                        0x01    /* Issue Bus Reset */
13719 -
13720 -typedef struct _MPT_IOCTL {
13721 -       struct _MPT_ADAPTER     *ioc;
13722 -       u8                       ReplyFrame[MPT_DEFAULT_FRAME_SIZE];    /* reply frame data */
13723 -       u8                       sense[MPT_SENSE_BUFFER_ALLOC];
13724 -       int                      wait_done;     /* wake-up value for this ioc */
13725 -       u8                       rsvd;
13726 -       u8                       status;        /* current command status */
13727 -       u8                       reset;         /* 1 if bus reset allowed */
13728 -       u8                       id;            /* target for reset */
13729 -       struct mutex             ioctl_mutex;
13730 -} MPT_IOCTL;
13731 -
13732 -#define MPT_SAS_MGMT_STATUS_RF_VALID   0x02    /* The Reply Frame is VALID */
13733 -#define MPT_SAS_MGMT_STATUS_COMMAND_GOOD       0x10    /* Command Status GOOD */
13734 -#define MPT_SAS_MGMT_STATUS_TM_FAILED  0x40    /* User TM request failed */
13735 +#define MPT_MGMT_STATUS_RF_VALID       0x01    /* The Reply Frame is VALID */
13736 +#define MPT_MGMT_STATUS_COMMAND_GOOD   0x02    /* Command Status GOOD */
13737 +#define MPT_MGMT_STATUS_PENDING                0x04    /* command is pending */
13738 +#define MPT_MGMT_STATUS_DID_IOCRESET   0x08    /* IOC Reset occurred on the current*/
13739 +#define MPT_MGMT_STATUS_SENSE_VALID    0x10    /* valid sense info */
13740 +#define MPT_MGMT_STATUS_TIMER_ACTIVE   0x20    /* obsolete */
13741 +#define MPT_MGMT_STATUS_FREE_MF                0x40    /* free the mf from complete routine */
13742 +
13743 +
13744 +#define INITIALIZE_MGMT_STATUS(status) \
13745 +       status = MPT_MGMT_STATUS_PENDING;
13746 +#define CLEAR_MGMT_STATUS(status) \
13747 +       status = 0;
13748 +#define CLEAR_MGMT_PENDING_STATUS(status) \
13749 +       status &= ~MPT_MGMT_STATUS_PENDING;
13750 +#define SET_MGMT_MSG_CONTEXT(msg_context, value) \
13751 +       msg_context = value;
13752  
13753 -typedef struct _MPT_SAS_MGMT {
13754 +typedef struct _MPT_MGMT {
13755         struct mutex             mutex;
13756         struct completion        done;
13757         u8                       reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
13758 +       u8                       sense[MPT_SENSE_BUFFER_ALLOC];
13759         u8                       status;        /* current command status */
13760 -}MPT_SAS_MGMT;
13761 +       int                      completion_code;
13762 +       u32                      msg_context;
13763 +}MPT_MGMT;
13764  
13765  /*
13766   *  Event Structure and define
13767 @@ -534,7 +539,8 @@ struct inactive_raid_component_info {
13768  typedef        struct _RaidCfgData {
13769         IOCPage2_t      *pIocPg2;               /* table of Raid Volumes */
13770         IOCPage3_t      *pIocPg3;               /* table of physical disks */
13771 -       struct mutex    inactive_list_mutex;
13772 +       IOCPage6_t      *pIocPg6;               /* table of IR static data */
13773 +       struct semaphore        inactive_list_mutex;
13774         struct list_head        inactive_list; /* link list for physical
13775                                                 disk that belong in
13776                                                 inactive volumes */
13777 @@ -564,6 +570,9 @@ struct mptfc_rport_info
13778         u8              flags;
13779  };
13780  
13781 +typedef void (*MPT_ADD_SGE)(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
13782 +typedef void (*MPT_ADD_CHAIN)(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr);
13783 +
13784  /*
13785   *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
13786   */
13787 @@ -573,6 +582,9 @@ typedef struct _MPT_ADAPTER
13788         int                      pci_irq;       /* This irq           */
13789         char                     name[MPT_NAME_LENGTH]; /* "iocN"             */
13790         char                     prod_name[MPT_NAME_LENGTH];    /* "LSIFC9x9"         */
13791 +#ifdef CONFIG_FUSION_LOGGING
13792 +       char                     evStr[EVENT_DESCR_STR_SZ]; /* used in mpt_display_event_info */
13793 +#endif
13794         char                     board_name[16];
13795         char                     board_assembly[16];
13796         char                     board_tracer[16];
13797 @@ -584,8 +596,8 @@ typedef struct _MPT_ADAPTER
13798         SYSIF_REGS __iomem      *chip;          /* == c8817000 (mmap) */
13799         SYSIF_REGS __iomem      *pio_chip;      /* Programmed IO (downloadboot) */
13800         u8                       bus_type;
13801 -       u32                      mem_phys;      /* == f4020000 (mmap) */
13802 -       u32                      pio_mem_phys;  /* Programmed IO (downloadboot) */
13803 +       unsigned long            mem_phys;      /* == f4020000 (mmap) */
13804 +       unsigned long            pio_mem_phys;  /* Programmed IO (downloadboot) */
13805         int                      mem_size;      /* mmap memory size */
13806         int                      number_of_buses;
13807         int                      devices_per_bus;
13808 @@ -600,6 +612,8 @@ typedef struct _MPT_ADAPTER
13809         int                      reply_depth;   /* Num Allocated reply frames */
13810         int                      reply_sz;      /* Reply frame size */
13811         int                      num_chain;     /* Number of chain buffers */
13812 +       MPT_ADD_SGE              add_sge;       /* Pointer to add_sge function */
13813 +       MPT_ADD_CHAIN            add_chain;     /* Pointer to add_chain function */
13814                 /* Pool of buffers for chaining. ReqToChain
13815                  * and ChainToChain track index of chain buffers.
13816                  * ChainBuffer (DMA) virt/phys addresses.
13817 @@ -628,31 +642,27 @@ typedef struct _MPT_ADAPTER
13818         dma_addr_t               sense_buf_pool_dma;
13819         u32                      sense_buf_low_dma;
13820         u8                      *HostPageBuffer; /* SAS - host page buffer support */
13821 -       u32                     HostPageBuffer_sz;
13822 -       dma_addr_t              HostPageBuffer_dma;
13823 +       u32                      HostPageBuffer_sz;
13824 +       dma_addr_t               HostPageBuffer_dma;
13825         int                      mtrr_reg;
13826         struct pci_dev          *pcidev;        /* struct pci_dev pointer */
13827 -       int                     bars;           /* bitmask of BAR's that must be configured */
13828 -       int                     msi_enable;
13829 +       int                     bars;   /* bitmask of BAR's that must be configured */
13830 +       int                      msi_enable;
13831         u8                      __iomem *memmap;        /* mmap address */
13832         struct Scsi_Host        *sh;            /* Scsi Host pointer */
13833 -       SpiCfgData              spi_data;       /* Scsi config. data */
13834 -       RaidCfgData             raid_data;      /* Raid config. data */
13835 -       SasCfgData              sas_data;       /* Sas config. data */
13836 -       FcCfgData               fc_data;        /* Fc config. data */
13837 -       MPT_IOCTL               *ioctl;         /* ioctl data pointer */
13838 +       SpiCfgData               spi_data;      /* Scsi config. data */
13839 +       RaidCfgData              raid_data;     /* Raid config. data */
13840 +       SasCfgData               sas_data;      /* Sas config. data */
13841 +       FcCfgData                fc_data;       /* Fc config. data */
13842         struct proc_dir_entry   *ioc_dentry;
13843         struct _MPT_ADAPTER     *alt_ioc;       /* ptr to 929 bound adapter port */
13844 -       spinlock_t               diagLock;      /* diagnostic reset lock */
13845 -       int                      diagPending;
13846         u32                      biosVersion;   /* BIOS version from IO Unit Page 2 */
13847         int                      eventTypes;    /* Event logging parameters */
13848         int                      eventContext;  /* Next event context */
13849         int                      eventLogSize;  /* Max number of cached events */
13850         struct _mpt_ioctl_events *events;       /* pointer to event log */
13851         u8                      *cached_fw;     /* Pointer to FW */
13852 -       dma_addr_t              cached_fw_dma;
13853 -       struct list_head         configQ;       /* linked list of config. requests */
13854 +       dma_addr_t               cached_fw_dma;
13855         int                      hs_reply_idx;
13856  #ifndef MFCNT
13857         u32                      pad0;
13858 @@ -665,13 +675,16 @@ typedef struct _MPT_ADAPTER
13859         IOCFactsReply_t          facts;
13860         PortFactsReply_t         pfacts[2];
13861         FCPortPage0_t            fc_port_page0[2];
13862 -       struct timer_list        persist_timer; /* persist table timer */
13863 -       int                      persist_wait_done; /* persist completion flag */
13864 -       u8                       persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */
13865         LANPage0_t               lan_cnfg_page0;
13866         LANPage1_t               lan_cnfg_page1;
13867 +#if defined(CPQ_CIM)
13868 +       u32                      csmi_change_count;     /* count to track all IR
13869 +                                       events for CSMI */
13870 +       u8                       pci_slot_number; /* ioc page 1 - pci slot number */
13871 +#endif
13872  
13873         u8                       ir_firmware; /* =1 if IR firmware detected */
13874 +
13875         /*
13876          * Description: errata_flag_1064
13877          * If a PCIX read occurs within 1 or 2 cycles after the chip receives
13878 @@ -682,25 +695,46 @@ typedef struct _MPT_ADAPTER
13879         int                      aen_event_read_flag; /* flag to indicate event log was read*/
13880         u8                       FirstWhoInit;
13881         u8                       upload_fw;     /* If set, do a fw upload */
13882 -       u8                       reload_fw;     /* Force a FW Reload on next reset */
13883         u8                       NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */
13884 -       u8                       pad1[4];
13885         u8                       DoneCtx;
13886         u8                       TaskCtx;
13887         u8                       InternalCtx;
13888 -       spinlock_t               initializing_hba_lock;
13889 -       int                      initializing_hba_lock_flag;
13890         struct list_head         list;
13891         struct net_device       *netdev;
13892         struct list_head         sas_topology;
13893         struct mutex             sas_topology_mutex;
13894 -       struct mutex             sas_discovery_mutex;
13895 -       u8                       sas_discovery_runtime;
13896 -       u8                       sas_discovery_ignore_events;
13897 +       u8                       disable_hotplug_remove;
13898 +
13899 +       struct workqueue_struct  *fw_event_q;
13900 +       struct list_head         fw_event_list;
13901 +       spinlock_t               fw_event_lock;
13902 +       u8                       fw_events_off; /* if '1', then ignore events */
13903 +       char fw_event_q_name[20];
13904 +
13905 +       struct mptsas_portinfo  *hba_port_info; /* port_info object for the host */
13906 +       u64                      hba_port_sas_addr;
13907 +       u16                      hba_port_num_phy;
13908 +       struct list_head         sas_device_info_list;
13909 +       struct semaphore         sas_device_info_mutex;
13910 +       u8                       old_sas_discovery_protocal;
13911 +       u8                       sas_discovery_quiesce_io;
13912         int                      sas_index; /* index refrencing */
13913 -       MPT_SAS_MGMT             sas_mgmt;
13914 -       struct work_struct       sas_persist_task;
13915 +       MPT_MGMT                 sas_mgmt;
13916 +       MPT_MGMT                 internal_cmds;
13917 +       MPT_MGMT                 mptbase_cmds; /* for sending config pages */
13918 +       MPT_MGMT                 taskmgmt_cmds;
13919 +       MPT_MGMT                 ioctl_cmds;            /* ioctl data pointer */
13920 +       spinlock_t               taskmgmt_lock; /* diagnostic reset lock */
13921 +       int                      taskmgmt_in_progress;
13922 +       u8                       taskmgmt_quiesce_io;
13923 +       u8                       ioc_reset_in_progress;
13924 +#if defined(CPQ_CIM)
13925 +       u8                       num_ports;
13926 +#endif
13927  
13928 +       char                     reset_work_q_name[20];
13929 +       struct workqueue_struct *reset_work_q;
13930 +       struct delayed_work      fault_reset_work;
13931         struct work_struct       fc_setup_reset_work;
13932         struct list_head         fc_rports;
13933         struct work_struct       fc_lsc_work;
13934 @@ -709,14 +743,27 @@ typedef struct _MPT_ADAPTER
13935         struct work_struct       fc_rescan_work;
13936         char                     fc_rescan_work_q_name[20];
13937         struct workqueue_struct *fc_rescan_work_q;
13938 +       unsigned long             hard_resets;          /* driver forced bus resets count */
13939 +       unsigned long             soft_resets;          /* fw/external bus resets count */
13940 +       unsigned long             timeouts;             /* cmd timeouts */
13941         struct scsi_cmnd        **ScsiLookup;
13942         spinlock_t                scsi_lookup_lock;
13943 -
13944 -       char                     reset_work_q_name[20];
13945 -       struct workqueue_struct *reset_work_q;
13946 -       struct delayed_work      fault_reset_work;
13947 -       spinlock_t               fault_reset_work_lock;
13948 -
13949 +       int                       sdev_queue_depth;     /* sdev queue depth */
13950 +       u64                       dma_mask;
13951 +       u32                       broadcast_aen_busy;
13952 +#if defined(DIAG_BUFFER_SUPPORT)
13953 +       u8                      *DiagBuffer[MPI_DIAG_BUF_TYPE_COUNT];
13954 +       u32                     DataSize[MPI_DIAG_BUF_TYPE_COUNT];
13955 +       u32                     DiagBuffer_sz[MPI_DIAG_BUF_TYPE_COUNT];
13956 +       dma_addr_t              DiagBuffer_dma[MPI_DIAG_BUF_TYPE_COUNT];
13957 +       u8                      TraceLevel[MPI_DIAG_BUF_TYPE_COUNT];
13958 +       u8                      DiagBuffer_Status[MPI_DIAG_BUF_TYPE_COUNT];
13959 +       u32                     UniqueId[MPI_DIAG_BUF_TYPE_COUNT];
13960 +       u32                     ExtendedType[MPI_DIAG_BUF_TYPE_COUNT];
13961 +       u32                     ProductSpecific[MPI_DIAG_BUF_TYPE_COUNT][4];
13962 +#endif
13963 +       u8                      sg_addr_size;
13964 +       u8                      SGE_size;
13965  } MPT_ADAPTER;
13966  
13967  /*
13968 @@ -753,13 +800,12 @@ typedef struct _mpt_sge {
13969         dma_addr_t      Address;
13970  } MptSge_t;
13971  
13972 -#define mpt_addr_size() \
13973 -       ((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SGE_FLAGS_64_BIT_ADDRESSING : \
13974 -               MPI_SGE_FLAGS_32_BIT_ADDRESSING)
13975 -
13976 -#define mpt_msg_flags() \
13977 -       ((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \
13978 -               MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32)
13979 +#define mpt_msg_flags(ioc) \
13980 +       (ioc->sg_addr_size == sizeof(u64)) ? MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \
13981 +               MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32
13982 +
13983 +#define MPT_SGE_FLAGS_64_BIT_ADDRESSING \
13984 +       (MPI_SGE_FLAGS_64_BIT_ADDRESSING << MPI_SGE_FLAGS_SHIFT)
13985  
13986  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13987  /*
13988 @@ -778,26 +824,10 @@ typedef struct _mpt_sge {
13989  
13990  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13991  
13992 -#define SCSI_STD_SENSE_BYTES    18
13993 -#define SCSI_STD_INQUIRY_BYTES  36
13994 -#define SCSI_MAX_INQUIRY_BYTES  96
13995 -
13996  /*
13997   * MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers
13998   * Private to the driver.
13999   */
14000 -/* LOCAL structure and fields used when processing
14001 - * internally generated commands. These include:
14002 - * bus scan, dv and config requests.
14003 - */
14004 -typedef struct _MPT_LOCAL_REPLY {
14005 -       ConfigPageHeader_t header;
14006 -       int     completion;
14007 -       u8      sense[SCSI_STD_SENSE_BYTES];
14008 -       u8      scsiStatus;
14009 -       u8      skip;
14010 -       u32     pad;
14011 -} MPT_LOCAL_REPLY;
14012  
14013  #define MPT_HOST_BUS_UNKNOWN           (0xFF)
14014  #define MPT_HOST_TOO_MANY_TM           (0x05)
14015 @@ -813,13 +843,6 @@ typedef struct _MPT_LOCAL_REPLY {
14016  #define MPT_NVRAM_WIDE_DISABLE         (0x00100000)
14017  #define MPT_NVRAM_BOOT_CHOICE          (0x00200000)
14018  
14019 -/* The TM_STATE variable is used to provide strict single threading of TM
14020 - * requests as well as communicate TM error conditions.
14021 - */
14022 -#define TM_STATE_NONE          (0)
14023 -#define        TM_STATE_IN_PROGRESS   (1)
14024 -#define        TM_STATE_ERROR         (2)
14025 -
14026  typedef enum {
14027         FC,
14028         SPI,
14029 @@ -828,63 +851,28 @@ typedef enum {
14030  
14031  typedef struct _MPT_SCSI_HOST {
14032         MPT_ADAPTER              *ioc;
14033 -       int                       port;
14034 -       u32                       pad0;
14035 -       MPT_LOCAL_REPLY          *pLocal;               /* used for internal commands */
14036 -       struct timer_list         timer;
14037 -               /* Pool of memory for holding SCpnts before doing
14038 -                * OS callbacks. freeQ is the free pool.
14039 -                */
14040 -       u8                        tmPending;
14041 -       u8                        resetPending;
14042 -       u8                        negoNvram;            /* DV disabled, nego NVRAM */
14043 -       u8                        pad1;
14044 -       u8                        tmState;
14045 -       u8                        rsvd[2];
14046 -       MPT_FRAME_HDR            *cmdPtr;               /* Ptr to nonOS request */
14047 -       struct scsi_cmnd         *abortSCpnt;
14048 -       MPT_LOCAL_REPLY           localReply;           /* internal cmd reply struct */
14049 -       unsigned long             hard_resets;          /* driver forced bus resets count */
14050 -       unsigned long             soft_resets;          /* fw/external bus resets count */
14051 -       unsigned long             timeouts;             /* cmd timeouts */
14052         ushort                    sel_timeout[MPT_MAX_FC_DEVICES];
14053         char                      *info_kbuf;
14054 -       wait_queue_head_t         scandv_waitq;
14055 -       int                       scandv_wait_done;
14056         long                      last_queue_full;
14057 -       u16                       tm_iocstatus;
14058         u16                       spi_pending;
14059         struct list_head          target_reset_list;
14060  } MPT_SCSI_HOST;
14061  
14062  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14063  /*
14064 - *     More Dynamic Multi-Pathing stuff...
14065 - */
14066 -
14067 -/* Forward decl, a strange C thing, to prevent gcc compiler warnings */
14068 -struct scsi_cmnd;
14069 -
14070 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14071 -/*
14072   * Generic structure passed to the base mpt_config function.
14073   */
14074  typedef struct _x_config_parms {
14075 -       struct list_head         linkage;       /* linked list */
14076 -       struct timer_list        timer;         /* timer function for this request  */
14077         union {
14078                 ConfigExtendedPageHeader_t      *ehdr;
14079                 ConfigPageHeader_t      *hdr;
14080         } cfghdr;
14081         dma_addr_t               physAddr;
14082 -       int                      wait_done;     /* wait for this request */
14083         u32                      pageAddr;      /* properly formatted */
14084 +       u16                      status;
14085         u8                       action;
14086         u8                       dir;
14087         u8                       timeout;       /* seconds */
14088 -       u8                       pad1;
14089 -       u16                      status;
14090 -       u16                      pad2;
14091  } CONFIGPARMS;
14092  
14093  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14094 @@ -909,29 +897,37 @@ extern MPT_FRAME_HDR      *mpt_get_msg_frame(
14095  extern void     mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
14096  extern void     mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
14097  extern void     mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
14098 -extern void     mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
14099 -
14100  extern int      mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag);
14101  extern int      mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
14102  extern u32      mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
14103  extern void     mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
14104  extern int      mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
14105 +extern int      mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
14106  extern int      mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
14107  extern int      mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
14108  extern void     mpt_free_fw_memory(MPT_ADAPTER *ioc);
14109  extern int      mpt_findImVolumes(MPT_ADAPTER *ioc);
14110  extern int      mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
14111  extern int      mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk);
14112 +extern int      mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage1_t phys_disk);
14113 +extern int      mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num);
14114 +
14115 +extern int      mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
14116 +extern void     mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
14117 +extern void     mpt_halt_firmware(MPT_ADAPTER *ioc);
14118  
14119  /*
14120   *  Public data decl's...
14121   */
14122  extern struct list_head          ioc_list;
14123 +extern struct proc_dir_entry   *mpt_proc_root_dir;
14124 +extern int mpt_debug_level;
14125 +extern int mpt_fwfault_debug;
14126  
14127  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14128  #endif         /* } __KERNEL__ */
14129  
14130 -#ifdef CONFIG_64BIT
14131 +#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) || defined(__powerpc64__)
14132  #define CAST_U32_TO_PTR(x)     ((void *)(u64)x)
14133  #define CAST_PTR_TO_U32(x)     ((u32)(u64)x)
14134  #else
14135 @@ -956,7 +952,6 @@ extern struct list_head       ioc_list;
14136  #define MPT_SGE_FLAGS_END_OF_BUFFER            (0x40000000)
14137  #define MPT_SGE_FLAGS_LOCAL_ADDRESS            (0x08000000)
14138  #define MPT_SGE_FLAGS_DIRECTION                        (0x04000000)
14139 -#define MPT_SGE_FLAGS_ADDRESSING               (mpt_addr_size() << MPI_SGE_FLAGS_SHIFT)
14140  #define MPT_SGE_FLAGS_END_OF_LIST              (0x01000000)
14141  
14142  #define MPT_SGE_FLAGS_TRANSACTION_ELEMENT      (0x00000000)
14143 @@ -969,14 +964,12 @@ extern struct list_head     ioc_list;
14144          MPT_SGE_FLAGS_END_OF_BUFFER |  \
14145          MPT_SGE_FLAGS_END_OF_LIST |    \
14146          MPT_SGE_FLAGS_SIMPLE_ELEMENT | \
14147 -        MPT_SGE_FLAGS_ADDRESSING | \
14148          MPT_TRANSFER_IOC_TO_HOST)
14149  #define MPT_SGE_FLAGS_SSIMPLE_WRITE \
14150         (MPT_SGE_FLAGS_LAST_ELEMENT |   \
14151          MPT_SGE_FLAGS_END_OF_BUFFER |  \
14152          MPT_SGE_FLAGS_END_OF_LIST |    \
14153          MPT_SGE_FLAGS_SIMPLE_ELEMENT | \
14154 -        MPT_SGE_FLAGS_ADDRESSING | \
14155          MPT_TRANSFER_HOST_TO_IOC)
14156  
14157  /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14158 --- a/drivers/message/fusion/mptctl.c
14159 +++ b/drivers/message/fusion/mptctl.c
14160 @@ -45,6 +45,7 @@
14161  */
14162  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14163  
14164 +#include <linux/version.h>
14165  #include <linux/kernel.h>
14166  #include <linux/module.h>
14167  #include <linux/errno.h>
14168 @@ -71,6 +72,15 @@
14169  #include "mptbase.h"
14170  #include "mptctl.h"
14171  
14172 +#if defined(CPQ_CIM)
14173 +#include "mptsas.h"
14174 +#include "csmi/csmisas.h"
14175 +#endif // CPQ_CIM
14176 +
14177 +#if defined(DIAG_BUFFER_SUPPORT)
14178 +#include "rejected_ioctls/diag_buffer.h"
14179 +#endif
14180 +
14181  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14182  #define my_NAME                "Fusion MPT misc device (ioctl) driver"
14183  #define my_VERSION     MPT_LINUX_VERSION_COMMON
14184 @@ -84,6 +94,7 @@ MODULE_VERSION(my_VERSION);
14185  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14186  
14187  static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS;
14188 +static u8 mptctl_taskmgmt_id = MPT_MAX_PROTOCOL_DRIVERS;
14189  
14190  static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
14191  
14192 @@ -112,6 +123,42 @@ static int mptctl_do_reset(unsigned long
14193  static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
14194  static int mptctl_hp_targetinfo(unsigned long arg);
14195  
14196 +#if defined(CPQ_CIM)
14197 +/* csmisas proto's*/
14198 +static int csmisas_get_driver_info(unsigned long arg);
14199 +static int csmisas_get_cntlr_status(unsigned long arg);
14200 +static int csmisas_get_cntlr_config(unsigned long arg);
14201 +static int csmisas_get_phy_info(unsigned long arg);
14202 +static int csmisas_get_scsi_address(unsigned long arg);
14203 +static int csmisas_get_link_errors(unsigned long arg);
14204 +static int csmisas_smp_passthru(unsigned long arg);
14205 +static int csmisas_firmware_download(unsigned long arg);
14206 +static int csmisas_get_raid_info(unsigned long arg);
14207 +static int csmisas_get_raid_config(unsigned long arg);
14208 +static int csmisas_get_raid_features(unsigned long arg);
14209 +static int csmisas_set_raid_control(unsigned long arg);
14210 +static int csmisas_get_raid_element(unsigned long arg);
14211 +static int csmisas_set_raid_operation(unsigned long arg);
14212 +static int csmisas_set_phy_info(unsigned long arg);
14213 +static int csmisas_ssp_passthru(unsigned long arg);
14214 +static int csmisas_stp_passthru(unsigned long arg);
14215 +static int csmisas_get_sata_signature(unsigned long arg);
14216 +static int csmisas_get_device_address(unsigned long arg);
14217 +static int csmisas_task_managment(unsigned long arg);
14218 +static int csmisas_phy_control(unsigned long arg);
14219 +static int csmisas_get_connector_info(unsigned long arg);
14220 +static int csmisas_get_location(unsigned long arg);
14221 +#endif // CPQ_CIM
14222 +
14223 +#if defined(DIAG_BUFFER_SUPPORT)
14224 +/* diag_buffer proto's */
14225 +static int mptctl_register_diag_buffer(unsigned long arg);
14226 +static int mptctl_release_diag_buffer(unsigned long arg);
14227 +static int mptctl_unregister_diag_buffer(unsigned long arg);
14228 +static int mptctl_query_diag_buffer(unsigned long arg);
14229 +static int mptctl_read_diag_buffer(unsigned long arg);
14230 +#endif // DIAG_BUFFER_SUPPORT
14231 +
14232  static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
14233  static void mptctl_remove(struct pci_dev *);
14234  
14235 @@ -127,10 +174,6 @@ static MptSge_t *kbuf_alloc_2_sgl(int by
14236                 struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
14237  static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
14238                 struct buflist *buflist, MPT_ADAPTER *ioc);
14239 -static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
14240 -static int  mptctl_bus_reset(MPT_IOCTL *ioctl);
14241 -static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd);
14242 -static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
14243  
14244  /*
14245   * Reset Handler cleanup function
14246 @@ -183,10 +226,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, in
14247         int rc = 0;
14248  
14249         if (nonblock) {
14250 -               if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
14251 +               if (!mutex_trylock(&ioc->ioctl_cmds.mutex))
14252                         rc = -EAGAIN;
14253         } else {
14254 -               if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
14255 +               if (mutex_lock_interruptible(&ioc->ioctl_cmds.mutex))
14256                         rc = -ERESTARTSYS;
14257         }
14258         return rc;
14259 @@ -202,131 +245,104 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, in
14260  static int
14261  mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
14262  {
14263 -       char *sense_data;
14264 -       int sz, req_index;
14265 -       u16 iocStatus;
14266 -       u8 cmd;
14267 -
14268 -       if (req)
14269 -                cmd = req->u.hdr.Function;
14270 -       else
14271 -               return 1;
14272 -       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tcompleting mpi function (0x%02X), req=%p, "
14273 -           "reply=%p\n", ioc->name,  req->u.hdr.Function, req, reply));
14274 -
14275 -       if (ioc->ioctl) {
14276 +       char    *sense_data;
14277 +       int     req_index;
14278 +       int     sz;
14279  
14280 -               if (reply==NULL) {
14281 +       if (!req)
14282 +               return 0;
14283  
14284 -                       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_reply() NULL Reply "
14285 -                               "Function=%x!\n", ioc->name, cmd));
14286 +       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "completing mpi function "
14287 +           "(0x%02X), req=%p, reply=%p\n", ioc->name,  req->u.hdr.Function,
14288 +           req, reply));
14289  
14290 -                       ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
14291 -                       ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
14292 +       /*
14293 +        * Handling continuation of the same reply. Processing the first
14294 +        * reply, and eating the other replys that come later.
14295 +        */
14296 +       if (ioc->ioctl_cmds.msg_context != req->u.hdr.MsgContext)
14297 +               goto out_continuation;
14298  
14299 -                       /* We are done, issue wake up
14300 -                       */
14301 -                       ioc->ioctl->wait_done = 1;
14302 -                       wake_up (&mptctl_wait);
14303 -                       return 1;
14304 +       ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
14305  
14306 -               }
14307 +       if (!reply)
14308 +               goto out;
14309  
14310 -               /* Copy the reply frame (which much exist
14311 -                * for non-SCSI I/O) to the IOC structure.
14312 -                */
14313 -               memcpy(ioc->ioctl->ReplyFrame, reply,
14314 -                       min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
14315 -               ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
14316 +       ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
14317 +       sz = min(ioc->reply_sz, 4*reply->u.reply.MsgLength);
14318 +       memcpy(ioc->ioctl_cmds.reply, reply, sz);
14319  
14320 -               /* Set the command status to GOOD if IOC Status is GOOD
14321 -                * OR if SCSI I/O cmd and data underrun or recovered error.
14322 -                */
14323 -               iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK;
14324 -               if (iocStatus  == MPI_IOCSTATUS_SUCCESS)
14325 -                       ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
14326 -
14327 -               if (iocStatus || reply->u.reply.IOCLogInfo)
14328 -                       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tiocstatus (0x%04X), "
14329 -                               "loginfo (0x%08X)\n", ioc->name,
14330 -                               iocStatus,
14331 -                               le32_to_cpu(reply->u.reply.IOCLogInfo)));
14332 -
14333 -               if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
14334 -                       (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
14335 -
14336 -                       if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState)
14337 -                               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14338 -                                       "\tscsi_status (0x%02x), scsi_state (0x%02x), "
14339 -                                       "tag = (0x%04x), transfer_count (0x%08x)\n", ioc->name,
14340 -                                       reply->u.sreply.SCSIStatus,
14341 -                                       reply->u.sreply.SCSIState,
14342 -                                       le16_to_cpu(reply->u.sreply.TaskTag),
14343 -                                       le32_to_cpu(reply->u.sreply.TransferCount)));
14344 -
14345 -                       ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
14346 -
14347 -                       if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
14348 -                       (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
14349 -                       ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
14350 -                       }
14351 -               }
14352 +       if (reply->u.reply.IOCStatus || reply->u.reply.IOCLogInfo)
14353 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14354 +                   "iocstatus (0x%04X), loginfo (0x%08X)\n", ioc->name,
14355 +                   le16_to_cpu(reply->u.reply.IOCStatus),
14356 +                   le32_to_cpu(reply->u.reply.IOCLogInfo)));
14357 +
14358 +       if ((req->u.hdr.Function == MPI_FUNCTION_SCSI_IO_REQUEST) ||
14359 +               (req->u.hdr.Function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
14360 +
14361 +               if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState)
14362 +                       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14363 +                       "scsi_status (0x%02x), scsi_state (0x%02x), "
14364 +                       "tag = (0x%04x), transfer_count (0x%08x)\n", ioc->name,
14365 +                       reply->u.sreply.SCSIStatus,
14366 +                       reply->u.sreply.SCSIState,
14367 +                       le16_to_cpu(reply->u.sreply.TaskTag),
14368 +                       le32_to_cpu(reply->u.sreply.TransferCount)));
14369  
14370 -               /* Copy the sense data - if present
14371 -                */
14372 -               if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
14373 -                       (reply->u.sreply.SCSIState &
14374 -                        MPI_SCSI_STATE_AUTOSENSE_VALID)){
14375 +               if (reply->u.sreply.SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
14376                         sz = req->u.scsireq.SenseBufferLength;
14377                         req_index =
14378                             le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
14379 -                       sense_data =
14380 -                           ((u8 *)ioc->sense_buf_pool +
14381 +                       sense_data = ((u8 *)ioc->sense_buf_pool +
14382                              (req_index * MPT_SENSE_BUFFER_ALLOC));
14383 -                       memcpy(ioc->ioctl->sense, sense_data, sz);
14384 -                       ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
14385 +                       memcpy(ioc->ioctl_cmds.sense, sense_data, sz);
14386 +                       ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_SENSE_VALID;
14387                 }
14388 +       }
14389  
14390 -               if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
14391 -                       mptctl_free_tm_flags(ioc);
14392 -
14393 -               /* We are done, issue wake up
14394 -                */
14395 -               ioc->ioctl->wait_done = 1;
14396 -               wake_up (&mptctl_wait);
14397 + out:
14398 +       /* We are done, issue wake up
14399 +        */
14400 +       if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) {
14401 +               if (req->u.hdr.Function == MPI_FUNCTION_SCSI_TASK_MGMT)
14402 +                       mpt_clear_taskmgmt_in_progress_flag(ioc);
14403 +               ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
14404 +               complete(&ioc->ioctl_cmds.done);
14405         }
14406 +
14407 + out_continuation:
14408 +       if (reply && (reply->u.reply.MsgFlags &
14409 +           MPI_MSGFLAGS_CONTINUATION_REPLY))
14410 +               return 0;
14411         return 1;
14412  }
14413  
14414 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14415 -/* mptctl_timeout_expired
14416 - *
14417 - * Expecting an interrupt, however timed out.
14418 - *
14419 - */
14420 -static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
14421 +static int
14422 +mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
14423  {
14424 -       int rc = 1;
14425 +       if (!mf)
14426 +               return 0;
14427  
14428 -       dctlprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT ": Timeout Expired! Host %d\n",
14429 -                               ioctl->ioc->name, ioctl->ioc->id));
14430 -       if (ioctl == NULL)
14431 -               return;
14432 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p, mr=%p)\n",
14433 +           ioc->name, mf, mr));
14434  
14435 -       ioctl->wait_done = 0;
14436 -       if (ioctl->reset & MPTCTL_RESET_OK)
14437 -               rc = mptctl_bus_reset(ioctl);
14438 -
14439 -       if (rc) {
14440 -               /* Issue a reset for this device.
14441 -                * The IOC is not responding.
14442 -                */
14443 -               dctlprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
14444 -                        ioctl->ioc->name));
14445 -               mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
14446 -       }
14447 -       return;
14448 +       ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
14449 +
14450 +       if (!mr)
14451 +               goto out;
14452  
14453 +       ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
14454 +       memcpy(ioc->taskmgmt_cmds.reply, mr,
14455 +           min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
14456 + out:
14457 +       if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
14458 +               mpt_clear_taskmgmt_in_progress_flag(ioc);
14459 +               ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
14460 +               complete(&ioc->taskmgmt_cmds.done);
14461 +               return 1;
14462 +       }
14463 +       return 0;
14464  }
14465  
14466  /* mptctl_bus_reset
14467 @@ -334,132 +350,181 @@ static void mptctl_timeout_expired (MPT_
14468   * Bus reset code.
14469   *
14470   */
14471 -static int mptctl_bus_reset(MPT_IOCTL *ioctl)
14472 +static int
14473 +mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
14474  {
14475         MPT_FRAME_HDR   *mf;
14476         SCSITaskMgmt_t  *pScsiTm;
14477 -       MPT_SCSI_HOST   *hd;
14478 +       SCSITaskMgmtReply_t *pScsiTmReply;
14479         int              ii;
14480 -       int              retval=0;
14481 -
14482 -
14483 -       ioctl->reset &= ~MPTCTL_RESET_OK;
14484 -
14485 -       if (ioctl->ioc->sh == NULL)
14486 +       int              retval;
14487 +       unsigned long    timeout;
14488 +       unsigned long    time_count;
14489 +       u16              iocstatus;
14490 +
14491 +       /* bus reset is only good for SCSI IO, RAID PASSTHRU */
14492 +       if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) ||
14493 +           (function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
14494 +               dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt, not SCSI_IO!!\n",
14495 +                               ioc->name));
14496                 return -EPERM;
14497 +       }
14498  
14499 -       hd = shost_priv(ioctl->ioc->sh);
14500 -       if (hd == NULL)
14501 +       mutex_lock(&ioc->taskmgmt_cmds.mutex);
14502 +       if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
14503 +               mutex_unlock(&ioc->taskmgmt_cmds.mutex);
14504                 return -EPERM;
14505 +       }
14506  
14507 -       /* Single threading ....
14508 -        */
14509 -       if (mptctl_set_tm_flags(hd) != 0)
14510 -               return -EPERM;
14511 +       retval = 0;
14512  
14513         /* Send request
14514          */
14515 -       if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc)) == NULL) {
14516 -               dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt, no msg frames!!\n",
14517 -                               ioctl->ioc->name));
14518 -
14519 -               mptctl_free_tm_flags(ioctl->ioc);
14520 -               return -ENOMEM;
14521 +       if ((mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc)) == NULL) {
14522 +               dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt, no msg frames!!\n",
14523 +                               ioc->name));
14524 +               mpt_clear_taskmgmt_in_progress_flag(ioc);
14525 +               retval = -ENOMEM;
14526 +               goto mptctl_bus_reset_done;
14527         }
14528  
14529 -       dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
14530 -                       ioctl->ioc->name, mf));
14531 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
14532 +               ioc->name, mf));
14533  
14534         pScsiTm = (SCSITaskMgmt_t *) mf;
14535 -       pScsiTm->TargetID = ioctl->id;
14536 -       pScsiTm->Bus = hd->port;        /* 0 */
14537 -       pScsiTm->ChainOffset = 0;
14538 +       memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
14539         pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
14540 -       pScsiTm->Reserved = 0;
14541         pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
14542 -       pScsiTm->Reserved1 = 0;
14543         pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
14544 -
14545 +       pScsiTm->TargetID = 0;
14546 +       pScsiTm->Bus = 0;
14547 +       pScsiTm->ChainOffset = 0;
14548 +       pScsiTm->Reserved = 0;
14549 +       pScsiTm->Reserved1 = 0;
14550 +       pScsiTm->TaskMsgContext = 0;
14551         for (ii= 0; ii < 8; ii++)
14552                 pScsiTm->LUN[ii] = 0;
14553 -
14554         for (ii=0; ii < 7; ii++)
14555                 pScsiTm->Reserved2[ii] = 0;
14556  
14557 -       pScsiTm->TaskMsgContext = 0;
14558 -       dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT
14559 -               "mptctl_bus_reset: issued.\n", ioctl->ioc->name));
14560 -
14561 -       DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf);
14562 +       switch (ioc->bus_type) {
14563 +               case FC:
14564 +                       timeout = 40;
14565 +                       break;
14566 +               case SAS:
14567 +                       timeout = 30;
14568 +                       break;
14569 +               case SPI:
14570 +               default:
14571 +                       timeout = 2;
14572 +                       break;
14573 +       }
14574  
14575 -       ioctl->wait_done=0;
14576 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt type=%d timeout=%ld\n",
14577 +           ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout));
14578  
14579 -       if ((ioctl->ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
14580 -           (ioctl->ioc->facts.MsgVersion >= MPI_VERSION_01_05))
14581 -               mpt_put_msg_frame_hi_pri(mptctl_id, ioctl->ioc, mf);
14582 +       INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
14583 +       CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
14584 +       time_count = jiffies;
14585 +       if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
14586 +           (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
14587 +               mpt_put_msg_frame_hi_pri(mptctl_taskmgmt_id, ioc, mf);
14588         else {
14589 -               retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
14590 -                       sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
14591 +               retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc,
14592 +                   sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
14593                 if (retval != 0) {
14594 -                       dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!"
14595 -                               " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
14596 -                               hd->ioc, mf));
14597 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "TaskMgmt send_handshake FAILED!"
14598 +                               " (ioc %p, mf %p, rc=%d) \n", ioc->name,
14599 +                               ioc, mf, retval));
14600 +                       mpt_clear_taskmgmt_in_progress_flag(ioc);
14601                         goto mptctl_bus_reset_done;
14602                 }
14603         }
14604  
14605         /* Now wait for the command to complete */
14606 -       ii = wait_event_timeout(mptctl_wait,
14607 -            ioctl->wait_done == 1,
14608 -            HZ*5 /* 5 second timeout */);
14609 -
14610 -       if(ii <=0 && (ioctl->wait_done != 1 ))  {
14611 -               mpt_free_msg_frame(hd->ioc, mf);
14612 -               ioctl->wait_done = 0;
14613 -               retval = -1; /* return failure */
14614 +       ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
14615 +       if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
14616 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14617 +                   "TaskMgmt failed\n", ioc->name));
14618 +               mpt_free_msg_frame(ioc, mf);
14619 +               mpt_clear_taskmgmt_in_progress_flag(ioc);
14620 +               if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
14621 +                       retval = 0;
14622 +               else
14623 +                       retval = -1; /* return failure */
14624 +               goto mptctl_bus_reset_done;
14625         }
14626  
14627 -mptctl_bus_reset_done:
14628 -
14629 -       mptctl_free_tm_flags(ioctl->ioc);
14630 -       return retval;
14631 -}
14632 -
14633 -static int
14634 -mptctl_set_tm_flags(MPT_SCSI_HOST *hd) {
14635 -       unsigned long flags;
14636 -
14637 -       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
14638 +       if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
14639 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14640 +                   "TaskMgmt failed\n", ioc->name));
14641 +               retval = -1; /* return failure */
14642 +               goto mptctl_bus_reset_done;
14643 +       }
14644  
14645 -       if (hd->tmState == TM_STATE_NONE) {
14646 -               hd->tmState = TM_STATE_IN_PROGRESS;
14647 -               hd->tmPending = 1;
14648 -               spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
14649 -       } else {
14650 -               spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
14651 -               return -EBUSY;
14652 +       pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
14653 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14654 +           "TaskMgmt fw_channel = %d, fw_id = %d, task_type=0x%02X, "
14655 +           "iocstatus=0x%04X\n\tloginfo=0x%08X, response_code=0x%02X, "
14656 +           "term_cmnds=%d\n", ioc->name, pScsiTmReply->Bus,
14657 +           pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
14658 +           le16_to_cpu(pScsiTmReply->IOCStatus),
14659 +           le32_to_cpu(pScsiTmReply->IOCLogInfo),
14660 +           pScsiTmReply->ResponseCode,
14661 +           le32_to_cpu(pScsiTmReply->TerminationCount)));
14662 +
14663 +       iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
14664 +
14665 +       if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
14666 +          iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED ||
14667 +          iocstatus == MPI_IOCSTATUS_SUCCESS)
14668 +               retval = 0;
14669 +       else {
14670 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14671 +                   "TaskMgmt failed\n", ioc->name));
14672 +               retval = -1; /* return failure */
14673         }
14674  
14675 -       return 0;
14676 +
14677 + mptctl_bus_reset_done:
14678 +       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
14679 +       CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
14680 +       return retval;
14681  }
14682  
14683  static void
14684 -mptctl_free_tm_flags(MPT_ADAPTER *ioc)
14685 +mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
14686  {
14687 -       MPT_SCSI_HOST * hd;
14688         unsigned long flags;
14689  
14690 -       hd = shost_priv(ioc->sh);
14691 -       if (hd == NULL)
14692 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n",
14693 +               ioc->name, __FUNCTION__));
14694 +
14695 +       if(mpt_fwfault_debug)
14696 +               mpt_halt_firmware(ioc);
14697 +
14698 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
14699 +       if (ioc->ioc_reset_in_progress) {
14700 +               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
14701 +               CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
14702 +               mpt_free_msg_frame(ioc, mf);
14703                 return;
14704 +       }
14705 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
14706  
14707 -       spin_lock_irqsave(&ioc->FreeQlock, flags);
14708  
14709 -       hd->tmState = TM_STATE_NONE;
14710 -       hd->tmPending = 0;
14711 -       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
14712 +       if (!mptctl_bus_reset(ioc, mf->u.hdr.Function))
14713 +               return;
14714  
14715 -       return;
14716 +       /* Issue a reset for this device.
14717 +        * The IOC is not responding.
14718 +        */
14719 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
14720 +                ioc->name));
14721 +       CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
14722 +       if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
14723 +               mpt_HardResetHandler(ioc, CAN_SLEEP);
14724 +       mpt_free_msg_frame(ioc, mf);
14725  }
14726  
14727  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
14728 @@ -472,22 +537,23 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc)
14729  static int
14730  mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
14731  {
14732 -       MPT_IOCTL *ioctl = ioc->ioctl;
14733 -       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC %s_reset routed to IOCTL driver!\n", ioc->name,
14734 -               reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
14735 -               reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
14736 -
14737 -       if(ioctl == NULL)
14738 -               return 1;
14739 -
14740         switch(reset_phase) {
14741         case MPT_IOC_SETUP_RESET:
14742 -               ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
14743 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14744 +                   "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __FUNCTION__));
14745 +               break;
14746 +       case MPT_IOC_PRE_RESET:
14747 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14748 +                   "%s: MPT_IOC_PRE_RESET\n", ioc->name, __FUNCTION__));
14749                 break;
14750         case MPT_IOC_POST_RESET:
14751 -               ioctl->status &= ~MPT_IOCTL_STATUS_DID_IOCRESET;
14752 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
14753 +                   "%s: MPT_IOC_POST_RESET\n", ioc->name, __FUNCTION__));
14754 +               if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) {
14755 +                       ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_DID_IOCRESET;
14756 +                       complete(&ioc->ioctl_cmds.done);
14757 +               }
14758                 break;
14759 -       case MPT_IOC_PRE_RESET:
14760         default:
14761                 break;
14762         }
14763 @@ -505,7 +571,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, E
14764         event = le32_to_cpu(pEvReply->Event) & 0xFF;
14765  
14766         dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s() called\n",
14767 -           ioc->name, __func__));
14768 +           ioc->name, __FUNCTION__));
14769         if(async_queue == NULL)
14770                 return 1;
14771  
14772 @@ -548,15 +614,11 @@ static int
14773  mptctl_fasync(int fd, struct file *filep, int mode)
14774  {
14775         MPT_ADAPTER     *ioc;
14776 -       int ret;
14777  
14778 -       lock_kernel();
14779         list_for_each_entry(ioc, &ioc_list, list)
14780                 ioc->aen_event_read_flag=0;
14781  
14782 -       ret = fasync_helper(fd, filep, mode, &async_queue);
14783 -       unlock_kernel();
14784 -       return ret;
14785 +       return fasync_helper(fd, filep, mode, &async_queue);
14786  }
14787  
14788  static int
14789 @@ -582,6 +644,7 @@ __mptctl_ioctl(struct file *file, unsign
14790         int ret;
14791         MPT_ADAPTER *iocp = NULL;
14792  
14793 +
14794         if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
14795                 printk(KERN_ERR MYNAM "%s::mptctl_ioctl() @%d - "
14796                                 "Unable to copy mpt_ioctl_header data @ %p\n",
14797 @@ -596,17 +659,12 @@ __mptctl_ioctl(struct file *file, unsign
14798         iocnumX = khdr.iocnum & 0xFF;
14799         if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
14800             (iocp == NULL)) {
14801 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
14802                 printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - ioc%d not found!\n",
14803                                 __FILE__, __LINE__, iocnumX);
14804                 return -ENODEV;
14805         }
14806  
14807 -       if (!iocp->active) {
14808 -               printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - Controller disabled.\n",
14809 -                               __FILE__, __LINE__);
14810 -               return -EFAULT;
14811 -       }
14812 -
14813         /* Handle those commands that are just returning
14814          * information stored in the driver.
14815          * These commands should never time out and are unaffected
14816 @@ -626,6 +684,25 @@ __mptctl_ioctl(struct file *file, unsign
14817                 return mptctl_eventreport(arg);
14818         } else if (cmd == MPTFWREPLACE) {
14819                 return mptctl_replace_fw(arg);
14820 +#if defined(DIAG_BUFFER_SUPPORT)
14821 +/* diag_buffer static data calls*/
14822 +       } else if (cmd == MPTDIAGQUERY) {
14823 +               return mptctl_query_diag_buffer(arg);
14824 +       } else if (cmd == MPTDIAGUNREGISTER) {
14825 +               return mptctl_unregister_diag_buffer(arg);
14826 +#endif
14827 +
14828 +#if defined(CPQ_CIM)
14829 +/* csmisas static data calls*/
14830 +       } else if (cmd == CC_CSMI_SAS_GET_DRIVER_INFO) {
14831 +               return csmisas_get_driver_info(arg);
14832 +       } else if (cmd == CC_CSMI_SAS_GET_CNTLR_STATUS) {
14833 +               return csmisas_get_cntlr_status(arg);
14834 +       } else if (cmd == CC_CSMI_SAS_GET_SCSI_ADDRESS) {
14835 +               return csmisas_get_scsi_address(arg);
14836 +       } else if (cmd == CC_CSMI_SAS_GET_DEVICE_ADDRESS){
14837 +               return csmisas_get_device_address(arg);
14838 +#endif // CPQ_CIM
14839         }
14840  
14841         /* All of these commands require an interrupt or
14842 @@ -634,6 +711,8 @@ __mptctl_ioctl(struct file *file, unsign
14843         if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
14844                 return ret;
14845  
14846 +//     dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT ": mptctl_ioctl()\n", iocp->name));
14847 +
14848         if (cmd == MPTFWDOWNLOAD)
14849                 ret = mptctl_fw_download(arg);
14850         else if (cmd == MPTCOMMAND)
14851 @@ -644,10 +723,61 @@ __mptctl_ioctl(struct file *file, unsign
14852                 ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
14853         else if (cmd == HP_GETTARGETINFO)
14854                 ret = mptctl_hp_targetinfo(arg);
14855 +#if defined(CPQ_CIM)
14856 +/* csmisas requiring fw calls*/
14857 +       else if (cmd == CC_CSMI_SAS_GET_CNTLR_CONFIG)
14858 +               ret = csmisas_get_cntlr_config(arg);
14859 +       else if (cmd == CC_CSMI_SAS_GET_PHY_INFO)
14860 +               ret = csmisas_get_phy_info(arg);
14861 +       else if (cmd == CC_CSMI_SAS_GET_SATA_SIGNATURE)
14862 +               ret = csmisas_get_sata_signature(arg);
14863 +       else if (cmd == CC_CSMI_SAS_GET_LINK_ERRORS)
14864 +               ret = csmisas_get_link_errors(arg);
14865 +       else if (cmd == CC_CSMI_SAS_SMP_PASSTHRU)
14866 +               ret = csmisas_smp_passthru(arg);
14867 +       else if (cmd == CC_CSMI_SAS_SSP_PASSTHRU)
14868 +               ret = csmisas_ssp_passthru(arg);
14869 +       else if (cmd == CC_CSMI_SAS_FIRMWARE_DOWNLOAD)
14870 +               ret = csmisas_firmware_download(arg);
14871 +       else if (cmd == CC_CSMI_SAS_GET_RAID_INFO)
14872 +               ret = csmisas_get_raid_info(arg);
14873 +       else if (cmd == CC_CSMI_SAS_GET_RAID_CONFIG)
14874 +               ret = csmisas_get_raid_config(arg);
14875 +       else if (cmd == CC_CSMI_SAS_GET_RAID_FEATURES)
14876 +               ret = csmisas_get_raid_features(arg);
14877 +       else if (cmd == CC_CSMI_SAS_SET_RAID_CONTROL)
14878 +               ret = csmisas_set_raid_control(arg);
14879 +       else if (cmd == CC_CSMI_SAS_GET_RAID_ELEMENT)
14880 +               ret = csmisas_get_raid_element(arg);
14881 +       else if (cmd == CC_CSMI_SAS_SET_RAID_OPERATION)
14882 +               ret = csmisas_set_raid_operation(arg);
14883 +       else if (cmd == CC_CSMI_SAS_SET_PHY_INFO)
14884 +               ret = csmisas_set_phy_info(arg);
14885 +       else if (cmd == CC_CSMI_SAS_STP_PASSTHRU)
14886 +               ret = csmisas_stp_passthru(arg);
14887 +       else if (cmd == CC_CSMI_SAS_TASK_MANAGEMENT)
14888 +               ret = csmisas_task_managment(arg);
14889 +       else if (cmd == CC_CSMI_SAS_PHY_CONTROL)
14890 +               ret = csmisas_phy_control(arg);
14891 +       else if (cmd == CC_CSMI_SAS_GET_CONNECTOR_INFO)
14892 +               ret = csmisas_get_connector_info(arg);
14893 +       else if (cmd == CC_CSMI_SAS_GET_LOCATION)
14894 +               ret = csmisas_get_location(arg);
14895 +#endif // CPQ_CIM
14896 +
14897 +#if defined(DIAG_BUFFER_SUPPORT)
14898 +/* diag_buffer requiring fw calls*/
14899 +       else if (cmd == MPTDIAGREGISTER)
14900 +               ret = mptctl_register_diag_buffer(arg);
14901 +       else if (cmd == MPTDIAGRELEASE)
14902 +               ret = mptctl_release_diag_buffer(arg);
14903 +       else if (cmd == MPTDIAGREADBUFFER)
14904 +               ret = mptctl_read_diag_buffer(arg);
14905 +#endif // DIAG_BUFFER_SUPPORT
14906         else
14907                 ret = -EINVAL;
14908  
14909 -       mutex_unlock(&iocp->ioctl->ioctl_mutex);
14910 +       mutex_unlock(&iocp->ioctl_cmds.mutex);
14911  
14912         return ret;
14913  }
14914 @@ -676,6 +806,7 @@ static int mptctl_do_reset(unsigned long
14915         }
14916  
14917         if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
14918 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
14919                 printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n",
14920                                 __FILE__, __LINE__, krinfo.hdr.iocnum);
14921                 return -ENODEV; /* (-6) No such device or address */
14922 @@ -763,10 +894,11 @@ mptctl_do_fw_download(int ioc, char __us
14923         int                      sge_offset = 0;
14924         u16                      iocstat;
14925         pFWDownloadReply_t       ReplyMsg = NULL;
14926 +       unsigned long            timeleft;
14927  
14928         if (mpt_verify_adapter(ioc, &iocp) < 0) {
14929 -               printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
14930 -                                ioc);
14931 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
14932 +               printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n", ioc);
14933                 return -ENODEV; /* (-6) No such device or address */
14934         } else {
14935  
14936 @@ -847,10 +979,10 @@ mptctl_do_fw_download(int ioc, char __us
14937          *      64              4
14938          */
14939         maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t))
14940 -                       / (sizeof(dma_addr_t) + sizeof(u32));
14941 +                       / iocp->SGE_size;
14942         if (numfrags > maxfrags) {
14943                 ret = -EMLINK;
14944 -               goto fwdl_out;
14945 +               goto fwdl_out;
14946         }
14947  
14948         dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: sgl buffer = %p, sgfrags = %d\n",
14949 @@ -875,19 +1007,19 @@ mptctl_do_fw_download(int ioc, char __us
14950                 if (nib == 0 || nib == 3) {
14951                         ;
14952                 } else if (sgIn->Address) {
14953 -                       mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
14954 +                       iocp->add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
14955                         n++;
14956                         if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
14957                                 printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - "
14958 -                                       "Unable to copy f/w buffer hunk#%d @ %p\n",
14959 -                                       iocp->name, __FILE__, __LINE__, n, ufwbuf);
14960 +                                   "Unable to copy f/w buffer hunk#%d @ %p\n",
14961 +                                   iocp->name, __FILE__, __LINE__, n, ufwbuf);
14962                                 goto fwdl_out;
14963                         }
14964                         fw_bytes_copied += bl->len;
14965                 }
14966                 sgIn++;
14967                 bl++;
14968 -               sgOut += (sizeof(dma_addr_t) + sizeof(u32));
14969 +               sgOut += iocp->SGE_size;
14970         }
14971  
14972         DBG_DUMP_FW_DOWNLOAD(iocp, (u32 *)mf, numfrags);
14973 @@ -896,16 +1028,27 @@ mptctl_do_fw_download(int ioc, char __us
14974          * Finally, perform firmware download.
14975          */
14976         ReplyMsg = NULL;
14977 +       SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, dlmsg->MsgContext);
14978 +       INITIALIZE_MGMT_STATUS(iocp->ioctl_cmds.status)
14979         mpt_put_msg_frame(mptctl_id, iocp, mf);
14980  
14981         /* Now wait for the command to complete */
14982 -       ret = wait_event_timeout(mptctl_wait,
14983 -            iocp->ioctl->wait_done == 1,
14984 -            HZ*60);
14985 -
14986 -       if(ret <=0 && (iocp->ioctl->wait_done != 1 )) {
14987 -       /* Now we need to reset the board */
14988 -               mptctl_timeout_expired(iocp->ioctl);
14989 +       timeleft = wait_for_completion_timeout(&iocp->ioctl_cmds.done, HZ*60);
14990 +       if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
14991 +               ret = -ETIME;
14992 +               printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __FUNCTION__);
14993 +               if (iocp->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
14994 +                       mpt_free_msg_frame(iocp, mf);
14995 +                       goto fwdl_out;
14996 +               }
14997 +               if (!timeleft)
14998 +                       mptctl_timeout_expired(iocp, mf);
14999 +               goto fwdl_out;
15000 +       }
15001 +
15002 +       if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
15003 +               printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __FUNCTION__);
15004 +               mpt_free_msg_frame(iocp, mf);
15005                 ret = -ENODATA;
15006                 goto fwdl_out;
15007         }
15008 @@ -913,31 +1056,34 @@ mptctl_do_fw_download(int ioc, char __us
15009         if (sgl)
15010                 kfree_sgl(sgl, sgl_dma, buflist, iocp);
15011  
15012 -       ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame;
15013 +       ReplyMsg = (pFWDownloadReply_t)iocp->ioctl_cmds.reply;
15014         iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
15015         if (iocstat == MPI_IOCSTATUS_SUCCESS) {
15016 -               printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name);
15017 +               printk(MYIOC_s_INFO_FMT ": F/W update successfully sent!\n", iocp->name);
15018                 return 0;
15019         } else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {
15020 -               printk(MYIOC_s_WARN_FMT "Hmmm...  F/W download not supported!?!\n",
15021 -                       iocp->name);
15022 +               printk(MYIOC_s_WARN_FMT "Hmmm...  doesn't support F/W download?\n",
15023 +                   iocp->name);
15024                 printk(MYIOC_s_WARN_FMT "(time to go bang on somebodies door)\n",
15025 -                       iocp->name);
15026 +                   iocp->name);
15027                 return -EBADRQC;
15028         } else if (iocstat == MPI_IOCSTATUS_BUSY) {
15029                 printk(MYIOC_s_WARN_FMT "IOC_BUSY!\n", iocp->name);
15030                 printk(MYIOC_s_WARN_FMT "(try again later?)\n", iocp->name);
15031                 return -EBUSY;
15032         } else {
15033 -               printk(MYIOC_s_WARN_FMT "ioctl_fwdl() returned [bad] status = %04xh\n",
15034 -                       iocp->name, iocstat);
15035 +               printk(MYIOC_s_WARN_FMT "returned [bad] status = %04xh\n",
15036 +                   iocp->name, iocstat);
15037                 printk(MYIOC_s_WARN_FMT "(bad VooDoo)\n", iocp->name);
15038                 return -ENOMSG;
15039         }
15040         return 0;
15041  
15042  fwdl_out:
15043 -        kfree_sgl(sgl, sgl_dma, buflist, iocp);
15044 +
15045 +       CLEAR_MGMT_STATUS(iocp->ioctl_cmds.status);
15046 +       SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, 0);
15047 +       kfree_sgl(sgl, sgl_dma, buflist, iocp);
15048         return ret;
15049  }
15050  
15051 @@ -1008,7 +1154,7 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
15052          *
15053          */
15054         sgl = sglbuf;
15055 -       sg_spill = ((ioc->req_sz - sge_offset)/(sizeof(dma_addr_t) + sizeof(u32))) - 1;
15056 +       sg_spill = ((ioc->req_sz - sge_offset)/ioc->SGE_size) - 1;
15057         while (bytes_allocd < bytes) {
15058                 this_alloc = min(alloc_sz, bytes-bytes_allocd);
15059                 buflist[buflist_ent].len = this_alloc;
15060 @@ -1019,9 +1165,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
15061                         alloc_sz = alloc_sz / 2;
15062                         if (alloc_sz == 0) {
15063                                 printk(MYIOC_s_WARN_FMT "-SG: No can do - "
15064 -                                   "not enough memory!   :-(\n", ioc->name);
15065 +                                   "not enough memory! :-(\n", ioc->name);
15066                                 printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n",
15067 -                                       ioc->name, numfrags);
15068 +                                   ioc->name, numfrags);
15069                                 goto free_and_fail;
15070                         }
15071                         continue;
15072 @@ -1029,7 +1175,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
15073                         dma_addr_t dma_addr;
15074  
15075                         bytes_allocd += this_alloc;
15076 -                       sgl->FlagsLength = (0x10000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|this_alloc);
15077 +                       sgl->FlagsLength = (0x10000000|sgdir|this_alloc);
15078 +                       if (ioc->sg_addr_size == sizeof(u64))
15079 +                               sgl->FlagsLength |= MPT_SGE_FLAGS_64_BIT_ADDRESSING;
15080                         dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir);
15081                         sgl->Address = dma_addr;
15082  
15083 @@ -1044,8 +1192,8 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
15084  
15085                 /* Need to chain? */
15086                 if (fragcnt == sg_spill) {
15087 -                       printk(MYIOC_s_WARN_FMT
15088 -                           "-SG: No can do - " "Chain required!   :-(\n", ioc->name);
15089 +                       printk(MYIOC_s_WARN_FMT "-SG: No can do - "
15090 +                           "Chain required! :-(\n", ioc->name);
15091                         printk(MYIOC_s_WARN_FMT "(freeing %d frags)\n", ioc->name, numfrags);
15092                         goto free_and_fail;
15093                 }
15094 @@ -1054,9 +1202,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
15095                 if (numfrags*8 > MAX_SGL_BYTES){
15096                         /* GRRRRR... */
15097                         printk(MYIOC_s_WARN_FMT "-SG: No can do - "
15098 -                               "too many SG frags!   :-(\n", ioc->name);
15099 +                           "too many SG frags! :-(\n", ioc->name);
15100                         printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n",
15101 -                               ioc->name, numfrags);
15102 +                           ioc->name, numfrags);
15103                         goto free_and_fail;
15104                 }
15105         }
15106 @@ -1213,6 +1361,7 @@ mptctl_getiocinfo (unsigned long arg, un
15107  
15108         if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
15109             (ioc == NULL)) {
15110 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15111                 printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
15112                                 __FILE__, __LINE__, iocnum);
15113                 kfree(karg);
15114 @@ -1222,8 +1371,8 @@ mptctl_getiocinfo (unsigned long arg, un
15115         /* Verify the data transfer size is correct. */
15116         if (karg->hdr.maxDataSize != data_size) {
15117                 printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
15118 -                       "Structure size mismatch. Command not completed.\n",
15119 -                       ioc->name, __FILE__, __LINE__);
15120 +                   "Structure size mismatch. Command not completed.\n",
15121 +                   ioc->name, __FILE__, __LINE__);
15122                 kfree(karg);
15123                 return -EFAULT;
15124         }
15125 @@ -1275,6 +1424,8 @@ mptctl_getiocinfo (unsigned long arg, un
15126         if (ioc->sh) {
15127                 shost_for_each_device(sdev, ioc->sh) {
15128                         vdevice = sdev->hostdata;
15129 +                       if (vdevice == NULL || vdevice->vtarget == NULL)
15130 +                               continue;
15131                         if (vdevice->vtarget->tflags &
15132                             MPT_TARGET_FLAGS_RAID_COMPONENT)
15133                                 continue;
15134 @@ -1346,6 +1497,7 @@ mptctl_gettargetinfo (unsigned long arg)
15135  
15136         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15137             (ioc == NULL)) {
15138 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15139                 printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
15140                                 __FILE__, __LINE__, iocnum);
15141                 return -ENODEV;
15142 @@ -1362,8 +1514,8 @@ mptctl_gettargetinfo (unsigned long arg)
15143         port = karg.hdr.port;
15144  
15145         if (maxWordsLeft <= 0) {
15146 -               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n",
15147 -                       ioc->name, __FILE__, __LINE__);
15148 +               printk(MYIOC_s_ERR_FMT "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
15149 +                   ioc->name, __FILE__, __LINE__);
15150                 return -ENOMEM;
15151         }
15152  
15153 @@ -1383,8 +1535,8 @@ mptctl_gettargetinfo (unsigned long arg)
15154          */
15155         pmem = kzalloc(numBytes, GFP_KERNEL);
15156         if (!pmem) {
15157 -               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n",
15158 -                       ioc->name, __FILE__, __LINE__);
15159 +               printk(MYIOC_s_ERR_FMT "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
15160 +                   ioc->name, __FILE__, __LINE__);
15161                 return -ENOMEM;
15162         }
15163         pdata =  (int *) pmem;
15164 @@ -1396,6 +1548,8 @@ mptctl_gettargetinfo (unsigned long arg)
15165                         if (!maxWordsLeft)
15166                                 continue;
15167                         vdevice = sdev->hostdata;
15168 +                       if (vdevice == NULL || vdevice->vtarget == NULL)
15169 +                               continue;
15170                         if (vdevice->vtarget->tflags &
15171                             MPT_TARGET_FLAGS_RAID_COMPONENT)
15172                                 continue;
15173 @@ -1460,6 +1614,7 @@ mptctl_readtest (unsigned long arg)
15174  
15175         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15176             (ioc == NULL)) {
15177 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15178                 printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n",
15179                                 __FILE__, __LINE__, iocnum);
15180                 return -ENODEV;
15181 @@ -1521,6 +1676,7 @@ mptctl_eventquery (unsigned long arg)
15182  
15183         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15184             (ioc == NULL)) {
15185 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15186                 printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
15187                                 __FILE__, __LINE__, iocnum);
15188                 return -ENODEV;
15189 @@ -1560,6 +1716,7 @@ mptctl_eventenable (unsigned long arg)
15190  
15191         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15192             (ioc == NULL)) {
15193 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15194                 printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
15195                                 __FILE__, __LINE__, iocnum);
15196                 return -ENODEV;
15197 @@ -1573,8 +1730,7 @@ mptctl_eventenable (unsigned long arg)
15198                 int sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
15199                 ioc->events = kzalloc(sz, GFP_KERNEL);
15200                 if (!ioc->events) {
15201 -                       printk(MYIOC_s_ERR_FMT
15202 -                           ": ERROR - Insufficient memory to add adapter!\n",
15203 +                       printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
15204                             ioc->name);
15205                         return -ENOMEM;
15206                 }
15207 @@ -1609,13 +1765,14 @@ mptctl_eventreport (unsigned long arg)
15208  
15209         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15210             (ioc == NULL)) {
15211 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15212                 printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
15213                                 __FILE__, __LINE__, iocnum);
15214                 return -ENODEV;
15215         }
15216 +
15217         dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n",
15218             ioc->name));
15219 -
15220         numBytes = karg.hdr.maxDataSize - sizeof(mpt_ioctl_header);
15221         maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS);
15222  
15223 @@ -1663,6 +1820,7 @@ mptctl_replace_fw (unsigned long arg)
15224  
15225         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15226             (ioc == NULL)) {
15227 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15228                 printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
15229                                 __FILE__, __LINE__, iocnum);
15230                 return -ENODEV;
15231 @@ -1694,8 +1852,8 @@ mptctl_replace_fw (unsigned long arg)
15232          */
15233         if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
15234                 printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_replace_fw - "
15235 -                               "Unable to read in mpt_ioctl_replace_fw image "
15236 -                               "@ %p\n", ioc->name, __FILE__, __LINE__, uarg);
15237 +                       "Unable to read in mpt_ioctl_replace_fw image "
15238 +                       "@ %p\n", ioc->name, __FILE__, __LINE__, uarg);
15239                 mpt_free_fw_memory(ioc);
15240                 return -EFAULT;
15241         }
15242 @@ -1712,7 +1870,7 @@ mptctl_replace_fw (unsigned long arg)
15243   *
15244   * Outputs:    None.
15245   * Return:     0 if successful
15246 - *             -EBUSY  if previous command timeout and IOC reset is not complete.
15247 + *             -EBUSY  if previous command timout and IOC reset is not complete.
15248   *             -EFAULT if data unavailable
15249   *             -ENODEV if no such device/adapter
15250   *             -ETIME  if timer expires
15251 @@ -1737,6 +1895,7 @@ mptctl_mpt_command (unsigned long arg)
15252  
15253         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15254             (ioc == NULL)) {
15255 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15256                 printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
15257                                 __FILE__, __LINE__, iocnum);
15258                 return -ENODEV;
15259 @@ -1752,7 +1911,7 @@ mptctl_mpt_command (unsigned long arg)
15260   *
15261   * Outputs:    None.
15262   * Return:     0 if successful
15263 - *             -EBUSY  if previous command timeout and IOC reset is not complete.
15264 + *             -EBUSY  if previous command timout and IOC reset is not complete.
15265   *             -EFAULT if data unavailable
15266   *             -ENODEV if no such device/adapter
15267   *             -ETIME  if timer expires
15268 @@ -1775,8 +1934,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15269         int             sz, rc = 0;
15270         int             msgContext;
15271         u16             req_idx;
15272 -       ulong           timeout;
15273 +       unsigned long   timeout;
15274 +       unsigned long   timeleft;
15275         struct scsi_device *sdev;
15276 +       unsigned long    flags;
15277 +       u8               function;
15278  
15279         /* bufIn and bufOut are used for user to kernel space transfers
15280          */
15281 @@ -1785,28 +1947,28 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15282  
15283         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15284             (ioc == NULL)) {
15285 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15286                 printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
15287                                 __FILE__, __LINE__, iocnum);
15288                 return -ENODEV;
15289         }
15290 -       if (!ioc->ioctl) {
15291 -               printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - "
15292 -                       "No memory available during driver init.\n",
15293 -                               __FILE__, __LINE__);
15294 -               return -ENOMEM;
15295 -       } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
15296 +
15297 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
15298 +       if (ioc->ioc_reset_in_progress) {
15299 +               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
15300                 printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - "
15301 -                       "Busy with IOC Reset \n", __FILE__, __LINE__);
15302 +                       "Busy with diagnostic reset\n", __FILE__, __LINE__);
15303                 return -EBUSY;
15304         }
15305 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
15306  
15307         /* Verify that the final request frame will not be too large.
15308          */
15309         sz = karg.dataSgeOffset * 4;
15310         if (karg.dataInSize > 0)
15311 -               sz += sizeof(dma_addr_t) + sizeof(u32);
15312 +               sz += ioc->SGE_size;
15313         if (karg.dataOutSize > 0)
15314 -               sz += sizeof(dma_addr_t) + sizeof(u32);
15315 +               sz += ioc->SGE_size;
15316  
15317         if (sz > ioc->req_sz) {
15318                 printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
15319 @@ -1832,18 +1994,19 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15320                 printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
15321                         "Unable to read MF from mpt_ioctl_command struct @ %p\n",
15322                         ioc->name, __FILE__, __LINE__, mfPtr);
15323 +               function = -1;
15324                 rc = -EFAULT;
15325                 goto done_free_mem;
15326         }
15327         hdr->MsgContext = cpu_to_le32(msgContext);
15328 -
15329 +       function = hdr->Function;
15330  
15331         /* Verify that this request is allowed.
15332          */
15333         dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sending mpi function (0x%02X), req=%p\n",
15334 -           ioc->name, hdr->Function, mf));
15335 +           ioc->name, function, mf));
15336  
15337 -       switch (hdr->Function) {
15338 +       switch (function) {
15339         case MPI_FUNCTION_IOC_FACTS:
15340         case MPI_FUNCTION_PORT_FACTS:
15341                 karg.dataOutSize  = karg.dataInSize = 0;
15342 @@ -1898,7 +2061,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15343                         }
15344  
15345                         pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
15346 -                       pScsiReq->MsgFlags |= mpt_msg_flags();
15347 +                       pScsiReq->MsgFlags |= mpt_msg_flags(ioc);
15348  
15349  
15350                         /* verify that app has not requested
15351 @@ -1920,6 +2083,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15352                                 struct scsi_target *starget = scsi_target(sdev);
15353                                 VirtTarget *vtarget = starget->hostdata;
15354  
15355 +                               if (vtarget == NULL)
15356 +                                       continue;
15357                                 if ((pScsiReq->TargetID == vtarget->id) &&
15358                                     (pScsiReq->Bus == vtarget->channel) &&
15359                                     (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
15360 @@ -1940,9 +2105,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15361                         pScsiReq->Control = cpu_to_le32(scsidir | qtag);
15362                         pScsiReq->DataLength = cpu_to_le32(dataSize);
15363  
15364 -                       ioc->ioctl->reset = MPTCTL_RESET_OK;
15365 -                       ioc->ioctl->id = pScsiReq->TargetID;
15366 -
15367                 } else {
15368                         printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
15369                                 "SCSI driver is not loaded. \n",
15370 @@ -1955,7 +2117,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15371         case MPI_FUNCTION_SMP_PASSTHROUGH:
15372                 /* Check mf->PassthruFlags to determine if
15373                  * transfer is ImmediateMode or not.
15374 -                * Immediate mode returns data in the ReplyFrame.
15375 +                * Immediate mode returns data in the reply.
15376                  * Else, we are sending request and response data
15377                  * in two SGLs at the end of the mf.
15378                  */
15379 @@ -1984,7 +2146,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15380                         int dataSize;
15381  
15382                         pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
15383 -                       pScsiReq->MsgFlags |= mpt_msg_flags();
15384 +                       pScsiReq->MsgFlags |= mpt_msg_flags(ioc);
15385  
15386  
15387                         /* verify that app has not requested
15388 @@ -2019,8 +2181,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15389                         pScsiReq->Control = cpu_to_le32(scsidir | qtag);
15390                         pScsiReq->DataLength = cpu_to_le32(dataSize);
15391  
15392 -                       ioc->ioctl->reset = MPTCTL_RESET_OK;
15393 -                       ioc->ioctl->id = pScsiReq->TargetID;
15394                 } else {
15395                         printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
15396                                 "SCSI driver is not loaded. \n",
15397 @@ -2031,20 +2191,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15398                 break;
15399  
15400         case MPI_FUNCTION_SCSI_TASK_MGMT:
15401 -               {
15402 -                       MPT_SCSI_HOST *hd = NULL;
15403 -                       if ((ioc->sh == NULL) || ((hd = shost_priv(ioc->sh)) == NULL)) {
15404 -                               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
15405 -                                       "SCSI driver not loaded or SCSI host not found. \n",
15406 -                                       ioc->name, __FILE__, __LINE__);
15407 -                               rc = -EFAULT;
15408 -                               goto done_free_mem;
15409 -                       } else if (mptctl_set_tm_flags(hd) != 0) {
15410 -                               rc = -EPERM;
15411 -                               goto done_free_mem;
15412 -                       }
15413 -               }
15414 +       {
15415 +               SCSITaskMgmt_t  *pScsiTm;
15416 +               pScsiTm = (SCSITaskMgmt_t *)mf;
15417 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tTaskType=0x%x MsgFlags=0x%x "
15418 +                   "TaskMsgContext=0x%x id=%d channel=%d\n", ioc->name, pScsiTm->TaskType,
15419 +                   le32_to_cpu(pScsiTm->TaskMsgContext), pScsiTm->MsgFlags,
15420 +                   pScsiTm->TargetID, pScsiTm->Bus));
15421                 break;
15422 +       }
15423  
15424         case MPI_FUNCTION_IOC_INIT:
15425                 {
15426 @@ -2054,7 +2209,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15427                         /* Verify that all entries in the IOC INIT match
15428                          * existing setup (and in LE format).
15429                          */
15430 -                       if (sizeof(dma_addr_t) == sizeof(u64)) {
15431 +                       if (ioc->sg_addr_size == sizeof(u64)) {
15432                                 high_addr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
15433                                 sense_high= cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
15434                         } else {
15435 @@ -2062,6 +2217,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15436                                 sense_high= 0;
15437                         }
15438  
15439 +                       if (!pInit->MaxDevices && !pInit->MaxBuses) {
15440 +                               pInit->MaxDevices = ioc->facts.MaxDevices;
15441 +                               pInit->MaxBuses = ioc->facts.MaxBuses;
15442 +                       }
15443 +
15444                         if ((pInit->Flags != 0) || (pInit->MaxDevices != ioc->facts.MaxDevices) ||
15445                                 (pInit->MaxBuses != ioc->facts.MaxBuses) ||
15446                                 (pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||
15447 @@ -2102,7 +2262,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15448  
15449                 printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
15450                         "Illegal request (function 0x%x) \n",
15451 -                       ioc->name, __FILE__, __LINE__, hdr->Function);
15452 +                       ioc->name, __FILE__, __LINE__, function);
15453                 rc = -EFAULT;
15454                 goto done_free_mem;
15455         }
15456 @@ -2128,8 +2288,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15457                         if (karg.dataInSize > 0) {
15458                                 flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
15459                                                 MPI_SGE_FLAGS_END_OF_BUFFER |
15460 -                                               MPI_SGE_FLAGS_DIRECTION |
15461 -                                               mpt_addr_size() )
15462 +                                               MPI_SGE_FLAGS_DIRECTION )
15463                                                 << MPI_SGE_FLAGS_SHIFT;
15464                         } else {
15465                                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
15466 @@ -2146,8 +2305,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15467                                 /* Set up this SGE.
15468                                  * Copy to MF and to sglbuf
15469                                  */
15470 -                               mpt_add_sge(psge, flagsLength, dma_addr_out);
15471 -                               psge += (sizeof(u32) + sizeof(dma_addr_t));
15472 +                               ioc->add_sge(psge, flagsLength, dma_addr_out);
15473 +                               psge += ioc->SGE_size;
15474  
15475                                 /* Copy user data to kernel space.
15476                                  */
15477 @@ -2180,17 +2339,24 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15478                                 /* Set up this SGE
15479                                  * Copy to MF and to sglbuf
15480                                  */
15481 -                               mpt_add_sge(psge, flagsLength, dma_addr_in);
15482 +                               ioc->add_sge(psge, flagsLength, dma_addr_in);
15483                         }
15484                 }
15485         } else  {
15486                 /* Add a NULL SGE
15487                  */
15488 -               mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
15489 +               ioc->add_sge(psge, flagsLength, (dma_addr_t) -1);
15490         }
15491  
15492 -       ioc->ioctl->wait_done = 0;
15493 -       if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
15494 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, hdr->MsgContext);
15495 +       INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
15496 +       if (function == MPI_FUNCTION_SCSI_TASK_MGMT) {
15497 +
15498 +               mutex_lock(&ioc->taskmgmt_cmds.mutex);
15499 +               if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
15500 +                       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
15501 +                       goto done_free_mem;
15502 +               }
15503  
15504                 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
15505  
15506 @@ -2198,53 +2364,57 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15507                     (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
15508                         mpt_put_msg_frame_hi_pri(mptctl_id, ioc, mf);
15509                 else {
15510 -                       rc =mpt_send_handshake_request(mptctl_id, ioc,
15511 -                               sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
15512 +                       rc = mpt_send_handshake_request(mptctl_id, ioc,
15513 +                           sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
15514                         if (rc != 0) {
15515                                 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
15516 -                                   "_send_handshake FAILED! (ioc %p, mf %p)\n",
15517 +                                   "send_handshake FAILED! (ioc %p, mf %p)\n",
15518                                     ioc->name, ioc, mf));
15519 -                               mptctl_free_tm_flags(ioc);
15520 +                               mpt_clear_taskmgmt_in_progress_flag(ioc);
15521                                 rc = -ENODATA;
15522 +                               mutex_unlock(&ioc->taskmgmt_cmds.mutex);
15523                                 goto done_free_mem;
15524                         }
15525                 }
15526 -
15527         } else
15528                 mpt_put_msg_frame(mptctl_id, ioc, mf);
15529  
15530         /* Now wait for the command to complete */
15531         timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
15532 -       timeout = wait_event_timeout(mptctl_wait,
15533 -            ioc->ioctl->wait_done == 1,
15534 -            HZ*timeout);
15535 -
15536 -       if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
15537 -       /* Now we need to reset the board */
15538 -
15539 -               if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT)
15540 -                       mptctl_free_tm_flags(ioc);
15541 -
15542 -               mptctl_timeout_expired(ioc->ioctl);
15543 -               rc = -ENODATA;
15544 +       timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done, HZ*timeout);
15545 +       if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
15546 +               rc = -ETIME;
15547 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: TIMED OUT!\n",
15548 +                   ioc->name, __FUNCTION__));
15549 +               if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
15550 +                       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
15551 +               if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
15552 +                       goto done_free_mem;
15553 +               }
15554 +               if (!timeleft) {
15555 +                       mptctl_timeout_expired(ioc, mf);
15556 +                       mf = NULL;
15557 +               }
15558                 goto done_free_mem;
15559         }
15560  
15561 +       if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
15562 +               mutex_unlock(&ioc->taskmgmt_cmds.mutex);
15563 +
15564         mf = NULL;
15565  
15566         /* If a valid reply frame, copy to the user.
15567          * Offset 2: reply length in U32's
15568          */
15569 -       if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
15570 +       if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
15571                 if (karg.maxReplyBytes < ioc->reply_sz) {
15572 -                        sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);
15573 +                        sz = min(karg.maxReplyBytes, 4*ioc->ioctl_cmds.reply[2]);
15574                 } else {
15575 -                        sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);
15576 +                        sz = min(ioc->reply_sz, 4*ioc->ioctl_cmds.reply[2]);
15577                 }
15578 -
15579                 if (sz > 0) {
15580                         if (copy_to_user(karg.replyFrameBufPtr,
15581 -                                &ioc->ioctl->ReplyFrame, sz)){
15582 +                                ioc->ioctl_cmds.reply, sz)){
15583                                  printk(MYIOC_s_ERR_FMT
15584                                      "%s@%d::mptctl_do_mpt_command - "
15585                                  "Unable to write out reply frame %p\n",
15586 @@ -2257,10 +2427,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15587  
15588         /* If valid sense data, copy to user.
15589          */
15590 -       if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
15591 +       if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_SENSE_VALID) {
15592                 sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
15593                 if (sz > 0) {
15594 -                       if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
15595 +                       if (copy_to_user(karg.senseDataPtr, ioc->ioctl_cmds.sense, sz)) {
15596                                 printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
15597                                 "Unable to write sense data to user %p\n",
15598                                 ioc->name, __FILE__, __LINE__,
15599 @@ -2274,9 +2444,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15600         /* If the overall status is _GOOD and data in, copy data
15601          * to user.
15602          */
15603 -       if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
15604 -                               (karg.dataInSize > 0) && (bufIn.kptr)) {
15605 -
15606 +       if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD) &&
15607 +               (karg.dataInSize > 0) && (bufIn.kptr)) {
15608                 if (copy_to_user(karg.dataInBufPtr,
15609                                  bufIn.kptr, karg.dataInSize)) {
15610                         printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
15611 @@ -2289,9 +2458,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_
15612  
15613  done_free_mem:
15614  
15615 -       ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD |
15616 -               MPT_IOCTL_STATUS_SENSE_VALID |
15617 -               MPT_IOCTL_STATUS_RF_VALID );
15618 +       CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
15619 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
15620  
15621         /* Free the allocated memory.
15622          */
15623 @@ -2320,7 +2488,7 @@ done_free_mem:
15624   * Outputs:    None.
15625   * Return:     0 if successful
15626   *             -EFAULT if data unavailable
15627 - *             -EBUSY  if previous command timeout and IOC reset is not complete.
15628 + *             -EBUSY  if previous command timout and IOC reset is not complete.
15629   *             -ENODEV if no such device/adapter
15630   *             -ETIME  if timer expires
15631   *             -ENOMEM if memory allocation error
15632 @@ -2331,16 +2499,17 @@ mptctl_hp_hostinfo(unsigned long arg, un
15633         hp_host_info_t  __user *uarg = (void __user *) arg;
15634         MPT_ADAPTER             *ioc;
15635         struct pci_dev          *pdev;
15636 -       char                    *pbuf=NULL;
15637 +       char                    *pbuf=NULL;
15638         dma_addr_t              buf_dma;
15639         hp_host_info_t          karg;
15640 -       CONFIGPARMS             cfg;
15641 -       ConfigPageHeader_t      hdr;
15642         int                     iocnum;
15643 -       int                     rc, cim_rev;
15644 +       int                     cim_rev;
15645         ToolboxIstwiReadWriteRequest_t  *IstwiRWRequest;
15646         MPT_FRAME_HDR           *mf = NULL;
15647         MPIHeader_t             *mpi_hdr;
15648 +       unsigned long           timeleft;
15649 +       int                     retval;
15650 +       u32                     MsgContext;
15651  
15652         /* Reset long to int. Should affect IA64 and SPARC only
15653          */
15654 @@ -2360,13 +2529,14 @@ mptctl_hp_hostinfo(unsigned long arg, un
15655  
15656         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15657             (ioc == NULL)) {
15658 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15659                 printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
15660                                 __FILE__, __LINE__, iocnum);
15661                 return -ENODEV;
15662         }
15663 +
15664         dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n",
15665             ioc->name));
15666 -
15667         /* Fill in the data and return the structure to the calling
15668          * program
15669          */
15670 @@ -2406,42 +2576,9 @@ mptctl_hp_hostinfo(unsigned long arg, un
15671         karg.fw_version[10] = (ioc->facts.FWVersion.Struct.Dev % 10 ) + '0';
15672         karg.fw_version[11] = '\0';
15673  
15674 -       /* Issue a config request to get the device serial number
15675 -        */
15676 -       hdr.PageVersion = 0;
15677 -       hdr.PageLength = 0;
15678 -       hdr.PageNumber = 0;
15679 -       hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
15680 -       cfg.cfghdr.hdr = &hdr;
15681 -       cfg.physAddr = -1;
15682 -       cfg.pageAddr = 0;
15683 -       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
15684 -       cfg.dir = 0;    /* read */
15685 -       cfg.timeout = 10;
15686 +       strncpy(karg.serial_number, ioc->board_tracer, 16);
15687  
15688 -       strncpy(karg.serial_number, " ", 24);
15689 -       if (mpt_config(ioc, &cfg) == 0) {
15690 -               if (cfg.cfghdr.hdr->PageLength > 0) {
15691 -                       /* Issue the second config page request */
15692 -                       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
15693 -
15694 -                       pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
15695 -                       if (pbuf) {
15696 -                               cfg.physAddr = buf_dma;
15697 -                               if (mpt_config(ioc, &cfg) == 0) {
15698 -                                       ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf;
15699 -                                       if (strlen(pdata->BoardTracerNumber) > 1) {
15700 -                                               strncpy(karg.serial_number,                                                                         pdata->BoardTracerNumber, 24);
15701 -                                               karg.serial_number[24-1]='\0';
15702 -                                       }
15703 -                               }
15704 -                               pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
15705 -                               pbuf = NULL;
15706 -                       }
15707 -               }
15708 -       }
15709 -       rc = mpt_GetIocState(ioc, 1);
15710 -       switch (rc) {
15711 +       switch (mpt_GetIocState(ioc, 1)) {
15712         case MPI_IOC_STATE_OPERATIONAL:
15713                 karg.ioc_status =  HP_STATUS_OK;
15714                 break;
15715 @@ -2468,12 +2605,12 @@ mptctl_hp_hostinfo(unsigned long arg, un
15716         karg.soft_resets = 0;
15717         karg.timeouts = 0;
15718         if (ioc->sh != NULL) {
15719 -               MPT_SCSI_HOST *hd =  shost_priv(ioc->sh);
15720 +               MPT_SCSI_HOST *hd =  (MPT_SCSI_HOST *)ioc->sh->hostdata;
15721  
15722                 if (hd && (cim_rev == 1)) {
15723 -                       karg.hard_resets = hd->hard_resets;
15724 -                       karg.soft_resets = hd->soft_resets;
15725 -                       karg.timeouts = hd->timeouts;
15726 +                       karg.hard_resets = ioc->hard_resets;
15727 +                       karg.soft_resets = ioc->soft_resets;
15728 +                       karg.timeouts = ioc->timeouts;
15729                 }
15730         }
15731  
15732 @@ -2482,16 +2619,18 @@ mptctl_hp_hostinfo(unsigned long arg, un
15733          */
15734         if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
15735                 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
15736 -                   ioc->name,__func__));
15737 +                   ioc->name,__FUNCTION__));
15738 +               retval = -ENOMEM;
15739                 goto out;
15740         }
15741  
15742         IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf;
15743         mpi_hdr = (MPIHeader_t *) mf;
15744 +       MsgContext = mpi_hdr->MsgContext;
15745         memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t));
15746         IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX;
15747         IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
15748 -       IstwiRWRequest->MsgContext = mpi_hdr->MsgContext;
15749 +       IstwiRWRequest->MsgContext = MsgContext;
15750         IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ;
15751         IstwiRWRequest->NumAddressBytes = 0x01;
15752         IstwiRWRequest->DataLength = cpu_to_le16(0x04);
15753 @@ -2501,28 +2640,30 @@ mptctl_hp_hostinfo(unsigned long arg, un
15754                 IstwiRWRequest->DeviceAddr = 0xB0;
15755  
15756         pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
15757 -       if (!pbuf)
15758 +       if (!pbuf) {
15759 +               retval = -ENOMEM;
15760                 goto out;
15761 -       mpt_add_sge((char *)&IstwiRWRequest->SGL,
15762 -           (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
15763 +       }
15764 +       ioc->add_sge((char *)&IstwiRWRequest->SGL, (MPT_SGE_FLAGS_SSIMPLE_READ|4),buf_dma);
15765  
15766 -       ioc->ioctl->wait_done = 0;
15767 +       retval = 0;
15768 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, IstwiRWRequest->MsgContext);
15769 +       INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
15770         mpt_put_msg_frame(mptctl_id, ioc, mf);
15771 -
15772 -       rc = wait_event_timeout(mptctl_wait,
15773 -            ioc->ioctl->wait_done == 1,
15774 -            HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
15775 -
15776 -       if(rc <=0 && (ioc->ioctl->wait_done != 1 )) {
15777 -               /*
15778 -                * Now we need to reset the board
15779 -                */
15780 -               mpt_free_msg_frame(ioc, mf);
15781 -               mptctl_timeout_expired(ioc->ioctl);
15782 +       timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done, HZ*MPT_IOCTL_DEFAULT_TIMEOUT);
15783 +       if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
15784 +               retval = -ETIME;
15785 +               printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name, __FUNCTION__);
15786 +               if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
15787 +                       mpt_free_msg_frame(ioc, mf);
15788 +                       goto out;
15789 +               }
15790 +               if (!timeleft)
15791 +                       mptctl_timeout_expired(ioc, mf);
15792                 goto out;
15793         }
15794  
15795 -       /*
15796 +       /*
15797          *ISTWI Data Definition
15798          * pbuf[0] = FW_VERSION = 0x4
15799          * pbuf[1] = Bay Count = 6 or 4 or 2, depending on
15800 @@ -2531,10 +2672,13 @@ mptctl_hp_hostinfo(unsigned long arg, un
15801          *   bays have drives in them
15802          * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3)
15803          */
15804 -       if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID)
15805 +       if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)
15806                 karg.rsvd = *(u32 *)pbuf;
15807  
15808   out:
15809 +       CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
15810 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
15811 +
15812         if (pbuf)
15813                 pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
15814  
15815 @@ -2547,7 +2691,7 @@ mptctl_hp_hostinfo(unsigned long arg, un
15816                 return -EFAULT;
15817         }
15818  
15819 -       return 0;
15820 +       return retval;
15821  
15822  }
15823  
15824 @@ -2557,7 +2701,7 @@ mptctl_hp_hostinfo(unsigned long arg, un
15825   * Outputs:    None.
15826   * Return:     0 if successful
15827   *             -EFAULT if data unavailable
15828 - *             -EBUSY  if previous command timeout and IOC reset is not complete.
15829 + *             -EBUSY  if previous command timout and IOC reset is not complete.
15830   *             -ENODEV if no such device/adapter
15831   *             -ETIME  if timer expires
15832   *             -ENOMEM if memory allocation error
15833 @@ -2587,13 +2731,14 @@ mptctl_hp_targetinfo(unsigned long arg)
15834  
15835         if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
15836                 (ioc == NULL)) {
15837 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15838                 printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
15839                                 __FILE__, __LINE__, iocnum);
15840                 return -ENODEV;
15841         }
15842 -       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
15843 -           ioc->name));
15844  
15845 +       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_targetinfo called.\n",
15846 +           ioc->name));
15847         /*  There is nothing to do for FCP parts.
15848          */
15849         if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
15850 @@ -2685,7 +2830,7 @@ mptctl_hp_targetinfo(unsigned long arg)
15851                         pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg3_alloc, page_dma);
15852                 }
15853         }
15854 -       hd = shost_priv(ioc->sh);
15855 +       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
15856         if (hd != NULL)
15857                 karg.select_timeouts = hd->sel_timeout[karg.hdr.id];
15858  
15859 @@ -2703,7 +2848,7 @@ mptctl_hp_targetinfo(unsigned long arg)
15860  
15861  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
15862  
15863 -static const struct file_operations mptctl_fops = {
15864 +static struct file_operations mptctl_fops = {
15865         .owner =        THIS_MODULE,
15866         .llseek =       no_llseek,
15867         .release =      mptctl_release,
15868 @@ -2743,8 +2888,9 @@ compat_mptfwxfer_ioctl(struct file *filp
15869         iocnumX = kfw32.iocnum & 0xFF;
15870         if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
15871             (iocp == NULL)) {
15872 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15873                 printk(KERN_DEBUG MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
15874 -                       __LINE__, iocnumX);
15875 +                               __LINE__, iocnumX);
15876                 return -ENODEV;
15877         }
15878  
15879 @@ -2759,7 +2905,7 @@ compat_mptfwxfer_ioctl(struct file *filp
15880  
15881         ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
15882  
15883 -       mutex_unlock(&iocp->ioctl->ioctl_mutex);
15884 +       mutex_unlock(&iocp->ioctl_cmds.mutex);
15885  
15886         return ret;
15887  }
15888 @@ -2783,8 +2929,9 @@ compat_mpt_command(struct file *filp, un
15889         iocnumX = karg32.hdr.iocnum & 0xFF;
15890         if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
15891             (iocp == NULL)) {
15892 +               if (mpt_debug_level & MPT_DEBUG_IOCTL)
15893                 printk(KERN_DEBUG MYNAM "::compat_mpt_command @%d - ioc%d not found!\n",
15894 -                       __LINE__, iocnumX);
15895 +                               __LINE__, iocnumX);
15896                 return -ENODEV;
15897         }
15898  
15899 @@ -2813,7 +2960,7 @@ compat_mpt_command(struct file *filp, un
15900          */
15901         ret = mptctl_do_mpt_command (karg, &uarg->MF);
15902  
15903 -       mutex_unlock(&iocp->ioctl->ioctl_mutex);
15904 +       mutex_unlock(&iocp->ioctl_cmds.mutex);
15905  
15906         return ret;
15907  }
15908 @@ -2833,6 +2980,31 @@ static long compat_mpctl_ioctl(struct fi
15909         case MPTHARDRESET:
15910         case HP_GETHOSTINFO:
15911         case HP_GETTARGETINFO:
15912 +#if defined(CPQ_CIM)
15913 +       case CC_CSMI_SAS_GET_DRIVER_INFO:
15914 +       case CC_CSMI_SAS_GET_CNTLR_CONFIG:
15915 +       case CC_CSMI_SAS_GET_CNTLR_STATUS:
15916 +       case CC_CSMI_SAS_GET_SCSI_ADDRESS:
15917 +       case CC_CSMI_SAS_GET_DEVICE_ADDRESS:
15918 +       case CC_CSMI_SAS_GET_PHY_INFO:
15919 +       case CC_CSMI_SAS_GET_SATA_SIGNATURE:
15920 +       case CC_CSMI_SAS_GET_LINK_ERRORS:
15921 +       case CC_CSMI_SAS_SMP_PASSTHRU:
15922 +       case CC_CSMI_SAS_SSP_PASSTHRU:
15923 +       case CC_CSMI_SAS_FIRMWARE_DOWNLOAD:
15924 +       case CC_CSMI_SAS_GET_RAID_INFO:
15925 +       case CC_CSMI_SAS_GET_RAID_CONFIG:
15926 +       case CC_CSMI_SAS_GET_RAID_FEATURES:
15927 +       case CC_CSMI_SAS_SET_RAID_CONTROL:
15928 +       case CC_CSMI_SAS_GET_RAID_ELEMENT:
15929 +       case CC_CSMI_SAS_SET_RAID_OPERATION:
15930 +       case CC_CSMI_SAS_SET_PHY_INFO:
15931 +       case CC_CSMI_SAS_STP_PASSTHRU:
15932 +       case CC_CSMI_SAS_TASK_MANAGEMENT:
15933 +       case CC_CSMI_SAS_PHY_CONTROL:
15934 +       case CC_CSMI_SAS_GET_CONNECTOR_INFO:
15935 +       case CC_CSMI_SAS_GET_LOCATION:
15936 +#endif /* CPQ_CIM */
15937         case MPTTEST:
15938                 ret = __mptctl_ioctl(f, cmd, arg);
15939                 break;
15940 @@ -2865,21 +3037,11 @@ static long compat_mpctl_ioctl(struct fi
15941  static int
15942  mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
15943  {
15944 -       MPT_IOCTL *mem;
15945         MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
15946  
15947 -       /*
15948 -        * Allocate and inite a MPT_IOCTL structure
15949 -       */
15950 -       mem = kzalloc(sizeof(MPT_IOCTL), GFP_KERNEL);
15951 -       if (!mem) {
15952 -               mptctl_remove(pdev);
15953 -               return -ENOMEM;
15954 -       }
15955 +       mutex_init(&ioc->ioctl_cmds.mutex);
15956 +       init_completion(&ioc->ioctl_cmds.done);
15957  
15958 -       ioc->ioctl = mem;
15959 -       ioc->ioctl->ioc = ioc;
15960 -       mutex_init(&ioc->ioctl->ioctl_mutex);
15961         return 0;
15962  }
15963  
15964 @@ -2893,9 +3055,22 @@ mptctl_probe(struct pci_dev *pdev, const
15965  static void
15966  mptctl_remove(struct pci_dev *pdev)
15967  {
15968 +#if defined(DIAG_BUFFER_SUPPORT)
15969         MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
15970 +       int     i;
15971  
15972 -       kfree ( ioc->ioctl );
15973 +       /*
15974 +        * Cleanup diag buffer allocated memory
15975 +        */
15976 +       for (i = 0; i < MPI_DIAG_BUF_TYPE_COUNT; i++) {
15977 +               if (ioc->DiagBuffer[i] == NULL)
15978 +                       continue;
15979 +               pci_free_consistent(ioc->pcidev, ioc->DiagBuffer_sz[i],
15980 +                   ioc->DiagBuffer[i], ioc->DiagBuffer_dma[i]);
15981 +               ioc->DiagBuffer[i] = NULL;
15982 +               ioc->DiagBuffer_Status[i] = 0;
15983 +       }
15984 +#endif
15985  }
15986  
15987  static struct mpt_pci_driver mptctl_driver = {
15988 @@ -2935,6 +3110,7 @@ static int __init mptctl_init(void)
15989                 goto out_fail;
15990         }
15991  
15992 +       mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER);
15993         mpt_reset_register(mptctl_id, mptctl_ioc_reset);
15994         mpt_event_register(mptctl_id, mptctl_event_process);
15995  
15996 @@ -2956,15 +3132,23 @@ static void mptctl_exit(void)
15997  
15998         /* De-register reset handler from base module */
15999         mpt_reset_deregister(mptctl_id);
16000 +       mpt_reset_deregister(mptctl_taskmgmt_id);
16001  
16002         /* De-register callback handler from base module */
16003         mpt_deregister(mptctl_id);
16004  
16005          mpt_device_driver_deregister(MPTCTL_DRIVER);
16006 -
16007  }
16008  
16009  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16010  
16011 +#if defined(CPQ_CIM)
16012 +#include "csmi/csmisas.c"
16013 +#endif // CPQ_CIM
16014 +
16015 +#if defined(DIAG_BUFFER_SUPPORT)
16016 +#include "rejected_ioctls/diag_buffer.c"
16017 +#endif
16018 +
16019  module_init(mptctl_init);
16020  module_exit(mptctl_exit);
16021 --- a/drivers/message/fusion/mptctl.h
16022 +++ b/drivers/message/fusion/mptctl.h
16023 @@ -1,5 +1,5 @@
16024  /*
16025 - *  linux/drivers/message/fusion/mptioctl.h
16026 + *  linux/drivers/message/fusion/mptctl.h
16027   *      Fusion MPT misc device (ioctl) driver.
16028   *      For use with PCI chip/adapter(s):
16029   *          LSIFC9xx/LSI409xx Fibre Channel
16030 @@ -460,8 +460,5 @@ typedef struct _hp_target_info {
16031  
16032  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16033  
16034 -
16035 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16036 -
16037  #endif
16038  
16039 --- a/drivers/message/fusion/mptdebug.h
16040 +++ b/drivers/message/fusion/mptdebug.h
16041 @@ -17,6 +17,10 @@
16042   *
16043   * Example:  (programming for MPT_DEBUG_EVENTS on host 5)
16044   *
16045 + * global setting:
16046 + * echo 8 > /sys/module/mptbase/parameters/mpt_debug_level
16047 + *
16048 + * per host setting:
16049   * echo 8 > /sys/class/scsi_host/host5/debug_level
16050   *
16051   * --------------------------------------------------------
16052 @@ -55,9 +59,11 @@
16053  #define MPT_DEBUG_RESET                        0x00008000
16054  #define MPT_DEBUG_SCSI                 0x00010000
16055  #define MPT_DEBUG_IOCTL                        0x00020000
16056 +#define MPT_DEBUG_CSMISAS              0x00040000
16057  #define MPT_DEBUG_FC                   0x00080000
16058  #define MPT_DEBUG_SAS                  0x00100000
16059  #define MPT_DEBUG_SAS_WIDE             0x00200000
16060 +#define MPT_DEBUG_36GB_MEM             0x00400000
16061  
16062  /*
16063   * CONFIG_FUSION_LOGGING - enabled in Kconfig
16064 @@ -126,6 +132,9 @@
16065  #define dctlprintk(IOC, CMD)                   \
16066         MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL)
16067  
16068 +#define dcsmisasprintk(IOC, CMD)               \
16069 +       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CSMISAS)
16070 +
16071  #define dfcprintk(IOC, CMD)                    \
16072         MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FC)
16073  
16074 @@ -135,7 +144,8 @@
16075  #define dsaswideprintk(IOC, CMD)               \
16076         MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE)
16077  
16078 -
16079 +#define d36memprintk(IOC, CMD)         \
16080 +       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_36GB_MEM)
16081  
16082  /*
16083   * Verbose logging
16084 --- a/drivers/message/fusion/mptfc.c
16085 +++ b/drivers/message/fusion/mptfc.c
16086 @@ -43,6 +43,7 @@
16087      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16088  */
16089  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16090 +
16091  #include <linux/module.h>
16092  #include <linux/kernel.h>
16093  #include <linux/init.h>
16094 @@ -52,8 +53,10 @@
16095  #include <linux/delay.h>       /* for mdelay */
16096  #include <linux/interrupt.h>   /* needed for in_interrupt() proto */
16097  #include <linux/reboot.h>      /* notifier code */
16098 +#include <linux/sched.h>
16099  #include <linux/workqueue.h>
16100  #include <linux/sort.h>
16101 +#include <linux/pci.h>
16102  
16103  #include <scsi/scsi.h>
16104  #include <scsi/scsi_cmnd.h>
16105 @@ -84,6 +87,14 @@ MODULE_PARM_DESC(mptfc_dev_loss_tmo, " I
16106                                      " return following a device loss event."
16107                                      "  Default=60.");
16108  
16109 +static int mpt_sdev_queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
16110 +static int mptfc_set_sdev_queue_depth(const char *val, struct kernel_param *kp);
16111 +module_param_call(mpt_sdev_queue_depth, mptfc_set_sdev_queue_depth,
16112 +    param_get_int,  &mpt_sdev_queue_depth, 0600);
16113 +MODULE_PARM_DESC(mpt_sdev_queue_depth,
16114 +    " Max Device Queue Depth (default="
16115 +    __MODULE_STRING(MPT_SCSI_CMD_PER_DEV_HIGH) ")");
16116 +
16117  /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
16118  #define MPTFC_MAX_LUN (16895)
16119  static int max_lun = MPTFC_MAX_LUN;
16120 @@ -183,6 +194,34 @@ static struct fc_function_template mptfc
16121         .show_host_symbolic_name = 1,
16122  };
16123  
16124 +/**
16125 + *     mptfc_set_sdev_queue_depth - global setting of the mpt_sdev_queue_depth
16126 + *     found via /sys/module/mptfc/parameters/mpt_sdev_queue_depth
16127 + *     @val:
16128 + *     @kp:
16129 + *
16130 + *     Returns
16131 + **/
16132 +static int
16133 +mptfc_set_sdev_queue_depth(const char *val, struct kernel_param *kp)
16134 +{
16135 +       int ret = param_set_int(val, kp);
16136 +       MPT_ADAPTER *ioc;
16137 +       struct scsi_device      *sdev;
16138 +
16139 +       if (ret)
16140 +               return ret;
16141 +
16142 +       list_for_each_entry(ioc, &ioc_list, list) {
16143 +               if (ioc->bus_type != FC)
16144 +                       continue;
16145 +               shost_for_each_device(sdev, ioc->sh)
16146 +                       mptscsih_change_queue_depth(sdev, mpt_sdev_queue_depth);
16147 +               ioc->sdev_queue_depth = mpt_sdev_queue_depth;
16148 +       }
16149 +       return 0;
16150 +}
16151 +
16152  static int
16153  mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
16154                           int (*func)(struct scsi_cmnd *SCpnt),
16155 @@ -194,7 +233,7 @@ mptfc_block_error_handler(struct scsi_cm
16156         struct fc_rport         *rport = starget_to_rport(scsi_target(sdev));
16157         unsigned long           flags;
16158         int                     ready;
16159 -       MPT_ADAPTER             *ioc;
16160 +       MPT_ADAPTER             *ioc;
16161  
16162         hd = shost_priv(SCpnt->device->host);
16163         ioc = hd->ioc;
16164 @@ -231,28 +270,28 @@ static int
16165  mptfc_abort(struct scsi_cmnd *SCpnt)
16166  {
16167         return
16168 -           mptfc_block_error_handler(SCpnt, mptscsih_abort, __func__);
16169 +           mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__);
16170  }
16171  
16172  static int
16173  mptfc_dev_reset(struct scsi_cmnd *SCpnt)
16174  {
16175         return
16176 -           mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __func__);
16177 +           mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__);
16178  }
16179  
16180  static int
16181  mptfc_bus_reset(struct scsi_cmnd *SCpnt)
16182  {
16183         return
16184 -           mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __func__);
16185 +           mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__);
16186  }
16187  
16188  static int
16189  mptfc_host_reset(struct scsi_cmnd *SCpnt)
16190  {
16191         return
16192 -           mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __func__);
16193 +           mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__);
16194  }
16195  
16196  static void
16197 @@ -476,6 +515,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int
16198                                 if (vtarget) {
16199                                         vtarget->id = pg0->CurrentTargetID;
16200                                         vtarget->channel = pg0->CurrentBus;
16201 +                                       vtarget->deleted = 0;
16202                                 }
16203                         }
16204                         *((struct mptfc_rport_info **)rport->dd_data) = ri;
16205 @@ -513,6 +553,7 @@ mptfc_target_destroy(struct scsi_target 
16206         struct fc_rport         *rport;
16207         struct mptfc_rport_info *ri;
16208  
16209 +       printk("%s - starget=%p\n", __FUNCTION__, starget);
16210         rport = starget_to_rport(starget);
16211         if (rport) {
16212                 ri = *((struct mptfc_rport_info **)rport->dd_data);
16213 @@ -560,6 +601,7 @@ mptfc_target_alloc(struct scsi_target *s
16214  
16215         return rc;
16216  }
16217 +
16218  /*
16219   *     mptfc_dump_lun_info
16220   *     @ioc
16221 @@ -589,7 +631,6 @@ mptfc_dump_lun_info(MPT_ADAPTER *ioc, st
16222                 (unsigned long long)nn));
16223  }
16224  
16225 -
16226  /*
16227   *     OS entry point to allow host driver to alloc memory
16228   *     for each scsi device. Called once per device the bus scan.
16229 @@ -604,7 +645,7 @@ mptfc_slave_alloc(struct scsi_device *sd
16230         VirtDevice              *vdevice;
16231         struct scsi_target      *starget;
16232         struct fc_rport         *rport;
16233 -       MPT_ADAPTER             *ioc;
16234 +       MPT_ADAPTER             *ioc;
16235  
16236         starget = scsi_target(sdev);
16237         rport = starget_to_rport(starget);
16238 @@ -614,11 +655,10 @@ mptfc_slave_alloc(struct scsi_device *sd
16239  
16240         hd = shost_priv(sdev->host);
16241         ioc = hd->ioc;
16242 -
16243         vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
16244         if (!vdevice) {
16245                 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
16246 -                               ioc->name, sizeof(VirtDevice));
16247 +                   ioc->name, sizeof(VirtDevice));
16248                 return -ENOMEM;
16249         }
16250  
16251 @@ -635,10 +675,7 @@ mptfc_slave_alloc(struct scsi_device *sd
16252         vdevice->lun = sdev->lun;
16253  
16254         vtarget->num_luns++;
16255 -
16256 -
16257         mptfc_dump_lun_info(ioc, rport, sdev, vtarget);
16258 -
16259         return 0;
16260  }
16261  
16262 @@ -944,11 +981,12 @@ start_over:
16263         return rc;
16264  }
16265  
16266 -static void
16267 +static int
16268  mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
16269  {
16270         int             ii;
16271         FCPortPage1_t   *pp1;
16272 +       int             rc;
16273  
16274         #define MPTFC_FW_DEVICE_TIMEOUT (1)
16275         #define MPTFC_FW_IO_PEND_TIMEOUT (1)
16276 @@ -956,8 +994,8 @@ mptfc_SetFcPortPage1_defaults(MPT_ADAPTE
16277         #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
16278  
16279         for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
16280 -               if (mptfc_GetFcPortPage1(ioc, ii) != 0)
16281 -                       continue;
16282 +               if ((rc = mptfc_GetFcPortPage1(ioc, ii)) < 0)
16283 +                       return rc;
16284                 pp1 = ioc->fc_data.fc_port_page1[ii].data;
16285                 if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
16286                  && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
16287 @@ -968,8 +1006,10 @@ mptfc_SetFcPortPage1_defaults(MPT_ADAPTE
16288                 pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
16289                 pp1->Flags &= ~OFF_FLAGS;
16290                 pp1->Flags |= ON_FLAGS;
16291 -               mptfc_WriteFcPortPage1(ioc, ii);
16292 +               if ((rc = mptfc_WriteFcPortPage1(ioc, ii)) < 0)
16293 +                       return rc;
16294         }
16295 +       return 0;
16296  }
16297  
16298  
16299 @@ -1082,10 +1122,13 @@ mptfc_link_status_change(struct work_str
16300  static void
16301  mptfc_setup_reset(struct work_struct *work)
16302  {
16303 -       MPT_ADAPTER             *ioc =
16304 +       MPT_ADAPTER             *ioc =
16305                 container_of(work, MPT_ADAPTER, fc_setup_reset_work);
16306         u64                     pn;
16307         struct mptfc_rport_info *ri;
16308 +       struct scsi_target      *starget;
16309 +       VirtTarget              *vtarget;
16310 +
16311  
16312         /* reset about to happen, delete (block) all rports */
16313         list_for_each_entry(ri, &ioc->fc_rports, list) {
16314 @@ -1093,6 +1136,12 @@ mptfc_setup_reset(struct work_struct *wo
16315                         ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
16316                         fc_remote_port_delete(ri->rport);       /* won't sleep */
16317                         ri->rport = NULL;
16318 +                       starget = ri->starget;
16319 +                       if (starget) {
16320 +                               vtarget = starget->hostdata;
16321 +                               if (vtarget)
16322 +                                       vtarget->deleted = 1;
16323 +                       }
16324  
16325                         pn = (u64)ri->pg0.WWPN.High << 32 |
16326                              (u64)ri->pg0.WWPN.Low;
16327 @@ -1111,8 +1160,22 @@ mptfc_rescan_devices(struct work_struct 
16328         MPT_ADAPTER             *ioc =
16329                 container_of(work, MPT_ADAPTER, fc_rescan_work);
16330         int                     ii;
16331 +       int                     rc;
16332         u64                     pn;
16333         struct mptfc_rport_info *ri;
16334 +       struct scsi_target      *starget;
16335 +       VirtTarget              *vtarget;
16336 +
16337 +       /*
16338 +        * if cannot set defaults, something's really wrong, bail out
16339 +        */
16340 +
16341 +       if ((rc = mptfc_SetFcPortPage1_defaults(ioc)) < 0) {
16342 +               dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
16343 +                   "mptfc_rescan.%d: unable to set PP1 defaults, rc %d.\n",
16344 +                   ioc->name, ioc->sh->host_no, rc));
16345 +               return;
16346 +       }
16347  
16348         /* start by tagging all ports as missing */
16349         list_for_each_entry(ri, &ioc->fc_rports, list) {
16350 @@ -1140,6 +1203,12 @@ mptfc_rescan_devices(struct work_struct 
16351                                        MPT_RPORT_INFO_FLAGS_MISSING);
16352                         fc_remote_port_delete(ri->rport);       /* won't sleep */
16353                         ri->rport = NULL;
16354 +                       starget = ri->starget;
16355 +                       if (starget) {
16356 +                               vtarget = starget->hostdata;
16357 +                               if (vtarget)
16358 +                                       vtarget->deleted = 1;
16359 +                       }
16360  
16361                         pn = (u64)ri->pg0.WWPN.High << 32 |
16362                              (u64)ri->pg0.WWPN.Low;
16363 @@ -1238,6 +1307,10 @@ mptfc_probe(struct pci_dev *pdev, const 
16364         sh->max_id = ioc->pfacts->MaxDevices;
16365         sh->max_lun = max_lun;
16366  
16367 +       sh->this_id = ioc->pfacts[0].PortSCSIID;
16368 +
16369 +       ioc->sdev_queue_depth = mpt_sdev_queue_depth;
16370 +
16371         /* Required entry.
16372          */
16373         sh->unique_id = ioc->id;
16374 @@ -1251,17 +1324,15 @@ mptfc_probe(struct pci_dev *pdev, const 
16375          * A slightly different algorithm is required for
16376          * 64bit SGEs.
16377          */
16378 -       scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
16379 -       if (sizeof(dma_addr_t) == sizeof(u64)) {
16380 +       scale = ioc->req_sz/ioc->SGE_size;
16381 +       if (ioc->sg_addr_size == sizeof(u64)) {
16382                 numSGE = (scale - 1) *
16383                   (ioc->facts.MaxChainDepth-1) + scale +
16384 -                 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
16385 -                 sizeof(u32));
16386 +                 (ioc->req_sz - 60) / ioc->SGE_size;
16387         } else {
16388                 numSGE = 1 + (scale - 1) *
16389                   (ioc->facts.MaxChainDepth-1) + scale +
16390 -                 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
16391 -                 sizeof(u32));
16392 +                 (ioc->req_sz - 64) / ioc->SGE_size;
16393         }
16394  
16395         if (numSGE < sh->sg_tablesize) {
16396 @@ -1290,30 +1361,6 @@ mptfc_probe(struct pci_dev *pdev, const 
16397         dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
16398                  ioc->name, ioc->ScsiLookup));
16399  
16400 -       /* Clear the TM flags
16401 -        */
16402 -       hd->tmPending = 0;
16403 -       hd->tmState = TM_STATE_NONE;
16404 -       hd->resetPending = 0;
16405 -       hd->abortSCpnt = NULL;
16406 -
16407 -       /* Clear the pointer used to store
16408 -        * single-threaded commands, i.e., those
16409 -        * issued during a bus scan, dv and
16410 -        * configuration pages.
16411 -        */
16412 -       hd->cmdPtr = NULL;
16413 -
16414 -       /* Initialize this SCSI Hosts' timers
16415 -        * To use, set the timer expires field
16416 -        * and add_timer
16417 -        */
16418 -       init_timer(&hd->timer);
16419 -       hd->timer.data = (unsigned long) hd;
16420 -       hd->timer.function = mptscsih_timer_expired;
16421 -
16422 -       init_waitqueue_head(&hd->scandv_waitq);
16423 -       hd->scandv_wait_done = 0;
16424         hd->last_queue_full = 0;
16425  
16426         sh->transportt = mptfc_transport_template;
16427 @@ -1326,8 +1373,8 @@ mptfc_probe(struct pci_dev *pdev, const 
16428  
16429         /* initialize workqueue */
16430  
16431 -       snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name),
16432 -                "mptfc_wq_%d", sh->host_no);
16433 +       snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name), "mptfc_wq_%d",
16434 +               sh->host_no);
16435         ioc->fc_rescan_work_q =
16436                 create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
16437         if (!ioc->fc_rescan_work_q)
16438 @@ -1340,7 +1387,6 @@ mptfc_probe(struct pci_dev *pdev, const 
16439         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
16440                 (void) mptfc_GetFcPortPage0(ioc, ii);
16441         }
16442 -       mptfc_SetFcPortPage1_defaults(ioc);
16443  
16444         /*
16445          * scan for rports -
16446 @@ -1378,9 +1424,6 @@ mptfc_event_process(MPT_ADAPTER *ioc, Ev
16447         unsigned long flags;
16448         int rc=1;
16449  
16450 -       devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
16451 -                       ioc->name, event));
16452 -
16453         if (ioc->sh == NULL ||
16454                 ((hd = shost_priv(ioc->sh)) == NULL))
16455                 return 1;
16456 @@ -1416,45 +1459,45 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int re
16457         unsigned long   flags;
16458  
16459         rc = mptscsih_ioc_reset(ioc,reset_phase);
16460 -       if (rc == 0)
16461 +       if ((ioc->bus_type != FC) || (!rc))
16462                 return rc;
16463  
16464 -
16465 -       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
16466 -               ": IOC %s_reset routed to FC host driver!\n",ioc->name,
16467 -               reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
16468 -               reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
16469 -
16470 -       if (reset_phase == MPT_IOC_SETUP_RESET) {
16471 +       switch(reset_phase) {
16472 +       case MPT_IOC_SETUP_RESET:
16473 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
16474 +                   "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __FUNCTION__));
16475                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
16476                 if (ioc->fc_rescan_work_q) {
16477                         queue_work(ioc->fc_rescan_work_q,
16478                                    &ioc->fc_setup_reset_work);
16479                 }
16480                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
16481 -       }
16482 -
16483 -       else if (reset_phase == MPT_IOC_PRE_RESET) {
16484 -       }
16485 -
16486 -       else {  /* MPT_IOC_POST_RESET */
16487 -               mptfc_SetFcPortPage1_defaults(ioc);
16488 +               break;
16489 +       case MPT_IOC_PRE_RESET:
16490 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
16491 +                   "%s: MPT_IOC_PRE_RESET\n", ioc->name, __FUNCTION__));
16492 +               break;
16493 +       case MPT_IOC_POST_RESET:
16494 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
16495 +                   "%s: MPT_IOC_POST_RESET\n",  ioc->name, __FUNCTION__));
16496                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
16497                 if (ioc->fc_rescan_work_q) {
16498                         queue_work(ioc->fc_rescan_work_q,
16499                                    &ioc->fc_rescan_work);
16500                 }
16501                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
16502 +               break;
16503 +       default:
16504 +               break;
16505         }
16506         return 1;
16507  }
16508  
16509 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16510  /**
16511   *     mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
16512   *
16513   *     Returns 0 for success, non-zero for failure.
16514 - */
16515 + **/
16516  static int __init
16517  mptfc_init(void)
16518  {
16519 @@ -1486,12 +1529,11 @@ mptfc_init(void)
16520         return error;
16521  }
16522  
16523 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16524  /**
16525   *     mptfc_remove - Remove fc infrastructure for devices
16526   *     @pdev: Pointer to pci_dev structure
16527   *
16528 - */
16529 + **/
16530  static void __devexit
16531  mptfc_remove(struct pci_dev *pdev)
16532  {
16533 @@ -1501,6 +1543,8 @@ mptfc_remove(struct pci_dev *pdev)
16534         unsigned long           flags;
16535         int                     ii;
16536  
16537 +       printk("%s -pdev=%p\n", __FUNCTION__, pdev);
16538 +
16539         /* destroy workqueue */
16540         if ((work_q=ioc->fc_rescan_work_q)) {
16541                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
16542 @@ -1543,7 +1587,6 @@ mptfc_exit(void)
16543  
16544         mpt_reset_deregister(mptfcDoneCtx);
16545         mpt_event_deregister(mptfcDoneCtx);
16546 -
16547         mpt_deregister(mptfcInternalCtx);
16548         mpt_deregister(mptfcTaskCtx);
16549         mpt_deregister(mptfcDoneCtx);
16550 --- a/drivers/message/fusion/mptlan.c
16551 +++ b/drivers/message/fusion/mptlan.c
16552 @@ -6,7 +6,6 @@
16553   *
16554   *  Copyright (c) 2000-2008 LSI Corporation
16555   *  (mailto:DL-MPTFusionLinux@lsi.com)
16556 - *
16557   */
16558  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16559  /*
16560 @@ -165,6 +164,11 @@ DEFINE_RWLOCK(bad_naa_lock);
16561  #endif
16562  
16563  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16564 +/*
16565 + * Fusion MPT LAN external data
16566 + */
16567 +
16568 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16569  /**
16570   *     lan_reply - Handle all data sent from the hardware.
16571   *     @ioc: Pointer to MPT_ADAPTER structure
16572 @@ -190,8 +194,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
16573                 u32 tmsg = CAST_PTR_TO_U32(reply);
16574  
16575                 dioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n",
16576 -                               IOC_AND_NETDEV_NAMES_s_s(dev),
16577 -                               tmsg));
16578 +                   IOC_AND_NETDEV_NAMES_s_s(dev), tmsg));
16579  
16580                 switch (GET_LAN_FORM(tmsg)) {
16581  
16582 @@ -440,6 +443,7 @@ mpt_lan_open(struct net_device *dev)
16583         dlprintk((KERN_INFO MYNAM "/lo: Finished initializing RcvCtl\n"));
16584  
16585         mpt_lan_post_receive_buckets(priv);
16586 +
16587         printk(KERN_INFO MYNAM ": %s/%s: interface up & active\n",
16588                         IOC_AND_NETDEV_NAMES_s_s(dev));
16589  
16590 @@ -610,7 +614,7 @@ mpt_lan_send_turbo(struct net_device *de
16591  
16592         dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
16593                         IOC_AND_NETDEV_NAMES_s_s(dev),
16594 -                       __func__, sent));
16595 +                       __FUNCTION__, sent));
16596  
16597         priv->SendCtl[ctx].skb = NULL;
16598         pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
16599 @@ -676,7 +680,7 @@ mpt_lan_send_reply(struct net_device *de
16600  
16601                 dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
16602                                 IOC_AND_NETDEV_NAMES_s_s(dev),
16603 -                               __func__, sent));
16604 +                               __FUNCTION__, sent));
16605  
16606                 priv->SendCtl[ctx].skb = NULL;
16607                 pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
16608 @@ -715,7 +719,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
16609         u16 cur_naa = 0x1000;
16610  
16611         dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n",
16612 -                       __func__, skb));
16613 +                       __FUNCTION__, skb));
16614  
16615         spin_lock_irqsave(&priv->txfidx_lock, flags);
16616         if (priv->mpt_txfidx_tail < 0) {
16617 @@ -723,7 +727,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
16618                 spin_unlock_irqrestore(&priv->txfidx_lock, flags);
16619  
16620                 printk (KERN_ERR "%s: no tx context available: %u\n",
16621 -                       __func__, priv->mpt_txfidx_tail);
16622 +                       __FUNCTION__, priv->mpt_txfidx_tail);
16623                 return 1;
16624         }
16625  
16626 @@ -733,7 +737,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
16627                 spin_unlock_irqrestore(&priv->txfidx_lock, flags);
16628  
16629                 printk (KERN_ERR "%s: Unable to alloc request frame\n",
16630 -                       __func__);
16631 +                       __FUNCTION__);
16632                 return 1;
16633         }
16634  
16635 @@ -780,6 +784,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
16636  //                     ctx, skb, skb->data));
16637  
16638         mac = skb_mac_header(skb);
16639 +
16640  #ifdef QLOGIC_NAA_WORKAROUND
16641  {
16642         struct NAA_Hosed *nh;
16643 @@ -805,6 +810,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
16644  }
16645  #endif
16646  
16647 +
16648         pTrans->TransactionDetails[0] = cpu_to_le32((cur_naa         << 16) |
16649                                                     (mac[0] <<  8) |
16650                                                     (mac[1] <<  0));
16651 @@ -828,7 +834,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
16652                           MPI_SGE_FLAGS_END_OF_LIST) << MPI_SGE_FLAGS_SHIFT) |
16653                         skb->len);
16654         pSimple->Address.Low = cpu_to_le32((u32) dma);
16655 -       if (sizeof(dma_addr_t) > sizeof(u32))
16656 +       if (mpt_dev->sg_addr_size > sizeof(u32))
16657                 pSimple->Address.High = cpu_to_le32((u32) ((u64) dma >> 32));
16658         else
16659                 pSimple->Address.High = 0;
16660 @@ -1117,7 +1123,6 @@ mpt_lan_receive_post_reply(struct net_de
16661                                             PCI_DMA_FROMDEVICE);
16662  
16663                 skb_copy_from_linear_data(old_skb, skb_put(skb, len), len);
16664 -
16665                 pci_dma_sync_single_for_device(mpt_dev->pcidev,
16666                                                priv->RcvCtl[ctx].dma,
16667                                                priv->RcvCtl[ctx].len,
16668 @@ -1208,7 +1213,7 @@ mpt_lan_post_receive_buckets(struct mpt_
16669  
16670         dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n",
16671                         IOC_AND_NETDEV_NAMES_s_s(dev),
16672 -                       __func__, buckets, curr));
16673 +                       __FUNCTION__, buckets, curr));
16674  
16675         max = (mpt_dev->req_sz - MPT_LAN_RECEIVE_POST_REQUEST_SIZE) /
16676                         (MPT_LAN_TRANSACTION32_SIZE + sizeof(SGESimple64_t));
16677 @@ -1217,9 +1222,9 @@ mpt_lan_post_receive_buckets(struct mpt_
16678                 mf = mpt_get_msg_frame(LanCtx, mpt_dev);
16679                 if (mf == NULL) {
16680                         printk (KERN_ERR "%s: Unable to alloc request frame\n",
16681 -                               __func__);
16682 +                               __FUNCTION__);
16683                         dioprintk((KERN_ERR "%s: %u buckets remaining\n",
16684 -                                __func__, buckets));
16685 +                                __FUNCTION__, buckets));
16686                         goto out;
16687                 }
16688                 pRecvReq = (LANReceivePostRequest_t *) mf;
16689 @@ -1244,7 +1249,7 @@ mpt_lan_post_receive_buckets(struct mpt_
16690                         spin_lock_irqsave(&priv->rxfidx_lock, flags);
16691                         if (priv->mpt_rxfidx_tail < 0) {
16692                                 printk (KERN_ERR "%s: Can't alloc context\n",
16693 -                                       __func__);
16694 +                                       __FUNCTION__);
16695                                 spin_unlock_irqrestore(&priv->rxfidx_lock,
16696                                                        flags);
16697                                 break;
16698 @@ -1267,7 +1272,7 @@ mpt_lan_post_receive_buckets(struct mpt_
16699                                 if (skb == NULL) {
16700                                         printk (KERN_WARNING
16701                                                 MYNAM "/%s: Can't alloc skb\n",
16702 -                                               __func__);
16703 +                                               __FUNCTION__);
16704                                         priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
16705                                         spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
16706                                         break;
16707 @@ -1295,7 +1300,7 @@ mpt_lan_post_receive_buckets(struct mpt_
16708                                   MPI_SGE_FLAGS_SIMPLE_ELEMENT |
16709                                   MPI_SGE_FLAGS_64_BIT_ADDRESSING) << MPI_SGE_FLAGS_SHIFT) | len);
16710                         pSimple->Address.Low = cpu_to_le32((u32) priv->RcvCtl[ctx].dma);
16711 -                       if (sizeof(dma_addr_t) > sizeof(u32))
16712 +                       if (mpt_dev->sg_addr_size > sizeof(u32))
16713                                 pSimple->Address.High = cpu_to_le32((u32) ((u64) priv->RcvCtl[ctx].dma >> 32));
16714                         else
16715                                 pSimple->Address.High = 0;
16716 @@ -1305,7 +1310,7 @@ mpt_lan_post_receive_buckets(struct mpt_
16717  
16718                 if (pSimple == NULL) {
16719  /**/                   printk (KERN_WARNING MYNAM "/%s: No buckets posted\n",
16720 -/**/                           __func__);
16721 +/**/                           __FUNCTION__);
16722                         mpt_free_msg_frame(mpt_dev, mf);
16723                         goto out;
16724                 }
16725 @@ -1329,9 +1334,9 @@ mpt_lan_post_receive_buckets(struct mpt_
16726  
16727  out:
16728         dioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n",
16729 -                 __func__, buckets, atomic_read(&priv->buckets_out)));
16730 +                 __FUNCTION__, buckets, atomic_read(&priv->buckets_out)));
16731         dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n",
16732 -       __func__, priv->total_posted, priv->total_received));
16733 +       __FUNCTION__, priv->total_posted, priv->total_received));
16734  
16735         clear_bit(0, &priv->post_buckets_active);
16736  }
16737 @@ -1340,18 +1345,17 @@ static void
16738  mpt_lan_post_receive_buckets_work(struct work_struct *work)
16739  {
16740         mpt_lan_post_receive_buckets(container_of(work, struct mpt_lan_priv,
16741 -                                                 post_buckets_task.work));
16742 +               post_buckets_task.work));
16743  }
16744  
16745  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16746  static struct net_device *
16747  mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
16748  {
16749 -       struct net_device *dev;
16750 -       struct mpt_lan_priv *priv;
16751 +       struct net_device *dev = alloc_fcdev(sizeof(struct mpt_lan_priv));
16752 +       struct mpt_lan_priv *priv = NULL;
16753         u8 HWaddr[FC_ALEN], *a;
16754  
16755 -       dev = alloc_fcdev(sizeof(struct mpt_lan_priv));
16756         if (!dev)
16757                 return NULL;
16758  
16759 @@ -1363,8 +1367,9 @@ mpt_register_lan_device (MPT_ADAPTER *mp
16760         priv->mpt_dev = mpt_dev;
16761         priv->pnum = pnum;
16762  
16763 +       memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task));
16764         INIT_DELAYED_WORK(&priv->post_buckets_task,
16765 -                         mpt_lan_post_receive_buckets_work);
16766 +               mpt_lan_post_receive_buckets_work);
16767         priv->post_buckets_active = 0;
16768  
16769         dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n",
16770 @@ -1387,6 +1392,8 @@ mpt_register_lan_device (MPT_ADAPTER *mp
16771         spin_lock_init(&priv->txfidx_lock);
16772         spin_lock_init(&priv->rxfidx_lock);
16773  
16774 +       memset(&priv->stats, 0, sizeof(priv->stats));
16775 +
16776         /*  Grab pre-fetched LANPage1 stuff. :-) */
16777         a = (u8 *) &mpt_dev->lan_cnfg_page1.HardwareAddressLow;
16778  
16779 @@ -1421,6 +1428,7 @@ mpt_register_lan_device (MPT_ADAPTER *mp
16780         dlprintk((KERN_INFO MYNAM ": Finished registering dev "
16781                 "and setting initial values\n"));
16782  
16783 +
16784         if (register_netdev(dev) != 0) {
16785                 free_netdev(dev);
16786                 dev = NULL;
16787 --- a/drivers/message/fusion/mptlan.h
16788 +++ b/drivers/message/fusion/mptlan.h
16789 @@ -6,7 +6,6 @@
16790   *
16791   *  Copyright (c) 2000-2008 LSI Corporation
16792   *  (mailto:DL-MPTFusionLinux@lsi.com)
16793 - *
16794   */
16795  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
16796  /*
16797 @@ -55,6 +54,7 @@
16798  #include <linux/module.h>
16799  #endif
16800  
16801 +#include <linux/version.h>
16802  #include <linux/netdevice.h>
16803  #include <linux/errno.h>
16804  // #include <linux/etherdevice.h>
16805 @@ -73,6 +73,7 @@
16806  
16807  #include <asm/uaccess.h>
16808  #include <asm/io.h>
16809 +#include <linux/pci.h>
16810  
16811      /* Override mptbase.h by pre-defining these! */
16812  #define MODULEAUTHOR   "LSI Corporation"
16813 --- a/drivers/message/fusion/mptsas.c
16814 +++ b/drivers/message/fusion/mptsas.c
16815 @@ -47,9 +47,11 @@
16816  #include <linux/kernel.h>
16817  #include <linux/init.h>
16818  #include <linux/errno.h>
16819 -#include <linux/jiffies.h>
16820 +#include <linux/sched.h>
16821  #include <linux/workqueue.h>
16822 +#include <linux/interrupt.h>
16823  #include <linux/delay.h>       /* for mdelay */
16824 +#include <linux/pci.h>
16825  
16826  #include <scsi/scsi.h>
16827  #include <scsi/scsi_cmnd.h>
16828 @@ -62,7 +64,6 @@
16829  #include "mptscsih.h"
16830  #include "mptsas.h"
16831  
16832 -
16833  #define my_NAME                "Fusion MPT SAS Host driver"
16834  #define my_VERSION     MPT_LINUX_VERSION_COMMON
16835  #define MYNAM          "mptsas"
16836 @@ -72,6 +73,8 @@
16837   */
16838  #define MPTSAS_RAID_CHANNEL    1
16839  
16840 +#define SAS_CONFIG_PAGE_TIMEOUT                30
16841 +
16842  MODULE_AUTHOR(MODULEAUTHOR);
16843  MODULE_DESCRIPTION(my_NAME);
16844  MODULE_LICENSE("GPL");
16845 @@ -83,6 +86,25 @@ MODULE_PARM_DESC(mpt_pt_clear,
16846                 " Clear persistency table: enable=1  "
16847                 "(default=MPTSCSIH_PT_CLEAR=0)");
16848  
16849 +static int mpt_cmd_retry_count = 144;
16850 +module_param(mpt_cmd_retry_count, int, 0);
16851 +MODULE_PARM_DESC(mpt_cmd_retry_count,
16852 +               " Device discovery TUR command retry count: default=144");
16853 +
16854 +static int mpt_disable_hotplug_remove = 0;
16855 +module_param(mpt_disable_hotplug_remove, int, 0);
16856 +MODULE_PARM_DESC(mpt_disable_hotplug_remove,
16857 +               " Disable hotpug remove events: default=0");
16858 +
16859 +static int mpt_sdev_queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
16860 +static int mptsas_set_sdev_queue_depth(const char *val,
16861 +    struct kernel_param *kp);
16862 +module_param_call(mpt_sdev_queue_depth, mptsas_set_sdev_queue_depth,
16863 +    param_get_int, &mpt_sdev_queue_depth, 0600);
16864 +MODULE_PARM_DESC(mpt_sdev_queue_depth,
16865 +    " Max Device Queue Depth (default="
16866 +    __MODULE_STRING(MPT_SCSI_CMD_PER_DEV_HIGH) ")");
16867 +
16868  /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
16869  #define MPTSAS_MAX_LUN (16895)
16870  static int max_lun = MPTSAS_MAX_LUN;
16871 @@ -93,8 +115,53 @@ static u8   mptsasDoneCtx = MPT_MAX_PROTOC
16872  static u8      mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
16873  static u8      mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
16874  static u8      mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
16875 +static u8      mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
16876 +
16877 +static inline void mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
16878 +static struct mptsas_phyinfo * mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc,
16879 +       u64 sas_address);
16880 +static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
16881 +       u32 form, u32 form_specific);
16882 +static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
16883 +               u32 form, u32 form_specific);
16884 +
16885 +static int mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info);
16886 +static void mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info);
16887 +static void mptsas_expander_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info);
16888 +static int mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
16889 +               u32 form, u32 form_specific);
16890 +static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
16891 +static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
16892 +
16893 +static void mptsas_firmware_event_work(struct work_struct *work);
16894 +
16895 +/**
16896 + *     mptsas_set_sdev_queue_depth - global setting of the mpt_sdev_queue_depth
16897 + *     found via /sys/module/mptsas/parameters/mpt_sdev_queue_depth
16898 + *     @val:
16899 + *     @kp:
16900 + *
16901 + *     Returns
16902 + **/
16903 +static int
16904 +mptsas_set_sdev_queue_depth(const char *val, struct kernel_param *kp)
16905 +{
16906 +       int ret = param_set_int(val, kp);
16907 +       MPT_ADAPTER *ioc;
16908 +       struct scsi_device      *sdev;
16909  
16910 -static void mptsas_hotplug_work(struct work_struct *work);
16911 +       if (ret)
16912 +               return ret;
16913 +
16914 +       list_for_each_entry(ioc, &ioc_list, list) {
16915 +               if (ioc->bus_type != SAS)
16916 +                       continue;
16917 +               shost_for_each_device(sdev, ioc->sh)
16918 +                       mptscsih_change_queue_depth(sdev, mpt_sdev_queue_depth);
16919 +               ioc->sdev_queue_depth = mpt_sdev_queue_depth;
16920 +       }
16921 +       return 0;
16922 +}
16923  
16924  static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
16925                                         MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
16926 @@ -218,37 +285,183 @@ static void mptsas_print_expander_pg1(MP
16927             le16_to_cpu(pg1->AttachedDevHandle)));
16928  }
16929  
16930 -static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
16931 +/* inhibit sas firmware event handling */
16932 +static void
16933 +mptsas_fw_event_off(MPT_ADAPTER *ioc)
16934 +{
16935 +       unsigned long flags;
16936 +
16937 +       spin_lock_irqsave(&ioc->fw_event_lock, flags);
16938 +       ioc->fw_events_off = 1;
16939 +       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
16940 +
16941 +}
16942 +
16943 +/* enable sas firmware event handling */
16944 +static void
16945 +mptsas_fw_event_on(MPT_ADAPTER *ioc)
16946 +{
16947 +       unsigned long flags;
16948 +
16949 +       spin_lock_irqsave(&ioc->fw_event_lock, flags);
16950 +       ioc->fw_events_off = 0;
16951 +       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
16952 +}
16953 +
16954 +/* queue a sas firmware event */
16955 +static void
16956 +mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
16957 +    unsigned long delay)
16958 +{
16959 +       unsigned long flags;
16960 +
16961 +#if defined(CPQ_CIM)
16962 +       ioc->csmi_change_count++;
16963 +#endif
16964 +
16965 +       spin_lock_irqsave(&ioc->fw_event_lock, flags);
16966 +       list_add_tail(&fw_event->list, &ioc->fw_event_list);
16967 +       INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
16968 +       devtprintk(ioc, printk(MYIOC_s_INFO_FMT "%s: add (fw_event=0x%p)\n",
16969 +           ioc->name,__FUNCTION__, fw_event));
16970 +       queue_delayed_work(ioc->fw_event_q, &fw_event->work,
16971 +           msecs_to_jiffies(delay));
16972 +       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
16973 +}
16974 +
16975 +/* requeue a sas firmware event */
16976 +static void
16977 +mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
16978 +    unsigned long delay)
16979 +{
16980 +       unsigned long flags;
16981 +       spin_lock_irqsave(&ioc->fw_event_lock, flags);
16982 +       devtprintk(ioc, printk(MYIOC_s_INFO_FMT "%s: reschedule task "
16983 +           "(fw_event=0x%p)\n", ioc->name,__FUNCTION__, fw_event));
16984 +       fw_event->retries++;
16985 +       queue_delayed_work(ioc->fw_event_q, &fw_event->work,
16986 +           msecs_to_jiffies(delay));
16987 +       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
16988 +}
16989 +
16990 +/* free memory assoicated to a sas firmware event */
16991 +static void
16992 +mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
16993 +{
16994 +       unsigned long flags;
16995 +
16996 +       spin_lock_irqsave(&ioc->fw_event_lock, flags);
16997 +       devtprintk(ioc, printk(MYIOC_s_INFO_FMT "%s: kfree (fw_event=0x%p)\n",
16998 +           ioc->name,__FUNCTION__, fw_event));
16999 +       list_del(&fw_event->list);
17000 +       kfree(fw_event);
17001 +       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
17002 +}
17003 +
17004 +/* walk the firmware event queue, and either stop or wait for outstanding events to complete */
17005 +static void
17006 +mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
17007 +{
17008 +       struct fw_event_work *fw_event, *next;
17009 +       struct mptsas_target_reset_event *target_reset_list, *n;
17010 +       u8      flush_q;
17011 +       MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
17012 +
17013 +       /* flush the target_reset_list */
17014 +       if (!list_empty(&hd->target_reset_list)) {
17015 +               list_for_each_entry_safe(target_reset_list, n,
17016 +                   &hd->target_reset_list, list) {
17017 +                       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
17018 +                           "%s: removing target reset for id=%d\n",
17019 +                           ioc->name, __FUNCTION__,
17020 +                          target_reset_list->sas_event_data.TargetID));
17021 +                       list_del(&target_reset_list->list);
17022 +                       kfree(target_reset_list);
17023 +               }
17024 +       }
17025 +
17026 +       if (list_empty(&ioc->fw_event_list) ||
17027 +            !ioc->fw_event_q || in_interrupt())
17028 +               return;
17029 +
17030 +       flush_q = 0;
17031 +       list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
17032 +               if (cancel_delayed_work(&fw_event->work))
17033 +                       mptsas_free_fw_event(ioc, fw_event);
17034 +               else
17035 +                       flush_q = 1;
17036 +       }
17037 +       if (flush_q)
17038 +               flush_workqueue(ioc->fw_event_q);
17039 +}
17040 +
17041 +
17042 +/**
17043 + *     phy_to_ioc -
17044 + *     @phy:
17045 + *
17046 + *
17047 + **/
17048 +static inline MPT_ADAPTER *
17049 +phy_to_ioc(struct sas_phy *phy)
17050  {
17051         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
17052         return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
17053  }
17054  
17055 -static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
17056 +/**
17057 + *     rphy_to_ioc -
17058 + *     @rphy:
17059 + *
17060 + *
17061 + **/
17062 +static inline MPT_ADAPTER *
17063 +rphy_to_ioc(struct sas_rphy *rphy)
17064  {
17065         struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
17066         return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
17067  }
17068  
17069 +/**
17070 + *     mptsas_find_portinfo_by_sas_address -
17071 + *     @ioc: Pointer to MPT_ADAPTER structure
17072 + *     @handle:
17073 + *
17074 + *     This function should be called with the sas_topology_mutex already held
17075 + *
17076 + **/
17077  static struct mptsas_portinfo *
17078 -mptsas_get_hba_portinfo(MPT_ADAPTER *ioc)
17079 +mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
17080  {
17081 -       struct list_head        *head = &ioc->sas_topology;
17082 -       struct mptsas_portinfo  *pi = NULL;
17083 -
17084 -       /* always the first entry on sas_topology list */
17085 -
17086 -       if (!list_empty(head))
17087 -               pi = list_entry(head->next, struct mptsas_portinfo, list);
17088 +       struct mptsas_portinfo *port_info, *rc=NULL;
17089 +       int i;
17090 +
17091 +       if (sas_address >= ioc->hba_port_sas_addr &&
17092 +           sas_address < (ioc->hba_port_sas_addr +
17093 +           ioc->hba_port_num_phy))
17094 +               return ioc->hba_port_info;
17095  
17096 -       return pi;
17097 +       mutex_lock(&ioc->sas_topology_mutex);
17098 +       list_for_each_entry(port_info, &ioc->sas_topology, list)
17099 +               for (i = 0; i < port_info->num_phys; i++)
17100 +                       if (port_info->phy_info[i].identify.sas_address ==
17101 +                           sas_address) {
17102 +                               rc = port_info;
17103 +                               goto out;
17104 +                       }
17105 + out:
17106 +       mutex_unlock(&ioc->sas_topology_mutex);
17107 +       return rc;
17108  }
17109  
17110 -/*
17111 - * mptsas_find_portinfo_by_handle
17112 +/**
17113 + *     mptsas_find_portinfo_by_handle -
17114 + *     @ioc: Pointer to MPT_ADAPTER structure
17115 + *     @handle:
17116   *
17117 - * This function should be called with the sas_topology_mutex already held
17118 - */
17119 + *     This function should be called with the sas_topology_mutex already held
17120 + *
17121 + **/
17122  static struct mptsas_portinfo *
17123  mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
17124  {
17125 @@ -265,9 +478,12 @@ mptsas_find_portinfo_by_handle(MPT_ADAPT
17126         return rc;
17127  }
17128  
17129 -/*
17130 - * Returns true if there is a scsi end device
17131 - */
17132 +/**
17133 + *     mptsas_is_end_device -
17134 + *     @attached:
17135 + *
17136 + *     Returns true if there is a scsi end device
17137 + **/
17138  static inline int
17139  mptsas_is_end_device(struct mptsas_devinfo * attached)
17140  {
17141 @@ -285,7 +501,14 @@ mptsas_is_end_device(struct mptsas_devin
17142                 return 0;
17143  }
17144  
17145 -/* no mutex */
17146 +/**
17147 + *     mptsas_port_delete -
17148 + *     @ioc: Pointer to MPT_ADAPTER structure
17149 + *     @port_details:
17150 + *
17151 + *     (no mutex)
17152 + *
17153 + **/
17154  static void
17155  mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
17156  {
17157 @@ -300,7 +523,7 @@ mptsas_port_delete(MPT_ADAPTER *ioc, str
17158         phy_info = port_info->phy_info;
17159  
17160         dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
17161 -           "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
17162 +           "bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details,
17163             port_details->num_phys, (unsigned long long)
17164             port_details->phy_bitmask));
17165  
17166 @@ -308,11 +531,17 @@ mptsas_port_delete(MPT_ADAPTER *ioc, str
17167                 if(phy_info->port_details != port_details)
17168                         continue;
17169                 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
17170 +               mptsas_set_rphy(ioc, phy_info, NULL);
17171                 phy_info->port_details = NULL;
17172         }
17173         kfree(port_details);
17174  }
17175  
17176 +/**
17177 + *     mptsas_get_rphy -
17178 + *     @phy_info:
17179 + *
17180 + **/
17181  static inline struct sas_rphy *
17182  mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
17183  {
17184 @@ -322,13 +551,20 @@ mptsas_get_rphy(struct mptsas_phyinfo *p
17185                 return NULL;
17186  }
17187  
17188 +/**
17189 + *     mptsas_set_rphy -
17190 + *     @ioc: Pointer to MPT_ADAPTER structure
17191 + *     @phy_info:
17192 + *     @rphy:
17193 + *
17194 + **/
17195  static inline void
17196  mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
17197  {
17198         if (phy_info->port_details) {
17199                 phy_info->port_details->rphy = rphy;
17200 -               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
17201 -                   ioc->name, rphy));
17202 +               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
17203 +                   "sas_rphy_add: rphy=%p\n", ioc->name, rphy));
17204         }
17205  
17206         if (rphy) {
17207 @@ -339,6 +575,11 @@ mptsas_set_rphy(MPT_ADAPTER *ioc, struct
17208         }
17209  }
17210  
17211 +/**
17212 + *     mptsas_get_port -
17213 + *     @phy_info:
17214 + *
17215 + **/
17216  static inline struct sas_port *
17217  mptsas_get_port(struct mptsas_phyinfo *phy_info)
17218  {
17219 @@ -348,6 +589,13 @@ mptsas_get_port(struct mptsas_phyinfo *p
17220                 return NULL;
17221  }
17222  
17223 +/**
17224 + *     mptsas_set_port -
17225 + *     @ioc: Pointer to MPT_ADAPTER structure
17226 + *     @phy_info:
17227 + *     @port:
17228 + *
17229 + **/
17230  static inline void
17231  mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
17232  {
17233 @@ -362,6 +610,11 @@ mptsas_set_port(MPT_ADAPTER *ioc, struct
17234         }
17235  }
17236  
17237 +/**
17238 + *     mptsas_get_starget -
17239 + *     @phy_info:
17240 + *
17241 + **/
17242  static inline struct scsi_target *
17243  mptsas_get_starget(struct mptsas_phyinfo *phy_info)
17244  {
17245 @@ -371,6 +624,12 @@ mptsas_get_starget(struct mptsas_phyinfo
17246                 return NULL;
17247  }
17248  
17249 +/**
17250 + *     mptsas_set_starget -
17251 + *     @phy_info:
17252 + *     @starget:
17253 + *
17254 + **/
17255  static inline void
17256  mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
17257  starget)
17258 @@ -379,714 +638,787 @@ starget)
17259                 phy_info->port_details->starget = starget;
17260  }
17261  
17262 -
17263 -/*
17264 - * mptsas_setup_wide_ports
17265 +/**
17266 + *     mptsas_add_device_component -
17267 + *     @ioc: Pointer to MPT_ADAPTER structure
17268 + *     @channel: fw mapped id's
17269 + *     @id:
17270 + *     @sas_address:
17271 + *     @device_info:
17272   *
17273 - * Updates for new and existing narrow/wide port configuration
17274 - * in the sas_topology
17275 - */
17276 + **/
17277  static void
17278 -mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
17279 +mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
17280 +       u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
17281  {
17282 -       struct mptsas_portinfo_details * port_details;
17283 -       struct mptsas_phyinfo *phy_info, *phy_info_cmp;
17284 -       u64     sas_address;
17285 -       int     i, j;
17286 -
17287 -       mutex_lock(&ioc->sas_topology_mutex);
17288 -
17289 -       phy_info = port_info->phy_info;
17290 -       for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
17291 -               if (phy_info->attached.handle)
17292 -                       continue;
17293 -               port_details = phy_info->port_details;
17294 -               if (!port_details)
17295 -                       continue;
17296 -               if (port_details->num_phys < 2)
17297 -                       continue;
17298 -               /*
17299 -                * Removing a phy from a port, letting the last
17300 -                * phy be removed by firmware events.
17301 -                */
17302 -               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
17303 -                   "%s: [%p]: deleting phy = %d\n",
17304 -                   ioc->name, __func__, port_details, i));
17305 -               port_details->num_phys--;
17306 -               port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
17307 -               memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
17308 -               sas_port_delete_phy(port_details->port, phy_info->phy);
17309 -               phy_info->port_details = NULL;
17310 +       struct sas_device_info  *sas_info, *next;
17311 +       struct scsi_device      *sdev;
17312 +       struct scsi_target      *starget;
17313 +       struct sas_rphy         *rphy;
17314 +
17315 +       /*
17316 +        * Delete all matching devices out of the list
17317 +        */
17318 +       down(&ioc->sas_device_info_mutex);
17319 +       list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
17320 +           list) {
17321 +               if (!sas_info->is_logical_volume &&
17322 +                   (sas_info->sas_address == sas_address ||
17323 +                   (sas_info->fw.channel == channel &&
17324 +                    sas_info->fw.id == id))) {
17325 +                       list_del(&sas_info->list);
17326 +                       kfree(sas_info);
17327 +               }
17328         }
17329  
17330 +       if (!(sas_info = kzalloc(sizeof(struct sas_device_info), GFP_KERNEL)))
17331 +               goto out;
17332 +
17333         /*
17334 -        * Populate and refresh the tree
17335 +        * Set Firmware mapping
17336          */
17337 -       phy_info = port_info->phy_info;
17338 -       for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
17339 -               sas_address = phy_info->attached.sas_address;
17340 -               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
17341 -                   ioc->name, i, (unsigned long long)sas_address));
17342 -               if (!sas_address)
17343 -                       continue;
17344 -               port_details = phy_info->port_details;
17345 -               /*
17346 -                * Forming a port
17347 -                */
17348 -               if (!port_details) {
17349 -                       port_details = kzalloc(sizeof(*port_details),
17350 -                               GFP_KERNEL);
17351 -                       if (!port_details)
17352 -                               goto out;
17353 -                       port_details->num_phys = 1;
17354 -                       port_details->port_info = port_info;
17355 -                       if (phy_info->phy_id < 64 )
17356 -                               port_details->phy_bitmask |=
17357 -                                   (1 << phy_info->phy_id);
17358 -                       phy_info->sas_port_add_phy=1;
17359 -                       dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
17360 -                           "phy_id=%d sas_address=0x%018llX\n",
17361 -                           ioc->name, i, (unsigned long long)sas_address));
17362 -                       phy_info->port_details = port_details;
17363 -               }
17364 +       sas_info->fw.id = id;
17365 +       sas_info->fw.channel = channel;
17366  
17367 -               if (i == port_info->num_phys - 1)
17368 -                       continue;
17369 -               phy_info_cmp = &port_info->phy_info[i + 1];
17370 -               for (j = i + 1 ; j < port_info->num_phys ; j++,
17371 -                   phy_info_cmp++) {
17372 -                       if (!phy_info_cmp->attached.sas_address)
17373 -                               continue;
17374 -                       if (sas_address != phy_info_cmp->attached.sas_address)
17375 -                               continue;
17376 -                       if (phy_info_cmp->port_details == port_details )
17377 -                               continue;
17378 -                       dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
17379 -                           "\t\tphy_id=%d sas_address=0x%018llX\n",
17380 -                           ioc->name, j, (unsigned long long)
17381 -                           phy_info_cmp->attached.sas_address));
17382 -                       if (phy_info_cmp->port_details) {
17383 -                               port_details->rphy =
17384 -                                   mptsas_get_rphy(phy_info_cmp);
17385 -                               port_details->port =
17386 -                                   mptsas_get_port(phy_info_cmp);
17387 -                               port_details->starget =
17388 -                                   mptsas_get_starget(phy_info_cmp);
17389 -                               port_details->num_phys =
17390 -                                       phy_info_cmp->port_details->num_phys;
17391 -                               if (!phy_info_cmp->port_details->num_phys)
17392 -                                       kfree(phy_info_cmp->port_details);
17393 -                       } else
17394 -                               phy_info_cmp->sas_port_add_phy=1;
17395 -                       /*
17396 -                        * Adding a phy to a port
17397 -                        */
17398 -                       phy_info_cmp->port_details = port_details;
17399 -                       if (phy_info_cmp->phy_id < 64 )
17400 -                               port_details->phy_bitmask |=
17401 -                               (1 << phy_info_cmp->phy_id);
17402 -                       port_details->num_phys++;
17403 +       sas_info->sas_address = sas_address;
17404 +       sas_info->device_info = device_info;
17405 +       sas_info->slot = slot;
17406 +       sas_info->enclosure_logical_id = enclosure_logical_id;
17407 +       INIT_LIST_HEAD(&sas_info->list);
17408 +       list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
17409 +
17410 +       /*
17411 +        * Set OS mapping
17412 +        */
17413 +       shost_for_each_device(sdev, ioc->sh) {
17414 +               starget = scsi_target(sdev);
17415 +               rphy = dev_to_rphy(starget->dev.parent);
17416 +               if (rphy->identify.sas_address == sas_address) {
17417 +                       sas_info->os.id = starget->id;
17418 +                       sas_info->os.channel = starget->channel;
17419                 }
17420         }
17421  
17422   out:
17423 -
17424 -       for (i = 0; i < port_info->num_phys; i++) {
17425 -               port_details = port_info->phy_info[i].port_details;
17426 -               if (!port_details)
17427 -                       continue;
17428 -               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
17429 -                   "%s: [%p]: phy_id=%02d num_phys=%02d "
17430 -                   "bitmask=0x%016llX\n", ioc->name, __func__,
17431 -                   port_details, i, port_details->num_phys,
17432 -                   (unsigned long long)port_details->phy_bitmask));
17433 -               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
17434 -                   ioc->name, port_details->port, port_details->rphy));
17435 -       }
17436 -       dsaswideprintk(ioc, printk("\n"));
17437 -       mutex_unlock(&ioc->sas_topology_mutex);
17438 +       up(&ioc->sas_device_info_mutex);
17439 +       return;
17440  }
17441  
17442  /**
17443 - * csmisas_find_vtarget
17444 - *
17445 - * @ioc
17446 - * @volume_id
17447 - * @volume_bus
17448 + *     mptsas_add_device_component_by_fw -
17449 + *     @ioc: Pointer to MPT_ADAPTER structure
17450 + *     @channel:  fw mapped id's
17451 + *     @id:
17452   *
17453   **/
17454 -static VirtTarget *
17455 -mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
17456 +static void
17457 +mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
17458  {
17459 -       struct scsi_device              *sdev;
17460 -       VirtDevice                      *vdevice;
17461 -       VirtTarget                      *vtarget = NULL;
17462 +       struct mptsas_devinfo sas_device;
17463 +       struct mptsas_enclosure enclosure_info;
17464 +       int rc;
17465  
17466 -       shost_for_each_device(sdev, ioc->sh) {
17467 -               if ((vdevice = sdev->hostdata) == NULL)
17468 -                       continue;
17469 -               if (vdevice->vtarget->id == id &&
17470 -                   vdevice->vtarget->channel == channel)
17471 -                       vtarget = vdevice->vtarget;
17472 -       }
17473 -       return vtarget;
17474 +       rc = mptsas_sas_device_pg0(ioc, &sas_device,
17475 +           (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
17476 +            MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
17477 +           (channel << 8) + id);
17478 +       if (rc)
17479 +               return;
17480 +
17481 +       memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
17482 +       mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
17483 +           (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
17484 +            MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
17485 +            sas_device.handle_enclosure);
17486 +
17487 +       mptsas_add_device_component(ioc, sas_device.channel,
17488 +           sas_device.id, sas_device.sas_address, sas_device.device_info,
17489 +           sas_device.slot, enclosure_info.enclosure_logical_id);
17490  }
17491  
17492  /**
17493 - * mptsas_target_reset
17494 - *
17495 - * Issues TARGET_RESET to end device using handshaking method
17496 - *
17497 - * @ioc
17498 - * @channel
17499 - * @id
17500 - *
17501 - * Returns (1) success
17502 - *         (0) failure
17503 - *
17504 - **/
17505 -static int
17506 -mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
17507 -{
17508 -       MPT_FRAME_HDR   *mf;
17509 -       SCSITaskMgmt_t  *pScsiTm;
17510 -
17511 -       if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
17512 -               dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
17513 -                   ioc->name,__func__, __LINE__));
17514 -               return 0;
17515 -       }
17516 -
17517 -       /* Format the Request
17518 -        */
17519 -       pScsiTm = (SCSITaskMgmt_t *) mf;
17520 -       memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
17521 -       pScsiTm->TargetID = id;
17522 -       pScsiTm->Bus = channel;
17523 -       pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
17524 -       pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
17525 -       pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
17526 -
17527 -       DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
17528 -
17529 -       mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
17530 -
17531 -       return 1;
17532 -}
17533 -
17534 -/**
17535 - * mptsas_target_reset_queue
17536 - *
17537 - * Receive request for TARGET_RESET after recieving an firmware
17538 - * event NOT_RESPONDING_EVENT, then put command in link list
17539 - * and queue if task_queue already in use.
17540 - *
17541 - * @ioc
17542 - * @sas_event_data
17543 + *     mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding
17544 + *     each individual device to list
17545 + *     @ioc: Pointer to MPT_ADAPTER structure
17546 + *     @channel: fw mapped id's
17547 + *     @id:
17548   *
17549   **/
17550  static void
17551 -mptsas_target_reset_queue(MPT_ADAPTER *ioc,
17552 -    EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
17553 +mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc, struct scsi_target *starget)
17554  {
17555 -       MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
17556 -       VirtTarget *vtarget = NULL;
17557 -       struct mptsas_target_reset_event *target_reset_list;
17558 -       u8              id, channel;
17559 +       CONFIGPARMS                     cfg;
17560 +       ConfigPageHeader_t              hdr;
17561 +       dma_addr_t                      dma_handle;
17562 +       pRaidVolumePage0_t              buffer = NULL;
17563 +       int                             i;
17564 +       RaidPhysDiskPage0_t             phys_disk;
17565 +       struct sas_device_info          *sas_info, *next;
17566  
17567 -       id = sas_event_data->TargetID;
17568 -       channel = sas_event_data->Bus;
17569 +       memset(&cfg, 0 , sizeof(CONFIGPARMS));
17570 +       memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
17571 +       hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
17572 +       /* assumption that all volumes on channel = 0 */
17573 +       cfg.pageAddr = starget->id;
17574 +       cfg.cfghdr.hdr = &hdr;
17575 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
17576 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
17577  
17578 -       if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
17579 -               return;
17580 +       if (mpt_config(ioc, &cfg) != 0)
17581 +               goto out;
17582  
17583 -       vtarget->deleted = 1; /* block IO */
17584 +       if (!hdr.PageLength)
17585 +               goto out;
17586  
17587 -       target_reset_list = kzalloc(sizeof(*target_reset_list),
17588 -           GFP_ATOMIC);
17589 -       if (!target_reset_list) {
17590 -               dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
17591 -                   ioc->name,__func__, __LINE__));
17592 -               return;
17593 -       }
17594 +       buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
17595 +           &dma_handle);
17596  
17597 -       memcpy(&target_reset_list->sas_event_data, sas_event_data,
17598 -               sizeof(*sas_event_data));
17599 -       list_add_tail(&target_reset_list->list, &hd->target_reset_list);
17600 +       if (!buffer)
17601 +               goto out;
17602  
17603 -       if (hd->resetPending)
17604 -               return;
17605 +       cfg.physAddr = dma_handle;
17606 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
17607  
17608 -       if (mptsas_target_reset(ioc, channel, id)) {
17609 -               target_reset_list->target_reset_issued = 1;
17610 -               hd->resetPending = 1;
17611 -       }
17612 -}
17613 +       if (mpt_config(ioc, &cfg) != 0)
17614 +               goto out;
17615  
17616 -/**
17617 - * mptsas_dev_reset_complete
17618 - *
17619 - * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
17620 - * enable work queue to finish off removing device from upper layers.
17621 - * then send next TARGET_RESET in the queue.
17622 - *
17623 - * @ioc
17624 - *
17625 - **/
17626 -static void
17627 -mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
17628 -{
17629 -       MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
17630 -        struct list_head *head = &hd->target_reset_list;
17631 -       struct mptsas_target_reset_event *target_reset_list;
17632 -       struct mptsas_hotplug_event *ev;
17633 -       EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
17634 -       u8              id, channel;
17635 -       __le64          sas_address;
17636 +       if (!buffer->NumPhysDisks)
17637 +               goto out;
17638  
17639 -       if (list_empty(head))
17640 -               return;
17641 +       /*
17642 +        * Adding entry for hidden components
17643 +        */
17644 +       for (i = 0; i < buffer->NumPhysDisks; i++) {
17645  
17646 -       target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
17647 +               if(mpt_raid_phys_disk_pg0(ioc,
17648 +                   buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
17649 +                       continue;
17650  
17651 -       sas_event_data = &target_reset_list->sas_event_data;
17652 -       id = sas_event_data->TargetID;
17653 -       channel = sas_event_data->Bus;
17654 -       hd->resetPending = 0;
17655 +               mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
17656 +                   phys_disk.PhysDiskID);
17657  
17658 -       /*
17659 -        * retry target reset
17660 -        */
17661 -       if (!target_reset_list->target_reset_issued) {
17662 -               if (mptsas_target_reset(ioc, channel, id)) {
17663 -                       target_reset_list->target_reset_issued = 1;
17664 -                       hd->resetPending = 1;
17665 +               down(&ioc->sas_device_info_mutex);
17666 +               list_for_each_entry(sas_info, &ioc->sas_device_info_list,
17667 +                   list) {
17668 +                       if (!sas_info->is_logical_volume &&
17669 +                           (sas_info->fw.channel == phys_disk.PhysDiskBus &&
17670 +                           sas_info->fw.id == phys_disk.PhysDiskID)) {
17671 +                               sas_info->is_hidden_raid_component = 1;
17672 +                               sas_info->volume_id = starget->id;
17673 +                       }
17674                 }
17675 -               return;
17676 +               up(&ioc->sas_device_info_mutex);
17677         }
17678  
17679         /*
17680 -        * enable work queue to remove device from upper layers
17681 +        * Delete all matching devices out of the list
17682          */
17683 -       list_del(&target_reset_list->list);
17684 +       down(&ioc->sas_device_info_mutex);
17685 +       list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
17686 +           list) {
17687 +               if (sas_info->is_logical_volume && sas_info->fw.id ==
17688 +                   starget->id) {
17689 +                       list_del(&sas_info->list);
17690 +                       kfree(sas_info);
17691 +               }
17692 +       }
17693  
17694 -       ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
17695 -       if (!ev) {
17696 -               dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
17697 -                   ioc->name,__func__, __LINE__));
17698 -               return;
17699 +       sas_info = kzalloc(sizeof(struct sas_device_info), GFP_KERNEL);
17700 +       if (sas_info) {
17701 +               sas_info->fw.id = starget->id;
17702 +               sas_info->os.id = starget->id;
17703 +               sas_info->os.channel = starget->channel;
17704 +               sas_info->is_logical_volume = 1;
17705 +               INIT_LIST_HEAD(&sas_info->list);
17706 +               list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
17707         }
17708 +       up(&ioc->sas_device_info_mutex);
17709  
17710 -       INIT_WORK(&ev->work, mptsas_hotplug_work);
17711 -       ev->ioc = ioc;
17712 -       ev->handle = le16_to_cpu(sas_event_data->DevHandle);
17713 -       ev->parent_handle =
17714 -           le16_to_cpu(sas_event_data->ParentDevHandle);
17715 -       ev->channel = channel;
17716 -       ev->id =id;
17717 -       ev->phy_id = sas_event_data->PhyNum;
17718 -       memcpy(&sas_address, &sas_event_data->SASAddress,
17719 -           sizeof(__le64));
17720 -       ev->sas_address = le64_to_cpu(sas_address);
17721 -       ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
17722 -       ev->event_type = MPTSAS_DEL_DEVICE;
17723 -       schedule_work(&ev->work);
17724 -       kfree(target_reset_list);
17725 + out:
17726 +       if (buffer)
17727 +               pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
17728 +                   dma_handle);
17729 +}
17730  
17731 -       /*
17732 -        * issue target reset to next device in the queue
17733 -        */
17734 +/**
17735 + *     mptsas_add_device_component_starget -
17736 + *     @ioc: Pointer to MPT_ADAPTER structure
17737 + *     @starget:
17738 + *
17739 + **/
17740 +static void
17741 +mptsas_add_device_component_starget(MPT_ADAPTER *ioc, struct scsi_target *starget)
17742 +{
17743 +       VirtTarget              *vtarget;
17744 +       struct sas_rphy         *rphy;
17745 +       struct mptsas_phyinfo *phy_info = NULL;
17746 +       struct mptsas_enclosure enclosure_info;
17747  
17748 -       head = &hd->target_reset_list;
17749 -       if (list_empty(head))
17750 +       rphy = dev_to_rphy(starget->dev.parent);
17751 +       vtarget = starget->hostdata;
17752 +       phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
17753 +                   rphy->identify.sas_address);
17754 +       if (!phy_info)
17755                 return;
17756  
17757 -       target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
17758 -           list);
17759 -
17760 -       sas_event_data = &target_reset_list->sas_event_data;
17761 -       id = sas_event_data->TargetID;
17762 -       channel = sas_event_data->Bus;
17763 -
17764 -       if (mptsas_target_reset(ioc, channel, id)) {
17765 -               target_reset_list->target_reset_issued = 1;
17766 -               hd->resetPending = 1;
17767 -       }
17768 +       memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
17769 +       mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
17770 +           (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
17771 +            MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
17772 +            phy_info->attached.handle_enclosure);
17773 +
17774 +       mptsas_add_device_component(ioc, phy_info->attached.channel,
17775 +           phy_info->attached.id, phy_info->attached.sas_address,
17776 +           phy_info->attached.device_info,
17777 +           phy_info->attached.slot, enclosure_info.enclosure_logical_id);
17778  }
17779  
17780  /**
17781 - * mptsas_taskmgmt_complete
17782 - *
17783 - * @ioc
17784 - * @mf
17785 - * @mr
17786 + *     mptsas_del_device_component_by_os - Once a device has been removed, we
17787 + *     mark the entry in the list as being cached
17788 + *     @ioc: Pointer to MPT_ADAPTER structure
17789 + *     @channel: os mapped id's
17790 + *     @id:
17791   *
17792   **/
17793 -static int
17794 -mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
17795 +static void
17796 +mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
17797  {
17798 -       mptsas_dev_reset_complete(ioc);
17799 -       return mptscsih_taskmgmt_complete(ioc, mf, mr);
17800 +       struct sas_device_info  *sas_info, *next;
17801 +
17802 +       /*
17803 +        * Set is_cached flag
17804 +        */
17805 +       list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
17806 +               list) {
17807 +               if (sas_info->os.channel == channel && sas_info->os.id == id)
17808 +                       sas_info->is_cached = 1;
17809 +       }
17810  }
17811  
17812  /**
17813 - * mptscsih_ioc_reset
17814 - *
17815 - * @ioc
17816 - * @reset_phase
17817 + *     mptsas_del_device_components - Cleaning the list
17818 + *     @ioc: Pointer to MPT_ADAPTER structure
17819   *
17820   **/
17821 -static int
17822 -mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
17823 +static void
17824 +mptsas_del_device_components(MPT_ADAPTER *ioc)
17825  {
17826 -       MPT_SCSI_HOST   *hd;
17827 -       struct mptsas_target_reset_event *target_reset_list, *n;
17828 -       int rc;
17829 -
17830 -       rc = mptscsih_ioc_reset(ioc, reset_phase);
17831 -
17832 -       if (ioc->bus_type != SAS)
17833 -               goto out;
17834 -
17835 -       if (reset_phase != MPT_IOC_POST_RESET)
17836 -               goto out;
17837 +       struct sas_device_info  *sas_info, *next;
17838  
17839 -       if (!ioc->sh || !ioc->sh->hostdata)
17840 -               goto out;
17841 -       hd = shost_priv(ioc->sh);
17842 -       if (!hd->ioc)
17843 -               goto out;
17844 -
17845 -       if (list_empty(&hd->target_reset_list))
17846 -               goto out;
17847 -
17848 -       /* flush the target_reset_list */
17849 -       list_for_each_entry_safe(target_reset_list, n,
17850 -           &hd->target_reset_list, list) {
17851 -               list_del(&target_reset_list->list);
17852 -               kfree(target_reset_list);
17853 +       down(&ioc->sas_device_info_mutex);
17854 +       list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
17855 +               list) {
17856 +               list_del(&sas_info->list);
17857 +               kfree(sas_info);
17858         }
17859 -
17860 - out:
17861 -       return rc;
17862 +       up(&ioc->sas_device_info_mutex);
17863  }
17864  
17865 -static int
17866 -mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
17867 -               u32 form, u32 form_specific)
17868 +/**
17869 + *     mptsas_setup_wide_ports - Updates for new and existing narrow/wide port
17870 + *     configuration
17871 + *     in the sas_topology
17872 + *     @ioc: Pointer to MPT_ADAPTER structure
17873 + *     @port_info:
17874 + *
17875 + */
17876 +static void
17877 +mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
17878  {
17879 -       ConfigExtendedPageHeader_t hdr;
17880 -       CONFIGPARMS cfg;
17881 -       SasEnclosurePage0_t *buffer;
17882 -       dma_addr_t dma_handle;
17883 -       int error;
17884 -       __le64 le_identifier;
17885 -
17886 -       memset(&hdr, 0, sizeof(hdr));
17887 -       hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
17888 -       hdr.PageNumber = 0;
17889 -       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
17890 -       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
17891 +       struct mptsas_portinfo_details * port_details;
17892 +       struct mptsas_phyinfo *phy_info, *phy_info_cmp;
17893 +       u64     sas_address;
17894 +       int     i, j;
17895  
17896 -       cfg.cfghdr.ehdr = &hdr;
17897 -       cfg.physAddr = -1;
17898 -       cfg.pageAddr = form + form_specific;
17899 -       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
17900 -       cfg.dir = 0;    /* read */
17901 -       cfg.timeout = 10;
17902 +       mutex_lock(&ioc->sas_topology_mutex);
17903  
17904 -       error = mpt_config(ioc, &cfg);
17905 -       if (error)
17906 -               goto out;
17907 -       if (!hdr.ExtPageLength) {
17908 -               error = -ENXIO;
17909 -               goto out;
17910 -       }
17911 +       phy_info = port_info->phy_info;
17912 +       for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
17913 +               if (phy_info->attached.handle)
17914 +                       continue;
17915 +               port_details = phy_info->port_details;
17916 +               if (!port_details)
17917 +                       continue;
17918 +               if (port_details->num_phys < 2)
17919 +                       continue;
17920  
17921 -       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
17922 -                       &dma_handle);
17923 -       if (!buffer) {
17924 -               error = -ENOMEM;
17925 -               goto out;
17926 +               /*
17927 +                * Removing a phy from a port, letting the last
17928 +                * phy be removed by firmware events.
17929 +                */
17930 +               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
17931 +                       "%s: [%p]: deleting phy = %d\n",
17932 +                       ioc->name, __FUNCTION__, port_details, i));
17933 +               port_details->num_phys--;
17934 +               port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
17935 +               memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
17936 +               devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
17937 +                   MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
17938 +                    phy_info->phy_id, phy_info->phy));
17939 +               sas_port_delete_phy(port_details->port, phy_info->phy);
17940 +               phy_info->port_details = NULL;
17941         }
17942  
17943 -       cfg.physAddr = dma_handle;
17944 -       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
17945 -
17946 -       error = mpt_config(ioc, &cfg);
17947 -       if (error)
17948 -               goto out_free_consistent;
17949 -
17950 -       /* save config data */
17951 -       memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
17952 -       enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
17953 -       enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
17954 -       enclosure->flags = le16_to_cpu(buffer->Flags);
17955 -       enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
17956 -       enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
17957 -       enclosure->start_id = buffer->StartTargetID;
17958 -       enclosure->start_channel = buffer->StartBus;
17959 -       enclosure->sep_id = buffer->SEPTargetID;
17960 -       enclosure->sep_channel = buffer->SEPBus;
17961 +       /*
17962 +        * Populate and refresh the tree
17963 +        */
17964 +       phy_info = port_info->phy_info;
17965 +       for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
17966 +               sas_address = phy_info->attached.sas_address;
17967 +               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
17968 +                   ioc->name, i, (unsigned long long)sas_address));
17969 +               if (!sas_address)
17970 +                       continue;
17971 +               port_details = phy_info->port_details;
17972 +               /*
17973 +                * Forming a port
17974 +                */
17975 +               if (!port_details) {
17976 +                       port_details = kzalloc(sizeof(struct mptsas_portinfo_details),
17977 +                               GFP_KERNEL);
17978 +                       if (!port_details)
17979 +                               goto out;
17980 +                       port_details->num_phys = 1;
17981 +                       port_details->port_info = port_info;
17982 +                       if (phy_info->phy_id < 64 )
17983 +                               port_details->phy_bitmask |=
17984 +                                   (1 << phy_info->phy_id);
17985 +                       phy_info->sas_port_add_phy=1;
17986 +                       dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
17987 +                           "phy_id=%d sas_address=0x%018llX\n", ioc->name, i,
17988 +                           (unsigned long long) sas_address));
17989 +                       phy_info->port_details = port_details;
17990 +               }
17991 +
17992 +               if (i == port_info->num_phys - 1)
17993 +                       continue;
17994 +               phy_info_cmp = &port_info->phy_info[i + 1];
17995 +               for (j = i + 1 ; j < port_info->num_phys ; j++,
17996 +                   phy_info_cmp++) {
17997 +                       if (!phy_info_cmp->attached.sas_address)
17998 +                               continue;
17999 +                       if (sas_address != phy_info_cmp->attached.sas_address)
18000 +                               continue;
18001 +                       if (phy_info_cmp->port_details == port_details )
18002 +                               continue;
18003 +                       dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
18004 +                           "\t\tphy_id=%d sas_address=0x%018llX\n",
18005 +                           ioc->name, j, (unsigned long long)
18006 +                           phy_info_cmp->attached.sas_address));
18007 +                       if (phy_info_cmp->port_details) {
18008 +                               port_details->rphy =
18009 +                                   mptsas_get_rphy(phy_info_cmp);
18010 +                               port_details->port =
18011 +                                   mptsas_get_port(phy_info_cmp);
18012 +                               port_details->starget =
18013 +                                   mptsas_get_starget(phy_info_cmp);
18014 +                               port_details->num_phys =
18015 +                                       phy_info_cmp->port_details->num_phys;
18016 +                               if (!phy_info_cmp->port_details->num_phys)
18017 +                                       kfree(phy_info_cmp->port_details);
18018 +                       } else
18019 +                               phy_info_cmp->sas_port_add_phy=1;
18020 +                       /*
18021 +                        * Adding a phy to a port
18022 +                        */
18023 +                       phy_info_cmp->port_details = port_details;
18024 +                       if (phy_info_cmp->phy_id < 64 )
18025 +                               port_details->phy_bitmask |=
18026 +                               (1 << phy_info_cmp->phy_id);
18027 +                       port_details->num_phys++;
18028 +               }
18029 +       }
18030  
18031 - out_free_consistent:
18032 -       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
18033 -                           buffer, dma_handle);
18034   out:
18035 -       return error;
18036 +
18037 +       for (i = 0; i < port_info->num_phys; i++) {
18038 +               port_details = port_info->phy_info[i].port_details;
18039 +               if (!port_details)
18040 +                       continue;
18041 +               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
18042 +                   "%s: [%p]: phy_id=%02d num_phys=%02d "
18043 +                   "bitmask=0x%016llX\n", ioc->name, __FUNCTION__,
18044 +                   port_details, i, port_details->num_phys,
18045 +                   (unsigned long long)port_details->phy_bitmask));
18046 +               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
18047 +                   ioc->name, port_details->port, port_details->rphy));
18048 +       }
18049 +       dsaswideprintk(ioc, printk("\n"));
18050 +       mutex_unlock(&ioc->sas_topology_mutex);
18051  }
18052  
18053 -static int
18054 -mptsas_slave_configure(struct scsi_device *sdev)
18055 +/**
18056 + *     mptsas_find_vtarget - obtain vtarget object for non-raid devices
18057 + *     @ioc: Pointer to MPT_ADAPTER structure
18058 + *     @channel:
18059 + *     @id:
18060 + *
18061 + **/
18062 +static VirtTarget *
18063 +mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
18064 +{
18065 +       struct scsi_device              *sdev;
18066 +       VirtDevice                      *vdevice;
18067 +       VirtTarget                      *vtarget = NULL;
18068 +
18069 +       shost_for_each_device(sdev, ioc->sh) {
18070 +               if ((vdevice = sdev->hostdata) == NULL ||
18071 +                       (vdevice->vtarget == NULL))
18072 +                       continue;
18073 +               if ((vdevice->vtarget->tflags &
18074 +                   MPT_TARGET_FLAGS_RAID_COMPONENT ||
18075 +                   vdevice->vtarget->raidVolume))
18076 +                       continue;
18077 +               if (vdevice->vtarget->id == id &&
18078 +                   vdevice->vtarget->channel == channel)
18079 +                       vtarget = vdevice->vtarget;
18080 +       }
18081 +       return vtarget;
18082 +}
18083 +
18084 +static void
18085 +mptsas_queue_device_delete(MPT_ADAPTER *ioc,
18086 +    MpiEventDataSasDeviceStatusChange_t *sas_event_data)
18087  {
18088 +       struct fw_event_work *fw_event;
18089 +       int sz;
18090  
18091 -       if (sdev->channel == MPTSAS_RAID_CHANNEL)
18092 -               goto out;
18093 +       sz = offsetof(struct fw_event_work, event_data) +
18094 +           sizeof(MpiEventDataSasDeviceStatusChange_t);
18095 +       fw_event = kzalloc(sz, GFP_ATOMIC);
18096 +       if (!fw_event) {
18097 +               printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
18098 +                   ioc->name, __FUNCTION__, __LINE__);
18099 +               return;
18100 +       }
18101 +       memcpy(fw_event->event_data, sas_event_data,
18102 +           sizeof(MpiEventDataSasDeviceStatusChange_t));
18103 +       fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
18104 +       fw_event->ioc = ioc;
18105 +       mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
18106 +}
18107  
18108 -       sas_read_port_mode_page(sdev);
18109 +static void
18110 +mptsas_queue_rescan(MPT_ADAPTER *ioc)
18111 +{
18112 +       struct fw_event_work *fw_event;
18113 +       int sz;
18114  
18115 - out:
18116 -       return mptscsih_slave_configure(sdev);
18117 +       sz = offsetof(struct fw_event_work, event_data);
18118 +       fw_event = kzalloc(sz, GFP_ATOMIC);
18119 +       if (!fw_event) {
18120 +               printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
18121 +                   ioc->name, __FUNCTION__, __LINE__);
18122 +               return;
18123 +       }
18124 +       fw_event->event = -1;
18125 +       fw_event->ioc = ioc;
18126 +       mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
18127  }
18128  
18129 +
18130 +/**
18131 + *     mptsas_target_reset - Issues TARGET_RESET to end device using
18132 + *     handshaking method
18133 + *     @ioc: Pointer to MPT_ADAPTER structure
18134 + *     @channel:
18135 + *     @id:
18136 + *
18137 + *     Returns (1) success
18138 + *             (0) failure
18139 + *
18140 + **/
18141  static int
18142 -mptsas_target_alloc(struct scsi_target *starget)
18143 +mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
18144  {
18145 -       struct Scsi_Host *host = dev_to_shost(&starget->dev);
18146 -       MPT_SCSI_HOST           *hd = shost_priv(host);
18147 -       VirtTarget              *vtarget;
18148 -       u8                      id, channel;
18149 -       struct sas_rphy         *rphy;
18150 -       struct mptsas_portinfo  *p;
18151 -       int                      i;
18152 -       MPT_ADAPTER             *ioc = hd->ioc;
18153 +       MPT_FRAME_HDR   *mf;
18154 +       SCSITaskMgmt_t  *pScsiTm;
18155  
18156 -       vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
18157 -       if (!vtarget)
18158 -               return -ENOMEM;
18159 +       if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
18160 +               return 0;
18161  
18162 -       vtarget->starget = starget;
18163 -       vtarget->ioc_id = ioc->id;
18164 -       vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
18165 -       id = starget->id;
18166 -       channel = 0;
18167 +       if ((mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc)) == NULL) {
18168 +               dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
18169 +                   ioc->name,__FUNCTION__, __LINE__));
18170 +               goto out_fail;
18171 +       }
18172  
18173 -       /*
18174 -        * RAID volumes placed beyond the last expected port.
18175 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
18176 +               ioc->name, mf));
18177 +
18178 +       /* Format the Request
18179          */
18180 -       if (starget->channel == MPTSAS_RAID_CHANNEL) {
18181 -               for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
18182 -                       if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
18183 -                               channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
18184 -               goto out;
18185 -       }
18186 +       pScsiTm = (SCSITaskMgmt_t *) mf;
18187 +       memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
18188 +       pScsiTm->TargetID = id;
18189 +       pScsiTm->Bus = channel;
18190 +       pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
18191 +       pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
18192 +       pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
18193  
18194 -       rphy = dev_to_rphy(starget->dev.parent);
18195 -       mutex_lock(&ioc->sas_topology_mutex);
18196 -       list_for_each_entry(p, &ioc->sas_topology, list) {
18197 -               for (i = 0; i < p->num_phys; i++) {
18198 -                       if (p->phy_info[i].attached.sas_address !=
18199 -                                       rphy->identify.sas_address)
18200 -                               continue;
18201 -                       id = p->phy_info[i].attached.id;
18202 -                       channel = p->phy_info[i].attached.channel;
18203 -                       mptsas_set_starget(&p->phy_info[i], starget);
18204 +       DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
18205  
18206 -                       /*
18207 -                        * Exposing hidden raid components
18208 -                        */
18209 -                       if (mptscsih_is_phys_disk(ioc, channel, id)) {
18210 -                               id = mptscsih_raid_id_to_num(ioc,
18211 -                                               channel, id);
18212 -                               vtarget->tflags |=
18213 -                                   MPT_TARGET_FLAGS_RAID_COMPONENT;
18214 -                               p->phy_info[i].attached.phys_disk_num = id;
18215 -                       }
18216 -                       mutex_unlock(&ioc->sas_topology_mutex);
18217 -                       goto out;
18218 -               }
18219 -       }
18220 -       mutex_unlock(&ioc->sas_topology_mutex);
18221 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
18222 +          "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
18223 +          ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
18224  
18225 -       kfree(vtarget);
18226 -       return -ENXIO;
18227 +       mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
18228  
18229 - out:
18230 -       vtarget->id = id;
18231 -       vtarget->channel = channel;
18232 -       starget->hostdata = vtarget;
18233 +       return 1;
18234 +
18235 + out_fail:
18236 +
18237 +       mpt_clear_taskmgmt_in_progress_flag(ioc);
18238         return 0;
18239  }
18240 -
18241 +/**
18242 + * mptsas_target_reset_queue -
18243 + * @ioc: Pointer to MPT_ADAPTER structure
18244 + * @sas_event_data:
18245 + *
18246 + * Receive request for TARGET_RESET after
18247 + * recieving an firmware event NOT_RESPONDING_EVENT, then put command in
18248 + * link list and queue if task_queue already in use.
18249 + **/
18250  static void
18251 -mptsas_target_destroy(struct scsi_target *starget)
18252 +mptsas_target_reset_queue(MPT_ADAPTER *ioc,
18253 +    EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
18254  {
18255 -       struct Scsi_Host *host = dev_to_shost(&starget->dev);
18256 -       MPT_SCSI_HOST           *hd = shost_priv(host);
18257 -       struct sas_rphy         *rphy;
18258 -       struct mptsas_portinfo  *p;
18259 -       int                      i;
18260 -       MPT_ADAPTER *ioc = hd->ioc;
18261 +       MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
18262 +       VirtTarget *vtarget = NULL;
18263 +       struct mptsas_target_reset_event        *target_reset_list;
18264 +       u8              id, channel;
18265  
18266 -       if (!starget->hostdata)
18267 -               return;
18268 +       id = sas_event_data->TargetID;
18269 +       channel = sas_event_data->Bus;
18270  
18271 -       if (starget->channel == MPTSAS_RAID_CHANNEL)
18272 -               goto out;
18273 +       if ((vtarget = mptsas_find_vtarget(ioc, channel, id))) {
18274 +               if (!ioc->disable_hotplug_remove)
18275 +                       vtarget->deleted = 1; /* block IO */
18276 +       }
18277  
18278 -       rphy = dev_to_rphy(starget->dev.parent);
18279 -       list_for_each_entry(p, &ioc->sas_topology, list) {
18280 -               for (i = 0; i < p->num_phys; i++) {
18281 -                       if (p->phy_info[i].attached.sas_address !=
18282 -                                       rphy->identify.sas_address)
18283 -                               continue;
18284 -                       mptsas_set_starget(&p->phy_info[i], NULL);
18285 -                       goto out;
18286 -               }
18287 +       target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
18288 +           GFP_ATOMIC);
18289 +       if (!target_reset_list) {
18290 +               dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
18291 +                   ioc->name,__FUNCTION__, __LINE__));
18292 +               return;
18293         }
18294  
18295 - out:
18296 -       kfree(starget->hostdata);
18297 -       starget->hostdata = NULL;
18298 -}
18299 +       memcpy(&target_reset_list->sas_event_data, sas_event_data,
18300 +               sizeof(*sas_event_data));
18301 +       list_add_tail(&target_reset_list->list, &hd->target_reset_list);
18302 +
18303 +       target_reset_list->time_count = jiffies;
18304  
18305 +       if (mptsas_target_reset(ioc, channel, id))
18306 +               target_reset_list->target_reset_issued = 1;
18307 +}
18308  
18309 +/**
18310 + *     mptsas_taskmgmt_complete - Completion for TARGET_RESET after
18311 + *     NOT_RESPONDING_EVENT, enable work queue to finish off removing device
18312 + *     from upper layers. then send next TARGET_RESET in the queue.
18313 + *     @ioc: Pointer to MPT_ADAPTER structure
18314 + *
18315 + **/
18316  static int
18317 -mptsas_slave_alloc(struct scsi_device *sdev)
18318 +mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
18319  {
18320 -       struct Scsi_Host        *host = sdev->host;
18321 -       MPT_SCSI_HOST           *hd = shost_priv(host);
18322 -       struct sas_rphy         *rphy;
18323 -       struct mptsas_portinfo  *p;
18324 -       VirtDevice              *vdevice;
18325 -       struct scsi_target      *starget;
18326 -       int                     i;
18327 -       MPT_ADAPTER *ioc = hd->ioc;
18328 +       MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
18329 +        struct list_head *head = &hd->target_reset_list;
18330 +       struct mptsas_target_reset_event        *target_reset_list;
18331 +       u8              id, channel;
18332 +       SCSITaskMgmtReply_t *pScsiTmReply;
18333  
18334 -       vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
18335 -       if (!vdevice) {
18336 -               printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
18337 -                               ioc->name, sizeof(VirtDevice));
18338 -               return -ENOMEM;
18339 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
18340 +           "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
18341 +
18342 +       pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
18343 +       if (pScsiTmReply) {
18344 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
18345 +                   "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
18346 +                   "\ttask_type = 0x%02X, iocstatus = 0x%04X "
18347 +                   "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
18348 +                   "term_cmnds = %d\n", ioc->name,
18349 +                   pScsiTmReply->Bus, pScsiTmReply->TargetID,
18350 +                   pScsiTmReply->TaskType,
18351 +                   le16_to_cpu(pScsiTmReply->IOCStatus),
18352 +                   le32_to_cpu(pScsiTmReply->IOCLogInfo),
18353 +                   pScsiTmReply->ResponseCode,
18354 +                   le32_to_cpu(pScsiTmReply->TerminationCount)));
18355 +
18356 +               if (pScsiTmReply->ResponseCode)
18357 +                       mptscsih_taskmgmt_response_code(ioc,
18358 +                       pScsiTmReply->ResponseCode);
18359 +       }
18360 +
18361 +       if (pScsiTmReply && (pScsiTmReply->TaskType ==
18362 +           MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
18363 +            MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
18364 +               ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
18365 +               ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
18366 +               memcpy(ioc->taskmgmt_cmds.reply, mr,
18367 +                   min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
18368 +               if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
18369 +                       ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
18370 +                       complete(&ioc->taskmgmt_cmds.done);
18371 +                       return 1;
18372 +               }
18373 +               return 0;
18374         }
18375 -       starget = scsi_target(sdev);
18376 -       vdevice->vtarget = starget->hostdata;
18377  
18378 -       if (sdev->channel == MPTSAS_RAID_CHANNEL)
18379 -               goto out;
18380 +       mpt_clear_taskmgmt_in_progress_flag(ioc);
18381  
18382 -       rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
18383 -       mutex_lock(&ioc->sas_topology_mutex);
18384 -       list_for_each_entry(p, &ioc->sas_topology, list) {
18385 -               for (i = 0; i < p->num_phys; i++) {
18386 -                       if (p->phy_info[i].attached.sas_address !=
18387 -                                       rphy->identify.sas_address)
18388 -                               continue;
18389 -                       vdevice->lun = sdev->lun;
18390 -                       /*
18391 -                        * Exposing hidden raid components
18392 -                        */
18393 -                       if (mptscsih_is_phys_disk(ioc,
18394 -                           p->phy_info[i].attached.channel,
18395 -                           p->phy_info[i].attached.id))
18396 -                               sdev->no_uld_attach = 1;
18397 -                       mutex_unlock(&ioc->sas_topology_mutex);
18398 -                       goto out;
18399 -               }
18400 +       if (list_empty(head))
18401 +               return 1;
18402 +
18403 +       target_reset_list = list_entry(head->next,
18404 +           struct mptsas_target_reset_event, list);
18405 +
18406 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
18407 +           "TaskMgmt: completed (%d seconds)\n",
18408 +           ioc->name, jiffies_to_msecs(jiffies -
18409 +           target_reset_list->time_count)/1000));
18410 +
18411 +       id = pScsiTmReply->TargetID;
18412 +       channel = pScsiTmReply->Bus;
18413 +       target_reset_list->time_count = jiffies;
18414 +
18415 +       /*
18416 +        * retry target reset
18417 +        */
18418 +       if (!target_reset_list->target_reset_issued) {
18419 +               if (mptsas_target_reset(ioc, channel, id))
18420 +                       target_reset_list->target_reset_issued = 1;
18421 +               return 1;
18422         }
18423 -       mutex_unlock(&ioc->sas_topology_mutex);
18424  
18425 -       kfree(vdevice);
18426 -       return -ENXIO;
18427 +       /*
18428 +        * enable work queue to remove device from upper layers
18429 +        */
18430 +       list_del(&target_reset_list->list);
18431 +       if ((mptsas_find_vtarget(ioc, channel, id)) && !ioc->fw_events_off)
18432 +               mptsas_queue_device_delete(ioc, &target_reset_list->sas_event_data);
18433  
18434 - out:
18435 -       vdevice->vtarget->num_luns++;
18436 -       sdev->hostdata = vdevice;
18437 -       return 0;
18438 +
18439 +       /*
18440 +        * issue target reset to next device in the queue
18441 +        */
18442 +
18443 +       head = &hd->target_reset_list;
18444 +       if (list_empty(head))
18445 +               return 1;
18446 +
18447 +       target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
18448 +           list);
18449 +
18450 +       id = target_reset_list->sas_event_data.TargetID;
18451 +       channel = target_reset_list->sas_event_data.Bus;
18452 +       target_reset_list->time_count = jiffies;
18453 +
18454 +       if (mptsas_target_reset(ioc, channel, id))
18455 +               target_reset_list->target_reset_issued = 1;
18456 +
18457 +       return 1;
18458  }
18459  
18460 +/**
18461 + *     mptsas_ioc_reset -
18462 + *     @ioc: Pointer to MPT_ADAPTER structure
18463 + *     @reset_phase:
18464 + *
18465 + **/
18466  static int
18467 -mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
18468 +mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
18469  {
18470 -       VirtDevice      *vdevice = SCpnt->device->hostdata;
18471 -
18472 -       if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
18473 -               SCpnt->result = DID_NO_CONNECT << 16;
18474 -               done(SCpnt);
18475 -               return 0;
18476 -       }
18477 +       MPT_SCSI_HOST   *hd;
18478 +       int rc;
18479  
18480 -//     scsi_print_command(SCpnt);
18481 +       rc = mptscsih_ioc_reset(ioc, reset_phase);
18482 +       if ((ioc->bus_type != SAS) || (!rc))
18483 +               return rc;
18484  
18485 -       return mptscsih_qcmd(SCpnt,done);
18486 -}
18487 +       hd = shost_priv(ioc->sh);
18488 +       if (!hd->ioc)
18489 +               goto out;
18490  
18491 +       switch(reset_phase) {
18492 +       case MPT_IOC_SETUP_RESET:
18493 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
18494 +                   "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __FUNCTION__));
18495 +               mptsas_fw_event_off(ioc);
18496 +               break;
18497 +       case MPT_IOC_PRE_RESET:
18498 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
18499 +                   "%s: MPT_IOC_PRE_RESET\n", ioc->name, __FUNCTION__));
18500 +               break;
18501 +       case MPT_IOC_POST_RESET:
18502 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
18503 +                   "%s: MPT_IOC_POST_RESET\n", ioc->name, __FUNCTION__));
18504 +               if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
18505 +                       ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
18506 +                       complete(&ioc->sas_mgmt.done);
18507 +               }
18508 +               mptsas_cleanup_fw_event_q(ioc);
18509 +               mptsas_queue_rescan(ioc);
18510 +               mptsas_fw_event_on(ioc);
18511 +               break;
18512 +       default:
18513 +               break;
18514 +       }
18515  
18516 -static struct scsi_host_template mptsas_driver_template = {
18517 -       .module                         = THIS_MODULE,
18518 -       .proc_name                      = "mptsas",
18519 -       .proc_info                      = mptscsih_proc_info,
18520 -       .name                           = "MPT SPI Host",
18521 -       .info                           = mptscsih_info,
18522 -       .queuecommand                   = mptsas_qcmd,
18523 -       .target_alloc                   = mptsas_target_alloc,
18524 -       .slave_alloc                    = mptsas_slave_alloc,
18525 -       .slave_configure                = mptsas_slave_configure,
18526 -       .target_destroy                 = mptsas_target_destroy,
18527 -       .slave_destroy                  = mptscsih_slave_destroy,
18528 -       .change_queue_depth             = mptscsih_change_queue_depth,
18529 -       .eh_abort_handler               = mptscsih_abort,
18530 -       .eh_device_reset_handler        = mptscsih_dev_reset,
18531 -       .eh_bus_reset_handler           = mptscsih_bus_reset,
18532 -       .eh_host_reset_handler          = mptscsih_host_reset,
18533 -       .bios_param                     = mptscsih_bios_param,
18534 -       .can_queue                      = MPT_FC_CAN_QUEUE,
18535 -       .this_id                        = -1,
18536 -       .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
18537 -       .max_sectors                    = 8192,
18538 -       .cmd_per_lun                    = 7,
18539 -       .use_clustering                 = ENABLE_CLUSTERING,
18540 -       .shost_attrs                    = mptscsih_host_attrs,
18541 -};
18542 + out:
18543 +       return rc;
18544 +}
18545  
18546 -static int mptsas_get_linkerrors(struct sas_phy *phy)
18547 +/**
18548 + *     mptsas_sas_enclosure_pg0 -
18549 + *     @ioc: Pointer to MPT_ADAPTER structure
18550 + *     @enclosure:
18551 + *     @form:
18552 + *     @form_specific:
18553 + *
18554 + **/
18555 +static int
18556 +mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
18557 +               u32 form, u32 form_specific)
18558  {
18559 -       MPT_ADAPTER *ioc = phy_to_ioc(phy);
18560         ConfigExtendedPageHeader_t hdr;
18561         CONFIGPARMS cfg;
18562 -       SasPhyPage1_t *buffer;
18563 +       SasEnclosurePage0_t *buffer;
18564         dma_addr_t dma_handle;
18565         int error;
18566 +       __le64 le_identifier;
18567  
18568 -       /* FIXME: only have link errors on local phys */
18569 -       if (!scsi_is_sas_phy_local(phy))
18570 -               return -EINVAL;
18571 -
18572 -       hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
18573 -       hdr.ExtPageLength = 0;
18574 -       hdr.PageNumber = 1 /* page number 1*/;
18575 -       hdr.Reserved1 = 0;
18576 -       hdr.Reserved2 = 0;
18577 +       memset(&hdr, 0, sizeof(hdr));
18578 +       hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
18579 +       hdr.PageNumber = 0;
18580         hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
18581 -       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
18582 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
18583  
18584         cfg.cfghdr.ehdr = &hdr;
18585         cfg.physAddr = -1;
18586 -       cfg.pageAddr = phy->identify.phy_identifier;
18587 +       cfg.pageAddr = form + form_specific;
18588         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
18589 -       cfg.dir = 0;    /* read */
18590 -       cfg.timeout = 10;
18591 +       cfg.dir = 0;    /* read */
18592 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
18593  
18594         error = mpt_config(ioc, &cfg);
18595         if (error)
18596 -               return error;
18597 -       if (!hdr.ExtPageLength)
18598 -               return -ENXIO;
18599 +               goto out;
18600 +       if (!hdr.ExtPageLength) {
18601 +               error = -ENXIO;
18602 +               goto out;
18603 +       }
18604  
18605         buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
18606 -                                     &dma_handle);
18607 -       if (!buffer)
18608 -               return -ENOMEM;
18609 +                       &dma_handle);
18610 +       if (!buffer) {
18611 +               error = -ENOMEM;
18612 +               goto out;
18613 +       }
18614  
18615         cfg.physAddr = dma_handle;
18616         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
18617 @@ -1095,289 +1427,852 @@ static int mptsas_get_linkerrors(struct 
18618         if (error)
18619                 goto out_free_consistent;
18620  
18621 -       mptsas_print_phy_pg1(ioc, buffer);
18622 -
18623 -       phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
18624 -       phy->running_disparity_error_count =
18625 -               le32_to_cpu(buffer->RunningDisparityErrorCount);
18626 -       phy->loss_of_dword_sync_count =
18627 -               le32_to_cpu(buffer->LossDwordSynchCount);
18628 -       phy->phy_reset_problem_count =
18629 -               le32_to_cpu(buffer->PhyResetProblemCount);
18630 +       /* save config data */
18631 +       memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
18632 +       enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
18633 +       enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
18634 +       enclosure->flags = le16_to_cpu(buffer->Flags);
18635 +       enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
18636 +       enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
18637 +       enclosure->start_id = buffer->StartTargetID;
18638 +       enclosure->start_channel = buffer->StartBus;
18639 +       enclosure->sep_id = buffer->SEPTargetID;
18640 +       enclosure->sep_channel = buffer->SEPBus;
18641  
18642   out_free_consistent:
18643         pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
18644                             buffer, dma_handle);
18645 + out:
18646         return error;
18647  }
18648  
18649 -static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
18650 -               MPT_FRAME_HDR *reply)
18651 +/**
18652 + *     mptsas_get_lun_number - returns the first entry in report_luns table
18653 + *     @ioc: Pointer to MPT_ADAPTER structure
18654 + *     @channel:
18655 + *     @id:
18656 + *     @lun:
18657 + *
18658 + */
18659 +static int
18660 +mptsas_get_lun_number(MPT_ADAPTER *ioc, u8 channel, u8 id, int *lun)
18661  {
18662 -       ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
18663 -       if (reply != NULL) {
18664 -               ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
18665 -               memcpy(ioc->sas_mgmt.reply, reply,
18666 -                   min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
18667 -       }
18668 -       complete(&ioc->sas_mgmt.done);
18669 -       return 1;
18670 -}
18671 +       INTERNAL_CMD    *iocmd;
18672 +       struct scsi_lun *lun_data;
18673 +       dma_addr_t      lun_data_dma;
18674 +       u32             lun_data_len;
18675 +       u8              *data;
18676 +       MPT_SCSI_HOST   *hd;
18677 +       int             rc;
18678 +       u32             length, num_luns;
18679  
18680 -static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
18681 -{
18682 -       MPT_ADAPTER *ioc = phy_to_ioc(phy);
18683 -       SasIoUnitControlRequest_t *req;
18684 -       SasIoUnitControlReply_t *reply;
18685 -       MPT_FRAME_HDR *mf;
18686 -       MPIHeader_t *hdr;
18687 -       unsigned long timeleft;
18688 -       int error = -ERESTARTSYS;
18689 +       iocmd = NULL;
18690 +       hd = shost_priv(ioc->sh);
18691 +       lun_data_len = (255 * sizeof(struct scsi_lun));
18692 +       lun_data = pci_alloc_consistent(ioc->pcidev, lun_data_len,
18693 +           &lun_data_dma);
18694 +       if (!lun_data) {
18695 +               printk(MYIOC_s_ERR_FMT "%s: pci_alloc_consistent(%d) FAILED!\n",
18696 +                   ioc->name, __FUNCTION__, lun_data_len);
18697 +               rc = -ENOMEM;
18698 +               goto out;
18699 +       }
18700  
18701 -       /* FIXME: fusion doesn't allow non-local phy reset */
18702 -       if (!scsi_is_sas_phy_local(phy))
18703 -               return -EINVAL;
18704 +       iocmd = kzalloc(sizeof(INTERNAL_CMD), GFP_KERNEL);
18705 +       if (!iocmd) {
18706 +               printk(MYIOC_s_ERR_FMT "%s: kzalloc(%zd) FAILED!\n",
18707 +                   ioc->name, __FUNCTION__, sizeof(INTERNAL_CMD));
18708 +               rc = -ENOMEM;
18709 +               goto out;
18710 +       }
18711  
18712 -       /* not implemented for expanders */
18713 -       if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
18714 -               return -ENXIO;
18715 +       /*
18716 +        * Report Luns
18717 +        */
18718 +       iocmd->cmd = REPORT_LUNS;
18719 +       iocmd->data_dma = lun_data_dma;
18720 +       iocmd->data = (u8 *)lun_data;
18721 +       iocmd->size = lun_data_len;
18722 +       iocmd->channel = channel;
18723 +       iocmd->id = id;
18724  
18725 -       if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
18726 +       if ((rc = mptscsih_do_cmd(hd, iocmd)) < 0) {
18727 +               printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
18728 +                   "report_luns failed due to rc=0x%x\n", ioc->name,
18729 +                   __FUNCTION__, channel, id, rc);
18730                 goto out;
18731 +       }
18732  
18733 -       mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
18734 -       if (!mf) {
18735 -               error = -ENOMEM;
18736 -               goto out_unlock;
18737 +       if (rc != MPT_SCANDV_GOOD) {
18738 +               printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
18739 +                   "report_luns failed due to rc=0x%x\n", ioc->name,
18740 +                   __FUNCTION__, channel, id, rc);
18741 +               rc = -rc;
18742 +               goto out;
18743         }
18744  
18745 -       hdr = (MPIHeader_t *) mf;
18746 -       req = (SasIoUnitControlRequest_t *)mf;
18747 -       memset(req, 0, sizeof(SasIoUnitControlRequest_t));
18748 -       req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
18749 -       req->MsgContext = hdr->MsgContext;
18750 -       req->Operation = hard_reset ?
18751 -               MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
18752 -       req->PhyNum = phy->identify.phy_identifier;
18753 +       data = (u8 *)lun_data;
18754 +       length = ((data[0] << 24) | (data[1] << 16) |
18755 +           (data[2] << 8) | (data[3] << 0));
18756  
18757 -       mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
18758 +       num_luns = (length / sizeof(struct scsi_lun));
18759 +       if (!num_luns)
18760 +               goto out;
18761 +       /* return 1st lun in the list */
18762 +       *lun = scsilun_to_int(&lun_data[1]);
18763  
18764 -       timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
18765 -                       10 * HZ);
18766 -       if (!timeleft) {
18767 -               /* On timeout reset the board */
18768 -               mpt_free_msg_frame(ioc, mf);
18769 -               mpt_HardResetHandler(ioc, CAN_SLEEP);
18770 -               error = -ETIMEDOUT;
18771 -               goto out_unlock;
18772 +#if 0
18773 +       /* some debugging, left commented out */
18774 +       {
18775 +               struct scsi_lun *lunp;
18776 +               for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++)
18777 +                       printk("%x\n", scsilun_to_int(lunp));
18778         }
18779 +#endif
18780  
18781 -       /* a reply frame is expected */
18782 -       if ((ioc->sas_mgmt.status &
18783 -           MPT_IOCTL_STATUS_RF_VALID) == 0) {
18784 -               error = -ENXIO;
18785 -               goto out_unlock;
18786 -       }
18787 + out:
18788 +       if (lun_data)
18789 +               pci_free_consistent(ioc->pcidev, lun_data_len, lun_data,
18790 +                   lun_data_dma);
18791 +       kfree(iocmd);
18792 +       return rc;
18793 +}
18794  
18795 -       /* process the completed Reply Message Frame */
18796 -       reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
18797 -       if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
18798 -               printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
18799 -                   ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
18800 -               error = -ENXIO;
18801 -               goto out_unlock;
18802 +/**
18803 + * enum device_state -
18804 + * @DEVICE_RETRY: need to retry the TUR
18805 + * @DEVICE_ERROR: TUR return error, don't add device
18806 + * @DEVICE_READY: device can be added
18807 + *
18808 + */
18809 +enum device_state{
18810 +       DEVICE_RETRY,
18811 +       DEVICE_ERROR,
18812 +       DEVICE_READY,
18813 +};
18814 +
18815 +/**
18816 + * mptsas_test_unit_ready -
18817 + * @ioc: Pointer to MPT_ADAPTER structure
18818 + * @channel:
18819 + * @id:
18820 + * @count: retry count
18821 + *
18822 + */
18823 +enum device_state
18824 +mptsas_test_unit_ready(MPT_ADAPTER *ioc, u8 channel, u8 id, u16 count)
18825 +{
18826 +       INTERNAL_CMD    *iocmd;
18827 +       MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
18828 +       enum device_state       state;
18829 +       int                     rc;
18830 +       u8              skey, asc, ascq;
18831 +       u8              retry_ua;
18832 +
18833 +       if (count >= mpt_cmd_retry_count)
18834 +               return DEVICE_ERROR;
18835 +
18836 +       retry_ua = 0;
18837 +       iocmd = kzalloc(sizeof(INTERNAL_CMD), GFP_KERNEL);
18838 +       if (!iocmd) {
18839 +               printk(MYIOC_s_ERR_FMT "%s: kzalloc(%zd) FAILED!\n",
18840 +               __FUNCTION__, ioc->name, sizeof(INTERNAL_CMD));
18841 +               return DEVICE_ERROR;
18842 +       }
18843 +
18844 +       state = DEVICE_ERROR;
18845 +       iocmd->cmd = TEST_UNIT_READY;
18846 +       iocmd->data_dma = -1;
18847 +       iocmd->data = NULL;
18848 +
18849 +       if (mptscsih_is_phys_disk(ioc, channel, id)) {
18850 +               iocmd->flags |= MPT_ICFLAG_PHYS_DISK;
18851 +               iocmd->physDiskNum = mptscsih_raid_id_to_num(ioc, channel, id);
18852 +               iocmd->id = id;
18853 +       }
18854 +       iocmd->channel = channel;
18855 +       iocmd->id = id;
18856 +
18857 + retry:
18858 +       devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_channel=%d "
18859 +           "fw_id=%d retry=%d\n", ioc->name, __FUNCTION__, channel, id, count));
18860 +       rc = mptscsih_do_cmd(hd, iocmd);
18861 +       devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rc=0x%02x\n",
18862 +           ioc->name, __FUNCTION__, rc));
18863 +       if (rc < 0) {
18864 +               printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
18865 +                   "tur failed due to timeout\n", ioc->name,
18866 +                   __FUNCTION__, channel, id);
18867 +               goto tur_done;
18868 +       }
18869 +
18870 +       switch(rc) {
18871 +       case MPT_SCANDV_GOOD:
18872 +               state = DEVICE_READY;
18873 +               goto tur_done;
18874 +       case MPT_SCANDV_BUSY:
18875 +               devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: "
18876 +                   "fw_channel=%d fw_id=%d : device busy\n",
18877 +                   ioc->name, __FUNCTION__, channel, id));
18878 +               state = DEVICE_RETRY;
18879 +               break;
18880 +       case MPT_SCANDV_DID_RESET:
18881 +               devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: "
18882 +                   "fw_channel=%d fw_id=%d : did reset\n",
18883 +                   ioc->name, __FUNCTION__, channel, id));
18884 +               state = DEVICE_RETRY;
18885 +               break;
18886 +       case MPT_SCANDV_SENSE:
18887 +               skey = ioc->internal_cmds.sense[2] & 0x0F;
18888 +               asc = ioc->internal_cmds.sense[12];
18889 +               ascq = ioc->internal_cmds.sense[13];
18890 +
18891 +               devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: "
18892 +                   "fw_channel=%d fw_id=%d : [sense_key,asc,"
18893 +                   "ascq]: [0x%02x,0x%02x,0x%02x]\n", ioc->name,
18894 +                    __FUNCTION__, channel, id, skey, asc, ascq));
18895 +
18896 +               if (skey == UNIT_ATTENTION) {
18897 +                       if (!retry_ua) {
18898 +                               retry_ua++;
18899 +                               goto retry;
18900 +                       }
18901 +               } else if (skey == NOT_READY) {
18902 +                       /*
18903 +                        * medium isn't present
18904 +                        */
18905 +                       if (asc == 0x3a) {
18906 +                               state = DEVICE_READY;
18907 +                               goto tur_done;
18908 +                       }
18909 +                       /*
18910 +                        * LU becoming ready, or
18911 +                        * LU hasn't self-configured yet
18912 +                        */
18913 +                       if ((asc == 0x04 && ascq == 0x01) ||
18914 +                           (asc == 0x04 && ascq == 0x11) ||
18915 +                           asc == 0x3e) {
18916 +                               state = DEVICE_RETRY;
18917 +                               break;
18918 +                       }
18919 +               } else if (skey == ILLEGAL_REQUEST) {
18920 +               /* try sending a tur to a non-zero lun number */
18921 +                       if (!iocmd->lun && !mptsas_get_lun_number(ioc,
18922 +                           channel, id, &iocmd->lun) && iocmd->lun)
18923 +                               goto retry;
18924 +               }
18925 +               printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d : "
18926 +                   "tur failed due to [sense_key,asc,ascq]: "
18927 +                   "[0x%02x,0x%02x,0x%02x]\n", ioc->name,
18928 +                   __FUNCTION__, channel, id, skey, asc, ascq);
18929 +               goto tur_done;
18930 +       case MPT_SCANDV_SELECTION_TIMEOUT:
18931 +               printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
18932 +                   "tur failed due to no device\n", ioc->name,
18933 +                   __FUNCTION__, channel,
18934 +                   id);
18935 +               goto tur_done;
18936 +       case MPT_SCANDV_SOME_ERROR:
18937 +               printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
18938 +                   "tur failed due to some error\n", ioc->name,
18939 +                   __FUNCTION__,
18940 +                   channel, id);
18941 +               goto tur_done;
18942 +       default:
18943 +               printk(MYIOC_s_ERR_FMT
18944 +                   "%s: fw_channel=%d fw_id=%d: tur failed due to "
18945 +                   "unknown rc=0x%02x\n", ioc->name, __FUNCTION__,
18946 +                   channel, id, rc );
18947 +               goto tur_done;
18948 +       }
18949 + tur_done:
18950 +       kfree(iocmd);
18951 +       return state;
18952 +}
18953 +
18954 +/**
18955 + *     mptsas_issue_tlr - Enabling Transport Layer Retries
18956 + *     @hd:
18957 + *     @sdev:
18958 + *
18959 + **/
18960 +static void
18961 +mptsas_issue_tlr(MPT_SCSI_HOST *hd, struct scsi_device *sdev)
18962 +{
18963 +       INTERNAL_CMD    *iocmd;
18964 +       VirtDevice      *vdevice = sdev->hostdata;
18965 +       u8              retries;
18966 +       u8              rc;
18967 +       MPT_ADAPTER *ioc = hd->ioc;
18968 +
18969 +       if ( sdev->inquiry[8]  == 'H' &&
18970 +            sdev->inquiry[9]  == 'P' &&
18971 +            sdev->inquiry[10] == ' ' &&
18972 +            sdev->inquiry[11] == ' ' &&
18973 +            sdev->inquiry[12] == ' ' &&
18974 +            sdev->inquiry[13] == ' ' &&
18975 +            sdev->inquiry[14] == ' ' &&
18976 +            sdev->inquiry[15] == ' ' ) {
18977 +
18978 +               iocmd = kzalloc(sizeof(INTERNAL_CMD), GFP_KERNEL);
18979 +               if (!iocmd) {
18980 +                       printk(MYIOC_s_ERR_FMT "%s: kzalloc(%zd) FAILED!\n",
18981 +                       __FUNCTION__, ioc->name, sizeof(INTERNAL_CMD));
18982 +                       return;
18983 +               }
18984 +               iocmd->id = vdevice->vtarget->id;
18985 +               iocmd->channel = vdevice->vtarget->channel;
18986 +               iocmd->lun = vdevice->lun;
18987 +               iocmd->physDiskNum = -1;
18988 +               iocmd->cmd = TRANSPORT_LAYER_RETRIES;
18989 +               iocmd->data_dma = -1;
18990 +               for (retries = 0, rc = -1; retries < 3; retries++) {
18991 +                       rc = mptscsih_do_cmd(hd, iocmd);
18992 +                       if (!rc)
18993 +                               break;
18994 +               }
18995 +               if (rc != 0)
18996 +                       printk(MYIOC_s_DEBUG_FMT "unable to enable TLR on"
18997 +                          " fw_channel %d, fw_id %d, lun=%d\n",
18998 +                          ioc->name, vdevice->vtarget->channel,
18999 +                          vdevice->vtarget->id, sdev->lun);
19000 +               kfree(iocmd);
19001         }
19002 +}
19003  
19004 -       error = 0;
19005 +/**
19006 + *     mptsas_slave_configure -
19007 + *     @sdev:
19008 + *
19009 + **/
19010 +static int
19011 +mptsas_slave_configure(struct scsi_device *sdev)
19012 +{
19013 +       struct Scsi_Host        *host = sdev->host;
19014 +       MPT_SCSI_HOST           *hd = shost_priv(host);
19015 +       MPT_ADAPTER             *ioc = hd->ioc;
19016 +       VirtDevice              *vdevice = sdev->hostdata;
19017 +
19018 +
19019 +       if (vdevice->vtarget->deleted) {
19020 +               sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
19021 +               vdevice->vtarget->deleted = 0;
19022 +       }
19023  
19024 - out_unlock:
19025 -       mutex_unlock(&ioc->sas_mgmt.mutex);
19026 +       /*
19027 +        * RAID volumes placed beyond the last expected port.
19028 +        * Ignore sending sas mode pages in that case..
19029 +        */
19030 +       if (sdev->channel == MPTSAS_RAID_CHANNEL) {
19031 +               mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev));
19032 +               goto out;
19033 +       }
19034 +
19035 +       sas_read_port_mode_page(sdev);
19036 +
19037 +       mptsas_add_device_component_starget(ioc, scsi_target(sdev));
19038 +
19039 +       if (sdev->type == TYPE_TAPE &&
19040 +           (ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_TLR ))
19041 +               mptsas_issue_tlr(hd, sdev);
19042   out:
19043 -       return error;
19044 +
19045 +       return mptscsih_slave_configure(sdev);
19046  }
19047  
19048 +/**
19049 + *     mptsas_target_alloc -
19050 + *     @starget:
19051 + *
19052 + **/
19053  static int
19054 -mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
19055 +mptsas_target_alloc(struct scsi_target *starget)
19056  {
19057 -       MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
19058 -       int i, error;
19059 -       struct mptsas_portinfo *p;
19060 -       struct mptsas_enclosure enclosure_info;
19061 -       u64 enclosure_handle;
19062 +       struct Scsi_Host *host = dev_to_shost(&starget->dev);
19063 +       MPT_SCSI_HOST           *hd = shost_priv(host);
19064 +       VirtTarget              *vtarget;
19065 +       u8                      id, channel;
19066 +       struct sas_rphy         *rphy;
19067 +       struct mptsas_portinfo  *p;
19068 +       int                      i;
19069 +       MPT_ADAPTER             *ioc = hd->ioc;
19070 +
19071 +       vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
19072 +       if (!vtarget)
19073 +               return -ENOMEM;
19074 +
19075 +       vtarget->starget = starget;
19076 +       vtarget->ioc_id = ioc->id;
19077 +       vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
19078 +       id = starget->id;
19079 +       channel = 0;
19080 +
19081 +       /*
19082 +        * RAID volumes placed beyond the last expected port.
19083 +        */
19084 +       if (starget->channel == MPTSAS_RAID_CHANNEL) {
19085 +               if (!ioc->raid_data.pIocPg2) {
19086 +                       kfree(vtarget);
19087 +                       return -ENXIO;
19088 +               }
19089 +               for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
19090 +                       if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
19091 +                               channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
19092 +               vtarget->raidVolume = 1;
19093 +               goto out;
19094 +       }
19095  
19096 +       rphy = dev_to_rphy(starget->dev.parent);
19097         mutex_lock(&ioc->sas_topology_mutex);
19098         list_for_each_entry(p, &ioc->sas_topology, list) {
19099                 for (i = 0; i < p->num_phys; i++) {
19100 -                       if (p->phy_info[i].attached.sas_address ==
19101 -                           rphy->identify.sas_address) {
19102 -                               enclosure_handle = p->phy_info[i].
19103 -                                       attached.handle_enclosure;
19104 -                               goto found_info;
19105 +                       if (p->phy_info[i].attached.sas_address !=
19106 +                           rphy->identify.sas_address)
19107 +                               continue;
19108 +                       id = p->phy_info[i].attached.id;
19109 +                       channel = p->phy_info[i].attached.channel;
19110 +                       mptsas_set_starget(&p->phy_info[i], starget);
19111 +
19112 +                       starget_printk(KERN_INFO, starget, MYIOC_s_FMT
19113 +                       "add device: fw_channel %d, fw_id %d, phy %d, sas_addr 0x%llx\n",
19114 +                       ioc->name, p->phy_info[i].attached.channel,
19115 +                       p->phy_info[i].attached.id, p->phy_info[i].attached.phy_id,
19116 +                       (unsigned long long)p->phy_info[i].attached.sas_address);
19117 +
19118 +                       /*
19119 +                        * Exposing hidden raid components
19120 +                        */
19121 +                       if (mptscsih_is_phys_disk(ioc, channel, id)) {
19122 +                               id = mptscsih_raid_id_to_num(ioc,
19123 +                                   channel, id);
19124 +                               vtarget->tflags |=
19125 +                                   MPT_TARGET_FLAGS_RAID_COMPONENT;
19126 +                               p->phy_info[i].attached.phys_disk_num = id;
19127                         }
19128 +                       mutex_unlock(&ioc->sas_topology_mutex);
19129 +                       goto out;
19130                 }
19131         }
19132         mutex_unlock(&ioc->sas_topology_mutex);
19133 +
19134 +       kfree(vtarget);
19135         return -ENXIO;
19136  
19137 - found_info:
19138 -       mutex_unlock(&ioc->sas_topology_mutex);
19139 -       memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
19140 -       error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
19141 -                       (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
19142 -                        MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
19143 -       if (!error)
19144 -               *identifier = enclosure_info.enclosure_logical_id;
19145 -       return error;
19146 + out:
19147 +       vtarget->id = id;
19148 +       vtarget->channel = channel;
19149 +       starget->hostdata = vtarget;
19150 +       return 0;
19151  }
19152  
19153 -static int
19154 -mptsas_get_bay_identifier(struct sas_rphy *rphy)
19155 +/**
19156 + *     mptsas_target_destroy -
19157 + *     @starget:
19158 + *
19159 + **/
19160 +static void
19161 +mptsas_target_destroy(struct scsi_target *starget)
19162  {
19163 -       MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
19164 -       struct mptsas_portinfo *p;
19165 -       int i, rc;
19166 +       struct Scsi_Host *host = dev_to_shost(&starget->dev);
19167 +       MPT_SCSI_HOST           *hd = shost_priv(host);
19168 +       struct sas_rphy         *rphy;
19169 +       struct mptsas_portinfo  *p;
19170 +       int                      i;
19171 +       MPT_ADAPTER             *ioc = hd->ioc;
19172  
19173 -       mutex_lock(&ioc->sas_topology_mutex);
19174 +       if (!starget->hostdata)
19175 +               return;
19176 +
19177 +       mptsas_del_device_component_by_os(ioc, starget->channel,
19178 +           starget->id);
19179 +
19180 +       if (starget->channel == MPTSAS_RAID_CHANNEL)
19181 +               goto out;
19182 +
19183 +       rphy = dev_to_rphy(starget->dev.parent);
19184         list_for_each_entry(p, &ioc->sas_topology, list) {
19185                 for (i = 0; i < p->num_phys; i++) {
19186 -                       if (p->phy_info[i].attached.sas_address ==
19187 -                           rphy->identify.sas_address) {
19188 -                               rc = p->phy_info[i].attached.slot;
19189 -                               goto out;
19190 -                       }
19191 +                       if (p->phy_info[i].attached.sas_address !=
19192 +                                       rphy->identify.sas_address)
19193 +                               continue;
19194 +
19195 +                       starget_printk(KERN_INFO, starget, MYIOC_s_FMT
19196 +                       "delete device: fw_channel %d, fw_id %d, phy %d, "
19197 +                       "sas_addr 0x%llx\n", ioc->name,
19198 +                       p->phy_info[i].attached.channel,
19199 +                       p->phy_info[i].attached.id,
19200 +                       p->phy_info[i].attached.phy_id, (unsigned long long)
19201 +                       p->phy_info[i].attached.sas_address);
19202 +
19203 +                       mptsas_port_delete(ioc, p->phy_info[i].port_details);
19204                 }
19205         }
19206 -       rc = -ENXIO;
19207 +
19208   out:
19209 -       mutex_unlock(&ioc->sas_topology_mutex);
19210 -       return rc;
19211 +       kfree(starget->hostdata);
19212 +       starget->hostdata = NULL;
19213  }
19214  
19215 -static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
19216 -                             struct request *req)
19217 +/**
19218 + *     mptsas_slave_alloc -
19219 + *     @sdev:
19220 + *
19221 + **/
19222 +static int
19223 +mptsas_slave_alloc(struct scsi_device *sdev)
19224  {
19225 -       MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
19226 -       MPT_FRAME_HDR *mf;
19227 -       SmpPassthroughRequest_t *smpreq;
19228 -       struct request *rsp = req->next_rq;
19229 -       int ret;
19230 -       int flagsLength;
19231 -       unsigned long timeleft;
19232 -       char *psge;
19233 -       dma_addr_t dma_addr_in = 0;
19234 -       dma_addr_t dma_addr_out = 0;
19235 -       u64 sas_address = 0;
19236 -
19237 -       if (!rsp) {
19238 -               printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
19239 -                   ioc->name, __func__);
19240 -               return -EINVAL;
19241 -       }
19242 +       struct Scsi_Host        *host = sdev->host;
19243 +       MPT_SCSI_HOST           *hd = shost_priv(host);
19244 +       struct sas_rphy         *rphy;
19245 +       struct mptsas_portinfo  *p;
19246 +       VirtDevice              *vdevice;
19247 +       struct scsi_target      *starget;
19248 +       int                     i;
19249 +       MPT_ADAPTER             *ioc = hd->ioc;
19250  
19251 -       /* do we need to support multiple segments? */
19252 -       if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
19253 -               printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
19254 -                   ioc->name, __func__, req->bio->bi_vcnt, req->data_len,
19255 -                   rsp->bio->bi_vcnt, rsp->data_len);
19256 -               return -EINVAL;
19257 +       vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
19258 +       if (!vdevice) {
19259 +               printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
19260 +                   ioc->name, sizeof(VirtDevice));
19261 +               return -ENOMEM;
19262         }
19263 +       starget = scsi_target(sdev);
19264 +       vdevice->vtarget = starget->hostdata;
19265  
19266 -       ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
19267 -       if (ret)
19268 +       /*
19269 +        * RAID volumes placed beyond the last expected port.
19270 +        */
19271 +       if (sdev->channel == MPTSAS_RAID_CHANNEL)
19272                 goto out;
19273  
19274 -       mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
19275 -       if (!mf) {
19276 -               ret = -ENOMEM;
19277 -               goto out_unlock;
19278 +       rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
19279 +       mutex_lock(&ioc->sas_topology_mutex);
19280 +       list_for_each_entry(p, &ioc->sas_topology, list) {
19281 +               for (i = 0; i < p->num_phys; i++) {
19282 +                       if (p->phy_info[i].attached.sas_address !=
19283 +                                       rphy->identify.sas_address)
19284 +                               continue;
19285 +                       vdevice->lun = sdev->lun;
19286 +                       /*
19287 +                        * Exposing hidden raid components
19288 +                        */
19289 +                       if (mptscsih_is_phys_disk(ioc,
19290 +                           p->phy_info[i].attached.channel,
19291 +                           p->phy_info[i].attached.id))
19292 +                               sdev->no_uld_attach = 1;
19293 +                       mutex_unlock(&ioc->sas_topology_mutex);
19294 +                       goto out;
19295 +               }
19296         }
19297 +       mutex_unlock(&ioc->sas_topology_mutex);
19298  
19299 -       smpreq = (SmpPassthroughRequest_t *)mf;
19300 -       memset(smpreq, 0, sizeof(*smpreq));
19301 +       kfree(vdevice);
19302 +       return -ENXIO;
19303  
19304 -       smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);
19305 -       smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
19306 + out:
19307 +       vdevice->vtarget->num_luns++;
19308 +       sdev->hostdata = vdevice;
19309 +       return 0;
19310 +}
19311  
19312 -       if (rphy)
19313 -               sas_address = rphy->identify.sas_address;
19314 -       else {
19315 -               struct mptsas_portinfo *port_info;
19316 +/**
19317 + *     mptsas_qcmd -
19318 + *     @SCpnt:
19319 + *     @done:
19320 + *
19321 + **/
19322 +static int
19323 +mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
19324 +{
19325 +       MPT_SCSI_HOST   *hd;
19326 +       MPT_ADAPTER     *ioc;
19327 +       VirtDevice      *vdevice = SCpnt->device->hostdata;
19328  
19329 -               mutex_lock(&ioc->sas_topology_mutex);
19330 -               port_info = mptsas_get_hba_portinfo(ioc);
19331 -               if (port_info && port_info->phy_info)
19332 -                       sas_address =
19333 -                               port_info->phy_info[0].phy->identify.sas_address;
19334 -               mutex_unlock(&ioc->sas_topology_mutex);
19335 +       if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
19336 +               SCpnt->result = DID_NO_CONNECT << 16;
19337 +               done(SCpnt);
19338 +               return 0;
19339         }
19340  
19341 -       *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
19342 +       hd = shost_priv(SCpnt->device->host);
19343 +       ioc = hd->ioc;
19344  
19345 -       psge = (char *)
19346 -               (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
19347 +       if (ioc->sas_discovery_quiesce_io)
19348 +               return SCSI_MLQUEUE_HOST_BUSY;
19349  
19350 -       /* request */
19351 -       flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
19352 -                      MPI_SGE_FLAGS_END_OF_BUFFER |
19353 -                      MPI_SGE_FLAGS_DIRECTION |
19354 -                      mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT;
19355 -       flagsLength |= (req->data_len - 4);
19356 -
19357 -       dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
19358 -                                     req->data_len, PCI_DMA_BIDIRECTIONAL);
19359 -       if (!dma_addr_out)
19360 -               goto put_mf;
19361 -       mpt_add_sge(psge, flagsLength, dma_addr_out);
19362 -       psge += (sizeof(u32) + sizeof(dma_addr_t));
19363 -
19364 -       /* response */
19365 -       flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
19366 -       flagsLength |= rsp->data_len + 4;
19367 -       dma_addr_in =  pci_map_single(ioc->pcidev, bio_data(rsp->bio),
19368 -                                     rsp->data_len, PCI_DMA_BIDIRECTIONAL);
19369 -       if (!dma_addr_in)
19370 -               goto unmap;
19371 -       mpt_add_sge(psge, flagsLength, dma_addr_in);
19372 +//     scsi_print_command(SCpnt);
19373 +       return mptscsih_qcmd(SCpnt,done);
19374 +}
19375  
19376 -       mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
19377  
19378 -       timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
19379 -       if (!timeleft) {
19380 -               printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
19381 -               /* On timeout reset the board */
19382 -               mpt_HardResetHandler(ioc, CAN_SLEEP);
19383 -               ret = -ETIMEDOUT;
19384 -               goto unmap;
19385 -       }
19386 -       mf = NULL;
19387 -
19388 -       if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {
19389 -               SmpPassthroughReply_t *smprep;
19390 -
19391 -               smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
19392 -               memcpy(req->sense, smprep, sizeof(*smprep));
19393 -               req->sense_len = sizeof(*smprep);
19394 -               req->data_len = 0;
19395 -               rsp->data_len -= smprep->ResponseDataLength;
19396 -       } else {
19397 -               printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
19398 -                   ioc->name, __func__);
19399 -               ret = -ENXIO;
19400 -       }
19401 -unmap:
19402 -       if (dma_addr_out)
19403 -               pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
19404 -                                PCI_DMA_BIDIRECTIONAL);
19405 -       if (dma_addr_in)
19406 -               pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,
19407 -                                PCI_DMA_BIDIRECTIONAL);
19408 -put_mf:
19409 -       if (mf)
19410 +static struct scsi_host_template mptsas_driver_template = {
19411 +       .module                         = THIS_MODULE,
19412 +       .proc_name                      = "mptsas",
19413 +       .proc_info                      = mptscsih_proc_info,
19414 +       .name                           = "MPT SPI Host",
19415 +       .info                           = mptscsih_info,
19416 +       .queuecommand                   = mptsas_qcmd,
19417 +       .target_alloc                   = mptsas_target_alloc,
19418 +       .slave_alloc                    = mptsas_slave_alloc,
19419 +       .slave_configure                = mptsas_slave_configure,
19420 +       .target_destroy                 = mptsas_target_destroy,
19421 +       .slave_destroy                  = mptscsih_slave_destroy,
19422 +       .change_queue_depth             = mptscsih_change_queue_depth,
19423 +       .eh_abort_handler               = mptscsih_abort,
19424 +       .eh_device_reset_handler        = mptscsih_dev_reset,
19425 +       .eh_bus_reset_handler           = mptscsih_bus_reset,
19426 +       .eh_host_reset_handler          = mptscsih_host_reset,
19427 +       .bios_param                     = mptscsih_bios_param,
19428 +       .can_queue                      = MPT_FC_CAN_QUEUE,
19429 +       .this_id                        = -1,
19430 +       .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
19431 +       .max_sectors                    = 8192,
19432 +       .cmd_per_lun                    = 7,
19433 +       .use_clustering                 = ENABLE_CLUSTERING,
19434 +       .shost_attrs                    = mptscsih_host_attrs,
19435 +};
19436 +
19437 +/**
19438 + *     mptsas_get_linkerrors -
19439 + *     @phy:
19440 + *
19441 + **/
19442 +static int mptsas_get_linkerrors(struct sas_phy *phy)
19443 +{
19444 +       MPT_ADAPTER *ioc = phy_to_ioc(phy);
19445 +       ConfigExtendedPageHeader_t hdr;
19446 +       CONFIGPARMS cfg;
19447 +       SasPhyPage1_t *buffer;
19448 +       dma_addr_t dma_handle;
19449 +       int error;
19450 +
19451 +       /* FIXME: only have link errors on local phys */
19452 +       if (!scsi_is_sas_phy_local(phy))
19453 +               return -EINVAL;
19454 +
19455 +       hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
19456 +       hdr.ExtPageLength = 0;
19457 +       hdr.PageNumber = 1 /* page number 1*/;
19458 +       hdr.Reserved1 = 0;
19459 +       hdr.Reserved2 = 0;
19460 +       hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
19461 +       hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
19462 +
19463 +       cfg.cfghdr.ehdr = &hdr;
19464 +       cfg.physAddr = -1;
19465 +       cfg.pageAddr = phy->identify.phy_identifier;
19466 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
19467 +       cfg.dir = 0;    /* read */
19468 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
19469 +
19470 +       error = mpt_config(ioc, &cfg);
19471 +       if (error)
19472 +               return error;
19473 +       if (!hdr.ExtPageLength)
19474 +               return -ENXIO;
19475 +
19476 +       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
19477 +                                     &dma_handle);
19478 +       if (!buffer)
19479 +               return -ENOMEM;
19480 +
19481 +       cfg.physAddr = dma_handle;
19482 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
19483 +
19484 +       error = mpt_config(ioc, &cfg);
19485 +       if (error)
19486 +               goto out_free_consistent;
19487 +
19488 +       mptsas_print_phy_pg1(ioc, buffer);
19489 +
19490 +       phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
19491 +       phy->running_disparity_error_count =
19492 +               le32_to_cpu(buffer->RunningDisparityErrorCount);
19493 +       phy->loss_of_dword_sync_count =
19494 +               le32_to_cpu(buffer->LossDwordSynchCount);
19495 +       phy->phy_reset_problem_count =
19496 +               le32_to_cpu(buffer->PhyResetProblemCount);
19497 +
19498 + out_free_consistent:
19499 +       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
19500 +                           buffer, dma_handle);
19501 +       return error;
19502 +}
19503 +
19504 +/**
19505 + *     mptsas_mgmt_done -
19506 + *     @ioc: Pointer to MPT_ADAPTER structure
19507 + *     @req:
19508 + *     @reply:
19509 + *
19510 + **/
19511 +static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
19512 +               MPT_FRAME_HDR *reply)
19513 +{
19514 +       ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
19515 +       if (reply != NULL) {
19516 +               ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
19517 +               memcpy(ioc->sas_mgmt.reply, reply,
19518 +                   min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
19519 +       }
19520 +
19521 +       if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
19522 +               ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING;
19523 +               complete(&ioc->sas_mgmt.done);
19524 +               return 1;
19525 +       }
19526 +       return 0;
19527 +}
19528 +
19529 +/**
19530 + *     mptsas_phy_reset -
19531 + *     @phy:
19532 + *     @hard_reset:
19533 + *
19534 + **/
19535 +static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
19536 +{
19537 +       MPT_ADAPTER *ioc = phy_to_ioc(phy);
19538 +       SasIoUnitControlRequest_t *req;
19539 +       SasIoUnitControlReply_t *reply;
19540 +       MPT_FRAME_HDR *mf;
19541 +       MPIHeader_t *hdr;
19542 +       unsigned long timeleft;
19543 +       int error = -ERESTARTSYS;
19544 +
19545 +       /* FIXME: fusion doesn't allow non-local phy reset */
19546 +       if (!scsi_is_sas_phy_local(phy))
19547 +               return -EINVAL;
19548 +
19549 +       /* not implemented for expanders */
19550 +       if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
19551 +               return -ENXIO;
19552 +
19553 +       if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
19554 +               goto out;
19555 +
19556 +       mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
19557 +       if (!mf) {
19558 +               error = -ENOMEM;
19559 +               goto out_unlock;
19560 +       }
19561 +
19562 +       hdr = (MPIHeader_t *) mf;
19563 +       req = (SasIoUnitControlRequest_t *)mf;
19564 +       memset(req, 0, sizeof(SasIoUnitControlRequest_t));
19565 +       req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
19566 +       req->MsgContext = hdr->MsgContext;
19567 +       req->Operation = hard_reset ?
19568 +               MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
19569 +       req->PhyNum = phy->identify.phy_identifier;
19570 +
19571 +       INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
19572 +       mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
19573 +       timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10*HZ);
19574 +       if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
19575 +               error = -ETIME;
19576                 mpt_free_msg_frame(ioc, mf);
19577 -out_unlock:
19578 +               if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
19579 +                       goto out;
19580 +               if (!timeleft) {
19581 +                       if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
19582 +                               mpt_HardResetHandler(ioc, CAN_SLEEP);
19583 +               }
19584 +               goto out_unlock;
19585 +       }
19586 +
19587 +       /* a reply frame is expected */
19588 +       if ((ioc->sas_mgmt.status &
19589 +           MPT_MGMT_STATUS_RF_VALID) == 0) {
19590 +               error = -ENXIO;
19591 +               goto out_unlock;
19592 +       }
19593 +
19594 +       /* process the completed Reply Message Frame */
19595 +       reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
19596 +       if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
19597 +               printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
19598 +                   ioc->name, __FUNCTION__, reply->IOCStatus, reply->IOCLogInfo);
19599 +               error = -ENXIO;
19600 +               goto out_unlock;
19601 +       }
19602 +
19603 +       error = 0;
19604 +
19605 + out_unlock:
19606 +       CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
19607         mutex_unlock(&ioc->sas_mgmt.mutex);
19608 -out:
19609 -       return ret;
19610 + out:
19611 +       return error;
19612 +}
19613 +
19614 +/**
19615 + *     mptsas_get_enclosure_identifier -
19616 + *     @rphy:
19617 + *     @identifier:
19618 + *
19619 + **/
19620 +static int
19621 +mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
19622 +{
19623 +       MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
19624 +       int i, error;
19625 +       struct mptsas_portinfo *p;
19626 +       struct mptsas_enclosure enclosure_info;
19627 +       u64 enclosure_handle;
19628 +
19629 +       mutex_lock(&ioc->sas_topology_mutex);
19630 +       list_for_each_entry(p, &ioc->sas_topology, list) {
19631 +               for (i = 0; i < p->num_phys; i++) {
19632 +                       if (p->phy_info[i].attached.sas_address ==
19633 +                           rphy->identify.sas_address) {
19634 +                               enclosure_handle = p->phy_info[i].
19635 +                                       attached.handle_enclosure;
19636 +                               goto found_info;
19637 +                       }
19638 +               }
19639 +       }
19640 +       mutex_unlock(&ioc->sas_topology_mutex);
19641 +       return -ENXIO;
19642 +
19643 + found_info:
19644 +       mutex_unlock(&ioc->sas_topology_mutex);
19645 +       memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
19646 +       error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
19647 +                       (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
19648 +                        MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
19649 +                        enclosure_handle);
19650 +       if (!error)
19651 +               *identifier = enclosure_info.enclosure_logical_id;
19652 +       return error;
19653 +}
19654 +
19655 +/**
19656 + *     mptsas_get_bay_identifier -
19657 + *     @rphy:
19658 + *
19659 + **/
19660 +static int
19661 +mptsas_get_bay_identifier(struct sas_rphy *rphy)
19662 +{
19663 +       MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
19664 +       struct mptsas_portinfo *p;
19665 +       int i, rc;
19666 +
19667 +       mutex_lock(&ioc->sas_topology_mutex);
19668 +       list_for_each_entry(p, &ioc->sas_topology, list) {
19669 +               for (i = 0; i < p->num_phys; i++) {
19670 +                       if (p->phy_info[i].attached.sas_address ==
19671 +                           rphy->identify.sas_address) {
19672 +                               rc = p->phy_info[i].attached.slot;
19673 +                               goto out;
19674 +                       }
19675 +               }
19676 +       }
19677 +       rc = -ENXIO;
19678 + out:
19679 +       mutex_unlock(&ioc->sas_topology_mutex);
19680 +       return rc;
19681  }
19682  
19683  static struct sas_function_template mptsas_transport_functions = {
19684 @@ -1385,11 +2280,16 @@ static struct sas_function_template mpts
19685         .get_enclosure_identifier = mptsas_get_enclosure_identifier,
19686         .get_bay_identifier     = mptsas_get_bay_identifier,
19687         .phy_reset              = mptsas_phy_reset,
19688 -       .smp_handler            = mptsas_smp_handler,
19689  };
19690  
19691  static struct scsi_transport_template *mptsas_transport_template;
19692  
19693 +/**
19694 + *     mptsas_sas_io_unit_pg0 -
19695 + *     @ioc: Pointer to MPT_ADAPTER structure
19696 + *     @port_info:
19697 + *
19698 + **/
19699  static int
19700  mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
19701  {
19702 @@ -1412,7 +2312,7 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc,
19703         cfg.pageAddr = 0;
19704         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
19705         cfg.dir = 0;    /* read */
19706 -       cfg.timeout = 10;
19707 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
19708  
19709         error = mpt_config(ioc, &cfg);
19710         if (error)
19711 @@ -1438,7 +2338,7 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc,
19712  
19713         port_info->num_phys = buffer->NumPhys;
19714         port_info->phy_info = kcalloc(port_info->num_phys,
19715 -               sizeof(*port_info->phy_info),GFP_KERNEL);
19716 +               sizeof(struct mptsas_phyinfo),GFP_KERNEL);
19717         if (!port_info->phy_info) {
19718                 error = -ENOMEM;
19719                 goto out_free_consistent;
19720 @@ -1459,6 +2359,8 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc,
19721                 port_info->phy_info[i].portinfo = port_info;
19722                 port_info->phy_info[i].handle =
19723                     le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
19724 +               port_info->phy_info[i].port_flags =
19725 +                   buffer->PhyData[i].PortFlags;
19726         }
19727  
19728   out_free_consistent:
19729 @@ -1468,6 +2370,11 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc,
19730         return error;
19731  }
19732  
19733 +/**
19734 + *     mptsas_sas_io_unit_pg1 -
19735 + *     @ioc: Pointer to MPT_ADAPTER structure
19736 + *
19737 + **/
19738  static int
19739  mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
19740  {
19741 @@ -1483,11 +2390,11 @@ mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
19742  
19743         cfg.cfghdr.ehdr = &hdr;
19744         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
19745 -       cfg.timeout = 10;
19746         cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
19747         cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
19748         cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
19749         cfg.cfghdr.ehdr->PageNumber = 1;
19750 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
19751  
19752         error = mpt_config(ioc, &cfg);
19753         if (error)
19754 @@ -1525,6 +2432,14 @@ mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
19755         return error;
19756  }
19757  
19758 +/**
19759 + *     mptsas_sas_phy_pg0 -
19760 + *     @ioc: Pointer to MPT_ADAPTER structure
19761 + *     @phy_info:
19762 + *     @form:
19763 + *     @form_specific:
19764 + *
19765 + **/
19766  static int
19767  mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
19768                 u32 form, u32 form_specific)
19769 @@ -1545,12 +2460,12 @@ mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, str
19770  
19771         cfg.cfghdr.ehdr = &hdr;
19772         cfg.dir = 0;    /* read */
19773 -       cfg.timeout = 10;
19774  
19775         /* Get Phy Pg 0 for each Phy. */
19776         cfg.physAddr = -1;
19777         cfg.pageAddr = form + form_specific;
19778         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
19779 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
19780  
19781         error = mpt_config(ioc, &cfg);
19782         if (error)
19783 @@ -1581,6 +2496,8 @@ mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, str
19784         phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
19785         phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
19786         phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
19787 +       phy_info->change_count = buffer->ChangeCount;
19788 +       phy_info->phy_info = le32_to_cpu(buffer->PhyInfo);
19789  
19790   out_free_consistent:
19791         pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
19792 @@ -1589,6 +2506,14 @@ mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, str
19793         return error;
19794  }
19795  
19796 +/**
19797 + *     mptsas_sas_device_pg0 -
19798 + *     @ioc: Pointer to MPT_ADAPTER structure
19799 + *     @device_info:
19800 + *     @form:
19801 + *     @form_specific:
19802 + *
19803 + **/
19804  static int
19805  mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
19806                 u32 form, u32 form_specific)
19807 @@ -1600,10 +2525,6 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, 
19808         __le64 sas_address;
19809         int error=0;
19810  
19811 -       if (ioc->sas_discovery_runtime &&
19812 -               mptsas_is_end_device(device_info))
19813 -                       goto out;
19814 -
19815         hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
19816         hdr.ExtPageLength = 0;
19817         hdr.PageNumber = 0;
19818 @@ -1617,9 +2538,8 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, 
19819         cfg.physAddr = -1;
19820         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
19821         cfg.dir = 0;    /* read */
19822 -       cfg.timeout = 10;
19823 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
19824  
19825 -       memset(device_info, 0, sizeof(struct mptsas_devinfo));
19826         error = mpt_config(ioc, &cfg);
19827         if (error)
19828                 goto out;
19829 @@ -1639,11 +2559,18 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, 
19830         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
19831  
19832         error = mpt_config(ioc, &cfg);
19833 +
19834 +       if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
19835 +               error = -ENODEV;
19836 +               goto out_free_consistent;
19837 +       }
19838 +
19839         if (error)
19840                 goto out_free_consistent;
19841  
19842         mptsas_print_device_pg0(ioc, buffer);
19843  
19844 +       memset(device_info, 0, sizeof(struct mptsas_devinfo));
19845         device_info->handle = le16_to_cpu(buffer->DevHandle);
19846         device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
19847         device_info->handle_enclosure =
19848 @@ -1666,6 +2593,14 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, 
19849         return error;
19850  }
19851  
19852 +/**
19853 + *     mptsas_sas_expander_pg0 -
19854 + *     @ioc: Pointer to MPT_ADAPTER structure
19855 + *     @port_info:
19856 + *     @form:
19857 + *     @form_specific:
19858 + *
19859 + **/
19860  static int
19861  mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
19862                 u32 form, u32 form_specific)
19863 @@ -1675,7 +2610,9 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc
19864         SasExpanderPage0_t *buffer;
19865         dma_addr_t dma_handle;
19866         int i, error;
19867 +       __le64 sas_address;
19868  
19869 +       memset(port_info, 0, sizeof(struct mptsas_portinfo));
19870         hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
19871         hdr.ExtPageLength = 0;
19872         hdr.PageNumber = 0;
19873 @@ -1689,9 +2626,8 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc
19874         cfg.pageAddr = form + form_specific;
19875         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
19876         cfg.dir = 0;    /* read */
19877 -       cfg.timeout = 10;
19878 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
19879  
19880 -       memset(port_info, 0, sizeof(struct mptsas_portinfo));
19881         error = mpt_config(ioc, &cfg);
19882         if (error)
19883                 goto out;
19884 @@ -1712,27 +2648,32 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc
19885         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
19886  
19887         error = mpt_config(ioc, &cfg);
19888 -       if (error)
19889 -               goto out_free_consistent;
19890 -
19891 -       if (!buffer->NumPhys) {
19892 +       if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
19893                 error = -ENODEV;
19894                 goto out_free_consistent;
19895         }
19896  
19897 +       if (error)
19898 +               goto out_free_consistent;
19899 +
19900         /* save config data */
19901 -       port_info->num_phys = buffer->NumPhys;
19902 +       port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
19903         port_info->phy_info = kcalloc(port_info->num_phys,
19904 -               sizeof(*port_info->phy_info),GFP_KERNEL);
19905 +               sizeof(struct mptsas_phyinfo),GFP_KERNEL);
19906         if (!port_info->phy_info) {
19907                 error = -ENOMEM;
19908                 goto out_free_consistent;
19909         }
19910  
19911 +       memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
19912         for (i = 0; i < port_info->num_phys; i++) {
19913                 port_info->phy_info[i].portinfo = port_info;
19914                 port_info->phy_info[i].handle =
19915                     le16_to_cpu(buffer->DevHandle);
19916 +               port_info->phy_info[i].identify.sas_address =
19917 +                   le64_to_cpu(sas_address);
19918 +               port_info->phy_info[i].identify.handle_parent =
19919 +                   le16_to_cpu(buffer->ParentDevHandle);
19920         }
19921  
19922   out_free_consistent:
19923 @@ -1742,6 +2683,14 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc
19924         return error;
19925  }
19926  
19927 +/**
19928 + *     mptsas_sas_expander_pg1 -
19929 + *     @ioc: Pointer to MPT_ADAPTER structure
19930 + *     @phy_info:
19931 + *     @form:
19932 + *     @form_specific:
19933 + *
19934 + **/
19935  static int
19936  mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
19937                 u32 form, u32 form_specific)
19938 @@ -1752,11 +2701,7 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc
19939         dma_addr_t dma_handle;
19940         int error=0;
19941  
19942 -       if (ioc->sas_discovery_runtime &&
19943 -               mptsas_is_end_device(&phy_info->attached))
19944 -                       goto out;
19945 -
19946 -       hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
19947 +       hdr.PageVersion = MPI_SASEXPANDER1_PAGEVERSION;
19948         hdr.ExtPageLength = 0;
19949         hdr.PageNumber = 1;
19950         hdr.Reserved1 = 0;
19951 @@ -1764,1352 +2709,2349 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc
19952         hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
19953         hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
19954  
19955 -       cfg.cfghdr.ehdr = &hdr;
19956 -       cfg.physAddr = -1;
19957 -       cfg.pageAddr = form + form_specific;
19958 +       cfg.cfghdr.ehdr = &hdr;
19959 +       cfg.physAddr = -1;
19960 +       cfg.pageAddr = form + form_specific;
19961 +       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
19962 +       cfg.dir = 0;    /* read */
19963 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
19964 +
19965 +       error = mpt_config(ioc, &cfg);
19966 +       if (error)
19967 +               goto out;
19968 +
19969 +       if (!hdr.ExtPageLength) {
19970 +               error = -ENXIO;
19971 +               goto out;
19972 +       }
19973 +
19974 +       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
19975 +                                     &dma_handle);
19976 +       if (!buffer) {
19977 +               error = -ENOMEM;
19978 +               goto out;
19979 +       }
19980 +
19981 +       cfg.physAddr = dma_handle;
19982 +       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
19983 +
19984 +       error = mpt_config(ioc, &cfg);
19985 +       if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
19986 +               error = -ENODEV;
19987 +               goto out;
19988 +       }
19989 +
19990 +       if (error)
19991 +               goto out_free_consistent;
19992 +
19993 +
19994 +       mptsas_print_expander_pg1(ioc, buffer);
19995 +
19996 +       /* save config data */
19997 +       phy_info->phy_id = buffer->PhyIdentifier;
19998 +       phy_info->port_id = buffer->PhysicalPort;
19999 +       phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
20000 +       phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
20001 +       phy_info->hw_link_rate = buffer->HwLinkRate;
20002 +       phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
20003 +       phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
20004 +       phy_info->change_count = buffer->ChangeCount;
20005 +       phy_info->phy_info = le32_to_cpu(buffer->PhyInfo);
20006 +
20007 + out_free_consistent:
20008 +       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
20009 +                           buffer, dma_handle);
20010 + out:
20011 +       return error;
20012 +}
20013 +
20014 +/**
20015 + *     mptsas_parse_device_info -
20016 + *     @identify:
20017 + *     @device_info:
20018 + *
20019 + **/
20020 +static void
20021 +mptsas_parse_device_info(struct sas_identify *identify,
20022 +               struct mptsas_devinfo *device_info)
20023 +{
20024 +       u16 protocols;
20025 +
20026 +       identify->sas_address = device_info->sas_address;
20027 +       identify->phy_identifier = device_info->phy_id;
20028 +
20029 +       /*
20030 +        * Fill in Phy Initiator Port Protocol.
20031 +        * Bits 6:3, more than one bit can be set, fall through cases.
20032 +        */
20033 +       protocols = device_info->device_info & 0x78;
20034 +       identify->initiator_port_protocols = 0;
20035 +       if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
20036 +               identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
20037 +       if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
20038 +               identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
20039 +       if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
20040 +               identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
20041 +       if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
20042 +               identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
20043 +
20044 +       /*
20045 +        * Fill in Phy Target Port Protocol.
20046 +        * Bits 10:7, more than one bit can be set, fall through cases.
20047 +        */
20048 +       protocols = device_info->device_info & 0x780;
20049 +       identify->target_port_protocols = 0;
20050 +       if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
20051 +               identify->target_port_protocols |= SAS_PROTOCOL_SSP;
20052 +       if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
20053 +               identify->target_port_protocols |= SAS_PROTOCOL_STP;
20054 +       if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
20055 +               identify->target_port_protocols |= SAS_PROTOCOL_SMP;
20056 +       if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
20057 +               identify->target_port_protocols |= SAS_PROTOCOL_SATA;
20058 +
20059 +       /*
20060 +        * Fill in Attached device type.
20061 +        */
20062 +       switch (device_info->device_info &
20063 +                       MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
20064 +       case MPI_SAS_DEVICE_INFO_NO_DEVICE:
20065 +               identify->device_type = SAS_PHY_UNUSED;
20066 +               break;
20067 +       case MPI_SAS_DEVICE_INFO_END_DEVICE:
20068 +               identify->device_type = SAS_END_DEVICE;
20069 +               break;
20070 +       case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
20071 +               identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
20072 +               break;
20073 +       case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
20074 +               identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
20075 +               break;
20076 +       }
20077 +}
20078 +
20079 +/**
20080 + *     mptsas_probe_one_phy -
20081 + *     @dev:
20082 + *     @phy_info:
20083 + *     @local:
20084 + *
20085 + **/
20086 +static int mptsas_probe_one_phy(struct device *dev,
20087 +               struct mptsas_phyinfo *phy_info, int index, int local)
20088 +{
20089 +       MPT_ADAPTER *ioc;
20090 +       struct sas_phy *phy;
20091 +       struct sas_port *port;
20092 +       int error = 0;
20093 +
20094 +       if (!dev) {
20095 +               error = -ENODEV;
20096 +               goto out;
20097 +       }
20098 +
20099 +       if (!phy_info->phy) {
20100 +               phy = sas_phy_alloc(dev, index);
20101 +               if (!phy) {
20102 +                       error = -ENOMEM;
20103 +                       goto out;
20104 +               }
20105 +       } else
20106 +               phy = phy_info->phy;
20107 +
20108 +       mptsas_parse_device_info(&phy->identify, &phy_info->identify);
20109 +
20110 +       /*
20111 +        * Set Negotiated link rate.
20112 +        */
20113 +       switch (phy_info->negotiated_link_rate) {
20114 +       case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
20115 +               phy->negotiated_linkrate = SAS_PHY_DISABLED;
20116 +               break;
20117 +       case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
20118 +               phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
20119 +               break;
20120 +       case MPI_SAS_IOUNIT0_RATE_1_5:
20121 +               phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
20122 +               break;
20123 +       case MPI_SAS_IOUNIT0_RATE_3_0:
20124 +               phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
20125 +               break;
20126 +       case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
20127 +       case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
20128 +       default:
20129 +               phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
20130 +               break;
20131 +       }
20132 +
20133 +       /*
20134 +        * Set Max hardware link rate.
20135 +        */
20136 +       switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
20137 +       case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
20138 +               phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
20139 +               break;
20140 +       case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
20141 +               phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
20142 +               break;
20143 +       default:
20144 +               break;
20145 +       }
20146 +
20147 +       /*
20148 +        * Set Max programmed link rate.
20149 +        */
20150 +       switch (phy_info->programmed_link_rate &
20151 +                       MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
20152 +       case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
20153 +               phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
20154 +               break;
20155 +       case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
20156 +               phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
20157 +               break;
20158 +       default:
20159 +               break;
20160 +       }
20161 +
20162 +       /*
20163 +        * Set Min hardware link rate.
20164 +        */
20165 +       switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
20166 +       case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
20167 +               phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
20168 +               break;
20169 +       case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
20170 +               phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
20171 +               break;
20172 +       default:
20173 +               break;
20174 +       }
20175 +
20176 +       /*
20177 +        * Set Min programmed link rate.
20178 +        */
20179 +       switch (phy_info->programmed_link_rate &
20180 +                       MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
20181 +       case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
20182 +               phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
20183 +               break;
20184 +       case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
20185 +               phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
20186 +               break;
20187 +       default:
20188 +               break;
20189 +       }
20190 +
20191 +       if (!phy_info->phy) {
20192 +
20193 +               error = sas_phy_add(phy);
20194 +               if (error) {
20195 +                       sas_phy_free(phy);
20196 +                       goto out;
20197 +               }
20198 +               phy_info->phy = phy;
20199 +       }
20200 +
20201 +       if (!phy_info->attached.handle ||
20202 +                       !phy_info->port_details)
20203 +               goto out;
20204 +
20205 +       port = mptsas_get_port(phy_info);
20206 +       ioc = phy_to_ioc(phy_info->phy);
20207 +
20208 +       if (phy_info->sas_port_add_phy) {
20209 +               if (!port) {
20210 +                       port = sas_port_alloc_num(dev);
20211 +                       if (!port) {
20212 +                               error = -ENOMEM;
20213 +                               goto out;
20214 +                       }
20215 +                       error = sas_port_add(port);
20216 +                       if (error) {
20217 +                               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20218 +                                       "%s: exit at line=%d\n", ioc->name,
20219 +                                       __FUNCTION__, __LINE__));
20220 +                               goto out;
20221 +                       }
20222 +                       mptsas_set_port(ioc, phy_info, port);
20223 +                       devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev,
20224 +                           MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n",
20225 +                           ioc->name, port->port_identifier,
20226 +                           (unsigned long long)phy_info->attached.sas_address));
20227 +               }
20228 +               sas_port_add_phy(port, phy_info->phy);
20229 +               phy_info->sas_port_add_phy = 0;
20230 +               devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
20231 +                   MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name,
20232 +                    phy_info->phy_id, phy_info->phy));
20233 +       }
20234 +
20235 +       if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
20236 +
20237 +               struct sas_rphy *rphy;
20238 +               struct device *parent;
20239 +               struct sas_identify identify;
20240 +
20241 +               parent = dev->parent->parent;
20242 +
20243 +               if (mptsas_is_end_device(&phy_info->attached) &&
20244 +                   phy_info->attached.handle_parent) {
20245 +                       goto out;
20246 +               }
20247 +
20248 +               mptsas_parse_device_info(&identify, &phy_info->attached);
20249 +               if (scsi_is_host_device(parent)) {
20250 +                       struct mptsas_portinfo *port_info;
20251 +                       int i;
20252 +
20253 +                       port_info = ioc->hba_port_info;
20254 +                       for (i = 0; i < port_info->num_phys; i++)
20255 +                               if (port_info->phy_info[i].identify.sas_address ==
20256 +                                   identify.sas_address) {
20257 +                                       sas_port_mark_backlink(port);
20258 +                                       goto out;
20259 +                       }
20260 +
20261 +               } else if (scsi_is_sas_rphy(parent)) {
20262 +                       struct sas_rphy *parent_rphy = dev_to_rphy(parent);
20263 +                       if (identify.sas_address ==
20264 +                           parent_rphy->identify.sas_address) {
20265 +                               sas_port_mark_backlink(port);
20266 +                               goto out;
20267 +                       }
20268 +               }
20269 +
20270 +               switch (identify.device_type) {
20271 +               case SAS_END_DEVICE:
20272 +                       rphy = sas_end_device_alloc(port);
20273 +                       break;
20274 +               case SAS_EDGE_EXPANDER_DEVICE:
20275 +               case SAS_FANOUT_EXPANDER_DEVICE:
20276 +                       rphy = sas_expander_alloc(port, identify.device_type);
20277 +                       break;
20278 +               default:
20279 +                       rphy = NULL;
20280 +                       break;
20281 +               }
20282 +               if (!rphy) {
20283 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20284 +                               "%s: exit at line=%d\n", ioc->name,
20285 +                               __FUNCTION__, __LINE__));
20286 +                       goto out;
20287 +               }
20288 +
20289 +               rphy->identify = identify;
20290 +               error = sas_rphy_add(rphy);
20291 +               if (error) {
20292 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20293 +                               "%s: exit at line=%d\n", ioc->name,
20294 +                               __FUNCTION__, __LINE__));
20295 +                       sas_rphy_free(rphy);
20296 +                       goto out;
20297 +               }
20298 +               mptsas_set_rphy(ioc, phy_info, rphy);
20299 +       }
20300 +
20301 + out:
20302 +       return error;
20303 +}
20304 +
20305 +/**
20306 + *     mptsas_probe_hba_phys -
20307 + *     @ioc: Pointer to MPT_ADAPTER structure
20308 + *     @handle:
20309 + *
20310 + **/
20311 +static int
20312 +mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
20313 +{
20314 +       struct mptsas_portinfo *port_info, *hba;
20315 +       int error = -ENOMEM, i;
20316 +
20317 +       hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
20318 +       if (! hba)
20319 +               goto out;
20320 +
20321 +       error = mptsas_sas_io_unit_pg0(ioc, hba);
20322 +       if (error)
20323 +               goto out_free_port_info;
20324 +
20325 +       mptsas_sas_io_unit_pg1(ioc);
20326 +       mutex_lock(&ioc->sas_topology_mutex);
20327 +       port_info = ioc->hba_port_info;
20328 +       if (!port_info) {
20329 +               ioc->hba_port_info = port_info = hba;
20330 +               ioc->hba_port_num_phy = port_info->num_phys;
20331 +               list_add_tail(&port_info->list, &ioc->sas_topology);
20332 +       } else {
20333 +               for (i = 0; i < hba->num_phys; i++) {
20334 +                       port_info->phy_info[i].negotiated_link_rate =
20335 +                               hba->phy_info[i].negotiated_link_rate;
20336 +                       port_info->phy_info[i].handle =
20337 +                               hba->phy_info[i].handle;
20338 +                       port_info->phy_info[i].port_id =
20339 +                               hba->phy_info[i].port_id;
20340 +                       port_info->phy_info[i].port_flags =
20341 +                           hba->phy_info[i].port_flags;
20342 +               }
20343 +               kfree(hba->phy_info);
20344 +               kfree(hba);
20345 +               hba = NULL;
20346 +       }
20347 +       mutex_unlock(&ioc->sas_topology_mutex);
20348 +#if defined(CPQ_CIM)
20349 +       ioc->num_ports = port_info->num_phys;
20350 +#endif
20351 +       for (i = 0; i < port_info->num_phys; i++) {
20352 +               mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
20353 +                       (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
20354 +                        MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
20355 +               port_info->phy_info[i].identify.handle =
20356 +                   port_info->phy_info[i].handle;
20357 +               mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
20358 +                       (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
20359 +                        MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
20360 +                        port_info->phy_info[i].identify.handle);
20361 +               if (!ioc->hba_port_sas_addr)
20362 +                       ioc->hba_port_sas_addr =
20363 +                           port_info->phy_info[i].identify.sas_address;
20364 +               port_info->phy_info[i].identify.phy_id =
20365 +                   port_info->phy_info[i].phy_id = i;
20366 +               if (port_info->phy_info[i].attached.handle)
20367 +                       mptsas_sas_device_pg0(ioc,
20368 +                               &port_info->phy_info[i].attached,
20369 +                               (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
20370 +                                MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
20371 +                               port_info->phy_info[i].attached.handle);
20372 +       }
20373 +
20374 +       mptsas_setup_wide_ports(ioc, port_info);
20375 +
20376 +       for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
20377 +               mptsas_probe_one_phy(&ioc->sh->shost_gendev,
20378 +                   &port_info->phy_info[i], ioc->sas_index, 1);
20379 +
20380 +       return 0;
20381 +
20382 + out_free_port_info:
20383 +       kfree(hba);
20384 + out:
20385 +       return error;
20386 +}
20387 +
20388 +/**
20389 + *     mptsas_find_phyinfo_by_sas_address -
20390 + *     @ioc: Pointer to MPT_ADAPTER structure
20391 + *     @sas_address:
20392 + *
20393 + **/
20394 +static struct mptsas_phyinfo *
20395 +mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
20396 +{
20397 +       struct mptsas_portinfo *port_info;
20398 +       struct mptsas_phyinfo *phy_info = NULL;
20399 +       int i;
20400 +
20401 +       mutex_lock(&ioc->sas_topology_mutex);
20402 +       list_for_each_entry(port_info, &ioc->sas_topology, list) {
20403 +               for (i = 0; i < port_info->num_phys; i++) {
20404 +                       if (!mptsas_is_end_device(
20405 +                               &port_info->phy_info[i].attached))
20406 +                               continue;
20407 +                       if (port_info->phy_info[i].attached.sas_address
20408 +                           != sas_address)
20409 +                               continue;
20410 +                       phy_info = &port_info->phy_info[i];
20411 +                       break;
20412 +               }
20413 +       }
20414 +       mutex_unlock(&ioc->sas_topology_mutex);
20415 +       return phy_info;
20416 +}
20417 +
20418 +/**
20419 + *     mptsas_find_phyinfo_by_phys_disk_num -
20420 + *     @ioc: Pointer to MPT_ADAPTER structure
20421 + *     @phys_disk_num:
20422 + *     @channel:
20423 + *     @id:
20424 + *
20425 + **/
20426 +static struct mptsas_phyinfo *
20427 +mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
20428 +       u8 channel, u8 id)
20429 +{
20430 +       struct mptsas_phyinfo *phy_info;
20431 +       struct mptsas_portinfo *port_info;
20432 +       RaidPhysDiskPage1_t *phys_disk = NULL;
20433 +       int num_paths;
20434 +       u64 sas_address = 0;
20435 +       int i;
20436 +
20437 +       phy_info = NULL;
20438 +       if (!ioc->raid_data.pIocPg3)
20439 +               return NULL;
20440 +       /* dual port support */
20441 +       num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
20442 +       if (!num_paths)
20443 +               goto out;
20444 +       phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t,Path) +
20445 +          (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
20446 +       if (!phys_disk)
20447 +               goto out;
20448 +       mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk);
20449 +       for (i = 0; i < num_paths; i++) {
20450 +               if ((phys_disk->Path[i].Flags & 1) != 0)
20451 +                       /* entry no longer valid */
20452 +                       continue;
20453 +               if ((id == phys_disk->Path[i].PhysDiskID) &&
20454 +                   (channel == phys_disk->Path[i].PhysDiskBus)) {
20455 +                       memcpy(&sas_address, &phys_disk->Path[i].WWID,
20456 +                               sizeof(u64));
20457 +                       phy_info = mptsas_find_phyinfo_by_sas_address(ioc, sas_address);
20458 +                       goto out;
20459 +               }
20460 +       }
20461 +
20462 + out:
20463 +       kfree(phys_disk);
20464 +       if (phy_info)
20465 +               return phy_info;
20466 +
20467 +       /*
20468 +        * Extra code to handle RAID0 case, where the sas_address is not updated
20469 +        * in phys_disk_page_1 when hotswapped
20470 +        */
20471 +       mutex_lock(&ioc->sas_topology_mutex);
20472 +       list_for_each_entry(port_info, &ioc->sas_topology, list) {
20473 +               for (i = 0; i < port_info->num_phys && !phy_info; i++) {
20474 +                       if (!mptsas_is_end_device(
20475 +                               &port_info->phy_info[i].attached))
20476 +                               continue;
20477 +                       if (port_info->phy_info[i].attached.phys_disk_num == ~0)
20478 +                               continue;
20479 +                       if (port_info->phy_info[i].attached.phys_disk_num == phys_disk_num &&
20480 +                           port_info->phy_info[i].attached.id == id &&
20481 +                           port_info->phy_info[i].attached.channel == channel)
20482 +                               phy_info = &port_info->phy_info[i];
20483 +               }
20484 +       }
20485 +       mutex_unlock(&ioc->sas_topology_mutex);
20486 +       return phy_info;
20487 +}
20488 +
20489 +/**
20490 + *     mptsas_reprobe_lun -
20491 + *     @sdev:
20492 + *     @data:
20493 + *
20494 + **/
20495 +static void
20496 +mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
20497 +{
20498 +       int rc;
20499 +
20500 +       sdev->no_uld_attach = data ? 1 : 0;
20501 +       rc = scsi_device_reprobe(sdev);
20502 +}
20503 +
20504 +/**
20505 + *     mptsas_reprobe_target -
20506 + *     @starget:
20507 + *     @uld_attach:
20508 + *
20509 + **/
20510 +static void
20511 +mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
20512 +{
20513 +       starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
20514 +                       mptsas_reprobe_lun);
20515 +}
20516 +
20517 +/**
20518 + *     mptsas_adding_inactive_raid_components -
20519 + *     @ioc: Pointer to MPT_ADAPTER structure
20520 + *     @channel:
20521 + *     @id:
20522 + *
20523 + *
20524 + *      TODO: check for hotspares
20525 + **/
20526 +static void
20527 +mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
20528 +{
20529 +       CONFIGPARMS                     cfg;
20530 +       ConfigPageHeader_t              hdr;
20531 +       dma_addr_t                      dma_handle;
20532 +       pRaidVolumePage0_t              buffer = NULL;
20533 +       RaidPhysDiskPage0_t             phys_disk;
20534 +       int                             i;
20535 +       struct mptsas_phyinfo           *phy_info;
20536 +       struct mptsas_devinfo           sas_device;
20537 +
20538 +       memset(&cfg, 0 , sizeof(CONFIGPARMS));
20539 +       memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
20540 +       hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
20541 +       cfg.pageAddr = (channel << 8) + id;
20542 +       cfg.cfghdr.hdr = &hdr;
20543         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
20544 -       cfg.dir = 0;    /* read */
20545 -       cfg.timeout = 10;
20546 +       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
20547  
20548 -       error = mpt_config(ioc, &cfg);
20549 -       if (error)
20550 +       if (mpt_config(ioc, &cfg) != 0)
20551                 goto out;
20552  
20553 -       if (!hdr.ExtPageLength) {
20554 -               error = -ENXIO;
20555 +       if (!hdr.PageLength)
20556                 goto out;
20557 -       }
20558  
20559 -       buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
20560 -                                     &dma_handle);
20561 -       if (!buffer) {
20562 -               error = -ENOMEM;
20563 +       buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
20564 +           &dma_handle);
20565 +
20566 +       if (!buffer)
20567                 goto out;
20568 -       }
20569  
20570         cfg.physAddr = dma_handle;
20571         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
20572  
20573 -       error = mpt_config(ioc, &cfg);
20574 -       if (error)
20575 -               goto out_free_consistent;
20576 -
20577 -
20578 -       mptsas_print_expander_pg1(ioc, buffer);
20579 -
20580 -       /* save config data */
20581 -       phy_info->phy_id = buffer->PhyIdentifier;
20582 -       phy_info->port_id = buffer->PhysicalPort;
20583 -       phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
20584 -       phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
20585 -       phy_info->hw_link_rate = buffer->HwLinkRate;
20586 -       phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
20587 -       phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
20588 +       if (mpt_config(ioc, &cfg) != 0)
20589 +               goto out;
20590  
20591 - out_free_consistent:
20592 -       pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
20593 -                           buffer, dma_handle);
20594 - out:
20595 -       return error;
20596 -}
20597 +       if (!(buffer->VolumeStatus.Flags &
20598 +           MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
20599 +               goto out;
20600  
20601 -static void
20602 -mptsas_parse_device_info(struct sas_identify *identify,
20603 -               struct mptsas_devinfo *device_info)
20604 -{
20605 -       u16 protocols;
20606 +       if (!buffer->NumPhysDisks)
20607 +               goto out;
20608  
20609 -       identify->sas_address = device_info->sas_address;
20610 -       identify->phy_identifier = device_info->phy_id;
20611 +       for (i = 0; i < buffer->NumPhysDisks; i++) {
20612  
20613 -       /*
20614 -        * Fill in Phy Initiator Port Protocol.
20615 -        * Bits 6:3, more than one bit can be set, fall through cases.
20616 -        */
20617 -       protocols = device_info->device_info & 0x78;
20618 -       identify->initiator_port_protocols = 0;
20619 -       if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
20620 -               identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
20621 -       if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
20622 -               identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
20623 -       if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
20624 -               identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
20625 -       if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
20626 -               identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
20627 +               if (mpt_raid_phys_disk_pg0(ioc,
20628 +                   buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
20629 +                       continue;
20630  
20631 -       /*
20632 -        * Fill in Phy Target Port Protocol.
20633 -        * Bits 10:7, more than one bit can be set, fall through cases.
20634 -        */
20635 -       protocols = device_info->device_info & 0x780;
20636 -       identify->target_port_protocols = 0;
20637 -       if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
20638 -               identify->target_port_protocols |= SAS_PROTOCOL_SSP;
20639 -       if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
20640 -               identify->target_port_protocols |= SAS_PROTOCOL_STP;
20641 -       if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
20642 -               identify->target_port_protocols |= SAS_PROTOCOL_SMP;
20643 -       if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
20644 -               identify->target_port_protocols |= SAS_PROTOCOL_SATA;
20645 +               if (mptsas_sas_device_pg0(ioc, &sas_device,
20646 +                   (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
20647 +                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
20648 +                       (phys_disk.PhysDiskBus << 8) +
20649 +                       phys_disk.PhysDiskID))
20650 +                       continue;
20651  
20652 -       /*
20653 -        * Fill in Attached device type.
20654 -        */
20655 -       switch (device_info->device_info &
20656 -                       MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
20657 -       case MPI_SAS_DEVICE_INFO_NO_DEVICE:
20658 -               identify->device_type = SAS_PHY_UNUSED;
20659 -               break;
20660 -       case MPI_SAS_DEVICE_INFO_END_DEVICE:
20661 -               identify->device_type = SAS_END_DEVICE;
20662 -               break;
20663 -       case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
20664 -               identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
20665 -               break;
20666 -       case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
20667 -               identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
20668 -               break;
20669 +               phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
20670 +                   sas_device.sas_address);
20671 +               mptsas_add_end_device(ioc, phy_info);
20672         }
20673 +
20674 + out:
20675 +       if (buffer)
20676 +               pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
20677 +                   dma_handle);
20678  }
20679  
20680 -static int mptsas_probe_one_phy(struct device *dev,
20681 -               struct mptsas_phyinfo *phy_info, int index, int local)
20682 +/**
20683 + *     mptsas_add_end_device - report a new end device to sas transport layer
20684 + *     @ioc: Pointer to MPT_ADAPTER structure
20685 + *     @phy_info: decribes attached device
20686 + *
20687 + *     return (0) success (1) failure
20688 + *
20689 + **/
20690 +static int
20691 +mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
20692  {
20693 -       MPT_ADAPTER *ioc;
20694 -       struct sas_phy *phy;
20695 +       struct sas_rphy *rphy;
20696         struct sas_port *port;
20697 -       int error = 0;
20698 +       struct sas_identify identify;
20699 +       char *ds = NULL;
20700 +       u8 fw_id;
20701  
20702 -       if (!dev) {
20703 -               error = -ENODEV;
20704 -               goto out;
20705 +       if (!phy_info){
20706 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20707 +                       "%s: exit at line=%d\n", ioc->name,
20708 +                       __FUNCTION__, __LINE__));
20709 +               return 1;
20710         }
20711  
20712 -       if (!phy_info->phy) {
20713 -               phy = sas_phy_alloc(dev, index);
20714 -               if (!phy) {
20715 -                       error = -ENOMEM;
20716 -                       goto out;
20717 -               }
20718 -       } else
20719 -               phy = phy_info->phy;
20720 -
20721 -       mptsas_parse_device_info(&phy->identify, &phy_info->identify);
20722 -
20723 -       /*
20724 -        * Set Negotiated link rate.
20725 -        */
20726 -       switch (phy_info->negotiated_link_rate) {
20727 -       case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
20728 -               phy->negotiated_linkrate = SAS_PHY_DISABLED;
20729 -               break;
20730 -       case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
20731 -               phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
20732 -               break;
20733 -       case MPI_SAS_IOUNIT0_RATE_1_5:
20734 -               phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
20735 -               break;
20736 -       case MPI_SAS_IOUNIT0_RATE_3_0:
20737 -               phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
20738 -               break;
20739 -       case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
20740 -       case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
20741 -       default:
20742 -               phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
20743 -               break;
20744 -       }
20745 +       fw_id = phy_info->attached.id;
20746  
20747 -       /*
20748 -        * Set Max hardware link rate.
20749 -        */
20750 -       switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
20751 -       case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
20752 -               phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
20753 -               break;
20754 -       case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
20755 -               phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
20756 -               break;
20757 -       default:
20758 -               break;
20759 +       if (mptsas_get_rphy(phy_info)) {
20760 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20761 +                       "%s: fw_id=%d exit at line=%d\n", ioc->name,
20762 +                       __FUNCTION__, fw_id, __LINE__));
20763 +               return 2;
20764         }
20765  
20766 -       /*
20767 -        * Set Max programmed link rate.
20768 -        */
20769 -       switch (phy_info->programmed_link_rate &
20770 -                       MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
20771 -       case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
20772 -               phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
20773 -               break;
20774 -       case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
20775 -               phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
20776 -               break;
20777 -       default:
20778 -               break;
20779 +       port = mptsas_get_port(phy_info);
20780 +       if (!port) {
20781 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20782 +                       "%s: fw_id=%d exit at line=%d\n", ioc->name,
20783 +                       __FUNCTION__, fw_id, __LINE__));
20784 +               return 3;
20785 +       }
20786 +
20787 +       if (phy_info->attached.device_info &
20788 +           MPI_SAS_DEVICE_INFO_SSP_TARGET)
20789 +               ds = "ssp";
20790 +       if (phy_info->attached.device_info &
20791 +           MPI_SAS_DEVICE_INFO_STP_TARGET)
20792 +               ds = "stp";
20793 +       if (phy_info->attached.device_info &
20794 +           MPI_SAS_DEVICE_INFO_SATA_DEVICE)
20795 +               ds = "sata";
20796 +
20797 +       printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
20798 +           " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
20799 +           phy_info->attached.channel, phy_info->attached.id,
20800 +           phy_info->attached.phy_id, (unsigned long long)
20801 +           phy_info->attached.sas_address);
20802 +
20803 +       mptsas_parse_device_info(&identify, &phy_info->attached);
20804 +       rphy = sas_end_device_alloc(port);
20805 +       if (!rphy) {
20806 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20807 +                       "%s: fw_id=%d exit at line=%d\n", ioc->name,
20808 +                       __FUNCTION__, fw_id, __LINE__));
20809 +               return 5; /* non-fatal: an rphy can be added later */
20810 +       }
20811 +
20812 +       rphy->identify = identify;
20813 +       if (sas_rphy_add(rphy)) {
20814 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20815 +                       "%s: fw_id=%d exit at line=%d\n", ioc->name,
20816 +                       __FUNCTION__, fw_id, __LINE__));
20817 +               sas_rphy_free(rphy);
20818 +               return 6;
20819         }
20820 +       mptsas_set_rphy(ioc, phy_info, rphy);
20821 +       return 0;
20822 +}
20823  
20824 -       /*
20825 -        * Set Min hardware link rate.
20826 -        */
20827 -       switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
20828 -       case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
20829 -               phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
20830 -               break;
20831 -       case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
20832 -               phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
20833 -               break;
20834 -       default:
20835 -               break;
20836 -       }
20837 +/**
20838 + *     mptsas_del_end_device - report a deleted end device to sas transport
20839 + *     layer
20840 + *     @ioc: Pointer to MPT_ADAPTER structure
20841 + *     @phy_info: decribes attached device
20842 + *
20843 + **/
20844 +static void
20845 +mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
20846 +{
20847 +       struct sas_rphy *rphy;
20848 +       struct sas_port *port;
20849 +       struct mptsas_portinfo *port_info;
20850 +       struct mptsas_phyinfo *phy_info_parent;
20851 +       int i;
20852 +       struct scsi_target * starget;
20853 +       char *ds = NULL;
20854 +       u8 fw_id;
20855 +       u64 sas_address;
20856  
20857 -       /*
20858 -        * Set Min programmed link rate.
20859 -        */
20860 -       switch (phy_info->programmed_link_rate &
20861 -                       MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
20862 -       case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
20863 -               phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
20864 -               break;
20865 -       case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
20866 -               phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
20867 -               break;
20868 -       default:
20869 -               break;
20870 -       }
20871 +       if (!phy_info)
20872 +               return;
20873  
20874 -       if (!phy_info->phy) {
20875 +       fw_id = phy_info->attached.id;
20876 +       sas_address = phy_info->attached.sas_address;
20877  
20878 -               error = sas_phy_add(phy);
20879 -               if (error) {
20880 -                       sas_phy_free(phy);
20881 -                       goto out;
20882 -               }
20883 -               phy_info->phy = phy;
20884 +       if (!phy_info->port_details) {
20885 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20886 +                       "%s: fw_id=%d exit at line=%d\n", ioc->name,
20887 +                       __FUNCTION__, fw_id, __LINE__));
20888 +               return;
20889         }
20890 -
20891 -       if (!phy_info->attached.handle ||
20892 -                       !phy_info->port_details)
20893 -               goto out;
20894 +       rphy = mptsas_get_rphy(phy_info);
20895 +       if (!rphy) {
20896 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20897 +                       "%s: fw_id=%d exit at line=%d\n", ioc->name,
20898 +                       __FUNCTION__, fw_id, __LINE__));
20899 +               return;
20900 +       }
20901 +       if (phy_info->attached.device_info &
20902 +           MPI_SAS_DEVICE_INFO_SSP_TARGET)
20903 +               ds = "ssp";
20904 +       if (phy_info->attached.device_info &
20905 +           MPI_SAS_DEVICE_INFO_STP_TARGET)
20906 +               ds = "stp";
20907 +       if (phy_info->attached.device_info &
20908 +           MPI_SAS_DEVICE_INFO_SATA_DEVICE)
20909 +               ds = "sata";
20910 +
20911 +       starget = mptsas_get_starget(phy_info);
20912 +
20913 +       printk(MYIOC_s_INFO_FMT "removing %s device: fw_channel %d,"
20914 +           " fw_id %d, phy %d, sas_addr 0x%llx\n", ioc->name, ds,
20915 +           phy_info->attached.channel, phy_info->attached.id,
20916 +           phy_info->attached.phy_id, (unsigned long long)
20917 +           sas_address);
20918  
20919         port = mptsas_get_port(phy_info);
20920 -       ioc = phy_to_ioc(phy_info->phy);
20921 +       if (!port) {
20922 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20923 +                       "%s: fw_id=%d exit at line=%d\n", ioc->name,
20924 +                       __FUNCTION__, fw_id, __LINE__));
20925 +               return;
20926 +       }
20927 +       port_info = phy_info->portinfo;
20928 +       phy_info_parent = port_info->phy_info;
20929 +       for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
20930 +               if(!phy_info_parent->phy)
20931 +                       continue;
20932 +               if (phy_info_parent->attached.sas_address !=
20933 +                   sas_address)
20934 +                       continue;
20935 +               dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
20936 +                   MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
20937 +                   ioc->name, phy_info_parent->phy_id,
20938 +                   phy_info_parent->phy);
20939 +               sas_port_delete_phy(port, phy_info_parent->phy);
20940 +       }
20941 +
20942 +       dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
20943 +           "delete port %d, sas_addr (0x%llx)\n", ioc->name,
20944 +            port->port_identifier, (unsigned long long)sas_address);
20945 +       sas_port_delete(port);
20946 +//     mptsas_port_delete(ioc, phy_info->port_details);
20947 +}
20948  
20949 -       if (phy_info->sas_port_add_phy) {
20950 +struct mptsas_phyinfo *
20951 +mptsas_refreshing_device_handles(MPT_ADAPTER *ioc, struct mptsas_devinfo *sas_device)
20952 +{
20953 +       struct mptsas_phyinfo *phy_info;
20954 +       struct mptsas_portinfo *port_info;
20955 +       int i;
20956  
20957 -               if (!port) {
20958 -                       port = sas_port_alloc_num(dev);
20959 -                       if (!port) {
20960 -                               error = -ENOMEM;
20961 -                               goto out;
20962 -                       }
20963 -                       error = sas_port_add(port);
20964 -                       if (error) {
20965 -                               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
20966 -                                       "%s: exit at line=%d\n", ioc->name,
20967 -                                       __func__, __LINE__));
20968 -                               goto out;
20969 -                       }
20970 -                       mptsas_set_port(ioc, phy_info, port);
20971 -                       dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
20972 -                           "sas_port_alloc: port=%p dev=%p port_id=%d\n",
20973 -                           ioc->name, port, dev, port->port_identifier));
20974 -               }
20975 -               dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
20976 -                   ioc->name, phy_info->phy_id));
20977 -               sas_port_add_phy(port, phy_info->phy);
20978 -               phy_info->sas_port_add_phy = 0;
20979 +       phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
20980 +           sas_device->sas_address);
20981 +       if (!phy_info)
20982 +               goto out;
20983 +       port_info = phy_info->portinfo;
20984 +       if (!port_info)
20985 +               goto out;
20986 +       mutex_lock(&ioc->sas_topology_mutex);
20987 +       for (i = 0; i < port_info->num_phys; i++) {
20988 +               if(port_info->phy_info[i].attached.sas_address !=
20989 +                   sas_device->sas_address)
20990 +                       continue;
20991 +               port_info->phy_info[i].attached.channel = sas_device->channel;
20992 +               port_info->phy_info[i].attached.id = sas_device->id;
20993 +               port_info->phy_info[i].attached.sas_address =
20994 +                   sas_device->sas_address;
20995 +               port_info->phy_info[i].attached.handle = sas_device->handle;
20996 +               port_info->phy_info[i].attached.handle_parent =
20997 +                   sas_device->handle_parent;
20998 +               port_info->phy_info[i].attached.handle_enclosure =
20999 +                   sas_device->handle_enclosure;
21000         }
21001 +       mutex_unlock(&ioc->sas_topology_mutex);
21002 + out:
21003 +       return phy_info;
21004 +}
21005  
21006 -       if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
21007 -
21008 -               struct sas_rphy *rphy;
21009 -               struct device *parent;
21010 -               struct sas_identify identify;
21011  
21012 -               parent = dev->parent->parent;
21013 -               /*
21014 -                * Let the hotplug_work thread handle processing
21015 -                * the adding/removing of devices that occur
21016 -                * after start of day.
21017 -                */
21018 -               if (ioc->sas_discovery_runtime &&
21019 -                       mptsas_is_end_device(&phy_info->attached))
21020 -                               goto out;
21021 +/**
21022 + *     mptsas_hotplug_work - Work queue thread to handle SAS hotplug events
21023 + *
21024 + *
21025 + **/
21026 +static void
21027 +mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
21028 +    struct mptsas_hotplug_event *hot_plug_info)
21029 +{
21030 +       struct mptsas_phyinfo *phy_info;
21031 +       struct scsi_target * starget;
21032 +       struct mptsas_devinfo sas_device;
21033 +       VirtTarget *vtarget;
21034 +       enum device_state state;
21035 +       int i;
21036  
21037 -               mptsas_parse_device_info(&identify, &phy_info->attached);
21038 -               if (scsi_is_host_device(parent)) {
21039 -                       struct mptsas_portinfo *port_info;
21040 -                       int i;
21041 +       switch (hot_plug_info->event_type) {
21042  
21043 -                       mutex_lock(&ioc->sas_topology_mutex);
21044 -                       port_info = mptsas_get_hba_portinfo(ioc);
21045 -                       mutex_unlock(&ioc->sas_topology_mutex);
21046 +       case MPTSAS_ADD_PHYSDISK:
21047  
21048 -                       for (i = 0; i < port_info->num_phys; i++)
21049 -                               if (port_info->phy_info[i].identify.sas_address ==
21050 -                                   identify.sas_address) {
21051 -                                       sas_port_mark_backlink(port);
21052 -                                       goto out;
21053 -                               }
21054 +               if (!ioc->raid_data.pIocPg2)
21055 +                       break;
21056  
21057 -               } else if (scsi_is_sas_rphy(parent)) {
21058 -                       struct sas_rphy *parent_rphy = dev_to_rphy(parent);
21059 -                       if (identify.sas_address ==
21060 -                           parent_rphy->identify.sas_address) {
21061 -                               sas_port_mark_backlink(port);
21062 -                               goto out;
21063 +               for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
21064 +                       if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
21065 +                           hot_plug_info->id) {
21066 +                               printk(MYIOC_s_WARN_FMT "firmware bug: unable "
21067 +                                   "to add hidden disk - target_id matchs "
21068 +                                   "volume_id\n", ioc->name);
21069 +                               mptsas_free_fw_event(ioc, fw_event);
21070 +                               return;
21071                         }
21072                 }
21073  
21074 -               switch (identify.device_type) {
21075 -               case SAS_END_DEVICE:
21076 -                       rphy = sas_end_device_alloc(port);
21077 -                       break;
21078 -               case SAS_EDGE_EXPANDER_DEVICE:
21079 -               case SAS_FANOUT_EXPANDER_DEVICE:
21080 -                       rphy = sas_expander_alloc(port, identify.device_type);
21081 +       case MPTSAS_ADD_DEVICE:
21082 +               memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
21083 +               mptsas_sas_device_pg0(ioc, &sas_device,
21084 +                   (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
21085 +                   MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
21086 +                   (hot_plug_info->channel << 8) +
21087 +                   hot_plug_info->id);
21088 +
21089 +               if (!sas_device.handle)
21090 +                       return;
21091 +
21092 +               phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
21093 +               if (!phy_info)
21094                         break;
21095 -               default:
21096 -                       rphy = NULL;
21097 +
21098 +               if (mptsas_get_rphy(phy_info))
21099                         break;
21100 -               }
21101 -               if (!rphy) {
21102 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21103 -                               "%s: exit at line=%d\n", ioc->name,
21104 -                               __func__, __LINE__));
21105 -                       goto out;
21106 -               }
21107  
21108 -               rphy->identify = identify;
21109 -               error = sas_rphy_add(rphy);
21110 -               if (error) {
21111 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21112 -                               "%s: exit at line=%d\n", ioc->name,
21113 -                               __func__, __LINE__));
21114 -                       sas_rphy_free(rphy);
21115 -                       goto out;
21116 +               state = mptsas_test_unit_ready(ioc, phy_info->attached.channel,
21117 +                   phy_info->attached.id, fw_event->retries);
21118 +
21119 +               if (state == DEVICE_RETRY && !ioc->fw_events_off) {
21120 +                       mptsas_requeue_fw_event(ioc, fw_event, 1000);
21121 +                       return;
21122                 }
21123 -               mptsas_set_rphy(ioc, phy_info, rphy);
21124 -       }
21125  
21126 - out:
21127 -       return error;
21128 -}
21129 +               if (state == DEVICE_READY)
21130 +                       mptsas_add_end_device(ioc, phy_info);
21131 +               break;
21132  
21133 -static int
21134 -mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
21135 -{
21136 -       struct mptsas_portinfo *port_info, *hba;
21137 -       int error = -ENOMEM, i;
21138 +       case MPTSAS_DEL_DEVICE:
21139  
21140 -       hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
21141 -       if (! hba)
21142 -               goto out;
21143 +               if (!ioc->disable_hotplug_remove) {
21144 +                       phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
21145 +                           hot_plug_info->sas_address);
21146 +                       mptsas_del_end_device(ioc, phy_info);
21147 +               }
21148 +               break;
21149  
21150 -       error = mptsas_sas_io_unit_pg0(ioc, hba);
21151 -       if (error)
21152 -               goto out_free_port_info;
21153 +       case MPTSAS_DEL_PHYSDISK:
21154  
21155 -       mptsas_sas_io_unit_pg1(ioc);
21156 -       mutex_lock(&ioc->sas_topology_mutex);
21157 -       port_info = mptsas_get_hba_portinfo(ioc);
21158 -       if (!port_info) {
21159 -               port_info = hba;
21160 -               list_add_tail(&port_info->list, &ioc->sas_topology);
21161 -       } else {
21162 -               for (i = 0; i < hba->num_phys; i++) {
21163 -                       port_info->phy_info[i].negotiated_link_rate =
21164 -                               hba->phy_info[i].negotiated_link_rate;
21165 -                       port_info->phy_info[i].handle =
21166 -                               hba->phy_info[i].handle;
21167 -                       port_info->phy_info[i].port_id =
21168 -                               hba->phy_info[i].port_id;
21169 -               }
21170 -               kfree(hba->phy_info);
21171 -               kfree(hba);
21172 -               hba = NULL;
21173 -       }
21174 -       mutex_unlock(&ioc->sas_topology_mutex);
21175 -       for (i = 0; i < port_info->num_phys; i++) {
21176 -               mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
21177 -                       (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
21178 -                        MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
21179 +               mpt_findImVolumes(ioc);
21180  
21181 -               mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
21182 -                       (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
21183 -                        MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
21184 -                        port_info->phy_info[i].handle);
21185 -               port_info->phy_info[i].identify.phy_id =
21186 -                   port_info->phy_info[i].phy_id = i;
21187 -               if (port_info->phy_info[i].attached.handle)
21188 -                       mptsas_sas_device_pg0(ioc,
21189 -                               &port_info->phy_info[i].attached,
21190 -                               (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
21191 -                                MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
21192 -                               port_info->phy_info[i].attached.handle);
21193 -       }
21194 +               phy_info = mptsas_find_phyinfo_by_phys_disk_num(
21195 +                   ioc, hot_plug_info->phys_disk_num, hot_plug_info->channel,
21196 +                   hot_plug_info->id);
21197 +               mptsas_del_end_device(ioc, phy_info);
21198 +               break;
21199  
21200 -       mptsas_setup_wide_ports(ioc, port_info);
21201 +       case MPTSAS_ADD_PHYSDISK_REPROBE:
21202  
21203 -       for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
21204 -               mptsas_probe_one_phy(&ioc->sh->shost_gendev,
21205 -                   &port_info->phy_info[i], ioc->sas_index, 1);
21206 +               if (mptsas_sas_device_pg0(ioc, &sas_device,
21207 +                   (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
21208 +                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
21209 +                   (hot_plug_info->channel << 8) + hot_plug_info->id)) {
21210 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21211 +                       "%s: fw_id=%d exit at line=%d\n", ioc->name,
21212 +                               __FUNCTION__, hot_plug_info->id, __LINE__));
21213 +                       break;
21214 +               }
21215  
21216 -       return 0;
21217 +               phy_info = mptsas_find_phyinfo_by_sas_address(
21218 +                   ioc, sas_device.sas_address);
21219  
21220 - out_free_port_info:
21221 -       kfree(hba);
21222 - out:
21223 -       return error;
21224 -}
21225 +               if (!phy_info){
21226 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21227 +                               "%s: fw_id=%d exit at line=%d\n", ioc->name,
21228 +                               __FUNCTION__, hot_plug_info->id, __LINE__));
21229 +                       break;
21230 +               }
21231  
21232 -static int
21233 -mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
21234 -{
21235 -       struct mptsas_portinfo *port_info, *p, *ex;
21236 -       struct device *parent;
21237 -       struct sas_rphy *rphy;
21238 -       int error = -ENOMEM, i, j;
21239 +               starget = mptsas_get_starget(phy_info);
21240 +               if (!starget) {
21241 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21242 +                               "%s: fw_id=%d exit at line=%d\n", ioc->name,
21243 +                               __FUNCTION__, hot_plug_info->id, __LINE__));
21244 +                       break;
21245 +               }
21246  
21247 -       ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
21248 -       if (!ex)
21249 -               goto out;
21250 +               vtarget = starget->hostdata;
21251 +               if (!vtarget) {
21252 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21253 +                               "%s: fw_id=%d exit at line=%d\n", ioc->name,
21254 +                               __FUNCTION__, hot_plug_info->id, __LINE__));
21255 +                       break;
21256 +               }
21257  
21258 -       error = mptsas_sas_expander_pg0(ioc, ex,
21259 -           (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
21260 -            MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
21261 -       if (error)
21262 -               goto out_free_port_info;
21263 +               mpt_findImVolumes(ioc);
21264  
21265 -       *handle = ex->phy_info[0].handle;
21266 +               starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
21267 +                   "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
21268 +                   ioc->name, hot_plug_info->channel, hot_plug_info->id,
21269 +                   hot_plug_info->phys_disk_num, (unsigned long long)
21270 +                   sas_device.sas_address);
21271 +
21272 +               vtarget->id = hot_plug_info->phys_disk_num;
21273 +               vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
21274 +               phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
21275 +               mptsas_reprobe_target(starget, 1);
21276 +               break;
21277  
21278 -       mutex_lock(&ioc->sas_topology_mutex);
21279 -       port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
21280 -       if (!port_info) {
21281 -               port_info = ex;
21282 -               list_add_tail(&port_info->list, &ioc->sas_topology);
21283 -       } else {
21284 -               for (i = 0; i < ex->num_phys; i++) {
21285 -                       port_info->phy_info[i].handle =
21286 -                               ex->phy_info[i].handle;
21287 -                       port_info->phy_info[i].port_id =
21288 -                               ex->phy_info[i].port_id;
21289 +       case MPTSAS_DEL_PHYSDISK_REPROBE:
21290 +
21291 +               if (mptsas_sas_device_pg0(ioc, &sas_device,
21292 +                   (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
21293 +                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
21294 +                       (hot_plug_info->channel << 8) + hot_plug_info->id)) {
21295 +                               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21296 +                                   "%s: fw_id=%d exit at line=%d\n",
21297 +                                   ioc->name, __FUNCTION__,
21298 +                                   hot_plug_info->id, __LINE__));
21299 +                       break;
21300                 }
21301 -               kfree(ex->phy_info);
21302 -               kfree(ex);
21303 -               ex = NULL;
21304 -       }
21305 -       mutex_unlock(&ioc->sas_topology_mutex);
21306  
21307 -       for (i = 0; i < port_info->num_phys; i++) {
21308 -               mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
21309 -                       (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
21310 -                        MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
21311 +               phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
21312 +                               sas_device.sas_address);
21313 +               if (!phy_info) {
21314 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21315 +                           "%s: fw_id=%d exit at line=%d\n", ioc->name,
21316 +                           __FUNCTION__, hot_plug_info->id, __LINE__));
21317 +                       break;
21318 +               }
21319  
21320 -               if (port_info->phy_info[i].identify.handle) {
21321 -                       mptsas_sas_device_pg0(ioc,
21322 -                               &port_info->phy_info[i].identify,
21323 -                               (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
21324 -                                MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
21325 -                               port_info->phy_info[i].identify.handle);
21326 -                       port_info->phy_info[i].identify.phy_id =
21327 -                           port_info->phy_info[i].phy_id;
21328 +               starget = mptsas_get_starget(phy_info);
21329 +               if (!starget) {
21330 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21331 +                           "%s: fw_id=%d exit at line=%d\n", ioc->name,
21332 +                           __FUNCTION__, hot_plug_info->id, __LINE__));
21333 +                       break;
21334                 }
21335  
21336 -               if (port_info->phy_info[i].attached.handle) {
21337 -                       mptsas_sas_device_pg0(ioc,
21338 -                               &port_info->phy_info[i].attached,
21339 -                               (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
21340 -                                MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
21341 -                               port_info->phy_info[i].attached.handle);
21342 -                       port_info->phy_info[i].attached.phy_id =
21343 -                           port_info->phy_info[i].phy_id;
21344 +               vtarget = starget->hostdata;
21345 +               if (!vtarget) {
21346 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21347 +                           "%s: fw_id=%d exit at line=%d\n", ioc->name,
21348 +                           __FUNCTION__, hot_plug_info->id, __LINE__));
21349 +                       break;
21350                 }
21351 -       }
21352  
21353 -       parent = &ioc->sh->shost_gendev;
21354 -       for (i = 0; i < port_info->num_phys; i++) {
21355 -               mutex_lock(&ioc->sas_topology_mutex);
21356 -               list_for_each_entry(p, &ioc->sas_topology, list) {
21357 -                       for (j = 0; j < p->num_phys; j++) {
21358 -                               if (port_info->phy_info[i].identify.handle !=
21359 -                                               p->phy_info[j].attached.handle)
21360 -                                       continue;
21361 -                               rphy = mptsas_get_rphy(&p->phy_info[j]);
21362 -                               parent = &rphy->dev;
21363 -                       }
21364 +               if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
21365 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
21366 +                           "%s: fw_id=%d exit at line=%d\n", ioc->name,
21367 +                           __FUNCTION__, hot_plug_info->id, __LINE__));
21368 +                       break;
21369                 }
21370 -               mutex_unlock(&ioc->sas_topology_mutex);
21371 -       }
21372  
21373 -       mptsas_setup_wide_ports(ioc, port_info);
21374 +               mpt_findImVolumes(ioc);
21375 +
21376 +               starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
21377 +                   " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
21378 +                   ioc->name, hot_plug_info->channel, hot_plug_info->id,
21379 +                   hot_plug_info->phys_disk_num, (unsigned long long)
21380 +                   sas_device.sas_address);
21381 +
21382 +               vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
21383 +               vtarget->id = hot_plug_info->id;
21384 +               phy_info->attached.phys_disk_num = ~0;
21385 +               mptsas_reprobe_target(starget, 0);
21386 +               mptsas_add_device_component_by_fw(ioc,
21387 +                   hot_plug_info->channel, hot_plug_info->id);
21388 +               break;
21389 +
21390 +       case MPTSAS_ADD_RAID:
21391 +
21392 +               mpt_findImVolumes(ioc);
21393 +               printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
21394 +                   "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
21395 +                   hot_plug_info->id);
21396 +               scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
21397 +                   hot_plug_info->id, 0);
21398 +               break;
21399 +
21400 +       case MPTSAS_DEL_RAID:
21401 +
21402 +               mpt_findImVolumes(ioc);
21403 +               printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
21404 +                   "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
21405 +                   hot_plug_info->id);
21406 +               scsi_remove_device(hot_plug_info->sdev);
21407 +               scsi_device_put(hot_plug_info->sdev);
21408 +               break;
21409  
21410 -       for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
21411 -               mptsas_probe_one_phy(parent, &port_info->phy_info[i],
21412 -                   ioc->sas_index, 0);
21413 +       case MPTSAS_ADD_INACTIVE_VOLUME:
21414  
21415 -       return 0;
21416 +               mpt_findImVolumes(ioc);
21417 +               mptsas_adding_inactive_raid_components(ioc,
21418 +                   hot_plug_info->channel, hot_plug_info->id);
21419 +               break;
21420  
21421 - out_free_port_info:
21422 -       if (ex) {
21423 -               kfree(ex->phy_info);
21424 -               kfree(ex);
21425 +       default:
21426 +               break;
21427         }
21428 - out:
21429 -       return error;
21430 +
21431 +       mptsas_free_fw_event(ioc, fw_event);
21432  }
21433  
21434 -/*
21435 - * mptsas_delete_expander_phys
21436 +/**
21437 + * mptsas_send_sas_event
21438   *
21439   *
21440 - * This will traverse topology, and remove expanders
21441 - * that are no longer present
21442 - */
21443 + * @ioc
21444 + * @sas_event_data
21445 + *
21446 + **/
21447  static void
21448 -mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
21449 +mptsas_send_sas_event(struct fw_event_work *fw_event)
21450  {
21451 -       struct mptsas_portinfo buffer;
21452 -       struct mptsas_portinfo *port_info, *n, *parent;
21453 -       struct mptsas_phyinfo *phy_info;
21454 -       struct sas_port * port;
21455 -       int i;
21456 -       u64     expander_sas_address;
21457 +       MPT_ADAPTER *ioc;
21458 +       struct mptsas_hotplug_event hot_plug_info;
21459 +       EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
21460 +       u32 device_info;
21461 +       u64 sas_address;
21462  
21463 -       mutex_lock(&ioc->sas_topology_mutex);
21464 -       list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
21465 +       ioc = fw_event->ioc;
21466 +       sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
21467 +           fw_event->event_data;
21468 +       device_info = le32_to_cpu(sas_event_data->DeviceInfo);
21469  
21470 -               if (port_info->phy_info &&
21471 -                   (!(port_info->phy_info[0].identify.device_info &
21472 -                   MPI_SAS_DEVICE_INFO_SMP_TARGET)))
21473 -                       continue;
21474 +       if ((device_info &
21475 +            (MPI_SAS_DEVICE_INFO_SSP_TARGET |
21476 +             MPI_SAS_DEVICE_INFO_STP_TARGET |
21477 +             MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) {
21478 +               mptsas_free_fw_event(ioc, fw_event);
21479 +               return;
21480 +       }
21481  
21482 -               if (mptsas_sas_expander_pg0(ioc, &buffer,
21483 -                    (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
21484 -                    MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
21485 -                    port_info->phy_info[0].handle)) {
21486 +       if (sas_event_data->ReasonCode ==
21487 +               MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
21488 +               mptbase_sas_persist_operation(ioc,
21489 +                   MPI_SAS_OP_CLEAR_NOT_PRESENT);
21490 +               mptsas_free_fw_event(ioc, fw_event);
21491 +               return;
21492 +       }
21493  
21494 -                       /*
21495 -                        * Obtain the port_info instance to the parent port
21496 -                        */
21497 -                       parent = mptsas_find_portinfo_by_handle(ioc,
21498 -                           port_info->phy_info[0].identify.handle_parent);
21499 +       switch (sas_event_data->ReasonCode) {
21500 +       case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
21501 +       case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
21502 +               memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
21503 +               hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
21504 +               hot_plug_info.channel = sas_event_data->Bus;
21505 +               hot_plug_info.id = sas_event_data->TargetID;
21506 +               hot_plug_info.phy_id = sas_event_data->PhyNum;
21507 +               memcpy(&sas_address, &sas_event_data->SASAddress,
21508 +                   sizeof(u64));
21509 +               hot_plug_info.sas_address = le64_to_cpu(sas_address);
21510 +               hot_plug_info.device_info = device_info;
21511 +               if (sas_event_data->ReasonCode &
21512 +                   MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
21513 +                       hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
21514 +               else
21515 +                       hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
21516 +               mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
21517 +               break;
21518 +
21519 +       case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
21520 +               mptbase_sas_persist_operation(ioc,
21521 +                   MPI_SAS_OP_CLEAR_NOT_PRESENT);
21522 +               mptsas_free_fw_event(ioc, fw_event);
21523 +               break;
21524  
21525 -                       if (!parent)
21526 -                               goto next_port;
21527 +       case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
21528 +       /* TODO */
21529 +       case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
21530 +       /* TODO */
21531 +       default:
21532 +               mptsas_free_fw_event(ioc, fw_event);
21533 +               break;
21534 +       }
21535 +}
21536  
21537 -                       expander_sas_address =
21538 -                               port_info->phy_info[0].identify.sas_address;
21539  
21540 -                       /*
21541 -                        * Delete rphys in the parent that point
21542 -                        * to this expander.  The transport layer will
21543 -                        * cleanup all the children.
21544 -                        */
21545 -                       phy_info = parent->phy_info;
21546 -                       for (i = 0; i < parent->num_phys; i++, phy_info++) {
21547 -                               port = mptsas_get_port(phy_info);
21548 -                               if (!port)
21549 -                                       continue;
21550 -                               if (phy_info->attached.sas_address !=
21551 -                                       expander_sas_address)
21552 -                                       continue;
21553 -                               dsaswideprintk(ioc,
21554 -                                   dev_printk(KERN_DEBUG, &port->dev,
21555 -                                   MYIOC_s_FMT "delete port (%d)\n", ioc->name,
21556 -                                   port->port_identifier));
21557 -                               sas_port_delete(port);
21558 -                               mptsas_port_delete(ioc, phy_info->port_details);
21559 -                       }
21560 - next_port:
21561 -
21562 -                       phy_info = port_info->phy_info;
21563 -                       for (i = 0; i < port_info->num_phys; i++, phy_info++)
21564 -                               mptsas_port_delete(ioc, phy_info->port_details);
21565 -
21566 -                       list_del(&port_info->list);
21567 -                       kfree(port_info->phy_info);
21568 -                       kfree(port_info);
21569 +/**
21570 + * mptsas_send_raid_event
21571 + *
21572 + *
21573 + * @ioc
21574 + * @raid_event_data
21575 + *
21576 + **/
21577 +static void
21578 +mptsas_send_raid_event(struct fw_event_work *fw_event)
21579 +{
21580 +       MPT_ADAPTER *ioc;
21581 +       EVENT_DATA_RAID *raid_event_data;
21582 +       struct mptsas_hotplug_event hot_plug_info;
21583 +       int status;
21584 +       int state;
21585 +       struct scsi_device *sdev = NULL;
21586 +       VirtDevice *vdevice = NULL;
21587 +       RaidPhysDiskPage0_t phys_disk;
21588 +
21589 +       ioc = fw_event->ioc;
21590 +       raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
21591 +       status = le32_to_cpu(raid_event_data->SettingsStatus);
21592 +       state = (status >> 8) & 0xff;
21593 +
21594 +       memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
21595 +       hot_plug_info.id = raid_event_data->VolumeID;
21596 +       hot_plug_info.channel = raid_event_data->VolumeBus;
21597 +       hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
21598 +
21599 +       if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
21600 +           raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
21601 +           raid_event_data->ReasonCode ==
21602 +           MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
21603 +               sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
21604 +                   hot_plug_info.id, 0);
21605 +               hot_plug_info.sdev = sdev;
21606 +               if (sdev)
21607 +                       vdevice = sdev->hostdata;
21608 +       }
21609 +
21610 +       devtprintk(ioc, printk(MYIOC_s_INFO_FMT "Entering %s: "
21611 +           "ReasonCode=%02x\n", ioc->name, __FUNCTION__,
21612 +           raid_event_data->ReasonCode));
21613 +
21614 +       switch (raid_event_data->ReasonCode) {
21615 +       case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
21616 +               hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
21617 +               break;
21618 +       case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
21619 +               hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
21620 +               break;
21621 +       case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
21622 +               switch (state) {
21623 +               case MPI_PD_STATE_ONLINE:
21624 +               case MPI_PD_STATE_NOT_COMPATIBLE:
21625 +                       mpt_raid_phys_disk_pg0(ioc,
21626 +                           raid_event_data->PhysDiskNum, &phys_disk);
21627 +                       hot_plug_info.id = phys_disk.PhysDiskID;
21628 +                       hot_plug_info.channel = phys_disk.PhysDiskBus;
21629 +                       hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
21630 +                       break;
21631 +               case MPI_PD_STATE_FAILED:
21632 +               case MPI_PD_STATE_MISSING:
21633 +               case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
21634 +               case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
21635 +               case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
21636 +                       hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
21637 +                       break;
21638 +               default:
21639 +                       break;
21640                 }
21641 -               /*
21642 -               * Free this memory allocated from inside
21643 -               * mptsas_sas_expander_pg0
21644 -               */
21645 -               kfree(buffer.phy_info);
21646 +               break;
21647 +       case MPI_EVENT_RAID_RC_VOLUME_DELETED:
21648 +               if (!sdev)
21649 +                       break;
21650 +               vdevice->vtarget->deleted = 1; /* block IO */
21651 +               hot_plug_info.event_type = MPTSAS_DEL_RAID;
21652 +               break;
21653 +       case MPI_EVENT_RAID_RC_VOLUME_CREATED:
21654 +               if (sdev) {
21655 +                       scsi_device_put(sdev);
21656 +                       break;
21657 +               }
21658 +               hot_plug_info.event_type = MPTSAS_ADD_RAID;
21659 +               break;
21660 +       case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
21661 +               if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
21662 +                       if (!sdev)
21663 +                               break;
21664 +                       vdevice->vtarget->deleted = 1; /* block IO */
21665 +                       hot_plug_info.event_type = MPTSAS_DEL_RAID;
21666 +                       break;
21667 +               }
21668 +               switch (state) {
21669 +               case MPI_RAIDVOL0_STATUS_STATE_FAILED:
21670 +               case MPI_RAIDVOL0_STATUS_STATE_MISSING:
21671 +                       if (!sdev)
21672 +                               break;
21673 +                       vdevice->vtarget->deleted = 1; /* block IO */
21674 +                       hot_plug_info.event_type = MPTSAS_DEL_RAID;
21675 +                       break;
21676 +               case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
21677 +               case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
21678 +                       if (sdev) {
21679 +                               scsi_device_put(sdev);
21680 +                               break;
21681 +                       }
21682 +                       hot_plug_info.event_type = MPTSAS_ADD_RAID;
21683 +                       break;
21684 +               default:
21685 +                       break;
21686 +               }
21687 +               break;
21688 +       default:
21689 +               break;
21690         }
21691 -       mutex_unlock(&ioc->sas_topology_mutex);
21692 +
21693 +       if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
21694 +               mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
21695 +       else
21696 +               mptsas_free_fw_event(ioc, fw_event);
21697  }
21698  
21699 -/*
21700 - * Start of day discovery
21701 - */
21702 -static void
21703 -mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
21704 +/**
21705 + *     mptsas_issue_tm - send mptsas internal tm request
21706 + *     @ioc: Pointer to MPT_ADAPTER structure
21707 + *     @type
21708 + *     @channel
21709 + *     @id
21710 + *     @lun
21711 + *     @task_context
21712 + *     @timeout
21713 + *
21714 + *     return:
21715 + *
21716 + **/
21717 +static int
21718 +mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun, int task_context, ulong timeout,
21719 +       u8 *issue_reset)
21720  {
21721 -       u32 handle = 0xFFFF;
21722 -       int i;
21723 +       MPT_FRAME_HDR   *mf;
21724 +       SCSITaskMgmt_t  *pScsiTm;
21725 +       int              retval;
21726 +       unsigned long    timeleft;
21727  
21728 -       mutex_lock(&ioc->sas_discovery_mutex);
21729 -       mptsas_probe_hba_phys(ioc);
21730 -       while (!mptsas_probe_expander_phys(ioc, &handle))
21731 -               ;
21732 -       /*
21733 -         Reporting RAID volumes.
21734 -       */
21735 -       if (!ioc->ir_firmware)
21736 +       *issue_reset = 0;
21737 +       if ((mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc)) == NULL) {
21738 +               retval = -1; /* return failure */
21739 +               dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
21740 +                   "msg frames!!\n", ioc->name));
21741                 goto out;
21742 -       if (!ioc->raid_data.pIocPg2)
21743 +       }
21744 +
21745 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, "
21746 +           "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, "
21747 +           "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf,
21748 +            type, timeout, channel, id, (unsigned long long)lun,
21749 +            task_context));
21750 +
21751 +       pScsiTm = (SCSITaskMgmt_t *) mf;
21752 +       memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
21753 +       pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
21754 +       pScsiTm->TaskType = type;
21755 +       pScsiTm->MsgFlags = 0;
21756 +       pScsiTm->TargetID = id;
21757 +       pScsiTm->Bus = channel;
21758 +       pScsiTm->ChainOffset = 0;
21759 +       pScsiTm->Reserved = 0;
21760 +       pScsiTm->Reserved1 = 0;
21761 +       pScsiTm->TaskMsgContext = task_context;
21762 +       int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
21763 +
21764 +       INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
21765 +       CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
21766 +       retval = 0;
21767 +       mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
21768 +
21769 +       /* Now wait for the command to complete */
21770 +       timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
21771 +           timeout*HZ);
21772 +       if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
21773 +               retval = -1; /* return failure */
21774 +               dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
21775 +                   "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf));
21776 +               mpt_free_msg_frame(ioc, mf);
21777 +               if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
21778 +                       goto out;
21779 +               *issue_reset = 1;
21780                 goto out;
21781 -       if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
21782 +       }
21783 +
21784 +       if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
21785 +               retval = -1; /* return failure */
21786 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
21787 +                   "TaskMgmt request: failed with no reply\n", ioc->name));
21788                 goto out;
21789 -       for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
21790 -               scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
21791 -                   ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
21792         }
21793 +
21794   out:
21795 -       mutex_unlock(&ioc->sas_discovery_mutex);
21796 +       CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
21797 +       return retval;
21798  }
21799  
21800 -/*
21801 - * Work queue thread to handle Runtime discovery
21802 - * Mere purpose is the hot add/delete of expanders
21803 - *(Mutex UNLOCKED)
21804 - */
21805 +/**
21806 + *     mptsas_broadcast_primative_work - Work queue thread to handle
21807 + *     broadcast primitive events
21808 + *     @work: work queue payload containing info describing the event
21809 + *
21810 + **/
21811  static void
21812 -__mptsas_discovery_work(MPT_ADAPTER *ioc)
21813 +mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
21814  {
21815 -       u32 handle = 0xFFFF;
21816 +       MPT_ADAPTER *ioc = fw_event->ioc;
21817 +       MPT_FRAME_HDR           *mf;
21818 +       VirtDevice              *vdevice;
21819 +       int                     ii;
21820 +       struct scsi_cmnd        *sc;
21821 +       SCSITaskMgmtReply_t *   pScsiTmReply;
21822 +       u8                      issue_reset;
21823 +       int                     task_context;
21824 +       u8                      channel, id;
21825 +       int                      lun;
21826 +       u32                      termination_count;
21827 +       u32                      query_count;
21828 +
21829 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
21830 +           "%s - enter\n", ioc->name, __FUNCTION__));
21831 +
21832 +       mutex_lock(&ioc->taskmgmt_cmds.mutex);
21833 +       if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
21834 +               mutex_unlock(&ioc->taskmgmt_cmds.mutex);
21835 +               mptsas_requeue_fw_event(ioc, fw_event, 1000);
21836 +               return;
21837 +       }
21838  
21839 -       ioc->sas_discovery_runtime=1;
21840 -       mptsas_delete_expander_phys(ioc);
21841 -       mptsas_probe_hba_phys(ioc);
21842 -       while (!mptsas_probe_expander_phys(ioc, &handle))
21843 -               ;
21844 -       ioc->sas_discovery_runtime=0;
21845 +       issue_reset = 0;
21846 +       termination_count = 0;
21847 +       query_count = 0;
21848 +       mpt_findImVolumes(ioc);
21849 +       pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
21850 +
21851 +       for (ii = 0; ii < ioc->req_depth; ii++) {
21852 +               sc = mptscsih_get_scsi_lookup(ioc, ii);
21853 +               if (!sc)
21854 +                       continue;
21855 +               mf = MPT_INDEX_2_MFPTR(ioc, ii);
21856 +               if (!mf)
21857 +                       continue;
21858 +               task_context = mf->u.frame.hwhdr.msgctxu.MsgContext;
21859 +               vdevice = sc->device->hostdata;
21860 +               if (!vdevice || !vdevice->vtarget)
21861 +                       continue;
21862 +               if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
21863 +                       continue; /* skip hidden raid components */
21864 +               if (vdevice->vtarget->raidVolume)
21865 +                       continue; /* skip hidden raid components */
21866 +               channel = vdevice->vtarget->channel;
21867 +               id = vdevice->vtarget->id;
21868 +               lun = vdevice->lun;
21869 +               if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK,
21870 +                   channel, id, (u64)lun, task_context, 30, &issue_reset))
21871 +                       goto out;
21872 +               query_count++;
21873 +               termination_count +=
21874 +                   le32_to_cpu(pScsiTmReply->TerminationCount);
21875 +               if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) &&
21876 +                   (pScsiTmReply->ResponseCode ==
21877 +                   MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
21878 +                   pScsiTmReply->ResponseCode ==
21879 +                   MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
21880 +                       continue;
21881 +               if (mptsas_issue_tm(ioc,
21882 +                   MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET,
21883 +                   channel, id, (u64)lun, 0, 30, &issue_reset))
21884 +                       goto out;
21885 +               termination_count +=
21886 +                   le32_to_cpu(pScsiTmReply->TerminationCount);
21887 +       }
21888 +
21889 + out:
21890 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
21891 +           "%s - exit, query_count = %d termination_count = %d\n",
21892 +           ioc->name, __FUNCTION__, query_count, termination_count));
21893 +
21894 +       ioc->broadcast_aen_busy = 0;
21895 +       mpt_clear_taskmgmt_in_progress_flag(ioc);
21896 +       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
21897 +
21898 +       if (issue_reset) {
21899 +               printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
21900 +                   ioc->name, __FUNCTION__);
21901 +               if (mpt_SoftResetHandler(ioc, CAN_SLEEP))
21902 +                       mpt_HardResetHandler(ioc, CAN_SLEEP);
21903 +       }
21904 +       mptsas_free_fw_event(ioc, fw_event);
21905  }
21906  
21907 -/*
21908 - * Work queue thread to handle Runtime discovery
21909 - * Mere purpose is the hot add/delete of expanders
21910 - *(Mutex LOCKED)
21911 - */
21912 +/**
21913 + *     mptsas_send_ir2_event - handle exposing hidden disk when an inactive raid volume is added
21914 + *     @ioc: Pointer to MPT_ADAPTER structure
21915 + *     @ir2_data:
21916 + *
21917 + **/
21918  static void
21919 -mptsas_discovery_work(struct work_struct *work)
21920 +mptsas_send_ir2_event(struct fw_event_work *fw_event)
21921  {
21922 -       struct mptsas_discovery_event *ev =
21923 -               container_of(work, struct mptsas_discovery_event, work);
21924 -       MPT_ADAPTER *ioc = ev->ioc;
21925 -
21926 -       mutex_lock(&ioc->sas_discovery_mutex);
21927 -       __mptsas_discovery_work(ioc);
21928 -       mutex_unlock(&ioc->sas_discovery_mutex);
21929 -       kfree(ev);
21930 +       MPT_ADAPTER *ioc;
21931 +       struct mptsas_hotplug_event hot_plug_info;
21932 +       MPI_EVENT_DATA_IR2 * ir2_data;
21933 +       u8 reasonCode;
21934 +       RaidPhysDiskPage0_t phys_disk;
21935 +
21936 +       ioc = fw_event->ioc;
21937 +       ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
21938 +       reasonCode = ir2_data->ReasonCode;
21939 +
21940 +       devtprintk(ioc, printk(MYIOC_s_INFO_FMT "Entering %s: "
21941 +           "ReasonCode=%02x\n", ioc->name,__FUNCTION__, reasonCode));
21942 +
21943 +       memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
21944 +       hot_plug_info.id = ir2_data->TargetID;
21945 +       hot_plug_info.channel = ir2_data->Bus;
21946 +       switch (reasonCode) {
21947 +       case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
21948 +               hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
21949 +               break;
21950 +       case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
21951 +               hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
21952 +               hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
21953 +               break;
21954 +       case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
21955 +               hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
21956 +               mpt_raid_phys_disk_pg0(ioc,
21957 +                   ir2_data->PhysDiskNum, &phys_disk);
21958 +               hot_plug_info.id = phys_disk.PhysDiskID;
21959 +               hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
21960 +               break;
21961 +       default:
21962 +               mptsas_free_fw_event(ioc, fw_event);
21963 +               return;
21964 +       }
21965 +       mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
21966  }
21967  
21968 -static struct mptsas_phyinfo *
21969 -mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
21970 +static void
21971 +mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
21972  {
21973 -       struct mptsas_portinfo *port_info;
21974 -       struct mptsas_phyinfo *phy_info = NULL;
21975 -       int i;
21976 +       struct mptsas_portinfo *parent;
21977 +       struct device *parent_dev;
21978 +       struct sas_rphy *rphy;
21979 +       int             i;
21980 +       u64             sas_address; /* expander sas address */
21981 +       u32             handle;
21982  
21983 -       mutex_lock(&ioc->sas_topology_mutex);
21984 -       list_for_each_entry(port_info, &ioc->sas_topology, list) {
21985 -               for (i = 0; i < port_info->num_phys; i++) {
21986 -                       if (!mptsas_is_end_device(
21987 -                               &port_info->phy_info[i].attached))
21988 -                               continue;
21989 -                       if (port_info->phy_info[i].attached.sas_address
21990 -                           != sas_address)
21991 -                               continue;
21992 -                       phy_info = &port_info->phy_info[i];
21993 -                       break;
21994 -               }
21995 -       }
21996 -       mutex_unlock(&ioc->sas_topology_mutex);
21997 -       return phy_info;
21998 -}
21999 +       handle = port_info->phy_info[0].handle;
22000 +       sas_address = port_info->phy_info[0].identify.sas_address;
22001 +       for (i = 0; i < port_info->num_phys; i++) {
22002 +               mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
22003 +                   (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
22004 +                   MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
22005  
22006 -static struct mptsas_phyinfo *
22007 -mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
22008 -{
22009 -       struct mptsas_portinfo *port_info;
22010 -       struct mptsas_phyinfo *phy_info = NULL;
22011 -       int i;
22012 +               mptsas_sas_device_pg0(ioc,
22013 +                   &port_info->phy_info[i].identify,
22014 +                   (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
22015 +                   MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
22016 +                   port_info->phy_info[i].identify.handle);
22017 +               port_info->phy_info[i].identify.phy_id =
22018 +                   port_info->phy_info[i].phy_id;
22019  
22020 -       mutex_lock(&ioc->sas_topology_mutex);
22021 -       list_for_each_entry(port_info, &ioc->sas_topology, list) {
22022 -               for (i = 0; i < port_info->num_phys; i++) {
22023 -                       if (!mptsas_is_end_device(
22024 -                               &port_info->phy_info[i].attached))
22025 -                               continue;
22026 -                       if (port_info->phy_info[i].attached.id != id)
22027 -                               continue;
22028 -                       if (port_info->phy_info[i].attached.channel != channel)
22029 -                               continue;
22030 -                       phy_info = &port_info->phy_info[i];
22031 -                       break;
22032 +               if (port_info->phy_info[i].attached.handle) {
22033 +                       mptsas_sas_device_pg0(ioc,
22034 +                           &port_info->phy_info[i].attached,
22035 +                           (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
22036 +                            MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
22037 +                           port_info->phy_info[i].attached.handle);
22038 +                       port_info->phy_info[i].attached.phy_id =
22039 +                           port_info->phy_info[i].phy_id;
22040                 }
22041         }
22042 -       mutex_unlock(&ioc->sas_topology_mutex);
22043 -       return phy_info;
22044 -}
22045 -
22046 -static struct mptsas_phyinfo *
22047 -mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
22048 -{
22049 -       struct mptsas_portinfo *port_info;
22050 -       struct mptsas_phyinfo *phy_info = NULL;
22051 -       int i;
22052  
22053         mutex_lock(&ioc->sas_topology_mutex);
22054 -       list_for_each_entry(port_info, &ioc->sas_topology, list) {
22055 -               for (i = 0; i < port_info->num_phys; i++) {
22056 -                       if (!mptsas_is_end_device(
22057 -                               &port_info->phy_info[i].attached))
22058 -                               continue;
22059 -                       if (port_info->phy_info[i].attached.phys_disk_num == ~0)
22060 -                               continue;
22061 -                       if (port_info->phy_info[i].attached.phys_disk_num != id)
22062 -                               continue;
22063 -                       if (port_info->phy_info[i].attached.channel != channel)
22064 -                               continue;
22065 -                       phy_info = &port_info->phy_info[i];
22066 -                       break;
22067 +       parent = mptsas_find_portinfo_by_handle(ioc,
22068 +           port_info->phy_info[0].identify.handle_parent);
22069 +       if (!parent) {
22070 +               mutex_unlock(&ioc->sas_topology_mutex);
22071 +               return;
22072 +       }
22073 +       for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
22074 +           i++) {
22075 +               if (parent->phy_info[i].attached.sas_address == sas_address) {
22076 +                       rphy = mptsas_get_rphy(&parent->phy_info[i]);
22077 +                       parent_dev = &rphy->dev;
22078                 }
22079         }
22080         mutex_unlock(&ioc->sas_topology_mutex);
22081 -       return phy_info;
22082 +
22083 +       mptsas_setup_wide_ports(ioc, port_info);
22084 +       for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
22085 +               mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
22086 +                   ioc->sas_index, 0);
22087  }
22088  
22089 -/*
22090 - * Work queue thread to clear the persitency table
22091 - */
22092  static void
22093 -mptsas_persist_clear_table(struct work_struct *work)
22094 +mptsas_expander_event_add(MPT_ADAPTER *ioc,
22095 +    MpiEventDataSasExpanderStatusChange_t* expander_data)
22096  {
22097 -       MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
22098 +       struct mptsas_portinfo *port_info;
22099 +       int i;
22100 +       __le64 sas_address;
22101  
22102 -       mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
22103 -}
22104 +       port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
22105 +       if (!port_info)
22106 +               BUG();
22107 +       port_info->num_phys = (expander_data->NumPhys) ?
22108 +           expander_data->NumPhys : 1;
22109 +       port_info->phy_info = kcalloc(port_info->num_phys,
22110 +           sizeof(struct mptsas_phyinfo),GFP_KERNEL);
22111 +       if (!port_info->phy_info)
22112 +               BUG();
22113 +       memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
22114 +       for (i = 0; i < port_info->num_phys; i++) {
22115 +               port_info->phy_info[i].portinfo = port_info;
22116 +               port_info->phy_info[i].handle =
22117 +                   le16_to_cpu(expander_data->DevHandle);
22118 +               port_info->phy_info[i].identify.sas_address =
22119 +                   le64_to_cpu(sas_address);
22120 +               port_info->phy_info[i].identify.handle_parent =
22121 +                   le16_to_cpu(expander_data->ParentDevHandle);
22122 +       }
22123  
22124 -static void
22125 -mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
22126 -{
22127 -       int rc;
22128 +       mutex_lock(&ioc->sas_topology_mutex);
22129 +       list_add_tail(&port_info->list, &ioc->sas_topology);
22130 +       mutex_unlock(&ioc->sas_topology_mutex);
22131  
22132 -       sdev->no_uld_attach = data ? 1 : 0;
22133 -       rc = scsi_device_reprobe(sdev);
22134 -}
22135 +       printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
22136 +           "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
22137 +           (unsigned long long)sas_address);
22138  
22139 -static void
22140 -mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
22141 -{
22142 -       starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
22143 -                       mptsas_reprobe_lun);
22144 +       mptsas_expander_refresh(ioc, port_info);
22145  }
22146  
22147 +/**
22148 + * mptsas_delete_expander_siblings - remove siblings attached to expander
22149 + * @ioc: Pointer to MPT_ADAPTER structure
22150 + * @parent: the parent port_info object
22151 + * @expander: the expander port_info object
22152 + **/
22153  static void
22154 -mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
22155 +mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
22156 +    *parent, struct mptsas_portinfo *expander)
22157  {
22158 -       CONFIGPARMS                     cfg;
22159 -       ConfigPageHeader_t              hdr;
22160 -       dma_addr_t                      dma_handle;
22161 -       pRaidVolumePage0_t              buffer = NULL;
22162 -       RaidPhysDiskPage0_t             phys_disk;
22163 -       int                             i;
22164 -       struct mptsas_hotplug_event     *ev;
22165 +       struct mptsas_phyinfo *phy_info;
22166 +       struct mptsas_portinfo *port_info;
22167 +       struct sas_rphy *rphy;
22168 +       int i;
22169  
22170 -       memset(&cfg, 0 , sizeof(CONFIGPARMS));
22171 -       memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
22172 -       hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
22173 -       cfg.pageAddr = (channel << 8) + id;
22174 -       cfg.cfghdr.hdr = &hdr;
22175 -       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
22176 +       phy_info = expander->phy_info;
22177 +       for (i = 0; i < expander->num_phys; i++, phy_info++) {
22178 +               if (!(rphy = mptsas_get_rphy(phy_info)))
22179 +                       continue;
22180 +               if (rphy->identify.device_type == SAS_END_DEVICE)
22181 +                       mptsas_del_end_device(ioc, phy_info);
22182 +       }
22183  
22184 -       if (mpt_config(ioc, &cfg) != 0)
22185 -               goto out;
22186 +       phy_info = expander->phy_info;
22187 +       for (i = 0; i < expander->num_phys; i++, phy_info++) {
22188 +               if (!(rphy = mptsas_get_rphy(phy_info)))
22189 +                       continue;
22190 +               if (rphy->identify.device_type ==
22191 +                   MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
22192 +                   rphy->identify.device_type ==
22193 +                   MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
22194 +                       port_info = mptsas_find_portinfo_by_sas_address(ioc,
22195 +                           rphy->identify.sas_address);
22196 +                       if (!port_info)
22197 +                               continue;
22198 +                       if (port_info == parent) /* backlink rphy */
22199 +                               continue;
22200 +                       mptsas_expander_delete(ioc, port_info);
22201 +               }
22202 +       }
22203 +}
22204  
22205 -       if (!hdr.PageLength)
22206 -               goto out;
22207  
22208 -       buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
22209 -           &dma_handle);
22210 +/**
22211 + *     mptsas_expander_delete - remove this expander
22212 + *     @ioc: Pointer to MPT_ADAPTER structure
22213 + *     @port_info: expander port_info struct
22214 + *
22215 + **/
22216  
22217 -       if (!buffer)
22218 -               goto out;
22219 +static void
22220 +mptsas_expander_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
22221 +{
22222  
22223 -       cfg.physAddr = dma_handle;
22224 -       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
22225 +       struct mptsas_portinfo *parent;
22226 +       int             i;
22227 +       u64             expander_sas_address;
22228 +       struct mptsas_phyinfo *phy_info;
22229 +       struct mptsas_portinfo buffer;
22230 +       struct mptsas_portinfo_details * port_details;
22231 +       struct sas_port * port;
22232  
22233 -       if (mpt_config(ioc, &cfg) != 0)
22234 -               goto out;
22235 +       if (!port_info)
22236 +               return;
22237  
22238 -       if (!(buffer->VolumeStatus.Flags &
22239 -           MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
22240 -               goto out;
22241 +       /* see if expander is still there before deleting */
22242 +       mptsas_sas_expander_pg0(ioc, &buffer,
22243 +           (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
22244 +           MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
22245 +           port_info->phy_info[0].identify.handle);
22246  
22247 -       if (!buffer->NumPhysDisks)
22248 -               goto out;
22249 +       if (buffer.num_phys) {
22250 +               kfree(buffer.phy_info);
22251 +               return;
22252 +       }
22253  
22254 -       for (i = 0; i < buffer->NumPhysDisks; i++) {
22255  
22256 -               if (mpt_raid_phys_disk_pg0(ioc,
22257 -                   buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
22258 -                       continue;
22259 +       /*
22260 +        * Obtain the port_info instance to the parent port
22261 +        */
22262 +       port_details = NULL;
22263 +       expander_sas_address =
22264 +           port_info->phy_info[0].identify.sas_address;
22265 +       parent = mptsas_find_portinfo_by_handle(ioc,
22266 +           port_info->phy_info[0].identify.handle_parent);
22267 +       mptsas_delete_expander_siblings(ioc, parent, port_info);
22268 +       if (!parent)
22269 +               goto out;
22270  
22271 -               ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
22272 -               if (!ev) {
22273 -                       printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name);
22274 -                       goto out;
22275 +       /*
22276 +        * Delete rphys in the parent that point
22277 +        * to this expander.
22278 +        */
22279 +       phy_info = parent->phy_info;
22280 +       port = NULL;
22281 +       for (i = 0; i < parent->num_phys; i++, phy_info++) {
22282 +               if(!phy_info->phy)
22283 +                       continue;
22284 +               if (phy_info->attached.sas_address !=
22285 +                   expander_sas_address)
22286 +                       continue;
22287 +               if (!port) {
22288 +                       port = mptsas_get_port(phy_info);
22289 +                       port_details = phy_info->port_details;
22290                 }
22291 -
22292 -               INIT_WORK(&ev->work, mptsas_hotplug_work);
22293 -               ev->ioc = ioc;
22294 -               ev->id = phys_disk.PhysDiskID;
22295 -               ev->channel = phys_disk.PhysDiskBus;
22296 -               ev->phys_disk_num_valid = 1;
22297 -               ev->phys_disk_num = phys_disk.PhysDiskNum;
22298 -               ev->event_type = MPTSAS_ADD_DEVICE;
22299 -               schedule_work(&ev->work);
22300 +               dev_printk(KERN_DEBUG, &phy_info->phy->dev,
22301 +                   MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
22302 +                   phy_info->phy_id, phy_info->phy);
22303 +               sas_port_delete_phy(port, phy_info->phy);
22304 +       }
22305 +       if (port) {
22306 +               dev_printk(KERN_DEBUG, &port->dev,
22307 +                   MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
22308 +                   ioc->name, port->port_identifier,
22309 +                   (unsigned long long)expander_sas_address);
22310 +               sas_port_delete(port);
22311 +               mptsas_port_delete(ioc, port_details);
22312         }
22313 -
22314   out:
22315 -       if (buffer)
22316 -               pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
22317 -                   dma_handle);
22318 +
22319 +       printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
22320 +           "sas_addr (0x%llx)\n",  ioc->name, port_info->num_phys,
22321 +           (unsigned long long)expander_sas_address);
22322 +
22323 +       /*
22324 +        * free link
22325 +        */
22326 +       list_del(&port_info->list);
22327 +       kfree(port_info->phy_info);
22328 +       kfree(port_info);
22329  }
22330 -/*
22331 - * Work queue thread to handle SAS hotplug events
22332 +
22333 +
22334 +/**
22335 + * mptsas_send_expander_event - expanders events
22336 + * @ioc: Pointer to MPT_ADAPTER structure
22337 + * @expander_data: event data
22338 + *
22339 + *
22340 + * This function handles adding, removing, and refreshing
22341 + * device handles within the expander objects.
22342   */
22343  static void
22344 -mptsas_hotplug_work(struct work_struct *work)
22345 +mptsas_send_expander_event(struct fw_event_work *fw_event)
22346  {
22347 -       struct mptsas_hotplug_event *ev =
22348 -               container_of(work, struct mptsas_hotplug_event, work);
22349 +       MPT_ADAPTER *ioc;
22350 +       MpiEventDataSasExpanderStatusChange_t* expander_data;
22351 +       struct mptsas_portinfo *port_info;
22352 +       __le64 sas_address;
22353 +       int i;
22354  
22355 -       MPT_ADAPTER *ioc = ev->ioc;
22356 -       struct mptsas_phyinfo *phy_info;
22357 -       struct sas_rphy *rphy;
22358 -       struct sas_port *port;
22359 -       struct scsi_device *sdev;
22360 -       struct scsi_target * starget;
22361 -       struct sas_identify identify;
22362 -       char *ds = NULL;
22363 -       struct mptsas_devinfo sas_device;
22364 -       VirtTarget *vtarget;
22365 -       VirtDevice *vdevice;
22366 +       ioc = fw_event->ioc;
22367 +       expander_data = (MpiEventDataSasExpanderStatusChange_t *)
22368 +           fw_event->event_data;
22369 +       memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
22370 +       port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
22371 +
22372 +       if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
22373 +               if (port_info) {
22374 +                       for (i = 0; i < port_info->num_phys; i++) {
22375 +                               port_info->phy_info[i].portinfo = port_info;
22376 +                               port_info->phy_info[i].handle =
22377 +                                   le16_to_cpu(expander_data->DevHandle);
22378 +                               port_info->phy_info[i].identify.sas_address =
22379 +                                   le64_to_cpu(sas_address);
22380 +                               port_info->phy_info[i].identify.handle_parent =
22381 +                                   le16_to_cpu(expander_data->ParentDevHandle);
22382 +                       }
22383 +                       mptsas_expander_refresh(ioc, port_info);
22384 +               } else if (!port_info && expander_data->NumPhys)
22385 +                       mptsas_expander_event_add(ioc, expander_data);
22386 +       } else if (expander_data->ReasonCode ==
22387 +           MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
22388 +               mptsas_expander_delete(ioc, port_info);
22389  
22390 -       mutex_lock(&ioc->sas_discovery_mutex);
22391 -       switch (ev->event_type) {
22392 -       case MPTSAS_DEL_DEVICE:
22393 +       mptsas_free_fw_event(ioc, fw_event);
22394 +}
22395  
22396 -               phy_info = NULL;
22397 -               if (ev->phys_disk_num_valid) {
22398 -                       if (ev->hidden_raid_component){
22399 -                               if (mptsas_sas_device_pg0(ioc, &sas_device,
22400 -                                   (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
22401 -                                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
22402 -                                   (ev->channel << 8) + ev->id)) {
22403 -                                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22404 -                                       "%s: exit at line=%d\n", ioc->name,
22405 -                                               __func__, __LINE__));
22406 -                                       break;
22407 -                               }
22408 -                               phy_info = mptsas_find_phyinfo_by_sas_address(
22409 -                                   ioc, sas_device.sas_address);
22410 -                       }else
22411 -                               phy_info = mptsas_find_phyinfo_by_phys_disk_num(
22412 -                                   ioc, ev->channel, ev->phys_disk_num);
22413 -               }
22414  
22415 -               if (!phy_info)
22416 -                       phy_info = mptsas_find_phyinfo_by_target(ioc,
22417 -                           ev->channel, ev->id);
22418 +/**
22419 + * mptsas_expander_add -
22420 + * @ioc: Pointer to MPT_ADAPTER structure
22421 + * @handle:
22422 + *
22423 + */
22424 +struct mptsas_portinfo *
22425 +mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
22426 +{
22427 +       struct mptsas_portinfo buffer, *port_info;
22428 +       int i;
22429  
22430 -               /*
22431 -                * Sanity checks, for non-existing phys and remote rphys.
22432 -                */
22433 -               if (!phy_info){
22434 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22435 -                               "%s: exit at line=%d\n", ioc->name,
22436 -                               __func__, __LINE__));
22437 -                       break;
22438 -               }
22439 -               if (!phy_info->port_details) {
22440 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22441 -                               "%s: exit at line=%d\n", ioc->name,
22442 -                               __func__, __LINE__));
22443 -                       break;
22444 -               }
22445 -               rphy = mptsas_get_rphy(phy_info);
22446 -               if (!rphy) {
22447 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22448 -                               "%s: exit at line=%d\n", ioc->name,
22449 -                               __func__, __LINE__));
22450 -                       break;
22451 -               }
22452 +       if ((mptsas_sas_expander_pg0(ioc, &buffer,
22453 +           (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
22454 +           MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
22455 +               return NULL;
22456  
22457 -               port = mptsas_get_port(phy_info);
22458 -               if (!port) {
22459 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22460 -                               "%s: exit at line=%d\n", ioc->name,
22461 -                               __func__, __LINE__));
22462 -                       break;
22463 -               }
22464 +       port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
22465 +       if (!port_info) {
22466 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22467 +               "%s: exit at line=%d\n", ioc->name,
22468 +               __FUNCTION__, __LINE__));
22469 +               return NULL;
22470 +       }
22471 +       port_info->num_phys = buffer.num_phys;
22472 +       port_info->phy_info = buffer.phy_info;
22473 +       for (i = 0; i < port_info->num_phys; i++)
22474 +               port_info->phy_info[i].portinfo = port_info;
22475 +       mutex_lock(&ioc->sas_topology_mutex);
22476 +       list_add_tail(&port_info->list, &ioc->sas_topology);
22477 +       mutex_unlock(&ioc->sas_topology_mutex);
22478 +       printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
22479 +           "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
22480 +           (unsigned long long)buffer.phy_info[0].identify.sas_address);
22481 +       mptsas_expander_refresh(ioc, port_info);
22482 +       return port_info;
22483 +}
22484  
22485 -               starget = mptsas_get_starget(phy_info);
22486 -               if (starget) {
22487 -                       vtarget = starget->hostdata;
22488 +static void
22489 +mptsas_send_link_status_event(struct fw_event_work *fw_event)
22490 +{
22491 +       MPT_ADAPTER *ioc;
22492 +       MpiEventDataSasPhyLinkStatus_t *link_data;
22493 +       struct mptsas_portinfo *port_info;
22494 +       struct mptsas_phyinfo *phy_info = NULL;
22495 +       __le64 sas_address;
22496 +       u8 phy_num;
22497 +       u8 link_rate;
22498  
22499 -                       if (!vtarget) {
22500 -                               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22501 -                                       "%s: exit at line=%d\n", ioc->name,
22502 -                                       __func__, __LINE__));
22503 -                               break;
22504 -                       }
22505 +       ioc = fw_event->ioc;
22506 +       link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
22507  
22508 -                       /*
22509 -                        * Handling  RAID components
22510 -                        */
22511 -                       if (ev->phys_disk_num_valid &&
22512 -                           ev->hidden_raid_component) {
22513 -                               printk(MYIOC_s_INFO_FMT
22514 -                                   "RAID Hidding: channel=%d, id=%d, "
22515 -                                   "physdsk %d \n", ioc->name, ev->channel,
22516 -                                   ev->id, ev->phys_disk_num);
22517 -                               vtarget->id = ev->phys_disk_num;
22518 -                               vtarget->tflags |=
22519 -                                   MPT_TARGET_FLAGS_RAID_COMPONENT;
22520 -                               mptsas_reprobe_target(starget, 1);
22521 -                               phy_info->attached.phys_disk_num =
22522 -                                   ev->phys_disk_num;
22523 -                       break;
22524 +       memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
22525 +       sas_address = le64_to_cpu(sas_address);
22526 +       link_rate = link_data->LinkRates >> 4;
22527 +       phy_num = link_data->PhyNum;
22528 +
22529 +       port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
22530 +       if (port_info) {
22531 +               phy_info = &port_info->phy_info[phy_num];
22532 +               if (phy_info)
22533 +                       phy_info->negotiated_link_rate = link_rate;
22534 +       }
22535 +
22536 +       if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
22537 +           link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
22538 +
22539 +               if (!port_info) {
22540 +                       if (ioc->old_sas_discovery_protocal) {
22541 +                               port_info = mptsas_expander_add(ioc,
22542 +                                   le16_to_cpu(link_data->DevHandle));
22543 +                               if (port_info)
22544 +                                       goto out;
22545                         }
22546 +                       goto out;
22547                 }
22548 +               if (port_info == ioc->hba_port_info)
22549 +                       mptsas_probe_hba_phys(ioc);
22550 +               else
22551 +                       mptsas_expander_refresh(ioc, port_info);
22552 +       } else if (phy_info && phy_info->phy) {
22553 +               if (link_rate ==  MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
22554 +                       phy_info->phy->negotiated_linkrate =
22555 +                           SAS_PHY_DISABLED;
22556 +               else if (link_rate ==
22557 +                   MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
22558 +                       phy_info->phy->negotiated_linkrate =
22559 +                           SAS_LINK_RATE_FAILED;
22560 +               else
22561 +                       phy_info->phy->negotiated_linkrate =
22562 +                           SAS_LINK_RATE_UNKNOWN;
22563 +       }
22564 + out:
22565 +       mptsas_free_fw_event(ioc, fw_event);
22566 +}
22567  
22568 -               if (phy_info->attached.device_info &
22569 -                   MPI_SAS_DEVICE_INFO_SSP_TARGET)
22570 -                       ds = "ssp";
22571 -               if (phy_info->attached.device_info &
22572 -                   MPI_SAS_DEVICE_INFO_STP_TARGET)
22573 -                       ds = "stp";
22574 -               if (phy_info->attached.device_info &
22575 -                   MPI_SAS_DEVICE_INFO_SATA_DEVICE)
22576 -                       ds = "sata";
22577 -
22578 -               printk(MYIOC_s_INFO_FMT
22579 -                      "removing %s device, channel %d, id %d, phy %d\n",
22580 -                      ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
22581 -               dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
22582 -                   "delete port (%d)\n", ioc->name, port->port_identifier);
22583 -               sas_port_delete(port);
22584 -               mptsas_port_delete(ioc, phy_info->port_details);
22585 -               break;
22586 -       case MPTSAS_ADD_DEVICE:
22587 -
22588 -               if (ev->phys_disk_num_valid)
22589 -                       mpt_findImVolumes(ioc);
22590  
22591 -               /*
22592 -                * Refresh sas device pg0 data
22593 -                */
22594 -               if (mptsas_sas_device_pg0(ioc, &sas_device,
22595 -                   (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
22596 -                    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
22597 -                       (ev->channel << 8) + ev->id)) {
22598 -                               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22599 -                                       "%s: exit at line=%d\n", ioc->name,
22600 -                                       __func__, __LINE__));
22601 -                       break;
22602 +static void
22603 +mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
22604 +{
22605 +       MPT_ADAPTER *ioc;
22606 +       EventDataQueueFull_t *qfull_data;
22607 +       struct sas_device_info *sas_info;
22608 +       struct scsi_device      *sdev;
22609 +       int depth;
22610 +       int id = -1;
22611 +       int channel = -1;
22612 +       int fw_id, fw_channel;
22613 +       u16 current_depth;
22614 +
22615 +
22616 +       ioc = fw_event->ioc;
22617 +       qfull_data = (EventDataQueueFull_t *)fw_event->event_data;
22618 +       fw_id = qfull_data->TargetID;
22619 +       fw_channel = qfull_data->Bus;
22620 +       current_depth = le16_to_cpu(qfull_data->CurrentDepth);
22621 +
22622 +       /* if hidden raid component, look for the volume id */
22623 +       down(&ioc->sas_device_info_mutex);
22624 +       if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
22625 +               list_for_each_entry(sas_info, &ioc->sas_device_info_list,
22626 +                   list) {
22627 +                       if (sas_info->is_cached ||
22628 +                           sas_info->is_logical_volume)
22629 +                               continue;
22630 +                       if (sas_info->is_hidden_raid_component &&
22631 +                           (sas_info->fw.channel == fw_channel &&
22632 +                           sas_info->fw.id == fw_id)) {
22633 +                               id = sas_info->volume_id;
22634 +                               channel = MPTSAS_RAID_CHANNEL;
22635 +                               goto out;
22636 +                       }
22637                 }
22638 -
22639 -               __mptsas_discovery_work(ioc);
22640 -
22641 -               phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
22642 -                               sas_device.sas_address);
22643 -
22644 -               if (!phy_info || !phy_info->port_details) {
22645 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22646 -                               "%s: exit at line=%d\n", ioc->name,
22647 -                               __func__, __LINE__));
22648 -                       break;
22649 +       } else {
22650 +               list_for_each_entry(sas_info, &ioc->sas_device_info_list,
22651 +                   list) {
22652 +                       if (sas_info->is_cached ||
22653 +                           sas_info->is_hidden_raid_component ||
22654 +                           sas_info->is_logical_volume)
22655 +                               continue;
22656 +                       if (sas_info->fw.channel == fw_channel &&
22657 +                           sas_info->fw.id == fw_id) {
22658 +                               id = sas_info->os.id;
22659 +                               channel = sas_info->os.channel;
22660 +                               goto out;
22661 +                       }
22662                 }
22663  
22664 -               starget = mptsas_get_starget(phy_info);
22665 -               if (starget && (!ev->hidden_raid_component)){
22666 -
22667 -                       vtarget = starget->hostdata;
22668 +       }
22669  
22670 -                       if (!vtarget) {
22671 -                               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22672 -                                   "%s: exit at line=%d\n", ioc->name,
22673 -                                   __func__, __LINE__));
22674 -                               break;
22675 -                       }
22676 -                       /*
22677 -                        * Handling  RAID components
22678 -                        */
22679 -                       if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
22680 -                               printk(MYIOC_s_INFO_FMT
22681 -                                   "RAID Exposing: channel=%d, id=%d, "
22682 -                                   "physdsk %d \n", ioc->name, ev->channel,
22683 -                                   ev->id, ev->phys_disk_num);
22684 -                               vtarget->tflags &=
22685 -                                   ~MPT_TARGET_FLAGS_RAID_COMPONENT;
22686 -                               vtarget->id = ev->id;
22687 -                               mptsas_reprobe_target(starget, 0);
22688 -                               phy_info->attached.phys_disk_num = ~0;
22689 + out:
22690 +       up(&ioc->sas_device_info_mutex);
22691 +
22692 +       if (id != -1) {
22693 +               shost_for_each_device(sdev, ioc->sh) {
22694 +                       if (sdev->id == id && sdev->channel == channel) {
22695 +                               if (current_depth > sdev->queue_depth) {
22696 +                                       sdev_printk(KERN_INFO, sdev,
22697 +                                           "strange observation, the queue "
22698 +                                           "depth is (%d) meanwhile fw queue "
22699 +                                           "depth (%d)\n", sdev->queue_depth,
22700 +                                           current_depth);
22701 +                                       continue;
22702 +                               }
22703 +                               depth = scsi_track_queue_full(sdev,
22704 +                                   current_depth - 1);
22705 +                               if (depth > 0)
22706 +                                       sdev_printk(KERN_INFO, sdev,
22707 +                                       "Queue depth reduced to (%d)\n",
22708 +                                          depth);
22709 +                               else if (depth < 0)
22710 +                                       sdev_printk(KERN_INFO, sdev,
22711 +                                       "Tagged Command Queueing is being "
22712 +                                       "disabled\n");
22713 +                               else if (depth == 0)
22714 +                                       sdev_printk(KERN_INFO, sdev,
22715 +                                       "Queue depth not changed yet\n");
22716                         }
22717 -                       break;
22718                 }
22719 +       }
22720  
22721 -               if (mptsas_get_rphy(phy_info)) {
22722 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22723 -                               "%s: exit at line=%d\n", ioc->name,
22724 -                               __func__, __LINE__));
22725 -                       if (ev->channel) printk("%d\n", __LINE__);
22726 -                       break;
22727 -               }
22728 +       mptsas_free_fw_event(ioc, fw_event);
22729 +}
22730  
22731 -               port = mptsas_get_port(phy_info);
22732 -               if (!port) {
22733 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22734 -                               "%s: exit at line=%d\n", ioc->name,
22735 -                               __func__, __LINE__));
22736 -                       break;
22737 -               }
22738 -               memcpy(&phy_info->attached, &sas_device,
22739 -                   sizeof(struct mptsas_devinfo));
22740 +/**
22741 + * mptsas_firmware_event_work - work thread for processing fw events
22742 + * @work: work queue payload containing info describing the event
22743 + * Context: user
22744 + *
22745 + */
22746 +static void
22747 +mptsas_firmware_event_work(struct work_struct *work)
22748 +{
22749 +       struct fw_event_work *fw_event =
22750 +               container_of(work, struct fw_event_work, work.work);
22751 +       MPT_ADAPTER *ioc = fw_event->ioc;
22752 +
22753 +       /* special rescan topology handling */
22754 +       if (fw_event->event == -1) {
22755 +               devtprintk(ioc, printk(MYIOC_s_INFO_FMT "%s: rescan after "
22756 +                   "reset\n", ioc->name,__FUNCTION__));
22757 +               mptsas_not_responding_devices(ioc);
22758 +               mptsas_scan_sas_topology(ioc);
22759 +               mptsas_free_fw_event(ioc, fw_event);
22760 +               return;
22761 +       }
22762  
22763 -               if (phy_info->attached.device_info &
22764 -                   MPI_SAS_DEVICE_INFO_SSP_TARGET)
22765 -                       ds = "ssp";
22766 -               if (phy_info->attached.device_info &
22767 -                   MPI_SAS_DEVICE_INFO_STP_TARGET)
22768 -                       ds = "stp";
22769 -               if (phy_info->attached.device_info &
22770 -                   MPI_SAS_DEVICE_INFO_SATA_DEVICE)
22771 -                       ds = "sata";
22772 -
22773 -               printk(MYIOC_s_INFO_FMT
22774 -                      "attaching %s device, channel %d, id %d, phy %d\n",
22775 -                      ioc->name, ds, ev->channel, ev->id, ev->phy_id);
22776 +       /* events handling turned off during host reset */
22777 +       if (ioc->fw_events_off) {
22778 +               mptsas_free_fw_event(ioc, fw_event);
22779 +               return;
22780 +       }
22781  
22782 -               mptsas_parse_device_info(&identify, &phy_info->attached);
22783 -               rphy = sas_end_device_alloc(port);
22784 -               if (!rphy) {
22785 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22786 -                               "%s: exit at line=%d\n", ioc->name,
22787 -                               __func__, __LINE__));
22788 -                       break; /* non-fatal: an rphy can be added later */
22789 -               }
22790 +       devtprintk(ioc, printk(MYIOC_s_INFO_FMT "%s: fw_event=(0x%p), "
22791 +           "event = (0x%02x)\n", ioc->name,__FUNCTION__, fw_event,
22792 +           (fw_event->event & 0xFF)));
22793  
22794 -               rphy->identify = identify;
22795 -               if (sas_rphy_add(rphy)) {
22796 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
22797 -                               "%s: exit at line=%d\n", ioc->name,
22798 -                               __func__, __LINE__));
22799 -                       sas_rphy_free(rphy);
22800 -                       break;
22801 -               }
22802 -               mptsas_set_rphy(ioc, phy_info, rphy);
22803 +       switch (fw_event->event) {
22804 +       case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
22805 +               mptsas_send_sas_event(fw_event);
22806                 break;
22807 -       case MPTSAS_ADD_RAID:
22808 -               sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
22809 -                   ev->id, 0);
22810 -               if (sdev) {
22811 -                       scsi_device_put(sdev);
22812 -                       break;
22813 -               }
22814 -               printk(MYIOC_s_INFO_FMT
22815 -                      "attaching raid volume, channel %d, id %d\n",
22816 -                      ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
22817 -               scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
22818 -               mpt_findImVolumes(ioc);
22819 +       case MPI_EVENT_INTEGRATED_RAID:
22820 +               mptsas_send_raid_event(fw_event);
22821                 break;
22822 -       case MPTSAS_DEL_RAID:
22823 -               sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
22824 -                   ev->id, 0);
22825 -               if (!sdev)
22826 -                       break;
22827 -               printk(MYIOC_s_INFO_FMT
22828 -                      "removing raid volume, channel %d, id %d\n",
22829 -                      ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
22830 -               vdevice = sdev->hostdata;
22831 -               scsi_remove_device(sdev);
22832 -               scsi_device_put(sdev);
22833 -               mpt_findImVolumes(ioc);
22834 +       case MPI_EVENT_IR2:
22835 +               mptsas_send_ir2_event(fw_event);
22836                 break;
22837 -       case MPTSAS_ADD_INACTIVE_VOLUME:
22838 -               mptsas_adding_inactive_raid_components(ioc,
22839 -                   ev->channel, ev->id);
22840 +       case MPI_EVENT_PERSISTENT_TABLE_FULL:
22841 +               mptbase_sas_persist_operation(ioc,
22842 +                   MPI_SAS_OP_CLEAR_NOT_PRESENT);
22843 +               mptsas_free_fw_event(ioc, fw_event);
22844                 break;
22845 -       case MPTSAS_IGNORE_EVENT:
22846 -       default:
22847 +       case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
22848 +               mptsas_broadcast_primative_work(fw_event);
22849 +               break;
22850 +       case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
22851 +               mptsas_send_expander_event(fw_event);
22852 +               break;
22853 +       case MPI_EVENT_SAS_PHY_LINK_STATUS:
22854 +               mptsas_send_link_status_event(fw_event);
22855 +               break;
22856 +       case MPI_EVENT_QUEUE_FULL:
22857 +               mptsas_handle_queue_full_event(fw_event);
22858                 break;
22859         }
22860 -
22861 -       mutex_unlock(&ioc->sas_discovery_mutex);
22862 -       kfree(ev);
22863  }
22864  
22865 -static void
22866 -mptsas_send_sas_event(MPT_ADAPTER *ioc,
22867 -               EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
22868 -{
22869 -       struct mptsas_hotplug_event *ev;
22870 -       u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
22871 -       __le64 sas_address;
22872  
22873 -       if ((device_info &
22874 -            (MPI_SAS_DEVICE_INFO_SSP_TARGET |
22875 -             MPI_SAS_DEVICE_INFO_STP_TARGET |
22876 -             MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
22877 -               return;
22878 +/**
22879 + *     mptsas_event_process -
22880 + *     @ioc: Pointer to MPT_ADAPTER structure
22881 + *     @reply:
22882 + *
22883 + **/
22884 +static int
22885 +mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
22886 +{
22887 +       u32 event = le32_to_cpu(reply->Event);
22888 +       int sz, event_data_sz;
22889 +       struct fw_event_work *fw_event;
22890 +       unsigned long delay;
22891  
22892 -       switch (sas_event_data->ReasonCode) {
22893 -       case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
22894 +       /* events turned off due to host reset or driver unloading */
22895 +       if (ioc->fw_events_off)
22896 +               return 0;
22897  
22898 -               mptsas_target_reset_queue(ioc, sas_event_data);
22899 +       delay = msecs_to_jiffies(1);
22900 +       switch (event) {
22901 +       case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
22902 +       {
22903 +               EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data =
22904 +                   (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data;
22905 +               if (broadcast_event_data->Primitive !=
22906 +                   MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
22907 +                       return 0;
22908 +               if (ioc->broadcast_aen_busy)
22909 +                       return 0;
22910 +               ioc->broadcast_aen_busy = 1;
22911                 break;
22912 +       }
22913 +       case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
22914 +       {
22915 +               EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
22916 +                   (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
22917  
22918 -       case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
22919 -               ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
22920 -               if (!ev) {
22921 -                       printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
22922 -                       break;
22923 +               if (sas_event_data->ReasonCode ==
22924 +                   MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
22925 +                       mptsas_target_reset_queue(ioc, sas_event_data);
22926 +                       return 0;
22927                 }
22928 +               break;
22929 +       }
22930 +       case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
22931 +       {
22932 +               MpiEventDataSasExpanderStatusChange_t *expander_data =
22933 +                   (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
22934  
22935 -               INIT_WORK(&ev->work, mptsas_hotplug_work);
22936 -               ev->ioc = ioc;
22937 -               ev->handle = le16_to_cpu(sas_event_data->DevHandle);
22938 -               ev->parent_handle =
22939 -                   le16_to_cpu(sas_event_data->ParentDevHandle);
22940 -               ev->channel = sas_event_data->Bus;
22941 -               ev->id = sas_event_data->TargetID;
22942 -               ev->phy_id = sas_event_data->PhyNum;
22943 -               memcpy(&sas_address, &sas_event_data->SASAddress,
22944 -                   sizeof(__le64));
22945 -               ev->sas_address = le64_to_cpu(sas_address);
22946 -               ev->device_info = device_info;
22947 +               if (ioc->old_sas_discovery_protocal)
22948 +                       return 0;
22949  
22950 -               if (sas_event_data->ReasonCode &
22951 -                   MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
22952 -                       ev->event_type = MPTSAS_ADD_DEVICE;
22953 -               else
22954 -                       ev->event_type = MPTSAS_DEL_DEVICE;
22955 -               schedule_work(&ev->work);
22956 +               if (expander_data->ReasonCode ==
22957 +                   MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
22958 +                   ioc->device_missing_delay)
22959 +                       delay = HZ * ioc->device_missing_delay;
22960                 break;
22961 -       case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
22962 -       /*
22963 -        * Persistent table is full.
22964 -        */
22965 -               INIT_WORK(&ioc->sas_persist_task,
22966 -                   mptsas_persist_clear_table);
22967 -               schedule_work(&ioc->sas_persist_task);
22968 +       }
22969 +       case MPI_EVENT_SAS_DISCOVERY:
22970 +       {
22971 +               u32 discovery_status;
22972 +               EventDataSasDiscovery_t *discovery_data =
22973 +                   (EventDataSasDiscovery_t *)reply->Data;
22974 +
22975 +               discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
22976 +               ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
22977 +               if (ioc->old_sas_discovery_protocal && !discovery_status)
22978 +                       mptsas_queue_rescan(ioc);
22979 +               return 0;
22980 +       }
22981 +       case MPI_EVENT_INTEGRATED_RAID:
22982 +       case MPI_EVENT_PERSISTENT_TABLE_FULL:
22983 +       case MPI_EVENT_IR2:
22984 +       case MPI_EVENT_SAS_PHY_LINK_STATUS:
22985 +       case MPI_EVENT_QUEUE_FULL:
22986                 break;
22987 -       /*
22988 -        * TODO, handle other events
22989 -        */
22990 -       case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
22991 -       case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
22992 -       case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
22993 -       case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
22994 -       case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
22995 -       case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
22996 -       case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
22997         default:
22998 -               break;
22999 +               return 0;
23000         }
23001 +
23002 +       event_data_sz = ((reply->MsgLength * 4) -
23003 +           offsetof(EventNotificationReply_t, Data));
23004 +       sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
23005 +       fw_event = kzalloc(sz, GFP_ATOMIC);
23006 +       if (!fw_event) {
23007 +               printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
23008 +                   __FUNCTION__, __LINE__);
23009 +               return 0;
23010 +       }
23011 +       memcpy(fw_event->event_data, reply->Data, event_data_sz);
23012 +       fw_event->event = event;
23013 +       fw_event->ioc = ioc;
23014 +       mptsas_add_fw_event(ioc, fw_event, delay);
23015 +       return 0;
23016  }
23017 -static void
23018 -mptsas_send_raid_event(MPT_ADAPTER *ioc,
23019 -               EVENT_DATA_RAID *raid_event_data)
23020 +
23021 +
23022 +/* Delete a volume when no longer listed in ioc pg2
23023 + */
23024 +static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
23025  {
23026 -       struct mptsas_hotplug_event *ev;
23027 -       int status = le32_to_cpu(raid_event_data->SettingsStatus);
23028 -       int state = (status >> 8) & 0xff;
23029 +       struct scsi_device *sdev;
23030 +       int i;
23031  
23032 -       if (ioc->bus_type != SAS)
23033 +       sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0);
23034 +       if (!sdev)
23035                 return;
23036 +       if (!ioc->raid_data.pIocPg2)
23037 +               goto out;
23038 +       if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
23039 +               goto out;
23040 +       for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
23041 +               if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id)
23042 +                       goto release_sdev;
23043 + out:
23044 +       printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
23045 +           "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,id);
23046 +       scsi_remove_device(sdev);
23047 + release_sdev:
23048 +       scsi_device_put(sdev);
23049 +}
23050 +
23051 +static void
23052 +mptsas_not_responding_devices(MPT_ADAPTER *ioc)
23053 +{
23054 +       struct mptsas_portinfo buffer, *port_info;
23055 +       struct sas_device_info  *sas_info;
23056 +       struct mptsas_devinfo sas_device;
23057 +       u32     handle;
23058 +       VirtTarget *vtarget = NULL;
23059 +       struct mptsas_phyinfo *phy_info;
23060 +       u8 found_expander;
23061  
23062 -       ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
23063 -       if (!ev) {
23064 -               printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
23065 +       if (ioc->disable_hotplug_remove)
23066                 return;
23067 +
23068 +       mpt_findImVolumes(ioc);
23069 +
23070 +       /* devices, logical volumes */
23071 + redo_device_scan:
23072 +       list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
23073 +               if (sas_info->is_cached)
23074 +                       continue;
23075 +               if (!sas_info->is_logical_volume) {
23076 +                       sas_device.handle = 0;
23077 +                       mptsas_sas_device_pg0(ioc, &sas_device,
23078 +                           (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
23079 +                            MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
23080 +                               (sas_info->fw.channel << 8) +
23081 +                               sas_info->fw.id);
23082 +                       if (sas_device.handle)
23083 +                               continue;
23084 +                       /* delete device */
23085 +                       if ((vtarget = mptsas_find_vtarget(ioc,
23086 +                                   sas_info->fw.channel,
23087 +                           sas_info->fw.id)))
23088 +                               vtarget->deleted = 1;
23089 +                       phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
23090 +                           sas_info->sas_address);
23091 +                       if (phy_info) {
23092 +                               mptsas_del_end_device(ioc, phy_info);
23093 +                               goto redo_device_scan;
23094 +                       }
23095 +               } else
23096 +                       mptsas_volume_delete(ioc, sas_info->fw.id);
23097         }
23098  
23099 -       INIT_WORK(&ev->work, mptsas_hotplug_work);
23100 -       ev->ioc = ioc;
23101 -       ev->id = raid_event_data->VolumeID;
23102 -       ev->channel = raid_event_data->VolumeBus;
23103 -       ev->event_type = MPTSAS_IGNORE_EVENT;
23104 +       /* expanders */
23105 + redo_expander_scan:
23106 +       list_for_each_entry(port_info, &ioc->sas_topology, list) {
23107  
23108 -       switch (raid_event_data->ReasonCode) {
23109 -       case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
23110 -               ev->phys_disk_num_valid = 1;
23111 -               ev->phys_disk_num = raid_event_data->PhysDiskNum;
23112 -               ev->event_type = MPTSAS_ADD_DEVICE;
23113 -               break;
23114 -       case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
23115 -               ev->phys_disk_num_valid = 1;
23116 -               ev->phys_disk_num = raid_event_data->PhysDiskNum;
23117 -               ev->hidden_raid_component = 1;
23118 -               ev->event_type = MPTSAS_DEL_DEVICE;
23119 -               break;
23120 -       case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
23121 -               switch (state) {
23122 -               case MPI_PD_STATE_ONLINE:
23123 -               case MPI_PD_STATE_NOT_COMPATIBLE:
23124 -                       ev->phys_disk_num_valid = 1;
23125 -                       ev->phys_disk_num = raid_event_data->PhysDiskNum;
23126 -                       ev->hidden_raid_component = 1;
23127 -                       ev->event_type = MPTSAS_ADD_DEVICE;
23128 -                       break;
23129 -               case MPI_PD_STATE_MISSING:
23130 -               case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
23131 -               case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
23132 -               case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
23133 -                       ev->phys_disk_num_valid = 1;
23134 -                       ev->phys_disk_num = raid_event_data->PhysDiskNum;
23135 -                       ev->event_type = MPTSAS_DEL_DEVICE;
23136 -                       break;
23137 -               default:
23138 -                       break;
23139 +               if (port_info->phy_info &&
23140 +                   (!(port_info->phy_info[0].identify.device_info &
23141 +                   MPI_SAS_DEVICE_INFO_SMP_TARGET)))
23142 +                       continue;
23143 +               found_expander = 0;
23144 +               handle = 0xFFFF;
23145 +               while (!mptsas_sas_expander_pg0(ioc, &buffer,
23146 +                   (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
23147 +                    MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) &&
23148 +                   !found_expander) {
23149 +
23150 +                       handle = buffer.phy_info[0].handle;
23151 +                       if (buffer.phy_info[0].identify.sas_address ==
23152 +                           port_info->phy_info[0].identify.sas_address) {
23153 +                               found_expander = 1;
23154 +                       }
23155 +                       kfree(buffer.phy_info);
23156                 }
23157 -               break;
23158 -       case MPI_EVENT_RAID_RC_VOLUME_DELETED:
23159 -               ev->event_type = MPTSAS_DEL_RAID;
23160 -               break;
23161 -       case MPI_EVENT_RAID_RC_VOLUME_CREATED:
23162 -               ev->event_type = MPTSAS_ADD_RAID;
23163 -               break;
23164 -       case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
23165 -               switch (state) {
23166 -               case MPI_RAIDVOL0_STATUS_STATE_FAILED:
23167 -               case MPI_RAIDVOL0_STATUS_STATE_MISSING:
23168 -                       ev->event_type = MPTSAS_DEL_RAID;
23169 -                       break;
23170 -               case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
23171 -               case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
23172 -                       ev->event_type = MPTSAS_ADD_RAID;
23173 -                       break;
23174 -               default:
23175 -                       break;
23176 +
23177 +               if (!found_expander) {
23178 +                       mptsas_expander_delete(ioc, port_info);
23179 +                       goto redo_expander_scan;
23180                 }
23181 -               break;
23182 -       default:
23183 -               break;
23184         }
23185 -       schedule_work(&ev->work);
23186  }
23187  
23188 +/**
23189 + *     mptsas_probe_expanders - adding expanders
23190 + *     @ioc: Pointer to MPT_ADAPTER structure
23191 + *
23192 + **/
23193  static void
23194 -mptsas_send_discovery_event(MPT_ADAPTER *ioc,
23195 -       EVENT_DATA_SAS_DISCOVERY *discovery_data)
23196 +mptsas_probe_expanders(MPT_ADAPTER *ioc)
23197  {
23198 -       struct mptsas_discovery_event *ev;
23199 +       struct mptsas_portinfo buffer, *port_info;
23200 +       u32                     handle;
23201 +       int i;
23202  
23203 -       /*
23204 -        * DiscoveryStatus
23205 -        *
23206 -        * This flag will be non-zero when firmware
23207 -        * kicks off discovery, and return to zero
23208 -        * once its completed.
23209 -        */
23210 -       if (discovery_data->DiscoveryStatus)
23211 -               return;
23212 +       handle = 0xFFFF;
23213 +       while (!mptsas_sas_expander_pg0(ioc, &buffer,
23214 +           (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
23215 +            MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
23216  
23217 -       ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
23218 -       if (!ev)
23219 -               return;
23220 -       INIT_WORK(&ev->work, mptsas_discovery_work);
23221 -       ev->ioc = ioc;
23222 -       schedule_work(&ev->work);
23223 -};
23224 +               handle = buffer.phy_info[0].handle;
23225 +               port_info = mptsas_find_portinfo_by_sas_address(ioc,
23226 +                   buffer.phy_info[0].identify.sas_address);
23227 +
23228 +               if (port_info) {
23229 +                       /* refreshing handles */
23230 +                       for (i = 0; i < buffer.num_phys; i++) {
23231 +                               port_info->phy_info[i].handle = handle;
23232 +                               port_info->phy_info[i].identify.handle_parent =
23233 +                                   buffer.phy_info[0].identify.handle_parent;
23234 +                       }
23235 +                       mptsas_expander_refresh(ioc, port_info);
23236 +                       kfree(buffer.phy_info);
23237 +                       continue;
23238 +               }
23239 +
23240 +               port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
23241 +               if (!port_info) {
23242 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
23243 +                       "%s: exit at line=%d\n", ioc->name,
23244 +                       __FUNCTION__, __LINE__));
23245 +                       return;
23246 +               }
23247 +               port_info->num_phys = buffer.num_phys;
23248 +               port_info->phy_info = buffer.phy_info;
23249 +               for (i = 0; i < port_info->num_phys; i++)
23250 +                       port_info->phy_info[i].portinfo = port_info;
23251 +               mutex_lock(&ioc->sas_topology_mutex);
23252 +               list_add_tail(&port_info->list, &ioc->sas_topology);
23253 +               mutex_unlock(&ioc->sas_topology_mutex);
23254 +               printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
23255 +                   "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
23256 +           (unsigned long long)buffer.phy_info[0].identify.sas_address);
23257 +               mptsas_expander_refresh(ioc, port_info);
23258 +       }
23259 +}
23260  
23261 -/*
23262 - * mptsas_send_ir2_event - handle exposing hidden disk when
23263 - * an inactive raid volume is added
23264 - *
23265 - * @ioc: Pointer to MPT_ADAPTER structure
23266 - * @ir2_data
23267 - *
23268 - */
23269  static void
23270 -mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
23271 +mptsas_probe_devices(MPT_ADAPTER *ioc)
23272  {
23273 -       struct mptsas_hotplug_event *ev;
23274 +       u16 retry_count;
23275 +       u16 handle;
23276 +       struct mptsas_devinfo sas_device;
23277 +       struct mptsas_phyinfo *phy_info;
23278 +       enum device_state state;
23279  
23280 -       if (ir2_data->ReasonCode !=
23281 -           MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
23282 -               return;
23283 +       handle = 0xFFFF;
23284 +       while (!(mptsas_sas_device_pg0(ioc, &sas_device,
23285 +           MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
23286 +
23287 +               handle = sas_device.handle;
23288 +
23289 +               if ((sas_device.device_info &
23290 +                    (MPI_SAS_DEVICE_INFO_SSP_TARGET |
23291 +                     MPI_SAS_DEVICE_INFO_STP_TARGET |
23292 +                     MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
23293 +                       continue;
23294  
23295 -       ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
23296 -       if (!ev)
23297 -               return;
23298 +               phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
23299 +               if (!phy_info)
23300 +                       continue;
23301  
23302 -       INIT_WORK(&ev->work, mptsas_hotplug_work);
23303 -       ev->ioc = ioc;
23304 -       ev->id = ir2_data->TargetID;
23305 -       ev->channel = ir2_data->Bus;
23306 -       ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
23307 +               if (mptsas_get_rphy(phy_info))
23308 +                       continue;
23309  
23310 -       schedule_work(&ev->work);
23311 -};
23312 +               state = DEVICE_RETRY;
23313 +               retry_count = 0;
23314 +               while(state == DEVICE_RETRY) {
23315 +                       state = mptsas_test_unit_ready(ioc, sas_device.channel,
23316 +                           sas_device.id, retry_count++);
23317 +                       ssleep(1);
23318 +               }
23319 +               if (state == DEVICE_READY)
23320 +                       mptsas_add_end_device(ioc, phy_info);
23321 +       }
23322 +}
23323  
23324 -static int
23325 -mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
23326 +/**
23327 + *     mptsas_scan_sas_topology -
23328 + *     @ioc: Pointer to MPT_ADAPTER structure
23329 + *     @sas_address:
23330 + *
23331 + **/
23332 +static void
23333 +mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
23334  {
23335 -       int rc=1;
23336 -       u8 event = le32_to_cpu(reply->Event) & 0xFF;
23337 +       struct scsi_device *sdev;
23338 +       int i;
23339  
23340 -       if (!ioc->sh)
23341 -               goto out;
23342 +       mptsas_probe_hba_phys(ioc);
23343 +       mptsas_probe_expanders(ioc);
23344 +       mptsas_probe_devices(ioc);
23345  
23346         /*
23347 -        * sas_discovery_ignore_events
23348 -        *
23349 -        * This flag is to prevent anymore processing of
23350 -        * sas events once mptsas_remove function is called.
23351 -        */
23352 -       if (ioc->sas_discovery_ignore_events) {
23353 -               rc = mptscsih_event_process(ioc, reply);
23354 -               goto out;
23355 -       }
23356 -
23357 -       switch (event) {
23358 -       case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
23359 -               mptsas_send_sas_event(ioc,
23360 -                       (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
23361 -               break;
23362 -       case MPI_EVENT_INTEGRATED_RAID:
23363 -               mptsas_send_raid_event(ioc,
23364 -                       (EVENT_DATA_RAID *)reply->Data);
23365 -               break;
23366 -       case MPI_EVENT_PERSISTENT_TABLE_FULL:
23367 -               INIT_WORK(&ioc->sas_persist_task,
23368 -                   mptsas_persist_clear_table);
23369 -               schedule_work(&ioc->sas_persist_task);
23370 -               break;
23371 -        case MPI_EVENT_SAS_DISCOVERY:
23372 -               mptsas_send_discovery_event(ioc,
23373 -                       (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
23374 -               break;
23375 -       case MPI_EVENT_IR2:
23376 -               mptsas_send_ir2_event(ioc,
23377 -                   (PTR_MPI_EVENT_DATA_IR2)reply->Data);
23378 -               break;
23379 -       default:
23380 -               rc = mptscsih_event_process(ioc, reply);
23381 -               break;
23382 +         Reporting RAID volumes.
23383 +       */
23384 +       if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
23385 +           !ioc->raid_data.pIocPg2->NumActiveVolumes)
23386 +               return;
23387 +       for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
23388 +               if ((sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
23389 +                   ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0))) {
23390 +                       scsi_device_put(sdev);
23391 +                       continue;
23392 +               }
23393 +               printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
23394 +                   "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
23395 +                   ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
23396 +               scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
23397 +                   ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
23398         }
23399 - out:
23400 -
23401 -       return rc;
23402  }
23403  
23404 +/**
23405 + *     mptsas_probe -
23406 + *     @pdev:
23407 + *     @id:
23408 + *
23409 + **/
23410  static int
23411  mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
23412  {
23413 @@ -3129,6 +5071,7 @@ mptsas_probe(struct pci_dev *pdev, const
23414                 return r;
23415  
23416         ioc = pci_get_drvdata(pdev);
23417 +       mptsas_fw_event_off(ioc);
23418         ioc->DoneCtx = mptsasDoneCtx;
23419         ioc->TaskCtx = mptsasTaskCtx;
23420         ioc->InternalCtx = mptsasInternalCtx;
23421 @@ -3173,7 +5116,7 @@ mptsas_probe(struct pci_dev *pdev, const
23422                         ioc->name);
23423                 error = -1;
23424                 goto out_mptsas_probe;
23425 -        }
23426 +       }
23427  
23428         spin_lock_irqsave(&ioc->FreeQlock, flags);
23429  
23430 @@ -3187,10 +5130,9 @@ mptsas_probe(struct pci_dev *pdev, const
23431  
23432         /* set 16 byte cdb's */
23433         sh->max_cmd_len = 16;
23434 -
23435 +       sh->can_queue = min_t(int, ioc->req_depth - 10, sh->can_queue);
23436         sh->max_id = ioc->pfacts[0].PortSCSIID;
23437         sh->max_lun = max_lun;
23438 -
23439         sh->transportt = mptsas_transport_template;
23440  
23441         /* Required entry.
23442 @@ -3199,10 +5141,10 @@ mptsas_probe(struct pci_dev *pdev, const
23443  
23444         INIT_LIST_HEAD(&ioc->sas_topology);
23445         mutex_init(&ioc->sas_topology_mutex);
23446 -       mutex_init(&ioc->sas_discovery_mutex);
23447         mutex_init(&ioc->sas_mgmt.mutex);
23448         init_completion(&ioc->sas_mgmt.done);
23449  
23450 +
23451         /* Verify that we won't exceed the maximum
23452          * number of chain buffers
23453          * We can optimize:  ZZ = req_sz/sizeof(SGE)
23454 @@ -3212,17 +5154,16 @@ mptsas_probe(struct pci_dev *pdev, const
23455          * A slightly different algorithm is required for
23456          * 64bit SGEs.
23457          */
23458 -       scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
23459 -       if (sizeof(dma_addr_t) == sizeof(u64)) {
23460 +
23461 +       scale = ioc->req_sz/ioc->SGE_size;
23462 +       if (ioc->sg_addr_size == sizeof(u64)) {
23463                 numSGE = (scale - 1) *
23464                   (ioc->facts.MaxChainDepth-1) + scale +
23465 -                 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
23466 -                 sizeof(u32));
23467 +                 (ioc->req_sz - 60) / ioc->SGE_size;
23468         } else {
23469                 numSGE = 1 + (scale - 1) *
23470                   (ioc->facts.MaxChainDepth-1) + scale +
23471 -                 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
23472 -                 sizeof(u32));
23473 +                 (ioc->req_sz - 64) / ioc->SGE_size;
23474         }
23475  
23476         if (numSGE < sh->sg_tablesize) {
23477 @@ -3250,34 +5191,17 @@ mptsas_probe(struct pci_dev *pdev, const
23478         dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
23479                  ioc->name, ioc->ScsiLookup));
23480  
23481 -       /* Clear the TM flags
23482 -        */
23483 -       hd->tmPending = 0;
23484 -       hd->tmState = TM_STATE_NONE;
23485 -       hd->resetPending = 0;
23486 -       hd->abortSCpnt = NULL;
23487 -
23488 -       /* Clear the pointer used to store
23489 -        * single-threaded commands, i.e., those
23490 -        * issued during a bus scan, dv and
23491 -        * configuration pages.
23492 -        */
23493 -       hd->cmdPtr = NULL;
23494 -
23495 -       /* Initialize this SCSI Hosts' timers
23496 -        * To use, set the timer expires field
23497 -        * and add_timer
23498 -        */
23499 -       init_timer(&hd->timer);
23500 -       hd->timer.data = (unsigned long) hd;
23501 -       hd->timer.function = mptscsih_timer_expired;
23502 -
23503 +       ioc->sdev_queue_depth = mpt_sdev_queue_depth;
23504         ioc->sas_data.ptClear = mpt_pt_clear;
23505 -
23506 -       init_waitqueue_head(&hd->scandv_waitq);
23507 -       hd->scandv_wait_done = 0;
23508         hd->last_queue_full = 0;
23509 +       ioc->disable_hotplug_remove = mpt_disable_hotplug_remove;
23510 +       if (ioc->disable_hotplug_remove)
23511 +               printk(MYIOC_s_INFO_FMT "disabling hotplug remove\n", ioc->name);
23512 +
23513         INIT_LIST_HEAD(&hd->target_reset_list);
23514 +       INIT_LIST_HEAD(&ioc->sas_device_info_list);
23515 +       init_MUTEX(&ioc->sas_device_info_mutex);
23516 +
23517         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
23518  
23519         if (ioc->sas_data.ptClear==1) {
23520 @@ -3292,8 +5216,11 @@ mptsas_probe(struct pci_dev *pdev, const
23521                 goto out_mptsas_probe;
23522         }
23523  
23524 +       /* older firmware doesn't support expander events */
23525 +       if ((ioc->facts.HeaderVersion >> 8) < 0xE)
23526 +               ioc->old_sas_discovery_protocal = 1;
23527         mptsas_scan_sas_topology(ioc);
23528 -
23529 +       mptsas_fw_event_on(ioc);
23530         return 0;
23531  
23532   out_mptsas_probe:
23533 @@ -3302,13 +5229,23 @@ mptsas_probe(struct pci_dev *pdev, const
23534         return error;
23535  }
23536  
23537 -static void __devexit mptsas_remove(struct pci_dev *pdev)
23538 +/**
23539 + *     mptsas_remove -
23540 + *     @pdev:
23541 + *
23542 + **/
23543 +static void __devexit
23544 +mptsas_remove(struct pci_dev *pdev)
23545  {
23546         MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
23547         struct mptsas_portinfo *p, *n;
23548         int i;
23549  
23550 -       ioc->sas_discovery_ignore_events = 1;
23551 +       mptsas_fw_event_off(ioc);
23552 +       mptsas_cleanup_fw_event_q(ioc);
23553 +
23554 +       mptsas_del_device_components(ioc);
23555 +
23556         sas_remove_host(ioc->sh);
23557  
23558         mutex_lock(&ioc->sas_topology_mutex);
23559 @@ -3316,11 +5253,12 @@ static void __devexit mptsas_remove(stru
23560                 list_del(&p->list);
23561                 for (i = 0 ; i < p->num_phys ; i++)
23562                         mptsas_port_delete(ioc, p->phy_info[i].port_details);
23563 +
23564                 kfree(p->phy_info);
23565                 kfree(p);
23566         }
23567         mutex_unlock(&ioc->sas_topology_mutex);
23568 -
23569 +       ioc->hba_port_info = NULL;
23570         mptscsih_remove(pdev);
23571  }
23572  
23573 @@ -3352,6 +5290,10 @@ static struct pci_driver mptsas_driver =
23574  #endif
23575  };
23576  
23577 +/**
23578 + *     mptsas_init -
23579 + *
23580 + **/
23581  static int __init
23582  mptsas_init(void)
23583  {
23584 @@ -3365,10 +5307,12 @@ mptsas_init(void)
23585                 return -ENODEV;
23586  
23587         mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
23588 -       mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
23589 +       mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
23590         mptsasInternalCtx =
23591                 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
23592         mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
23593 +       mptsasDeviceResetCtx =
23594 +               mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
23595  
23596         mpt_event_register(mptsasDoneCtx, mptsas_event_process);
23597         mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
23598 @@ -3380,6 +5324,10 @@ mptsas_init(void)
23599         return error;
23600  }
23601  
23602 +/**
23603 + *     mptsas_exit -
23604 + *
23605 + **/
23606  static void __exit
23607  mptsas_exit(void)
23608  {
23609 @@ -3393,6 +5341,7 @@ mptsas_exit(void)
23610         mpt_deregister(mptsasInternalCtx);
23611         mpt_deregister(mptsasTaskCtx);
23612         mpt_deregister(mptsasDoneCtx);
23613 +       mpt_deregister(mptsasDeviceResetCtx);
23614  }
23615  
23616  module_init(mptsas_init);
23617 --- a/drivers/message/fusion/mptsas.h
23618 +++ b/drivers/message/fusion/mptsas.h
23619 @@ -50,9 +50,10 @@
23620  /*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
23621  
23622  struct mptsas_target_reset_event {
23623 -       struct list_head        list;
23624 -       EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
23625 +       struct list_head        list;
23626 +       MpiEventDataSasDeviceStatusChange_t sas_event_data;
23627         u8      target_reset_issued;
23628 +       unsigned long    time_count;
23629  };
23630  
23631  enum mptsas_hotplug_action {
23632 @@ -61,11 +62,34 @@ enum mptsas_hotplug_action {
23633         MPTSAS_ADD_RAID,
23634         MPTSAS_DEL_RAID,
23635         MPTSAS_ADD_INACTIVE_VOLUME,
23636 +       MPTSAS_ADD_PHYSDISK,
23637 +       MPTSAS_ADD_PHYSDISK_REPROBE,
23638 +       MPTSAS_DEL_PHYSDISK,
23639 +       MPTSAS_DEL_PHYSDISK_REPROBE,
23640 +       MPTSAS_REQUEUE_EVENT,
23641         MPTSAS_IGNORE_EVENT,
23642  };
23643  
23644 +struct sas_mapping{
23645 +       u8                      id;
23646 +       u8                      channel;
23647 +};
23648 +
23649 +struct sas_device_info {
23650 +       struct list_head        list;
23651 +       struct sas_mapping      os;     /* operating system mapping*/
23652 +       struct sas_mapping      fw;     /* firmware mapping */
23653 +       u64                     sas_address;
23654 +       u32                     device_info; /* specific bits for devices */
23655 +       u16                     slot;           /* enclosure slot id */
23656 +       u64                     enclosure_logical_id; /*enclosure address */
23657 +       u8                      is_logical_volume; /* is this logical volume */
23658 +       u8                      is_hidden_raid_component; /* this belongs to volume */
23659 +       u8                      volume_id; /* this valid when is_hidden_raid_component set */
23660 +       u8                      is_cached;      /* cached data for a removed device */
23661 +};
23662 +
23663  struct mptsas_hotplug_event {
23664 -       struct work_struct      work;
23665         MPT_ADAPTER             *ioc;
23666         enum mptsas_hotplug_action event_type;
23667         u64                     sas_address;
23668 @@ -73,17 +97,28 @@ struct mptsas_hotplug_event {
23669         u8                      id;
23670         u32                     device_info;
23671         u16                     handle;
23672 -       u16                     parent_handle;
23673         u8                      phy_id;
23674 -       u8                      phys_disk_num_valid;    /* hrc (hidden raid component) */
23675         u8                      phys_disk_num;          /* hrc - unique index*/
23676 -       u8                      hidden_raid_component;  /* hrc - don't expose*/
23677 +       struct scsi_device      *sdev;
23678  };
23679  
23680 -struct mptsas_discovery_event {
23681 +
23682 +struct fw_event_work {
23683 +       struct list_head        list;
23684 +       struct delayed_work      work;
23685 +       MPT_ADAPTER             *ioc;
23686 +       u32                     event;
23687 +       u8                      retries;
23688 +       u8                      event_data[1];
23689 +};
23690 +
23691 +#if 0
23692 +struct mptsas_link_status_event {
23693         struct work_struct      work;
23694 +       MpiEventDataSasPhyLinkStatus_t link_data;
23695         MPT_ADAPTER             *ioc;
23696  };
23697 +#endif
23698  
23699  /*
23700   * SAS topology structures
23701 @@ -113,32 +148,35 @@ struct mptsas_devinfo {
23702   * Specific details on ports, wide/narrow
23703   */
23704  struct mptsas_portinfo_details{
23705 -       u16     num_phys;       /* number of phys belong to this port */
23706 -       u64     phy_bitmask;    /* TODO, extend support for 255 phys */
23707 -       struct sas_rphy *rphy;  /* transport layer rphy object */
23708 +       u16     num_phys;       /* number of phys beloing to this port */
23709 +       u64     phy_bitmask;    /* this needs extending to support 128 phys */
23710 +       struct sas_rphy *rphy; /* rphy for end devices */
23711         struct sas_port *port;  /* transport layer port object */
23712         struct scsi_target *starget;
23713         struct mptsas_portinfo *port_info;
23714  };
23715  
23716  struct mptsas_phyinfo {
23717 -       u16     handle;                 /* unique id to address this */
23718 -       u8      phy_id;                 /* phy index */
23719 -       u8      port_id;                /* firmware port identifier */
23720 +       u16     handle;                 /* handle for this phy */
23721 +       u8      phy_id;                 /* phy index */
23722 +       u8      port_id;                /* port number this phy is part of */
23723         u8      negotiated_link_rate;   /* nego'd link rate for this phy */
23724 -       u8      hw_link_rate;           /* hardware max/min phys link rate */
23725 +       u8      hw_link_rate;           /* hardware max/min phys link rate */
23726         u8      programmed_link_rate;   /* programmed max/min phy link rate */
23727         u8      sas_port_add_phy;       /* flag to request sas_port_add_phy*/
23728 +       u8      change_count;           /* change count of the phy */
23729 +       u8      port_flags;             /* info wrt host sas ports */
23730 +       u32     phy_info;               /* various info wrt the phy */
23731         struct mptsas_devinfo identify; /* point to phy device info */
23732         struct mptsas_devinfo attached; /* point to attached device info */
23733 -       struct sas_phy *phy;            /* transport layer phy object */
23734 +       struct sas_phy *phy;
23735         struct mptsas_portinfo *portinfo;
23736         struct mptsas_portinfo_details * port_details;
23737  };
23738  
23739  struct mptsas_portinfo {
23740         struct list_head list;
23741 -       u16             num_phys;       /* number of phys */
23742 +       u16     num_phys;               /* number of phys */
23743         struct mptsas_phyinfo *phy_info;
23744  };
23745  
23746 @@ -156,3 +194,4 @@ struct mptsas_enclosure {
23747  
23748  /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
23749  #endif
23750 +
23751 --- a/drivers/message/fusion/mptscsih.c
23752 +++ b/drivers/message/fusion/mptscsih.c
23753 @@ -53,7 +53,9 @@
23754  #include <linux/delay.h>       /* for mdelay */
23755  #include <linux/interrupt.h>   /* needed for in_interrupt() proto */
23756  #include <linux/reboot.h>      /* notifier code */
23757 +#include <linux/sched.h>
23758  #include <linux/workqueue.h>
23759 +#include <linux/pci.h>
23760  
23761  #include <scsi/scsi.h>
23762  #include <scsi/scsi_cmnd.h>
23763 @@ -77,10 +79,15 @@ MODULE_LICENSE("GPL");
23764  MODULE_VERSION(my_VERSION);
23765  
23766  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
23767 +typedef struct _BIG_SENSE_BUF {
23768 +       u8              data[MPT_SENSE_BUFFER_ALLOC];
23769 +} BIG_SENSE_BUF;
23770 +
23771 +
23772  /*
23773   *  Other private/forward protos...
23774   */
23775 -static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
23776 +struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
23777  static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
23778  static void    mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
23779  static int     SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
23780 @@ -92,17 +99,10 @@ static int  mptscsih_AddSGE(MPT_ADAPTER *
23781                                  SCSIIORequest_t *pReq, int req_idx);
23782  static void    mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
23783  static void    mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
23784 -static int     mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
23785 -static int     mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
23786 -
23787 -static int     mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
23788  
23789  int            mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
23790  int            mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
23791 -
23792 -int            mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
23793 -static int     mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
23794 -static void    mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
23795 +static void    mptscsih_synchronize_cache(struct scsi_device *sdev, MPT_SCSI_HOST *hd, VirtDevice *vdevice);
23796  
23797  void           mptscsih_remove(struct pci_dev *);
23798  void           mptscsih_shutdown(struct pci_dev *);
23799 @@ -111,81 +111,17 @@ int               mptscsih_suspend(struct pci_dev *p
23800  int            mptscsih_resume(struct pci_dev *pdev);
23801  #endif
23802  
23803 -#define SNS_LEN(scp)   SCSI_SENSE_BUFFERSIZE
23804 -
23805 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
23806 -/**
23807 - *     mptscsih_add_sge - Place a simple SGE at address pAddr.
23808 - *     @pAddr: virtual address for SGE
23809 - *     @flagslength: SGE flags and data transfer length
23810 - *     @dma_addr: Physical address
23811 - *
23812 - *     This routine places a MPT request frame back on the MPT adapter's
23813 - *     FreeQ.
23814 - */
23815 -static inline void
23816 -mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
23817 -{
23818 -       if (sizeof(dma_addr_t) == sizeof(u64)) {
23819 -               SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
23820 -               u32 tmp = dma_addr & 0xFFFFFFFF;
23821 -
23822 -               pSge->FlagsLength = cpu_to_le32(flagslength);
23823 -               pSge->Address.Low = cpu_to_le32(tmp);
23824 -               tmp = (u32) ((u64)dma_addr >> 32);
23825 -               pSge->Address.High = cpu_to_le32(tmp);
23826 -
23827 -       } else {
23828 -               SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
23829 -               pSge->FlagsLength = cpu_to_le32(flagslength);
23830 -               pSge->Address = cpu_to_le32(dma_addr);
23831 -       }
23832 -} /* mptscsih_add_sge() */
23833 +#define SNS_LEN(scp)   sizeof((scp)->sense_buffer)
23834  
23835  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
23836  /**
23837 - *     mptscsih_add_chain - Place a chain SGE at address pAddr.
23838 - *     @pAddr: virtual address for SGE
23839 - *     @next: nextChainOffset value (u32's)
23840 - *     @length: length of next SGL segment
23841 - *     @dma_addr: Physical address
23842 - *
23843 - *     This routine places a MPT request frame back on the MPT adapter's
23844 - *     FreeQ.
23845 - */
23846 -static inline void
23847 -mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
23848 -{
23849 -       if (sizeof(dma_addr_t) == sizeof(u64)) {
23850 -               SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
23851 -               u32 tmp = dma_addr & 0xFFFFFFFF;
23852 -
23853 -               pChain->Length = cpu_to_le16(length);
23854 -               pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
23855 -
23856 -               pChain->NextChainOffset = next;
23857 -
23858 -               pChain->Address.Low = cpu_to_le32(tmp);
23859 -               tmp = (u32) ((u64)dma_addr >> 32);
23860 -               pChain->Address.High = cpu_to_le32(tmp);
23861 -       } else {
23862 -               SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
23863 -               pChain->Length = cpu_to_le16(length);
23864 -               pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
23865 -               pChain->NextChainOffset = next;
23866 -               pChain->Address = cpu_to_le32(dma_addr);
23867 -       }
23868 -} /* mptscsih_add_chain() */
23869 -
23870 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
23871 -/*
23872   *     mptscsih_getFreeChainBuffer - Function to get a free chain
23873   *     from the MPT_SCSI_HOST FreeChainQ.
23874   *     @ioc: Pointer to MPT_ADAPTER structure
23875   *     @req_idx: Index of the SCSI IO request frame. (output)
23876   *
23877   *     return SUCCESS or FAILED
23878 - */
23879 + **/
23880  static inline int
23881  mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
23882  {
23883 @@ -195,7 +131,7 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER 
23884         int chain_idx;
23885  
23886         dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n",
23887 -           ioc->name));
23888 +                       ioc->name));
23889         spin_lock_irqsave(&ioc->FreeQlock, flags);
23890         if (!list_empty(&ioc->FreeChainQ)) {
23891                 int offset;
23892 @@ -206,14 +142,13 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER 
23893                 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
23894                 chain_idx = offset / ioc->req_sz;
23895                 rc = SUCCESS;
23896 -               dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
23897 -                   "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
23898 -                   ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
23899 +               dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
23900 +                       ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
23901         } else {
23902                 rc = FAILED;
23903                 chain_idx = MPT_HOST_NO_CHAIN;
23904                 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
23905 -                   ioc->name));
23906 +                       ioc->name));
23907         }
23908         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
23909  
23910 @@ -222,7 +157,7 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER 
23911  } /* mptscsih_getFreeChainBuffer() */
23912  
23913  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
23914 -/*
23915 +/**
23916   *     mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
23917   *     SCSIIORequest_t Message Frame.
23918   *     @ioc: Pointer to MPT_ADAPTER structure
23919 @@ -230,7 +165,7 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER 
23920   *     @pReq: Pointer to SCSIIORequest_t structure
23921   *
23922   *     Returns ...
23923 - */
23924 + **/
23925  static int
23926  mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
23927                 SCSIIORequest_t *pReq, int req_idx)
23928 @@ -281,10 +216,10 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct
23929          */
23930  
23931  nextSGEset:
23932 -       numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
23933 +       numSgeSlots = ((frm_sz - sgeOffset) / ioc->SGE_size );
23934         numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
23935  
23936 -       sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
23937 +       sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | sgdir;
23938  
23939         /* Get first (num - 1) SG elements
23940          * Skip any SG entries with a length of 0
23941 @@ -299,11 +234,11 @@ nextSGEset:
23942                 }
23943  
23944                 v2 = sg_dma_address(sg);
23945 -               mptscsih_add_sge(psge, sgflags | thisxfer, v2);
23946 +               ioc->add_sge(psge, sgflags | thisxfer, v2);
23947  
23948                 sg = sg_next(sg);       /* Get next SG element from the OS */
23949 -               psge += (sizeof(u32) + sizeof(dma_addr_t));
23950 -               sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
23951 +               psge += ioc->SGE_size;
23952 +               sgeOffset += ioc->SGE_size;
23953                 sg_done++;
23954         }
23955  
23956 @@ -320,12 +255,8 @@ nextSGEset:
23957                 thisxfer = sg_dma_len(sg);
23958  
23959                 v2 = sg_dma_address(sg);
23960 -               mptscsih_add_sge(psge, sgflags | thisxfer, v2);
23961 -               /*
23962 -               sg = sg_next(sg);
23963 -               psge += (sizeof(u32) + sizeof(dma_addr_t));
23964 -               */
23965 -               sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
23966 +               ioc->add_sge(psge, sgflags | thisxfer, v2);
23967 +               sgeOffset += ioc->SGE_size;
23968                 sg_done++;
23969  
23970                 if (chainSge) {
23971 @@ -334,7 +265,7 @@ nextSGEset:
23972                          * Update the chain element
23973                          * Offset and Length fields.
23974                          */
23975 -                       mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
23976 +                       ioc->add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
23977                 } else {
23978                         /* The current buffer is the original MF
23979                          * and there is no Chain buffer.
23980 @@ -367,7 +298,7 @@ nextSGEset:
23981                  * set properly).
23982                  */
23983                 if (sg_done) {
23984 -                       u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
23985 +                       u32 *ptmp = (u32 *) (psge - ioc->SGE_size);
23986                         sgflags = le32_to_cpu(*ptmp);
23987                         sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
23988                         *ptmp = cpu_to_le32(sgflags);
23989 @@ -381,8 +312,8 @@ nextSGEset:
23990                          * Old chain element is now complete.
23991                          */
23992                         u8 nextChain = (u8) (sgeOffset >> 2);
23993 -                       sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
23994 -                       mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
23995 +                       sgeOffset += ioc->SGE_size;
23996 +                       ioc->add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
23997                 } else {
23998                         /* The original MF buffer requires a chain buffer -
23999                          * set the offset.
24000 @@ -461,7 +392,7 @@ mptscsih_issue_sep_command(MPT_ADAPTER *
24001  
24002         if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
24003                 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
24004 -                   ioc->name,__func__));
24005 +                   ioc->name,__FUNCTION__));
24006                 return;
24007         }
24008  
24009 @@ -592,14 +523,14 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, s
24010         }
24011  
24012         scsi_print_command(sc);
24013 -       printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n",
24014 -           ioc->name, pScsiReply->Bus, pScsiReply->TargetID);
24015 -       printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "
24016 -           "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,
24017 -           scsi_get_resid(sc));
24018 -       printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, "
24019 -           "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag),
24020 +       printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %d\n",
24021 +           ioc->name, pScsiReply->Bus, pScsiReply->TargetID, sc->device->lun);
24022 +       printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, resid = %d\n",
24023 +              ioc->name, scsi_bufflen(sc), sc->underflow, scsi_get_resid(sc));
24024 +       printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, sc->result = %08X\n",
24025 +           ioc->name, le16_to_cpu(pScsiReply->TaskTag),
24026             le32_to_cpu(pScsiReply->TransferCount), sc->result);
24027 +
24028         printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), "
24029             "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n",
24030             ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus,
24031 @@ -625,7 +556,7 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, s
24032  #endif
24033  
24034  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24035 -/*
24036 +/**
24037   *     mptscsih_io_done - Main SCSI IO callback routine registered to
24038   *     Fusion MPT (base) driver
24039   *     @ioc: Pointer to MPT_ADAPTER structure
24040 @@ -638,7 +569,7 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, s
24041   *     load/init time via the mpt_register() API call.
24042   *
24043   *     Returns 1 indicating alloc'd request frame ptr should be freed.
24044 - */
24045 + **/
24046  int
24047  mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
24048  {
24049 @@ -651,14 +582,15 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24050         VirtTarget       *vtarget;
24051  
24052         hd = shost_priv(ioc->sh);
24053 +
24054         req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
24055         req_idx_MR = (mr != NULL) ?
24056             le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
24057         if ((req_idx != req_idx_MR) ||
24058 -           (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
24059 -               printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
24060 -                   ioc->name);
24061 -               printk (MYIOC_s_ERR_FMT
24062 +           (le32_to_cpu(mf->u.frame.linkage.arg1) == 0xdeadbeaf)) {
24063 +               printk(MYIOC_s_WARN_FMT
24064 +                   "Received a mf that was already freed\n", ioc->name);
24065 +               printk (MYIOC_s_WARN_FMT
24066                     "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
24067                     ioc->name, req_idx, req_idx_MR, mf, mr,
24068                     mptscsih_get_scsi_lookup(ioc, req_idx_MR));
24069 @@ -693,7 +625,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24070  
24071         if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
24072                 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24073 -                       "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
24074 +                       "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task_tag=%d)\n",
24075                         ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
24076         }else{
24077                 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24078 @@ -706,6 +638,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24079                 ;
24080         } else {
24081                 u32      xfer_cnt;
24082 +               u32      difftransfer;
24083                 u16      status;
24084                 u8       scsi_state, scsi_status;
24085                 u32      log_info;
24086 @@ -716,6 +649,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24087                 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
24088                 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
24089                 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
24090 +               vdevice = sc->device->hostdata;
24091  
24092                 /*
24093                  *  if we get a data underrun indication, yet no data was
24094 @@ -733,20 +667,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24095                 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
24096                         mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
24097  
24098 -               /*
24099 -                *  Look for + dump FCP ResponseInfo[]!
24100 -                */
24101 -               if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
24102 -                   pScsiReply->ResponseInfo) {
24103 -                       printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
24104 -                       "FCP_ResponseInfo=%08xh\n", ioc->name,
24105 -                       sc->device->host->host_no, sc->device->channel,
24106 -                       sc->device->id, sc->device->lun,
24107 -                       le32_to_cpu(pScsiReply->ResponseInfo));
24108 -               }
24109 -
24110                 switch(status) {
24111                 case MPI_IOCSTATUS_BUSY:                        /* 0x0002 */
24112 +               case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:      /* 0x0006 */
24113                         /* CHECKME!
24114                          * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
24115                          * But not: DID_BUS_BUSY lest one risk
24116 @@ -771,7 +694,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24117                         if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
24118                                 hd->sel_timeout[pScsiReq->TargetID]++;
24119  
24120 -                       vdevice = sc->device->hostdata;
24121                         if (!vdevice)
24122                                 break;
24123                         vtarget = vdevice->vtarget;
24124 @@ -793,14 +715,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24125                                         }
24126                                 }
24127                         } else if (ioc->bus_type == FC) {
24128 -                               /*
24129 -                                * The FC IOC may kill a request for variety of
24130 -                                * reasons, some of which may be recovered by a
24131 -                                * retry, some which are unlikely to be
24132 -                                * recovered. Return DID_ERROR instead of
24133 -                                * DID_RESET to permit retry of the command,
24134 -                                * just not an infinite number of them
24135 -                                */
24136 +                               /* The FC IOC may kill a request for variety of reasons,
24137 +                               some of which may be recovered by a retry, some which
24138 +                               are unlikely to be recovered. Return DID_ERROR instead
24139 +                               of DID_RESET to permit retry of the command, just not
24140 +                               an infinite number of them */
24141                                 sc->result = DID_ERROR << 16;
24142                                 break;
24143                         }
24144 @@ -810,12 +729,16 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24145                          */
24146  
24147                 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
24148 -               case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
24149                         /* Linux handles an unsolicited DID_RESET better
24150                          * than an unsolicited DID_ABORT.
24151                          */
24152                         sc->result = DID_RESET << 16;
24153  
24154 +               case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
24155 +                       if ( ioc->bus_type == FC )
24156 +                               sc->result = DID_ERROR << 16;
24157 +                       else
24158 +                               sc->result = DID_RESET << 16;
24159                         break;
24160  
24161                 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:      /* 0x0049 */
24162 @@ -824,9 +747,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24163                                 sc->result=DID_SOFT_ERROR << 16;
24164                         else /* Sufficient data transfer occurred */
24165                                 sc->result = (DID_OK << 16) | scsi_status;
24166 -                       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24167 -                           "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
24168 -                           ioc->name, sc->result, sc->device->channel, sc->device->id));
24169                         break;
24170  
24171                 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
24172 @@ -835,11 +755,34 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24173                          *  precedence!
24174                          */
24175                         sc->result = (DID_OK << 16) | scsi_status;
24176 -                       if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
24177 -                               /* Have already saved the status and sense data
24178 +
24179 +                       if (!(scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
24180 +
24181 +                               /*
24182 +                                * For an Errata on LSI53C1030
24183 +                                * When the length of request data
24184 +                                * and transfer data are different
24185 +                                * with result of command (READ or VERIFY),
24186 +                                * DID_SOFT_ERROR is set.
24187                                  */
24188 -                               ;
24189 -                       } else {
24190 +                               if (ioc->bus_type == SPI && vdevice &&
24191 +                                   vdevice->vtarget->type == TYPE_DISK) {
24192 +                                       if (pScsiReq->CDB[0] == READ_6  ||
24193 +                                           pScsiReq->CDB[0] == READ_10 ||
24194 +                                           pScsiReq->CDB[0] == READ_12 ||
24195 +                                           pScsiReq->CDB[0] == READ_16 ||
24196 +                                           pScsiReq->CDB[0] == VERIFY  ||
24197 +                                           pScsiReq->CDB[0] == VERIFY_16) {
24198 +                                               if (scsi_bufflen(sc) !=
24199 +                                                   xfer_cnt) {
24200 +                                                       sc->result = DID_SOFT_ERROR << 16;
24201 +                                                       printk(MYIOC_s_WARN_FMT "Errata"
24202 +                                                              "on LSI53C1030 occurred. sc->request_bufflen=0x%02x, "
24203 +                                                              "xfer_cnt=0x%02x\n", ioc->name, scsi_bufflen(sc), xfer_cnt);
24204 +                                               }
24205 +                                       }
24206 +                               }
24207 +
24208                                 if (xfer_cnt < sc->underflow) {
24209                                         if (scsi_status == SAM_STAT_BUSY)
24210                                                 sc->result = SAM_STAT_BUSY;
24211 @@ -848,7 +791,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24212                                 }
24213                                 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
24214                                         /* What to do?
24215 -                                       */
24216 +                                       */
24217                                         sc->result = DID_SOFT_ERROR << 16;
24218                                 }
24219                                 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
24220 @@ -857,13 +800,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24221                                 }
24222                         }
24223  
24224 -
24225 -                       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24226 -                           "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
24227 -                           ioc->name, sc->underflow));
24228 -                       dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24229 -                           "  ActBytesXferd=%02xh\n", ioc->name, xfer_cnt));
24230 -
24231                         /* Report Queue Full
24232                          */
24233                         if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
24234 @@ -879,6 +815,44 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24235                         if (scsi_state == 0) {
24236                                 ;
24237                         } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
24238 +
24239 +                               /*
24240 +                                * For potential trouble on LSI53C1030. (date:2007.xx.)
24241 +                                * It is checked whether the length of request data is equal to
24242 +                                * the length of transfer and residual.
24243 +                                * MEDIUM_ERROR is set by incorrect data.
24244 +                                */
24245 +                               if (ioc->bus_type == SPI && vdevice &&
24246 +                                   vdevice->vtarget->type == TYPE_DISK) {
24247 +                                       if (sc->sense_buffer[2] & 0x20) {
24248 +                                               difftransfer =
24249 +                                                       sc->sense_buffer[3] << 24 |
24250 +                                                       sc->sense_buffer[4] << 16 |
24251 +                                                       sc->sense_buffer[5] << 8 |
24252 +                                                       sc->sense_buffer[6];
24253 +                                               if ((sc->sense_buffer[3] & 0x80) == 0x80) {
24254 +                                                       if (scsi_bufflen(sc) != xfer_cnt) {
24255 +                                                               sc->sense_buffer[2] = MEDIUM_ERROR;
24256 +                                                               sc->sense_buffer[12] = 0xff;
24257 +                                                               sc->sense_buffer[13] = 0xff;
24258 +                                                               printk(MYIOC_s_WARN_FMT "Errata on "
24259 +                                                                      "LSI53C1030 occurred. sc->request_bufflen=0x%02x,"
24260 +                                                                      "xfer_cnt=0x%02x\n", ioc->name, scsi_bufflen(sc), xfer_cnt);
24261 +                                                       }
24262 +                                               } else {
24263 +                                                       if (scsi_bufflen(sc) != xfer_cnt + difftransfer) {
24264 +                                                               sc->sense_buffer[2] = MEDIUM_ERROR;
24265 +                                                               sc->sense_buffer[12] = 0xff;
24266 +                                                               sc->sense_buffer[13] = 0xff;
24267 +                                                               printk(MYIOC_s_WARN_FMT "Errata on "
24268 +                                                                      "LSI53C1030 occurred. sc->request_bufflen=0x%02x,"
24269 +                                                                      " xfer_cnt=0x%02x, difftransfer=0x%02x\n",
24270 +                                                                      ioc->name, scsi_bufflen(sc) , xfer_cnt, difftransfer);
24271 +                                                       }
24272 +                                               }
24273 +                                       }
24274 +                               }
24275 +
24276                                 /*
24277                                  * If running against circa 200003dd 909 MPT f/w,
24278                                  * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
24279 @@ -890,7 +864,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24280  
24281                         }
24282                         else if (scsi_state &
24283 -                                (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
24284 +                                (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
24285                            ) {
24286                                 /*
24287                                  * What to do?
24288 @@ -926,7 +900,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24289                 case MPI_IOCSTATUS_INVALID_SGL:                 /* 0x0003 */
24290                 case MPI_IOCSTATUS_INTERNAL_ERROR:              /* 0x0004 */
24291                 case MPI_IOCSTATUS_RESERVED:                    /* 0x0005 */
24292 -               case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:      /* 0x0006 */
24293                 case MPI_IOCSTATUS_INVALID_FIELD:               /* 0x0007 */
24294                 case MPI_IOCSTATUS_INVALID_STATE:               /* 0x0008 */
24295                 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
24296 @@ -957,7 +930,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24297         return 1;
24298  }
24299  
24300 -/*
24301 +/**
24302   *     mptscsih_flush_running_cmds - For each command found, search
24303   *             Scsi_Host instance taskQ and reply to OS.
24304   *             Called only if recovering from a FW reload.
24305 @@ -966,7 +939,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
24306   *     Returns: None.
24307   *
24308   *     Must be called while new I/Os are being queued.
24309 - */
24310 + **/
24311  static void
24312  mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
24313  {
24314 @@ -992,14 +965,14 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOS
24315                 scsi_dma_unmap(sc);
24316                 sc->result = DID_RESET << 16;
24317                 sc->host_scribble = NULL;
24318 -               sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT
24319 -                   "completing cmds: fw_channel %d, fw_id %d, sc=%p,"
24320 -                   " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii);
24321 +               dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT
24322 +                   "completing cmds: fw_channel %d, fw_id %d, sc=%p, mf = %p, "
24323 +                   "idx=%x\n", ioc->name, channel, id, sc, mf, ii));
24324                 sc->scsi_done(sc);
24325         }
24326  }
24327  
24328 -/*
24329 +/**
24330   *     mptscsih_search_running_cmds - Delete any commands associated
24331   *             with the specified target and lun. Function called only
24332   *             when a lun is disable by mid-layer.
24333 @@ -1012,15 +985,15 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOS
24334   *     Returns: None.
24335   *
24336   *     Called from slave_destroy.
24337 - */
24338 + **/
24339  static void
24340  mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
24341  {
24342         SCSIIORequest_t *mf = NULL;
24343         int              ii;
24344         struct scsi_cmnd *sc;
24345 -       struct scsi_lun  lun;
24346 -       MPT_ADAPTER *ioc = hd->ioc;
24347 +       struct scsi_lun lun;
24348 +       MPT_ADAPTER     *ioc = hd->ioc;
24349         unsigned long   flags;
24350  
24351         spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
24352 @@ -1030,8 +1003,11 @@ mptscsih_search_running_cmds(MPT_SCSI_HO
24353                         mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
24354                         if (mf == NULL)
24355                                 continue;
24356 -                       /* If the device is a hidden raid component, then its
24357 -                        * expected that the mf->function will be RAID_SCSI_IO
24358 +
24359 +                       /*
24360 +                        * If the device is a hidden raid component,
24361 +                        * then its expected that
24362 +                        * the function would be raid scsi io
24363                          */
24364                         if (vdevice->vtarget->tflags &
24365                             MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
24366 @@ -1053,9 +1029,11 @@ mptscsih_search_running_cmds(MPT_SCSI_HO
24367                         scsi_dma_unmap(sc);
24368                         sc->host_scribble = NULL;
24369                         sc->result = DID_NO_CONNECT << 16;
24370 -                       sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d,"
24371 -                          "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel,
24372 -                          vdevice->vtarget->id, sc, mf, ii);
24373 +                       dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device,
24374 +                          MYIOC_s_FMT "completing cmds: fw_channel %d, "
24375 +                          "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name,
24376 +                          vdevice->vtarget->channel, vdevice->vtarget->id,
24377 +                          sc, mf, ii));
24378                         sc->scsi_done(sc);
24379                         spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
24380                 }
24381 @@ -1067,7 +1045,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HO
24382  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24383  
24384  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24385 -/*
24386 +/**
24387   *     mptscsih_report_queue_full - Report QUEUE_FULL status returned
24388   *     from a SCSI target device.
24389   *     @sc: Pointer to scsi_cmnd structure
24390 @@ -1077,12 +1055,12 @@ mptscsih_search_running_cmds(MPT_SCSI_HO
24391   *     This routine periodically reports QUEUE_FULL status returned from a
24392   *     SCSI target device.  It reports this to the console via kernel
24393   *     printk() API call, not more than once every 10 seconds.
24394 - */
24395 + **/
24396  static void
24397  mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
24398  {
24399         long time = jiffies;
24400 -       MPT_SCSI_HOST           *hd;
24401 +       MPT_SCSI_HOST   *hd;
24402         MPT_ADAPTER     *ioc;
24403  
24404         if (sc->device == NULL)
24405 @@ -1100,12 +1078,12 @@ mptscsih_report_queue_full(struct scsi_c
24406  }
24407  
24408  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24409 -/*
24410 +/**
24411   *     mptscsih_remove - Removed scsi devices
24412   *     @pdev: Pointer to pci_dev structure
24413   *
24414   *
24415 - */
24416 + **/
24417  void
24418  mptscsih_remove(struct pci_dev *pdev)
24419  {
24420 @@ -1151,10 +1129,10 @@ mptscsih_remove(struct pci_dev *pdev)
24421  }
24422  
24423  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24424 -/*
24425 +/**
24426   *     mptscsih_shutdown - reboot notifier
24427   *
24428 - */
24429 + **/
24430  void
24431  mptscsih_shutdown(struct pci_dev *pdev)
24432  {
24433 @@ -1162,11 +1140,11 @@ mptscsih_shutdown(struct pci_dev *pdev)
24434  
24435  #ifdef CONFIG_PM
24436  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24437 -/*
24438 +/**
24439   *     mptscsih_suspend - Fusion MPT scsi driver suspend routine.
24440   *
24441   *
24442 - */
24443 + **/
24444  int
24445  mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
24446  {
24447 @@ -1179,11 +1157,11 @@ mptscsih_suspend(struct pci_dev *pdev, p
24448  }
24449  
24450  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24451 -/*
24452 +/**
24453   *     mptscsih_resume - Fusion MPT scsi driver resume routine.
24454   *
24455   *
24456 - */
24457 + **/
24458  int
24459  mptscsih_resume(struct pci_dev *pdev)
24460  {
24461 @@ -1205,7 +1183,7 @@ mptscsih_resume(struct pci_dev *pdev)
24462   *     (linux scsi_host_template.info routine)
24463   *
24464   *     Returns pointer to buffer where information was written.
24465 - */
24466 + **/
24467  const char *
24468  mptscsih_info(struct Scsi_Host *SChost)
24469  {
24470 @@ -1338,7 +1316,7 @@ mptscsih_proc_info(struct Scsi_Host *hos
24471   *     from a linux scsi_cmnd request and send it to the IOC.
24472   *
24473   *     Returns 0. (rtn value discarded by linux scsi mid-layer)
24474 - */
24475 + **/
24476  int
24477  mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
24478  {
24479 @@ -1346,7 +1324,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
24480         MPT_FRAME_HDR           *mf;
24481         SCSIIORequest_t         *pScsiReq;
24482         VirtDevice              *vdevice = SCpnt->device->hostdata;
24483 -       int      lun;
24484         u32      datalen;
24485         u32      scsictl;
24486         u32      scsidir;
24487 @@ -1357,24 +1334,20 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
24488  
24489         hd = shost_priv(SCpnt->device->host);
24490         ioc = hd->ioc;
24491 -       lun = SCpnt->device->lun;
24492         SCpnt->scsi_done = done;
24493  
24494         dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n",
24495                 ioc->name, SCpnt, done));
24496  
24497 -       if (hd->resetPending) {
24498 -               dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
24499 -                       ioc->name, SCpnt));
24500 +       if (ioc->taskmgmt_quiesce_io)
24501                 return SCSI_MLQUEUE_HOST_BUSY;
24502 -       }
24503  
24504         /*
24505          *  Put together a MPT SCSI request...
24506          */
24507         if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
24508                 dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
24509 -                               ioc->name));
24510 +                       ioc->name));
24511                 return SCSI_MLQUEUE_HOST_BUSY;
24512         }
24513  
24514 @@ -1422,7 +1395,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
24515         pScsiReq->CDBLength = SCpnt->cmd_len;
24516         pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
24517         pScsiReq->Reserved = 0;
24518 -       pScsiReq->MsgFlags = mpt_msg_flags();
24519 +       pScsiReq->MsgFlags = mpt_msg_flags(ioc);
24520         int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
24521         pScsiReq->Control = cpu_to_le32(scsictl);
24522  
24523 @@ -1448,7 +1421,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
24524          */
24525         if (datalen == 0) {
24526                 /* Add a NULL SGE */
24527 -               mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
24528 +               ioc->add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
24529                         (dma_addr_t) -1);
24530         } else {
24531                 /* Add a 32 or 64 bit SGE */
24532 @@ -1472,7 +1445,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
24533  }
24534  
24535  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24536 -/*
24537 +/**
24538   *     mptscsih_freeChainBuffers - Function to free chain buffers associated
24539   *     with a SCSI IO request
24540   *     @hd: Pointer to the MPT_SCSI_HOST instance
24541 @@ -1480,7 +1453,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
24542   *
24543   *     Called if SG chain buffer allocation fails and mptscsih callbacks.
24544   *     No return.
24545 - */
24546 + **/
24547  static void
24548  mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
24549  {
24550 @@ -1527,243 +1500,457 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i
24551   */
24552  
24553  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24554 -/**
24555 - *     mptscsih_TMHandler - Generic handler for SCSI Task Management.
24556 - *     @hd: Pointer to MPT SCSI HOST structure
24557 - *     @type: Task Management type
24558 - *     @channel: channel number for task management
24559 - *     @id: Logical Target ID for reset (if appropriate)
24560 - *     @lun: Logical Unit for reset (if appropriate)
24561 - *     @ctx2abort: Context for the task to be aborted (if appropriate)
24562 - *     @timeout: timeout for task management control
24563 - *
24564 - *     Fall through to mpt_HardResetHandler if: not operational, too many
24565 - *     failed TM requests or handshake failure.
24566 - *
24567 - *     Remark: Currently invoked from a non-interrupt thread (_bh).
24568 - *
24569 - *     Note: With old EH code, at most 1 SCSI TaskMgmt function per IOC
24570 - *     will be active.
24571 - *
24572 - *     Returns 0 for SUCCESS, or %FAILED.
24573 - **/
24574 -int
24575 -mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
24576 -{
24577 -       MPT_ADAPTER     *ioc;
24578 -       int              rc = -1;
24579 -       u32              ioc_raw_state;
24580 -       unsigned long    flags;
24581 -
24582 -       ioc = hd->ioc;
24583 -       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name));
24584 -
24585 -       // SJR - CHECKME - Can we avoid this here?
24586 -       // (mpt_HardResetHandler has this check...)
24587 -       spin_lock_irqsave(&ioc->diagLock, flags);
24588 -       if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
24589 -               spin_unlock_irqrestore(&ioc->diagLock, flags);
24590 -               return FAILED;
24591 -       }
24592 -       spin_unlock_irqrestore(&ioc->diagLock, flags);
24593 -
24594 -       /*  Wait a fixed amount of time for the TM pending flag to be cleared.
24595 -        *  If we time out and not bus reset, then we return a FAILED status
24596 -        *  to the caller.
24597 -        *  The call to mptscsih_tm_pending_wait() will set the pending flag
24598 -        *  if we are
24599 -        *  successful. Otherwise, reload the FW.
24600 -        */
24601 -       if (mptscsih_tm_pending_wait(hd) == FAILED) {
24602 -               if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
24603 -                       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: "
24604 -                          "Timed out waiting for last TM (%d) to complete! \n",
24605 -                          ioc->name, hd->tmPending));
24606 -                       return FAILED;
24607 -               } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
24608 -                       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target "
24609 -                               "reset: Timed out waiting for last TM (%d) "
24610 -                               "to complete! \n", ioc->name,
24611 -                               hd->tmPending));
24612 -                       return FAILED;
24613 -               } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
24614 -                       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: "
24615 -                          "Timed out waiting for last TM (%d) to complete! \n",
24616 -                         ioc->name, hd->tmPending));
24617 -                       return FAILED;
24618 -               }
24619 -       } else {
24620 -               spin_lock_irqsave(&ioc->FreeQlock, flags);
24621 -               hd->tmPending |=  (1 << type);
24622 -               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
24623 -       }
24624 -
24625 -       ioc_raw_state = mpt_GetIocState(ioc, 0);
24626 -
24627 -       if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
24628 -               printk(MYIOC_s_WARN_FMT
24629 -                       "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
24630 -                       ioc->name, type, ioc_raw_state);
24631 -               printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name);
24632 -               if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
24633 -                       printk(MYIOC_s_WARN_FMT "TMHandler: HardReset "
24634 -                           "FAILED!!\n", ioc->name);
24635 -               return FAILED;
24636 -       }
24637 -
24638 -       if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
24639 -               printk(MYIOC_s_WARN_FMT
24640 -                       "TM Handler for type=%x: ioc_state: "
24641 -                       "DOORBELL_ACTIVE (0x%x)!\n",
24642 -                       ioc->name, type, ioc_raw_state);
24643 -               return FAILED;
24644 -       }
24645 -
24646 -       /* Isse the Task Mgmt request.
24647 -        */
24648 -       if (hd->hard_resets < -1)
24649 -               hd->hard_resets++;
24650 -
24651 -       rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
24652 -           ctx2abort, timeout);
24653 -       if (rc)
24654 -               printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
24655 -                      ioc->name);
24656 -       else
24657 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n",
24658 -                          ioc->name));
24659 -
24660 -       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24661 -                       "TMHandler rc = %d!\n", ioc->name, rc));
24662 -
24663 -       return rc;
24664 -}
24665 -
24666 -
24667  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
24668 -/**
24669 - *     mptscsih_IssueTaskMgmt - Generic send Task Management function.
24670 - *     @hd: Pointer to MPT_SCSI_HOST structure
24671 - *     @type: Task Management type
24672 - *     @channel: channel number for task management
24673 - *     @id: Logical Target ID for reset (if appropriate)
24674 - *     @lun: Logical Unit for reset (if appropriate)
24675 - *     @ctx2abort: Context for the task to be aborted (if appropriate)
24676 - *     @timeout: timeout for task management control
24677 - *
24678 - *     Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
24679 - *     or a non-interrupt thread.  In the former, must not call schedule().
24680 - *
24681 - *     Not all fields are meaningfull for all task types.
24682 - *
24683 - *     Returns 0 for SUCCESS, or FAILED.
24684 - *
24685 - **/
24686 +
24687  static int
24688 -mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
24689 +mptscsih_scandv_bus_reset(MPT_ADAPTER *ioc)
24690  {
24691         MPT_FRAME_HDR   *mf;
24692         SCSITaskMgmt_t  *pScsiTm;
24693 +       SCSITaskMgmtReply_t *pScsiTmReply;
24694         int              ii;
24695         int              retval;
24696 -       MPT_ADAPTER     *ioc = hd->ioc;
24697 +       unsigned long    timeout;
24698 +       unsigned long    time_count;
24699 +       u16              iocstatus;
24700 +
24701 +       mutex_lock(&ioc->taskmgmt_cmds.mutex);
24702 +       if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
24703 +               mutex_unlock(&ioc->taskmgmt_cmds.mutex);
24704 +               return -EPERM;
24705 +       }
24706  
24707 -       /* Return Fail to calling function if no message frames available.
24708 +       /* Send request
24709          */
24710         if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
24711 -               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
24712 +               dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt, no msg frames!!\n",
24713                                 ioc->name));
24714 -               return FAILED;
24715 +               mpt_clear_taskmgmt_in_progress_flag(ioc);
24716 +               retval = -ENOMEM;
24717 +               goto out;
24718         }
24719 -       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
24720 -                       ioc->name, mf));
24721  
24722 -       /* Format the Request
24723 -        */
24724 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
24725 +               ioc->name, mf));
24726 +
24727         pScsiTm = (SCSITaskMgmt_t *) mf;
24728 -       pScsiTm->TargetID = id;
24729 -       pScsiTm->Bus = channel;
24730 -       pScsiTm->ChainOffset = 0;
24731 +       memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
24732         pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
24733 -
24734 +       pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
24735 +       pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
24736 +       pScsiTm->TargetID = 0;
24737 +       pScsiTm->Bus = 0;
24738 +       pScsiTm->ChainOffset = 0;
24739         pScsiTm->Reserved = 0;
24740 -       pScsiTm->TaskType = type;
24741         pScsiTm->Reserved1 = 0;
24742 -       pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
24743 -                    ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
24744 -
24745 -       int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
24746 -
24747 +       pScsiTm->TaskMsgContext = 0;
24748 +       for (ii= 0; ii < 8; ii++)
24749 +               pScsiTm->LUN[ii] = 0;
24750         for (ii=0; ii < 7; ii++)
24751                 pScsiTm->Reserved2[ii] = 0;
24752  
24753 -       pScsiTm->TaskMsgContext = ctx2abort;
24754 -
24755 -       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
24756 -               "type=%d\n", ioc->name, ctx2abort, type));
24757 +       switch (ioc->bus_type) {
24758 +               case FC:
24759 +                       timeout = 40;
24760 +                       break;
24761 +               case SAS:
24762 +                       timeout = 30;
24763 +                       break;
24764 +               case SPI:
24765 +               default:
24766 +                       timeout = 2;
24767 +                       break;
24768 +       }
24769  
24770 -       DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
24771 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt type=%d timeout=%ld\n",
24772 +           ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout));
24773  
24774 +       INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
24775 +       CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
24776 +       retval = 0;
24777 +       time_count = jiffies;
24778         if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
24779             (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
24780                 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
24781         else {
24782                 retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
24783 -                       sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
24784 -               if (retval) {
24785 -                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"
24786 -                       " (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd,
24787 -                       ioc, mf, retval));
24788 -                       goto fail_out;
24789 +                   sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
24790 +               if (retval != 0) {
24791 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "TaskMgmt send_handshake FAILED!"
24792 +                               " (ioc %p, mf %p, rc=%d) \n", ioc->name,
24793 +                               ioc, mf, retval));
24794 +                       mpt_clear_taskmgmt_in_progress_flag(ioc);
24795 +                       goto out;
24796                 }
24797         }
24798  
24799 -       if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
24800 -               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"
24801 -                       " (hd %p, ioc %p, mf %p) \n", ioc->name, hd,
24802 -                       ioc, mf));
24803 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
24804 -                        ioc->name));
24805 -               retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
24806 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",
24807 -                        ioc->name, retval));
24808 -               goto fail_out;
24809 +       /* Now wait for the command to complete */
24810 +       ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
24811 +       if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
24812 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24813 +                   "TaskMgmt failed\n", ioc->name));
24814 +               mpt_free_msg_frame(ioc, mf);
24815 +               mpt_clear_taskmgmt_in_progress_flag(ioc);
24816 +               retval = -1; /* return failure */
24817 +               goto out;
24818         }
24819  
24820 -       /*
24821 -        * Handle success case, see if theres a non-zero ioc_status.
24822 -        */
24823 -       if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
24824 -          hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
24825 -          hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
24826 -               retval = 0;
24827 -       else
24828 -               retval = FAILED;
24829 +       if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
24830 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24831 +                   "TaskMgmt failed\n", ioc->name));
24832 +               retval = -1; /* return failure */
24833 +               goto out;
24834 +       }
24835  
24836 -       return retval;
24837 +       pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
24838 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24839 +           "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n"
24840 +           "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n"
24841 +           "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus,
24842 +           pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
24843 +           le16_to_cpu(pScsiTmReply->IOCStatus),
24844 +           le32_to_cpu(pScsiTmReply->IOCLogInfo),
24845 +           pScsiTmReply->ResponseCode,
24846 +           le32_to_cpu(pScsiTmReply->TerminationCount)));
24847  
24848 - fail_out:
24849 +       iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
24850  
24851 -       /*
24852 -        * Free task management mf, and corresponding tm flags
24853 -        */
24854 -       mpt_free_msg_frame(ioc, mf);
24855 -       hd->tmPending = 0;
24856 -       hd->tmState = TM_STATE_NONE;
24857 -       return FAILED;
24858 +       if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
24859 +          iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED ||
24860 +          iocstatus == MPI_IOCSTATUS_SUCCESS)
24861 +               retval = 0;
24862 +       else {
24863 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24864 +                   "TaskMgmt failed\n", ioc->name));
24865 +               retval = -1; /* return failure */
24866 +       }
24867 +
24868 + out:
24869 +       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
24870 +       CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
24871 +       return retval;
24872  }
24873  
24874 -static int
24875 -mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
24876 +int
24877 +mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
24878  {
24879 -       switch (ioc->bus_type) {
24880 -       case FC:
24881 -               return 40;
24882 -       case SAS:
24883 -               return 10;
24884 +       MPT_SCSI_HOST   *hd;
24885 +
24886 +       if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
24887 +               return 0;
24888 +
24889 +       switch (reset_phase) {
24890 +       case MPT_IOC_SETUP_RESET:
24891 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24892 +                   "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __FUNCTION__));
24893 +               break;
24894 +       case MPT_IOC_PRE_RESET:
24895 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24896 +                   "%s: MPT_IOC_PRE_RESET\n", ioc->name, __FUNCTION__));
24897 +               hd = shost_priv(ioc->sh);
24898 +               mptscsih_flush_running_cmds(hd);
24899 +               break;
24900 +       case MPT_IOC_POST_RESET:
24901 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24902 +                   "%s: MPT_IOC_POST_RESET\n", ioc->name, __FUNCTION__));
24903 +               if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) {
24904 +                       ioc->internal_cmds.status |= MPT_MGMT_STATUS_DID_IOCRESET;
24905 +                       complete(&ioc->internal_cmds.done);
24906 +               }
24907 +               break;
24908 +       default:
24909 +               break;
24910 +       }
24911 +       return 1;               /* currently means nothing really */
24912 +}
24913 +
24914 +void
24915 +mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
24916 +{
24917 +       char *desc;
24918 +
24919 +       switch (response_code) {
24920 +       case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
24921 +               desc = "The task completed.";
24922 +               break;
24923 +       case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
24924 +               desc = "The IOC received an invalid frame status.";
24925 +               break;
24926 +       case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
24927 +               desc = "The task type is not supported.";
24928 +               break;
24929 +       case MPI_SCSITASKMGMT_RSP_TM_FAILED:
24930 +               desc = "The requested task failed.";
24931 +               break;
24932 +       case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
24933 +               desc = "The task completed successfully.";
24934 +               break;
24935 +       case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
24936 +               desc = "The LUN request is invalid.";
24937 +               break;
24938 +       case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
24939 +               desc = "The task is in the IOC queue and has not been sent to target.";
24940 +               break;
24941 +       default:
24942 +               desc = "unknown";
24943 +               break;
24944 +       }
24945 +       printk(MYIOC_s_DEBUG_FMT "Response Code(0x%08x): F/W: %s\n",
24946 +               ioc->name, response_code, desc);
24947 +}
24948 +
24949 +static int
24950 +mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, SCSITaskMgmtReply_t *pScsiTmReply)
24951 +{
24952 +       u16                      iocstatus;
24953 +       u32                      termination_count;
24954 +       int                      retval;
24955 +
24956 +       if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
24957 +               retval = FAILED;
24958 +               goto out;
24959 +       }
24960 +
24961 +       DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
24962 +
24963 +       iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
24964 +       termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
24965 +
24966 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
24967 +           "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n"
24968 +           "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n"
24969 +           "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus,
24970 +           pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus),
24971 +           le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode,
24972 +           termination_count));
24973 +
24974 +       if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
24975 +           pScsiTmReply->ResponseCode)
24976 +               mptscsih_taskmgmt_response_code(ioc,
24977 +                   pScsiTmReply->ResponseCode);
24978 +
24979 +       if (iocstatus == MPI_IOCSTATUS_SUCCESS) {
24980 +               retval = 0;
24981 +               goto out;
24982 +       }
24983 +
24984 +       retval = FAILED;
24985 +       if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
24986 +               if (termination_count == 1)
24987 +                       retval = 0;
24988 +               goto out;
24989 +       }
24990 +
24991 +       if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
24992 +          iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
24993 +               retval = 0;
24994 +
24995 + out:
24996 +       return retval;
24997 +}
24998 +
24999 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25000 +/**
25001 + *     mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
25002 + *     @ioc: Pointer to MPT_ADAPTER structure
25003 + *     @mf: Pointer to SCSI task mgmt request frame
25004 + *     @mr: Pointer to SCSI task mgmt reply frame
25005 + *
25006 + *     This routine is called from mptbase.c::mpt_interrupt() at the completion
25007 + *     of any SCSI task management request.
25008 + *     This routine is registered with the MPT (base) driver at driver
25009 + *     load/init time via the mpt_register() API call.
25010 + *
25011 + *     Returns 1 indicating alloc'd request frame ptr should be freed.
25012 + **/
25013 +int
25014 +mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
25015 +{
25016 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p, mr=%p)\n",
25017 +           ioc->name, mf, mr));
25018 +
25019 +       ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
25020 +
25021 +       if (!mr)
25022 +               goto out;
25023 +
25024 +       ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
25025 +       memcpy(ioc->taskmgmt_cmds.reply, mr,
25026 +           min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
25027 + out:
25028 +       if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
25029 +               mpt_clear_taskmgmt_in_progress_flag(ioc);
25030 +               ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
25031 +               complete(&ioc->taskmgmt_cmds.done);
25032 +               return 1;
25033 +       }
25034 +       return 0;
25035 +}
25036 +
25037 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25038 +/**
25039 + *     mptscsih_IssueTaskMgmt - Generic send Task Management function.
25040 + *     @hd: Pointer to MPT_SCSI_HOST structure
25041 + *     @type: Task Management type
25042 + *     @channel: channel number for task management
25043 + *     @id: Logical Target ID for reset (if appropriate)
25044 + *     @lun: Logical Unit for reset (if appropriate)
25045 + *     @ctx2abort: Context for the task to be aborted (if appropriate)
25046 + *     @timeout: timeout for task management control
25047 + *
25048 + *     Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
25049 + *     or a non-interrupt thread.  In the former, must not call schedule().
25050 + *
25051 + *     Not all fields are meaningfull for all task types.
25052 + *
25053 + *     Returns 0 for SUCCESS, or FAILED.
25054 + *
25055 + **/
25056 +int
25057 +mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
25058 +{
25059 +       MPT_FRAME_HDR   *mf = NULL;
25060 +       SCSITaskMgmt_t  *pScsiTm;
25061 +       int              ii;
25062 +       int              retval;
25063 +       MPT_ADAPTER     *ioc = hd->ioc;
25064 +       unsigned long    timeleft;
25065 +       u8               issue_hard_reset;
25066 +       u32              ioc_raw_state;
25067 +       unsigned long    time_count;
25068 +
25069 +       issue_hard_reset = 0;
25070 +       ioc_raw_state = mpt_GetIocState(ioc, 0);
25071 +
25072 +       if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
25073 +               printk(MYIOC_s_WARN_FMT
25074 +                       "TaskMgmt type=%x: IOC Not operational (0x%x)!\n",
25075 +                       ioc->name, type, ioc_raw_state);
25076 +               printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
25077 +                   ioc->name, __FUNCTION__);
25078 +               if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
25079 +                       printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset "
25080 +                           "FAILED!!\n", ioc->name);
25081 +               return 0;
25082 +       }
25083 +
25084 +       if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
25085 +               printk(MYIOC_s_WARN_FMT
25086 +                       "TaskMgmt type=%x: ioc_state: "
25087 +                       "DOORBELL_ACTIVE (0x%x)!\n",
25088 +                       ioc->name, type, ioc_raw_state);
25089 +               return FAILED;
25090 +       }
25091 +
25092 +       mutex_lock(&ioc->taskmgmt_cmds.mutex);
25093 +       if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
25094 +       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
25095 +               retval = FAILED;
25096 +               goto out;
25097 +       }
25098 +
25099 +       /* Return Fail to calling function if no message frames available.
25100 +        */
25101 +       if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
25102 +               dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "TaskMgmt no msg frames!!\n",
25103 +                               ioc->name));
25104 +               retval = FAILED;
25105 +               mpt_clear_taskmgmt_in_progress_flag(ioc);
25106 +               goto out;
25107 +       }
25108 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
25109 +                       ioc->name, mf));
25110 +
25111 +       /* Format the Request
25112 +        */
25113 +       pScsiTm = (SCSITaskMgmt_t *) mf;
25114 +       pScsiTm->TargetID = id;
25115 +       pScsiTm->Bus = channel;
25116 +       pScsiTm->ChainOffset = 0;
25117 +       pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
25118 +
25119 +       pScsiTm->Reserved = 0;
25120 +       pScsiTm->TaskType = type;
25121 +       pScsiTm->Reserved1 = 0;
25122 +       pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
25123 +                    ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
25124 +
25125 +       int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
25126 +
25127 +       for (ii=0; ii < 7; ii++)
25128 +               pScsiTm->Reserved2[ii] = 0;
25129 +
25130 +       pScsiTm->TaskMsgContext = ctx2abort;
25131 +
25132 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) "
25133 +           "task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort,
25134 +           type, timeout));
25135 +
25136 +       DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
25137 +
25138 +       INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
25139 +       time_count = jiffies;
25140 +       if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
25141 +           (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
25142 +               mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
25143 +       else {
25144 +               retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
25145 +                       sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
25146 +               if (retval) {
25147 +                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "TaskMgmt handshake FAILED!"
25148 +                           " (mf=%p, rc=%d) \n", ioc->name, mf, retval));
25149 +                       mpt_free_msg_frame(ioc, mf);
25150 +                       mpt_clear_taskmgmt_in_progress_flag(ioc);
25151 +                       goto out;
25152 +               }
25153 +       }
25154 +
25155 +       timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
25156 +       if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
25157 +               retval = FAILED;
25158 +               dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
25159 +                   "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf));
25160 +               mpt_clear_taskmgmt_in_progress_flag(ioc);
25161 +               if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
25162 +                       goto out;
25163 +               issue_hard_reset = 1;
25164 +               goto out;
25165 +       }
25166 +
25167 +       retval = mptscsih_taskmgmt_reply(ioc, type,
25168 +           (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply);
25169 +
25170 +       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25171 +           "TaskMgmt completed (%d seconds)\n",
25172 +           ioc->name, jiffies_to_msecs(jiffies - time_count)/1000));
25173 +
25174 + out:
25175 +
25176 +       CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
25177 +       if(issue_hard_reset) {
25178 +               printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
25179 +                   ioc->name, __FUNCTION__);
25180 +               if ((retval = mpt_SoftResetHandler(ioc, CAN_SLEEP)) != 0)
25181 +                       retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
25182 +               mpt_free_msg_frame(ioc, mf);
25183 +       }
25184 +
25185 +       retval = (retval == 0) ? 0 : FAILED;
25186 +       mutex_unlock(&ioc->taskmgmt_cmds.mutex);
25187 +       return retval;
25188 +}
25189 +
25190 +static int
25191 +mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
25192 +{
25193 +       switch (ioc->bus_type) {
25194 +       case FC:
25195 +               return 40;
25196 +       case SAS:
25197 +               return 30;
25198         case SPI:
25199         default:
25200 -               return 2;
25201 +               return 10;
25202         }
25203  }
25204  
25205 @@ -1786,7 +1973,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
25206         int              retval;
25207         VirtDevice       *vdevice;
25208         ulong            sn = SCpnt->serial_number;
25209 -       MPT_ADAPTER     *ioc;
25210 +       MPT_ADAPTER     *ioc;
25211  
25212         /* If we can't locate our host adapter structure, return FAILED status.
25213          */
25214 @@ -1810,7 +1997,21 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
25215                     ioc->name, SCpnt));
25216                 SCpnt->result = DID_NO_CONNECT << 16;
25217                 SCpnt->scsi_done(SCpnt);
25218 -               retval = 0;
25219 +               retval = SUCCESS;
25220 +               goto out;
25221 +       }
25222 +
25223 +       /* Find this command
25224 +        */
25225 +       if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
25226 +               /* Cmd not found in ScsiLookup.
25227 +                * Do OS callback.
25228 +                */
25229 +               SCpnt->result = DID_RESET << 16;
25230 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25231 +                   "task abort: command not in the active list! (sc=%p)\n",
25232 +                   ioc->name, SCpnt));
25233 +               retval = SUCCESS;
25234                 goto out;
25235         }
25236  
25237 @@ -1825,27 +2026,23 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
25238                 goto out;
25239         }
25240  
25241 -       /* Find this command
25242 +       /* Task aborts are not supported for volumes.
25243          */
25244 -       if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
25245 -               /* Cmd not found in ScsiLookup.
25246 -                * Do OS callback.
25247 -                */
25248 +       if (vdevice->vtarget->raidVolume) {
25249 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25250 +                   "task abort: raid volume (sc=%p)\n",
25251 +                   ioc->name, SCpnt));
25252                 SCpnt->result = DID_RESET << 16;
25253 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
25254 -                  "Command not in the active list! (sc=%p)\n", ioc->name,
25255 -                  SCpnt));
25256 -               retval = 0;
25257 -               goto out;
25258 -       }
25259 -
25260 -       if (hd->resetPending) {
25261                 retval = FAILED;
25262                 goto out;
25263         }
25264  
25265 -       if (hd->timeouts < -1)
25266 -               hd->timeouts++;
25267 +       if(mpt_fwfault_debug)
25268 +               mpt_halt_firmware(ioc);
25269 +
25270 +       if (ioc->timeouts < -1)
25271 +               ioc->timeouts++;
25272 +
25273  
25274         /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
25275          * (the IO to be ABORT'd)
25276 @@ -1856,25 +2053,31 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
25277          */
25278         mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
25279         ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
25280 -
25281 -       hd->abortSCpnt = SCpnt;
25282 -
25283 -       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
25284 +       mptscsih_IssueTaskMgmt(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
25285             vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
25286             ctx2abort, mptscsih_get_tm_timeout(ioc));
25287  
25288 +       /* check to see whether command actually completed and/or
25289 +        * terminated
25290 +        */
25291         if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
25292 -           SCpnt->serial_number == sn)
25293 +           SCpnt->serial_number == sn) {
25294 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25295 +                   "task abort: command still in active list! (sc=%p)\n",
25296 +                   ioc->name, SCpnt));
25297                 retval = FAILED;
25298 +       } else {
25299 +               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25300 +                   "task abort: command cleared from active list! (sc=%p)\n",
25301 +                   ioc->name, SCpnt));
25302 +               retval = SUCCESS;
25303 +       }
25304  
25305   out:
25306         printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
25307 -           ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
25308 +           ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED" ), SCpnt);
25309  
25310 -       if (retval == 0)
25311 -               return SUCCESS;
25312 -       else
25313 -               return FAILED;
25314 +       return retval;
25315  }
25316  
25317  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25318 @@ -1907,14 +2110,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SC
25319                ioc->name, SCpnt);
25320         scsi_print_command(SCpnt);
25321  
25322 -       if (hd->resetPending) {
25323 -               retval = FAILED;
25324 -               goto out;
25325 -       }
25326 -
25327         vdevice = SCpnt->device->hostdata;
25328         if (!vdevice || !vdevice->vtarget) {
25329 -               retval = 0;
25330 +               retval = SUCCESS;
25331                 goto out;
25332         }
25333  
25334 @@ -1925,12 +2123,12 @@ mptscsih_dev_reset(struct scsi_cmnd * SC
25335                 goto out;
25336         }
25337  
25338 -       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
25339 -           vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
25340 -           mptscsih_get_tm_timeout(ioc));
25341 +       retval = mptscsih_IssueTaskMgmt(hd,
25342 +           MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, vdevice->vtarget->channel,
25343 +           vdevice->vtarget->id, 0, 0, mptscsih_get_tm_timeout(ioc));
25344  
25345   out:
25346 -       printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
25347 +       printk(MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
25348             ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
25349  
25350         if (retval == 0)
25351 @@ -1955,12 +2153,12 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
25352         MPT_SCSI_HOST   *hd;
25353         int              retval;
25354         VirtDevice       *vdevice;
25355 -       MPT_ADAPTER     *ioc;
25356 +       MPT_ADAPTER *ioc;
25357  
25358         /* If we can't locate our host adapter structure, return FAILED status.
25359          */
25360         if ((hd = shost_priv(SCpnt->device->host)) == NULL){
25361 -               printk(KERN_ERR MYNAM ": bus reset: "
25362 +               printk(KERN_ERR MYNAM ": bus_reset: "
25363                    "Can't locate host! (sc=%p)\n", SCpnt);
25364                 return FAILED;
25365         }
25366 @@ -1970,11 +2168,13 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
25367                ioc->name, SCpnt);
25368         scsi_print_command(SCpnt);
25369  
25370 -       if (hd->timeouts < -1)
25371 -               hd->timeouts++;
25372 +       if (ioc->timeouts < -1)
25373 +               ioc->timeouts++;
25374  
25375         vdevice = SCpnt->device->hostdata;
25376 -       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
25377 +       if (!vdevice || !vdevice->vtarget)
25378 +               return SUCCESS;
25379 +       retval = mptscsih_IssueTaskMgmt(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
25380             vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
25381  
25382         printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
25383 @@ -1999,8 +2199,9 @@ int
25384  mptscsih_host_reset(struct scsi_cmnd *SCpnt)
25385  {
25386         MPT_SCSI_HOST *  hd;
25387 -       int              retval;
25388 -       MPT_ADAPTER     *ioc;
25389 +       int              status = SUCCESS;
25390 +       MPT_ADAPTER     *ioc;
25391 +       int             retval;
25392  
25393         /*  If we can't locate the host to reset, then we failed. */
25394         if ((hd = shost_priv(SCpnt->device->host)) == NULL){
25395 @@ -2011,237 +2212,29 @@ mptscsih_host_reset(struct scsi_cmnd *SC
25396  
25397         ioc = hd->ioc;
25398         printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
25399 -           ioc->name, SCpnt);
25400 +              ioc->name, SCpnt);
25401  
25402         /*  If our attempts to reset the host failed, then return a failed
25403          *  status.  The host will be taken off line by the SCSI mid-layer.
25404          */
25405 -       if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) {
25406 -               retval = FAILED;
25407 -       } else {
25408 -               /*  Make sure TM pending is cleared and TM state is set to
25409 -                *  NONE.
25410 -                */
25411 -               retval = 0;
25412 -               hd->tmPending = 0;
25413 -               hd->tmState = TM_STATE_NONE;
25414 -       }
25415 +       if ((retval = mpt_SoftResetHandler(ioc, CAN_SLEEP)) != 0)
25416 +               retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
25417 +
25418 +       if (retval < 0)
25419 +               status = FAILED;
25420 +       else
25421 +               status = SUCCESS;
25422  
25423         printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
25424             ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
25425  
25426 -       return retval;
25427 -}
25428 -
25429 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25430 -/**
25431 - *     mptscsih_tm_pending_wait - wait for pending task management request to complete
25432 - *     @hd: Pointer to MPT host structure.
25433 - *
25434 - *     Returns {SUCCESS,FAILED}.
25435 - */
25436 -static int
25437 -mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
25438 -{
25439 -       unsigned long  flags;
25440 -       int            loop_count = 4 * 10;  /* Wait 10 seconds */
25441 -       int            status = FAILED;
25442 -       MPT_ADAPTER     *ioc = hd->ioc;
25443 -
25444 -       do {
25445 -               spin_lock_irqsave(&ioc->FreeQlock, flags);
25446 -               if (hd->tmState == TM_STATE_NONE) {
25447 -                       hd->tmState = TM_STATE_IN_PROGRESS;
25448 -                       hd->tmPending = 1;
25449 -                       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
25450 -                       status = SUCCESS;
25451 -                       break;
25452 -               }
25453 -               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
25454 -               msleep(250);
25455 -       } while (--loop_count);
25456 -
25457         return status;
25458  }
25459  
25460  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25461  /**
25462 - *     mptscsih_tm_wait_for_completion - wait for completion of TM task
25463 - *     @hd: Pointer to MPT host structure.
25464 - *     @timeout: timeout value
25465 - *
25466 - *     Returns {SUCCESS,FAILED}.
25467 - */
25468 -static int
25469 -mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
25470 -{
25471 -       unsigned long  flags;
25472 -       int            loop_count = 4 * timeout;
25473 -       int            status = FAILED;
25474 -       MPT_ADAPTER     *ioc = hd->ioc;
25475 -
25476 -       do {
25477 -               spin_lock_irqsave(&ioc->FreeQlock, flags);
25478 -               if(hd->tmPending == 0) {
25479 -                       status = SUCCESS;
25480 -                       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
25481 -                       break;
25482 -               }
25483 -               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
25484 -               msleep(250);
25485 -       } while (--loop_count);
25486 -
25487 -       return status;
25488 -}
25489 -
25490 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25491 -static void
25492 -mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
25493 -{
25494 -       char *desc;
25495 -
25496 -       switch (response_code) {
25497 -       case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
25498 -               desc = "The task completed.";
25499 -               break;
25500 -       case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
25501 -               desc = "The IOC received an invalid frame status.";
25502 -               break;
25503 -       case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
25504 -               desc = "The task type is not supported.";
25505 -               break;
25506 -       case MPI_SCSITASKMGMT_RSP_TM_FAILED:
25507 -               desc = "The requested task failed.";
25508 -               break;
25509 -       case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
25510 -               desc = "The task completed successfully.";
25511 -               break;
25512 -       case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
25513 -               desc = "The LUN request is invalid.";
25514 -               break;
25515 -       case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
25516 -               desc = "The task is in the IOC queue and has not been sent to target.";
25517 -               break;
25518 -       default:
25519 -               desc = "unknown";
25520 -               break;
25521 -       }
25522 -       printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
25523 -               ioc->name, response_code, desc);
25524 -}
25525 -
25526 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25527 -/**
25528 - *     mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
25529 - *     @ioc: Pointer to MPT_ADAPTER structure
25530 - *     @mf: Pointer to SCSI task mgmt request frame
25531 - *     @mr: Pointer to SCSI task mgmt reply frame
25532 - *
25533 - *     This routine is called from mptbase.c::mpt_interrupt() at the completion
25534 - *     of any SCSI task management request.
25535 - *     This routine is registered with the MPT (base) driver at driver
25536 - *     load/init time via the mpt_register() API call.
25537 - *
25538 - *     Returns 1 indicating alloc'd request frame ptr should be freed.
25539 - **/
25540 -int
25541 -mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
25542 -{
25543 -       SCSITaskMgmtReply_t     *pScsiTmReply;
25544 -       SCSITaskMgmt_t          *pScsiTmReq;
25545 -       MPT_SCSI_HOST           *hd;
25546 -       unsigned long            flags;
25547 -       u16                      iocstatus;
25548 -       u8                       tmType;
25549 -       u32                      termination_count;
25550 -
25551 -       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
25552 -           ioc->name, mf, mr));
25553 -       if (!ioc->sh) {
25554 -               dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
25555 -                   "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
25556 -               return 1;
25557 -       }
25558 -
25559 -       if (mr == NULL) {
25560 -               dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
25561 -                   "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
25562 -               return 1;
25563 -       }
25564 -
25565 -       hd = shost_priv(ioc->sh);
25566 -       pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
25567 -       pScsiTmReq = (SCSITaskMgmt_t*)mf;
25568 -       tmType = pScsiTmReq->TaskType;
25569 -       iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
25570 -       termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
25571 -
25572 -       if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
25573 -           pScsiTmReply->ResponseCode)
25574 -               mptscsih_taskmgmt_response_code(ioc,
25575 -                   pScsiTmReply->ResponseCode);
25576 -       DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
25577 -
25578 -#ifdef CONFIG_FUSION_LOGGING
25579 -       if ((ioc->debug_level & MPT_DEBUG_REPLY) ||
25580 -                               (ioc->debug_level & MPT_DEBUG_TM ))
25581 -               printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
25582 -                       "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
25583 -                       "term_cmnds=%d\n", __func__, ioc->id, pScsiTmReply->Bus,
25584 -                        pScsiTmReply->TargetID, pScsiTmReq->TaskType,
25585 -                       le16_to_cpu(pScsiTmReply->IOCStatus),
25586 -                       le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
25587 -                       le32_to_cpu(pScsiTmReply->TerminationCount));
25588 -#endif
25589 -       if (!iocstatus) {
25590 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name));
25591 -                       hd->abortSCpnt = NULL;
25592 -               goto out;
25593 -       }
25594 -
25595 -       /* Error?  (anything non-zero?) */
25596 -
25597 -       /* clear flags and continue.
25598 -        */
25599 -       switch (tmType) {
25600 -
25601 -       case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
25602 -               if (termination_count == 1)
25603 -                       iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
25604 -               hd->abortSCpnt = NULL;
25605 -               break;
25606 -
25607 -       case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
25608 -
25609 -               /* If an internal command is present
25610 -                * or the TM failed - reload the FW.
25611 -                * FC FW may respond FAILED to an ABORT
25612 -                */
25613 -               if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
25614 -                   hd->cmdPtr)
25615 -                       if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
25616 -                               printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name);
25617 -               break;
25618 -
25619 -       case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
25620 -       default:
25621 -               break;
25622 -       }
25623 -
25624 - out:
25625 -       spin_lock_irqsave(&ioc->FreeQlock, flags);
25626 -       hd->tmPending = 0;
25627 -       hd->tmState = TM_STATE_NONE;
25628 -       hd->tm_iocstatus = iocstatus;
25629 -       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
25630 -
25631 -       return 1;
25632 -}
25633 -
25634 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25635 -/*
25636   *     This is anyones guess quite frankly.
25637 - */
25638 + **/
25639  int
25640  mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
25641                 sector_t capacity, int geom[])
25642 @@ -2278,40 +2271,82 @@ mptscsih_bios_param(struct scsi_device *
25643         return 0;
25644  }
25645  
25646 -/* Search IOC page 3 to determine if this is hidden physical disk
25647 +/**
25648 + * Search IOC page 3 to determine if this is hidden physical disk
25649   *
25650 - */
25651 + **/
25652  int
25653  mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
25654  {
25655         struct inactive_raid_component_info *component_info;
25656 -       int i;
25657 +       u8 i, j;
25658 +       RaidPhysDiskPage1_t *phys_disk;
25659         int rc = 0;
25660 +       int num_paths;
25661  
25662         if (!ioc->raid_data.pIocPg3)
25663                 goto out;
25664         for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
25665                 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
25666 -                   (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
25667 +                   (channel ==
25668 +                    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
25669                         rc = 1;
25670                         goto out;
25671                 }
25672         }
25673  
25674 +       if (ioc->bus_type != SAS)
25675 +               goto out;
25676 +
25677 +       /*
25678 +        * Check if dual path
25679 +        */
25680 +       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
25681 +               num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
25682 +                   ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
25683 +               if (num_paths < 2)
25684 +                       continue;
25685 +               phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t,Path) +
25686 +                  (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
25687 +               if (!phys_disk)
25688 +                       continue;
25689 +               if ((mpt_raid_phys_disk_pg1(ioc,
25690 +                   ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
25691 +                   phys_disk))) {
25692 +                       kfree(phys_disk);
25693 +                       continue;
25694 +               }
25695 +               for (j = 0; j < num_paths; j++) {
25696 +                       if ((phys_disk->Path[j].Flags &
25697 +                           MPI_RAID_PHYSDISK1_FLAG_INVALID))
25698 +                               continue;
25699 +                       if ((phys_disk->Path[j].Flags &
25700 +                           MPI_RAID_PHYSDISK1_FLAG_BROKEN))
25701 +                               continue;
25702 +                       if ((id == phys_disk->Path[j].PhysDiskID) &&
25703 +                           (channel == phys_disk->Path[j].PhysDiskBus)) {
25704 +                               rc = 1;
25705 +                               kfree(phys_disk);
25706 +                               goto out;
25707 +                       }
25708 +               }
25709 +               kfree(phys_disk);
25710 +       }
25711 +
25712         /*
25713          * Check inactive list for matching phys disks
25714          */
25715         if (list_empty(&ioc->raid_data.inactive_list))
25716                 goto out;
25717  
25718 -       mutex_lock(&ioc->raid_data.inactive_list_mutex);
25719 +       down(&ioc->raid_data.inactive_list_mutex);
25720         list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
25721             list) {
25722                 if ((component_info->d.PhysDiskID == id) &&
25723                     (component_info->d.PhysDiskBus == channel))
25724                         rc = 1;
25725         }
25726 -       mutex_unlock(&ioc->raid_data.inactive_list_mutex);
25727 +       up(&ioc->raid_data.inactive_list_mutex);
25728  
25729   out:
25730         return rc;
25731 @@ -2322,43 +2357,84 @@ u8
25732  mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
25733  {
25734         struct inactive_raid_component_info *component_info;
25735 -       int i;
25736 +       int i,j;
25737 +       RaidPhysDiskPage1_t *phys_disk;
25738         int rc = -ENXIO;
25739 +       u8 num_paths;
25740  
25741         if (!ioc->raid_data.pIocPg3)
25742                 goto out;
25743         for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
25744                 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
25745 -                   (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
25746 +                   (channel ==
25747 +                    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
25748                         rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
25749                         goto out;
25750                 }
25751         }
25752  
25753 +       if (ioc->bus_type != SAS)
25754 +               goto out;
25755 +
25756 +       /*
25757 +        * Check if dual path
25758 +        */
25759 +       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
25760 +               num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
25761 +                   ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
25762 +               if (num_paths < 2)
25763 +                       continue;
25764 +               phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t,Path) +
25765 +                  (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
25766 +               if (!phys_disk)
25767 +                       continue;
25768 +               if ((mpt_raid_phys_disk_pg1(ioc,
25769 +                   ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
25770 +                   phys_disk))) {
25771 +                       kfree(phys_disk);
25772 +                       continue;
25773 +               }
25774 +               for (j = 0; j < num_paths; j++) {
25775 +                       if ((phys_disk->Path[j].Flags &
25776 +                           MPI_RAID_PHYSDISK1_FLAG_INVALID))
25777 +                               continue;
25778 +                       if ((phys_disk->Path[j].Flags &
25779 +                           MPI_RAID_PHYSDISK1_FLAG_BROKEN))
25780 +                               continue;
25781 +                       if ((id == phys_disk->Path[j].PhysDiskID) &&
25782 +                           (channel == phys_disk->Path[j].PhysDiskBus)) {
25783 +                               rc = phys_disk->PhysDiskNum;
25784 +                               kfree(phys_disk);
25785 +                               goto out;
25786 +                       }
25787 +               }
25788 +               kfree(phys_disk);
25789 +       }
25790 +
25791         /*
25792          * Check inactive list for matching phys disks
25793          */
25794         if (list_empty(&ioc->raid_data.inactive_list))
25795                 goto out;
25796  
25797 -       mutex_lock(&ioc->raid_data.inactive_list_mutex);
25798 +       down(&ioc->raid_data.inactive_list_mutex);
25799         list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
25800             list) {
25801                 if ((component_info->d.PhysDiskID == id) &&
25802                     (component_info->d.PhysDiskBus == channel))
25803                         rc = component_info->d.PhysDiskNum;
25804         }
25805 -       mutex_unlock(&ioc->raid_data.inactive_list_mutex);
25806 +       up(&ioc->raid_data.inactive_list_mutex);
25807  
25808   out:
25809         return rc;
25810  }
25811  EXPORT_SYMBOL(mptscsih_raid_id_to_num);
25812  
25813 -/*
25814 +/**
25815   *     OS entry point to allow for host driver to free allocated memory
25816   *     Called if no device present or device being unloaded
25817 - */
25818 + **/
25819  void
25820  mptscsih_slave_destroy(struct scsi_device *sdev)
25821  {
25822 @@ -2370,23 +2446,25 @@ mptscsih_slave_destroy(struct scsi_devic
25823  
25824         starget = scsi_target(sdev);
25825         vtarget = starget->hostdata;
25826 +       vtarget->num_luns--;
25827         vdevice = sdev->hostdata;
25828 +       if (!vdevice)
25829 +               return;
25830  
25831         mptscsih_search_running_cmds(hd, vdevice);
25832 -       vtarget->num_luns--;
25833 -       mptscsih_synchronize_cache(hd, vdevice);
25834 +       mptscsih_synchronize_cache(sdev, hd, vdevice);
25835         kfree(vdevice);
25836         sdev->hostdata = NULL;
25837  }
25838  
25839  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25840 -/*
25841 +/**
25842   *     mptscsih_change_queue_depth - This function will set a devices queue depth
25843   *     @sdev: per scsi_device pointer
25844   *     @qdepth: requested queue depth
25845   *
25846   *     Adding support for new 'change_queue_depth' api.
25847 -*/
25848 + **/
25849  int
25850  mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
25851  {
25852 @@ -2401,15 +2479,16 @@ mptscsih_change_queue_depth(struct scsi_
25853         vtarget = starget->hostdata;
25854  
25855         if (ioc->bus_type == SPI) {
25856 -               if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
25857 -                       max_depth = 1;
25858 -               else if (sdev->type == TYPE_DISK &&
25859 -                        vtarget->minSyncFactor <= MPT_ULTRA160)
25860 +               if (sdev->type == TYPE_DISK &&
25861 +                   vtarget->minSyncFactor <= MPT_ULTRA160)
25862                         max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
25863                 else
25864                         max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
25865         } else
25866 -               max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
25867 +               max_depth = ioc->sh->can_queue;
25868 +
25869 +       if (!sdev->tagged_supported)
25870 +               max_depth = 1;
25871  
25872         if (qdepth > max_depth)
25873                 qdepth = max_depth;
25874 @@ -2419,15 +2498,24 @@ mptscsih_change_queue_depth(struct scsi_
25875                 tagged = MSG_SIMPLE_TAG;
25876  
25877         scsi_adjust_queue_depth(sdev, tagged, qdepth);
25878 +
25879 +       if (sdev->inquiry_len > 7)
25880 +               sdev_printk(KERN_INFO, sdev, MYIOC_s_FMT "qdepth=%d, "
25881 +                   "tagged=%d, simple=%d, ordered=%d, scsi_level=%d, "
25882 +                   "cmd_que=%d\n", ioc->name, sdev->queue_depth,
25883 +                   sdev->tagged_supported, sdev->simple_tags,
25884 +                   sdev->ordered_tags, sdev->scsi_level,
25885 +                   (sdev->inquiry[7] & 2) >> 1);
25886 +
25887         return sdev->queue_depth;
25888  }
25889  
25890 -/*
25891 +/**
25892   *     OS entry point to adjust the queue_depths on a per-device basis.
25893   *     Called once per device the bus scan. Use it to force the queue_depth
25894   *     member to 1 if a device does not support Q tags.
25895   *     Return non-zero if fails.
25896 - */
25897 + **/
25898  int
25899  mptscsih_slave_configure(struct scsi_device *sdev)
25900  {
25901 @@ -2436,52 +2524,37 @@ mptscsih_slave_configure(struct scsi_dev
25902         VirtDevice              *vdevice;
25903         struct scsi_target      *starget;
25904         MPT_SCSI_HOST           *hd = shost_priv(sh);
25905 -       MPT_ADAPTER             *ioc = hd->ioc;
25906 +       MPT_ADAPTER             *ioc = hd->ioc;
25907  
25908         starget = scsi_target(sdev);
25909         vtarget = starget->hostdata;
25910         vdevice = sdev->hostdata;
25911 +       vdevice->configured_lun = 1;
25912  
25913 -       dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25914 -               "device @ %p, channel=%d, id=%d, lun=%d\n",
25915 -               ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
25916 -       if (ioc->bus_type == SPI)
25917 -               dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25918 -                   "sdtr %d wdtr %d ppr %d inq length=%d\n",
25919 -                   ioc->name, sdev->sdtr, sdev->wdtr,
25920 -                   sdev->ppr, sdev->inquiry_len));
25921 +       if ((ioc->bus_type != SAS) && (sdev->id > sh->max_id)) {
25922 +               /* error case, should never happen */
25923 +               scsi_adjust_queue_depth(sdev, 0, 1);
25924 +               goto slave_configure_exit;
25925 +       }
25926  
25927 -       vdevice->configured_lun = 1;
25928 -       mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
25929 +       mptscsih_change_queue_depth(sdev, ioc->sdev_queue_depth);
25930  
25931 -       dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25932 -               "Queue depth=%d, tflags=%x\n",
25933 -               ioc->name, sdev->queue_depth, vtarget->tflags));
25934 -
25935 -       if (ioc->bus_type == SPI)
25936 -               dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25937 -                   "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
25938 -                   ioc->name, vtarget->negoFlags, vtarget->maxOffset,
25939 -                   vtarget->minSyncFactor));
25940 -
25941 -       dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
25942 -               "tagged %d, simple %d, ordered %d\n",
25943 -               ioc->name,sdev->tagged_supported, sdev->simple_tags,
25944 -               sdev->ordered_tags));
25945 +slave_configure_exit:
25946  
25947         return 0;
25948  }
25949  
25950  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25951 -/*
25952 +/**
25953   *  Private routines...
25954   */
25955  
25956  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25957 -/* Utility function to copy sense data from the scsi_cmnd buffer
25958 +/**
25959 + * Utility function to copy sense data from the scsi_cmnd buffer
25960   * to the FC and SCSI target structures.
25961   *
25962 - */
25963 + **/
25964  static void
25965  mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
25966  {
25967 @@ -2521,31 +2594,31 @@ mptscsih_copy_sense_data(struct scsi_cmn
25968                                 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
25969  
25970                                 ioc->eventContext++;
25971 -                               if (ioc->pcidev->vendor ==
25972 -                                   PCI_VENDOR_ID_IBM) {
25973 -                                       mptscsih_issue_sep_command(ioc,
25974 -                                           vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
25975 -                                       vdevice->vtarget->tflags |=
25976 -                                           MPT_TARGET_FLAGS_LED_ON;
25977 +                               if (ioc->pcidev->vendor == PCI_VENDOR_ID_IBM) {
25978 +                                       mptscsih_issue_sep_command(ioc, vdevice->vtarget,
25979 +                                           MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
25980 +                                       vdevice->vtarget->tflags |= MPT_TARGET_FLAGS_LED_ON;
25981                                 }
25982                         }
25983                 }
25984         } else {
25985                 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
25986 -                               ioc->name));
25987 +                   ioc->name));
25988         }
25989  }
25990  
25991  /**
25992   * mptscsih_get_scsi_lookup
25993 - * @ioc: Pointer to MPT_ADAPTER structure
25994 - * @i: index into the array
25995   *
25996   * retrieves scmd entry from ScsiLookup[] array list
25997   *
25998 + * @ioc: Pointer to MPT_ADAPTER structure
25999 + * @i: index into the array
26000 + *
26001   * Returns the scsi_cmd pointer
26002 + *
26003   **/
26004 -static struct scsi_cmnd *
26005 +struct scsi_cmnd *
26006  mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
26007  {
26008         unsigned long   flags;
26009 @@ -2560,12 +2633,14 @@ mptscsih_get_scsi_lookup(MPT_ADAPTER *io
26010  
26011  /**
26012   * mptscsih_getclear_scsi_lookup
26013 - * @ioc: Pointer to MPT_ADAPTER structure
26014 - * @i: index into the array
26015   *
26016   * retrieves and clears scmd entry from ScsiLookup[] array list
26017   *
26018 + * @ioc: Pointer to MPT_ADAPTER structure
26019 + * @i: index into the array
26020 + *
26021   * Returns the scsi_cmd pointer
26022 + *
26023   **/
26024  static struct scsi_cmnd *
26025  mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
26026 @@ -2602,10 +2677,14 @@ mptscsih_set_scsi_lookup(MPT_ADAPTER *io
26027  }
26028  
26029  /**
26030 - * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list
26031 + * SCPNT_TO_LOOKUP_IDX
26032 + *
26033 + * search's for a given scmd in the ScsiLookup[] array list
26034 + *
26035   * @ioc: Pointer to MPT_ADAPTER structure
26036 - * @sc: scsi_cmnd pointer
26037 - */
26038 + * @scmd: scsi_cmnd pointer
26039 + *
26040 + **/
26041  static int
26042  SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
26043  {
26044 @@ -2627,380 +2706,226 @@ SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, st
26045  
26046  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
26047  int
26048 -mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
26049 +mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
26050  {
26051 -       MPT_SCSI_HOST   *hd;
26052 -       unsigned long    flags;
26053 -
26054 -       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
26055 -           ": IOC %s_reset routed to SCSI host driver!\n",
26056 -           ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
26057 -           reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
26058 -
26059 -       /* If a FW reload request arrives after base installed but
26060 -        * before all scsi hosts have been attached, then an alt_ioc
26061 -        * may have a NULL sh pointer.
26062 -        */
26063 -       if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
26064 -               return 0;
26065 -       else
26066 -               hd = shost_priv(ioc->sh);
26067 -
26068 -       if (reset_phase == MPT_IOC_SETUP_RESET) {
26069 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name));
26070 -
26071 -               /* Clean Up:
26072 -                * 1. Set Hard Reset Pending Flag
26073 -                * All new commands go to doneQ
26074 -                */
26075 -               hd->resetPending = 1;
26076 -
26077 -       } else if (reset_phase == MPT_IOC_PRE_RESET) {
26078 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name));
26079 -
26080 -               /* 2. Flush running commands
26081 -                *      Clean ScsiLookup (and associated memory)
26082 -                *      AND clean mytaskQ
26083 -                */
26084 +       u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
26085  
26086 -               /* 2b. Reply to OS all known outstanding I/O commands.
26087 -                */
26088 -               mptscsih_flush_running_cmds(hd);
26089 +       devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
26090 +           "MPT event (=%02Xh) routed to SCSI host driver!\n",
26091 +           ioc->name, event));
26092  
26093 -               /* 2c. If there was an internal command that
26094 -                * has not completed, configuration or io request,
26095 -                * free these resources.
26096 -                */
26097 -               if (hd->cmdPtr) {
26098 -                       del_timer(&hd->timer);
26099 -                       mpt_free_msg_frame(ioc, hd->cmdPtr);
26100 -               }
26101 +       if ((event == MPI_EVENT_IOC_BUS_RESET ||
26102 +           event == MPI_EVENT_EXT_BUS_RESET) &&
26103 +           (ioc->bus_type == SPI) && (ioc->soft_resets < -1))
26104 +                       ioc->soft_resets++;
26105  
26106 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name));
26107 +       return 1;               /* currently means nothing really */
26108 +}
26109  
26110 -       } else {
26111 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name));
26112 +int
26113 +mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
26114 +{
26115 +       MPT_ADAPTER             *ioc = hd->ioc;
26116 +       MpiRaidActionRequest_t  *pReq;
26117 +       MPT_FRAME_HDR           *mf;
26118 +       int                     ret;
26119 +       unsigned long           timeleft;
26120  
26121 -               /* Once a FW reload begins, all new OS commands are
26122 -                * redirected to the doneQ w/ a reset status.
26123 -                * Init all control structures.
26124 -                */
26125 +       mutex_lock(&ioc->internal_cmds.mutex);
26126  
26127 -               /* 2. Chain Buffer initialization
26128 -                */
26129 +       /* Get and Populate a free Frame
26130 +        */
26131 +       if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
26132 +               dfailprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!\n",
26133 +                       ioc->name, __FUNCTION__));
26134 +               ret = -EAGAIN;
26135 +               goto out;
26136 +       }
26137 +       pReq = (MpiRaidActionRequest_t *)mf;
26138 +       if (quiesce)
26139 +               pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
26140 +       else
26141 +               pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
26142 +       pReq->Reserved1 = 0;
26143 +       pReq->ChainOffset = 0;
26144 +       pReq->Function = MPI_FUNCTION_RAID_ACTION;
26145 +       pReq->VolumeID = id;
26146 +       pReq->VolumeBus = channel;
26147 +       pReq->PhysDiskNum = 0;
26148 +       pReq->MsgFlags = 0;
26149 +       pReq->Reserved2 = 0;
26150 +       pReq->ActionDataWord = 0; /* Reserved for this action */
26151  
26152 -               /* 4. Renegotiate to all devices, if SPI
26153 -                */
26154 +       ioc->add_sge((char *)&pReq->ActionDataSGE,
26155 +               MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
26156  
26157 -               /* 5. Enable new commands to be posted
26158 -                */
26159 -               spin_lock_irqsave(&ioc->FreeQlock, flags);
26160 -               hd->tmPending = 0;
26161 -               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
26162 -               hd->resetPending = 0;
26163 -               hd->tmState = TM_STATE_NONE;
26164 +       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",
26165 +                       ioc->name, pReq->Action, channel, id));
26166  
26167 -               /* 6. If there was an internal command,
26168 -                * wake this process up.
26169 -                */
26170 -               if (hd->cmdPtr) {
26171 -                       /*
26172 -                        * Wake up the original calling thread
26173 -                        */
26174 -                       hd->pLocal = &hd->localReply;
26175 -                       hd->pLocal->completion = MPT_SCANDV_DID_RESET;
26176 -                       hd->scandv_wait_done = 1;
26177 -                       wake_up(&hd->scandv_waitq);
26178 -                       hd->cmdPtr = NULL;
26179 +       INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
26180 +       mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
26181 +       timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, 10*HZ);
26182 +       if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
26183 +               ret = -ETIME;
26184 +               dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: TIMED OUT!\n",
26185 +                   ioc->name, __FUNCTION__));
26186 +               if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
26187 +                       goto out;
26188 +               if (!timeleft) {
26189 +                       printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
26190 +                           ioc->name, __FUNCTION__);
26191 +                       if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
26192 +                               mpt_HardResetHandler(ioc, CAN_SLEEP);
26193 +                       mpt_free_msg_frame(ioc, mf);
26194                 }
26195 -
26196 -               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name));
26197 -
26198 +               goto out;
26199         }
26200  
26201 -       return 1;               /* currently means nothing really */
26202 +       ret = ioc->internal_cmds.completion_code;
26203 +
26204 + out:
26205 +       CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
26206 +       mutex_unlock(&ioc->internal_cmds.mutex);
26207 +       return ret;
26208  }
26209  
26210 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
26211 -int
26212 -mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
26213 +/**
26214 + *     mptscsih_get_completion_code -
26215 + *     @ioc: Pointer to MPT_ADAPTER structure
26216 + *     @reply:
26217 + *     @cmd:
26218 + *
26219 + **/
26220 +static int
26221 +mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
26222  {
26223 -       MPT_SCSI_HOST *hd;
26224 -       u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
26225 +       SCSIIOReply_t   *pReply;
26226 +       MpiRaidActionReply_t *pr;
26227 +       u8               scsi_status;
26228 +       u16              status;
26229 +       int              completion_code;
26230  
26231 -       devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
26232 -                       ioc->name, event));
26233 +       pReply = (SCSIIOReply_t *)reply;
26234 +       status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
26235 +       scsi_status = pReply->SCSIStatus;
26236  
26237 -       if (ioc->sh == NULL ||
26238 -               ((hd = shost_priv(ioc->sh)) == NULL))
26239 -               return 1;
26240 +       devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
26241 +           "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
26242 +            ioc->name, status, pReply->SCSIState, scsi_status, le32_to_cpu(pReply->IOCLogInfo)));
26243  
26244 -       switch (event) {
26245 -       case MPI_EVENT_UNIT_ATTENTION:                  /* 03 */
26246 -               /* FIXME! */
26247 -               break;
26248 -       case MPI_EVENT_IOC_BUS_RESET:                   /* 04 */
26249 -       case MPI_EVENT_EXT_BUS_RESET:                   /* 05 */
26250 -               if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
26251 -                       hd->soft_resets++;
26252 -               break;
26253 -       case MPI_EVENT_LOGOUT:                          /* 09 */
26254 -               /* FIXME! */
26255 +       switch(status) {
26256 +
26257 +       case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
26258 +               completion_code = MPT_SCANDV_SELECTION_TIMEOUT;
26259                 break;
26260  
26261 -       case MPI_EVENT_RESCAN:                          /* 06 */
26262 +       case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
26263 +       case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
26264 +       case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
26265 +       case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
26266 +               completion_code = MPT_SCANDV_DID_RESET;
26267                 break;
26268  
26269 -               /*
26270 -                *  CHECKME! Don't think we need to do
26271 -                *  anything for these, but...
26272 -                */
26273 -       case MPI_EVENT_LINK_STATUS_CHANGE:              /* 07 */
26274 -       case MPI_EVENT_LOOP_STATE_CHANGE:               /* 08 */
26275 -               /*
26276 -                *  CHECKME!  Falling thru...
26277 -                */
26278 +       case MPI_IOCSTATUS_BUSY:
26279 +       case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
26280 +               completion_code = MPT_SCANDV_BUSY;
26281                 break;
26282  
26283 -       case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
26284 +       case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
26285 +       case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
26286 +       case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
26287 +               if (pReply->Function == MPI_FUNCTION_CONFIG) {
26288 +                       completion_code = MPT_SCANDV_GOOD;
26289 +               } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
26290 +                       pr = (MpiRaidActionReply_t *)reply;
26291 +                       if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
26292 +                               completion_code = MPT_SCANDV_GOOD;
26293 +                       else
26294 +                               completion_code = MPT_SCANDV_SOME_ERROR;
26295 +               } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)
26296 +                       completion_code = MPT_SCANDV_SENSE;
26297 +               else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
26298 +                       if (req->u.scsireq.CDB[0] == INQUIRY)
26299 +                               completion_code = MPT_SCANDV_ISSUE_SENSE;
26300 +                       else
26301 +                               completion_code = MPT_SCANDV_DID_RESET;
26302 +               }
26303 +               else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
26304 +                       completion_code = MPT_SCANDV_DID_RESET;
26305 +               else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
26306 +                       completion_code = MPT_SCANDV_DID_RESET;
26307 +               else if (scsi_status == MPI_SCSI_STATUS_BUSY)
26308 +                       completion_code = MPT_SCANDV_BUSY;
26309 +               else
26310 +                       completion_code = MPT_SCANDV_GOOD;
26311                 break;
26312  
26313 -       case MPI_EVENT_NONE:                            /* 00 */
26314 -       case MPI_EVENT_LOG_DATA:                        /* 01 */
26315 -       case MPI_EVENT_STATE_CHANGE:                    /* 02 */
26316 -       case MPI_EVENT_EVENT_CHANGE:                    /* 0A */
26317 +       case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:         /* 0x0047 */
26318 +               if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
26319 +                       completion_code = MPT_SCANDV_DID_RESET;
26320 +               else
26321 +                       completion_code = MPT_SCANDV_SOME_ERROR;
26322 +               break;
26323         default:
26324 -               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n",
26325 -                   ioc->name, event));
26326 +               completion_code = MPT_SCANDV_SOME_ERROR;
26327                 break;
26328 -       }
26329  
26330 -       return 1;               /* currently means nothing really */
26331 -}
26332 +       }       /* switch(status) */
26333  
26334 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
26335 -/*
26336 - *  Bus Scan and Domain Validation functionality ...
26337 - */
26338 +       devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
26339 +           "  completionCode set to %08xh\n", ioc->name, completion_code));
26340 +       return completion_code;
26341 +}
26342  
26343 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
26344 -/*
26345 - *     mptscsih_scandv_complete - Scan and DV callback routine registered
26346 - *     to Fustion MPT (base) driver.
26347 - *
26348 +/**
26349 + *     mptscsih_scandv_complete -
26350   *     @ioc: Pointer to MPT_ADAPTER structure
26351 - *     @mf: Pointer to original MPT request frame
26352 - *     @mr: Pointer to MPT reply frame (NULL if TurboReply)
26353 + *     @req:
26354 + *     @reply:
26355   *
26356 - *     This routine is called from mpt.c::mpt_interrupt() at the completion
26357 - *     of any SCSI IO request.
26358 - *     This routine is registered with the Fusion MPT (base) driver at driver
26359 - *     load/init time via the mpt_register() API call.
26360 - *
26361 - *     Returns 1 indicating alloc'd request frame ptr should be freed.
26362 - *
26363 - *     Remark: Sets a completion code and (possibly) saves sense data
26364 - *     in the IOC member localReply structure.
26365 - *     Used ONLY for DV and other internal commands.
26366 - */
26367 + **/
26368  int
26369 -mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
26370 +mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
26371  {
26372 -       MPT_SCSI_HOST   *hd;
26373         SCSIIORequest_t *pReq;
26374 -       int              completionCode;
26375 +       SCSIIOReply_t   *pReply;
26376 +       u8               cmd;
26377         u16              req_idx;
26378 +       u8              *sense_data;
26379 +       int              sz;
26380  
26381 -       hd = shost_priv(ioc->sh);
26382 -
26383 -       if ((mf == NULL) ||
26384 -           (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
26385 -               printk(MYIOC_s_ERR_FMT
26386 -                       "ScanDvComplete, %s req frame ptr! (=%p)\n",
26387 -                               ioc->name, mf?"BAD":"NULL", (void *) mf);
26388 -               goto wakeup;
26389 -       }
26390 -
26391 -       del_timer(&hd->timer);
26392 -       req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
26393 -       mptscsih_set_scsi_lookup(ioc, req_idx, NULL);
26394 -       pReq = (SCSIIORequest_t *) mf;
26395 +       ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
26396 +       ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD;
26397 +       if (!reply)
26398 +               goto out;
26399  
26400 -       if (mf != hd->cmdPtr) {
26401 -               printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
26402 -                               ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
26403 +       pReply = (SCSIIOReply_t *) reply;
26404 +       pReq = (SCSIIORequest_t *) req;
26405 +       ioc->internal_cmds.completion_code =
26406 +           mptscsih_get_completion_code(ioc, req, reply);
26407 +       ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
26408 +       memcpy(ioc->internal_cmds.reply, reply,
26409 +           min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength));
26410 +       cmd = reply->u.hdr.Function;
26411 +       if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
26412 +           (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) &&
26413 +           (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
26414 +               req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
26415 +               sense_data = ((u8 *)ioc->sense_buf_pool +
26416 +                   (req_idx * MPT_SENSE_BUFFER_ALLOC));
26417 +               sz = min_t(int, pReq->SenseBufferLength,
26418 +                   MPT_SENSE_BUFFER_ALLOC);
26419 +               memcpy(ioc->internal_cmds.sense, sense_data, sz);
26420         }
26421 -       hd->cmdPtr = NULL;
26422 -
26423 -       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
26424 -                       ioc->name, mf, mr, req_idx));
26425 -
26426 -       hd->pLocal = &hd->localReply;
26427 -       hd->pLocal->scsiStatus = 0;
26428 -
26429 -       /* If target struct exists, clear sense valid flag.
26430 -        */
26431 -       if (mr == NULL) {
26432 -               completionCode = MPT_SCANDV_GOOD;
26433 -       } else {
26434 -               SCSIIOReply_t   *pReply;
26435 -               u16              status;
26436 -               u8               scsi_status;
26437 -
26438 -               pReply = (SCSIIOReply_t *) mr;
26439 -
26440 -               status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
26441 -               scsi_status = pReply->SCSIStatus;
26442 -
26443 -
26444 -               switch(status) {
26445 -
26446 -               case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
26447 -                       completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
26448 -                       break;
26449 -
26450 -               case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
26451 -               case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
26452 -               case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
26453 -               case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
26454 -                       completionCode = MPT_SCANDV_DID_RESET;
26455 -                       break;
26456 -
26457 -               case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
26458 -               case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
26459 -               case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
26460 -                       if (pReply->Function == MPI_FUNCTION_CONFIG) {
26461 -                               ConfigReply_t *pr = (ConfigReply_t *)mr;
26462 -                               completionCode = MPT_SCANDV_GOOD;
26463 -                               hd->pLocal->header.PageVersion = pr->Header.PageVersion;
26464 -                               hd->pLocal->header.PageLength = pr->Header.PageLength;
26465 -                               hd->pLocal->header.PageNumber = pr->Header.PageNumber;
26466 -                               hd->pLocal->header.PageType = pr->Header.PageType;
26467 -
26468 -                       } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
26469 -                               /* If the RAID Volume request is successful,
26470 -                                * return GOOD, else indicate that
26471 -                                * some type of error occurred.
26472 -                                */
26473 -                               MpiRaidActionReply_t    *pr = (MpiRaidActionReply_t *)mr;
26474 -                               if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
26475 -                                       completionCode = MPT_SCANDV_GOOD;
26476 -                               else
26477 -                                       completionCode = MPT_SCANDV_SOME_ERROR;
26478 -                               memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
26479 -
26480 -                       } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
26481 -                               u8              *sense_data;
26482 -                               int              sz;
26483 -
26484 -                               /* save sense data in global structure
26485 -                                */
26486 -                               completionCode = MPT_SCANDV_SENSE;
26487 -                               hd->pLocal->scsiStatus = scsi_status;
26488 -                               sense_data = ((u8 *)ioc->sense_buf_pool +
26489 -                                       (req_idx * MPT_SENSE_BUFFER_ALLOC));
26490 -
26491 -                               sz = min_t(int, pReq->SenseBufferLength,
26492 -                                                       SCSI_STD_SENSE_BYTES);
26493 -                               memcpy(hd->pLocal->sense, sense_data, sz);
26494 -
26495 -                               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "  Check Condition, sense ptr %p\n",
26496 -                                   ioc->name, sense_data));
26497 -                       } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
26498 -                               if (pReq->CDB[0] == INQUIRY)
26499 -                                       completionCode = MPT_SCANDV_ISSUE_SENSE;
26500 -                               else
26501 -                                       completionCode = MPT_SCANDV_DID_RESET;
26502 -                       }
26503 -                       else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
26504 -                               completionCode = MPT_SCANDV_DID_RESET;
26505 -                       else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
26506 -                               completionCode = MPT_SCANDV_DID_RESET;
26507 -                       else {
26508 -                               completionCode = MPT_SCANDV_GOOD;
26509 -                               hd->pLocal->scsiStatus = scsi_status;
26510 -                       }
26511 -                       break;
26512 -
26513 -               case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:         /* 0x0047 */
26514 -                       if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
26515 -                               completionCode = MPT_SCANDV_DID_RESET;
26516 -                       else
26517 -                               completionCode = MPT_SCANDV_SOME_ERROR;
26518 -                       break;
26519 -
26520 -               default:
26521 -                       completionCode = MPT_SCANDV_SOME_ERROR;
26522 -                       break;
26523 -
26524 -               }       /* switch(status) */
26525 -
26526 -       } /* end of address reply case */
26527 -
26528 -       hd->pLocal->completion = completionCode;
26529 -
26530 -       /* MF and RF are freed in mpt_interrupt
26531 -        */
26532 -wakeup:
26533 -       /* Free Chain buffers (will never chain) in scan or dv */
26534 -       //mptscsih_freeChainBuffers(ioc, req_idx);
26535 -
26536 -       /*
26537 -        * Wake up the original calling thread
26538 -        */
26539 -       hd->scandv_wait_done = 1;
26540 -       wake_up(&hd->scandv_waitq);
26541 -
26542 + out:
26543 +       if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING))
26544 +               return 0;
26545 +       ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
26546 +       complete(&ioc->internal_cmds.done);
26547         return 1;
26548  }
26549  
26550  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
26551 -/*     mptscsih_timer_expired - Call back for timer process.
26552 - *     Used only for dv functionality.
26553 - *     @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
26554 - *
26555 - */
26556 -void
26557 -mptscsih_timer_expired(unsigned long data)
26558 -{
26559 -       MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
26560 -       MPT_ADAPTER     *ioc = hd->ioc;
26561 -
26562 -       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", ioc->name, hd->cmdPtr));
26563 -
26564 -       if (hd->cmdPtr) {
26565 -               MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
26566 -
26567 -               if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
26568 -                       /* Desire to issue a task management request here.
26569 -                        * TM requests MUST be single threaded.
26570 -                        * If old eh code and no TM current, issue request.
26571 -                        * If new eh code, do nothing. Wait for OS cmd timeout
26572 -                        *      for bus reset.
26573 -                        */
26574 -               } else {
26575 -                       /* Perform a FW reload */
26576 -                       if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
26577 -                               printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
26578 -                       }
26579 -               }
26580 -       } else {
26581 -               /* This should NEVER happen */
26582 -               printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", ioc->name);
26583 -       }
26584 -
26585 -       /* No more processing.
26586 -        * TM call will generate an interrupt for SCSI TM Management.
26587 -        * The FW will reply to all outstanding commands, callback will finish cleanup.
26588 -        * Hard reset clean-up will free all resources.
26589 -        */
26590 -       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", ioc->name));
26591 -
26592 -       return;
26593 -}
26594 -
26595 -
26596 -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
26597  /**
26598   *     mptscsih_do_cmd - Do internal command.
26599   *     @hd: MPT_SCSI_HOST pointer
26600 @@ -3019,28 +2944,33 @@ mptscsih_timer_expired(unsigned long dat
26601   *                0 if good
26602   *
26603   *              > 0 if command complete but some type of completion error.
26604 - */
26605 -static int
26606 + **/
26607 +int
26608  mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
26609  {
26610         MPT_FRAME_HDR   *mf;
26611         SCSIIORequest_t *pScsiReq;
26612 -       SCSIIORequest_t  ReqCopy;
26613         int              my_idx, ii, dir;
26614 -       int              rc, cmdTimeout;
26615 -       int             in_isr;
26616 +       int              timeout;
26617         char             cmdLen;
26618         char             CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
26619 -       char             cmd = io->cmd;
26620 -       MPT_ADAPTER     *ioc = hd->ioc;
26621 +       u8               cmd = io->cmd;
26622 +       MPT_ADAPTER *ioc = hd->ioc;
26623 +       int              ret = 0;
26624 +       unsigned long    timeleft;
26625 +       unsigned long    flags;
26626  
26627 -       in_isr = in_interrupt();
26628 -       if (in_isr) {
26629 -               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n",
26630 -                                       ioc->name));
26631 -               return -EPERM;
26632 +       /* don't send internal command during diag reset */
26633 +       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
26634 +       if (ioc->ioc_reset_in_progress) {
26635 +               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
26636 +               dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
26637 +                   "%s: busy with host reset\n", ioc->name, __FUNCTION__));
26638 +               return MPT_SCANDV_BUSY;
26639         }
26640 +       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
26641  
26642 +       mutex_lock(&ioc->internal_cmds.mutex);
26643  
26644         /* Set command specific information
26645          */
26646 @@ -3050,13 +2980,13 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
26647                 dir = MPI_SCSIIO_CONTROL_READ;
26648                 CDB[0] = cmd;
26649                 CDB[4] = io->size;
26650 -               cmdTimeout = 10;
26651 +               timeout = 10;
26652                 break;
26653  
26654         case TEST_UNIT_READY:
26655                 cmdLen = 6;
26656                 dir = MPI_SCSIIO_CONTROL_READ;
26657 -               cmdTimeout = 10;
26658 +               timeout = 10;
26659                 break;
26660  
26661         case START_STOP:
26662 @@ -3064,7 +2994,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
26663                 dir = MPI_SCSIIO_CONTROL_READ;
26664                 CDB[0] = cmd;
26665                 CDB[4] = 1;     /*Spin up the disk */
26666 -               cmdTimeout = 15;
26667 +               timeout = 15;
26668                 break;
26669  
26670         case REQUEST_SENSE:
26671 @@ -3072,7 +3002,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
26672                 CDB[0] = cmd;
26673                 CDB[4] = io->size;
26674                 dir = MPI_SCSIIO_CONTROL_READ;
26675 -               cmdTimeout = 10;
26676 +               timeout = 10;
26677                 break;
26678  
26679         case READ_BUFFER:
26680 @@ -3091,7 +3021,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
26681                 CDB[6] = (io->size >> 16) & 0xFF;
26682                 CDB[7] = (io->size >>  8) & 0xFF;
26683                 CDB[8] = io->size & 0xFF;
26684 -               cmdTimeout = 10;
26685 +               timeout = 10;
26686                 break;
26687  
26688         case WRITE_BUFFER:
26689 @@ -3106,21 +3036,21 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
26690                 CDB[6] = (io->size >> 16) & 0xFF;
26691                 CDB[7] = (io->size >>  8) & 0xFF;
26692                 CDB[8] = io->size & 0xFF;
26693 -               cmdTimeout = 10;
26694 +               timeout = 10;
26695                 break;
26696  
26697         case RESERVE:
26698                 cmdLen = 6;
26699                 dir = MPI_SCSIIO_CONTROL_READ;
26700                 CDB[0] = cmd;
26701 -               cmdTimeout = 10;
26702 +               timeout = 10;
26703                 break;
26704  
26705         case RELEASE:
26706                 cmdLen = 6;
26707                 dir = MPI_SCSIIO_CONTROL_READ;
26708                 CDB[0] = cmd;
26709 -               cmdTimeout = 10;
26710 +               timeout = 10;
26711                 break;
26712  
26713         case SYNCHRONIZE_CACHE:
26714 @@ -3128,20 +3058,42 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
26715                 dir = MPI_SCSIIO_CONTROL_READ;
26716                 CDB[0] = cmd;
26717  //             CDB[1] = 0x02;  /* set immediate bit */
26718 -               cmdTimeout = 10;
26719 +               timeout = 10;
26720 +               break;
26721 +
26722 +       case REPORT_LUNS:
26723 +               cmdLen = 12;
26724 +               dir = MPI_SCSIIO_CONTROL_READ;
26725 +               CDB[0] = cmd;
26726 +               CDB[6] = (io->size >> 24) & 0xFF;
26727 +               CDB[7] = (io->size >> 16) & 0xFF;
26728 +               CDB[8] = (io->size >>  8) & 0xFF;
26729 +               CDB[9] = io->size & 0xFF;
26730 +               timeout = 10;
26731 +               break;
26732 +
26733 +       case TRANSPORT_LAYER_RETRIES:
26734 +               CDB[0] = cmd;
26735 +               CDB[1] = 0x01;
26736 +               cmdLen = 6;
26737 +               dir = MPI_SCSIIO_CONTROL_READ;
26738 +               timeout = 10;
26739                 break;
26740  
26741         default:
26742                 /* Error Case */
26743 -               return -EFAULT;
26744 +               ret = -EFAULT;
26745 +               goto out;
26746         }
26747  
26748         /* Get and Populate a free Frame
26749 +        * MsgContext set in mpt_get_msg_frame call
26750          */
26751         if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
26752 -               dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n",
26753 -                   ioc->name));
26754 -               return -EBUSY;
26755 +               dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n",
26756 +                   ioc->name, __FUNCTION__));
26757 +               ret = MPT_SCANDV_BUSY;
26758 +               goto out;
26759         }
26760  
26761         pScsiReq = (SCSIIORequest_t *) mf;
26762 @@ -3164,14 +3116,10 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
26763  
26764         pScsiReq->CDBLength = cmdLen;
26765         pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
26766 -
26767         pScsiReq->Reserved = 0;
26768 -
26769 -       pScsiReq->MsgFlags = mpt_msg_flags();
26770 -       /* MsgContext set in mpt_get_msg_fram call  */
26771 +       pScsiReq->MsgFlags = mpt_msg_flags(ioc);
26772  
26773         int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
26774 -
26775         if (io->flags & MPT_ICFLAG_TAGGED_CMD)
26776                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
26777         else
26778 @@ -3179,74 +3127,61 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
26779  
26780         if (cmd == REQUEST_SENSE) {
26781                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
26782 -               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n",
26783 -                       ioc->name, cmd));
26784 +               devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
26785 +                   "%s: Untagged! 0x%02x\n", ioc->name, __FUNCTION__, cmd));
26786         }
26787  
26788 -       for (ii=0; ii < 16; ii++)
26789 -               pScsiReq->CDB[ii] = CDB[ii];
26790 +       for (ii = 0; ii < 16; ii++)
26791 +           pScsiReq->CDB[ii] = CDB[ii];
26792  
26793         pScsiReq->DataLength = cpu_to_le32(io->size);
26794         pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
26795                                            + (my_idx * MPT_SENSE_BUFFER_ALLOC));
26796  
26797 -       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
26798 -                       ioc->name, cmd, io->channel, io->id, io->lun));
26799 -
26800 -       if (dir == MPI_SCSIIO_CONTROL_READ) {
26801 -               mpt_add_sge((char *) &pScsiReq->SGL,
26802 -                       MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
26803 -                       io->data_dma);
26804 -       } else {
26805 -               mpt_add_sge((char *) &pScsiReq->SGL,
26806 -                       MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
26807 -                       io->data_dma);
26808 -       }
26809 -
26810 -       /* The ISR will free the request frame, but we need
26811 -        * the information to initialize the target. Duplicate.
26812 -        */
26813 -       memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
26814 -
26815 -       /* Issue this command after:
26816 -        *      finish init
26817 -        *      add timer
26818 -        * Wait until the reply has been received
26819 -        *  ScsiScanDvCtx callback function will
26820 -        *      set hd->pLocal;
26821 -        *      set scandv_wait_done and call wake_up
26822 -        */
26823 -       hd->pLocal = NULL;
26824 -       hd->timer.expires = jiffies + HZ*cmdTimeout;
26825 -       hd->scandv_wait_done = 0;
26826 -
26827 -       /* Save cmd pointer, for resource free if timeout or
26828 -        * FW reload occurs
26829 -        */
26830 -       hd->cmdPtr = mf;
26831 +       devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
26832 +           "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n",
26833 +           ioc->name, __FUNCTION__, cmd, io->channel, io->id, io->lun));
26834 +
26835 +       if (dir == MPI_SCSIIO_CONTROL_READ)
26836 +               ioc->add_sge((char *) &pScsiReq->SGL,
26837 +                   MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma);
26838 +       else
26839 +               ioc->add_sge((char *) &pScsiReq->SGL,
26840 +                   MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma);
26841  
26842 -       add_timer(&hd->timer);
26843 +       INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
26844         mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
26845 -       wait_event(hd->scandv_waitq, hd->scandv_wait_done);
26846 -
26847 -       if (hd->pLocal) {
26848 -               rc = hd->pLocal->completion;
26849 -               hd->pLocal->skip = 0;
26850 -
26851 -               /* Always set fatal error codes in some cases.
26852 -                */
26853 -               if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
26854 -                       rc = -ENXIO;
26855 -               else if (rc == MPT_SCANDV_SOME_ERROR)
26856 -                       rc =  -rc;
26857 -       } else {
26858 -               rc = -EFAULT;
26859 -               /* This should never happen. */
26860 -               ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n",
26861 -                               ioc->name));
26862 +       timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done,
26863 +           timeout*HZ);
26864 +       if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
26865 +               ret = MPT_SCANDV_DID_RESET;
26866 +               dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
26867 +                   "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __FUNCTION__,
26868 +                   cmd));
26869 +               if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
26870 +                       mpt_free_msg_frame(ioc, mf);
26871 +                       goto out;
26872 +               }
26873 +               if (!timeleft) {
26874 +                       if (!mptscsih_scandv_bus_reset(ioc))
26875 +                               goto out;
26876 +                       printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
26877 +                           ioc->name, __FUNCTION__);
26878 +                       if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
26879 +                               mpt_HardResetHandler(ioc, CAN_SLEEP);
26880 +                       mpt_free_msg_frame(ioc, mf);
26881 +               }
26882 +               goto out;
26883         }
26884  
26885 -       return rc;
26886 +       ret = ioc->internal_cmds.completion_code;
26887 +       devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n",
26888 +                       ioc->name, __FUNCTION__, ret));
26889 +
26890 + out:
26891 +       CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
26892 +       mutex_unlock(&ioc->internal_cmds.mutex);
26893 +       return ret;
26894  }
26895  
26896  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
26897 @@ -3260,9 +3195,10 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
26898   *
26899   */
26900  static void
26901 -mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
26902 +mptscsih_synchronize_cache(struct scsi_device *sdev, MPT_SCSI_HOST *hd, VirtDevice *vdevice)
26903  {
26904         INTERNAL_CMD             iocmd;
26905 +       MPT_ADAPTER *ioc = hd->ioc;
26906  
26907         /* Ignore hidden raid components, this is handled when the command
26908          * is sent to the volume
26909 @@ -3274,23 +3210,23 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
26910             !vdevice->configured_lun)
26911                 return;
26912  
26913 -       /* Following parameters will not change
26914 -        * in this routine.
26915 -        */
26916 +       memset(&iocmd, 0, sizeof(INTERNAL_CMD));
26917         iocmd.cmd = SYNCHRONIZE_CACHE;
26918 -       iocmd.flags = 0;
26919         iocmd.physDiskNum = -1;
26920         iocmd.data = NULL;
26921         iocmd.data_dma = -1;
26922 -       iocmd.size = 0;
26923 -       iocmd.rsvd = iocmd.rsvd2 = 0;
26924         iocmd.channel = vdevice->vtarget->channel;
26925         iocmd.id = vdevice->vtarget->id;
26926         iocmd.lun = vdevice->lun;
26927  
26928 +       sdev_printk(KERN_INFO, sdev, MYIOC_s_FMT "SYNCHRONIZE_CACHE: fw_channel %d,"
26929 +           " fw_id %d\n", ioc->name, vdevice->vtarget->channel, vdevice->vtarget->id);
26930         mptscsih_do_cmd(hd, &iocmd);
26931  }
26932  
26933 +/*
26934 + * shost attributes
26935 + */
26936  static ssize_t
26937  mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr,
26938                          char *buf)
26939 @@ -3464,13 +3400,44 @@ mptscsih_debug_level_store(struct device
26940                 return -EINVAL;
26941  
26942         ioc->debug_level = val;
26943 -       printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
26944 -                               ioc->name, ioc->debug_level);
26945 +       printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n", ioc->name,
26946 +           ioc->debug_level);
26947         return strlen(buf);
26948  }
26949  static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
26950         mptscsih_debug_level_show, mptscsih_debug_level_store);
26951  
26952 +static ssize_t
26953 +mptscsih_disable_hotplug_remove_show(struct device *dev, struct device_attribute *attr, char *buf)
26954 +{
26955 +       struct Scsi_Host *host = class_to_shost(dev);
26956 +       MPT_SCSI_HOST   *hd = shost_priv(host);
26957 +       MPT_ADAPTER *ioc = hd->ioc;
26958 +
26959 +       return snprintf(buf, PAGE_SIZE, "%02xh\n", ioc->disable_hotplug_remove);
26960 +}
26961 +static ssize_t
26962 +mptscsih_disable_hotplug_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
26963 +{
26964 +       struct Scsi_Host *host = class_to_shost(dev);
26965 +       MPT_SCSI_HOST   *hd = shost_priv(host);
26966 +       MPT_ADAPTER *ioc = hd->ioc;
26967 +       int val = 0;
26968 +
26969 +       if (sscanf(buf, "%x", &val) != 1)
26970 +               return -EINVAL;
26971 +
26972 +       ioc->disable_hotplug_remove = val;
26973 +       if (ioc->disable_hotplug_remove)
26974 +               printk(MYIOC_s_INFO_FMT "disabling hotplug remove\n",
26975 +                   ioc->name);
26976 +       else
26977 +               printk(MYIOC_s_INFO_FMT "eanbling hotplug remove\n", ioc->name);
26978 +       return strlen(buf);
26979 +}
26980 +static DEVICE_ATTR(disable_hotplug_remove, S_IRUGO | S_IWUSR,
26981 +       mptscsih_disable_hotplug_remove_show, mptscsih_disable_hotplug_remove_store);
26982 +
26983  struct device_attribute *mptscsih_host_attrs[] = {
26984         &dev_attr_version_fw,
26985         &dev_attr_version_bios,
26986 @@ -3484,6 +3451,7 @@ struct device_attribute *mptscsih_host_a
26987         &dev_attr_io_delay,
26988         &dev_attr_device_delay,
26989         &dev_attr_debug_level,
26990 +       &dev_attr_disable_hotplug_remove,
26991         NULL,
26992  };
26993  EXPORT_SYMBOL(mptscsih_host_attrs);
26994 @@ -3510,7 +3478,9 @@ EXPORT_SYMBOL(mptscsih_scandv_complete);
26995  EXPORT_SYMBOL(mptscsih_event_process);
26996  EXPORT_SYMBOL(mptscsih_ioc_reset);
26997  EXPORT_SYMBOL(mptscsih_change_queue_depth);
26998 -EXPORT_SYMBOL(mptscsih_timer_expired);
26999 -EXPORT_SYMBOL(mptscsih_TMHandler);
27000 -
27001 +EXPORT_SYMBOL(mptscsih_IssueTaskMgmt);
27002 +EXPORT_SYMBOL(mptscsih_do_cmd);
27003 +EXPORT_SYMBOL(mptscsih_quiesce_raid);
27004 +EXPORT_SYMBOL(mptscsih_get_scsi_lookup);
27005 +EXPORT_SYMBOL(mptscsih_taskmgmt_response_code);
27006  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
27007 --- a/drivers/message/fusion/mptscsih.h
27008 +++ b/drivers/message/fusion/mptscsih.h
27009 @@ -60,6 +60,7 @@
27010  #define MPT_SCANDV_SELECTION_TIMEOUT   (0x00000008)
27011  #define MPT_SCANDV_ISSUE_SENSE         (0x00000010)
27012  #define MPT_SCANDV_FALLBACK            (0x00000020)
27013 +#define MPT_SCANDV_BUSY                        (0x00000040)
27014  
27015  #define MPT_SCANDV_MAX_RETRIES         (10)
27016  
27017 @@ -71,6 +72,7 @@
27018  #define MPT_ICFLAG_DID_RESET   0x20    /* Bus Reset occurred with this command */
27019  #define MPT_ICFLAG_RESERVED    0x40    /* Reserved has been issued */
27020  
27021 +
27022  #define MPT_SCSI_CMD_PER_DEV_HIGH      64
27023  #define MPT_SCSI_CMD_PER_DEV_LOW       32
27024  
27025 @@ -84,9 +86,11 @@
27026  #define MPTSCSIH_DOMAIN_VALIDATION      1
27027  #define MPTSCSIH_MAX_WIDTH              1
27028  #define MPTSCSIH_MIN_SYNC               0x08
27029 +#define MPTSCSIH_QAS                    1
27030  #define MPTSCSIH_SAF_TE                 0
27031  #define MPTSCSIH_PT_CLEAR               0
27032  
27033 +#define TRANSPORT_LAYER_RETRIES                0xC2
27034  #endif
27035  
27036  typedef struct _internal_cmd {
27037 @@ -112,7 +116,7 @@ extern int mptscsih_resume(struct pci_de
27038  extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
27039  extern const char * mptscsih_info(struct Scsi_Host *SChost);
27040  extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
27041 -extern void mptscsih_slave_destroy(struct scsi_device *device);
27042 +extern void mptscsih_slave_destroy(struct scsi_device *sdev);
27043  extern int mptscsih_slave_configure(struct scsi_device *device);
27044  extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
27045  extern int mptscsih_dev_reset(struct scsi_cmnd * SCpnt);
27046 @@ -125,8 +129,11 @@ extern int mptscsih_scandv_complete(MPT_
27047  extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
27048  extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
27049  extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
27050 -extern void mptscsih_timer_expired(unsigned long data);
27051 -extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
27052 +extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
27053  extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
27054  extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
27055 +extern int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
27056  extern struct device_attribute *mptscsih_host_attrs[];
27057 +extern int mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id);
27058 +extern struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
27059 +extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
27060 --- a/drivers/message/fusion/mptspi.c
27061 +++ b/drivers/message/fusion/mptspi.c
27062 @@ -53,8 +53,10 @@
27063  #include <linux/delay.h>       /* for mdelay */
27064  #include <linux/interrupt.h>   /* needed for in_interrupt() proto */
27065  #include <linux/reboot.h>      /* notifier code */
27066 +#include <linux/sched.h>
27067  #include <linux/workqueue.h>
27068  #include <linux/raid_class.h>
27069 +#include <linux/pci.h>
27070  
27071  #include <scsi/scsi.h>
27072  #include <scsi/scsi_cmnd.h>
27073 @@ -83,6 +85,10 @@ static int mpt_saf_te = MPTSCSIH_SAF_TE;
27074  module_param(mpt_saf_te, int, 0);
27075  MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1  (default=MPTSCSIH_SAF_TE=0)");
27076  
27077 +static int mpt_qas = MPTSCSIH_QAS;
27078 +module_param(mpt_qas, int, 1);
27079 +MODULE_PARM_DESC(mpt_qas, " Quick Arbitration and Selection (QAS) enabled=1, disabled=0 (default=MPTSCSIH_QAS=1)");
27080 +
27081  static void mptspi_write_offset(struct scsi_target *, int);
27082  static void mptspi_write_width(struct scsi_target *, int);
27083  static int mptspi_write_spi_device_pg1(struct scsi_target *,
27084 @@ -95,12 +101,12 @@ static u8  mptspiTaskCtx = MPT_MAX_PROTOC
27085  static u8      mptspiInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
27086  
27087  /**
27088 - *     mptspi_setTargetNegoParms  - Update the target negotiation parameters
27089 + *     mptspi_setTargetNegoParms  - Update the target negotiation parameters
27090   *     @hd: Pointer to a SCSI Host Structure
27091   *     @target: per target private data
27092   *     @sdev: SCSI device
27093   *
27094 - *     Update the target negotiation parameters based on the the Inquiry
27095 + *     Update the target negotiation parameters based on the the Inquiry
27096   *     data, adapter capabilities, and NVRAM settings.
27097   **/
27098  static void
27099 @@ -131,7 +137,7 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST 
27100                 if (scsi_device_sync(sdev)) {
27101                         factor = pspi_data->minSyncFactor;
27102                         if (!scsi_device_dt(sdev))
27103 -                                       factor = MPT_ULTRA2;
27104 +                               factor = MPT_ULTRA2;
27105                         else {
27106                                 if (!scsi_device_ius(sdev) &&
27107                                     !scsi_device_qas(sdev))
27108 @@ -209,6 +215,10 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST 
27109         target->maxOffset = offset;
27110         target->maxWidth = width;
27111  
27112 +       spi_min_period(scsi_target(sdev)) = factor;
27113 +       spi_max_offset(scsi_target(sdev)) = offset;
27114 +       spi_max_width(scsi_target(sdev)) = width;
27115 +
27116         target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
27117  
27118         /* Disable unused features.
27119 @@ -230,7 +240,7 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST 
27120                  */
27121  
27122                 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
27123 -                       "Disabling QAS due to noQas=%02x on id=%d!\n", ioc->name, noQas, id));
27124 +               "Disabling QAS due to noQas=%02x on id=%d!\n", ioc->name, noQas, id));
27125         }
27126  }
27127  
27128 @@ -262,7 +272,7 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, 
27129          */
27130         if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
27131                 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
27132 -                               "writeIOCPage4 : no msg frames!\n",ioc->name));
27133 +                   "writeIOCPage4 : no msg frames!\n", ioc->name));
27134                 return -EAGAIN;
27135         }
27136  
27137 @@ -300,11 +310,11 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, 
27138         flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
27139                 (IOCPage4Ptr->Header.PageLength + ii) * 4;
27140  
27141 -       mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
27142 +       ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
27143  
27144         ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
27145                 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
27146 -               ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
27147 +                       ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
27148  
27149         mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
27150  
27151 @@ -371,7 +381,7 @@ mptspi_initTarget(MPT_SCSI_HOST *hd, Vir
27152   *             non-zero = true
27153   *             zero = false
27154   *
27155 - */
27156 + **/
27157  static int
27158  mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
27159  {
27160 @@ -399,12 +409,11 @@ static int mptspi_target_alloc(struct sc
27161         struct Scsi_Host *shost = dev_to_shost(&starget->dev);
27162         struct _MPT_SCSI_HOST *hd = shost_priv(shost);
27163         VirtTarget              *vtarget;
27164 -       MPT_ADAPTER *ioc;
27165 +       MPT_ADAPTER *ioc = hd->ioc;
27166  
27167         if (hd == NULL)
27168                 return -ENODEV;
27169  
27170 -       ioc = hd->ioc;
27171         vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
27172         if (!vtarget)
27173                 return -ENOMEM;
27174 @@ -471,9 +480,12 @@ mptspi_target_destroy(struct scsi_target
27175  static void
27176  mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
27177  {
27178 -       ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d Requested = 0x%08x"
27179 +       if (!(hd->ioc->debug_level & MPT_DEBUG_DV))
27180 +               return;
27181 +
27182 +       starget_printk(KERN_DEBUG, starget, MYIOC_s_FMT "Wrote = 0x%08x"
27183             " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
27184 -           hd->ioc->name, starget->id, ii,
27185 +           hd->ioc->name, ii,
27186             ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
27187             ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
27188             ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
27189 @@ -483,7 +495,7 @@ mptspi_print_write_nego(struct _MPT_SCSI
27190             ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
27191             ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
27192             ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
27193 -           ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
27194 +           ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": "");
27195  }
27196  
27197  /**
27198 @@ -496,9 +508,12 @@ mptspi_print_write_nego(struct _MPT_SCSI
27199  static void
27200  mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
27201  {
27202 -       ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d Read = 0x%08x"
27203 +       if (!(hd->ioc->debug_level & MPT_DEBUG_DV))
27204 +               return;
27205 +
27206 +       starget_printk(KERN_DEBUG, starget, MYIOC_s_FMT "Read = 0x%08x"
27207             " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
27208 -           hd->ioc->name, starget->id, ii,
27209 +           hd->ioc->name, ii,
27210             ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
27211             ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
27212             ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
27213 @@ -508,7 +523,7 @@ mptspi_print_read_nego(struct _MPT_SCSI_
27214             ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
27215             ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
27216             ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
27217 -           ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
27218 +           ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": "");
27219  }
27220  
27221  static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
27222 @@ -557,9 +572,11 @@ static int mptspi_read_spi_device_pg0(st
27223         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
27224         cfg.dir = 0;
27225         cfg.pageAddr = starget->id;
27226 +       cfg.timeout = 60;
27227  
27228         if (mpt_config(ioc, &cfg)) {
27229 -               starget_printk(KERN_ERR, starget, MYIOC_s_FMT "mpt_config failed\n", ioc->name);
27230 +               starget_printk(KERN_ERR, starget,
27231 +                   MYIOC_s_FMT "mpt_config failed\n", ioc->name);
27232                 goto out_free;
27233         }
27234         err = 0;
27235 @@ -614,64 +631,11 @@ static void mptspi_read_parameters(struc
27236         spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
27237  }
27238  
27239 -static int
27240 -mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
27241 -{
27242 -       MpiRaidActionRequest_t  *pReq;
27243 -       MPT_FRAME_HDR           *mf;
27244 -       MPT_ADAPTER *ioc = hd->ioc;
27245 -
27246 -       /* Get and Populate a free Frame
27247 -        */
27248 -       if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
27249 -               ddvprintk(ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
27250 -                                       ioc->name));
27251 -               return -EAGAIN;
27252 -       }
27253 -       pReq = (MpiRaidActionRequest_t *)mf;
27254 -       if (quiesce)
27255 -               pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
27256 -       else
27257 -               pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
27258 -       pReq->Reserved1 = 0;
27259 -       pReq->ChainOffset = 0;
27260 -       pReq->Function = MPI_FUNCTION_RAID_ACTION;
27261 -       pReq->VolumeID = id;
27262 -       pReq->VolumeBus = channel;
27263 -       pReq->PhysDiskNum = 0;
27264 -       pReq->MsgFlags = 0;
27265 -       pReq->Reserved2 = 0;
27266 -       pReq->ActionDataWord = 0; /* Reserved for this action */
27267 -
27268 -       mpt_add_sge((char *)&pReq->ActionDataSGE,
27269 -               MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
27270 -
27271 -       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",
27272 -                       ioc->name, pReq->Action, channel, id));
27273 -
27274 -       hd->pLocal = NULL;
27275 -       hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
27276 -       hd->scandv_wait_done = 0;
27277 -
27278 -       /* Save cmd pointer, for resource free if timeout or
27279 -        * FW reload occurs
27280 -        */
27281 -       hd->cmdPtr = mf;
27282 -
27283 -       add_timer(&hd->timer);
27284 -       mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
27285 -       wait_event(hd->scandv_waitq, hd->scandv_wait_done);
27286 -
27287 -       if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
27288 -               return -1;
27289 -
27290 -       return 0;
27291 -}
27292 -
27293  static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
27294                              struct scsi_device *sdev)
27295  {
27296         VirtTarget *vtarget = scsi_target(sdev)->hostdata;
27297 +       struct scsi_target *starget = scsi_target(sdev);
27298         MPT_ADAPTER *ioc = hd->ioc;
27299  
27300         /* no DV on RAID devices */
27301 @@ -679,11 +643,20 @@ static void mptspi_dv_device(struct _MPT
27302             mptspi_is_raid(hd, sdev->id))
27303                 return;
27304  
27305 +       if (ioc->debug_level & MPT_DEBUG_DV)
27306 +               starget_printk(KERN_DEBUG, starget, MYIOC_s_FMT
27307 +                   "sdtr=%d, wdtr=%d, ppr=%d, min_period=0x%02x, "
27308 +                   "max_offset=0x%02x, max_width=%d, nego_flags=0x%02x, "
27309 +                   "tflags=0x%02x\n", ioc->name, sdev->sdtr, sdev->wdtr,
27310 +                   sdev->ppr, spi_min_period(starget),
27311 +                   spi_max_offset(starget), spi_max_width(starget),
27312 +                   vtarget->negoFlags, vtarget->tflags);
27313 +
27314         /* If this is a piece of a RAID, then quiesce first */
27315         if (sdev->channel == 1 &&
27316             mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
27317 -               starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT
27318 -                   "Integrated RAID quiesce failed\n", ioc->name);
27319 +               starget_printk(KERN_ERR, scsi_target(sdev),
27320 +                   MYIOC_s_FMT "Integrated RAID quiesce failed\n", ioc->name);
27321                 return;
27322         }
27323  
27324 @@ -693,8 +666,8 @@ static void mptspi_dv_device(struct _MPT
27325  
27326         if (sdev->channel == 1 &&
27327             mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
27328 -               starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT
27329 -                   "Integrated RAID resume failed\n", ioc->name);
27330 +               starget_printk(KERN_ERR, scsi_target(sdev),
27331 +                   MYIOC_s_FMT "Integrated RAID resume failed\n", ioc->name);
27332  
27333         mptspi_read_parameters(sdev->sdev_target);
27334         spi_display_xfer_agreement(sdev->sdev_target);
27335 @@ -716,7 +689,7 @@ static int mptspi_slave_alloc(struct scs
27336         vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
27337         if (!vdevice) {
27338                 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
27339 -                               ioc->name, sizeof(VirtDevice));
27340 +                   ioc->name, sizeof(VirtDevice));
27341                 return -ENOMEM;
27342         }
27343  
27344 @@ -738,21 +711,13 @@ static int mptspi_slave_configure(struct
27345  {
27346         struct _MPT_SCSI_HOST *hd = shost_priv(sdev->host);
27347         VirtTarget *vtarget = scsi_target(sdev)->hostdata;
27348 -       int ret;
27349 +       int     ret;
27350  
27351         mptspi_initTarget(hd, vtarget, sdev);
27352 -
27353         ret = mptscsih_slave_configure(sdev);
27354 -
27355         if (ret)
27356                 return ret;
27357  
27358 -       ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d min_period=0x%02x"
27359 -               " max_offset=0x%02x max_width=%d\n", hd->ioc->name,
27360 -               sdev->id, spi_min_period(scsi_target(sdev)),
27361 -               spi_max_offset(scsi_target(sdev)),
27362 -               spi_max_width(scsi_target(sdev))));
27363 -
27364         if ((sdev->channel == 1 ||
27365              !(mptspi_is_raid(hd, sdev->id))) &&
27366             !spi_initial_dv(sdev->sdev_target))
27367 @@ -857,8 +822,8 @@ static int mptspi_write_spi_device_pg1(s
27368  
27369         pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
27370         if (pg1 == NULL) {
27371 -               starget_printk(KERN_ERR, starget, MYIOC_s_FMT
27372 -                   "dma_alloc_coherent for parameters failed\n", ioc->name);
27373 +               starget_printk(KERN_ERR, starget,
27374 +                   MYIOC_s_FMT "dma_alloc_coherent for parameters failed\n", ioc->name);
27375                 return -EINVAL;
27376         }
27377  
27378 @@ -887,8 +852,8 @@ static int mptspi_write_spi_device_pg1(s
27379         mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
27380  
27381         if (mpt_config(ioc, &cfg)) {
27382 -               starget_printk(KERN_ERR, starget, MYIOC_s_FMT
27383 -                   "mpt_config failed\n", ioc->name);
27384 +               starget_printk(KERN_ERR, starget,
27385 +                   MYIOC_s_FMT "mpt_config failed\n", ioc->name);
27386                 goto out_free;
27387         }
27388         err = 0;
27389 @@ -963,14 +928,15 @@ static void mptspi_write_dt(struct scsi_
27390         if (spi_period(starget) == -1)
27391                 mptspi_read_parameters(starget);
27392  
27393 -       if (!dt && spi_period(starget) < 10)
27394 -               spi_period(starget) = 10;
27395 +       if (!dt) {
27396 +               spi_qas(starget) = 0;
27397 +               spi_iu(starget) = 0;
27398 +       }
27399  
27400         spi_dt(starget) = dt;
27401  
27402         nego = mptspi_getRP(starget);
27403  
27404 -
27405         pg1.RequestedParameters = cpu_to_le32(nego);
27406         pg1.Reserved = 0;
27407         pg1.Configuration = 0;
27408 @@ -986,9 +952,6 @@ static void mptspi_write_iu(struct scsi_
27409         if (spi_period(starget) == -1)
27410                 mptspi_read_parameters(starget);
27411  
27412 -       if (!iu && spi_period(starget) < 9)
27413 -               spi_period(starget) = 9;
27414 -
27415         spi_iu(starget) = iu;
27416  
27417         nego = mptspi_getRP(starget);
27418 @@ -1030,9 +993,11 @@ static void mptspi_write_qas(struct scsi
27419         struct _MPT_SCSI_HOST *hd = shost_priv(shost);
27420         VirtTarget *vtarget = starget->hostdata;
27421         u32 nego;
27422 +       MPT_ADAPTER *ioc = hd->ioc;
27423  
27424 -       if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
27425 -           hd->ioc->spi_data.noQas)
27426 +       if (!mpt_qas ||
27427 +           (vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
27428 +           ioc->spi_data.noQas)
27429                 spi_qas(starget) = 0;
27430         else
27431                 spi_qas(starget) = qas;
27432 @@ -1053,8 +1018,8 @@ static void mptspi_write_width(struct sc
27433  
27434         if (!width) {
27435                 spi_dt(starget) = 0;
27436 -               if (spi_period(starget) < 10)
27437 -                       spi_period(starget) = 10;
27438 +               spi_qas(starget) = 0;
27439 +               spi_iu(starget) = 0;
27440         }
27441  
27442         spi_width(starget) = width;
27443 @@ -1074,7 +1039,8 @@ struct work_queue_wrapper {
27444         int                     disk;
27445  };
27446  
27447 -static void mpt_work_wrapper(struct work_struct *work)
27448 +static void
27449 +mpt_work_wrapper(struct work_struct *work)
27450  {
27451         struct work_queue_wrapper *wqw =
27452                 container_of(work, struct work_queue_wrapper, work);
27453 @@ -1105,12 +1071,12 @@ static void mpt_work_wrapper(struct work
27454                 if(vtarget->id != disk)
27455                         continue;
27456  
27457 -               starget_printk(KERN_INFO, vtarget->starget, MYIOC_s_FMT
27458 -                   "Integrated RAID requests DV of new device\n", ioc->name);
27459 +               starget_printk(KERN_INFO, vtarget->starget,
27460 +                   MYIOC_s_FMT "Integrated RAID requests DV of new device\n", ioc->name);
27461                 mptspi_dv_device(hd, sdev);
27462         }
27463 -       shost_printk(KERN_INFO, shost, MYIOC_s_FMT
27464 -           "Integrated RAID detects new device %d\n", ioc->name, disk);
27465 +       shost_printk(KERN_INFO, shost,
27466 +           MYIOC_s_FMT "Integrated RAID detects new device %d\n", ioc->name, disk);
27467         scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, 1);
27468  }
27469  
27470 @@ -1121,8 +1087,8 @@ static void mpt_dv_raid(struct _MPT_SCSI
27471         MPT_ADAPTER *ioc = hd->ioc;
27472  
27473         if (!wqw) {
27474 -               shost_printk(KERN_ERR, ioc->sh, MYIOC_s_FMT
27475 -                   "Failed to act on RAID event for physical disk %d\n",
27476 +               shost_printk(KERN_ERR, ioc->sh,
27477 +                   MYIOC_s_FMT "Failed to act on RAID event for physical disk %d\n",
27478                     ioc->name, disk);
27479                 return;
27480         }
27481 @@ -1213,9 +1179,9 @@ static struct pci_device_id mptspi_pci_t
27482  MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
27483  
27484  
27485 -/*
27486 +/**
27487   * renegotiate for a given target
27488 - */
27489 + **/
27490  static void
27491  mptspi_dv_renegotiate_work(struct work_struct *work)
27492  {
27493 @@ -1261,32 +1227,33 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_H
27494         schedule_work(&wqw->work);
27495  }
27496  
27497 -/*
27498 +/**
27499   * spi module reset handler
27500 - */
27501 + **/
27502  static int
27503  mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
27504  {
27505 +       struct _MPT_SCSI_HOST *hd = NULL;
27506         int rc;
27507  
27508         rc = mptscsih_ioc_reset(ioc, reset_phase);
27509 +       if ((ioc->bus_type != SPI) || (!rc))
27510 +               goto out;
27511  
27512 -       /* only try to do a renegotiation if we're properly set up
27513 -        * if we get an ioc fault on bringup, ioc->sh will be NULL */
27514 -       if (reset_phase == MPT_IOC_POST_RESET &&
27515 -           ioc->sh) {
27516 -               struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
27517 +       hd = shost_priv(ioc->sh);
27518 +       if (!hd->ioc)
27519 +               goto out;
27520  
27521 +       if (ioc->active && reset_phase == MPT_IOC_POST_RESET)
27522                 mptspi_dv_renegotiate(hd);
27523 -       }
27524 -
27525 + out:
27526         return rc;
27527  }
27528  
27529  #ifdef CONFIG_PM
27530 -/*
27531 +/**
27532   * spi module resume handler
27533 - */
27534 + **/
27535  static int
27536  mptspi_resume(struct pci_dev *pdev)
27537  {
27538 @@ -1303,13 +1270,13 @@ mptspi_resume(struct pci_dev *pdev)
27539  
27540  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
27541  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
27542 -/*
27543 +/**
27544   *     mptspi_probe - Installs scsi devices per bus.
27545   *     @pdev: Pointer to pci_dev structure
27546   *
27547   *     Returns 0 for success, non-zero for failure.
27548   *
27549 - */
27550 + **/
27551  static int
27552  mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
27553  {
27554 @@ -1423,19 +1390,18 @@ mptspi_probe(struct pci_dev *pdev, const
27555          * A slightly different algorithm is required for
27556          * 64bit SGEs.
27557          */
27558 -       scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
27559 -       if (sizeof(dma_addr_t) == sizeof(u64)) {
27560 +       scale = ioc->req_sz/ioc->SGE_size;
27561 +       if (ioc->sg_addr_size == sizeof(u64)) {
27562                 numSGE = (scale - 1) *
27563                   (ioc->facts.MaxChainDepth-1) + scale +
27564 -                 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
27565 -                 sizeof(u32));
27566 +                 (ioc->req_sz - 60) / ioc->SGE_size;
27567         } else {
27568                 numSGE = 1 + (scale - 1) *
27569                   (ioc->facts.MaxChainDepth-1) + scale +
27570 -                 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
27571 -                 sizeof(u32));
27572 +                 (ioc->req_sz - 64) / ioc->SGE_size;
27573         }
27574  
27575 +
27576         if (numSGE < sh->sg_tablesize) {
27577                 /* Reset this value */
27578                 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
27579 @@ -1444,11 +1410,11 @@ mptspi_probe(struct pci_dev *pdev, const
27580                 sh->sg_tablesize = numSGE;
27581         }
27582  
27583 -       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
27584 -
27585         hd = shost_priv(sh);
27586         hd->ioc = ioc;
27587  
27588 +       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
27589 +
27590         /* SCSI needs scsi_cmnd lookup table!
27591          * (with size equal to req_depth*PtrSz!)
27592          */
27593 @@ -1462,39 +1428,12 @@ mptspi_probe(struct pci_dev *pdev, const
27594         dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
27595                  ioc->name, ioc->ScsiLookup));
27596  
27597 -       /* Clear the TM flags
27598 -        */
27599 -       hd->tmPending = 0;
27600 -       hd->tmState = TM_STATE_NONE;
27601 -       hd->resetPending = 0;
27602 -       hd->abortSCpnt = NULL;
27603 -
27604 -       /* Clear the pointer used to store
27605 -        * single-threaded commands, i.e., those
27606 -        * issued during a bus scan, dv and
27607 -        * configuration pages.
27608 -        */
27609 -       hd->cmdPtr = NULL;
27610 -
27611 -       /* Initialize this SCSI Hosts' timers
27612 -        * To use, set the timer expires field
27613 -        * and add_timer
27614 -        */
27615 -       init_timer(&hd->timer);
27616 -       hd->timer.data = (unsigned long) hd;
27617 -       hd->timer.function = mptscsih_timer_expired;
27618 -
27619 +       ioc->sdev_queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
27620         ioc->spi_data.Saf_Te = mpt_saf_te;
27621 -
27622 -       hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
27623         ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
27624 -               "saf_te %x\n",
27625 -               ioc->name,
27626 -               mpt_saf_te));
27627 -       ioc->spi_data.noQas = 0;
27628 +           "saf_te %x\n", ioc->name, mpt_saf_te));
27629 +       ioc->spi_data.noQas = mpt_qas ? 0 : MPT_TARGET_NO_NEGO_QAS;
27630  
27631 -       init_waitqueue_head(&hd->scandv_waitq);
27632 -       hd->scandv_wait_done = 0;
27633         hd->last_queue_full = 0;
27634         hd->spi_pending = 0;
27635  
27636 @@ -1514,7 +1453,7 @@ mptspi_probe(struct pci_dev *pdev, const
27637          * issue internal bus reset
27638          */
27639         if (ioc->spi_data.bus_reset)
27640 -               mptscsih_TMHandler(hd,
27641 +               mptscsih_IssueTaskMgmt(hd,
27642                     MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
27643                     0, 0, 0, 0, 5);
27644  
27645 @@ -1544,7 +1483,7 @@ static struct pci_driver mptspi_driver =
27646   *     mptspi_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
27647   *
27648   *     Returns 0 for success, non-zero for failure.
27649 - */
27650 + **/
27651  static int __init
27652  mptspi_init(void)
27653  {
27654 @@ -1574,7 +1513,8 @@ mptspi_init(void)
27655  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
27656  /**
27657   *     mptspi_exit - Unregisters MPT adapter(s)
27658 - */
27659 + *
27660 + **/
27661  static void __exit
27662  mptspi_exit(void)
27663  {
27664 @@ -1582,7 +1522,6 @@ mptspi_exit(void)
27665  
27666         mpt_reset_deregister(mptspiDoneCtx);
27667         mpt_event_deregister(mptspiDoneCtx);
27668 -
27669         mpt_deregister(mptspiInternalCtx);
27670         mpt_deregister(mptspiTaskCtx);
27671         mpt_deregister(mptspiDoneCtx);
27672 --- /dev/null
27673 +++ b/drivers/message/fusion/rejected_ioctls/diag_buffer.c
27674 @@ -0,0 +1,667 @@
27675 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
27676 +/* REGISTER DIAG BUFFER Routine.
27677 + *
27678 + * Outputs:    None.
27679 + * Return:     0 if successful
27680 + *             -EFAULT if data unavailable
27681 + *             -EBUSY  if previous command timout and IOC reset is not complete.
27682 + *             -ENODEV if no such device/adapter
27683 + *             -ETIME  if timer expires
27684 + *             -ENOMEM if memory allocation error
27685 + */
27686 +static int
27687 +mptctl_register_diag_buffer (unsigned long arg)
27688 +{
27689 +       mpt_diag_register_t     __user *uarg = (void __user *) arg;
27690 +       mpt_diag_register_t     karg;
27691 +       MPT_ADAPTER             *ioc;
27692 +       int                     iocnum, rc, ii;
27693 +       void *                  request_data;
27694 +       dma_addr_t              request_data_dma;
27695 +       u32                     request_data_sz;
27696 +       MPT_FRAME_HDR           *mf;
27697 +       DiagBufferPostRequest_t *diag_buffer_post_request;
27698 +       DiagBufferPostReply_t   *diag_buffer_post_reply;
27699 +       u32                     tmp;
27700 +       u8                      buffer_type;
27701 +       unsigned long           timeleft;
27702 +
27703 +       rc = 0;
27704 +       if (copy_from_user(&karg, uarg, sizeof(mpt_diag_register_t))) {
27705 +               printk(KERN_ERR "%s@%d::%s - "
27706 +               "Unable to read in mpt_diag_register_t struct @ %p\n",
27707 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
27708 +               return -EFAULT;
27709 +       }
27710 +
27711 +       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
27712 +               (ioc == NULL)) {
27713 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
27714 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
27715 +               return -ENODEV;
27716 +       }
27717 +
27718 +       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
27719 +               __FUNCTION__));
27720 +       buffer_type = karg.data.BufferType;
27721 +       if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
27722 +               printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability for "
27723 +                   "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
27724 +               return -ENODEV;
27725 +       }
27726 +
27727 +       if (ioc->DiagBuffer_Status[buffer_type] &
27728 +           MPT_DIAG_BUFFER_IS_REGISTERED) {
27729 +               printk(MYIOC_s_DEBUG_FMT "%s: already has a Registered "
27730 +                   "buffer for buffer_type=%x\n", ioc->name, __FUNCTION__,
27731 +                   buffer_type);
27732 +               return -EFAULT;
27733 +       }
27734 +
27735 +       /* Get a free request frame and save the message context.
27736 +        */
27737 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
27738 +               return -EAGAIN;
27739 +
27740 +       request_data = ioc->DiagBuffer[buffer_type];
27741 +       request_data_sz = karg.data.RequestedBufferSize;
27742 +
27743 +       if (request_data) {
27744 +               request_data_dma = ioc->DiagBuffer_dma[buffer_type];
27745 +               if (request_data_sz != ioc->DiagBuffer_sz[buffer_type]) {
27746 +                       pci_free_consistent(ioc->pcidev,
27747 +                           ioc->DiagBuffer_sz[buffer_type],
27748 +                           request_data, request_data_dma);
27749 +                       request_data = NULL;
27750 +               }
27751 +       }
27752 +
27753 +       if (request_data == NULL) {
27754 +               ioc->DiagBuffer_sz[buffer_type] = 0;
27755 +               ioc->DiagBuffer_dma[buffer_type] = 0;
27756 +               ioc->DataSize[buffer_type] = 0;
27757 +               request_data = pci_alloc_consistent(
27758 +                       ioc->pcidev, request_data_sz, &request_data_dma);
27759 +               if (request_data == NULL) {
27760 +                       printk(MYIOC_s_DEBUG_FMT "%s: pci_alloc_consistent"
27761 +                           " FAILED, (request_sz=%d)\n", ioc->name,
27762 +                           __FUNCTION__, request_data_sz);
27763 +                       mpt_free_msg_frame(ioc, mf);
27764 +                       return -EAGAIN;
27765 +               }
27766 +               ioc->DiagBuffer[buffer_type] = request_data;
27767 +               ioc->DiagBuffer_sz[buffer_type] = request_data_sz;
27768 +               ioc->DiagBuffer_dma[buffer_type] = request_data_dma;
27769 +       }
27770 +
27771 +       ioc->DiagBuffer_Status[buffer_type] = 0;
27772 +       diag_buffer_post_request = (DiagBufferPostRequest_t *)mf;
27773 +       diag_buffer_post_request->Function = MPI_FUNCTION_DIAG_BUFFER_POST;
27774 +       diag_buffer_post_request->ChainOffset = 0;
27775 +       diag_buffer_post_request->BufferType = karg.data.BufferType;
27776 +       diag_buffer_post_request->TraceLevel = ioc->TraceLevel[buffer_type] =
27777 +           karg.data.TraceLevel;
27778 +       diag_buffer_post_request->MsgFlags = 0;
27779 +       diag_buffer_post_request->Reserved1 = 0;
27780 +       diag_buffer_post_request->Reserved2 = 0;
27781 +       diag_buffer_post_request->Reserved3 = 0;
27782 +       diag_buffer_post_request->BufferAddress.High = 0;
27783 +       if (buffer_type == MPI_DIAG_BUF_TYPE_EXTENDED)
27784 +               ioc->ExtendedType[buffer_type] = karg.data.ExtendedType;
27785 +       else
27786 +               ioc->ExtendedType[buffer_type] = 0;
27787 +       diag_buffer_post_request->ExtendedType =
27788 +           cpu_to_le32(ioc->ExtendedType[buffer_type]);
27789 +       ioc->UniqueId[buffer_type] = karg.data.UniqueId;
27790 +       diag_buffer_post_request->BufferLength = cpu_to_le32(request_data_sz);
27791 +       for (ii = 0; ii < 4; ii++) {
27792 +               ioc->ProductSpecific[buffer_type][ii] =
27793 +                       karg.data.ProductSpecific[ii];
27794 +               diag_buffer_post_request->ProductSpecific[ii] =
27795 +                       cpu_to_le32(ioc->ProductSpecific[buffer_type][ii]);
27796 +       }
27797 +
27798 +       tmp = request_data_dma & 0xFFFFFFFF;
27799 +       diag_buffer_post_request->BufferAddress.Low = cpu_to_le32(tmp);
27800 +       if (ioc->sg_addr_size == sizeof(u64)) {
27801 +               tmp = (u32)((u64)request_data_dma >> 32);
27802 +               diag_buffer_post_request->BufferAddress.High = cpu_to_le32(tmp);
27803 +       }
27804 +
27805 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
27806 +           diag_buffer_post_request->MsgContext);
27807 +       INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
27808 +       mpt_put_msg_frame(mptctl_id, ioc, mf);
27809 +       timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
27810 +           MPT_IOCTL_DEFAULT_TIMEOUT*HZ);
27811 +       if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
27812 +               rc = -ETIME;
27813 +               printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name,
27814 +                   __FUNCTION__);
27815 +               if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
27816 +                       mpt_free_msg_frame(ioc, mf);
27817 +                       goto out;
27818 +               }
27819 +               if (!timeleft)
27820 +                       mptctl_timeout_expired(ioc, mf);
27821 +               goto out;
27822 +       }
27823 +
27824 +       /* process the completed Reply Message Frame */
27825 +       if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
27826 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: status=%x\n",
27827 +                   ioc->name, __FUNCTION__, ioc->ioctl_cmds.status));
27828 +               rc = -EFAULT;
27829 +               goto out;
27830 +       }
27831 +
27832 +       diag_buffer_post_reply = (DiagBufferPostReply_t *)ioc->ioctl_cmds.reply;
27833 +       if (le16_to_cpu(diag_buffer_post_reply->IOCStatus) ==
27834 +           MPI_IOCSTATUS_SUCCESS) {
27835 +               if (diag_buffer_post_reply->MsgLength > 5)
27836 +                       ioc->DataSize[buffer_type] =
27837 +                            le32_to_cpu(diag_buffer_post_reply->TransferLength);
27838 +               ioc->DiagBuffer_Status[buffer_type] |=
27839 +                       MPT_DIAG_BUFFER_IS_REGISTERED;
27840 +       } else {
27841 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: IOCStatus=%x "
27842 +                   "IOCLogInfo=%x\n", ioc->name, __FUNCTION__,
27843 +                   diag_buffer_post_reply->IOCStatus,
27844 +                   diag_buffer_post_reply->IOCLogInfo));
27845 +               rc = -EFAULT;
27846 +       }
27847 +
27848 + out:
27849 +
27850 +       CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
27851 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
27852 +       if (rc)
27853 +               pci_free_consistent(ioc->pcidev, request_data_sz,
27854 +                   request_data, request_data_dma);
27855 +       return rc;
27856 +}
27857 +
27858 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
27859 +/* RELEASE DIAG BUFFER Routine.
27860 + *
27861 + * Outputs:    None.
27862 + * Return:     0 if successful
27863 + *             -EFAULT if data unavailable
27864 + *             -EBUSY  if previous command timout and IOC reset is not complete.
27865 + *             -ENODEV if no such device/adapter
27866 + *             -ETIME  if timer expires
27867 + *             -ENOMEM if memory allocation error
27868 + */
27869 +static int
27870 +mptctl_release_diag_buffer (unsigned long arg)
27871 +{
27872 +       mpt_diag_release_t      __user *uarg = (void __user *) arg;
27873 +       mpt_diag_release_t      karg;
27874 +       MPT_ADAPTER             *ioc;
27875 +       void *                  request_data;
27876 +       int                     iocnum, rc;
27877 +       MPT_FRAME_HDR           *mf;
27878 +       DiagReleaseRequest_t    *diag_release;
27879 +       DiagReleaseReply_t      *diag_release_reply;
27880 +       u8                      buffer_type;
27881 +       unsigned long           timeleft;
27882 +
27883 +       rc = 0;
27884 +       if (copy_from_user(&karg, uarg, sizeof(mpt_diag_release_t))) {
27885 +               printk(KERN_ERR "%s@%d::%s - "
27886 +               "Unable to read in mpt_diag_release_t struct @ %p\n",
27887 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
27888 +               return -EFAULT;
27889 +       }
27890 +
27891 +       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
27892 +               (ioc == NULL)) {
27893 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
27894 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
27895 +               return -ENODEV;
27896 +       }
27897 +
27898 +       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
27899 +               __FUNCTION__));
27900 +       buffer_type = karg.data.UniqueId & 0x000000ff;
27901 +       if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
27902 +               printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability for "
27903 +                   "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
27904 +               return -ENODEV;
27905 +       }
27906 +
27907 +       if ((ioc->DiagBuffer_Status[buffer_type] &
27908 +               MPT_DIAG_BUFFER_IS_REGISTERED) == 0 ) {
27909 +               printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x is not "
27910 +                   "registered\n", ioc->name, __FUNCTION__, buffer_type);
27911 +               return -EFAULT;
27912 +       }
27913 +
27914 +       if (karg.data.UniqueId != ioc->UniqueId[buffer_type]) {
27915 +               printk(MYIOC_s_DEBUG_FMT "%s: unique_id=%x is not registered\n",
27916 +                   ioc->name, __FUNCTION__, karg.data.UniqueId);
27917 +               return -EFAULT;
27918 +       }
27919 +
27920 +       if (ioc->DiagBuffer_Status[buffer_type] & MPT_DIAG_BUFFER_IS_RELEASED) {
27921 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x "
27922 +                   "is already released\n", ioc->name, __FUNCTION__,
27923 +                   buffer_type));
27924 +               return rc;
27925 +       }
27926 +
27927 +       request_data = ioc->DiagBuffer[buffer_type];
27928 +
27929 +       if (request_data == NULL) {
27930 +               printk(MYIOC_s_DEBUG_FMT "%s: doesn't have buffer for "
27931 +                   "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
27932 +               return -ENODEV;
27933 +       }
27934 +
27935 +       /* Get a free request frame and save the message context.
27936 +        */
27937 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
27938 +               return -EAGAIN;
27939 +
27940 +       diag_release = (DiagReleaseRequest_t *)mf;
27941 +       diag_release->Function = MPI_FUNCTION_DIAG_RELEASE;
27942 +       diag_release->BufferType = buffer_type;
27943 +       diag_release->ChainOffset = 0;
27944 +       diag_release->Reserved1 = 0;
27945 +       diag_release->Reserved2 = 0;
27946 +       diag_release->Reserved3 = 0;
27947 +       diag_release->MsgFlags = 0;
27948 +
27949 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
27950 +           diag_release->MsgContext);
27951 +       INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
27952 +       mpt_put_msg_frame(mptctl_id, ioc, mf);
27953 +       timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
27954 +           MPT_IOCTL_DEFAULT_TIMEOUT*HZ);
27955 +       if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
27956 +               rc = -ETIME;
27957 +               printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name,
27958 +                   __FUNCTION__);
27959 +               if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
27960 +                       mpt_free_msg_frame(ioc, mf);
27961 +                       goto out;
27962 +               }
27963 +               if (!timeleft)
27964 +                       mptctl_timeout_expired(ioc, mf);
27965 +               goto out;
27966 +       }
27967 +
27968 +       /* process the completed Reply Message Frame */
27969 +       if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
27970 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: status=%x\n",
27971 +                   ioc->name, __FUNCTION__, ioc->ioctl_cmds.status));
27972 +               rc = -EFAULT;
27973 +               goto out;
27974 +       }
27975 +
27976 +       diag_release_reply = (DiagReleaseReply_t *)ioc->ioctl_cmds.reply;
27977 +       if (le16_to_cpu(diag_release_reply->IOCStatus) !=
27978 +           MPI_IOCSTATUS_SUCCESS) {
27979 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: IOCStatus=%x "
27980 +                       "IOCLogInfo=%x\n",
27981 +                   ioc->name, __FUNCTION__, diag_release_reply->IOCStatus,
27982 +                   diag_release_reply->IOCLogInfo));
27983 +               rc = -EFAULT;
27984 +       } else
27985 +               ioc->DiagBuffer_Status[buffer_type] |=
27986 +                   MPT_DIAG_BUFFER_IS_RELEASED;
27987 +
27988 + out:
27989 +
27990 +       CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
27991 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
27992 +       return rc;
27993 +}
27994 +
27995 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
27996 +/* UNREGISTER DIAG BUFFER Routine.
27997 + *
27998 + * Outputs:    None.
27999 + * Return:     0 if successful
28000 + *             -EFAULT if data unavailable
28001 + *             -EBUSY  if previous command timout and IOC reset is not complete.
28002 + *             -ENODEV if no such device/adapter
28003 + *             -ETIME  if timer expires
28004 + *             -ENOMEM if memory allocation error
28005 + */
28006 +static int
28007 +mptctl_unregister_diag_buffer (unsigned long arg)
28008 +{
28009 +       mpt_diag_unregister_t   __user *uarg = (void __user *) arg;
28010 +       mpt_diag_unregister_t   karg;
28011 +       MPT_ADAPTER             *ioc;
28012 +       int                     iocnum;
28013 +       void *                  request_data;
28014 +       dma_addr_t              request_data_dma;
28015 +       u32                     request_data_sz;
28016 +       u8                      buffer_type;
28017 +
28018 +       if (copy_from_user(&karg, uarg, sizeof(mpt_diag_unregister_t))) {
28019 +               printk(KERN_ERR "%s@%d::%s - "
28020 +               "Unable to read in mpt_diag_unregister_t struct @ %p\n",
28021 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
28022 +               return -EFAULT;
28023 +       }
28024 +
28025 +       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
28026 +               (ioc == NULL)) {
28027 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
28028 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
28029 +               return -ENODEV;
28030 +       }
28031 +
28032 +       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
28033 +               __FUNCTION__));
28034 +       buffer_type = karg.data.UniqueId & 0x000000ff;
28035 +       if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
28036 +               printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability for "
28037 +                   "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
28038 +               return -ENODEV;
28039 +       }
28040 +
28041 +       if ((ioc->DiagBuffer_Status[buffer_type] &
28042 +               MPT_DIAG_BUFFER_IS_REGISTERED) == 0) {
28043 +               printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x is not "
28044 +                   "registered\n", ioc->name, __FUNCTION__, buffer_type);
28045 +               return -EFAULT;
28046 +       }
28047 +       if ((ioc->DiagBuffer_Status[buffer_type] &
28048 +               MPT_DIAG_BUFFER_IS_RELEASED) == 0) {
28049 +               printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x has not been "
28050 +                   "released\n", ioc->name, __FUNCTION__, buffer_type);
28051 +               return -EFAULT;
28052 +       }
28053 +
28054 +       if (karg.data.UniqueId != ioc->UniqueId[buffer_type]) {
28055 +               printk(MYIOC_s_DEBUG_FMT "%s: unique_id=%x is not registered\n",
28056 +                   ioc->name, __FUNCTION__, karg.data.UniqueId);
28057 +               return -EFAULT;
28058 +       }
28059 +
28060 +       request_data = ioc->DiagBuffer[buffer_type];
28061 +       if (!request_data) {
28062 +               printk(MYIOC_s_DEBUG_FMT "%s: doesn't have buffer for "
28063 +                   "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
28064 +               return -ENODEV;
28065 +       }
28066 +
28067 +       request_data_sz = ioc->DiagBuffer_sz[buffer_type];
28068 +       request_data_dma = ioc->DiagBuffer_dma[buffer_type];
28069 +       pci_free_consistent(ioc->pcidev, request_data_sz,
28070 +           request_data, request_data_dma);
28071 +       ioc->DiagBuffer[buffer_type] = NULL;
28072 +       ioc->DiagBuffer_Status[buffer_type] = 0;
28073 +       return 0;
28074 +}
28075 +
28076 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
28077 +/* QUERY DIAG BUFFER Routine.
28078 + *
28079 + * Outputs:    None.
28080 + * Return:     0 if successful
28081 + *             -EFAULT if data unavailable
28082 + *             -EBUSY  if previous command timout and IOC reset is not complete.
28083 + *             -ENODEV if no such device/adapter
28084 + *             -ETIME  if timer expires
28085 + *             -ENOMEM if memory allocation error
28086 + */
28087 +static int
28088 +mptctl_query_diag_buffer (unsigned long arg)
28089 +{
28090 +       mpt_diag_query_t        __user *uarg = (void __user *)arg;
28091 +       mpt_diag_query_t        karg;
28092 +       MPT_ADAPTER             *ioc;
28093 +       void *                  request_data;
28094 +       int                     iocnum, ii, rc;
28095 +       u8                      buffer_type;
28096 +
28097 +       rc = -EFAULT;
28098 +       if (copy_from_user(&karg, uarg, sizeof(mpt_diag_query_t))) {
28099 +               printk(KERN_ERR "%s@%d::%s - "
28100 +               "Unable to read in mpt_diag_query_t struct @ %p\n",
28101 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
28102 +               return -EFAULT;
28103 +       }
28104 +
28105 +       karg.data.Flags = 0;
28106 +       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
28107 +               (ioc == NULL)) {
28108 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
28109 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
28110 +               goto out;
28111 +       }
28112 +
28113 +       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
28114 +               __FUNCTION__));
28115 +       buffer_type = karg.data.BufferType;
28116 +       if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
28117 +               printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability for "
28118 +                   "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
28119 +               goto out;
28120 +       }
28121 +
28122 +       if ((ioc->DiagBuffer_Status[buffer_type] &
28123 +               MPT_DIAG_BUFFER_IS_REGISTERED) == 0) {
28124 +               printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x is not "
28125 +                   "registered\n", ioc->name, __FUNCTION__, buffer_type);
28126 +               goto out;
28127 +       }
28128 +
28129 +       if (karg.data.UniqueId & 0xffffff00) {
28130 +               if (karg.data.UniqueId != ioc->UniqueId[buffer_type]) {
28131 +                       printk(MYIOC_s_DEBUG_FMT "%s: unique_id=%x is not "
28132 +                           "registered\n", ioc->name, __FUNCTION__,
28133 +                           karg.data.UniqueId);
28134 +                       goto out;
28135 +               }
28136 +       }
28137 +
28138 +       request_data = ioc->DiagBuffer[buffer_type];
28139 +       if (!request_data) {
28140 +               printk(MYIOC_s_DEBUG_FMT "%s: doesn't have buffer for "
28141 +                   "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
28142 +               goto out;
28143 +       }
28144 +
28145 +       rc = 0;
28146 +       if (buffer_type == MPI_DIAG_BUF_TYPE_EXTENDED) {
28147 +               if (karg.data.ExtendedType != ioc->ExtendedType[buffer_type])
28148 +                       goto out;
28149 +       } else
28150 +               karg.data.ExtendedType = 0;
28151 +
28152 +       if (ioc->DiagBuffer_Status[buffer_type] & MPT_DIAG_BUFFER_IS_RELEASED)
28153 +               karg.data.Flags = 3;
28154 +       else
28155 +               karg.data.Flags = 7;
28156 +       karg.data.TraceLevel = ioc->TraceLevel[buffer_type];
28157 +       for (ii = 0; ii < 4; ii++)
28158 +               karg.data.ProductSpecific[ii] =
28159 +                   ioc->ProductSpecific[buffer_type][ii];
28160 +       karg.data.DataSize = ioc->DiagBuffer_sz[buffer_type];
28161 +       karg.data.DriverAddedBufferSize = 0;
28162 +       karg.data.UniqueId = ioc->UniqueId[buffer_type];
28163 +
28164 + out:
28165 +       if (copy_to_user(uarg, &karg, sizeof(mpt_diag_query_t))) {
28166 +               printk(MYIOC_s_ERR_FMT "%s Unable to write mpt_diag_query_t "
28167 +                   "data @ %p\n", ioc->name, __FUNCTION__, uarg);
28168 +               return -EFAULT;
28169 +       }
28170 +       return rc;
28171 +}
28172 +
28173 +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
28174 +/* READ DIAG BUFFER Routine.
28175 + *
28176 + * Outputs:    None.
28177 + * Return:     0 if successful
28178 + *             -EFAULT if data unavailable
28179 + *             -EBUSY  if previous command timout and IOC reset is not complete.
28180 + *             -ENODEV if no such device/adapter
28181 + *             -ETIME  if timer expires
28182 + *             -ENOMEM if memory allocation error
28183 + */
28184 +static int
28185 +mptctl_read_diag_buffer (unsigned long arg)
28186 +{
28187 +       mpt_diag_read_buffer_t  __user *uarg = (void __user *) arg;
28188 +       mpt_diag_read_buffer_t  karg;
28189 +       MPT_ADAPTER             *ioc;
28190 +       void                    *request_data, *diagData;
28191 +       dma_addr_t              request_data_dma;
28192 +       DiagBufferPostRequest_t *diag_buffer_post_request;
28193 +       DiagBufferPostReply_t   *diag_buffer_post_reply;
28194 +       MPT_FRAME_HDR           *mf;
28195 +       int                     iocnum, rc, ii;
28196 +       u8                      buffer_type;
28197 +       u32                     tmp;
28198 +       unsigned long           timeleft;
28199 +
28200 +       rc = 0;
28201 +       if (copy_from_user(&karg, uarg, sizeof(mpt_diag_read_buffer_t))) {
28202 +               printk(KERN_ERR "%s@%d::%s - "
28203 +               "Unable to read in mpt_diag_read_buffer_t struct @ %p\n",
28204 +                   __FILE__, __LINE__, __FUNCTION__, uarg);
28205 +               return -EFAULT;
28206 +       }
28207 +
28208 +       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
28209 +               (ioc == NULL)) {
28210 +               printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
28211 +                   __FILE__, __FUNCTION__, __LINE__, iocnum);
28212 +               return -ENODEV;
28213 +       }
28214 +
28215 +       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
28216 +           __FUNCTION__));
28217 +       buffer_type = karg.data.UniqueId & 0x000000ff;
28218 +       if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
28219 +               printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability "
28220 +                   "for buffer_type=%x\n", ioc->name, __FUNCTION__,
28221 +                   buffer_type);
28222 +               return -EFAULT;
28223 +       }
28224 +
28225 +       if (karg.data.UniqueId != ioc->UniqueId[buffer_type]) {
28226 +               printk(MYIOC_s_DEBUG_FMT "%s: unique_id=%x is not registered\n",
28227 +                   ioc->name, __FUNCTION__, karg.data.UniqueId);
28228 +               return -EFAULT;
28229 +       }
28230 +
28231 +       request_data = ioc->DiagBuffer[buffer_type];
28232 +       if (!request_data) {
28233 +               printk(MYIOC_s_DEBUG_FMT "%s: doesn't have buffer for "
28234 +                   "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
28235 +               return -EFAULT;
28236 +       }
28237 +
28238 +       diagData = (void *)(request_data + karg.data.StartingOffset);
28239 +       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: diagData=%p "
28240 +           "request_data=%p StartingOffset=%x\n", ioc->name, __FUNCTION__,
28241 +           diagData, request_data, karg.data.StartingOffset));
28242 +
28243 +       if (copy_to_user((void __user *)&uarg->data.DiagnosticData[0],
28244 +           diagData, karg.data.BytesToRead)) {
28245 +               printk(MYIOC_s_ERR_FMT "%s: Unable to write "
28246 +                   "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
28247 +                   __FUNCTION__, diagData);
28248 +               return -EFAULT;
28249 +       }
28250 +
28251 +       if ((karg.data.Flags & MPI_FW_DIAG_FLAG_REREGISTER) == 0)
28252 +               goto out;
28253 +
28254 +       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Reregister "
28255 +               "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type));
28256 +       if ((ioc->DiagBuffer_Status[buffer_type] &
28257 +           MPT_DIAG_BUFFER_IS_RELEASED) == 0) {
28258 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x "
28259 +                   "is still registered\n", ioc->name, __FUNCTION__,
28260 +                   buffer_type));
28261 +               return rc;
28262 +       }
28263 +       /* Get a free request frame and save the message context.
28264 +       */
28265 +       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
28266 +               return -EAGAIN;
28267 +
28268 +       diag_buffer_post_request = (DiagBufferPostRequest_t *)mf;
28269 +       diag_buffer_post_request->Function = MPI_FUNCTION_DIAG_BUFFER_POST;
28270 +       diag_buffer_post_request->ChainOffset = 0;
28271 +       diag_buffer_post_request->BufferType = buffer_type;
28272 +       diag_buffer_post_request->TraceLevel =
28273 +               ioc->TraceLevel[buffer_type];
28274 +       diag_buffer_post_request->MsgFlags = 0;
28275 +       diag_buffer_post_request->Reserved1 = 0;
28276 +       diag_buffer_post_request->Reserved2 = 0;
28277 +       diag_buffer_post_request->Reserved3 = 0;
28278 +       diag_buffer_post_request->BufferAddress.High = 0;
28279 +       if ( buffer_type == MPI_DIAG_BUF_TYPE_EXTENDED )
28280 +               diag_buffer_post_request->ExtendedType =
28281 +                       cpu_to_le32(ioc->ExtendedType[buffer_type]);
28282 +       diag_buffer_post_request->BufferLength =
28283 +           cpu_to_le32(ioc->DiagBuffer_sz[buffer_type]);
28284 +       for (ii = 0; ii < 4; ii++)
28285 +               diag_buffer_post_request->ProductSpecific[ii] =
28286 +                   cpu_to_le32(ioc->ProductSpecific[buffer_type][ii]);
28287 +       request_data_dma = ioc->DiagBuffer_dma[buffer_type];
28288 +       tmp = request_data_dma & 0xFFFFFFFF;
28289 +       diag_buffer_post_request->BufferAddress.Low = cpu_to_le32(tmp);
28290 +       if (ioc->sg_addr_size == sizeof(u64)) {
28291 +               tmp = (u32)((u64)request_data_dma >> 32);
28292 +               diag_buffer_post_request->BufferAddress.High = cpu_to_le32(tmp);
28293 +       }
28294 +
28295 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
28296 +           diag_buffer_post_request->MsgContext);
28297 +       INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
28298 +       mpt_put_msg_frame(mptctl_id, ioc, mf);
28299 +       timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
28300 +           MPT_IOCTL_DEFAULT_TIMEOUT*HZ);
28301 +       if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
28302 +               rc = -ETIME;
28303 +               printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name,
28304 +                   __FUNCTION__);
28305 +               if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
28306 +                       mpt_free_msg_frame(ioc, mf);
28307 +                       goto out;
28308 +               }
28309 +               if (!timeleft)
28310 +                       mptctl_timeout_expired(ioc, mf);
28311 +               goto out;
28312 +       }
28313 +
28314 +       /* process the completed Reply Message Frame */
28315 +       if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
28316 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: status=%x\n",
28317 +                   ioc->name, __FUNCTION__, ioc->ioctl_cmds.status));
28318 +               rc = -EFAULT;
28319 +       }
28320 +
28321 +       diag_buffer_post_reply = (DiagBufferPostReply_t *)ioc->ioctl_cmds.reply;
28322 +       if (le16_to_cpu(diag_buffer_post_reply->IOCStatus) ==
28323 +           MPI_IOCSTATUS_SUCCESS) {
28324 +               if (diag_buffer_post_reply->MsgLength > 5)
28325 +                       ioc->DataSize[buffer_type] =
28326 +                           le32_to_cpu(diag_buffer_post_reply->TransferLength);
28327 +               ioc->DiagBuffer_Status[buffer_type] |=
28328 +                   MPT_DIAG_BUFFER_IS_REGISTERED;
28329 +       } else {
28330 +               dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: IOCStatus=%x "
28331 +                   "IOCLogInfo=%x\n", ioc->name, __FUNCTION__,
28332 +                   diag_buffer_post_reply->IOCStatus,
28333 +                   diag_buffer_post_reply->IOCLogInfo));
28334 +               rc = -EFAULT;
28335 +       }
28336 +
28337 + out:
28338 +       CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
28339 +       SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
28340 +       return rc;
28341 +}
28342 --- /dev/null
28343 +++ b/drivers/message/fusion/rejected_ioctls/diag_buffer.h
28344 @@ -0,0 +1,101 @@
28345 +#define MPTDIAGREGISTER                                _IOWR(MPT_MAGIC_NUMBER,26,mpt_diag_register_t)
28346 +#define MPTDIAGRELEASE                         _IOWR(MPT_MAGIC_NUMBER,27,mpt_diag_release_t)
28347 +#define MPTDIAGUNREGISTER                      _IOWR(MPT_MAGIC_NUMBER,28,mpt_diag_unregister_t)
28348 +#define MPTDIAGQUERY                           _IOWR(MPT_MAGIC_NUMBER,29,mpt_diag_query_t)
28349 +#define MPTDIAGREADBUFFER                      _IOWR(MPT_MAGIC_NUMBER,30,mpt_diag_read_buffer_t)
28350 +
28351 +#define MPI_FW_DIAG_IOCTL                      (0x80646961)
28352 +#define MPI_FW_DIAG_TYPE_REGISTER              (0x00000001)
28353 +#define MPI_FW_DIAG_TYPE_UNREGISTER            (0x00000002)
28354 +#define MPI_FW_DIAG_TYPE_QUERY                 (0x00000003)
28355 +#define MPI_FW_DIAG_TYPE_READ_BUFFER           (0x00000004)
28356 +#define MPI_FW_DIAG_TYPE_RELEASE               (0x00000005)
28357 +
28358 +#define MPI_FW_DIAG_INVALID_UID                        (0x00000000)
28359 +#define FW_DIAGNOSTIC_BUFFER_COUNT             (3)
28360 +#define FW_DIAGNOSTIC_UID_NOT_FOUND            (0xFF)
28361 +
28362 +#define MPI_FW_DIAG_ERROR_SUCCESS              (0x00000000)
28363 +#define MPI_FW_DIAG_ERROR_FAILURE              (0x00000001)
28364 +#define MPI_FW_DIAG_ERROR_INVALID_PARAMETER    (0x00000002)
28365 +#define MPI_FW_DIAG_ERROR_POST_FAILED          (0x00000010)
28366 +#define MPI_FW_DIAG_ERROR_INVALID_UID          (0x00000011)
28367 +
28368 +#define MPI_FW_DIAG_ERROR_RELEASE_FAILED       (0x00000012)
28369 +#define MPI_FW_DIAG_ERROR_NO_BUFFER            (0x00000013)
28370 +#define MPI_FW_DIAG_ERROR_ALREADY_RELEASED     (0x00000014)
28371 +
28372 +#define MPT_DIAG_CAPABILITY(bufftype)  (MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER << bufftype)
28373 +
28374 +#define MPT_DIAG_BUFFER_IS_REGISTERED          1
28375 +#define MPT_DIAG_BUFFER_IS_RELEASED            2
28376 +
28377 +typedef struct _MPI_FW_DIAG_REGISTER {
28378 +       u8                      TraceLevel;
28379 +       u8                      BufferType;
28380 +       u16                     Flags;
28381 +       u32                     ExtendedType;
28382 +       u32                     ProductSpecific[4];
28383 +       u32                     RequestedBufferSize;
28384 +       u32                     UniqueId;
28385 +} MPI_FW_DIAG_REGISTER, *PTR_MPI_FW_DIAG_REGISTER;
28386 +
28387 +typedef struct _mpt_diag_register {
28388 +       mpt_ioctl_header        hdr;
28389 +       MPI_FW_DIAG_REGISTER    data;
28390 +} mpt_diag_register_t;
28391 +
28392 +typedef struct _MPI_FW_DIAG_UNREGISTER {
28393 +       u32                     UniqueId;
28394 +} MPI_FW_DIAG_UNREGISTER, *PTR_MPI_FW_DIAG_UNREGISTER;
28395 +
28396 +typedef struct _mpt_diag_unregister {
28397 +       mpt_ioctl_header         hdr;
28398 +       MPI_FW_DIAG_UNREGISTER  data;
28399 +} mpt_diag_unregister_t;
28400 +
28401 +#define MPI_FW_DIAG_FLAG_APP_OWNED          (0x0001)
28402 +#define MPI_FW_DIAG_FLAG_BUFFER_VALID       (0x0002)
28403 +#define MPI_FW_DIAG_FLAG_FW_BUFFER_ACCESS   (0x0004)
28404 +
28405 +typedef struct _MPI_FW_DIAG_QUERY {
28406 +       u8                      TraceLevel;
28407 +       u8                      BufferType;
28408 +       u16                     Flags;
28409 +       u32                     ExtendedType;
28410 +       u32                     ProductSpecific[4];
28411 +       u32                     DataSize;
28412 +       u32                     DriverAddedBufferSize;
28413 +       u32                     UniqueId;
28414 +} MPI_FW_DIAG_QUERY, *PTR_MPI_FW_DIAG_QUERY;
28415 +
28416 +typedef struct _mpt_diag_query {
28417 +       mpt_ioctl_header        hdr;
28418 +       MPI_FW_DIAG_QUERY       data;
28419 +} mpt_diag_query_t;
28420 +
28421 +typedef struct _MPI_FW_DIAG_RELEASE {
28422 +       u32                     UniqueId;
28423 +} MPI_FW_DIAG_RELEASE, *PTR_MPI_FW_DIAG_RELEASE;
28424 +
28425 +typedef struct _mpt_diag_release {
28426 +       mpt_ioctl_header        hdr;
28427 +       MPI_FW_DIAG_RELEASE     data;
28428 +} mpt_diag_release_t;
28429 +
28430 +#define MPI_FW_DIAG_FLAG_REREGISTER         (0x0001)
28431 +
28432 +typedef struct _MPI_FW_DIAG_READ_BUFFER {
28433 +       u8                      Status;
28434 +       u8                      Reserved;
28435 +       u16                     Flags;
28436 +       u32                     StartingOffset;
28437 +       u32                     BytesToRead;
28438 +       u32                     UniqueId;
28439 +       u32                     DiagnosticData[1];
28440 +} MPI_FW_DIAG_READ_BUFFER, *PTR_MPI_FW_DIAG_READ_BUFFER;
28441 +
28442 +typedef struct _mpt_diag_read_buffer {
28443 +       mpt_ioctl_header        hdr;
28444 +       MPI_FW_DIAG_READ_BUFFER data;
28445 +} mpt_diag_read_buffer_t;
This page took 2.195379 seconds and 3 git commands to generate.