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
13cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro * Version	: v2.20.5.1 (Nov 16 2006)
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Authors:
16cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro * 	Atul Mukker		<Atul.Mukker@lsi.com>
17cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsi.com>
18cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro * 	Manoj Jose		<Manoj.Jose@lsi.com>
19cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro * 	Seokmann Ju
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 *
70395cf9691d72173d8cdaa613c5f0255f993af94bPaul Bolle * For history of changes, see Documentation/scsi/ChangeLog.megaraid
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
735a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
74acf3368ffb75fc4a83726655d697e79646fe4eb3Paul Gortmaker#include <linux/module.h>
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "megaraid_mbox.h"
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_init(void);
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_exit(void);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_detach_one(struct pci_dev *);
825457b6a6013516a73b8f48ec1adb9984b577a5c1Russell Kingstatic void megaraid_mbox_shutdown(struct pci_dev *);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_io_attach(adapter_t *);
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_io_detach(adapter_t *);
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_init_mbox(adapter_t *);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_fini_mbox(adapter_t *);
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_alloc_cmd_packets(adapter_t *);
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_free_cmd_packets(adapter_t *);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_setup_dma_pools(adapter_t *);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_teardown_dma_pools(adapter_t *);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_sysfs_alloc_resources(adapter_t *);
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_sysfs_free_resources(adapter_t *);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_abort_handler(struct scsi_cmnd *);
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_reset_handler(struct scsi_cmnd *);
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mbox_post_sync_cmd(adapter_t *, uint8_t []);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mbox_post_sync_cmd_fast(adapter_t *, uint8_t []);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_busywait_mbox(mraid_device_t *);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_product_info(adapter_t *);
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_extended_cdb(adapter_t *);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_support_ha(adapter_t *, uint16_t *);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_support_random_del(adapter_t *);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_get_max_sg(adapter_t *);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_enum_raid_scsi(adapter_t *);
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_flush_cache(adapter_t *);
112cd96d96f20f2509dfeb302548132e30f471c071aSumant Patrostatic int megaraid_mbox_fire_sync_cmd(adapter_t *);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_display_scb(adapter_t *, scb_t *);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_setup_device_map(adapter_t *);
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
117f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzikstatic int megaraid_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic scb_t *megaraid_mbox_build_cmd(adapter_t *, struct scsi_cmnd *, int *);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_runpendq(adapter_t *, scb_t *);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_prepare_pthru(adapter_t *, scb_t *,
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct scsi_cmnd *);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *,
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct scsi_cmnd *);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1257d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t megaraid_isr(int, void *);
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_dpc(unsigned long);
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
129ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t megaraid_sysfs_show_app_hndl(struct device *, struct device_attribute *attr, char *);
13010523b3b82456e416cbaffcc24ea2246980aa746Yani Ioannoustatic ssize_t megaraid_sysfs_show_ldnum(struct device *, struct device_attribute *attr, char *);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_cmm_register(adapter_t *);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_cmm_unregister(adapter_t *);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_mm_handler(unsigned long, uioc_t *, uint32_t);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_mbox_mm_command(adapter_t *, uioc_t *);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void megaraid_mbox_mm_done(adapter_t *, scb_t *);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gather_hbainfo(adapter_t *, mraid_hba_info_t *);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int wait_till_fw_empty(adapter_t *);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
142cd96d96f20f2509dfeb302548132e30f471c071aSumant PatroMODULE_AUTHOR("megaraidlinux@lsi.com");
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(MEGARAID_VERSION);
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ### modules parameters for driver ###
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap/*
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set to enable driver to expose unconfigured disk to kernel
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int megaraid_expose_unconf_disks = 0;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0);
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(unconf_disks,
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Set to expose unconfigured disks to kernel (default=0)");
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
159a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap/*
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driver wait time if the adapter's mailbox is busy
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(busy_wait, max_mbox_busy_wait, int, 0);
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(busy_wait,
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Max wait for mailbox in microseconds if busy (default=10)");
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap/*
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * number of sectors per IO command
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(max_sectors, megaraid_max_sectors, int, 0);
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_sectors,
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maximum number of sectors per IO command (default=128)");
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
175a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap/*
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * number of commands per logical unit
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(cmd_per_lun, megaraid_cmd_per_lun, int, 0);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(cmd_per_lun,
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maximum number of commands per logical unit (default=64)");
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
184a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap/*
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fast driver load option, skip scanning for physical devices during load.
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This would result in non-disk devices being skipped during driver load
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * time. These can be later added though, using /proc/scsi/scsi
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int megaraid_fast_load = 0;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(fast_load, megaraid_fast_load, int, 0);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(fast_load,
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Faster loading of the driver, skips physical devices! (default=0)");
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
195a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap/*
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mraid_debug level - threshold for amount of information to be displayed by
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the driver. This level can be changed through modules parameters, ioctl or
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysfs/proc interface. By default, print the announcement messages only.
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mraid_debug_level = CL_ANN;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(debug_level, mraid_debug_level, int, 0);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug_level, "Debug level for driver (default=0)");
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ### global data ###
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic uint8_t megaraid_mbox_version[8] =
208672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann	{ 0x02, 0x20, 0x04, 0x06, 3, 7, 20, 5 };
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PCI table for all supported controllers.
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id pci_id_table_g[] =  {
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4_DI_DISCOVERY,
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4_DI_DISCOVERY,
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4_SC,
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4_SC,
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4_DC,
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4_DC,
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
235672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_DEVICE_ID_VERDE,
236672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
237672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4_DI_EVERGLADES,
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4_DI_EVERGLADES,
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_SI_BIGBEND,
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_SI_BIGBEND,
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_DI_KOBUK,
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_DI_KOBUK,
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_DI_CORVETTE,
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_DI_CORVETTE,
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_DI_EXPEDITION,
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION,
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_PERC4E_DI_GUADALUPE,
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_DELL,
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE,
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
277672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_DEVICE_ID_DOBSON,
278672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
279672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_AMI,
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_DEVICE_ID_AMI_MEGARAID3,
284ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_ANY_ID,
285ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_ANY_ID,
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
289ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_DEVICE_ID_AMI_MEGARAID3,
290ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_ANY_ID,
291ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		PCI_ANY_ID,
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_VENDOR_ID_LSI_LOGIC,
295672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_DEVICE_ID_LINDSAY,
296672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
297672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann		PCI_ANY_ID,
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0}	/* Terminating entry */
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, pci_id_table_g);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
304382db811a8cc1427efabdc959cd1aeef8685ffa6Randy Dunlapstatic struct pci_driver megaraid_pci_driver = {
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "megaraid",
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= pci_id_table_g,
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= megaraid_probe_one,
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= __devexit_p(megaraid_detach_one),
3095457b6a6013516a73b8f48ec1adb9984b577a5c1Russell King	.shutdown	= megaraid_mbox_shutdown,
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// definitions for the device attributes for exporting logical drive number
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// for a scsi address (Host, Channel, Id, Lun)
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
317ee959b00c335d7780136c5abda37809191fe52c3Tony JonesDEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl,
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NULL);
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// Host template initializer for megaraid mbox sysfs device attributes
321ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic struct device_attribute *megaraid_shost_attrs[] = {
322ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	&dev_attr_megaraid_mbox_app_hndl,
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL,
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDEVICE_ATTR(megaraid_mbox_ld, S_IRUSR, megaraid_sysfs_show_ldnum, NULL);
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// Host template initializer for megaraid mbox sysfs device attributes
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct device_attribute *megaraid_sdev_attrs[] = {
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&dev_attr_megaraid_mbox_ld,
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL,
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
335f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net/**
336f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net * megaraid_change_queue_depth - Change the device's queue depth
337f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net * @sdev:	scsi device struct
338f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net * @qdepth:	depth to set
339e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie * @reason:	calling context
340f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net *
341f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net * Return value:
342f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net * 	actual depth set
343a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap */
344e881a172dac4d9ea3b2a1540041d872963c269bdMike Christiestatic int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth,
345e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie				       int reason)
346f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net{
347e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie	if (reason != SCSI_QDEPTH_DEFAULT)
348e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie		return -EOPNOTSUPP;
349e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie
350f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net	if (qdepth > MBOX_MAX_SCSI_CMDS)
351f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net		qdepth = MBOX_MAX_SCSI_CMDS;
352f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net	scsi_adjust_queue_depth(sdev, 0, qdepth);
353f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net	return sdev->queue_depth;
354f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net}
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Scsi host template for megaraid unified driver
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct scsi_host_template megaraid_template_g = {
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.module				= THIS_MODULE,
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name				= "LSI Logic MegaRAID driver",
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.proc_name			= "megaraid",
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.queuecommand			= megaraid_queue_command,
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_abort_handler		= megaraid_abort_handler,
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_device_reset_handler	= megaraid_reset_handler,
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_bus_reset_handler		= megaraid_reset_handler,
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.eh_host_reset_handler		= megaraid_reset_handler,
368f4c8aa1107969c26b1984eb2996a58f816dea71fbrking@charter.net	.change_queue_depth		= megaraid_change_queue_depth,
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.use_clustering			= ENABLE_CLUSTERING,
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.sdev_attrs			= megaraid_sdev_attrs,
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.shost_attrs			= megaraid_shost_attrs,
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_init - module load hook
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We register ourselves as hotplug enabled module and let PCI subsystem
379a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * discover our adapters.
380a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap */
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_init(void)
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	rval;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Announce the driver version
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_INFO "megaraid: %s %s\n", MEGARAID_VERSION,
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MEGARAID_EXT_VERSION));
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// check validity of module parameters
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_cmd_per_lun > MBOX_MAX_SCSI_CMDS) {
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mailbox: max commands per lun reset to %d\n",
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MBOX_MAX_SCSI_CMDS));
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_cmd_per_lun = MBOX_MAX_SCSI_CMDS;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// register as a PCI hot-plug driver module
402382db811a8cc1427efabdc959cd1aeef8685ffa6Randy Dunlap	rval = pci_register_driver(&megaraid_pci_driver);
403672b2d38da4fff4c4452685a25fb88b65243d1a6Ju, Seokmann	if (rval < 0) {
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: could not register hotplug support.\n"));
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_exit - driver unload entry point
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
415a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * We simply unwrap the megaraid_init routine here.
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_exit(void)
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_DLEVEL1, (KERN_NOTICE "megaraid: unloading framework\n"));
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// unregister as PCI hotplug driver
423382db811a8cc1427efabdc959cd1aeef8685ffa6Randy Dunlap	pci_unregister_driver(&megaraid_pci_driver);
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_probe_one - PCI hotplug entry point
431a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @pdev	: handle to this controller's PCI configuration space
432a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @id		: pci device id of the class of controllers
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine should be called whenever a new adapter is detected by the
4353a4fa0a25da81600ea0bcd75692ae8ca6050d165Robert P. J. Day * PCI hotplug susbsystem.
436a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap */
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// detected a new controller
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_INFO
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: probe new device %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdev->vendor, pdev->device, pdev->subsystem_vendor,
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdev->subsystem_device));
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, ("bus %d:slot %d:func %d\n", pdev->bus->number,
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)));
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_enable_device(pdev)) {
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: pci_enable_device failed\n"));
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Enable bus-mastering on this controller
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_master(pdev);
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate the per driver initialization structure
463dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau	adapter = kzalloc(sizeof(adapter_t), GFP_KERNEL);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter == NULL) {
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
467cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison		"megaraid: out of memory, %s %d.\n", __func__, __LINE__));
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_probe_one;
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// set up PCI related soft state and other pre-known parameters
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->unique_id	= pdev->bus->number << 8 | pdev->devfn;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->irq		= pdev->irq;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->pdev		= pdev;
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_set(&adapter->being_detached, 0);
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Setup the default DMA mask. This would be changed later on
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// depending on hardware capabilities
482284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang	if (pci_set_dma_mask(adapter->pdev, DMA_BIT_MASK(32)) != 0) {
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: pci_set_dma_mask failed:%d\n", __LINE__));
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_adapter;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Initialize the synchronization lock for kernel and LLD
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&adapter->lock);
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Initialize the command queues: the list of free SCBs and the list
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// of pending SCBs.
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&adapter->kscb_pool);
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(SCSI_FREE_LIST_LOCK(adapter));
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&adapter->pend_list);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(PENDING_LIST_LOCK(adapter));
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&adapter->completed_list);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(COMPLETED_LIST_LOCK(adapter));
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Start the mailbox based controller
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_init_mbox(adapter) != 0) {
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: maibox adapter did not initialize\n"));
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_adapter;
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Register with LSI Common Management Module
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_cmm_register(adapter) != 0) {
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: could not register with management module\n"));
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_fini_mbox;
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// setup adapter handle in PCI soft state
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, adapter);
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// attach with scsi mid-layer
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_io_attach(adapter) != 0) {
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING "megaraid: io attach failed\n"));
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_cmm_unreg;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_cmm_unreg:
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, NULL);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_cmm_unregister(adapter);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_fini_mbox:
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_fini_mbox(adapter);
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_adapter:
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter);
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_probe_one:
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_disable_device(pdev);
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
551a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * megaraid_detach_one - release framework resources and call LLD release routine
552a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @pdev	: handle for our PCI cofiguration space
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is called during driver unload. We free all the allocated
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * resources and call the corresponding LLD so that it can also release all
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * its resources.
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
558a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * This routine is also called from the PCI hotplug system.
559a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap */
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_detach_one(struct pci_dev *pdev)
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t		*adapter;
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Scsi_Host	*host;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Start a rollback on this adapter
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter = pci_get_drvdata(pdev);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter) {
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_CRIT
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: Invalid detach on %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pdev->vendor, pdev->device, pdev->subsystem_vendor,
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pdev->subsystem_device));
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: detaching device %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pdev->vendor, pdev->device, pdev->subsystem_vendor,
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pdev->subsystem_device));
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host = adapter->host;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// do not allow any more requests from the management module for this
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// adapter.
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// FIXME: How do we account for the request which might still be
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// pending with us?
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_set(&adapter->being_detached, 1);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// detach from the IO sub-system
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_io_detach(adapter);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// reset the device state in the PCI structure. We check this
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// condition when we enter here. If the device state is NULL,
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// that would mean the device has already been removed
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, NULL);
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Unregister from common management module
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	//
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// FIXME: this must return success or failure for conditions if there
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// is a command pending with LLD or not.
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_cmm_unregister(adapter);
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// finalize the mailbox based controller and release all resources
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_fini_mbox(adapter);
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter);
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scsi_host_put(host);
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_disable_device(pdev);
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA
623a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @pdev		: generic driver model device
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
625a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Shutdown notification, perform flush cache.
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6285457b6a6013516a73b8f48ec1adb9984b577a5c1Russell Kingmegaraid_mbox_shutdown(struct pci_dev *pdev)
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6305457b6a6013516a73b8f48ec1adb9984b577a5c1Russell King	adapter_t		*adapter = pci_get_drvdata(pdev);
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static int		counter;
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter) {
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: null device in shutdown\n"));
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// flush caches now
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_INFO "megaraid: flushing adapter %d...",
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		counter++));
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_flush_cache(adapter);
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, ("done\n"));
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_io_attach - attach a device with the IO subsystem
651a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: controller's soft state
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
653a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Attach this device with the IO subsystem.
654a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap */
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_io_attach(adapter_t *adapter)
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Scsi_Host	*host;
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Initialize SCSI Host structure
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host = scsi_host_alloc(&megaraid_template_g, 8);
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!host) {
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: scsi_register failed\n"));
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SCSIHOST2ADAP(host)	= (caddr_t)adapter;
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->host		= host;
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->irq		= adapter->irq;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->unique_id		= adapter->unique_id;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->can_queue		= adapter->max_cmds;
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->this_id		= adapter->init_id;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->sg_tablesize	= adapter->sglen;
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->max_sectors	= adapter->max_sectors;
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->cmd_per_lun	= adapter->cmd_per_lun;
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->max_channel	= adapter->max_channel;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->max_id		= adapter->max_target;
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->max_lun		= adapter->max_lun;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// notify mid-layer about the new controller
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (scsi_add_host(host, &adapter->pdev->dev)) {
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: scsi_add_host failed\n"));
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scsi_host_put(host);
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scsi_scan_host(host);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_io_detach - detach a device from the IO subsystem
703a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: controller's soft state
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
705a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Detach this device from the IO subsystem.
706a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap */
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_io_detach(adapter_t *adapter)
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Scsi_Host	*host;
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_DLEVEL1, (KERN_INFO "megaraid: io detach\n"));
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host = adapter->host;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scsi_remove_host(host);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * START: Mailbox Low Level Driver
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is section specific to the single mailbox based controllers
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_init_mbox - initialize controller
730a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: our soft state
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
732a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * - Allocate 16-byte aligned mailbox memory for firmware handshake
733a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * - Allocate controller's memory resources
734a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * - Find out all initialization data
735a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * - Allocate memory required for all the commands
736a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * - Use internal library of FW routines, build up complete soft state
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
738cedfb178ada245b6c52a654936b34d7996e26a1dRandy Dunlapstatic int __devinit
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_init_mbox(adapter_t *adapter)
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev		*pdev;
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev;
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
744fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann	uint32_t		magic64;
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->ito	= MBOX_TIMEOUT;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pdev		= adapter->pdev;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate and initialize the init data structure for mailbox
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * controllers
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
754dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau	raid_dev = kzalloc(sizeof(mraid_device_t), GFP_KERNEL);
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev == NULL) return -1;
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Attach the adapter soft state to raid device soft state
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->raid_device	= (caddr_t)raid_dev;
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->fast_load	= megaraid_fast_load;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// our baseport
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->baseport = pci_resource_start(pdev, 0);
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_request_regions(pdev, "MegaRAID: LSI Logic Corporation") != 0) {
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: mem region busy\n"));
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_raid_dev;
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!raid_dev->baseaddr) {
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: could not map hba memory\n") );
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_release_regions;
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
786cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	/* initialize the mutual exclusion lock for the mailbox */
787cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	spin_lock_init(&raid_dev->mailbox_lock);
788cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
789cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	/* allocate memory required for commands */
790cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	if (megaraid_alloc_cmd_packets(adapter) != 0)
791cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		goto out_iounmap;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
793cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	/*
794cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 * Issue SYNC cmd to flush the pending cmds in the adapter
795cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 * and initialize its internal state
796cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 */
797cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
798cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	if (megaraid_mbox_fire_sync_cmd(adapter))
799cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		con_log(CL_ANN, ("megaraid: sync cmd failed\n"));
800cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
801cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	/*
802cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 * Setup the rest of the soft state using the library of
803cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 * FW routines
804cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 */
805cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
806cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	/* request IRQ and register the interrupt service routine */
8071d6f359a2e06296418481239f8054a878f36e819Thomas Gleixner	if (request_irq(adapter->irq, megaraid_isr, IRQF_SHARED, "megaraid",
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter)) {
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: Couldn't register IRQ %d!\n", adapter->irq));
812cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		goto out_alloc_cmds;
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Product info
817cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	if (megaraid_mbox_product_info(adapter) != 0)
818cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		goto out_free_irq;
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Do we support extended CDBs
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_cdb_sz = 10;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_mbox_extended_cdb(adapter) == 0) {
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->max_cdb_sz = 16;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Do we support cluster environment, if we do, what is the initiator
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * id.
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * NOTE: In a non-cluster aware firmware environment, the LLD should
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * return 7 as initiator id.
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->ha		= 0;
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->init_id	= -1;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_mbox_support_ha(adapter, &adapter->init_id) == 0) {
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->ha = 1;
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Prepare the device ids array to have the mapping between the kernel
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * device address and megaraid device address.
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We export the physical devices on their actual addresses. The
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * logical drives are exported on a virtual SCSI channel
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_setup_device_map(adapter);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// If the firmware supports random deletion, update the device id map
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_mbox_support_random_del(adapter)) {
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Change the logical drives numbers in device_ids array one
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// slot in device_ids is reserved for target id, that's why
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// "<=" below
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= MAX_LOGICAL_DRIVES_40LD; i++) {
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adapter->device_ids[adapter->max_channel][i] += 0x80;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->device_ids[adapter->max_channel][adapter->init_id] =
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			0xFF;
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		raid_dev->random_del_supported = 1;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * find out the maximum number of scatter-gather elements supported by
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * this firmware
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->sglen = megaraid_mbox_get_max_sg(adapter);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// enumerate RAID and SCSI channels so that all devices on SCSI
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// channels can later be exported, including disk devices
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_enum_raid_scsi(adapter);
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Other parameters required by upper layer
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * maximum number of sectors per IO command
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_sectors = megaraid_max_sectors;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * number of queued commands per LUN.
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->cmd_per_lun = megaraid_cmd_per_lun;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate resources required to issue FW calls, when sysfs is
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * accessed
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
887cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	if (megaraid_sysfs_alloc_resources(adapter) != 0)
888cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		goto out_free_irq;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Set the DMA mask to 64-bit. All supported controllers as capable of
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// DMA in this range
892fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann	pci_read_config_dword(adapter->pdev, PCI_CONF_AMISIG64, &magic64);
893fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann
894fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann	if (((magic64 == HBA_SIGNATURE_64_BIT) &&
895fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		((adapter->pdev->subsystem_device !=
8968741ca71a3f626a56595b88200ebf952ce77ceefAndrey Mirkin		PCI_SUBSYS_ID_MEGARAID_SATA_150_6) &&
897fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		(adapter->pdev->subsystem_device !=
898fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		PCI_SUBSYS_ID_MEGARAID_SATA_150_4))) ||
899fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
900fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		adapter->pdev->device == PCI_DEVICE_ID_VERDE) ||
901fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
902fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		adapter->pdev->device == PCI_DEVICE_ID_DOBSON) ||
903fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
904fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		adapter->pdev->device == PCI_DEVICE_ID_LINDSAY) ||
905fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		(adapter->pdev->vendor == PCI_VENDOR_ID_DELL &&
906fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		adapter->pdev->device == PCI_DEVICE_ID_PERC4_DI_EVERGLADES) ||
907fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		(adapter->pdev->vendor == PCI_VENDOR_ID_DELL &&
908fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		adapter->pdev->device == PCI_DEVICE_ID_PERC4E_DI_KOBUK)) {
9096a35528a8346f6e6fd32ed7e51f04d1fa4ca2c01Yang Hongyang		if (pci_set_dma_mask(adapter->pdev, DMA_BIT_MASK(64))) {
910fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann			con_log(CL_ANN, (KERN_WARNING
911fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann				"megaraid: DMA mask for 64-bit failed\n"));
912fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann
913284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang			if (pci_set_dma_mask (adapter->pdev, DMA_BIT_MASK(32))) {
914fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann				con_log(CL_ANN, (KERN_WARNING
915fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann					"megaraid: 32-bit DMA mask failed\n"));
916fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann				goto out_free_sysfs_res;
917fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann			}
918fbf6080225a03aa2b3671acacebdf615f1d3f6baJu, Seokmann		}
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// setup tasklet for DPC
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc,
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(unsigned long)adapter);
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_DLEVEL1, (KERN_INFO
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid mbox hba successfully initialized\n"));
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_sysfs_res:
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_sysfs_free_resources(adapter);
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_irq:
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(adapter->irq, adapter);
934cd96d96f20f2509dfeb302548132e30f471c071aSumant Patroout_alloc_cmds:
935cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	megaraid_free_cmd_packets(adapter);
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_iounmap:
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(raid_dev->baseaddr);
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_release_regions:
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_release_regions(pdev);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_raid_dev:
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(raid_dev);
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_fini_mbox - undo controller initialization
949a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: our soft state
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_fini_mbox(adapter_t *adapter)
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// flush all caches
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_flush_cache(adapter);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tasklet_kill(&adapter->dpc_h);
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_sysfs_free_resources(adapter);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_free_cmd_packets(adapter);
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(adapter->irq, adapter);
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(raid_dev->baseaddr);
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_release_regions(adapter->pdev);
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(raid_dev);
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_alloc_cmd_packets - allocate shared mailbox
979a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: soft state of the raid controller
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate and align the shared mailbox. This maibox is used to issue
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * all the commands. For IO based controllers, the mailbox is also regsitered
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with the FW. Allocate memory for all commands as well.
984a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * This is our big allocator.
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_alloc_cmd_packets(adapter_t *adapter)
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev		*pdev;
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		align;
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*epthru_pci_blk;
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*sg_pci_blk;
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*mbox_pci_blk;
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pdev = adapter->pdev;
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Setup the mailbox
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate the common 16-byte aligned memory for the handshake
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * mailbox.
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->una_mbox64 = pci_alloc_consistent(adapter->pdev,
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sizeof(mbox64_t), &raid_dev->una_mbox64_dma);
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!raid_dev->una_mbox64) {
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
1011cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison			"megaraid: out of memory, %s %d\n", __func__,
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(raid_dev->una_mbox64, 0, sizeof(mbox64_t));
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Align the mailbox at 16-byte boundary
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox	= &raid_dev->una_mbox64->mbox32;
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox	= (mbox_t *)((((unsigned long)raid_dev->mbox) + 15) &
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(~0UL ^ 0xFUL));
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox64 = (mbox64_t *)(((unsigned long)raid_dev->mbox) - 8);
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	align = ((void *)raid_dev->mbox -
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((void *)&raid_dev->una_mbox64->mbox32));
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox_dma = (unsigned long)raid_dev->una_mbox64_dma + 8 +
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			align;
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for commands issued internally
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->ibuf = pci_alloc_consistent(pdev, MBOX_IBUF_SIZE,
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				&adapter->ibuf_dma_h);
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter->ibuf) {
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
1039cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison			"megaraid: out of memory, %s %d\n", __func__,
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_common_mbox;
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(adapter->ibuf, 0, MBOX_IBUF_SIZE);
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for our SCSI Command Blocks and their associated
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// memory
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate memory for the base list of scb. Later allocate memory for
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * CCBs and embedded components of each CCB and point the pointers in
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * scb to the allocated components
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * NOTE: The code to allocate SCB will be duplicated in all the LLD
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * since the calling routine does not yet know the number of available
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * commands.
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1057dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau	adapter->kscb_list = kcalloc(MBOX_MAX_SCSI_CMDS, sizeof(scb_t), GFP_KERNEL);
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->kscb_list == NULL) {
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
1061cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison			"megaraid: out of memory, %s %d\n", __func__,
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_ibuf;
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// memory allocation for our command packets
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_mbox_setup_dma_pools(adapter) != 0) {
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
1069cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison			"megaraid: out of memory, %s %d\n", __func__,
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_scb_list;
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Adjust the scb pointers and link in the free pool
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru_pci_blk	= raid_dev->epthru_pool;
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sg_pci_blk	= raid_dev->sg_pool;
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_pci_blk	= raid_dev->mbox_pool;
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb			= adapter->kscb_list + i;
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb			= raid_dev->ccb_list + i;
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox	= (mbox_t *)(mbox_pci_blk[i].vaddr + 16);
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->raw_mbox	= (uint8_t *)ccb->mbox;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox64	= (mbox64_t *)(mbox_pci_blk[i].vaddr + 8);
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox_dma_h	= (unsigned long)mbox_pci_blk[i].dma_addr + 16;
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// make sure the mailbox is aligned properly
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ccb->mbox_dma_h & 0x0F) {
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_CRIT
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mbox: not aligned on 16-bytes\n"));
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out_teardown_dma_pools;
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->epthru		= (mraid_epassthru_t *)
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						epthru_pci_blk[i].vaddr;
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->epthru_dma_h	= epthru_pci_blk[i].dma_addr;
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->pthru		= (mraid_passthru_t *)ccb->epthru;
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->pthru_dma_h	= ccb->epthru_dma_h;
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl64		= (mbox_sgl64 *)sg_pci_blk[i].vaddr;
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl_dma_h		= sg_pci_blk[i].dma_addr;
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl32		= (mbox_sgl32 *)ccb->sgl64;
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->ccb		= (caddr_t)ccb;
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->gp			= 0;
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->sno		= i;	// command index
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->scp		= NULL;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->state		= SCB_FREE;
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_direction	= PCI_DMA_NONE;
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_type		= MRAID_DMA_NONE;
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_channel	= -1;
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_target		= -1;
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// put scb in the free pool
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_add_tail(&scb->list, &adapter->kscb_pool);
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_teardown_dma_pools:
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_teardown_dma_pools(adapter);
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_scb_list:
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter->kscb_list);
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_ibuf:
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(pdev, MBOX_IBUF_SIZE, (void *)adapter->ibuf,
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->ibuf_dma_h);
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_free_common_mbox:
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(adapter->pdev, sizeof(mbox64_t),
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma);
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_free_cmd_packets - free memory
1142a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: soft state of the raid controller
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1144a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Release memory resources allocated for commands.
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_free_cmd_packets(adapter_t *adapter)
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_teardown_dma_pools(adapter);
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter->kscb_list);
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(adapter->pdev, MBOX_IBUF_SIZE,
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(void *)adapter->ibuf, adapter->ibuf_dma_h);
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(adapter->pdev, sizeof(mbox64_t),
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma);
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_setup_dma_pools - setup dma pool for command packets
1166a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: HBA soft state
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1168a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Setup the dma pools for mailbox, passthru and extended passthru structures,
1169a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * and scatter-gather lists.
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_setup_dma_pools(adapter_t *adapter)
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*epthru_pci_blk;
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*sg_pci_blk;
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*mbox_pci_blk;
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for 16-bytes aligned mailboxes
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->mbox_pool_handle = pci_pool_create("megaraid mbox pool",
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						adapter->pdev,
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						sizeof(mbox64_t) + 16,
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						16, 0);
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->mbox_pool_handle == NULL) {
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail_setup_dma_pool;
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_pci_blk = raid_dev->mbox_pool;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox_pci_blk[i].vaddr = pci_pool_alloc(
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						raid_dev->mbox_pool_handle,
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						GFP_KERNEL,
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&mbox_pci_blk[i].dma_addr);
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!mbox_pci_blk[i].vaddr) {
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fail_setup_dma_pool;
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate memory for each embedded passthru strucuture pointer
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Request for a 128 bytes aligned structure for each passthru command
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * structure
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Since passthru and extended passthru commands are exclusive, they
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * share common memory pool. Passthru structures piggyback on memory
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * allocted to extended passthru since passthru is smaller of the two
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->epthru_pool_handle = pci_pool_create("megaraid mbox pthru",
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adapter->pdev, sizeof(mraid_epassthru_t), 128, 0);
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->epthru_pool_handle == NULL) {
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail_setup_dma_pool;
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru_pci_blk = raid_dev->epthru_pool;
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru_pci_blk[i].vaddr = pci_pool_alloc(
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						raid_dev->epthru_pool_handle,
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						GFP_KERNEL,
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&epthru_pci_blk[i].dma_addr);
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!epthru_pci_blk[i].vaddr) {
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fail_setup_dma_pool;
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for each scatter-gather list. Request for 512 bytes
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// alignment for each sg list
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->sg_pool_handle = pci_pool_create("megaraid mbox sg",
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					adapter->pdev,
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					sizeof(mbox_sgl64) * MBOX_MAX_SG_SIZE,
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					512, 0);
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->sg_pool_handle == NULL) {
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail_setup_dma_pool;
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sg_pci_blk = raid_dev->sg_pool;
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sg_pci_blk[i].vaddr = pci_pool_alloc(
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						raid_dev->sg_pool_handle,
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						GFP_KERNEL,
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&sg_pci_blk[i].dma_addr);
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!sg_pci_blk[i].vaddr) {
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fail_setup_dma_pool;
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail_setup_dma_pool:
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_teardown_dma_pools(adapter);
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets
1262a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: HBA soft state
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1264a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Teardown the dma pool for mailbox, passthru and extended passthru
1265a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * structures, and scatter-gather lists.
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_teardown_dma_pools(adapter_t *adapter)
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*epthru_pci_blk;
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*sg_pci_blk;
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mraid_pci_blk	*mbox_pci_blk;
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sg_pci_blk = raid_dev->sg_pool;
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS && sg_pci_blk[i].vaddr; i++) {
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_free(raid_dev->sg_pool_handle, sg_pci_blk[i].vaddr,
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sg_pci_blk[i].dma_addr);
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->sg_pool_handle)
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_destroy(raid_dev->sg_pool_handle);
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru_pci_blk = raid_dev->epthru_pool;
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS && epthru_pci_blk[i].vaddr; i++) {
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_free(raid_dev->epthru_pool_handle,
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			epthru_pci_blk[i].vaddr, epthru_pci_blk[i].dma_addr);
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->epthru_pool_handle)
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_destroy(raid_dev->epthru_pool_handle);
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_pci_blk = raid_dev->mbox_pool;
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS && mbox_pci_blk[i].vaddr; i++) {
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_free(raid_dev->mbox_pool_handle,
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox_pci_blk[i].vaddr, mbox_pci_blk[i].dma_addr);
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->mbox_pool_handle)
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_destroy(raid_dev->mbox_pool_handle);
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_alloc_scb - detach and return a scb from the free list
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: controller's soft state
1310a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scp		: pointer to the scsi command to be executed
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1312a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Return the scb from the head of the free list. %NULL if there are none
1313a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * available.
1314a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap */
1315858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic scb_t *
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head	*head = &adapter->kscb_pool;
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb = NULL;
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// detach scb from free pool
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags);
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (list_empty(head)) {
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb = list_entry(head->next, scb_t, list);
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_del_init(&scb->list);
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->state	= SCB_ACTIVE;
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->scp	= scp;
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->dma_type	= MRAID_DMA_NONE;
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return scb;
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_dealloc_scb - return the scb to the free pool
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: controller's soft state
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		: scb to be freed
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1348a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Return the scb back to the free list of scbs. The caller must 'flush' the
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc.
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE NOTE: Make sure the scb is not on any list before calling this
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine.
1352a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap */
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// put scb in the free pool
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->state	= SCB_FREE;
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->scp	= NULL;
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags);
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_add(&scb->list, &adapter->kscb_pool);
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_mksgl - make the scatter-gather list
1373a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: controller's soft state
1374a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scb		: scsi control block
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1376a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Prepare the scatter-gather list.
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1378858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scatterlist	*sgl;
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scsi_cmnd	*scp;
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			sgcnt;
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scp	= scb->scp;
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
139132fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori	sgcnt = scsi_dma_map(scp);
139232fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori	BUG_ON(sgcnt < 0 || sgcnt > adapter->sglen);
139332fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// no mapping required if no data to be transferred
139532fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori	if (!sgcnt)
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->dma_type = MRAID_DMA_WSG;
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
140032fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori	scsi_for_each_sg(scp, sgl, sgcnt, i) {
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl64[i].address	= sg_dma_address(sgl);
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->sgl64[i].length	= sg_dma_len(sgl);
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Return count of SG nodes
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sgcnt;
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mbox_post_cmd - issue a mailbox command
1412a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: controller's soft state
1413a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scb		: command to be issued
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1415a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Post the command to the controller if mailbox is available.
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1417858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmbox_post_cmd(adapter_t *adapter, scb_t *scb)
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t	*mbox64;
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t	*ccb;
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	flags;
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int	i = 0;
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= raid_dev->mbox;
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64	= raid_dev->mbox64;
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Check for busy mailbox. If it is, return failure - the caller
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * should retry later.
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags);
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(mbox->busy)) {
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(1);
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i++;
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while(mbox->busy && (i < max_mbox_busy_wait));
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mbox->busy) {
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -1;
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Copy this command's mailbox data into "adapter's" mailbox
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy((caddr_t)mbox64, (caddr_t)ccb->mbox64, 22);
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->cmdid = scb->sno;
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->outstanding_cmds++;
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
146032fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori	if (scb->dma_direction == PCI_DMA_TODEVICE)
146132fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori		pci_dma_sync_sg_for_device(adapter->pdev,
146232fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori					   scsi_sglist(scb->scp),
146332fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori					   scsi_sg_count(scb->scp),
146432fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori					   PCI_DMA_TODEVICE);
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->busy	= 1;	// Set busy
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->poll	= 0;
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->ack	= 0;
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_queue_command - generic queue entry point for all LLDs
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scp		: pointer to the scsi command to be executed
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @done	: callback routine to be called after the cmd has be completed
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Queue entry point for mailbox based controllers.
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
1487f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzikmegaraid_queue_command_lck(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter;
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t		*scb;
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		if_busy;
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter		= SCP2ADAPTER(scp);
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scp->scsi_done	= done;
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scp->result	= 0;
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate and build a SCB request
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * if_busy flag will be set if megaraid_mbox_build_cmd() command could
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * not allocate scb. We will return non-zero status in that case.
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * NOTE: scb can be null even though certain commands completed
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, it would
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * return 0 in that case, and we would do the callback right away.
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if_busy	= 0;
1506f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	scb = megaraid_mbox_build_cmd(adapter, scp, &if_busy);
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!scb) {	// command already completed
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		done(scp);
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1512f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	megaraid_mbox_runpendq(adapter, scb);
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return if_busy;
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1516f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzikstatic DEF_SCSI_QCMD(megaraid_queue_command)
1517f281233d3eba15fb225d21ae2e228fd4553d824aJeff Garzik
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1519a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * megaraid_mbox_build_cmd - transform the mid-layer scsi commands
1520a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: controller's soft state
1521a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scp		: mid-layer scsi command pointer
1522a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @busy	: set if request could not be completed because of lack of
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		resources
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1525a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Transform the mid-layer scsi command to megaraid firmware lingua.
1526a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Convert the command issued by mid-layer to format understood by megaraid
1527a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * firmware. We also complete certain commands without sending them to firmware.
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic scb_t *
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*rdev = ADAP2RAIDDEV(adapter);
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			channel;
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			target;
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			islogical;
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_passthru_t	*pthru;
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t		*mbox64;
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char			skip[] = "skipping";
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char			scan[] = "scanning";
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char			*ss;
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Get the appropriate device map for the device this command is
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * intended for
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MRAID_GET_DEVICE_MAP(adapter, scp, channel, target, islogical);
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Logical drive commands
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (islogical) {
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (scp->cmnd[0]) {
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case TEST_UNIT_READY:
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Do we support clustering and is the support enabled
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * If no, return success always
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!adapter->ha) {
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_OK << 16);
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*busy = 1;
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dma_direction	= scp->sc_data_direction;
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_channel	= 0xFF;
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_target		= target;
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb			= (mbox_ccb_t *)scb->ccb;
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * The command id will be provided by the command
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * issuance routine
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[0]	= CLUSTER_CMD;
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[2]	= RESERVATION_STATUS;
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[3]	= target;
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return scb;
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MODE_SENSE:
158932fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori		{
159032fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori			struct scatterlist	*sgl;
159132fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori			caddr_t			vaddr;
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
159332fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori			sgl = scsi_sglist(scp);
159445711f1af6eff1a6d010703b4862e0d2b9afd056Jens Axboe			if (sg_page(sgl)) {
159545711f1af6eff1a6d010703b4862e0d2b9afd056Jens Axboe				vaddr = (caddr_t) sg_virt(&sgl[0]);
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
159732fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori				memset(vaddr, 0, scp->cmnd[4]);
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
160032fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori				con_log(CL_ANN, (KERN_WARNING
160132fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori						 "megaraid mailbox: invalid sg:%d\n",
160232fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori						 __LINE__));
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
160432fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori		}
160532fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori		scp->result = (DID_OK << 16);
160632fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori		return NULL;
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case INQUIRY:
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Display the channel scan for logical drives
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Do not display scan for a channel if already done.
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_INFO
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"scsi[%d]: scanning scsi channel %d",
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					adapter->host->host_no,
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					SCP2CHANNEL(scp)));
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					" [virtual] for logical drives\n"));
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rdev->last_disp |= (1L << SCP2CHANNEL(scp));
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1626aa677bc7445147f663ebde69d248a30839bada76Ju, Seokmann			if (scp->cmnd[1] & MEGA_SCSI_INQ_EVPD) {
1627aa677bc7445147f663ebde69d248a30839bada76Ju, Seokmann				scp->sense_buffer[0] = 0x70;
1628aa677bc7445147f663ebde69d248a30839bada76Ju, Seokmann				scp->sense_buffer[2] = ILLEGAL_REQUEST;
1629aa677bc7445147f663ebde69d248a30839bada76Ju, Seokmann				scp->sense_buffer[12] = MEGA_INVALID_FIELD_IN_CDB;
1630aa677bc7445147f663ebde69d248a30839bada76Ju, Seokmann				scp->result = CHECK_CONDITION << 1;
1631aa677bc7445147f663ebde69d248a30839bada76Ju, Seokmann				return NULL;
1632aa677bc7445147f663ebde69d248a30839bada76Ju, Seokmann			}
1633aa677bc7445147f663ebde69d248a30839bada76Ju, Seokmann
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Fall through */
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case READ_CAPACITY:
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Do not allow LUN > 0 for logical drives and
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * requests for more than 40 logical drives
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (SCP2LUN(scp)) {
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_BAD_TARGET << 16);
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((target % 0x80) >= MAX_LOGICAL_DRIVES_40LD) {
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_BAD_TARGET << 16);
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Allocate a SCB and initialize passthru */
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*busy = 1;
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb			= (mbox_ccb_t *)scb->ccb;
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_channel	= 0xFF;
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_target		= target;
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru			= ccb->pthru;
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox			= ccb->mbox;
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64			= ccb->mbox64;
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->timeout		= 0;
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->ars		= 1;
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->reqsenselen	= 14;
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->islogical	= 1;
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->logdrv		= target;
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->cdblen		= scp->cmd_len;
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->cmd		= MBOXCMD_PASSTHRU64;
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dma_direction	= scp->sc_data_direction;
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167632fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori			pthru->dataxferlen	= scsi_bufflen(scp);
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->dataxferaddr	= ccb->sgl_dma_h;
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pthru->numsge		= megaraid_mbox_mksgl(adapter,
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							scb);
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->xferaddr		= 0xFFFFFFFF;
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_lo	= (uint32_t )ccb->pthru_dma_h;
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_hi	= 0;
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return scb;
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case READ_6:
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case WRITE_6:
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case READ_10:
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case WRITE_10:
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case READ_12:
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case WRITE_12:
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Allocate a SCB and initialize mailbox
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*busy = 1;
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb			= (mbox_ccb_t *)scb->ccb;
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_channel	= 0xFF;
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_target		= target;
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox			= ccb->mbox;
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64			= ccb->mbox64;
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->logdrv		= target;
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * A little HACK: 2nd bit is zero for all scsi read
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * commands and is set for all scsi write commands
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->cmd = (scp->cmnd[0] & 0x02) ?  MBOXCMD_LWRITE64:
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					MBOXCMD_LREAD64 ;
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * 6-byte READ(0x08) or WRITE(0x0A) cdb
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (scp->cmd_len == 6) {
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->numsectors = (uint32_t)scp->cmnd[4];
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->lba =
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[1] << 16)	|
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[2] << 8)	|
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[3];
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->lba &= 0x1FFFFF;
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * 10-byte READ(0x28) or WRITE(0x2A) cdb
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (scp->cmd_len == 10) {
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->numsectors =
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[8] |
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[7] << 8);
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->lba =
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[2] << 24) |
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[3] << 16) |
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[4] << 8) |
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[5];
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (scp->cmd_len == 12) {
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->lba =
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[2] << 24) |
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[3] << 16) |
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[4] << 8) |
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[5];
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->numsectors =
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[6] << 24) |
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[7] << 16) |
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((uint32_t)scp->cmnd[8] << 8) |
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(uint32_t)scp->cmnd[9];
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_WARNING
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"megaraid: unsupported CDB length\n"));
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				megaraid_dealloc_scb(adapter, scb);
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dma_direction = scp->sc_data_direction;
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Calculate Scatter-Gather info
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_lo	= (uint32_t )ccb->sgl_dma_h;
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->numsge		= megaraid_mbox_mksgl(adapter,
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							scb);
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->xferaddr		= 0xFFFFFFFF;
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_hi	= 0;
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return scb;
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case RESERVE:
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case RELEASE:
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Do we support clustering and is the support enabled
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!adapter->ha) {
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_BAD_TARGET << 16);
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Allocate a SCB and initialize mailbox
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = (DID_ERROR << 16);
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*busy = 1;
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return NULL;
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb			= (mbox_ccb_t *)scb->ccb;
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_channel	= 0xFF;
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dev_target		= target;
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[0]	= CLUSTER_CMD;
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[2]	=  (scp->cmnd[0] == RESERVE) ?
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						RESERVE_LD : RELEASE_LD;
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ccb->raw_mbox[3]	= target;
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->dma_direction	= scp->sc_data_direction;
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return scb;
18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_BAD_TARGET << 16);
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else { // Passthru device commands
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Do not allow access to target id > 15 or LUN > 7
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (target > 15 || SCP2LUN(scp) > 7) {
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_BAD_TARGET << 16);
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// if fast load option was set and scan for last device is
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// over, reset the fast_load flag so that during a possible
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// next scan, devices can be made available
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rdev->fast_load && (target == 15) &&
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(SCP2CHANNEL(scp) == adapter->max_channel -1)) {
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_INFO
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid[%d]: physical device scan re-enabled\n",
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				adapter->host->host_no));
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rdev->fast_load = 0;
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Display the channel scan for physical devices
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ss = rdev->fast_load ? skip : scan;
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_INFO
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"scsi[%d]: %s scsi channel %d [Phy %d]",
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				adapter->host->host_no, ss, SCP2CHANNEL(scp),
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				channel));
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				" for non-raid devices\n"));
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rdev->last_disp |= (1L << SCP2CHANNEL(scp));
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// disable channel sweep if fast load option given
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rdev->fast_load) {
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_BAD_TARGET << 16);
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Allocate a SCB and initialize passthru
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(scb = megaraid_alloc_scb(adapter, scp))) {
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_ERROR << 16);
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*busy = 1;
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb			= (mbox_ccb_t *)scb->ccb;
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_channel	= channel;
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_target		= target;
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_direction	= scp->sc_data_direction;
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox			= ccb->mbox;
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox64			= ccb->mbox64;
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Does this firmware support extended CDBs
18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (adapter->max_cdb_sz == 16) {
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->cmd		= MBOXCMD_EXTPTHRU;
18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_prepare_epthru(adapter, scb, scp);
18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_lo	= (uint32_t)ccb->epthru_dma_h;
18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_hi	= 0;
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->xferaddr		= 0xFFFFFFFF;
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->cmd = MBOXCMD_PASSTHRU64;
18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_prepare_pthru(adapter, scb, scp);
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_lo	= (uint32_t)ccb->pthru_dma_h;
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox64->xferaddr_hi	= 0;
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->xferaddr		= 0xFFFFFFFF;
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return scb;
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// NOT REACHED
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_runpendq - execute commands queued in the pending queue
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: controller's soft state
1903a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scb_q	: SCB to be queued in the pending list
19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1905a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Scan the pending list for commands which are not yet issued and try to
19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * post to the controller. The SCB can be a null pointer, which would indicate
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * no SCB to be queue, just try to execute the ones in the pending list.
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: We do not actually traverse the pending list. The SCBs are plucked
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * out from the head of the pending list. If it is successfully issued, the
19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * next SCB is at the head now.
19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q)
19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (scb_q) {
19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb_q->state = SCB_PENDQ;
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_add_tail(&scb_q->list, &adapter->pend_list);
19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// if the adapter in not in quiescent mode, post the commands to FW
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->quiescent) {
19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!list_empty(&adapter->pend_list)) {
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		assert_spin_locked(PENDING_LIST_LOCK(adapter));
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb = list_entry(adapter->pend_list.next, scb_t, list);
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// remove the scb from the pending list and try to
19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// issue. If we are unable to issue it, put back in
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// the pending list and return
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del_init(&scb->list);
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// if mailbox was busy, return SCB back to pending
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// list. Make sure to add at the head, since that's
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// where it would have been removed from
19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->state = SCB_ISSUED;
19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mbox_post_cmd(adapter, scb) != 0) {
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->state = SCB_PENDQ;
19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_add(&scb->list, &adapter->pend_list);
19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter),
19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flags);
19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_prepare_pthru - prepare a command for physical devices
1978a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: pointer to controller's soft state
1979a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scb		: scsi control block
1980a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scp		: scsi command from the mid-layer
19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1982a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Prepare a command for the scsi physical devices.
19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb,
19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct scsi_cmnd *scp)
19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_passthru_t	*pthru;
19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			channel;
19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			target;
19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru	= ccb->pthru;
19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	channel	= scb->dev_channel;
19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target	= scb->dev_target;
19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout
19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->timeout		= 4;
20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->ars		= 1;
20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->islogical	= 0;
20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->channel		= 0;
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->target		= (channel << 4) | target;
20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->logdrv		= SCP2LUN(scp);
20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->reqsenselen	= 14;
20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pthru->cdblen		= scp->cmd_len;
20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201032fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori	if (scsi_bufflen(scp)) {
201132fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori		pthru->dataxferlen	= scsi_bufflen(scp);
20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->dataxferaddr	= ccb->sgl_dma_h;
20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->numsge		= megaraid_mbox_mksgl(adapter, scb);
20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->dataxferaddr	= 0;
20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->dataxferlen	= 0;
20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru->numsge		= 0;
20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_prepare_epthru - prepare a command for physical devices
2026a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: pointer to controller's soft state
2027a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scb		: scsi control block
2028a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scp		: scsi command from the mid-layer
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2030a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Prepare a command for the scsi physical devices. This rountine prepares
2031a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * commands for devices which can take extended CDBs (>10 bytes).
20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct scsi_cmnd *scp)
20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_epassthru_t	*epthru;
20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			channel;
20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			target;
20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru	= ccb->epthru;
20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	channel	= scb->dev_channel;
20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	target	= scb->dev_target;
20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->timeout		= 4;
20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->ars		= 1;
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->islogical	= 0;
20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->channel		= 0;
20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->target		= (channel << 4) | target;
20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->logdrv		= SCP2LUN(scp);
20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->reqsenselen	= 14;
20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epthru->cdblen		= scp->cmd_len;
20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(epthru->cdb, scp->cmnd, scp->cmd_len);
20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
205932fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori	if (scsi_bufflen(scp)) {
206032fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori		epthru->dataxferlen	= scsi_bufflen(scp);
20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->dataxferaddr	= ccb->sgl_dma_h;
20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->numsge		= megaraid_mbox_mksgl(adapter, scb);
20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->dataxferaddr	= 0;
20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->dataxferlen	= 0;
20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru->numsge		= 0;
20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs
2075a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: controller's soft state
20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2077a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Interrupt acknowledgement sequence for memory mapped HBAs. Find out the
20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * completed command and put them on the completed list for later processing.
20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:	1 if the interrupt is valid, 0 otherwise
20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2082858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_ack_sequence(adapter_t *adapter)
20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			nstatus;
20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			completed[MBOX_MAX_FIRMWARE_STATUS];
20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head	clist;
20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			handled;
20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint32_t		dword;
20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i, j;
20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= raid_dev->mbox;
20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// move the SCBs from the firmware completed array to our local list
21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&clist);
21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// loop till F/W has more commands for us to complete
21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	handled = 0;
21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags);
21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Check if a valid interrupt is pending. If found, force the
21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * interrupt line low.
21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dword = RDOUTDOOR(raid_dev);
21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dword != 0x10001234) break;
21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		handled = 1;
21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		WROUTDOOR(raid_dev, 0x10001234);
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nstatus = 0;
21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// wait for valid numstatus to post
21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < 0xFFFFF; i++) {
21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (mbox->numstatus != 0xFF) {
21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				nstatus = mbox->numstatus;
21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->numstatus = 0xFF;
21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->outstanding_cmds -= nstatus;
21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < nstatus; i++) {
21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// wait for valid command index to post
21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (j = 0; j < 0xFFFFF; j++) {
21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (mbox->completed[i] != 0xFF) break;
21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rmb();
21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			completed[i]		= mbox->completed[i];
21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mbox->completed[i]	= 0xFF;
21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (completed[i] == 0xFF) {
21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_CRIT
21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: command posting timed out\n"));
21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				BUG();
21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Get SCB associated with this command id
21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (completed[i] >= MBOX_MAX_SCSI_CMDS) {
21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// a cmm command
21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb = adapter->uscb_list + (completed[i] -
21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						MBOX_MAX_SCSI_CMDS);
21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// an os command
21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb = adapter->kscb_list + completed[i];
21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->status = mbox->status;
21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_add_tail(&scb->list, &clist);
21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Acknowledge interrupt
21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		WRINDOOR(raid_dev, 0x02);
21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while(1);
21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// put the completed commands in the completed list. DPC would
21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// complete these commands later
21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_splice(&clist, &adapter->completed_list);
21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// schedule the DPC if there is some work for it
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (handled)
21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tasklet_schedule(&adapter->dpc_h);
21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return handled;
21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_isr - isr for memory based mailbox based controllers
2190a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @irq		: irq
2191a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @devp	: pointer to our soft state
21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Interrupt service routine for memory-mapped mailbox controllers.
21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t
21967d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsmegaraid_isr(int irq, void *devp)
21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = devp;
21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		handled;
22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	handled = megaraid_ack_sequence(adapter);
22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Loop through any pending requests */
22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter->quiescent) {
22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_mbox_runpendq(adapter, NULL);
22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_RETVAL(handled);
22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_sync_scb - sync kernel buffers
22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: controller's soft state
22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		: pointer to the resource packet
22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMA sync if required.
22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2219858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic void
22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb)
22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t	*ccb;
22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
222632fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori	if (scb->dma_direction == PCI_DMA_FROMDEVICE)
222732fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori		pci_dma_sync_sg_for_cpu(adapter->pdev,
222832fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori					scsi_sglist(scb->scp),
222932fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori					scsi_sg_count(scb->scp),
22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					PCI_DMA_FROMDEVICE);
22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
223232fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori	scsi_dma_unmap(scb->scp);
22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_dpc - the tasklet to complete the commands from completed list
22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @devp	: pointer to HBA soft state
22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pick up the commands from the completed list and send back to the owners.
22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a reentrant function and does not assume any locks are held while
22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it is being called.
22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
22451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_dpc(unsigned long devp)
22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t		*adapter = (adapter_t *)devp;
22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev;
22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head	clist;
22511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scatterlist	*sgl;
22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*tmp;
22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scsi_cmnd	*scp;
22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_passthru_t	*pthru;
22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_epassthru_t	*epthru;
22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			islogical;
22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			pdev_index;
22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			pdev_state;
22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			c;
22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			status;
2265c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	uioc_t			*kioc;
22661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter) return;
22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev = ADAP2RAIDDEV(adapter);
22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// move the SCBs from the completed list to our local list
22731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&clist);
22741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
22761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_splice_init(&adapter->completed_list, &clist);
22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
22801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry_safe(scb, tmp, &clist, list) {
22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status		= scb->status;
22851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scp		= scb->scp;
22861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb		= (mbox_ccb_t *)scb->ccb;
22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pthru		= ccb->pthru;
22881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		epthru		= ccb->epthru;
22891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox		= ccb->mbox;
22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Make sure f/w has completed a valid command
22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->state != SCB_ISSUED) {
22931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_CRIT
22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid critical err: invalid command %d:%d:%p\n",
22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scb->sno, scb->state, scp));
22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BUG();
22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;	// Must never happen!
22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// check for the management command and complete it right away
23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->sno >= MBOX_MAX_SCSI_CMDS) {
23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->state	= SCB_FREE;
23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->status	= status;
23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// remove from local clist
23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_del_init(&scb->list);
23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2308c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			kioc			= (uioc_t *)scb->gp;
2309c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			kioc->status		= 0;
2310c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann
23111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_mm_done(adapter, scb);
23121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Was an abort issued for this command earlier
23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->state & SCB_ABORT) {
23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
23195cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig			"megaraid: aborted cmd [%x] completed\n",
23205cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig				scb->sno));
23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
23221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
23241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the inquiry came of a disk drive which is not part of
23251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * any RAID array, expose it to the kernel. For this to be
23261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * enabled, user must set the "megaraid_expose_unconf_disks"
23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * flag to 1 by specifying it on module parameter list.
23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * This would enable data migration off drives from other
23291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * configurations.
23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		islogical = MRAID_IS_LOGICAL(adapter, scp);
23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0
23331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				&& IS_RAID_CH(raid_dev, scb->dev_channel)) {
23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
233532fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori			sgl = scsi_sglist(scp);
233645711f1af6eff1a6d010703b4862e0d2b9afd056Jens Axboe			if (sg_page(sgl)) {
233745711f1af6eff1a6d010703b4862e0d2b9afd056Jens Axboe				c = *(unsigned char *) sg_virt(&sgl[0]);
233832fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori			} else {
233932fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori				con_log(CL_ANN, (KERN_WARNING
234032fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori						 "megaraid mailbox: invalid sg:%d\n",
234132fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori						 __LINE__));
234232fbac2256cedee62de5602b1703c15c150a6e14FUJITA Tomonori				c = 0;
23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((c & 0x1F ) == TYPE_DISK) {
23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pdev_index = (scb->dev_channel * 16) +
23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scb->dev_target;
23481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pdev_state =
23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					raid_dev->pdrv_state[pdev_index] & 0x0F;
23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (pdev_state == PDRV_ONLINE		||
23521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pdev_state == PDRV_FAILED	||
23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pdev_state == PDRV_RBLD		||
23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pdev_state == PDRV_HOTSPARE	||
23551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					megaraid_expose_unconf_disks == 0) {
23561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					status = 0xF0;
23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
23591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
23601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Convert MegaRAID status to Linux error code
23631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (status) {
23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x00:
23661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_OK << 16);
23681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
23691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x02:
23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* set sense_buffer and result fields */
23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (mbox->cmd == MBOXCMD_PASSTHRU ||
23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mbox->cmd == MBOXCMD_PASSTHRU64) {
23751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(scp->sense_buffer, pthru->reqsensearea,
23771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						14);
23781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = DRIVER_SENSE << 24 |
23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					DID_OK << 16 | CHECK_CONDITION << 1;
23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
23831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (mbox->cmd == MBOXCMD_EXTPTHRU) {
23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					memcpy(scp->sense_buffer,
23861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						epthru->reqsensearea, 14);
23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scp->result = DRIVER_SENSE << 24 |
23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						DID_OK << 16 |
23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						CHECK_CONDITION << 1;
23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scp->sense_buffer[0] = 0x70;
23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scp->sense_buffer[2] = ABORTED_COMMAND;
23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scp->result = CHECK_CONDITION << 1;
23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x08:
24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = DID_BUS_BUSY << 16 | status;
24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * If TEST_UNIT_READY fails, we know RESERVATION_STATUS
24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * failed
24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (scp->cmnd[0] == TEST_UNIT_READY) {
24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = DID_ERROR << 16 |
24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					RESERVATION_CONFLICT << 1;
24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Error code returned is 1 if Reserve or Release
24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * failed or the input parameter is invalid
24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (status == 1 && (scp->cmnd[0] == RESERVE ||
24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 scp->cmnd[0] == RELEASE)) {
24211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = DID_ERROR << 16 |
24231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					RESERVATION_CONFLICT << 1;
24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				scp->result = DID_BAD_TARGET << 16 | status;
24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
24291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// print a debug message for all failed commands
24311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status) {
24321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_display_scb(adapter, scb);
24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Free our internal resources and call the mid-layer callback
24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// routine
24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_mbox_sync_scb(adapter, scb);
24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// remove from local clist
24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del_init(&scb->list);
24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// put back in free list
24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_dealloc_scb(adapter, scb);
24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// send the scsi packet back to kernel
24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scp->scsi_done(scp);
24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_abort_handler - abort the scsi command
24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scp		: command to be aborted
24561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
24571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Abort a previous SCSI request. Only commands on the pending list can be
24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aborted. All the commands issued to the F/W must complete.
24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2461f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwigmegaraid_abort_handler(struct scsi_cmnd *scp)
24621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t		*adapter;
24641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev;
24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*tmp;
24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			found;
24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter		= SCP2ADAPTER(scp);
24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev	= ADAP2RAIDDEV(adapter);
24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_WARNING
24765cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig		"megaraid: aborting cmd=%x <c=%d t=%d l=%d>\n",
24775cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig		scp->cmnd[0], SCP2CHANNEL(scp),
24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		SCP2TARGET(scp), SCP2LUN(scp)));
24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// If FW has stopped responding, simply return failure
24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->hw_error) {
24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: hw error, not aborting\n"));
24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return FAILED;
24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// There might a race here, where the command was completed by the
24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// firmware and now it is on the completed list. Before we could
24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// complete the command to the kernel in dpc, the abort came.
24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Find out if this is the case to avoid the race.
24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb = NULL;
24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry_safe(scb, tmp, &adapter->completed_list, list) {
24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->scp == scp) {	// Found command
24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_del_init(&scb->list);	// from completed list
24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_WARNING
25005cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig			"megaraid: %d[%d:%d], abort from completed list\n",
25015cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig				scb->sno, scb->dev_channel, scb->dev_target));
25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_ABORT << 16);
25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->scsi_done(scp);
25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_dealloc_scb(adapter, scb);
25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter),
25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flags);
25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SUCCESS;
25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Find out if this command is still on the pending list. If it is and
25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// was never issued, abort and return success. If the command is owned
25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// by the firmware, we must wait for it to complete by the FW.
25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->scp == scp) {	// Found command
25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			list_del_init(&scb->list);	// from pending list
25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ASSERT(!(scb->state & SCB_ISSUED));
25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_WARNING
25305cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig				"megaraid abort: [%d:%d], driver owner\n",
25315cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig				scb->dev_channel, scb->dev_target));
25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->result = (DID_ABORT << 16);
25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scp->scsi_done(scp);
25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_dealloc_scb(adapter, scb);
25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter),
25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flags);
25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return SUCCESS;
25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Check do we even own this command, in which case this would be
25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// owned by the firmware. The only way to locate the FW scb is to
25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// traverse through the list of all SCB, since driver does not
25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// maintain these SCBs on any list
25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	found = 0;
2552f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_lock_irq(&adapter->lock);
25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb = adapter->kscb_list + i;
25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (scb->scp == scp) {
25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			found = 1;
25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(scb->state & SCB_ISSUED)) {
25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_WARNING
25625cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig				"megaraid abort: %d[%d:%d], invalid state\n",
25635cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig				scb->sno, scb->dev_channel, scb->dev_target));
25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				BUG();
25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (KERN_WARNING
25685cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig				"megaraid abort: %d[%d:%d], fw owner\n",
25695cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig				scb->sno, scb->dev_channel, scb->dev_target));
25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2573f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_unlock_irq(&adapter->lock);
25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!found) {
25765cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig		con_log(CL_ANN, (KERN_WARNING "megaraid abort: do now own\n"));
25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// FIXME: Should there be a callback for this command?
25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return SUCCESS;
25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// We cannot actually abort a command owned by firmware, return
25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// failure and wait for reset. In host reset handler, we will find out
25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// if the HBA is still live
25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return FAILED;
25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_reset_handler - device reset hadler for mailbox based driver
25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scp		: reference command
25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reset handler for the mailbox based controller. First try to find out if
25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the FW is still live, in which case the outstanding commands counter mut go
25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * down to 0. If that happens, also issue the reservation reset command to
25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * relinquish (possible) reservations on the logical drives connected to this
2596a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * host.
25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/
25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2599f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwigmegaraid_reset_handler(struct scsi_cmnd *scp)
26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter;
26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t		*scb;
26031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t		*tmp;
26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev;
26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	flags;
26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		recovery_window;
26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		recovering;
26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
2611c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	uioc_t		*kioc;
26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter		= SCP2ADAPTER(scp);
26141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev	= ADAP2RAIDDEV(adapter);
26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// return failure if adapter is not responding
26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->hw_error) {
26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: hw error, cannot reset\n"));
26201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return FAILED;
26211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
26221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Under exceptional conditions, FW can take up to 3 minutes to
26251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// complete command processing. Wait for additional 2 minutes for the
26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// pending commands counter to go down to 0. If it doesn't, let the
26271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// controller be marked offline
26281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Also, reset all the commands currently owned by the driver
26291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
26311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del_init(&scb->list);	// from pending list
26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2633c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		if (scb->sno >= MBOX_MAX_SCSI_CMDS) {
2634c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			con_log(CL_ANN, (KERN_WARNING
2635c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			"megaraid: IOCTL packet with %d[%d:%d] being reset\n",
2636c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			scb->sno, scb->dev_channel, scb->dev_target));
26371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2638c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			scb->status = -1;
26391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2640c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			kioc			= (uioc_t *)scb->gp;
2641c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			kioc->status		= -EFAULT;
2642c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann
2643c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			megaraid_mbox_mm_done(adapter, scb);
2644c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		} else {
2645c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			if (scb->scp == scp) {	// Found command
2646c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				con_log(CL_ANN, (KERN_WARNING
26475cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig					"megaraid: %d[%d:%d], reset from pending list\n",
26485cd049a59913f359e7d30c11d2dc6187822e77b1Christoph Hellwig					scb->sno, scb->dev_channel, scb->dev_target));
2649c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			} else {
2650c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				con_log(CL_ANN, (KERN_WARNING
2651c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				"megaraid: IO packet with %d[%d:%d] being reset\n",
2652c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				scb->sno, scb->dev_channel, scb->dev_target));
2653c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			}
2654c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann
2655c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			scb->scp->result = (DID_RESET << 16);
2656c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			scb->scp->scsi_done(scb->scp);
2657c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann
2658c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			megaraid_dealloc_scb(adapter, scb);
2659c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		}
26601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
26611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
26621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->outstanding_cmds) {
26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
26651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: %d outstanding commands. Max wait %d sec\n",
2666c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			adapter->outstanding_cmds,
2667c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann			(MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT)));
26681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
26691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
26711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	recovering = adapter->outstanding_cmds;
26731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2674c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	for (i = 0; i < recovery_window; i++) {
26751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_ack_sequence(adapter);
26771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// print a message once every 5 seconds only
26791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(i % 5)) {
26801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (
26811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: Wait for %d commands to complete:%d\n",
26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				adapter->outstanding_cmds,
2683c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann				(MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT) - i));
26841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
26851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
268625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		// bailout if no recovery happened in reset time
2687c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		if (adapter->outstanding_cmds == 0) {
26881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
26891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
26901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(1000);
26921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
26931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2694f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_lock(&adapter->lock);
26951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// If still outstanding commands, bail out
26971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->outstanding_cmds) {
26981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
26991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: critical hardware error!\n"));
27001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		raid_dev->hw_error = 1;
27021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2703f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig		rval = FAILED;
2704f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig		goto out;
27051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
27071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
2708af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa		"megaraid mbox: reset sequence completed successfully\n"));
27091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// If the controller supports clustering, reset reservations
2713f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	if (!adapter->ha) {
2714f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig		rval = SUCCESS;
2715f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig		goto out;
2716f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	}
27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// clear reservations if any
27191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = CLUSTER_CMD;
27201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = RESET_RESERVATIONS;
27211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval = SUCCESS;
27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd_fast(adapter, raw_mbox) == 0) {
27241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN,
27251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(KERN_INFO "megaraid: reservation reset\n"));
27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
27281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval = FAILED;
27291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: reservation reset failed\n"));
27311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2733f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig out:
2734f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_unlock_irq(&adapter->lock);
27351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
27361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
27391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * START: internal commands library
27401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
27411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This section of the driver has the common routine used by the driver and
27421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * also has all the FW routines
27431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
27461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mbox_post_sync_cmd() - blocking command to the mailbox based controllers
2747a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: controller's soft state
2748a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @raw_mbox	: the mailbox
27491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issue a scb in synchronous and non-interrupt mode for mailbox based
2751a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * controllers.
27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
27531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[])
27551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
27571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t	*mbox64;
27581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
27591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		status;
27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
27611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64	= raid_dev->mbox64;
27641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= raid_dev->mbox;
27651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
27671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Wait until mailbox is free
27681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
27691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (megaraid_busywait_mbox(raid_dev) != 0)
27701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto blocked_mailbox;
27711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
27731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Copy mailbox data into host structure
27741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
27751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16);
27761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->cmdid		= 0xFE;
27771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->busy		= 1;
27781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->poll		= 0;
27791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->ack		= 0;
27801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->numstatus		= 0xFF;
27811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->status		= 0xFF;
27821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
27841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
27851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// wait for maximum 1 second for status to post. If the status is not
27871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// available within 1 second, assume FW is initializing and wait
27881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// for an extended amount of time
27891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox->numstatus == 0xFF) {	// status not yet available
279053b3531bbbf70ac7551b32d1acc229d94de52658Alexey Dobriyan		udelay(25);
27911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; mbox->numstatus == 0xFF && i < 1000; i++) {
27931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
27941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
27951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
27961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == 1000) {
27991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
28001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mailbox: wait for FW to boot      "));
28011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; (mbox->numstatus == 0xFF) &&
28031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(i < MBOX_RESET_WAIT); i++) {
28041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rmb();
28051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, ("\b\b\b\b\b[%03d]",
28061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							MBOX_RESET_WAIT - i));
28071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				msleep(1000);
28081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
28091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (i == MBOX_RESET_WAIT) {
28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				con_log(CL_ANN, (
28131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"\nmegaraid mailbox: status not available\n"));
28141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -1;
28161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
28171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, ("\b\b\b\b\b[ok] \n"));
28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// wait for maximum 1 second for poll semaphore
28221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox->poll != 0x77) {
28231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(25);
28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; (mbox->poll != 0x77) && (i < 1000); i++) {
28261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
28271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
28281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == 1000) {
28311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_WARNING
28321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mailbox: could not get poll semaphore\n"));
28331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -1;
28341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2);
28381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
28391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// wait for maximum 1 second for acknowledgement
28411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (RDINDOOR(raid_dev) & 0x2) {
28421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(25);
28431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; (RDINDOOR(raid_dev) & 0x2) && (i < 1000); i++) {
28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rmb();
28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == 1000) {
28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_WARNING
28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mailbox: could not acknowledge\n"));
28521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -1;
28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
28541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->poll	= 0;
28561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->ack	= 0x77;
28571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = mbox->status;
28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// invalidate the completed command id array. After command
28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// completion, firmware would write the valid id.
28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->numstatus	= 0xFF;
28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->status	= 0xFF;
28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_FIRMWARE_STATUS; i++) {
28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->completed[i] = 0xFF;
28661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return status;
28691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsblocked_mailbox:
28711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n") );
28731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
28741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers
2879a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: controller's soft state
2880a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @raw_mbox	: the mailbox
28811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issue a scb in synchronous and non-interrupt mode for mailbox based
28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controllers. This is a faster version of the synchronous command and
2884a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * therefore can be called in interrupt-context as well.
28851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
28861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
28901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
28911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long		i;
28921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= raid_dev->mbox;
28951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// return immediately if the mailbox is busy
28971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox->busy) return -1;
28981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Copy mailbox data into host structure
29001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 14);
29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->cmdid		= 0xFE;
29021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->busy		= 1;
29031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->poll		= 0;
29041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->ack		= 0;
29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->numstatus		= 0xFF;
29061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->status		= 0xFF;
29071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
29091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
29101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	for (i = 0; i < MBOX_SYNC_WAIT_CNT; i++) {
29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mbox->numstatus != 0xFF) break;
2913ed7e8ef7f12f5c3c8bbb85eeb0a1ded91c7c5dbfJu, Seokmann		rmb();
2914c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann		udelay(MBOX_SYNC_DELAY_200);
29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2917c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	if (i == MBOX_SYNC_WAIT_CNT) {
29181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// We may need to re-calibrate the counter
29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_CRIT
29201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: fast sync command timed out\n"));
29211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2);
29241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
29251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mbox->status;
29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
29311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_busywait_mbox() - Wait until the controller's mailbox is available
2932a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @raid_dev	: RAID device (HBA) soft state
29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2934a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Wait until the controller's mailbox is available to accept more commands.
2935a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Wait for at most 1 second.
29361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_busywait_mbox(mraid_device_t *raid_dev)
29391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t	*mbox = raid_dev->mbox;
29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	i = 0;
29421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox->busy) {
29441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(25);
29451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; mbox->busy && i < 1000; i++)
29461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
29471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (i < 1000) return 0;
29501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else return -1;
29511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_product_info - some static information about the controller
2956a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: our soft state
29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2958a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Issue commands to the controller to grab some parameters required by our
29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * caller.
29601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
29621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_product_info(adapter_t *adapter)
29631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			raw_mbox[sizeof(mbox_t)];
29671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_pinfo_t		*pinfo;
29681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dma_addr_t		pinfo_dma_h;
29691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_inquiry3_t	*mraid_inq3;
29701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
29711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
29741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
29751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
29771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Issue an ENQUIRY3 command to find out certain adapter parameters,
29781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * e.g., max channels, max commands etc.
29791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
29801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pinfo = pci_alloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
29811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&pinfo_dma_h);
29821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pinfo == NULL) {
29841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
2985cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison			"megaraid: out of memory, %s %d\n", __func__,
29861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
29871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
29891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(pinfo, 0, sizeof(mraid_pinfo_t));
29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
29931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
29941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FC_NEW_CONFIG;
29961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = NC_SUBOP_ENQUIRY3;
29971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[3] = ENQ3_GET_SOLICITED_FULL;
29981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command
30001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
30011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING "megaraid: Inquiry3 failed\n"));
30031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
30051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pinfo, pinfo_dma_h);
30061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
30081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Collect information about state of each physical drive
30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * attached to the controller. We will expose all the disks
30131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * which are not part of RAID
30141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_inq3 = (mraid_inquiry3_t *)adapter->ibuf;
30161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_PHYSICAL_DRIVES; i++) {
30171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		raid_dev->pdrv_state[i] = mraid_inq3->pdrv_state[i];
30181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Get product info for information like number of channels,
30221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * maximum commands supported.
30231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
30251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)pinfo_dma_h;
30261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FC_NEW_CONFIG;
30281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = NC_SUBOP_PRODUCT_INFO;
30291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
30311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
30331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: product info failed\n"));
30341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
30361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pinfo, pinfo_dma_h);
30371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
30391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
30401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Setup some parameters for host, as required by our caller
30431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_channel = pinfo->nchannels;
30451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * we will export all the logical drives on a single channel.
30481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Add 1 since inquires do not come for inititor ID
30491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_target	= MAX_LOGICAL_DRIVES_40LD + 1;
30511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_lun	= 8;	// up to 8 LUNs for non-disk devices
30521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
30541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * These are the maximum outstanding commands for the scsi-layer
30551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
30561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->max_cmds	= MBOX_MAX_SCSI_CMDS;
30571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(adapter->fw_version, 0, VERSION_SIZE);
30591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(adapter->bios_version, 0, VERSION_SIZE);
30601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(adapter->fw_version, pinfo->fw_version, 4);
30621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->fw_version[4] = 0;
30631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(adapter->bios_version, pinfo->bios_version, 4);
30651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->bios_version[4] = 0;
30661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(CL_ANN, (KERN_NOTICE
30681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid: fw version:[%s] bios version:[%s]\n",
30691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->fw_version, adapter->bios_version));
30701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), pinfo,
30721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pinfo_dma_h);
30731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
30751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
30761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
30801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_extended_cdb - check for support for extended CDBs
3081a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: soft state for the controller
30821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3083a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * This routine check whether the controller in question supports extended
3084a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * ( > 10 bytes ) CDBs.
30851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
30861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
30871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_extended_cdb(adapter_t *adapter)
30881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
30891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
30901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
30911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
30921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
30941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
30961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr	= (uint32_t)adapter->ibuf_dma_h;
30971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
30991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = MAIN_MISC_OPCODE;
31011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = SUPPORT_EXT_CDB;
31021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
31041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Issue the command
31051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
31061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval = 0;
31071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
31081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval = -1;
31091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
31101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
31121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
31161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_support_ha - Do we support clustering
3117a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: soft state for the controller
3118a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @init_id	: ID of the initiator
31191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine if the firmware supports clustering and the ID of the initiator.
31211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
31221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
31231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id)
31241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
31261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
31271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
31281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
31311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
31331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
31351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
31371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = GET_TARGET_ID;
31391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command
31411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*init_id = 7;
31421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval =  -1;
31431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
31441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*init_id = *(uint8_t *)adapter->ibuf;
31461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_INFO
31481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: cluster firmware, initiator ID: %d\n",
31491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*init_id));
31501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval =  0;
31521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
31531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
31551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
31591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_support_random_del - Do we support random deletion
3160a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: soft state for the controller
31611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3162a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Determine if the firmware supports random deletion.
31631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return:	1 is operation supported, 0 otherwise
31641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
31651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
31661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_support_random_del(adapter_t *adapter)
31671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
31691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
31701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
31711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
317269cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	/*
317369cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	 * Newer firmware on Dell CERC expect a different
317469cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	 * random deletion handling, so disable it.
317569cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	 */
317669cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	if (adapter->pdev->vendor == PCI_VENDOR_ID_AMI &&
317769cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	    adapter->pdev->device == PCI_DEVICE_ID_AMI_MEGARAID3 &&
317869cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	    adapter->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
317969cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	    adapter->pdev->subsystem_device == PCI_SUBSYS_ID_CERC_ATA100_4CH &&
318069cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	    (adapter->fw_version[0] > '6' ||
318169cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	     (adapter->fw_version[0] == '6' &&
318269cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	      adapter->fw_version[2] > '6') ||
318369cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	     (adapter->fw_version[0] == '6'
318469cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	      && adapter->fw_version[2] == '6'
318569cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	      && adapter->fw_version[3] > '1'))) {
318669cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke		con_log(CL_DLEVEL1, ("megaraid: disable random deletion\n"));
318769cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke		return 0;
318869cd39e94669e2994277a29249b6ef93b088ddbbHannes Reinecke	}
31891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
31911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
31931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FC_DEL_LOGDRV;
31951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = OP_SUP_DEL_LOGDRV;
31961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command
31981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval = 0;
31991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
32001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_DLEVEL1, ("megaraid: supports random deletion\n"));
32021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval =  1;
32041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
32071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
32111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware
3212a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: soft state for the controller
32131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
32141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find out the maximum number of scatter-gather elements supported by the
3215a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * firmware.
32161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
32171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
32181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_get_max_sg(adapter_t *adapter)
32191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
32211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
32221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		nsg;
32231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
32261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
32281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
32301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
32321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = MAIN_MISC_OPCODE;
32341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = GET_MAX_SG_SUPPORT;
32351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command
32371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
32381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nsg =  *(uint8_t *)adapter->ibuf;
32391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
32411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nsg =  MBOX_DEFAULT_SG_SIZE;
32421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nsg > MBOX_MAX_SG_SIZE) nsg = MBOX_MAX_SG_SIZE;
32451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return nsg;
32471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
32511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels
3252a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: soft state for the controller
32531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3254a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Enumerate the RAID and SCSI channels for ROMB platforms so that channels
3255a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * can be exported as regular SCSI channels.
32561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
32571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
32581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_enum_raid_scsi(adapter_t *adapter)
32591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
32611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t		*mbox;
32621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		raw_mbox[sizeof(mbox_t)];
32631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
32661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
32681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
32701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
32721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = CHNL_CLASS;
32741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = GET_CHNL_CLASS;
32751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Issue the command. If the command fails, all channels are RAID
32771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// channels
32781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->channel_class = 0xFF;
32791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
32801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		raid_dev->channel_class =  *(uint8_t *)adapter->ibuf;
32811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
32841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
32881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_flush_cache - flush adapter and disks cache
3289a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: soft state for the controller
32901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3291a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Flush adapter cache followed by disks cache.
32921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
32931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
32941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_flush_cache(adapter_t *adapter)
32951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t	*mbox;
32971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t	raw_mbox[sizeof(mbox_t)];
32981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox = (mbox_t *)raw_mbox;
33011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
33031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FLUSH_ADAPTER;
33051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
33071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, ("megaraid: flush adapter failed\n"));
33081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
33091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FLUSH_SYSTEM;
33111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
33131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, ("megaraid: flush disks cache failed\n"));
33141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
33151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
33171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
33181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3321cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro * megaraid_mbox_fire_sync_cmd - fire the sync cmd
3322a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: soft state for the controller
3323cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro *
3324a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Clears the pending cmds in FW and reinits its RAID structs.
3325cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro */
3326cd96d96f20f2509dfeb302548132e30f471c071aSumant Patrostatic int
3327cd96d96f20f2509dfeb302548132e30f471c071aSumant Patromegaraid_mbox_fire_sync_cmd(adapter_t *adapter)
3328cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro{
3329cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox_t	*mbox;
3330cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	uint8_t	raw_mbox[sizeof(mbox_t)];
3331cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
3332cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox64_t *mbox64;
3333cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	int	status = 0;
3334cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	int i;
3335cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	uint32_t dword;
3336cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3337cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox = (mbox_t *)raw_mbox;
3338cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3339cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
3340cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3341cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	raw_mbox[0] = 0xFF;
3342cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3343cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox64	= raid_dev->mbox64;
3344cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox	= raid_dev->mbox;
3345cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3346cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	/* Wait until mailbox is free */
3347cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	if (megaraid_busywait_mbox(raid_dev) != 0) {
3348cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		status = 1;
3349cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		goto blocked_mailbox;
3350cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	}
3351cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3352cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	/* Copy mailbox data into host structure */
3353cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16);
3354cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox->cmdid		= 0xFE;
3355cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox->busy		= 1;
3356cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox->poll		= 0;
3357cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox->ack		= 0;
3358cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox->numstatus		= 0;
3359cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	mbox->status		= 0;
3360cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3361cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	wmb();
3362cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
3363cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3364cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	/* Wait for maximum 1 min for status to post.
3365cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 * If the Firmware SUPPORTS the ABOVE COMMAND,
3366cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 * mbox->cmd will be set to 0
3367cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 * else
3368cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 * the firmware will reject the command with
3369cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 * mbox->numstatus set to 1
3370cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	 */
3371cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3372cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	i = 0;
3373cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	status = 0;
3374cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	while (!mbox->numstatus && mbox->cmd == 0xFF) {
3375cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		rmb();
3376cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		msleep(1);
3377cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		i++;
3378cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		if (i > 1000 * 60) {
3379cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro			status = 1;
3380cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro			break;
3381cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		}
3382cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	}
3383cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	if (mbox->numstatus == 1)
3384cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro		status = 1; /*cmd not supported*/
3385cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3386cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	/* Check for interrupt line */
3387cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	dword = RDOUTDOOR(raid_dev);
3388cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	WROUTDOOR(raid_dev, dword);
3389cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	WRINDOOR(raid_dev,2);
3390cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3391cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	return status;
3392cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3393cd96d96f20f2509dfeb302548132e30f471c071aSumant Patroblocked_mailbox:
3394cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n"));
3395cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro	return status;
3396cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro}
3397cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro
3398cd96d96f20f2509dfeb302548132e30f471c071aSumant Patro/**
33991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_display_scb - display SCB information, mostly debug purposes
3400a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: controller's soft state
3401a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @scb			: SCB to be displayed
3402a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @level		: debug level for console print
34031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
34041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Diplay information about the given SCB iff the current debug level is
3405a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * verbose.
34061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
34071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
34081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb)
34091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
34101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
34111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scsi_cmnd	*scp;
34121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
34131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			level;
34141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
34151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb	= (mbox_ccb_t *)scb->ccb;
34181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scp	= scb->scp;
34191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox	= ccb->mbox;
34201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	level = CL_DLEVEL3;
34221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(level, (KERN_NOTICE
34241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"megaraid mailbox: status:%#x cmd:%#x id:%#x ", scb->status,
34251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->cmd, scb->sno));
34261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(level, ("sec:%#x lba:%#x addr:%#x ld:%d sg:%d\n",
34281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->numsectors, mbox->lba, mbox->xferaddr, mbox->logdrv,
34291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mbox->numsge));
34301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!scp) return;
34321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(level, (KERN_NOTICE "scsi cmnd: "));
34341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < scp->cmd_len; i++) {
34361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(level, ("%#2.02x ", scp->cmnd[i]));
34371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
34381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	con_log(level, ("\n"));
34401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
34421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
34431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
34461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_setup_device_map - manage device ids
34471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: Driver's soft state
34481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
344925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * Manange the device ids to have an appropriate mapping between the kernel
34501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi addresses and megaraid scsi and logical drive addresses. We export
34511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi devices on their actual addresses, whereas the logical drives are
34521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * exported on a virtual scsi channel.
3453a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap */
34541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
34551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_setup_device_map(adapter_t *adapter)
34561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
34571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		c;
34581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t		t;
34591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
34611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * First fill the values on the logical drive channel
34621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
34631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++)
34641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->device_ids[adapter->max_channel][t] =
34651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(t < adapter->init_id) ?  t : t - 1;
34661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->device_ids[adapter->max_channel][adapter->init_id] = 0xFF;
34681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
34701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Fill the values on the physical devices channels
34711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
34721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (c = 0; c < adapter->max_channel; c++)
34731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++)
34741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adapter->device_ids[c][t] = (c << 8) | t;
34751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
34761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
34791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * END: internal commands library
34801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
34811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
34831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * START: Interface for the common management module
34841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3485b1c118121ae37285ddc0a7a908999196bb35fb0bJoe Perches * This is the module, which interfaces with the common management module to
34861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * provide support for ioctl and sysfs
34871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
34881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3490b1c118121ae37285ddc0a7a908999196bb35fb0bJoe Perches * megaraid_cmm_register - register with the management module
3491a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: HBA soft state
34921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
34931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Register with the management module, which allows applications to issue
34941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl calls to the drivers. This interface is used by the management module
34951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to setup sysfs support as well.
34961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
34971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
34981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_cmm_register(adapter_t *adapter)
34991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
35001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
35011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_mmadp_t	adp;
35021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t		*scb;
35031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t	*ccb;
35041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
35051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
35061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate memory for the base list of scb for management module.
3508dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau	adapter->uscb_list = kcalloc(MBOX_MAX_USER_CMDS, sizeof(scb_t), GFP_KERNEL);
35091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (adapter->uscb_list == NULL) {
35111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
3512cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison			"megaraid: out of memory, %s %d\n", __func__,
35131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
35141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
35151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
35161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Initialize the synchronization parameters for resources for
35191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// commands for management module
35201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&adapter->uscb_pool);
35211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(USER_FREE_LIST_LOCK(adapter));
35231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// link all the packets. Note, CCB for commands, coming from the
35271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// commom management module, mailbox physical address are already
35281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// setup by it. We just need placeholder for that in our local command
35291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// control blocks
35301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MBOX_MAX_USER_CMDS; i++) {
35311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb			= adapter->uscb_list + i;
35331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb			= raid_dev->uccb_list + i;
35341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->ccb		= (caddr_t)ccb;
35361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox64		= raid_dev->umbox64 + i;
35371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->mbox		= &ccb->mbox64->mbox32;
35381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccb->raw_mbox		= (uint8_t *)ccb->mbox;
35391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->gp			= 0;
35411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// COMMAND ID 0 - (MBOX_MAX_SCSI_CMDS-1) ARE RESERVED FOR
35431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// COMMANDS COMING FROM IO SUBSYSTEM (MID-LAYER)
35441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->sno		= i + MBOX_MAX_SCSI_CMDS;
35451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->scp		= NULL;
35471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->state		= SCB_FREE;
35481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_direction	= PCI_DMA_NONE;
35491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dma_type		= MRAID_DMA_NONE;
35501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_channel	= -1;
35511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->dev_target		= -1;
35521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// put scb in the free pool
35541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_add_tail(&scb->list, &adapter->uscb_pool);
35551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
35561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.unique_id		= adapter->unique_id;
35581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.drvr_type		= DRVRTYPE_MBOX;
35591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.drvr_data		= (unsigned long)adapter;
35601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.pdev		= adapter->pdev;
35611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.issue_uioc		= megaraid_mbox_mm_handler;
3562c005fb4fb2d23ba29ad21dee5042b2f8451ca8baJu, Seokmann	adp.timeout		= MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
35631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adp.max_kioc		= MBOX_MAX_USER_CMDS;
35641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((rval = mraid_mm_register_adp(&adp)) != 0) {
35661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
35681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: did not register with CMM\n"));
35691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(adapter->uscb_list);
35711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
35721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
35741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
35751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3578b1c118121ae37285ddc0a7a908999196bb35fb0bJoe Perches * megaraid_cmm_unregister - un-register with the management module
3579a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: HBA soft state
35801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
35811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Un-register with the management module.
35821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: mgmt module must return failure for unregister if it has pending
3583a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * commands in LLD.
35841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
35851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
35861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_cmm_unregister(adapter_t *adapter)
35871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
35881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(adapter->uscb_list);
35891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_mm_unregister_adp(adapter->unique_id);
35901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
35911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
35921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
35951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD
3596a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @drvr_data		: LLD specific data
3597a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @kioc		: CMM interface packet
3598a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @action		: command action
35991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3600b1c118121ae37285ddc0a7a908999196bb35fb0bJoe Perches * This routine is invoked whenever the Common Management Module (CMM) has a
36011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command for us. The 'action' parameter specifies if this is a new command
36021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or otherwise.
36031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
36041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
36051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action)
36061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
36071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t *adapter;
36081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (action != IOCTL_ISSUE) {
36101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
36111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: unsupported management action:%#2x\n",
36121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			action));
36131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-ENOTSUPP);
36141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
36151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter = (adapter_t *)drvr_data;
36171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// make sure this adapter is not being detached right now.
36191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (atomic_read(&adapter->being_detached)) {
36201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
36211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: reject management request, detaching\n"));
36221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-ENODEV);
36231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
36241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (kioc->opcode) {
36261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case GET_ADAP_INFO:
36281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kioc->status =  gather_hbainfo(adapter, (mraid_hba_info_t *)
36301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(unsigned long)kioc->buf_vaddr);
36311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kioc->done(kioc);
36331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return kioc->status;
36351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MBOX_CMD:
36371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return megaraid_mbox_mm_command(adapter, kioc);
36391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
36411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kioc->status = (-EINVAL);
36421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kioc->done(kioc);
36431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EINVAL);
36441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
36451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;	// not reached
36471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
36481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
36501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_mm_command - issues commands routed through CMM
3651a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: HBA soft state
3652a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @kioc		: management command packet
36531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
36541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issues commands, which are routed through the management module.
36551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
36561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
36571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_mm_command(adapter_t *adapter, uioc_t *kioc)
36581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
36591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head	*head = &adapter->uscb_pool;
36601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t		*mbox64;
36611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			*raw_mbox;
36621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb_t			*scb;
36631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_ccb_t		*ccb;
36641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
36651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// detach one scb from free pool
36671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags);
36681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (list_empty(head)) {	// should never happen because of CMM
36701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
36721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid mbox: bug in cmm handler, lost resources\n"));
36731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
36751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EINVAL);
36771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
36781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb = list_entry(head->next, scb_t, list);
36801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_del_init(&scb->list);
36811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
36831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->state		= SCB_ACTIVE;
36851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->dma_type		= MRAID_DMA_NONE;
36861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->dma_direction	= PCI_DMA_NONE;
36871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccb		= (mbox_ccb_t *)scb->ccb;
36891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64		= (mbox64_t *)(unsigned long)kioc->cmdbuf;
36901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox	= (uint8_t *)&mbox64->mbox32;
36911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(ccb->mbox64, mbox64, sizeof(mbox64_t));
36931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->gp		= (unsigned long)kioc;
36951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
36971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If it is a logdrv random delete operation, we have to wait till
36981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * there are no outstanding cmds at the fw and then issue it directly
36991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
37001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) {
37011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (wait_till_fw_empty(adapter)) {
37031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
37041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mbox: LD delete, timed out\n"));
37051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kioc->status = -ETIME;
37071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->status = -1;
37091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_mm_done(adapter, scb);
37111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-ETIME);
37131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
37141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		INIT_LIST_HEAD(&scb->list);
37161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scb->state = SCB_ISSUED;
37181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mbox_post_cmd(adapter, scb) != 0) {
37191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
37211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid mbox: LD delete, mailbox busy\n"));
37221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kioc->status = -EBUSY;
37241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			scb->status = -1;
37261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			megaraid_mbox_mm_done(adapter, scb);
37281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (-EBUSY);
37301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
37311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
37331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
37341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// put the command on the pending list and execute
37361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	megaraid_mbox_runpendq(adapter, scb);
37371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
37391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
37401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
37431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldswait_till_fw_empty(adapter_t *adapter)
37441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
37451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	flags = 0;
37461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
37471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
37501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Set the quiescent flag to stop issuing cmds to FW.
37511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3752f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_lock_irqsave(&adapter->lock, flags);
37531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->quiescent++;
3754f2c8dc402b939ddcb0299bb60227c47dc454c85aChristoph Hellwig	spin_unlock_irqrestore(&adapter->lock, flags);
37551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
37571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Wait till there are no more cmds outstanding at FW. Try for at most
37581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 60 seconds
37591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
37601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 60 && adapter->outstanding_cmds; i++) {
37611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_DLEVEL1, (KERN_INFO
37621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: FW has %d pending commands\n",
37631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adapter->outstanding_cmds));
37641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(1000);
37661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
37671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return adapter->outstanding_cmds;
37691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
37701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
37731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_mbox_mm_done - callback for CMM commands
37741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @adapter	: HBA soft state
37751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scb		: completed command
37761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
37771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Callback routine for internal commands originated from the management
37781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * module.
37791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
37801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
37811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb)
37821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
37831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc_t			*kioc;
37841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t		*mbox64;
37851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t			*raw_mbox;
37861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long		flags;
37871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kioc			= (uioc_t *)scb->gp;
37891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64			= (mbox64_t *)(unsigned long)kioc->cmdbuf;
37901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64->mbox32.status	= scb->status;
37911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox		= (uint8_t *)&mbox64->mbox32;
37921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// put scb in the free pool
37951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->state	= SCB_FREE;
37961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scb->scp	= NULL;
37971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags);
37991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_add(&scb->list, &adapter->uscb_pool);
38011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
38031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// if a delete logical drive operation succeeded, restart the
38051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// controller
38061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) {
38071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adapter->quiescent--;
38091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_mbox_runpendq(adapter, NULL);
38111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
38121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kioc->done(kioc);
38141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
38161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
38171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
38201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * gather_hbainfo - HBA characteristics for the applications
3821a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter		: HBA soft state
3822a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @hinfo		: pointer to the caller's host info strucuture
38231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
38241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
38251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo)
38261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
38271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint8_t	dmajor;
38281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dmajor			= megaraid_mbox_version[0];
38301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_vendor_id	= adapter->pdev->vendor;
38321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_device_id	= adapter->pdev->device;
38331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->subsys_vendor_id	= adapter->pdev->subsystem_vendor;
38341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->subsys_device_id	= adapter->pdev->subsystem_device;
38351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_bus		= adapter->pdev->bus->number;
38371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_dev_fn	= adapter->pdev->devfn;
38381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->pci_slot		= PCI_SLOT(adapter->pdev->devfn);
38391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->irq		= adapter->host->irq;
38401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->baseport		= ADAP2RAIDDEV(adapter)->baseport;
38411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->unique_id	= (hinfo->pci_bus << 8) | adapter->pdev->devfn;
38431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hinfo->host_no		= adapter->host->host_no;
38441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
38461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
38471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
38491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * END: Interface for the common management module
38501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
38511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
38551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_alloc_resources - allocate sysfs related resources
3856a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: controller's soft state
38571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
38581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate packets required to issue FW calls whenever the sysfs attributes
38591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are read. These attributes would require up-to-date information from the
38601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FW. Also set up resources for mutual exclusion to share these resources and
38611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the wait queue.
38621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3863a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Return 0 on success.
3864a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Return -ERROR_CODE on failure.
38651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
38661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
38671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_alloc_resources(adapter_t *adapter)
38681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
38691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
38701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval = 0;
38711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->sysfs_uioc = kmalloc(sizeof(uioc_t), GFP_KERNEL);
38731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->sysfs_mbox64 = kmalloc(sizeof(mbox64_t), GFP_KERNEL);
38751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raid_dev->sysfs_buffer = pci_alloc_consistent(adapter->pdev,
38771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			PAGE_SIZE, &raid_dev->sysfs_buffer_dma);
38781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!raid_dev->sysfs_uioc || !raid_dev->sysfs_mbox64 ||
38801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		!raid_dev->sysfs_buffer) {
38811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_WARNING
3883cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison			"megaraid: out of memory, %s %d\n", __func__,
38841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__LINE__));
38851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval = -ENOMEM;
38871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		megaraid_sysfs_free_resources(adapter);
38891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
38901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38910c2cc4337968f7aab91a91b8d5889982e3a3bd0dMatthias Kaehlcke	mutex_init(&raid_dev->sysfs_mtx);
38921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_waitqueue_head(&raid_dev->sysfs_wait_q);
38941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
38961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
38971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
39001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_free_resources - free sysfs related resources
3901a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: controller's soft state
39021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
39031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free packets allocated for sysfs FW commands
39041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
39051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
39061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_free_resources(adapter_t *adapter)
39071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
39091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3910c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl	kfree(raid_dev->sysfs_uioc);
3911c9475cb0c358ff0dd473544280d92482df491913Jesper Juhl	kfree(raid_dev->sysfs_mbox64);
39121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->sysfs_buffer) {
39141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(adapter->pdev, PAGE_SIZE,
39151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			raid_dev->sysfs_buffer, raid_dev->sysfs_buffer_dma);
39161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
39171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
39181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
39211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_get_ldmap_done - callback for get ldmap
3922a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @uioc	: completed packet
39231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
39241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Callback routine called in the ISR/tasklet context for get ldmap call
39251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
39261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
39271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_get_ldmap_done(uioc_t *uioc)
39281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = (adapter_t *)uioc->buf_vaddr;
39301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
39311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->status = 0;
39331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wake_up(&raid_dev->sysfs_wait_q);
39351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
39361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
39391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap
3940a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @data	: timed out packet
39411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
39421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Timeout routine to recover and return to application, in case the adapter
3943a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * has stopped responding. A timeout of 60 seconds for this command seems like
3944a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * a good value.
39451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
39461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
39471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_get_ldmap_timeout(unsigned long data)
39481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc_t		*uioc = (uioc_t *)data;
39501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = (adapter_t *)uioc->buf_vaddr;
39511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
39521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->status = -ETIME;
39541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wake_up(&raid_dev->sysfs_wait_q);
39561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
39571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
39601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_get_ldmap - get update logical drive map
3961a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @adapter	: controller's soft state
39621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
39631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine will be called whenever user reads the logical drive
39641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * attributes, go get the current logical drive mapping table from the
3965b1c118121ae37285ddc0a7a908999196bb35fb0bJoe Perches * firmware. We use the management API's to issue commands to the controller.
39661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
39671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: The commands issuance functionality is not generalized and
39681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * implemented in context of "get ld map" command only. If required, the
39691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command issuance logical can be trivially pulled out and implemented as a
397025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * standalone library. For now, this should suffice since there is no other
39711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user of this interface.
39721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3973a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Return 0 on success.
3974a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * Return -1 on failure.
39751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
39761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
39771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmegaraid_sysfs_get_ldmap(adapter_t *adapter)
39781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
39801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc_t			*uioc;
39811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64_t		*mbox64;
39821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox_t			*mbox;
39831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char			*raw_mbox;
39841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct timer_list	sysfs_timer;
39851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct timer_list	*timerp;
39861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	caddr_t			ldmap;
39871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			rval = 0;
39881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
39901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allow only one read at a time to go through the sysfs attributes
39911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
39920c2cc4337968f7aab91a91b8d5889982e3a3bd0dMatthias Kaehlcke	mutex_lock(&raid_dev->sysfs_mtx);
39931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc	= raid_dev->sysfs_uioc;
39951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox64	= raid_dev->sysfs_mbox64;
39961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ldmap	= raid_dev->sysfs_buffer;
39971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(uioc, 0, sizeof(uioc_t));
39991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(mbox64, 0, sizeof(mbox64_t));
40001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(ldmap, 0, sizeof(raid_dev->curr_ldmap));
40011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox		= &mbox64->mbox32;
40031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox	= (char *)mbox;
40041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->cmdbuf    = (uint64_t)(unsigned long)mbox64;
40051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->buf_vaddr	= (caddr_t)adapter;
40061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->status	= -ENODATA;
40071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uioc->done	= megaraid_sysfs_get_ldmap_done;
40081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
40101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Prepare the mailbox packet to get the current logical drive mapping
40111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * table
40121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
40131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mbox->xferaddr = (uint32_t)raid_dev->sysfs_buffer_dma;
40141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[0] = FC_DEL_LOGDRV;
40161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	raw_mbox[2] = OP_GET_LDID_MAP;
40171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
40191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Setup a timer to recover from a non-responding controller
40201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
40211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timerp	= &sysfs_timer;
40221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_timer(timerp);
40231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timerp->function	= megaraid_sysfs_get_ldmap_timeout;
40251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timerp->data		= (unsigned long)uioc;
40261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timerp->expires		= jiffies + 60 * HZ;
40271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_timer(timerp);
40291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
40311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Send the command to the firmware
40321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
40331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rval = megaraid_mbox_mm_command(adapter, uioc);
40341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rval == 0) {	// command successfully issued
40361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_event(raid_dev->sysfs_wait_q, (uioc->status != -ENODATA));
40371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
40391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Check if the command timed out
40401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
40411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (uioc->status == -ETIME) {
40421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
40431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: sysfs get ld map timed out\n"));
40441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rval = -ETIME;
40461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
40471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
40481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rval = mbox->status;
40491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
40501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rval == 0) {
40521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(raid_dev->curr_ldmap, ldmap,
40531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sizeof(raid_dev->curr_ldmap));
40541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
40551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
40561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
40571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: get ld map failed with %x\n", rval));
40581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
40591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
40601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
40611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		con_log(CL_ANN, (KERN_NOTICE
40621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"megaraid: could not issue ldmap command:%x\n", rval));
40631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
40641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer_sync(timerp);
40671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40680c2cc4337968f7aab91a91b8d5889982e3a3bd0dMatthias Kaehlcke	mutex_unlock(&raid_dev->sysfs_mtx);
40691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rval;
40711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
40721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
40751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_show_app_hndl - display application handle for this adapter
4076a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @cdev	: class device object representation for the host
4077a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @buf		: buffer to send data to
40781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
40791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Display the handle used by the applications while executing management
40801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tasks on the adapter. We invoke a management module API to get the adapter
40811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * handle, since we do not interface with applications directly.
40821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
40831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
4084ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesmegaraid_sysfs_show_app_hndl(struct device *dev, struct device_attribute *attr,
4085ee959b00c335d7780136c5abda37809191fe52c3Tony Jones			     char *buf)
40861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4087ee959b00c335d7780136c5abda37809191fe52c3Tony Jones	struct Scsi_Host *shost = class_to_shost(dev);
40881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = (adapter_t *)SCSIHOST2ADAP(shost);
40891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint32_t	app_hndl;
40901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	app_hndl = mraid_mm_adapter_app_handle(adapter->unique_id);
40921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return snprintf(buf, 8, "%u\n", app_hndl);
40941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
40951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
40981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * megaraid_sysfs_show_ldnum - display the logical drive number for this device
4099a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @dev		: device object representation for the scsi device
4100a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @attr	: device attribute to show
4101a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * @buf		: buffer to send data to
41021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Display the logical drive number for the device in question, if it a valid
4104a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * logical drive. For physical devices, "-1" is returned.
4105a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap *
4106a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap * The logical drive number is displayed in following format:
41071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <SCSI ID> <LD NUM> <LD STICKY ID> <APP ADAPTER HANDLE>
41091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4110a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98Randy Dunlap *   <int>     <int>       <int>            <int>
41111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
41121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
411310523b3b82456e416cbaffcc24ea2246980aa746Yani Ioannoumegaraid_sysfs_show_ldnum(struct device *dev, struct device_attribute *attr, char *buf)
41141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
41151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct scsi_device *sdev = to_scsi_device(dev);
41161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter_t	*adapter = (adapter_t *)SCSIHOST2ADAP(sdev->host);
41171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
41181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		scsi_id = -1;
41191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		logical_drv = -1;
41201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		ldid_map = -1;
41211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	uint32_t	app_hndl = 0;
41221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		mapped_sdev_id;
41231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		rval;
41241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int		i;
41251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (raid_dev->random_del_supported &&
41271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MRAID_IS_LOGICAL_SDEV(adapter, sdev)) {
41281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rval = megaraid_sysfs_get_ldmap(adapter);
41301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rval == 0) {
41311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i = 0; i < MAX_LOGICAL_DRIVES_40LD; i++) {
41331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mapped_sdev_id = sdev->id;
41351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (sdev->id > adapter->init_id) {
41371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					mapped_sdev_id -= 1;
41381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
41391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (raid_dev->curr_ldmap[i] == mapped_sdev_id) {
41411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					scsi_id = sdev->id;
41431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					logical_drv = i;
41451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ldid_map = raid_dev->curr_ldmap[i];
41471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					app_hndl = mraid_mm_adapter_app_handle(
41491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							adapter->unique_id);
41501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
41521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
41531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
41541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
41551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
41561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			con_log(CL_ANN, (KERN_NOTICE
41571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"megaraid: sysfs get ld map failed: %x\n",
41581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rval));
41591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
41601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
41611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return snprintf(buf, 36, "%d %d %d %d\n", scsi_id, logical_drv,
41631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ldid_map, app_hndl);
41641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
41651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
41681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * END: Mailbox Low Level Driver
41691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
41701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(megaraid_init);
41711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(megaraid_exit);
41721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* vim: set ts=8 sw=8 tw=78 ai si: */
4174