megaraid_mbox.c revision 1d6f359a2e06296418481239f8054a878f36e819
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			Linux MegaRAID device driver
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2003-2004  LSI Logic Corporation.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	   This program is free software; you can redistribute it and/or
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	   modify it under the terms of the GNU General Public License
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	   as published by the Free Software Foundation; either version
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	   2 of the License, or (at your option) any later version.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FILE		: megaraid_mbox.c
13c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann * Version	: v2.20.4.8 (Apr 11 2006)
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Authors:
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	Atul Mukker		<Atul.Mukker@lsil.com>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsil.com>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	Manoj Jose		<Manoj.Jose@lsil.com>
19ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann * 	Seokmann Ju		<Seokmann.Ju@lsil.com>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * List of supported controllers
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OEM	Product Name			VID	DID	SSVID	SSID
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ---	------------			---	---	----	----
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC3/QC			101E	1960	1028	0471
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC3/DC			101E	1960	1028	0493
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC3/SC			101E	1960	1028	0475
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC3/Di			1028	1960	1028	0123
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC4/SC			1000	1960	1028	0520
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC4/DC			1000	1960	1028	0518
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC4/QC			1000	0407	1028	0531
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC4/Di			1028	000F	1028	014A
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC 4e/Si			1028	0013	1028	016c
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC 4e/Di			1028	0013	1028	016d
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC 4e/Di			1028	0013	1028	016e
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC 4e/Di			1028	0013	1028	016f
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC 4e/Di			1028	0013	1028	0170
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC 4e/DC			1000	0408	1028	0002
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dell PERC 4e/SC			1000	0408	1028	0001
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SCSI 320-0		1000	1960	1000	A520
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SCSI 320-1		1000	1960	1000	0520
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SCSI 320-2		1000	1960	1000	0518
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SCSI 320-0X		1000	0407	1000	0530
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SCSI 320-2X		1000	0407	1000	0532
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SCSI 320-4X		1000	0407	1000	0531
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SCSI 320-1E		1000	0408	1000	0001
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SCSI 320-2E		1000	0408	1000	0002
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SATA 150-4		1000	1960	1000	4523
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SATA 150-6		1000	1960	1000	0523
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SATA 300-4X		1000	0409	1000	3004
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LSI MegaRAID SATA 300-8X		1000	0409	1000	3008
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INTEL RAID Controller SRCU42X	1000	0407	8086	0532
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INTEL RAID Controller SRCS16		1000	1960	8086	0523
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INTEL RAID Controller SRCU42E	1000	0408	8086	0002
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INTEL RAID Controller SRCZCRX	1000	0407	8086	0530
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INTEL RAID Controller SRCS28X	1000	0409	8086	3008
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INTEL RAID Controller SROMBU42E	1000	0408	8086	3431
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INTEL RAID Controller SROMBU42E	1000	0408	8086	3499
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INTEL RAID Controller SRCU51L	1000	1960	8086	0520
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FSC	MegaRAID PCI Express ROMB	1000	0408	1734	1065
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ACER	MegaRAID ROMB-2E		1000	0408	1025	004D
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NEC	MegaRAID PCI Express ROMB	1000	0408	1033	8287
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For history of changes, see Documentation/ChangeLog.megaraid
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "megaraid_mbox.h"
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_init(void);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_exit(void);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_detach_one(struct pci_dev *);
805457b6a6013516a73b8f48ec1adb9984b577a5c1Russell Kingstatic void megaraid_mbox_shutdown(struct pci_dev *);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_io_attach(adapter_t *);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_io_detach(adapter_t *);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_init_mbox(adapter_t *);
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_fini_mbox(adapter_t *);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_alloc_cmd_packets(adapter_t *);
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_free_cmd_packets(adapter_t *);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_setup_dma_pools(adapter_t *);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_teardown_dma_pools(adapter_t *);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_sysfs_alloc_resources(adapter_t *);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_sysfs_free_resources(adapter_t *);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_abort_handler(struct scsi_cmnd *);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_reset_handler(struct scsi_cmnd *);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mbox_post_sync_cmd(adapter_t *, uint8_t []);
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mbox_post_sync_cmd_fast(adapter_t *, uint8_t []);
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_busywait_mbox(mraid_device_t *);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_product_info(adapter_t *);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_extended_cdb(adapter_t *);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_support_ha(adapter_t *, uint16_t *);
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_support_random_del(adapter_t *);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_get_max_sg(adapter_t *);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_enum_raid_scsi(adapter_t *);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_flush_cache(adapter_t *);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_display_scb(adapter_t *, scb_t *);
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_setup_device_map(adapter_t *);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_queue_command(struct scsi_cmnd *,
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		void (*)(struct scsi_cmnd *));
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic scb_t *megaraid_mbox_build_cmd(adapter_t *, struct scsi_cmnd *, int *);
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_runpendq(adapter_t *, scb_t *);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_prepare_pthru(adapter_t *, scb_t *,
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct scsi_cmnd *);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *,
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct scsi_cmnd *);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t megaraid_isr(int, void *, struct pt_regs *);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_dpc(unsigned long);
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t megaraid_sysfs_show_app_hndl(struct class_device *, char *);
12810523b3b82456e416cbaffcc24ea2246980aa746Yani Ioannoustatic ssize_t megaraid_sysfs_show_ldnum(struct device *, struct device_attribute *attr, char *);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_cmm_register(adapter_t *);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_cmm_unregister(adapter_t *);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_mm_handler(unsigned long, uioc_t *, uint32_t);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_mm_command(adapter_t *, uioc_t *);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_mm_done(adapter_t *, scb_t *);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gather_hbainfo(adapter_t *, mraid_hba_info_t *);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int wait_till_fw_empty(adapter_t *);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
140ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, SeokmannMODULE_AUTHOR("sju@lsil.com");
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(MEGARAID_VERSION);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ### modules parameters for driver ###
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set to enable driver to expose unconfigured disk to kernel
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_expose_unconf_disks = 0;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0);
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(unconf_disks,
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Set to expose unconfigured disks to kernel (default=0)");
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driver wait time if the adapter's mailbox is busy
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(busy_wait, max_mbox_busy_wait, int, 0);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(busy_wait,
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Max wait for mailbox in microseconds if busy (default=10)");
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * number of sectors per IO command
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS;
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(max_sectors, megaraid_max_sectors, int, 0);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_sectors,
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maximum number of sectors per IO command (default=128)");
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * number of commands per logical unit
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(cmd_per_lun, megaraid_cmd_per_lun, int, 0);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(cmd_per_lun,
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maximum number of commands per logical unit (default=64)");
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fast driver load option, skip scanning for physical devices during load.
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This would result in non-disk devices being skipped during driver load
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * time. These can be later added though, using /proc/scsi/scsi
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int megaraid_fast_load = 0;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(fast_load, megaraid_fast_load, int, 0);
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(fast_load,
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Faster loading of the driver, skips physical devices! (default=0)");
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mraid_debug level - threshold for amount of information to be displayed by
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the driver. This level can be changed through modules parameters, ioctl or
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysfs/proc interface. By default, print the announcement messages only.
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mraid_debug_level = CL_ANN;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(debug_level, mraid_debug_level, int, 0);
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug_level, "Debug level for driver (default=0)");
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ### global data ###
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic uint8_t megaraid_mbox_version[8] =
206672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann	{ 0x02, 0x20, 0x04, 0x06, 3, 7, 20, 5 };
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PCI table for all supported controllers.
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id pci_id_table_g[] =  {
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4_DI_DISCOVERY,
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4_DI_DISCOVERY,
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4_SC,
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4_SC,
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4_DC,
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4_DC,
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
233672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_DEVICE_ID_VERDE,
234672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
235672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4_DI_EVERGLADES,
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4_DI_EVERGLADES,
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_SI_BIGBEND,
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_SI_BIGBEND,
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_DI_KOBUK,
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_DI_KOBUK,
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_DI_CORVETTE,
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_DI_CORVETTE,
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_DI_EXPEDITION,
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION,
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_DI_GUADALUPE,
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE,
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
275672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_DEVICE_ID_DOBSON,
276672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
277672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_AMI,
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_AMI_MEGARAID3,
282ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_ANY_ID,
283ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_ANY_ID,
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
287ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_DEVICE_ID_AMI_MEGARAID3,
288ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_ANY_ID,
289ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_ANY_ID,
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
293672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_DEVICE_ID_LINDSAY,
294672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
295672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0}	/* Terminating entry */
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, pci_id_table_g);
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver megaraid_pci_driver_g = {
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "megaraid",
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= pci_id_table_g,
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= megaraid_probe_one,
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= __devexit_p(megaraid_detach_one),
3075457b6a6013516a73b8f48ec1adb9984b577a5c1Russell King	.shutdown	= megaraid_mbox_shutdown,
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// definitions for the device attributes for exporting logical drive number
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// for a scsi address (Host, Channel, Id, Lun)
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsCLASS_DEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl,
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NULL);
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// Host template initializer for megaraid mbox sysfs device attributes
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct class_device_attribute *megaraid_shost_attrs[] = {
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&class_device_attr_megaraid_mbox_app_hndl,
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL,
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDEVICE_ATTR(megaraid_mbox_ld, S_IRUSR, megaraid_sysfs_show_ldnum, NULL);
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// Host template initializer for megaraid mbox sysfs device attributes
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct device_attribute *megaraid_sdev_attrs[] = {
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&dev_attr_megaraid_mbox_ld,
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL,
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Scsi host template for megaraid unified driver
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct scsi_host_template megaraid_template_g = {
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.module				= THIS_MODULE,
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name				= "LSI Logic MegaRAID driver",
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.proc_name			= "megaraid",
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.queuecommand			= megaraid_queue_command,
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_abort_handler		= megaraid_abort_handler,
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_device_reset_handler	= megaraid_reset_handler,
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_bus_reset_handler		= megaraid_reset_handler,
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_host_reset_handler		= megaraid_reset_handler,
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.use_clustering			= ENABLE_CLUSTERING,
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.sdev_attrs			= megaraid_sdev_attrs,
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.shost_attrs			= megaraid_shost_attrs,
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_init - module load hook
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We register ourselves as hotplug enabled module and let PCI subsystem
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * discover our adaters
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_init(void)
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	rval;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Announce the driver version
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_INFO "megaraid: %s %s\n", MEGARAID_VERSION,
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MEGARAID_EXT_VERSION));
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// check validity of module parameters
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_cmd_per_lun > MBOX_MAX_SCSI_CMDS) {
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mailbox: max commands per lun reset to %d\n",
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MBOX_MAX_SCSI_CMDS));
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_cmd_per_lun = MBOX_MAX_SCSI_CMDS;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// register as a PCI hot-plug driver module
379672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann	rval = pci_register_driver(&megaraid_pci_driver_g);
380672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann	if (rval < 0) {
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: could not register hotplug support.\n"));
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_exit - driver unload entry point
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We simply unwrap the megaraid_init routine here
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_exit(void)
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_DLEVEL1, (KERN_NOTICE "megaraid: unloading framework\n"));
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// unregister as PCI hotplug driver
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_unregister_driver(&megaraid_pci_driver_g);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_probe_one - PCI hotplug entry point
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param pdev	: handle to this controller's PCI configuration space
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param id	: pci device id of the class of controllers
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine should be called whenever a new adapter is detected by the
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PCI hotplug susbsytem.
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// detected a new controller
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_INFO
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: probe new device %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdev->vendor, pdev->device, pdev->subsystem_vendor,
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdev->subsystem_device));
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, ("bus %d:slot %d:func %d\n", pdev->bus->number,
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)));
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_enable_device(pdev)) {
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: pci_enable_device failed\n"));
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Enable bus-mastering on this controller
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_master(pdev);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate the per driver initialization structure
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter = kmalloc(sizeof(adapter_t), GFP_KERNEL);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter == NULL) {
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: out of memory, %s %d.\n", __FUNCTION__, __LINE__));
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_probe_one;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(adapter, 0, sizeof(adapter_t));
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// set up PCI related soft state and other pre-known parameters
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->unique_id	= pdev->bus->number << 8 | pdev->devfn;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->irq		= pdev->irq;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->pdev		= pdev;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_set(&adapter->being_detached, 0);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Setup the default DMA mask. This would be changed later on
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// depending on hardware capabilities
460672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann	if (pci_set_dma_mask(adapter->pdev, DMA_32BIT_MASK) != 0) {
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: pci_set_dma_mask failed:%d\n", __LINE__));
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_adapter;
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Initialize the synchronization lock for kernel and LLD
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&adapter->lock);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Initialize the command queues: the list of free SCBs and the list
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// of pending SCBs.
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&adapter->kscb_pool);
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(SCSI_FREE_LIST_LOCK(adapter));
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&adapter->pend_list);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(PENDING_LIST_LOCK(adapter));
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&adapter->completed_list);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(COMPLETED_LIST_LOCK(adapter));
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Start the mailbox based controller
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_init_mbox(adapter) != 0) {
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: maibox adapter did not initialize\n"));
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_adapter;
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Register with LSI Common Management Module
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_cmm_register(adapter) != 0) {
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: could not register with management module\n"));
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_fini_mbox;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// setup adapter handle in PCI soft state
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, adapter);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// attach with scsi mid-layer
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_io_attach(adapter) != 0) {
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING "megaraid: io attach failed\n"));
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_cmm_unreg;
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_cmm_unreg:
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, NULL);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_cmm_unregister(adapter);
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_fini_mbox:
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_fini_mbox(adapter);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_adapter:
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter);
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_probe_one:
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_disable_device(pdev);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_detach_one - release the framework resources and call LLD release
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param pdev	: handle for our PCI cofiguration space
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is called during driver unload. We free all the allocated
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * resources and call the corresponding LLD so that it can also release all
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * its resources.
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is also called from the PCI hotplug system
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_detach_one(struct pci_dev *pdev)
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t		*adapter;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Scsi_Host	*host;
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Start a rollback on this adapter
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter = pci_get_drvdata(pdev);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter) {
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_CRIT
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: Invalid detach on %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pdev->vendor, pdev->device, pdev->subsystem_vendor,
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pdev->subsystem_device));
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: detaching device %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pdev->vendor, pdev->device, pdev->subsystem_vendor,
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pdev->subsystem_device));
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host = adapter->host;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// do not allow any more requests from the management module for this
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// adapter.
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// FIXME: How do we account for the request which might still be
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// pending with us?
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_set(&adapter->being_detached, 1);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// detach from the IO sub-system
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_io_detach(adapter);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// reset the device state in the PCI structure. We check this
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// condition when we enter here. If the device state is NULL,
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// that would mean the device has already been removed
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, NULL);
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Unregister from common management module
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	//
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// FIXME: this must return success or failure for conditions if there
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// is a command pending with LLD or not.
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_cmm_unregister(adapter);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// finalize the mailbox based controller and release all resources
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_fini_mbox(adapter);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scsi_host_put(host);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_disable_device(pdev);
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param device	: generice driver model device
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Shutdown notification, perform flush cache
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6075457b6a6013516a73b8f48ec1adb9984b577a5c1Russell Kingmegaraid_mbox_shutdown(struct pci_dev *pdev)
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6095457b6a6013516a73b8f48ec1adb9984b577a5c1Russell King	adapter_t		*adapter = pci_get_drvdata(pdev);
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static int		counter;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter) {
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: null device in shutdown\n"));
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// flush caches now
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_INFO "megaraid: flushing adapter %d...",
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		counter++));
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_flush_cache(adapter);
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, ("done\n"));
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_io_attach - attach a device with the IO subsystem
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: controller's soft state
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Attach this device with the IO subsystem
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_io_attach(adapter_t *adapter)
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Scsi_Host	*host;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Initialize SCSI Host structure
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host = scsi_host_alloc(&megaraid_template_g, 8);
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!host) {
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: scsi_register failed\n"));
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SCSIHOST2ADAP(host)	= (caddr_t)adapter;
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->host		= host;
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->irq		= adapter->irq;
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->unique_id		= adapter->unique_id;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->can_queue		= adapter->max_cmds;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->this_id		= adapter->init_id;
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->sg_tablesize	= adapter->sglen;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->max_sectors	= adapter->max_sectors;
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->cmd_per_lun	= adapter->cmd_per_lun;
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->max_channel	= adapter->max_channel;
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->max_id		= adapter->max_target;
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->max_lun		= adapter->max_lun;
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// notify mid-layer about the new controller
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (scsi_add_host(host, &adapter->pdev->dev)) {
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: scsi_add_host failed\n"));
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scsi_host_put(host);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scsi_scan_host(host);
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_io_detach - detach a device from the IO subsystem
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: controller's soft state
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Detach this device from the IO subsystem
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_io_detach(adapter_t *adapter)
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Scsi_Host	*host;
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_DLEVEL1, (KERN_INFO "megaraid: io detach\n"));
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host = adapter->host;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scsi_remove_host(host);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * START: Mailbox Low Level Driver
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is section specific to the single mailbox based controllers
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_init_mbox - initialize controller
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	- our soft state
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * . Allocate 16-byte aligned mailbox memory for firmware handshake
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * . Allocate controller's memory resources
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * . Find out all initialization data
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * . Allocate memory required for all the commands
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * . Use internal library of FW routines, build up complete soft state
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
717cedfb178ada245b6c52a654936b34d7996e26a1dRandy Dunlapstatic int __devinit
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_init_mbox(adapter_t *adapter)
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev		*pdev;
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev;
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->ito	= MBOX_TIMEOUT;
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pdev		= adapter->pdev;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate and initialize the init data structure for mailbox
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * controllers
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev = kmalloc(sizeof(mraid_device_t), GFP_KERNEL);
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev == NULL) return -1;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(raid_dev, 0, sizeof(mraid_device_t));
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Attach the adapter soft state to raid device soft state
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->raid_device	= (caddr_t)raid_dev;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->fast_load	= megaraid_fast_load;
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// our baseport
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->baseport = pci_resource_start(pdev, 0);
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_request_regions(pdev, "MegaRAID: LSI Logic Corporation") != 0) {
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: mem region busy\n"));
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_raid_dev;
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!raid_dev->baseaddr) {
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: could not map hba memory\n") );
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_release_regions;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	//
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Setup the rest of the soft state using the library of FW routines
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	//
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// request IRQ and register the interrupt service routine
7701d6f359a2e06296418481239f8054a878f36e819Thomas Gleixner	if (request_irq(adapter->irq, megaraid_isr, IRQF_SHARED, "megaraid",
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter)) {
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: Couldn't register IRQ %d!\n", adapter->irq));
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_iounmap;
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// initialize the mutual exclusion lock for the mailbox
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&raid_dev->mailbox_lock);
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// allocate memory required for commands
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_alloc_cmd_packets(adapter) != 0) {
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_irq;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Product info
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_mbox_product_info(adapter) != 0) {
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_alloc_cmds;
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Do we support extended CDBs
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_cdb_sz = 10;
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_mbox_extended_cdb(adapter) == 0) {
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->max_cdb_sz = 16;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Do we support cluster environment, if we do, what is the initiator
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * id.
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * NOTE: In a non-cluster aware firmware environment, the LLD should
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * return 7 as initiator id.
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->ha		= 0;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->init_id	= -1;
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_mbox_support_ha(adapter, &adapter->init_id) == 0) {
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->ha = 1;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Prepare the device ids array to have the mapping between the kernel
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * device address and megaraid device address.
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We export the physical devices on their actual addresses. The
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * logical drives are exported on a virtual SCSI channel
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_setup_device_map(adapter);
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// If the firmware supports random deletion, update the device id map
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_mbox_support_random_del(adapter)) {
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Change the logical drives numbers in device_ids array one
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// slot in device_ids is reserved for target id, that's why
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// "<=" below
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= MAX_LOGICAL_DRIVES_40LD; i++) {
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adapter->device_ids[adapter->max_channel][i] += 0x80;
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->device_ids[adapter->max_channel][adapter->init_id] =
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			0xFF;
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		raid_dev->random_del_supported = 1;
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * find out the maximum number of scatter-gather elements supported by
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * this firmware
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->sglen = megaraid_mbox_get_max_sg(adapter);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// enumerate RAID and SCSI channels so that all devices on SCSI
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// channels can later be exported, including disk devices
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_enum_raid_scsi(adapter);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Other parameters required by upper layer
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * maximum number of sectors per IO command
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_sectors = megaraid_max_sectors;
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * number of queued commands per LUN.
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->cmd_per_lun = megaraid_cmd_per_lun;
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate resources required to issue FW calls, when sysfs is
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * accessed
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_sysfs_alloc_resources(adapter) != 0) {
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_alloc_cmds;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Set the DMA mask to 64-bit. All supported controllers as capable of
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// DMA in this range
866672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann	if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK) != 0) {
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: could not set DMA mask for 64-bit.\n"));
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_sysfs_res;
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// setup tasklet for DPC
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc,
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(unsigned long)adapter);
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_DLEVEL1, (KERN_INFO
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid mbox hba successfully initialized\n"));
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_sysfs_res:
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_sysfs_free_resources(adapter);
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_alloc_cmds:
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_free_cmd_packets(adapter);
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_irq:
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(adapter->irq, adapter);
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_iounmap:
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(raid_dev->baseaddr);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_release_regions:
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_release_regions(pdev);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_raid_dev:
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(raid_dev);
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_fini_mbox - undo controller initialization
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: our soft state
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_fini_mbox(adapter_t *adapter)
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// flush all caches
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_flush_cache(adapter);
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_kill(&adapter->dpc_h);
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_sysfs_free_resources(adapter);
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_free_cmd_packets(adapter);
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(adapter->irq, adapter);
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(raid_dev->baseaddr);
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_release_regions(adapter->pdev);
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(raid_dev);
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_alloc_cmd_packets - allocate shared mailbox
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: soft state of the raid controller
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate and align the shared mailbox. This maibox is used to issue
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * all the commands. For IO based controllers, the mailbox is also regsitered
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with the FW. Allocate memory for all commands as well.
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is our big allocator
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_alloc_cmd_packets(adapter_t *adapter)
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev		*pdev;
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		align;
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*epthru_pci_blk;
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*sg_pci_blk;
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*mbox_pci_blk;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pdev = adapter->pdev;
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Setup the mailbox
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate the common 16-byte aligned memory for the handshake
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * mailbox.
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->una_mbox64 = pci_alloc_consistent(adapter->pdev,
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sizeof(mbox64_t), &raid_dev->una_mbox64_dma);
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!raid_dev->una_mbox64) {
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: out of memory, %s %d\n", __FUNCTION__,
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(raid_dev->una_mbox64, 0, sizeof(mbox64_t));
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Align the mailbox at 16-byte boundary
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox	= &raid_dev->una_mbox64->mbox32;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox	= (mbox_t *)((((unsigned long)raid_dev->mbox) + 15) &
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(~0UL ^ 0xFUL));
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox64 = (mbox64_t *)(((unsigned long)raid_dev->mbox) - 8);
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	align = ((void *)raid_dev->mbox -
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((void *)&raid_dev->una_mbox64->mbox32));
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox_dma = (unsigned long)raid_dev->una_mbox64_dma + 8 +
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			align;
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for commands issued internally
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->ibuf = pci_alloc_consistent(pdev, MBOX_IBUF_SIZE,
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				&adapter->ibuf_dma_h);
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter->ibuf) {
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: out of memory, %s %d\n", __FUNCTION__,
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_common_mbox;
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(adapter->ibuf, 0, MBOX_IBUF_SIZE);
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for our SCSI Command Blocks and their associated
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// memory
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate memory for the base list of scb. Later allocate memory for
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * CCBs and embedded components of each CCB and point the pointers in
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * scb to the allocated components
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * NOTE: The code to allocate SCB will be duplicated in all the LLD
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * since the calling routine does not yet know the number of available
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * commands.
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->kscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_SCSI_CMDS,
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GFP_KERNEL);
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->kscb_list == NULL) {
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: out of memory, %s %d\n", __FUNCTION__,
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_ibuf;
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(adapter->kscb_list, 0, sizeof(scb_t) * MBOX_MAX_SCSI_CMDS);
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// memory allocation for our command packets
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_mbox_setup_dma_pools(adapter) != 0) {
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: out of memory, %s %d\n", __FUNCTION__,
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_scb_list;
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Adjust the scb pointers and link in the free pool
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru_pci_blk	= raid_dev->epthru_pool;
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sg_pci_blk	= raid_dev->sg_pool;
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_pci_blk	= raid_dev->mbox_pool;
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb			= adapter->kscb_list + i;
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb			= raid_dev->ccb_list + i;
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox	= (mbox_t *)(mbox_pci_blk[i].vaddr + 16);
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->raw_mbox	= (uint8_t *)ccb->mbox;
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox64	= (mbox64_t *)(mbox_pci_blk[i].vaddr + 8);
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox_dma_h	= (unsigned long)mbox_pci_blk[i].dma_addr + 16;
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// make sure the mailbox is aligned properly
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ccb->mbox_dma_h & 0x0F) {
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_CRIT
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mbox: not aligned on 16-bytes\n"));
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out_teardown_dma_pools;
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->epthru		= (mraid_epassthru_t *)
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						epthru_pci_blk[i].vaddr;
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->epthru_dma_h	= epthru_pci_blk[i].dma_addr;
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->pthru		= (mraid_passthru_t *)ccb->epthru;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->pthru_dma_h	= ccb->epthru_dma_h;
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl64		= (mbox_sgl64 *)sg_pci_blk[i].vaddr;
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl_dma_h		= sg_pci_blk[i].dma_addr;
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl32		= (mbox_sgl32 *)ccb->sgl64;
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->ccb		= (caddr_t)ccb;
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->gp			= 0;
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->sno		= i;	// command index
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->scp		= NULL;
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->state		= SCB_FREE;
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_direction	= PCI_DMA_NONE;
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_type		= MRAID_DMA_NONE;
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_channel	= -1;
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_target		= -1;
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// put scb in the free pool
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_add_tail(&scb->list, &adapter->kscb_pool);
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_teardown_dma_pools:
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_teardown_dma_pools(adapter);
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_scb_list:
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter->kscb_list);
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_ibuf:
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(pdev, MBOX_IBUF_SIZE, (void *)adapter->ibuf,
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->ibuf_dma_h);
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_common_mbox:
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(adapter->pdev, sizeof(mbox64_t),
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma);
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_free_cmd_packets - free memory
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: soft state of the raid controller
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Release memory resources allocated for commands
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_free_cmd_packets(adapter_t *adapter)
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_teardown_dma_pools(adapter);
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter->kscb_list);
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(adapter->pdev, MBOX_IBUF_SIZE,
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(void *)adapter->ibuf, adapter->ibuf_dma_h);
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(adapter->pdev, sizeof(mbox64_t),
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma);
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_setup_dma_pools - setup dma pool for command packets
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: HBA soft state
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * setup the dma pools for mailbox, passthru and extended passthru structures,
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and scatter-gather lists
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_setup_dma_pools(adapter_t *adapter)
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*epthru_pci_blk;
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*sg_pci_blk;
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*mbox_pci_blk;
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for 16-bytes aligned mailboxes
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox_pool_handle = pci_pool_create("megaraid mbox pool",
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						adapter->pdev,
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						sizeof(mbox64_t) + 16,
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						16, 0);
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->mbox_pool_handle == NULL) {
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail_setup_dma_pool;
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_pci_blk = raid_dev->mbox_pool;
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox_pci_blk[i].vaddr = pci_pool_alloc(
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						raid_dev->mbox_pool_handle,
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						GFP_KERNEL,
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&mbox_pci_blk[i].dma_addr);
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!mbox_pci_blk[i].vaddr) {
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fail_setup_dma_pool;
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate memory for each embedded passthru strucuture pointer
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Request for a 128 bytes aligned structure for each passthru command
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * structure
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Since passthru and extended passthru commands are exclusive, they
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * share common memory pool. Passthru structures piggyback on memory
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * allocted to extended passthru since passthru is smaller of the two
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->epthru_pool_handle = pci_pool_create("megaraid mbox pthru",
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adapter->pdev, sizeof(mraid_epassthru_t), 128, 0);
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->epthru_pool_handle == NULL) {
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail_setup_dma_pool;
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru_pci_blk = raid_dev->epthru_pool;
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru_pci_blk[i].vaddr = pci_pool_alloc(
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						raid_dev->epthru_pool_handle,
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						GFP_KERNEL,
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&epthru_pci_blk[i].dma_addr);
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!epthru_pci_blk[i].vaddr) {
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fail_setup_dma_pool;
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for each scatter-gather list. Request for 512 bytes
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// alignment for each sg list
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->sg_pool_handle = pci_pool_create("megaraid mbox sg",
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					adapter->pdev,
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					sizeof(mbox_sgl64) * MBOX_MAX_SG_SIZE,
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					512, 0);
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->sg_pool_handle == NULL) {
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail_setup_dma_pool;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sg_pci_blk = raid_dev->sg_pool;
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sg_pci_blk[i].vaddr = pci_pool_alloc(
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						raid_dev->sg_pool_handle,
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						GFP_KERNEL,
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&sg_pci_blk[i].dma_addr);
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!sg_pci_blk[i].vaddr) {
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fail_setup_dma_pool;
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail_setup_dma_pool:
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_teardown_dma_pools(adapter);
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: HBA soft state
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * teardown the dma pool for mailbox, passthru and extended passthru
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * structures, and scatter-gather lists
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_teardown_dma_pools(adapter_t *adapter)
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*epthru_pci_blk;
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*sg_pci_blk;
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*mbox_pci_blk;
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sg_pci_blk = raid_dev->sg_pool;
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS && sg_pci_blk[i].vaddr; i++) {
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_free(raid_dev->sg_pool_handle, sg_pci_blk[i].vaddr,
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sg_pci_blk[i].dma_addr);
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->sg_pool_handle)
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_destroy(raid_dev->sg_pool_handle);
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru_pci_blk = raid_dev->epthru_pool;
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS && epthru_pci_blk[i].vaddr; i++) {
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_free(raid_dev->epthru_pool_handle,
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			epthru_pci_blk[i].vaddr, epthru_pci_blk[i].dma_addr);
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->epthru_pool_handle)
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_destroy(raid_dev->epthru_pool_handle);
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_pci_blk = raid_dev->mbox_pool;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS && mbox_pci_blk[i].vaddr; i++) {
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_free(raid_dev->mbox_pool_handle,
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox_pci_blk[i].vaddr, mbox_pci_blk[i].dma_addr);
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->mbox_pool_handle)
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_destroy(raid_dev->mbox_pool_handle);
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_alloc_scb - detach and return a scb from the free list
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: controller's soft state
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return the scb from the head of the free list. NULL if there are none
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * available
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
1269858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic scb_t *
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head	*head = &adapter->kscb_pool;
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb = NULL;
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// detach scb from free pool
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags);
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (list_empty(head)) {
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb = list_entry(head->next, scb_t, list);
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_del_init(&scb->list);
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->state	= SCB_ACTIVE;
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->scp	= scp;
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->dma_type	= MRAID_DMA_NONE;
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return scb;
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_dealloc_scb - return the scb to the free pool
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: controller's soft state
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		: scb to be freed
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return the scb back to the free list of scbs. The caller must 'flush' the
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc.
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE NOTE: Make sure the scb is not on any list before calling this
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine.
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// put scb in the free pool
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->state	= SCB_FREE;
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->scp	= NULL;
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags);
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_add(&scb->list, &adapter->kscb_pool);
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_mksgl - make the scatter-gather list
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- controller's soft state
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		- scsi control block
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * prepare the scatter-gather list
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1332858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scatterlist	*sgl;
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page		*page;
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		offset;
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scsi_cmnd	*scp;
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			sgcnt;
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scp	= scb->scp;
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// no mapping required if no data to be transferred
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!scp->request_buffer || !scp->request_bufflen)
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!scp->use_sg) {	/* scatter-gather list not used */
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		page = virt_to_page(scp->request_buffer);
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		offset = ((unsigned long)scp->request_buffer & ~PAGE_MASK);
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->buf_dma_h = pci_map_page(adapter->pdev, page, offset,
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  scp->request_bufflen,
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  scb->dma_direction);
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_type = MRAID_DMA_WBUF;
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * We need to handle special 64-bit commands that need a
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * minimum of 1 SG
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sgcnt = 1;
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl64[0].address	= ccb->buf_dma_h;
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl64[0].length	= scp->request_bufflen;
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return sgcnt;
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sgl = (struct scatterlist *)scp->request_buffer;
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// The number of sg elements returned must not exceed our limit
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sgcnt = pci_map_sg(adapter->pdev, sgl, scp->use_sg,
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dma_direction);
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sgcnt > adapter->sglen) {
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_CRIT
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid critical: too many sg elements:%d\n",
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sgcnt));
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG();
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->dma_type = MRAID_DMA_WSG;
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < sgcnt; i++, sgl++) {
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl64[i].address	= sg_dma_address(sgl);
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl64[i].length	= sg_dma_len(sgl);
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Return count of SG nodes
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sgcnt;
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mbox_post_cmd - issue a mailbox command
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- controller's soft state
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		- command to be issued
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * post the command to the controller if mailbox is availble.
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1405858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmbox_post_cmd(adapter_t *adapter, scb_t *scb)
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t	*mbox64;
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t	*ccb;
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	flags;
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int	i = 0;
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= raid_dev->mbox;
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64	= raid_dev->mbox64;
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Check for busy mailbox. If it is, return failure - the caller
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * should retry later.
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags);
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(mbox->busy)) {
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(1);
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i++;
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while(mbox->busy && (i < max_mbox_busy_wait));
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mbox->busy) {
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -1;
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Copy this command's mailbox data into "adapter's" mailbox
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy((caddr_t)mbox64, (caddr_t)ccb->mbox64, 22);
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->cmdid = scb->sno;
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->outstanding_cmds++;
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (scb->dma_direction == PCI_DMA_TODEVICE) {
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!scb->scp->use_sg) {	// sg list not used
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_dma_sync_single_for_device(adapter->pdev,
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ccb->buf_dma_h,
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scb->scp->request_bufflen,
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					PCI_DMA_TODEVICE);
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_dma_sync_sg_for_device(adapter->pdev,
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb->scp->request_buffer,
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb->scp->use_sg, PCI_DMA_TODEVICE);
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->busy	= 1;	// Set busy
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->poll	= 0;
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->ack	= 0;
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_queue_command - generic queue entry point for all LLDs
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scp		: pointer to the scsi command to be executed
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @done	: callback routine to be called after the cmd has be completed
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Queue entry point for mailbox based controllers.
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *))
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter;
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t		*scb;
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		if_busy;
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter		= SCP2ADAPTER(scp);
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scp->scsi_done	= done;
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scp->result	= 0;
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate and build a SCB request
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * if_busy flag will be set if megaraid_mbox_build_cmd() command could
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * not allocate scb. We will return non-zero status in that case.
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * NOTE: scb can be null even though certain commands completed
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, it would
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * return 0 in that case, and we would do the callback right away.
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if_busy	= 0;
1502f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	scb = megaraid_mbox_build_cmd(adapter, scp, &if_busy);
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!scb) {	// command already completed
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		done(scp);
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1508f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	megaraid_mbox_runpendq(adapter, scb);
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return if_busy;
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * firmware lingua
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- controller's soft state
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scp		- mid-layer scsi command pointer
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @busy	- set if request could not be completed because of lack of
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		resources
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * convert the command issued by mid-layer to format understood by megaraid
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * firmware. We also complete certain command without sending them to firmware
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic scb_t *
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*rdev = ADAP2RAIDDEV(adapter);
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			channel;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			target;
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			islogical;
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_passthru_t	*pthru;
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t		*mbox64;
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char			skip[] = "skipping";
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char			scan[] = "scanning";
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char			*ss;
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Get the appropriate device map for the device this command is
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * intended for
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MRAID_GET_DEVICE_MAP(adapter, scp, channel, target, islogical);
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Logical drive commands
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (islogical) {
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (scp->cmnd[0]) {
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case TEST_UNIT_READY:
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Do we support clustering and is the support enabled
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * If no, return success always
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!adapter->ha) {
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_OK << 16);
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*busy = 1;
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dma_direction	= scp->sc_data_direction;
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_channel	= 0xFF;
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_target		= target;
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb			= (mbox_ccb_t *)scb->ccb;
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * The command id will be provided by the command
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * issuance routine
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[0]	= CLUSTER_CMD;
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[2]	= RESERVATION_STATUS;
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[3]	= target;
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return scb;
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MODE_SENSE:
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (scp->use_sg) {
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				struct scatterlist	*sgl;
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				caddr_t			vaddr;
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sgl = (struct scatterlist *)scp->request_buffer;
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (sgl->page) {
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					vaddr = (caddr_t)
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						(page_address((&sgl[0])->page)
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						+ (&sgl[0])->offset);
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					memset(vaddr, 0, scp->cmnd[4]);
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else {
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					con_log(CL_ANN, (KERN_WARNING
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"megaraid mailbox: invalid sg:%d\n",
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					__LINE__));
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memset(scp->request_buffer, 0, scp->cmnd[4]);
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_OK << 16);
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case INQUIRY:
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Display the channel scan for logical drives
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Do not display scan for a channel if already done.
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_INFO
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"scsi[%d]: scanning scsi channel %d",
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					adapter->host->host_no,
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					SCP2CHANNEL(scp)));
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					" [virtual] for logical drives\n"));
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rdev->last_disp |= (1L << SCP2CHANNEL(scp));
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Fall through */
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case READ_CAPACITY:
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Do not allow LUN > 0 for logical drives and
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * requests for more than 40 logical drives
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (SCP2LUN(scp)) {
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_BAD_TARGET << 16);
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((target % 0x80) >= MAX_LOGICAL_DRIVES_40LD) {
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_BAD_TARGET << 16);
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Allocate a SCB and initialize passthru */
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*busy = 1;
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb			= (mbox_ccb_t *)scb->ccb;
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_channel	= 0xFF;
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_target		= target;
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru			= ccb->pthru;
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox			= ccb->mbox;
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64			= ccb->mbox64;
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->timeout		= 0;
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->ars		= 1;
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->reqsenselen	= 14;
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->islogical	= 1;
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->logdrv		= target;
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->cdblen		= scp->cmd_len;
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->cmd		= MBOXCMD_PASSTHRU64;
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dma_direction	= scp->sc_data_direction;
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->dataxferlen	= scp->request_bufflen;
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->dataxferaddr	= ccb->sgl_dma_h;
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->numsge		= megaraid_mbox_mksgl(adapter,
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							scb);
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->xferaddr		= 0xFFFFFFFF;
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_lo	= (uint32_t )ccb->pthru_dma_h;
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_hi	= 0;
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return scb;
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case READ_6:
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case WRITE_6:
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case READ_10:
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case WRITE_10:
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case READ_12:
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case WRITE_12:
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Allocate a SCB and initialize mailbox
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*busy = 1;
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb			= (mbox_ccb_t *)scb->ccb;
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_channel	= 0xFF;
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_target		= target;
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox			= ccb->mbox;
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64			= ccb->mbox64;
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->logdrv		= target;
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * A little HACK: 2nd bit is zero for all scsi read
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * commands and is set for all scsi write commands
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->cmd = (scp->cmnd[0] & 0x02) ?  MBOXCMD_LWRITE64:
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					MBOXCMD_LREAD64 ;
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * 6-byte READ(0x08) or WRITE(0x0A) cdb
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (scp->cmd_len == 6) {
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->numsectors = (uint32_t)scp->cmnd[4];
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->lba =
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[1] << 16)	|
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[2] << 8)	|
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[3];
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->lba &= 0x1FFFFF;
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * 10-byte READ(0x28) or WRITE(0x2A) cdb
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (scp->cmd_len == 10) {
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->numsectors =
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[8] |
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[7] << 8);
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->lba =
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[2] << 24) |
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[3] << 16) |
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[4] << 8) |
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[5];
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (scp->cmd_len == 12) {
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->lba =
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[2] << 24) |
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[3] << 16) |
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[4] << 8) |
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[5];
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->numsectors =
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[6] << 24) |
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[7] << 16) |
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[8] << 8) |
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[9];
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_WARNING
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"megaraid: unsupported CDB length\n"));
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				megaraid_dealloc_scb(adapter, scb);
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dma_direction = scp->sc_data_direction;
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Calculate Scatter-Gather info
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_lo	= (uint32_t )ccb->sgl_dma_h;
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->numsge		= megaraid_mbox_mksgl(adapter,
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							scb);
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->xferaddr		= 0xFFFFFFFF;
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_hi	= 0;
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return scb;
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case RESERVE:
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case RELEASE:
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Do we support clustering and is the support enabled
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!adapter->ha) {
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_BAD_TARGET << 16);
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Allocate a SCB and initialize mailbox
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*busy = 1;
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb			= (mbox_ccb_t *)scb->ccb;
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_channel	= 0xFF;
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_target		= target;
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[0]	= CLUSTER_CMD;
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[2]	=  (scp->cmnd[0] == RESERVE) ?
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						RESERVE_LD : RELEASE_LD;
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[3]	= target;
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dma_direction	= scp->sc_data_direction;
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return scb;
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_BAD_TARGET << 16);
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else { // Passthru device commands
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Do not allow access to target id > 15 or LUN > 7
18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (target > 15 || SCP2LUN(scp) > 7) {
18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_BAD_TARGET << 16);
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// if fast load option was set and scan for last device is
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// over, reset the fast_load flag so that during a possible
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// next scan, devices can be made available
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rdev->fast_load && (target == 15) &&
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(SCP2CHANNEL(scp) == adapter->max_channel -1)) {
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_INFO
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid[%d]: physical device scan re-enabled\n",
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				adapter->host->host_no));
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rdev->fast_load = 0;
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Display the channel scan for physical devices
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ss = rdev->fast_load ? skip : scan;
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_INFO
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"scsi[%d]: %s scsi channel %d [Phy %d]",
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				adapter->host->host_no, ss, SCP2CHANNEL(scp),
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				channel));
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				" for non-raid devices\n"));
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rdev->last_disp |= (1L << SCP2CHANNEL(scp));
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// disable channel sweep if fast load option given
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rdev->fast_load) {
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_BAD_TARGET << 16);
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Allocate a SCB and initialize passthru
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(scb = megaraid_alloc_scb(adapter, scp))) {
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_ERROR << 16);
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*busy = 1;
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb			= (mbox_ccb_t *)scb->ccb;
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_channel	= channel;
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_target		= target;
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_direction	= scp->sc_data_direction;
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox			= ccb->mbox;
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox64			= ccb->mbox64;
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Does this firmware support extended CDBs
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (adapter->max_cdb_sz == 16) {
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->cmd		= MBOXCMD_EXTPTHRU;
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_prepare_epthru(adapter, scb, scp);
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_lo	= (uint32_t)ccb->epthru_dma_h;
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_hi	= 0;
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->xferaddr		= 0xFFFFFFFF;
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->cmd = MBOXCMD_PASSTHRU64;
18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_prepare_pthru(adapter, scb, scp);
18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_lo	= (uint32_t)ccb->pthru_dma_h;
18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_hi	= 0;
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->xferaddr		= 0xFFFFFFFF;
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return scb;
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// NOT REACHED
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_runpendq - execute commands queued in the pending queue
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: controller's soft state
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		: SCB to be queued in the pending list
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scan the pending list for commands which are not yet issued and try to
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * post to the controller. The SCB can be a null pointer, which would indicate
18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * no SCB to be queue, just try to execute the ones in the pending list.
18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: We do not actually traverse the pending list. The SCBs are plucked
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * out from the head of the pending list. If it is successfully issued, the
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * next SCB is at the head now.
19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q)
19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (scb_q) {
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb_q->state = SCB_PENDQ;
19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_add_tail(&scb_q->list, &adapter->pend_list);
19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// if the adapter in not in quiescent mode, post the commands to FW
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->quiescent) {
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!list_empty(&adapter->pend_list)) {
19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		assert_spin_locked(PENDING_LIST_LOCK(adapter));
19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb = list_entry(adapter->pend_list.next, scb_t, list);
19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// remove the scb from the pending list and try to
19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// issue. If we are unable to issue it, put back in
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// the pending list and return
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del_init(&scb->list);
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// if mailbox was busy, return SCB back to pending
19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// list. Make sure to add at the head, since that's
19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// where it would have been removed from
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->state = SCB_ISSUED;
19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mbox_post_cmd(adapter, scb) != 0) {
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->state = SCB_PENDQ;
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_add(&scb->list, &adapter->pend_list);
19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter),
19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flags);
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_prepare_pthru - prepare a command for physical devices
19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- pointer to controller's soft state
19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		- scsi control block
19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scp		- scsi command from the mid-layer
19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * prepare a command for the scsi physical devices
19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb,
19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct scsi_cmnd *scp)
19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_passthru_t	*pthru;
19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			channel;
19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			target;
19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru	= ccb->pthru;
19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	channel	= scb->dev_channel;
19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target	= scb->dev_target;
19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout
19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->timeout		= 4;
19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->ars		= 1;
19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->islogical	= 0;
19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->channel		= 0;
19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->target		= (channel << 4) | target;
19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->logdrv		= SCP2LUN(scp);
19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->reqsenselen	= 14;
19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->cdblen		= scp->cmd_len;
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (scp->request_bufflen) {
20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->dataxferlen	= scp->request_bufflen;
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->dataxferaddr	= ccb->sgl_dma_h;
20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->numsge		= megaraid_mbox_mksgl(adapter, scb);
20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->dataxferaddr	= 0;
20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->dataxferlen	= 0;
20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->numsge		= 0;
20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_prepare_epthru - prepare a command for physical devices
20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- pointer to controller's soft state
20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		- scsi control block
20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scp		- scsi command from the mid-layer
20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * prepare a command for the scsi physical devices. This rountine prepares
20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * commands for devices which can take extended CDBs (>10 bytes)
20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct scsi_cmnd *scp)
20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_epassthru_t	*epthru;
20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			channel;
20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			target;
20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru	= ccb->epthru;
20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	channel	= scb->dev_channel;
20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target	= scb->dev_target;
20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout
20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->timeout		= 4;
20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->ars		= 1;
20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->islogical	= 0;
20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->channel		= 0;
20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->target		= (channel << 4) | target;
20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->logdrv		= SCP2LUN(scp);
20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->reqsenselen	= 14;
20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->cdblen		= scp->cmd_len;
20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(epthru->cdb, scp->cmnd, scp->cmd_len);
20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (scp->request_bufflen) {
20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->dataxferlen	= scp->request_bufflen;
20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->dataxferaddr	= ccb->sgl_dma_h;
20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->numsge		= megaraid_mbox_mksgl(adapter, scb);
20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->dataxferaddr	= 0;
20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->dataxferlen	= 0;
20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->numsge		= 0;
20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs
20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- controller's soft state
20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Interrupt ackrowledgement sequence for memory mapped HBAs. Find out the
20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * completed command and put them on the completed list for later processing.
20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:	1 if the interrupt is valid, 0 otherwise
20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2073858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int
20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_ack_sequence(adapter_t *adapter)
20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			nstatus;
20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			completed[MBOX_MAX_FIRMWARE_STATUS];
20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head	clist;
20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			handled;
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint32_t		dword;
20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i, j;
20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= raid_dev->mbox;
20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// move the SCBs from the firmware completed array to our local list
20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&clist);
20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// loop till F/W has more commands for us to complete
20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	handled = 0;
20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags);
20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Check if a valid interrupt is pending. If found, force the
20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * interrupt line low.
21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dword = RDOUTDOOR(raid_dev);
21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dword != 0x10001234) break;
21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		handled = 1;
21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		WROUTDOOR(raid_dev, 0x10001234);
21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nstatus = 0;
21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// wait for valid numstatus to post
21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < 0xFFFFF; i++) {
21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (mbox->numstatus != 0xFF) {
21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				nstatus = mbox->numstatus;
21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->numstatus = 0xFF;
21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->outstanding_cmds -= nstatus;
21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < nstatus; i++) {
21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// wait for valid command index to post
21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (j = 0; j < 0xFFFFF; j++) {
21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (mbox->completed[i] != 0xFF) break;
21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rmb();
21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			completed[i]		= mbox->completed[i];
21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->completed[i]	= 0xFF;
21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (completed[i] == 0xFF) {
21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_CRIT
21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: command posting timed out\n"));
21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				BUG();
21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Get SCB associated with this command id
21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (completed[i] >= MBOX_MAX_SCSI_CMDS) {
21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// a cmm command
21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb = adapter->uscb_list + (completed[i] -
21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						MBOX_MAX_SCSI_CMDS);
21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// an os command
21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb = adapter->kscb_list + completed[i];
21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->status = mbox->status;
21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_add_tail(&scb->list, &clist);
21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Acknowledge interrupt
21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		WRINDOOR(raid_dev, 0x02);
21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while(1);
21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// put the completed commands in the completed list. DPC would
21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// complete these commands later
21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_splice(&clist, &adapter->completed_list);
21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// schedule the DPC if there is some work for it
21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (handled)
21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tasklet_schedule(&adapter->dpc_h);
21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return handled;
21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_isr - isr for memory based mailbox based controllers
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @irq		- irq
21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @devp	- pointer to our soft state
21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @regs	- unused
21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Interrupt service routine for memory-mapped mailbox controllers.
21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t
21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_isr(int irq, void *devp, struct pt_regs *regs)
21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = devp;
21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		handled;
21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	handled = megaraid_ack_sequence(adapter);
21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Loop through any pending requests */
21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter->quiescent) {
21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_mbox_runpendq(adapter, NULL);
21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_RETVAL(handled);
22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_sync_scb - sync kernel buffers
22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: controller's soft state
22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		: pointer to the resource packet
22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMA sync if required.
22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2211858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic void
22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb)
22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t	*ccb;
22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (scb->dma_type) {
22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MRAID_DMA_WBUF:
22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_dma_sync_single_for_cpu(adapter->pdev,
22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ccb->buf_dma_h,
22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scb->scp->request_bufflen,
22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					PCI_DMA_FROMDEVICE);
22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_unmap_page(adapter->pdev, ccb->buf_dma_h,
22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->scp->request_bufflen, scb->dma_direction);
22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MRAID_DMA_WSG:
22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_dma_sync_sg_for_cpu(adapter->pdev,
22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scb->scp->request_buffer,
22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scb->scp->use_sg, PCI_DMA_FROMDEVICE);
22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_unmap_sg(adapter->pdev, scb->scp->request_buffer,
22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->scp->use_sg, scb->dma_direction);
22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_dpc - the tasklet to complete the commands from completed list
22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @devp	: pointer to HBA soft state
22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pick up the commands from the completed list and send back to the owners.
22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a reentrant function and does not assume any locks are held while
22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it is being called.
22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_dpc(unsigned long devp)
22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t		*adapter = (adapter_t *)devp;
22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev;
22661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head	clist;
22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scatterlist	*sgl;
22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*tmp;
22701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scsi_cmnd	*scp;
22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_passthru_t	*pthru;
22721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_epassthru_t	*epthru;
22731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
22741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			islogical;
22751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			pdev_index;
22761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			pdev_state;
22771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
22791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			c;
22801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			status;
2281c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	uioc_t			*kioc;
22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter) return;
22851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev = ADAP2RAIDDEV(adapter);
22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// move the SCBs from the completed list to our local list
22891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&clist);
22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_splice_init(&adapter->completed_list, &clist);
22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry_safe(scb, tmp, &clist, list) {
22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status		= scb->status;
23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scp		= scb->scp;
23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb		= (mbox_ccb_t *)scb->ccb;
23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru		= ccb->pthru;
23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru		= ccb->epthru;
23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox		= ccb->mbox;
23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Make sure f/w has completed a valid command
23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->state != SCB_ISSUED) {
23091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_CRIT
23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid critical err: invalid command %d:%d:%p\n",
23111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb->sno, scb->state, scp));
23121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BUG();
23131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;	// Must never happen!
23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// check for the management command and complete it right away
23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->sno >= MBOX_MAX_SCSI_CMDS) {
23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->state	= SCB_FREE;
23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->status	= status;
23201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// remove from local clist
23221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_del_init(&scb->list);
23231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2324c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			kioc			= (uioc_t *)scb->gp;
2325c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			kioc->status		= 0;
2326c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann
23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_mm_done(adapter, scb);
23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Was an abort issued for this command earlier
23331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->state & SCB_ABORT) {
23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
23351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: aborted cmd %lx[%x] completed\n",
23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->serial_number, scb->sno));
23371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
23401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the inquiry came of a disk drive which is not part of
23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * any RAID array, expose it to the kernel. For this to be
23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * enabled, user must set the "megaraid_expose_unconf_disks"
23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * flag to 1 by specifying it on module parameter list.
23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * This would enable data migration off drives from other
23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * configurations.
23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		islogical = MRAID_IS_LOGICAL(adapter, scp);
23481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0
23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				&& IS_RAID_CH(raid_dev, scb->dev_channel)) {
23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (scp->use_sg) {
23521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sgl = (struct scatterlist *)
23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scp->request_buffer;
23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (sgl->page) {
23561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					c = *(unsigned char *)
23571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(page_address((&sgl[0])->page) +
23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						(&sgl[0])->offset);
23591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
23601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else {
23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					con_log(CL_ANN, (KERN_WARNING
23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"megaraid mailbox: invalid sg:%d\n",
23631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					__LINE__));
23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					c = 0;
23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
23661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
23671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
23681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				c = *(uint8_t *)scp->request_buffer;
23691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
23701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((c & 0x1F ) == TYPE_DISK) {
23721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pdev_index = (scb->dev_channel * 16) +
23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scb->dev_target;
23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pdev_state =
23751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					raid_dev->pdrv_state[pdev_index] & 0x0F;
23761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (pdev_state == PDRV_ONLINE		||
23781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pdev_state == PDRV_FAILED	||
23791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pdev_state == PDRV_RBLD		||
23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pdev_state == PDRV_HOTSPARE	||
23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					megaraid_expose_unconf_disks == 0) {
23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					status = 0xF0;
23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
23861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Convert MegaRAID status to Linux error code
23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (status) {
23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x00:
23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_OK << 16);
23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x02:
23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* set sense_buffer and result fields */
23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (mbox->cmd == MBOXCMD_PASSTHRU ||
24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->cmd == MBOXCMD_PASSTHRU64) {
24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(scp->sense_buffer, pthru->reqsensearea,
24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						14);
24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = DRIVER_SENSE << 24 |
24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					DID_OK << 16 | CHECK_CONDITION << 1;
24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (mbox->cmd == MBOXCMD_EXTPTHRU) {
24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					memcpy(scp->sense_buffer,
24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						epthru->reqsensearea, 14);
24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scp->result = DRIVER_SENSE << 24 |
24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						DID_OK << 16 |
24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						CHECK_CONDITION << 1;
24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scp->sense_buffer[0] = 0x70;
24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scp->sense_buffer[2] = ABORTED_COMMAND;
24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scp->result = CHECK_CONDITION << 1;
24211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
24221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
24231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x08:
24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = DID_BUS_BUSY << 16 | status;
24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
24291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
24311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * If TEST_UNIT_READY fails, we know RESERVATION_STATUS
24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * failed
24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (scp->cmnd[0] == TEST_UNIT_READY) {
24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = DID_ERROR << 16 |
24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					RESERVATION_CONFLICT << 1;
24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Error code returned is 1 if Reserve or Release
24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * failed or the input parameter is invalid
24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (status == 1 && (scp->cmnd[0] == RESERVE ||
24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 scp->cmnd[0] == RELEASE)) {
24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = DID_ERROR << 16 |
24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					RESERVATION_CONFLICT << 1;
24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = DID_BAD_TARGET << 16 | status;
24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// print a debug message for all failed commands
24571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status) {
24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_display_scb(adapter, scb);
24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Free our internal resources and call the mid-layer callback
24621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// routine
24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_mbox_sync_scb(adapter, scb);
24641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// remove from local clist
24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del_init(&scb->list);
24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// put back in free list
24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_dealloc_scb(adapter, scb);
24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// send the scsi packet back to kernel
24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scp->scsi_done(scp);
24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_abort_handler - abort the scsi command
24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scp		: command to be aborted
24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Abort a previous SCSI request. Only commands on the pending list can be
24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aborted. All the commands issued to the F/W must complete.
24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2487f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwigmegaraid_abort_handler(struct scsi_cmnd *scp)
24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t		*adapter;
24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev;
24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*tmp;
24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			found;
24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter		= SCP2ADAPTER(scp);
24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev	= ADAP2RAIDDEV(adapter);
25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_WARNING
25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n",
25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scp->serial_number, scp->cmnd[0], SCP2CHANNEL(scp),
25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		SCP2TARGET(scp), SCP2LUN(scp)));
25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// If FW has stopped responding, simply return failure
25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->hw_error) {
25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: hw error, not aborting\n"));
25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return FAILED;
25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// There might a race here, where the command was completed by the
25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// firmware and now it is on the completed list. Before we could
25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// complete the command to the kernel in dpc, the abort came.
25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Find out if this is the case to avoid the race.
25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb = NULL;
25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry_safe(scb, tmp, &adapter->completed_list, list) {
25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->scp == scp) {	// Found command
25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_del_init(&scb->list);	// from completed list
25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_WARNING
25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: %ld:%d[%d:%d], abort from completed list\n",
25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->serial_number, scb->sno,
25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb->dev_channel, scb->dev_target));
25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_ABORT << 16);
25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->scsi_done(scp);
25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_dealloc_scb(adapter, scb);
25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter),
25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flags);
25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SUCCESS;
25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Find out if this command is still on the pending list. If it is and
25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// was never issued, abort and return success. If the command is owned
25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// by the firmware, we must wait for it to complete by the FW.
25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->scp == scp) {	// Found command
25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_del_init(&scb->list);	// from pending list
25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ASSERT(!(scb->state & SCB_ISSUED));
25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_WARNING
25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid abort: %ld[%d:%d], driver owner\n",
25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->serial_number, scb->dev_channel,
25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb->dev_target));
25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_ABORT << 16);
25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->scsi_done(scp);
25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_dealloc_scb(adapter, scb);
25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter),
25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flags);
25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SUCCESS;
25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
25731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Check do we even own this command, in which case this would be
25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// owned by the firmware. The only way to locate the FW scb is to
25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// traverse through the list of all SCB, since driver does not
25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// maintain these SCBs on any list
25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	found = 0;
2580f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_lock_irq(&adapter->lock);
25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb = adapter->kscb_list + i;
25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->scp == scp) {
25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			found = 1;
25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb->state & SCB_ISSUED)) {
25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_WARNING
25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid abort: %ld%d[%d:%d], invalid state\n",
25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->serial_number, scb->sno, scb->dev_channel,
25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb->dev_target));
25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				BUG();
25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
25961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_WARNING
25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid abort: %ld:%d[%d:%d], fw owner\n",
25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->serial_number, scb->sno, scb->dev_channel,
25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb->dev_target));
26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2603f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_unlock_irq(&adapter->lock);
26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!found) {
26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid abort: scsi cmd:%ld, do now own\n",
26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->serial_number));
26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// FIXME: Should there be a callback for this command?
26111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return SUCCESS;
26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// We cannot actually abort a command owned by firmware, return
26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// failure and wait for reset. In host reset handler, we will find out
26161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// if the HBA is still live
26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return FAILED;
26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
26211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_reset_handler - device reset hadler for mailbox based driver
26221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scp		: reference command
26231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
26241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reset handler for the mailbox based controller. First try to find out if
26251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the FW is still live, in which case the outstanding commands counter mut go
26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * down to 0. If that happens, also issue the reservation reset command to
26271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * relinquish (possible) reservations on the logical drives connected to this
26281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * host
26291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2631f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwigmegaraid_reset_handler(struct scsi_cmnd *scp)
26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter;
26341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t		*scb;
26351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t		*tmp;
26361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev;
26371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	flags;
26381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
26391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
26401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		recovery_window;
26411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		recovering;
26421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
2643c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	uioc_t		*kioc;
26441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter		= SCP2ADAPTER(scp);
26461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev	= ADAP2RAIDDEV(adapter);
26471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// return failure if adapter is not responding
26491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->hw_error) {
26501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
26511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: hw error, cannot reset\n"));
26521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return FAILED;
26531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
26541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Under exceptional conditions, FW can take up to 3 minutes to
26571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// complete command processing. Wait for additional 2 minutes for the
26581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// pending commands counter to go down to 0. If it doesn't, let the
26591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// controller be marked offline
26601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Also, reset all the commands currently owned by the driver
26611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
26621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
26631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del_init(&scb->list);	// from pending list
26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2665c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		if (scb->sno >= MBOX_MAX_SCSI_CMDS) {
2666c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			con_log(CL_ANN, (KERN_WARNING
2667c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			"megaraid: IOCTL packet with %d[%d:%d] being reset\n",
2668c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			scb->sno, scb->dev_channel, scb->dev_target));
26691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2670c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			scb->status = -1;
26711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2672c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			kioc			= (uioc_t *)scb->gp;
2673c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			kioc->status		= -EFAULT;
2674c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann
2675c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			megaraid_mbox_mm_done(adapter, scb);
2676c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		} else {
2677c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			if (scb->scp == scp) {	// Found command
2678c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				con_log(CL_ANN, (KERN_WARNING
2679c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann					"megaraid: %ld:%d[%d:%d], reset from pending list\n",
2680c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann					scp->serial_number, scb->sno,
2681c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann					scb->dev_channel, scb->dev_target));
2682c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			} else {
2683c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				con_log(CL_ANN, (KERN_WARNING
2684c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				"megaraid: IO packet with %d[%d:%d] being reset\n",
2685c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				scb->sno, scb->dev_channel, scb->dev_target));
2686c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			}
2687c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann
2688c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			scb->scp->result = (DID_RESET << 16);
2689c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			scb->scp->scsi_done(scb->scp);
2690c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann
2691c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			megaraid_dealloc_scb(adapter, scb);
2692c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		}
26931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
26941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
26951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->outstanding_cmds) {
26971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
26981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: %d outstanding commands. Max wait %d sec\n",
2699c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			adapter->outstanding_cmds,
2700c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			(MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT)));
27011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
27041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	recovering = adapter->outstanding_cmds;
27061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2707c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	for (i = 0; i < recovery_window; i++) {
27081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_ack_sequence(adapter);
27101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// print a message once every 5 seconds only
27121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(i % 5)) {
27131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (
27141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: Wait for %d commands to complete:%d\n",
27151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				adapter->outstanding_cmds,
2716c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				(MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT) - i));
27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// bailout if no recovery happended in reset time
2720c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		if (adapter->outstanding_cmds == 0) {
27211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
27221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(1000);
27251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2727f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_lock(&adapter->lock);
27281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// If still outstanding commands, bail out
27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->outstanding_cmds) {
27311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
27321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: critical hardware error!\n"));
27331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		raid_dev->hw_error = 1;
27351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2736f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig		rval = FAILED;
2737f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig		goto out;
27381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
27401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
27411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid mbox: reset sequence completed sucessfully\n"));
27421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// If the controller supports clustering, reset reservations
2746f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	if (!adapter->ha) {
2747f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig		rval = SUCCESS;
2748f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig		goto out;
2749f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	}
27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// clear reservations if any
27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = CLUSTER_CMD;
27531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = RESET_RESERVATIONS;
27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval = SUCCESS;
27561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd_fast(adapter, raw_mbox) == 0) {
27571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN,
27581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(KERN_INFO "megaraid: reservation reset\n"));
27591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
27611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval = FAILED;
27621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
27631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: reservation reset failed\n"));
27641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2766f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig out:
2767f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_unlock_irq(&adapter->lock);
27681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
27691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
27721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * START: internal commands library
27731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
27741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This section of the driver has the common routine used by the driver and
27751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * also has all the FW routines
27761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
27771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
27791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mbox_post_sync_cmd() - blocking command to the mailbox based controllers
27801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- controller's soft state
27811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @raw_mbox	- the mailbox
27821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
27831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issue a scb in synchronous and non-interrupt mode for mailbox based
27841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controllers
27851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
27861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
27871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[])
27881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
27901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t	*mbox64;
27911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
27921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		status;
27931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
27941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64	= raid_dev->mbox64;
27971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= raid_dev->mbox;
27981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
28001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Wait until mailbox is free
28011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
28021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_busywait_mbox(raid_dev) != 0)
28031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto blocked_mailbox;
28041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
28061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Copy mailbox data into host structure
28071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
28081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16);
28091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->cmdid		= 0xFE;
28101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->busy		= 1;
28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->poll		= 0;
28121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->ack		= 0;
28131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->numstatus		= 0xFF;
28141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->status		= 0xFF;
28151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
28171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// wait for maximum 1 second for status to post. If the status is not
28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// available within 1 second, assume FW is initializing and wait
28211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// for an extended amount of time
28221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox->numstatus == 0xFF) {	// status not yet available
282353b3531bbbf70ac7551b32d1acc229d94de52658Alexey Dobriyan		udelay(25);
28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; mbox->numstatus == 0xFF && i < 1000; i++) {
28261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
28271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
28281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == 1000) {
28321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
28331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mailbox: wait for FW to boot      "));
28341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; (mbox->numstatus == 0xFF) &&
28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(i < MBOX_RESET_WAIT); i++) {
28371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rmb();
28381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, ("\b\b\b\b\b[%03d]",
28391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							MBOX_RESET_WAIT - i));
28401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				msleep(1000);
28411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
28421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (i == MBOX_RESET_WAIT) {
28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (
28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"\nmegaraid mailbox: status not available\n"));
28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -1;
28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, ("\b\b\b\b\b[ok] \n"));
28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// wait for maximum 1 second for poll semaphore
28551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox->poll != 0x77) {
28561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(25);
28571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; (mbox->poll != 0x77) && (i < 1000); i++) {
28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
28601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == 1000) {
28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_WARNING
28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mailbox: could not get poll semaphore\n"));
28661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -1;
28671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2);
28711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
28721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// wait for maximum 1 second for acknowledgement
28741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (RDINDOOR(raid_dev) & 0x2) {
28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(25);
28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; (RDINDOOR(raid_dev) & 0x2) && (i < 1000); i++) {
28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
28791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
28801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == 1000) {
28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_WARNING
28841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mailbox: could not acknowledge\n"));
28851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -1;
28861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->poll	= 0;
28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->ack	= 0x77;
28901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = mbox->status;
28921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// invalidate the completed command id array. After command
28941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// completion, firmware would write the valid id.
28951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->numstatus	= 0xFF;
28961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->status	= 0xFF;
28971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_FIRMWARE_STATUS; i++) {
28981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->completed[i] = 0xFF;
28991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return status;
29021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsblocked_mailbox:
29041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n") );
29061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
29071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
29111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers
29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- controller's soft state
29131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @raw_mbox	- the mailbox
29141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issue a scb in synchronous and non-interrupt mode for mailbox based
29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controllers. This is a faster version of the synchronous command and
29171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * therefore can be called in interrupt-context as well
29181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
29201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
29211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
29241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long		i;
29251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= raid_dev->mbox;
29281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// return immediately if the mailbox is busy
29301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox->busy) return -1;
29311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Copy mailbox data into host structure
29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 14);
29341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->cmdid		= 0xFE;
29351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->busy		= 1;
29361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->poll		= 0;
29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->ack		= 0;
29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->numstatus		= 0xFF;
29391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->status		= 0xFF;
29401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
29421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
29431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2944c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	for (i = 0; i < MBOX_SYNC_WAIT_CNT; i++) {
29451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mbox->numstatus != 0xFF) break;
2946ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		rmb();
2947c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		udelay(MBOX_SYNC_DELAY_200);
29481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2950c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	if (i == MBOX_SYNC_WAIT_CNT) {
29511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// We may need to re-calibrate the counter
29521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_CRIT
29531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: fast sync command timed out\n"));
29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2);
29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
29581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mbox->status;
29601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
29641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_busywait_mbox() - Wait until the controller's mailbox is available
29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @raid_dev	- RAID device (HBA) soft state
29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
29671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * wait until the controller's mailbox is available to accept more commands.
29681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * wait for at most 1 second
29691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
29701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
29711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_busywait_mbox(mraid_device_t *raid_dev)
29721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t	*mbox = raid_dev->mbox;
29741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	i = 0;
29751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox->busy) {
29771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(25);
29781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; mbox->busy && i < 1000; i++)
29791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
29801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (i < 1000) return 0;
29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else return -1;
29841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
29881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_product_info - some static information about the controller
29891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- our soft state
29901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * issue commands to the controller to grab some parameters required by our
29921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * caller.
29931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
29941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
29951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_product_info(adapter_t *adapter)
29961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
29981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
29991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			raw_mbox[sizeof(mbox_t)];
30001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_pinfo_t		*pinfo;
30011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dma_addr_t		pinfo_dma_h;
30021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_inquiry3_t	*mraid_inq3;
30031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
30041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
30071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
30081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Issue an ENQUIRY3 command to find out certain adapter parameters,
30111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * e.g., max channels, max commands etc.
30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pinfo = pci_alloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
30141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&pinfo_dma_h);
30151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pinfo == NULL) {
30171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
30181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: out of memory, %s %d\n", __FUNCTION__,
30191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
30201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
30221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(pinfo, 0, sizeof(mraid_pinfo_t));
30241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
30261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
30271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FC_NEW_CONFIG;
30291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = NC_SUBOP_ENQUIRY3;
30301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[3] = ENQ3_GET_SOLICITED_FULL;
30311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command
30331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
30341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING "megaraid: Inquiry3 failed\n"));
30361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
30381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pinfo, pinfo_dma_h);
30391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
30411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Collect information about state of each physical drive
30451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * attached to the controller. We will expose all the disks
30461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * which are not part of RAID
30471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_inq3 = (mraid_inquiry3_t *)adapter->ibuf;
30491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_PHYSICAL_DRIVES; i++) {
30501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		raid_dev->pdrv_state[i] = mraid_inq3->pdrv_state[i];
30511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Get product info for information like number of channels,
30551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * maximum commands supported.
30561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
30581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)pinfo_dma_h;
30591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FC_NEW_CONFIG;
30611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = NC_SUBOP_PRODUCT_INFO;
30621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
30641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
30661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: product info failed\n"));
30671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
30691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pinfo, pinfo_dma_h);
30701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
30721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Setup some parameters for host, as required by our caller
30761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_channel = pinfo->nchannels;
30781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * we will export all the logical drives on a single channel.
30811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Add 1 since inquires do not come for inititor ID
30821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_target	= MAX_LOGICAL_DRIVES_40LD + 1;
30841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_lun	= 8;	// up to 8 LUNs for non-disk devices
30851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * These are the maximum outstanding commands for the scsi-layer
30881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_cmds	= MBOX_MAX_SCSI_CMDS;
30901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(adapter->fw_version, 0, VERSION_SIZE);
30921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(adapter->bios_version, 0, VERSION_SIZE);
30931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(adapter->fw_version, pinfo->fw_version, 4);
30951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->fw_version[4] = 0;
30961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(adapter->bios_version, pinfo->bios_version, 4);
30981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->bios_version[4] = 0;
30991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_NOTICE
31011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: fw version:[%s] bios version:[%s]\n",
31021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->fw_version, adapter->bios_version));
31031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), pinfo,
31051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pinfo_dma_h);
31061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
31081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
31131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_extended_cdb - check for support for extended CDBs
31141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- soft state for the controller
31151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine check whether the controller in question supports extended
31171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ( > 10 bytes ) CDBs
31181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
31191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
31201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_extended_cdb(adapter_t *adapter)
31211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
31231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
31241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
31251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
31271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
31291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr	= (uint32_t)adapter->ibuf_dma_h;
31301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
31321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = MAIN_MISC_OPCODE;
31341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = SUPPORT_EXT_CDB;
31351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
31371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Issue the command
31381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
31391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval = 0;
31401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
31411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval = -1;
31421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
31431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
31451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
31491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_support_ha - Do we support clustering
31501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- soft state for the controller
31511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @init_id	- ID of the initiator
31521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine if the firmware supports clustering and the ID of the initiator.
31541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
31551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
31561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id)
31571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
31591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
31601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
31611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
31641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
31661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
31681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
31701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = GET_TARGET_ID;
31721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command
31741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*init_id = 7;
31751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval =  -1;
31761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
31771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*init_id = *(uint8_t *)adapter->ibuf;
31791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_INFO
31811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: cluster firmware, initiator ID: %d\n",
31821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*init_id));
31831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval =  0;
31851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
31861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
31881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
31921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_support_random_del - Do we support random deletion
31931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- soft state for the controller
31941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine if the firmware supports random deletion
31961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return:	1 is operation supported, 0 otherwise
31971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
31981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
31991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_support_random_del(adapter_t *adapter)
32001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
32021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
32031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
32041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
32071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
32091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FC_DEL_LOGDRV;
32111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = OP_SUP_DEL_LOGDRV;
32121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command
32141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval = 0;
32151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
32161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_DLEVEL1, ("megaraid: supports random deletion\n"));
32181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval =  1;
32201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
32231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
32271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware
32281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- soft state for the controller
32291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
32301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find out the maximum number of scatter-gather elements supported by the
32311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * firmware
32321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
32331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
32341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_get_max_sg(adapter_t *adapter)
32351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
32371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
32381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		nsg;
32391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
32421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
32441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
32461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
32481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = MAIN_MISC_OPCODE;
32501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = GET_MAX_SG_SUPPORT;
32511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command
32531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
32541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nsg =  *(uint8_t *)adapter->ibuf;
32551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
32571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nsg =  MBOX_DEFAULT_SG_SIZE;
32581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nsg > MBOX_MAX_SG_SIZE) nsg = MBOX_MAX_SG_SIZE;
32611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return nsg;
32631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
32671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels
32681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	- soft state for the controller
32691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
32701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Enumerate the RAID and SCSI channels for ROMB platoforms so that channels
32711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can be exported as regular SCSI channels
32721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
32731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
32741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_enum_raid_scsi(adapter_t *adapter)
32751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
32771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
32781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
32791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
32821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
32841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
32861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
32881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = CHNL_CLASS;
32901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = GET_CHNL_CLASS;
32911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command. If the command fails, all channels are RAID
32931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// channels
32941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->channel_class = 0xFF;
32951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
32961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		raid_dev->channel_class =  *(uint8_t *)adapter->ibuf;
32971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
33001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
33011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
33041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_flush_cache - flush adapter and disks cache
33051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: soft state for the controller
33061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
33071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Flush adapter cache followed by disks cache
33081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
33091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
33101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_flush_cache(adapter_t *adapter)
33111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
33121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t	*mbox;
33131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t	raw_mbox[sizeof(mbox_t)];
33141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
33171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
33191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FLUSH_ADAPTER;
33211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
33231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, ("megaraid: flush adapter failed\n"));
33241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
33251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FLUSH_SYSTEM;
33271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
33291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, ("megaraid: flush disks cache failed\n"));
33301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
33311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
33331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
33341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
33371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_display_scb - display SCB information, mostly debug purposes
33381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: controllers' soft state
33391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param scb		: SCB to be displayed
33401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param level	: debug level for console print
33411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
33421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Diplay information about the given SCB iff the current debug level is
33431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * verbose
33441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
33451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
33461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb)
33471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
33481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
33491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scsi_cmnd	*scp;
33501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
33511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			level;
33521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
33531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
33561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scp	= scb->scp;
33571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= ccb->mbox;
33581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	level = CL_DLEVEL3;
33601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(level, (KERN_NOTICE
33621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid mailbox: status:%#x cmd:%#x id:%#x ", scb->status,
33631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->cmd, scb->sno));
33641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(level, ("sec:%#x lba:%#x addr:%#x ld:%d sg:%d\n",
33661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->numsectors, mbox->lba, mbox->xferaddr, mbox->logdrv,
33671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->numsge));
33681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!scp) return;
33701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(level, (KERN_NOTICE "scsi cmnd: "));
33721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < scp->cmd_len; i++) {
33741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(level, ("%#2.02x ", scp->cmnd[i]));
33751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
33761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(level, ("\n"));
33781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
33801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
33811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
33841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_setup_device_map - manage device ids
33851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: Driver's soft state
33861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
33871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Manange the device ids to have an appropraite mapping between the kernel
33881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi addresses and megaraid scsi and logical drive addresses. We export
33891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi devices on their actual addresses, whereas the logical drives are
33901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * exported on a virtual scsi channel.
33911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
33921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
33931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_setup_device_map(adapter_t *adapter)
33941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
33951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		c;
33961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		t;
33971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
33991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * First fill the values on the logical drive channel
34001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
34011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++)
34021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->device_ids[adapter->max_channel][t] =
34031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(t < adapter->init_id) ?  t : t - 1;
34041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->device_ids[adapter->max_channel][adapter->init_id] = 0xFF;
34061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
34081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Fill the values on the physical devices channels
34091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
34101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (c = 0; c < adapter->max_channel; c++)
34111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++)
34121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adapter->device_ids[c][t] = (c << 8) | t;
34131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
34141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
34171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * END: internal commands library
34181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
34191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
34211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * START: Interface for the common management module
34221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
34231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is the module, which interfaces with the common mangement module to
34241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * provide support for ioctl and sysfs
34251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
34261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
34281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_cmm_register - register with the mangement module
34291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: HBA soft state
34301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
34311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Register with the management module, which allows applications to issue
34321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl calls to the drivers. This interface is used by the management module
34331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to setup sysfs support as well.
34341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
34351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
34361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_cmm_register(adapter_t *adapter)
34371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
34381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
34391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_mmadp_t	adp;
34401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t		*scb;
34411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t	*ccb;
34421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
34431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
34441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for the base list of scb for management module.
34461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->uscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_USER_CMDS,
34471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			GFP_KERNEL);
34481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->uscb_list == NULL) {
34501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
34511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: out of memory, %s %d\n", __FUNCTION__,
34521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
34531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
34541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
34551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(adapter->uscb_list, 0, sizeof(scb_t) * MBOX_MAX_USER_CMDS);
34561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Initialize the synchronization parameters for resources for
34591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// commands for management module
34601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&adapter->uscb_pool);
34611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(USER_FREE_LIST_LOCK(adapter));
34631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// link all the packets. Note, CCB for commands, coming from the
34671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// commom management module, mailbox physical address are already
34681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// setup by it. We just need placeholder for that in our local command
34691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// control blocks
34701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_USER_CMDS; i++) {
34711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb			= adapter->uscb_list + i;
34731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb			= raid_dev->uccb_list + i;
34741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->ccb		= (caddr_t)ccb;
34761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox64		= raid_dev->umbox64 + i;
34771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox		= &ccb->mbox64->mbox32;
34781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->raw_mbox		= (uint8_t *)ccb->mbox;
34791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->gp			= 0;
34811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// COMMAND ID 0 - (MBOX_MAX_SCSI_CMDS-1) ARE RESERVED FOR
34831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// COMMANDS COMING FROM IO SUBSYSTEM (MID-LAYER)
34841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->sno		= i + MBOX_MAX_SCSI_CMDS;
34851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->scp		= NULL;
34871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->state		= SCB_FREE;
34881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_direction	= PCI_DMA_NONE;
34891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_type		= MRAID_DMA_NONE;
34901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_channel	= -1;
34911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_target		= -1;
34921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// put scb in the free pool
34941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_add_tail(&scb->list, &adapter->uscb_pool);
34951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
34961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.unique_id		= adapter->unique_id;
34981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.drvr_type		= DRVRTYPE_MBOX;
34991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.drvr_data		= (unsigned long)adapter;
35001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.pdev		= adapter->pdev;
35011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.issue_uioc		= megaraid_mbox_mm_handler;
3502c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	adp.timeout		= MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
35031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.max_kioc		= MBOX_MAX_USER_CMDS;
35041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((rval = mraid_mm_register_adp(&adp)) != 0) {
35061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
35081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: did not register with CMM\n"));
35091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(adapter->uscb_list);
35111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
35121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
35141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
35151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
35181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_cmm_unregister - un-register with the mangement module
35191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: HBA soft state
35201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
35211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Un-register with the management module.
35221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: mgmt module must return failure for unregister if it has pending
35231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * commands in LLD
35241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
35251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
35261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_cmm_unregister(adapter_t *adapter)
35271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
35281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter->uscb_list);
35291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_mm_unregister_adp(adapter->unique_id);
35301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
35311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
35321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
35351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD
35361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param drvr_data	: LLD specific data
35371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param kioc		: CMM interface packet
35381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param action	: command action
35391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
35401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is invoked whenever the Common Mangement Module (CMM) has a
35411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command for us. The 'action' parameter specifies if this is a new command
35421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or otherwise.
35431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
35441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
35451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action)
35461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
35471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t *adapter;
35481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (action != IOCTL_ISSUE) {
35501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
35511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: unsupported management action:%#2x\n",
35521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			action));
35531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-ENOTSUPP);
35541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
35551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter = (adapter_t *)drvr_data;
35571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// make sure this adapter is not being detached right now.
35591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (atomic_read(&adapter->being_detached)) {
35601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
35611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: reject management request, detaching\n"));
35621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-ENODEV);
35631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
35641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (kioc->opcode) {
35661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GET_ADAP_INFO:
35681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kioc->status =  gather_hbainfo(adapter, (mraid_hba_info_t *)
35701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(unsigned long)kioc->buf_vaddr);
35711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kioc->done(kioc);
35731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return kioc->status;
35751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MBOX_CMD:
35771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return megaraid_mbox_mm_command(adapter, kioc);
35791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
35811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kioc->status = (-EINVAL);
35821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kioc->done(kioc);
35831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EINVAL);
35841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
35851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;	// not reached
35871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
35881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
35901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_mm_command - issues commands routed through CMM
35911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: HBA soft state
35921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param kioc		: management command packet
35931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
35941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issues commands, which are routed through the management module.
35951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
35961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
35971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_mm_command(adapter_t *adapter, uioc_t *kioc)
35981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
35991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head	*head = &adapter->uscb_pool;
36001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t		*mbox64;
36011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			*raw_mbox;
36021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
36031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
36041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
36051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// detach one scb from free pool
36071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags);
36081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (list_empty(head)) {	// should never happen because of CMM
36101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
36121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: bug in cmm handler, lost resources\n"));
36131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
36151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EINVAL);
36171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
36181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb = list_entry(head->next, scb_t, list);
36201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_del_init(&scb->list);
36211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
36231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->state		= SCB_ACTIVE;
36251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->dma_type		= MRAID_DMA_NONE;
36261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->dma_direction	= PCI_DMA_NONE;
36271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb		= (mbox_ccb_t *)scb->ccb;
36291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64		= (mbox64_t *)(unsigned long)kioc->cmdbuf;
36301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox	= (uint8_t *)&mbox64->mbox32;
36311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(ccb->mbox64, mbox64, sizeof(mbox64_t));
36331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->gp		= (unsigned long)kioc;
36351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
36371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If it is a logdrv random delete operation, we have to wait till
36381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * there are no outstanding cmds at the fw and then issue it directly
36391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
36401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) {
36411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (wait_till_fw_empty(adapter)) {
36431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
36441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mbox: LD delete, timed out\n"));
36451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kioc->status = -ETIME;
36471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->status = -1;
36491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_mm_done(adapter, scb);
36511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-ETIME);
36531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
36541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		INIT_LIST_HEAD(&scb->list);
36561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->state = SCB_ISSUED;
36581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mbox_post_cmd(adapter, scb) != 0) {
36591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
36611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mbox: LD delete, mailbox busy\n"));
36621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kioc->status = -EBUSY;
36641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->status = -1;
36661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_mm_done(adapter, scb);
36681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-EBUSY);
36701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
36711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
36731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
36741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// put the command on the pending list and execute
36761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_runpendq(adapter, scb);
36771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
36791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
36801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
36831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldswait_till_fw_empty(adapter_t *adapter)
36841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
36851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	flags = 0;
36861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
36871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
36901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Set the quiescent flag to stop issuing cmds to FW.
36911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3692f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_lock_irqsave(&adapter->lock, flags);
36931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->quiescent++;
3694f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_unlock_irqrestore(&adapter->lock, flags);
36951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
36971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Wait till there are no more cmds outstanding at FW. Try for at most
36981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 60 seconds
36991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
37001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 60 && adapter->outstanding_cmds; i++) {
37011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_DLEVEL1, (KERN_INFO
37021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: FW has %d pending commands\n",
37031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adapter->outstanding_cmds));
37041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(1000);
37061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
37071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return adapter->outstanding_cmds;
37091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
37101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
37131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_mm_done - callback for CMM commands
37141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: HBA soft state
37151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		: completed command
37161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
37171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Callback routine for internal commands originated from the management
37181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * module.
37191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
37201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
37211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb)
37221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
37231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc_t			*kioc;
37241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t		*mbox64;
37251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			*raw_mbox;
37261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
37271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kioc			= (uioc_t *)scb->gp;
37291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64			= (mbox64_t *)(unsigned long)kioc->cmdbuf;
37301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64->mbox32.status	= scb->status;
37311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox		= (uint8_t *)&mbox64->mbox32;
37321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// put scb in the free pool
37351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->state	= SCB_FREE;
37361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->scp	= NULL;
37371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags);
37391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_add(&scb->list, &adapter->uscb_pool);
37411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
37431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// if a delete logical drive operation succeeded, restart the
37451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// controller
37461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) {
37471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->quiescent--;
37491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_mbox_runpendq(adapter, NULL);
37511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
37521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kioc->done(kioc);
37541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
37561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
37571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
37601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * gather_hbainfo - HBA characteristics for the applications
37611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter	: HBA soft state
37621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param hinfo		: pointer to the caller's host info strucuture
37631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
37641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
37651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo)
37661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
37671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t	dmajor;
37681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dmajor			= megaraid_mbox_version[0];
37701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_vendor_id	= adapter->pdev->vendor;
37721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_device_id	= adapter->pdev->device;
37731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->subsys_vendor_id	= adapter->pdev->subsystem_vendor;
37741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->subsys_device_id	= adapter->pdev->subsystem_device;
37751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_bus		= adapter->pdev->bus->number;
37771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_dev_fn	= adapter->pdev->devfn;
37781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_slot		= PCI_SLOT(adapter->pdev->devfn);
37791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->irq		= adapter->host->irq;
37801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->baseport		= ADAP2RAIDDEV(adapter)->baseport;
37811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->unique_id	= (hinfo->pci_bus << 8) | adapter->pdev->devfn;
37831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->host_no		= adapter->host->host_no;
37841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
37861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
37871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
37891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * END: Interface for the common management module
37901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
37911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
37951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_alloc_resources - allocate sysfs related resources
37961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
37971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate packets required to issue FW calls whenever the sysfs attributes
37981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are read. These attributes would require up-to-date information from the
37991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FW. Also set up resources for mutual exclusion to share these resources and
38001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the wait queue.
38011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
38021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter : controller's soft state
38031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
38041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @return 0 on success
38051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @return -ERROR_CODE on failure
38061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
38071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
38081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_alloc_resources(adapter_t *adapter)
38091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
38101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
38111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval = 0;
38121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->sysfs_uioc = kmalloc(sizeof(uioc_t), GFP_KERNEL);
38141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->sysfs_mbox64 = kmalloc(sizeof(mbox64_t), GFP_KERNEL);
38161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->sysfs_buffer = pci_alloc_consistent(adapter->pdev,
38181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			PAGE_SIZE, &raid_dev->sysfs_buffer_dma);
38191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!raid_dev->sysfs_uioc || !raid_dev->sysfs_mbox64 ||
38211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		!raid_dev->sysfs_buffer) {
38221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
38241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: out of memory, %s %d\n", __FUNCTION__,
38251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
38261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval = -ENOMEM;
38281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_sysfs_free_resources(adapter);
38301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
38311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sema_init(&raid_dev->sysfs_sem, 1);
38331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_waitqueue_head(&raid_dev->sysfs_wait_q);
38351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
38371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
38381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
38411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_free_resources - free sysfs related resources
38421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
38431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free packets allocated for sysfs FW commands
38441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
38451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter : controller's soft state
38461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
38471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
38481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_free_resources(adapter_t *adapter)
38491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
38501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
38511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3852c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl	kfree(raid_dev->sysfs_uioc);
3853c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl	kfree(raid_dev->sysfs_mbox64);
38541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->sysfs_buffer) {
38561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(adapter->pdev, PAGE_SIZE,
38571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			raid_dev->sysfs_buffer, raid_dev->sysfs_buffer_dma);
38581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
38591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
38601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
38631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_get_ldmap_done - callback for get ldmap
38641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
38651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Callback routine called in the ISR/tasklet context for get ldmap call
38661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
38671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param uioc : completed packet
38681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
38691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
38701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_get_ldmap_done(uioc_t *uioc)
38711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
38721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = (adapter_t *)uioc->buf_vaddr;
38731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
38741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->status = 0;
38761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wake_up(&raid_dev->sysfs_wait_q);
38781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
38791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
38821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap
38831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
38841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Timeout routine to recover and return to application, in case the adapter
38851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * has stopped responding. A timeout of 60 seconds for this command seem like
38861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a good value
38871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
38881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param uioc : timed out packet
38891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
38901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
38911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_get_ldmap_timeout(unsigned long data)
38921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
38931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc_t		*uioc = (uioc_t *)data;
38941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = (adapter_t *)uioc->buf_vaddr;
38951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
38961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->status = -ETIME;
38981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wake_up(&raid_dev->sysfs_wait_q);
39001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
39011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
39041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_get_ldmap - get update logical drive map
39051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
39061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine will be called whenever user reads the logical drive
39071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * attributes, go get the current logical drive mapping table from the
39081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * firmware. We use the managment API's to issue commands to the controller.
39091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
39101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: The commands issuance functionality is not generalized and
39111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * implemented in context of "get ld map" command only. If required, the
39121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command issuance logical can be trivially pulled out and implemented as a
39131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * standalone libary. For now, this should suffice since there is no other
39141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user of this interface.
39151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
39161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param adapter : controller's soft state
39171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
39181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @return 0 on success
39191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @return -1 on failure
39201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
39211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
39221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_get_ldmap(adapter_t *adapter)
39231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
39251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc_t			*uioc;
39261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t		*mbox64;
39271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
39281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char			*raw_mbox;
39291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct timer_list	sysfs_timer;
39301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct timer_list	*timerp;
39311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	caddr_t			ldmap;
39321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			rval = 0;
39331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
39351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allow only one read at a time to go through the sysfs attributes
39361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
39371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&raid_dev->sysfs_sem);
39381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc	= raid_dev->sysfs_uioc;
39401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64	= raid_dev->sysfs_mbox64;
39411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ldmap	= raid_dev->sysfs_buffer;
39421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(uioc, 0, sizeof(uioc_t));
39441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(mbox64, 0, sizeof(mbox64_t));
39451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(ldmap, 0, sizeof(raid_dev->curr_ldmap));
39461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox		= &mbox64->mbox32;
39481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox	= (char *)mbox;
39491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->cmdbuf    = (uint64_t)(unsigned long)mbox64;
39501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->buf_vaddr	= (caddr_t)adapter;
39511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->status	= -ENODATA;
39521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->done	= megaraid_sysfs_get_ldmap_done;
39531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
39551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Prepare the mailbox packet to get the current logical drive mapping
39561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * table
39571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
39581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)raid_dev->sysfs_buffer_dma;
39591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FC_DEL_LOGDRV;
39611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = OP_GET_LDID_MAP;
39621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
39641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Setup a timer to recover from a non-responding controller
39651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
39661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timerp	= &sysfs_timer;
39671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_timer(timerp);
39681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timerp->function	= megaraid_sysfs_get_ldmap_timeout;
39701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timerp->data		= (unsigned long)uioc;
39711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timerp->expires		= jiffies + 60 * HZ;
39721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_timer(timerp);
39741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
39761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Send the command to the firmware
39771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
39781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval = megaraid_mbox_mm_command(adapter, uioc);
39791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rval == 0) {	// command successfully issued
39811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_event(raid_dev->sysfs_wait_q, (uioc->status != -ENODATA));
39821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
39841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Check if the command timed out
39851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
39861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (uioc->status == -ETIME) {
39871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
39881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: sysfs get ld map timed out\n"));
39891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rval = -ETIME;
39911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
39921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
39931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rval = mbox->status;
39941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
39951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rval == 0) {
39971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(raid_dev->curr_ldmap, ldmap,
39981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sizeof(raid_dev->curr_ldmap));
39991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
40001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
40011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
40021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: get ld map failed with %x\n", rval));
40031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
40041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
40051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
40061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
40071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: could not issue ldmap command:%x\n", rval));
40081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
40091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer_sync(timerp);
40121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&raid_dev->sysfs_sem);
40141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
40161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
40171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
40201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_show_app_hndl - display application handle for this adapter
40211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
40221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Display the handle used by the applications while executing management
40231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tasks on the adapter. We invoke a management module API to get the adapter
40241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * handle, since we do not interface with applications directly.
40251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
40261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param cdev	: class device object representation for the host
40271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param buf	: buffer to send data to
40281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
40291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
40301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf)
40311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
40321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Scsi_Host *shost = class_to_shost(cdev);
40331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = (adapter_t *)SCSIHOST2ADAP(shost);
40341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint32_t	app_hndl;
40351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	app_hndl = mraid_mm_adapter_app_handle(adapter->unique_id);
40371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return snprintf(buf, 8, "%u\n", app_hndl);
40391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
40401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
40431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_show_ldnum - display the logical drive number for this device
40441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
40451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Display the logical drive number for the device in question, if it a valid
40461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * logical drive. For physical devices, "-1" is returned
40471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The logical drive number is displayed in following format
40481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
40491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <SCSI ID> <LD NUM> <LD STICKY ID> <APP ADAPTER HANDLE>
40501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   <int>     <int>       <int>            <int>
40511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
40521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param dev	: device object representation for the scsi device
40531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @param buf	: buffer to send data to
40541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
40551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
405610523b3b82456e416cbaffcc24ea2246980aa746Yani Ioannoumegaraid_sysfs_show_ldnum(struct device *dev, struct device_attribute *attr, char *buf)
40571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
40581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scsi_device *sdev = to_scsi_device(dev);
40591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = (adapter_t *)SCSIHOST2ADAP(sdev->host);
40601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
40611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		scsi_id = -1;
40621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		logical_drv = -1;
40631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		ldid_map = -1;
40641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint32_t	app_hndl = 0;
40651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		mapped_sdev_id;
40661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
40671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
40681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->random_del_supported &&
40701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MRAID_IS_LOGICAL_SDEV(adapter, sdev)) {
40711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval = megaraid_sysfs_get_ldmap(adapter);
40731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rval == 0) {
40741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < MAX_LOGICAL_DRIVES_40LD; i++) {
40761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mapped_sdev_id = sdev->id;
40781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (sdev->id > adapter->init_id) {
40801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					mapped_sdev_id -= 1;
40811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
40821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (raid_dev->curr_ldmap[i] == mapped_sdev_id) {
40841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scsi_id = sdev->id;
40861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					logical_drv = i;
40881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ldid_map = raid_dev->curr_ldmap[i];
40901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					app_hndl = mraid_mm_adapter_app_handle(
40921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							adapter->unique_id);
40931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
40951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
40961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
40971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
40981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
40991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
41001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: sysfs get ld map failed: %x\n",
41011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rval));
41021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
41031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
41041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return snprintf(buf, 36, "%d %d %d %d\n", scsi_id, logical_drv,
41061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ldid_map, app_hndl);
41071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
41081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
41111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * END: Mailbox Low Level Driver
41121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
41131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(megaraid_init);
41141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(megaraid_exit);
41151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* vim: set ts=8 sw=8 tw=78 ai si: */
4117