]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.drivers/mpt-fusion-4.00.43.00-update
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / mpt-fusion-4.00.43.00-update
CommitLineData
00e5a55c
BS
1Subject: Update MPT Fusion driver to v4.00.43.00
2From: Hannes Reinecke <hare@suse.de>
3Date: Tue Sep 30 13:38:53 2008 +0200:
4Git: a958ec0d1685af04282982f2e53b66c947fc7426
5
6References: bnc#425660
7
8This patch updates the MPT fusion drivers to v4.00.43.00.
9
10Signed-off-by: Sathya Prakash <Sathya.Prakash@lsi.com>
11Signed-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;