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