]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.drivers/mpt-fusion-4.00.43.00-update
Disable build of xen kernel.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / mpt-fusion-4.00.43.00-update
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;