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