diff options
Diffstat (limited to 'openvz-sources/022.077/5102_linux-2.6.8.1-megaraid-2.20.x.patch')
-rw-r--r-- | openvz-sources/022.077/5102_linux-2.6.8.1-megaraid-2.20.x.patch | 7317 |
1 files changed, 0 insertions, 7317 deletions
diff --git a/openvz-sources/022.077/5102_linux-2.6.8.1-megaraid-2.20.x.patch b/openvz-sources/022.077/5102_linux-2.6.8.1-megaraid-2.20.x.patch deleted file mode 100644 index 8708fb3..0000000 --- a/openvz-sources/022.077/5102_linux-2.6.8.1-megaraid-2.20.x.patch +++ /dev/null @@ -1,7317 +0,0 @@ ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid/Kconfig.megaraid 1970-01-01 03:00:00.000000000 +0300 -+++ rhel4u2/drivers/scsi/megaraid/Kconfig.megaraid 2005-10-19 11:47:15.000000000 +0400 -@@ -0,0 +1,78 @@ -+config MEGARAID_NEWGEN -+ bool "LSI Logic New Generation RAID Device Drivers" -+ depends on PCI && SCSI -+ help -+ LSI Logic RAID Device Drivers -+ -+config MEGARAID_MM -+ tristate "LSI Logic Management Module (New Driver)" -+ depends on PCI && SCSI && MEGARAID_NEWGEN -+ help -+ Management Module provides ioctl, sysfs support for LSI Logic -+ RAID controllers. -+ To compile this driver as a module, choose M here: the -+ module will be called megaraid_mm -+ -+ -+config MEGARAID_MAILBOX -+ tristate "LSI Logic MegaRAID Driver (New Driver)" -+ depends on PCI && SCSI && MEGARAID_MM -+ help -+ List of supported controllers -+ -+ OEM Product Name VID :DID :SVID:SSID -+ --- ------------ ---- ---- ---- ---- -+ Dell PERC3/QC 101E:1960:1028:0471 -+ Dell PERC3/DC 101E:1960:1028:0493 -+ Dell PERC3/SC 101E:1960:1028:0475 -+ Dell PERC3/Di 1028:000E:1028:0123 -+ Dell PERC4/SC 1000:1960:1028:0520 -+ Dell PERC4/DC 1000:1960:1028:0518 -+ Dell PERC4/QC 1000:0407:1028:0531 -+ Dell PERC4/Di 1028:000F:1028:014A -+ Dell PERC 4e/Si 1028:0013:1028:016c -+ Dell PERC 4e/Di 1028:0013:1028:016d -+ Dell PERC 4e/Di 1028:0013:1028:016e -+ Dell PERC 4e/Di 1028:0013:1028:016f -+ Dell PERC 4e/Di 1028:0013:1028:0170 -+ Dell PERC 4e/DC 1000:0408:1028:0002 -+ Dell PERC 4e/SC 1000:0408:1028:0001 -+ LSI MegaRAID SCSI 320-0 1000:1960:1000:A520 -+ LSI MegaRAID SCSI 320-1 1000:1960:1000:0520 -+ LSI MegaRAID SCSI 320-2 1000:1960:1000:0518 -+ LSI MegaRAID SCSI 320-0X 1000:0407:1000:0530 -+ LSI MegaRAID SCSI 320-2X 1000:0407:1000:0532 -+ LSI MegaRAID SCSI 320-4X 1000:0407:1000:0531 -+ LSI MegaRAID SCSI 320-1E 1000:0408:1000:0001 -+ LSI MegaRAID SCSI 320-2E 1000:0408:1000:0002 -+ LSI MegaRAID SATA 150-4 1000:1960:1000:4523 -+ LSI MegaRAID SATA 150-6 1000:1960:1000:0523 -+ LSI MegaRAID SATA 300-4X 1000:0409:1000:3004 -+ LSI MegaRAID SATA 300-8X 1000:0409:1000:3008 -+ INTEL RAID Controller SRCU42X 1000:0407:8086:0532 -+ INTEL RAID Controller SRCS16 1000:1960:8086:0523 -+ INTEL RAID Controller SRCU42E 1000:0408:8086:0002 -+ INTEL RAID Controller SRCZCRX 1000:0407:8086:0530 -+ INTEL RAID Controller SRCS28X 1000:0409:8086:3008 -+ INTEL RAID Controller SROMBU42E 1000:0408:8086:3431 -+ INTEL RAID Controller SROMBU42E 1000:0408:8086:3499 -+ INTEL RAID Controller SRCU51L 1000:1960:8086:0520 -+ FSC MegaRAID PCI Express ROMB 1000:0408:1734:1065 -+ ACER MegaRAID ROMB-2E 1000:0408:1025:004D -+ NEC MegaRAID PCI Express ROMB 1000:0408:1033:8287 -+ -+ To compile this driver as a module, choose M here: the -+ module will be called megaraid_mbox -+ -+if MEGARAID_NEWGEN=n -+config MEGARAID_LEGACY -+ tristate "LSI Logic Legacy MegaRAID Driver" -+ depends on PCI && SCSI -+ help -+ This driver supports the LSI MegaRAID 418, 428, 438, 466, 762, 490 -+ and 467 SCSI host adapters. This driver also support the all U320 -+ RAID controllers -+ -+ To compile this driver as a module, choose M here: the -+ module will be called megaraid -+endif ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ rhel4u2/drivers/scsi/megaraid/Makefile 2004-10-19 01:55:07.000000000 +0400 -@@ -0,0 +1,2 @@ -+obj-$(CONFIG_MEGARAID_MM) += megaraid_mm.o -+obj-$(CONFIG_MEGARAID_MAILBOX) += megaraid_mbox.o ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid/mbox_defs.h 1970-01-01 03:00:00.000000000 +0300 -+++ rhel4u2/drivers/scsi/megaraid/mbox_defs.h 2005-10-20 14:41:08.039168992 +0400 -@@ -0,0 +1,790 @@ -+/* -+ * -+ * Linux MegaRAID Unified device driver -+ * -+ * Copyright (c) 2003-2004 LSI Logic Corporation. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * FILE : mbox_defs.h -+ * -+ */ -+#ifndef _MRAID_MBOX_DEFS_H_ -+#define _MRAID_MBOX_DEFS_H_ -+ -+#include <linux/types.h> -+ -+/* -+ * Commands and states for mailbox based controllers -+ */ -+ -+#define MBOXCMD_LREAD 0x01 -+#define MBOXCMD_LWRITE 0x02 -+#define MBOXCMD_PASSTHRU 0x03 -+#define MBOXCMD_ADPEXTINQ 0x04 -+#define MBOXCMD_ADAPTERINQ 0x05 -+#define MBOXCMD_LREAD64 0xA7 -+#define MBOXCMD_LWRITE64 0xA8 -+#define MBOXCMD_PASSTHRU64 0xC3 -+#define MBOXCMD_EXTPTHRU 0xE3 -+ -+#define MAIN_MISC_OPCODE 0xA4 -+#define GET_MAX_SG_SUPPORT 0x01 -+#define SUPPORT_EXT_CDB 0x16 -+ -+#define FC_NEW_CONFIG 0xA1 -+#define NC_SUBOP_PRODUCT_INFO 0x0E -+#define NC_SUBOP_ENQUIRY3 0x0F -+#define ENQ3_GET_SOLICITED_FULL 0x02 -+#define OP_DCMD_READ_CONFIG 0x04 -+#define NEW_READ_CONFIG_8LD 0x67 -+#define READ_CONFIG_8LD 0x07 -+#define FLUSH_ADAPTER 0x0A -+#define FLUSH_SYSTEM 0xFE -+ -+/* -+ * Command for random deletion of logical drives -+ */ -+#define FC_DEL_LOGDRV 0xA4 -+#define OP_SUP_DEL_LOGDRV 0x2A -+#define OP_GET_LDID_MAP 0x18 -+#define OP_DEL_LOGDRV 0x1C -+ -+/* -+ * BIOS commands -+ */ -+#define IS_BIOS_ENABLED 0x62 -+#define GET_BIOS 0x01 -+#define CHNL_CLASS 0xA9 -+#define GET_CHNL_CLASS 0x00 -+#define SET_CHNL_CLASS 0x01 -+#define CH_RAID 0x01 -+#define CH_SCSI 0x00 -+#define BIOS_PVT_DATA 0x40 -+#define GET_BIOS_PVT_DATA 0x00 -+ -+ -+/* -+ * Commands to support clustering -+ */ -+#define GET_TARGET_ID 0x7D -+#define CLUSTER_OP 0x70 -+#define GET_CLUSTER_MODE 0x02 -+#define CLUSTER_CMD 0x6E -+#define RESERVE_LD 0x01 -+#define RELEASE_LD 0x02 -+#define RESET_RESERVATIONS 0x03 -+#define RESERVATION_STATUS 0x04 -+#define RESERVE_PD 0x05 -+#define RELEASE_PD 0x06 -+ -+ -+/* -+ * Module battery status -+ */ -+#define BATTERY_MODULE_MISSING 0x01 -+#define BATTERY_LOW_VOLTAGE 0x02 -+#define BATTERY_TEMP_HIGH 0x04 -+#define BATTERY_PACK_MISSING 0x08 -+#define BATTERY_CHARGE_MASK 0x30 -+#define BATTERY_CHARGE_DONE 0x00 -+#define BATTERY_CHARGE_INPROG 0x10 -+#define BATTERY_CHARGE_FAIL 0x20 -+#define BATTERY_CYCLES_EXCEEDED 0x40 -+ -+/* -+ * Physical drive states. -+ */ -+#define PDRV_UNCNF 0 -+#define PDRV_ONLINE 3 -+#define PDRV_FAILED 4 -+#define PDRV_RBLD 5 -+#define PDRV_HOTSPARE 6 -+ -+ -+/* -+ * Raid logical drive states. -+ */ -+#define RDRV_OFFLINE 0 -+#define RDRV_DEGRADED 1 -+#define RDRV_OPTIMAL 2 -+#define RDRV_DELETED 3 -+ -+/* -+ * Read, write and cache policies -+ */ -+#define NO_READ_AHEAD 0 -+#define READ_AHEAD 1 -+#define ADAP_READ_AHEAD 2 -+#define WRMODE_WRITE_THRU 0 -+#define WRMODE_WRITE_BACK 1 -+#define CACHED_IO 0 -+#define DIRECT_IO 1 -+ -+#define MAX_LOGICAL_DRIVES_8LD 8 -+#define MAX_LOGICAL_DRIVES_40LD 40 -+#define FC_MAX_PHYSICAL_DEVICES 256 -+#define MAX_MBOX_CHANNELS 5 -+#define MAX_MBOX_TARGET 15 -+#define MBOX_MAX_PHYSICAL_DRIVES MAX_MBOX_CHANNELS*MAX_MBOX_TARGET -+#define MAX_ROW_SIZE_40LD 32 -+#define MAX_ROW_SIZE_8LD 8 -+#define SPAN_DEPTH_8_SPANS 8 -+#define SPAN_DEPTH_4_SPANS 4 -+#define MAX_REQ_SENSE_LEN 0x20 -+ -+ -+ -+/** -+ * struct mbox_t - Driver and f/w handshake structure. -+ * @cmd : firmware command -+ * @cmdid : command id -+ * @numsectors : number of sectors to be transferred -+ * @lba : Logical Block Address on LD -+ * @xferaddr : DMA address for data transfer -+ * @logdrv : logical drive number -+ * @numsge : number of scatter gather elements in sg list -+ * @resvd : reserved -+ * @busy : f/w busy, must wait to issue more commands. -+ * @numstatus : number of commands completed. -+ * @status : status of the commands completed -+ * @completed : array of completed command ids. -+ * @poll : poll and ack sequence -+ * @ack : poll and ack sequence -+ * -+ * The central handshake structure between the driver and the firmware. This -+ * structure must be allocated by the driver and aligned at 8-byte boundary. -+ */ -+#define MBOX_MAX_FIRMWARE_STATUS 46 -+typedef struct { -+ uint8_t cmd; -+ uint8_t cmdid; -+ uint16_t numsectors; -+ uint32_t lba; -+ uint32_t xferaddr; -+ uint8_t logdrv; -+ uint8_t numsge; -+ uint8_t resvd; -+ uint8_t busy; -+ uint8_t numstatus; -+ uint8_t status; -+ uint8_t completed[MBOX_MAX_FIRMWARE_STATUS]; -+ uint8_t poll; -+ uint8_t ack; -+} __attribute__ ((packed)) mbox_t; -+ -+ -+/** -+ * mbox64_t - 64-bit extension for the mailbox -+ * @segment_lo : the low 32-bits of the address of the scatter-gather list -+ * @segment_hi : the upper 32-bits of the address of the scatter-gather list -+ * @mbox : 32-bit mailbox, whose xferadder field must be set to -+ * 0xFFFFFFFF -+ * -+ * This is the extension of the 32-bit mailbox to be able to perform DMA -+ * beyond 4GB address range. -+ */ -+typedef struct { -+ uint32_t xferaddr_lo; -+ uint32_t xferaddr_hi; -+ mbox_t mbox32; -+} __attribute__ ((packed)) mbox64_t; -+ -+/* -+ * mailbox structure used for internal commands -+ */ -+typedef struct { -+ u8 cmd; -+ u8 cmdid; -+ u8 opcode; -+ u8 subopcode; -+ u32 lba; -+ u32 xferaddr; -+ u8 logdrv; -+ u8 rsvd[3]; -+ u8 numstatus; -+ u8 status; -+} __attribute__ ((packed)) int_mbox_t; -+ -+/** -+ * mraid_passthru_t - passthru structure to issue commands to physical devices -+ * @timeout : command timeout, 0=6sec, 1=60sec, 2=10min, 3=3hr -+ * @ars : set if ARS required after check condition -+ * @islogical : set if command meant for logical devices -+ * @logdrv : logical drive number if command for LD -+ * @channel : Channel on which physical device is located -+ * @target : SCSI target of the device -+ * @queuetag : unused -+ * @queueaction : unused -+ * @cdb : SCSI CDB -+ * @cdblen : length of the CDB -+ * @reqsenselen : amount of request sense data to be returned -+ * @reqsensearea : Sense information buffer -+ * @numsge : number of scatter-gather elements in the sg list -+ * @scsistatus : SCSI status of the command completed. -+ * @dataxferaddr : DMA data transfer address -+ * @dataxferlen : amount of the data to be transferred. -+ */ -+typedef struct { -+ uint8_t timeout :3; -+ uint8_t ars :1; -+ uint8_t reserved :3; -+ uint8_t islogical :1; -+ uint8_t logdrv; -+ uint8_t channel; -+ uint8_t target; -+ uint8_t queuetag; -+ uint8_t queueaction; -+ uint8_t cdb[10]; -+ uint8_t cdblen; -+ uint8_t reqsenselen; -+ uint8_t reqsensearea[MAX_REQ_SENSE_LEN]; -+ uint8_t numsge; -+ uint8_t scsistatus; -+ uint32_t dataxferaddr; -+ uint32_t dataxferlen; -+} __attribute__ ((packed)) mraid_passthru_t; -+ -+typedef struct { -+ -+ uint32_t dataxferaddr_lo; -+ uint32_t dataxferaddr_hi; -+ mraid_passthru_t pthru32; -+ -+} __attribute__ ((packed)) mega_passthru64_t; -+ -+/** -+ * mraid_epassthru_t - passthru structure to issue commands to physical devices -+ * @timeout : command timeout, 0=6sec, 1=60sec, 2=10min, 3=3hr -+ * @ars : set if ARS required after check condition -+ * @rsvd1 : reserved field -+ * @cd_rom : (?) -+ * @rsvd2 : reserved field -+ * @islogical : set if command meant for logical devices -+ * @logdrv : logical drive number if command for LD -+ * @channel : Channel on which physical device is located -+ * @target : SCSI target of the device -+ * @queuetag : unused -+ * @queueaction : unused -+ * @cdblen : length of the CDB -+ * @rsvd3 : reserved field -+ * @cdb : SCSI CDB -+ * @numsge : number of scatter-gather elements in the sg list -+ * @status : SCSI status of the command completed. -+ * @reqsenselen : amount of request sense data to be returned -+ * @reqsensearea : Sense information buffer -+ * @rsvd4 : reserved field -+ * @dataxferaddr : DMA data transfer address -+ * @dataxferlen : amount of the data to be transferred. -+ */ -+typedef struct { -+ uint8_t timeout :3; -+ uint8_t ars :1; -+ uint8_t rsvd1 :1; -+ uint8_t cd_rom :1; -+ uint8_t rsvd2 :1; -+ uint8_t islogical :1; -+ uint8_t logdrv; -+ uint8_t channel; -+ uint8_t target; -+ uint8_t queuetag; -+ uint8_t queueaction; -+ uint8_t cdblen; -+ uint8_t rsvd3; -+ uint8_t cdb[16]; -+ uint8_t numsge; -+ uint8_t status; -+ uint8_t reqsenselen; -+ uint8_t reqsensearea[MAX_REQ_SENSE_LEN]; -+ uint8_t rsvd4; -+ uint32_t dataxferaddr; -+ uint32_t dataxferlen; -+} __attribute__ ((packed)) mraid_epassthru_t; -+ -+ -+/** -+ * mraid_pinfo_t - product info, static information about the controller -+ * @data_size : current size in bytes (not including resvd) -+ * @config_signature : Current value is 0x00282008 -+ * @fw_version : Firmware version -+ * @bios_version : version of the BIOS -+ * @product_name : Name given to the controller -+ * @max_commands : Maximum concurrent commands supported -+ * @nchannels : Number of SCSI Channels detected -+ * @fc_loop_present : Number of Fibre Loops detected -+ * @mem_type : EDO, FPM, SDRAM etc -+ * @signature : -+ * @dram_size : In terms of MB -+ * @subsysid : device PCI subsystem ID -+ * @subsysvid : device PCI subsystem vendor ID -+ * @notify_counters : -+ * @pad1k : 135 + 889 resvd = 1024 total size -+ * -+ * This structures holds the information about the controller which is not -+ * expected to change dynamically. -+ * -+ * The current value of config signature is 0x00282008: -+ * 0x28 = MAX_LOGICAL_DRIVES, -+ * 0x20 = Number of stripes and -+ * 0x08 = Number of spans -+ */ -+typedef struct { -+ uint32_t data_size; -+ uint32_t config_signature; -+ uint8_t fw_version[16]; -+ uint8_t bios_version[16]; -+ uint8_t product_name[80]; -+ uint8_t max_commands; -+ uint8_t nchannels; -+ uint8_t fc_loop_present; -+ uint8_t mem_type; -+ uint32_t signature; -+ uint16_t dram_size; -+ uint16_t subsysid; -+ uint16_t subsysvid; -+ uint8_t notify_counters; -+ uint8_t pad1k[889]; -+} __attribute__ ((packed)) mraid_pinfo_t; -+ -+ -+/** -+ * mraid_notify_t - the notification structure -+ * @global_counter : Any change increments this counter -+ * @param_counter : Indicates any params changed -+ * @param_id : Param modified - defined below -+ * @param_val : New val of last param modified -+ * @write_config_counter : write config occurred -+ * @write_config_rsvd : -+ * @ldrv_op_counter : Indicates ldrv op started/completed -+ * @ldrv_opid : ldrv num -+ * @ldrv_opcmd : ldrv operation - defined below -+ * @ldrv_opstatus : status of the operation -+ * @ldrv_state_counter : Indicates change of ldrv state -+ * @ldrv_state_id : ldrv num -+ * @ldrv_state_new : New state -+ * @ldrv_state_old : old state -+ * @pdrv_state_counter : Indicates change of ldrv state -+ * @pdrv_state_id : pdrv id -+ * @pdrv_state_new : New state -+ * @pdrv_state_old : old state -+ * @pdrv_fmt_counter : Indicates pdrv format started/over -+ * @pdrv_fmt_id : pdrv id -+ * @pdrv_fmt_val : format started/over -+ * @pdrv_fmt_rsvd : -+ * @targ_xfer_counter : Indicates SCSI-2 Xfer rate change -+ * @targ_xfer_id : pdrv Id -+ * @targ_xfer_val : new Xfer params of last pdrv -+ * @targ_xfer_rsvd : -+ * @fcloop_id_chg_counter : Indicates loopid changed -+ * @fcloopid_pdrvid : pdrv id -+ * @fcloop_id0 : loopid on fc loop 0 -+ * @fcloop_id1 : loopid on fc loop 1 -+ * @fcloop_state_counter : Indicates loop state changed -+ * @fcloop_state0 : state of fc loop 0 -+ * @fcloop_state1 : state of fc loop 1 -+ * @fcloop_state_rsvd : -+ */ -+typedef struct { -+ uint32_t global_counter; -+ uint8_t param_counter; -+ uint8_t param_id; -+ uint16_t param_val; -+ uint8_t write_config_counter; -+ uint8_t write_config_rsvd[3]; -+ uint8_t ldrv_op_counter; -+ uint8_t ldrv_opid; -+ uint8_t ldrv_opcmd; -+ uint8_t ldrv_opstatus; -+ uint8_t ldrv_state_counter; -+ uint8_t ldrv_state_id; -+ uint8_t ldrv_state_new; -+ uint8_t ldrv_state_old; -+ uint8_t pdrv_state_counter; -+ uint8_t pdrv_state_id; -+ uint8_t pdrv_state_new; -+ uint8_t pdrv_state_old; -+ uint8_t pdrv_fmt_counter; -+ uint8_t pdrv_fmt_id; -+ uint8_t pdrv_fmt_val; -+ uint8_t pdrv_fmt_rsvd; -+ uint8_t targ_xfer_counter; -+ uint8_t targ_xfer_id; -+ uint8_t targ_xfer_val; -+ uint8_t targ_xfer_rsvd; -+ uint8_t fcloop_id_chg_counter; -+ uint8_t fcloopid_pdrvid; -+ uint8_t fcloop_id0; -+ uint8_t fcloop_id1; -+ uint8_t fcloop_state_counter; -+ uint8_t fcloop_state0; -+ uint8_t fcloop_state1; -+ uint8_t fcloop_state_rsvd; -+} __attribute__ ((packed)) mraid_notify_t; -+ -+ -+/** -+ * mraid_inquiry3_t - enquiry for device information -+ * -+ * @data_size : current size in bytes (not including resvd) -+ * @notify : -+ * @notify_rsvd : -+ * @rebuild_rate : rebuild rate (0% - 100%) -+ * @cache_flush_int : cache flush interval in seconds -+ * @sense_alert : -+ * @drive_insert_count : drive insertion count -+ * @battery_status : -+ * @num_ldrv : no. of Log Drives configured -+ * @recon_state : state of reconstruct -+ * @ldrv_op_status : logdrv Status -+ * @ldrv_size : size of each log drv -+ * @ldrv_prop : -+ * @ldrv_state : state of log drives -+ * @pdrv_state : state of phys drvs. -+ * @pdrv_format : -+ * @targ_xfer : phys device transfer rate -+ * @pad1k : 761 + 263reserved = 1024 bytes total size -+ */ -+#define MAX_NOTIFY_SIZE 0x80 -+#define CUR_NOTIFY_SIZE sizeof(mraid_notify_t) -+ -+typedef struct { -+ uint32_t data_size; -+ -+ mraid_notify_t notify; -+ -+ uint8_t notify_rsvd[MAX_NOTIFY_SIZE - CUR_NOTIFY_SIZE]; -+ -+ uint8_t rebuild_rate; -+ uint8_t cache_flush_int; -+ uint8_t sense_alert; -+ uint8_t drive_insert_count; -+ -+ uint8_t battery_status; -+ uint8_t num_ldrv; -+ uint8_t recon_state[MAX_LOGICAL_DRIVES_40LD / 8]; -+ uint16_t ldrv_op_status[MAX_LOGICAL_DRIVES_40LD / 8]; -+ -+ uint32_t ldrv_size[MAX_LOGICAL_DRIVES_40LD]; -+ uint8_t ldrv_prop[MAX_LOGICAL_DRIVES_40LD]; -+ uint8_t ldrv_state[MAX_LOGICAL_DRIVES_40LD]; -+ uint8_t pdrv_state[FC_MAX_PHYSICAL_DEVICES]; -+ uint16_t pdrv_format[FC_MAX_PHYSICAL_DEVICES / 16]; -+ -+ uint8_t targ_xfer[80]; -+ uint8_t pad1k[263]; -+} __attribute__ ((packed)) mraid_inquiry3_t; -+ -+ -+/** -+ * mraid_adapinfo_t - information about the adapter -+ * @max_commands : max concurrent commands supported -+ * @rebuild_rate : rebuild rate - 0% thru 100% -+ * @max_targ_per_chan : max targ per channel -+ * @nchannels : number of channels on HBA -+ * @fw_version : firmware version -+ * @age_of_flash : number of times FW has been flashed -+ * @chip_set_value : contents of 0xC0000832 -+ * @dram_size : in MB -+ * @cache_flush_interval : in seconds -+ * @bios_version : -+ * @board_type : -+ * @sense_alert : -+ * @write_config_count : increase with every configuration change -+ * @drive_inserted_count : increase with every drive inserted -+ * @inserted_drive : channel:Id of inserted drive -+ * @battery_status : bit 0: battery module missing -+ * bit 1: VBAD -+ * bit 2: temprature high -+ * bit 3: battery pack missing -+ * bit 4,5: -+ * 00 - charge complete -+ * 01 - fast charge in progress -+ * 10 - fast charge fail -+ * 11 - undefined -+ * bit 6: counter > 1000 -+ * bit 7: Undefined -+ * @dec_fault_bus_info : -+ */ -+typedef struct { -+ uint8_t max_commands; -+ uint8_t rebuild_rate; -+ uint8_t max_targ_per_chan; -+ uint8_t nchannels; -+ uint8_t fw_version[4]; -+ uint16_t age_of_flash; -+ uint8_t chip_set_value; -+ uint8_t dram_size; -+ uint8_t cache_flush_interval; -+ uint8_t bios_version[4]; -+ uint8_t board_type; -+ uint8_t sense_alert; -+ uint8_t write_config_count; -+ uint8_t battery_status; -+ uint8_t dec_fault_bus_info; -+} __attribute__ ((packed)) mraid_adapinfo_t; -+ -+ -+/** -+ * mraid_ldrv_info_t - information about the logical drives -+ * @nldrv : Number of logical drives configured -+ * @rsvd : -+ * @size : size of each logical drive -+ * @prop : -+ * @state : state of each logical drive -+ */ -+typedef struct { -+ uint8_t nldrv; -+ uint8_t rsvd[3]; -+ uint32_t size[MAX_LOGICAL_DRIVES_8LD]; -+ uint8_t prop[MAX_LOGICAL_DRIVES_8LD]; -+ uint8_t state[MAX_LOGICAL_DRIVES_8LD]; -+} __attribute__ ((packed)) mraid_ldrv_info_t; -+ -+ -+/** -+ * mraid_pdrv_info_t - information about the physical drives -+ * @pdrv_state : state of each physical drive -+ */ -+typedef struct { -+ uint8_t pdrv_state[MBOX_MAX_PHYSICAL_DRIVES]; -+ uint8_t rsvd; -+} __attribute__ ((packed)) mraid_pdrv_info_t; -+ -+ -+/** -+ * mraid_inquiry_t - RAID inquiry, mailbox command 0x05 -+ * @mraid_adapinfo_t : adapter information -+ * @mraid_ldrv_info_t : logical drives information -+ * @mraid_pdrv_info_t : physical drives information -+ */ -+typedef struct { -+ mraid_adapinfo_t adapter_info; -+ mraid_ldrv_info_t logdrv_info; -+ mraid_pdrv_info_t pdrv_info; -+} __attribute__ ((packed)) mraid_inquiry_t; -+ -+ -+/** -+ * mraid_extinq_t - RAID extended inquiry, mailbox command 0x04 -+ * -+ * @raid_inq : raid inquiry -+ * @phys_drv_format : -+ * @stack_attn : -+ * @modem_status : -+ * @rsvd : -+ */ -+typedef struct { -+ mraid_inquiry_t raid_inq; -+ uint16_t phys_drv_format[MAX_MBOX_CHANNELS]; -+ uint8_t stack_attn; -+ uint8_t modem_status; -+ uint8_t rsvd[2]; -+} __attribute__ ((packed)) mraid_extinq_t; -+ -+ -+/** -+ * adap_device_t - device information -+ * @channel : channel fpor the device -+ * @target : target ID of the device -+ */ -+typedef struct { -+ uint8_t channel; -+ uint8_t target; -+}__attribute__ ((packed)) adap_device_t; -+ -+ -+/** -+ * adap_span_40ld_t - 40LD span -+ * @start_blk : starting block -+ * @num_blks : number of blocks -+ */ -+typedef struct { -+ uint32_t start_blk; -+ uint32_t num_blks; -+ adap_device_t device[MAX_ROW_SIZE_40LD]; -+}__attribute__ ((packed)) adap_span_40ld_t; -+ -+ -+/** -+ * adap_span_8ld_t - 8LD span -+ * @start_blk : starting block -+ * @num_blks : number of blocks -+ */ -+typedef struct { -+ uint32_t start_blk; -+ uint32_t num_blks; -+ adap_device_t device[MAX_ROW_SIZE_8LD]; -+}__attribute__ ((packed)) adap_span_8ld_t; -+ -+ -+/** -+ * logdrv_param_t - logical drives parameters -+ * -+ * @span_depth : total number of spans -+ * @level : RAID level -+ * @read_ahead : read ahead, no read ahead, adaptive read ahead -+ * @stripe_sz : encoded stripe size -+ * @status : status of the logical drive -+ * @write_mode : write mode, write_through/write_back -+ * @direct_io : direct io or through cache -+ * @row_size : number of stripes in a row -+ */ -+typedef struct { -+ uint8_t span_depth; -+ uint8_t level; -+ uint8_t read_ahead; -+ uint8_t stripe_sz; -+ uint8_t status; -+ uint8_t write_mode; -+ uint8_t direct_io; -+ uint8_t row_size; -+} __attribute__ ((packed)) logdrv_param_t; -+ -+ -+/** -+ * logdrv_40ld_t - logical drive definition for 40LD controllers -+ * @lparam : logical drives parameters -+ * @span : span -+ */ -+typedef struct { -+ logdrv_param_t lparam; -+ adap_span_40ld_t span[SPAN_DEPTH_8_SPANS]; -+}__attribute__ ((packed)) logdrv_40ld_t; -+ -+ -+/** -+ * logdrv_8ld_span8_t - logical drive definition for 8LD controllers -+ * @lparam : logical drives parameters -+ * @span : span -+ * -+ * 8-LD logical drive with upto 8 spans -+ */ -+typedef struct { -+ logdrv_param_t lparam; -+ adap_span_8ld_t span[SPAN_DEPTH_8_SPANS]; -+}__attribute__ ((packed)) logdrv_8ld_span8_t; -+ -+ -+/** -+ * logdrv_8ld_span4_t - logical drive definition for 8LD controllers -+ * @lparam : logical drives parameters -+ * @span : span -+ * -+ * 8-LD logical drive with upto 4 spans -+ */ -+typedef struct { -+ logdrv_param_t lparam; -+ adap_span_8ld_t span[SPAN_DEPTH_4_SPANS]; -+}__attribute__ ((packed)) logdrv_8ld_span4_t; -+ -+ -+/** -+ * phys_drive_t - physical device information -+ * @type : Type of the device -+ * @cur_status : current status of the device -+ * @tag_depth : Level of tagging -+ * @sync_neg : sync negotiation - ENABLE or DISBALE -+ * @size : configurable size in terms of 512 byte -+ */ -+typedef struct { -+ uint8_t type; -+ uint8_t cur_status; -+ uint8_t tag_depth; -+ uint8_t sync_neg; -+ uint32_t size; -+}__attribute__ ((packed)) phys_drive_t; -+ -+ -+/** -+ * disk_array_40ld_t - disk array for 40LD controllers -+ * @numldrv : number of logical drives -+ * @resvd : -+ * @ldrv : logical drives information -+ * @pdrv : physical drives information -+ */ -+typedef struct { -+ uint8_t numldrv; -+ uint8_t resvd[3]; -+ logdrv_40ld_t ldrv[MAX_LOGICAL_DRIVES_40LD]; -+ phys_drive_t pdrv[MBOX_MAX_PHYSICAL_DRIVES]; -+}__attribute__ ((packed)) disk_array_40ld_t; -+ -+ -+/** -+ * disk_array_8ld_span8_t - disk array for 8LD controllers -+ * @numldrv : number of logical drives -+ * @resvd : -+ * @ldrv : logical drives information -+ * @pdrv : physical drives information -+ * -+ * Disk array for 8LD logical drives with upto 8 spans -+ */ -+typedef struct { -+ uint8_t numldrv; -+ uint8_t resvd[3]; -+ logdrv_8ld_span8_t ldrv[MAX_LOGICAL_DRIVES_8LD]; -+ phys_drive_t pdrv[MBOX_MAX_PHYSICAL_DRIVES]; -+}__attribute__ ((packed)) disk_array_8ld_span8_t; -+ -+ -+/** -+ * disk_array_8ld_span4_t - disk array for 8LD controllers -+ * @numldrv : number of logical drives -+ * @resvd : -+ * @ldrv : logical drives information -+ * @pdrv : physical drives information -+ * -+ * Disk array for 8LD logical drives with upto 4 spans -+ */ -+typedef struct { -+ uint8_t numldrv; -+ uint8_t resvd[3]; -+ logdrv_8ld_span4_t ldrv[MAX_LOGICAL_DRIVES_8LD]; -+ phys_drive_t pdrv[MBOX_MAX_PHYSICAL_DRIVES]; -+}__attribute__ ((packed)) disk_array_8ld_span4_t; -+ -+ -+/** -+ * private_bios_data - bios private data for boot devices -+ * @geometry : bits 0-3 - BIOS geometry, 0x0001 - 1GB, 0x0010 - 2GB, -+ * 0x1000 - 8GB, Others values are invalid -+ * @unused : bits 4-7 are unused -+ * @boot_drv : logical drive set as boot drive, 0..7 - for 8LD cards, -+ * 0..39 - for 40LD cards -+ * @cksum : 0-(sum of first 13 bytes of this structure) -+ */ -+struct private_bios_data { -+ uint8_t geometry :4; -+ uint8_t unused :4; -+ uint8_t boot_drv; -+ uint8_t rsvd[12]; -+ uint16_t cksum; -+} __attribute__ ((packed)); -+ -+ -+/** -+ * mbox_sgl64 - 64-bit scatter list for mailbox based controllers -+ * @address : address of the buffer -+ * @length : data transfer length -+ */ -+typedef struct { -+ uint64_t address; -+ uint32_t length; -+} __attribute__ ((packed)) mbox_sgl64; -+ -+/** -+ * mbox_sgl32 - 32-bit scatter list for mailbox based controllers -+ * @address : address of the buffer -+ * @length : data transfer length -+ */ -+typedef struct { -+ uint32_t address; -+ uint32_t length; -+} __attribute__ ((packed)) mbox_sgl32; -+ -+#endif // _MRAID_MBOX_DEFS_H_ -+ -+/* vim: set ts=8 sw=8 tw=78: */ ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid/mega_common.h 1970-01-01 03:00:00.000000000 +0300 -+++ rhel4u2/drivers/scsi/megaraid/mega_common.h 2005-10-20 14:48:47.529315872 +0400 -@@ -0,0 +1,287 @@ -+/* -+ * -+ * Linux MegaRAID device driver -+ * -+ * Copyright (c) 2003-2004 LSI Logic Corporation. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * FILE : mega_common.h -+ * -+ * Libaray of common routine used by all low-level megaraid drivers -+ */ -+ -+#ifndef _MEGA_COMMON_H_ -+#define _MEGA_COMMON_H_ -+ -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/pci.h> -+#include <linux/spinlock.h> -+#include <linux/interrupt.h> -+#include <linux/delay.h> -+#include <linux/blkdev.h> -+#include <linux/list.h> -+#include <linux/version.h> -+#include <linux/moduleparam.h> -+#include <linux/dma-mapping.h> -+#include <asm/semaphore.h> -+#include <scsi/scsi.h> -+#include <scsi/scsi_cmnd.h> -+#include <scsi/scsi_device.h> -+#include <scsi/scsi_host.h> -+ -+ -+#define LSI_MAX_CHANNELS 16 -+#define LSI_MAX_LOGICAL_DRIVES_64LD (64+1) -+ -+ -+/** -+ * scb_t - scsi command control block -+ * @param ccb : command control block for individual driver -+ * @param list : list of control blocks -+ * @param gp : general purpose field for LLDs -+ * @param sno : all SCBs have a serial number -+ * @param scp : associated scsi command -+ * @param state : current state of scb -+ * @param dma_dir : direction of data transfer -+ * @param dma_type : transfer with sg list, buffer, or no data transfer -+ * @param dev_channel : actual channel on the device -+ * @param dev_target : actual target on the device -+ * @param status : completion status -+ * -+ * This is our central data structure to issue commands the each driver. -+ * Driver specific data structures are maintained in the ccb field. -+ * scb provides a field 'gp', which can be used by LLD for its own purposes -+ * -+ * dev_channel and dev_target must be initialized with the actual channel and -+ * target on the controller. -+ */ -+typedef struct { -+ caddr_t ccb; -+ struct list_head list; -+ unsigned long gp; -+ unsigned int sno; -+ struct scsi_cmnd *scp; -+ uint32_t state; -+ uint32_t dma_direction; -+ uint32_t dma_type; -+ uint16_t dev_channel; -+ uint16_t dev_target; -+ uint32_t status; -+} scb_t; -+ -+/* -+ * SCB states as it transitions from one state to another -+ */ -+#define SCB_FREE 0x0000 /* on the free list */ -+#define SCB_ACTIVE 0x0001 /* off the free list */ -+#define SCB_PENDQ 0x0002 /* on the pending queue */ -+#define SCB_ISSUED 0x0004 /* issued - owner f/w */ -+#define SCB_ABORT 0x0008 /* Got an abort for this one */ -+#define SCB_RESET 0x0010 /* Got a reset for this one */ -+ -+/* -+ * DMA types for scb -+ */ -+#define MRAID_DMA_NONE 0x0000 /* no data transfer for this command */ -+#define MRAID_DMA_WSG 0x0001 /* data transfer using a sg list */ -+#define MRAID_DMA_WBUF 0x0002 /* data transfer using a contiguous buffer */ -+ -+ -+/** -+ * struct adapter_t - driver's initialization structure -+ * @param dpc_h : tasklet handle -+ * @param pdev : pci configuration pointer for kernel -+ * @param host : pointer to host structure of mid-layer -+ * @param host_lock : pointer to appropriate lock -+ * @param lock : synchronization lock for mid-layer and driver -+ * @param quiescent : driver is quiescent for now. -+ * @param outstanding_cmds : number of commands pending in the driver -+ * @param kscb_list : pointer to the bulk of SCBs pointers for IO -+ * @param kscb_pool : pool of free scbs for IO -+ * @param kscb_pool_lock : lock for pool of free scbs -+ * @param pend_list : pending commands list -+ * @param pend_list_lock : exlusion lock for pending commands list -+ * @param completed_list : list of completed commands -+ * @param completed_list_lock : exclusion lock for list of completed commands -+ * @param sglen : max sg elements supported -+ * @param device_ids : to convert kernel device addr to our devices. -+ * @param raid_device : raid adapter specific pointer -+ * @param max_channel : maximum channel number supported - inclusive -+ * @param max_target : max target supported - inclusive -+ * @param max_lun : max lun supported - inclusive -+ * @param unique_id : unique identifier for each adapter -+ * @param irq : IRQ for this adapter -+ * @param ito : internal timeout value, (-1) means no timeout -+ * @param ibuf : buffer to issue internal commands -+ * @param ibuf_dma_h : dma handle for the above buffer -+ * @param uscb_list : SCB pointers for user cmds, common mgmt module -+ * @param uscb_pool : pool of SCBs for user commands -+ * @param uscb_pool_lock : exclusion lock for these SCBs -+ * @param max_cmds : max outstanding commands -+ * @param fw_version : firmware version -+ * @param bios_version : bios version -+ * @param max_cdb_sz : biggest CDB size supported. -+ * @param ha : is high availability present - clustering -+ * @param init_id : initiator ID, the default value should be 7 -+ * @param max_sectors : max sectors per request -+ * @param cmd_per_lun : max outstanding commands per LUN -+ * @param being_detached : set when unloading, no more mgmt calls -+ * -+ * -+ * mraid_setup_device_map() can be called anytime after the device map is -+ * available and MRAID_GET_DEVICE_MAP() can be called whenever the mapping is -+ * required, usually from LLD's queue entry point. The formar API sets up the -+ * MRAID_IS_LOGICAL(adapter_t *, struct scsi_cmnd *) to find out if the -+ * device in question is a logical drive. -+ * -+ * quiescent flag should be set by the driver if it is not accepting more -+ * commands -+ * -+ * NOTE: The fields of this structures are placed to minimize cache misses -+ */ -+ -+// amount of space required to store the bios and firmware version strings -+#define VERSION_SIZE 16 -+ -+typedef struct { -+ struct tasklet_struct dpc_h; -+ struct pci_dev *pdev; -+ struct Scsi_Host *host; -+ spinlock_t *host_lock; -+ spinlock_t lock; -+ uint8_t quiescent; -+ int outstanding_cmds; -+ scb_t *kscb_list; -+ struct list_head kscb_pool; -+ spinlock_t kscb_pool_lock; -+ struct list_head pend_list; -+ spinlock_t pend_list_lock; -+ struct list_head completed_list; -+ spinlock_t completed_list_lock; -+ uint16_t sglen; -+ int device_ids[LSI_MAX_CHANNELS] -+ [LSI_MAX_LOGICAL_DRIVES_64LD]; -+ caddr_t raid_device; -+ uint8_t max_channel; -+ uint16_t max_target; -+ uint8_t max_lun; -+ -+ uint32_t unique_id; -+ uint8_t irq; -+ uint8_t ito; -+ caddr_t ibuf; -+ dma_addr_t ibuf_dma_h; -+ scb_t *uscb_list; -+ struct list_head uscb_pool; -+ spinlock_t uscb_pool_lock; -+ int max_cmds; -+ uint8_t fw_version[VERSION_SIZE]; -+ uint8_t bios_version[VERSION_SIZE]; -+ uint8_t max_cdb_sz; -+ uint8_t ha; -+ uint16_t init_id; -+ uint16_t max_sectors; -+ uint16_t cmd_per_lun; -+ atomic_t being_detached; -+} adapter_t; -+ -+#define SCSI_FREE_LIST_LOCK(adapter) (&adapter->kscb_pool_lock) -+#define USER_FREE_LIST_LOCK(adapter) (&adapter->uscb_pool_lock) -+#define PENDING_LIST_LOCK(adapter) (&adapter->pend_list_lock) -+#define COMPLETED_LIST_LOCK(adapter) (&adapter->completed_list_lock) -+ -+ -+// conversion from scsi command -+#define SCP2HOST(scp) (scp)->device->host // to host -+#define SCP2HOSTDATA(scp) SCP2HOST(scp)->hostdata // to soft state -+#define SCP2CHANNEL(scp) (scp)->device->channel // to channel -+#define SCP2TARGET(scp) (scp)->device->id // to target -+#define SCP2LUN(scp) (scp)->device->lun // to LUN -+ -+// generic macro to convert scsi command and host to controller's soft state -+#define SCSIHOST2ADAP(host) (((caddr_t *)(host->hostdata))[0]) -+#define SCP2ADAPTER(scp) (adapter_t *)SCSIHOST2ADAP(SCP2HOST(scp)) -+ -+ -+/** -+ * MRAID_GET_DEVICE_MAP - device ids -+ * @param adp - Adapter's soft state -+ * @param scp - mid-layer scsi command pointer -+ * @param p_chan - physical channel on the controller -+ * @param target - target id of the device or logical drive number -+ * @param islogical - set if the command is for the logical drive -+ * -+ * Macro to retrieve information about device class, logical or physical and -+ * the corresponding physical channel and target or logical drive number -+ **/ -+#define MRAID_IS_LOGICAL(adp, scp) \ -+ (SCP2CHANNEL(scp) == (adp)->max_channel) ? 1 : 0 -+ -+#define MRAID_IS_LOGICAL_SDEV(adp, sdev) \ -+ (sdev->channel == (adp)->max_channel) ? 1 : 0 -+ -+#define MRAID_GET_DEVICE_MAP(adp, scp, p_chan, target, islogical) \ -+ /* \ -+ * Is the request coming for the virtual channel \ -+ */ \ -+ islogical = MRAID_IS_LOGICAL(adp, scp); \ -+ \ -+ /* \ -+ * Get an index into our table of drive ids mapping \ -+ */ \ -+ if (islogical) { \ -+ p_chan = 0xFF; \ -+ target = \ -+ (adp)->device_ids[(adp)->max_channel][SCP2TARGET(scp)]; \ -+ } \ -+ else { \ -+ p_chan = ((adp)->device_ids[SCP2CHANNEL(scp)] \ -+ [SCP2TARGET(scp)] >> 8) & 0xFF; \ -+ target = ((adp)->device_ids[SCP2CHANNEL(scp)] \ -+ [SCP2TARGET(scp)] & 0xFF); \ -+ } -+ -+/* -+ * ### Helper routines ### -+ */ -+#define LSI_DBGLVL mraid_debug_level // each LLD must define a global -+ // mraid_debug_level -+ -+#ifdef DEBUG -+#if defined (_ASSERT_PANIC) -+#define ASSERT_ACTION panic -+#else -+#define ASSERT_ACTION printk -+#endif -+ -+#define ASSERT(expression) \ -+ if (!(expression)) { \ -+ ASSERT_ACTION("assertion failed:(%s), file: %s, line: %d:%s\n", \ -+ #expression, __FILE__, __LINE__, __FUNCTION__); \ -+ } -+#else -+#define ASSERT(expression) -+#endif -+ -+/* -+ * struct mraid_pci_blk - structure holds DMA memory block info -+ * @param vaddr : virtual address to a memory block -+ * @param dma_addr : DMA handle to a memory block -+ * -+ * This structure is filled up for the caller. It is the responsibilty of the -+ * caller to allocate this array big enough to store addresses for all -+ * requested elements -+ */ -+struct mraid_pci_blk { -+ caddr_t vaddr; -+ dma_addr_t dma_addr; -+}; -+ -+#endif // _MEGA_COMMON_H_ -+ -+// vim: set ts=8 sw=8 tw=78: ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid/megaraid_ioctl.h 1970-01-01 03:00:00.000000000 +0300 -+++ rhel4u2/drivers/scsi/megaraid/megaraid_ioctl.h 2005-10-19 11:47:15.000000000 +0400 -@@ -0,0 +1,296 @@ -+/* -+ * -+ * Linux MegaRAID device driver -+ * -+ * Copyright (c) 2003-2004 LSI Logic Corporation. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * FILE : megaraid_ioctl.h -+ * -+ * Definitions to interface with user level applications -+ */ -+ -+#ifndef _MEGARAID_IOCTL_H_ -+#define _MEGARAID_IOCTL_H_ -+ -+#include <linux/types.h> -+#include <asm/semaphore.h> -+ -+#include "mbox_defs.h" -+ -+/** -+ * con_log() - console log routine -+ * @param level : indicates the severity of the message. -+ * @fparam mt : format string -+ * -+ * con_log displays the error messages on the console based on the current -+ * debug level. Also it attaches the appropriate kernel severity level with -+ * the message. -+ * -+ * -+ * consolge messages debug levels -+ */ -+#define CL_ANN 0 /* print unconditionally, announcements */ -+#define CL_DLEVEL1 1 /* debug level 1, informative */ -+#define CL_DLEVEL2 2 /* debug level 2, verbose */ -+#define CL_DLEVEL3 3 /* debug level 3, very verbose */ -+ -+#define con_log(level, fmt) if (LSI_DBGLVL >= level) printk fmt; -+ -+/* -+ * Definitions & Declarations needed to use common management module -+ */ -+ -+#define MEGAIOC_MAGIC 'm' -+#define MEGAIOCCMD _IOWR(MEGAIOC_MAGIC, 0, mimd_t) -+ -+#define MEGAIOC_QNADAP 'm' /* Query # of adapters */ -+#define MEGAIOC_QDRVRVER 'e' /* Query driver version */ -+#define MEGAIOC_QADAPINFO 'g' /* Query adapter information */ -+ -+#define USCSICMD 0x80 -+#define UIOC_RD 0x00001 -+#define UIOC_WR 0x00002 -+ -+#define MBOX_CMD 0x00000 -+#define GET_DRIVER_VER 0x10000 -+#define GET_N_ADAP 0x20000 -+#define GET_ADAP_INFO 0x30000 -+#define GET_CAP 0x40000 -+#define GET_STATS 0x50000 -+#define GET_IOCTL_VERSION 0x01 -+ -+#define EXT_IOCTL_SIGN_SZ 16 -+#define EXT_IOCTL_SIGN "$$_EXTD_IOCTL_$$" -+ -+#define MBOX_LEGACY 0x00 /* ioctl has legacy mbox*/ -+#define MBOX_HPE 0x01 /* ioctl has hpe mbox */ -+ -+#define APPTYPE_MIMD 0x00 /* old existing apps */ -+#define APPTYPE_UIOC 0x01 /* new apps using uioc */ -+ -+#define IOCTL_ISSUE 0x00000001 /* Issue ioctl */ -+#define IOCTL_ABORT 0x00000002 /* Abort previous ioctl */ -+ -+#define DRVRTYPE_MBOX 0x00000001 /* regular mbox driver */ -+#define DRVRTYPE_HPE 0x00000002 /* new hpe driver */ -+ -+#define MKADAP(adapno) (MEGAIOC_MAGIC << 8 | (adapno) ) -+#define GETADAP(mkadap) ((mkadap) ^ MEGAIOC_MAGIC << 8) -+ -+#define MAX_DMA_POOLS 5 /* 4k, 8k, 16k, 32k, 64k*/ -+ -+ -+/** -+ * struct uioc_t - the common ioctl packet structure -+ * -+ * @signature : Must be "$$_EXTD_IOCTL_$$" -+ * @mb_type : Type of the mail box (MB_LEGACY or MB_HPE) -+ * @app_type : Type of the issuing application (existing or new) -+ * @opcode : Opcode of the command -+ * @adapno : Adapter number -+ * @cmdbuf : Pointer to buffer - can point to mbox or plain data buffer -+ * @xferlen : xferlen for DCMD and non mailbox commands -+ * @data_dir : Direction of the data transfer -+ * @status : Status from the driver -+ * @reserved : reserved bytes for future expansion -+ * -+ * @user_data : user data transfer address is saved in this -+ * @user_data_len: length of the data buffer sent by user app -+ * @user_pthru : user passthru address is saves in this (null if DCMD) -+ * @pthru32 : kernel address passthru (allocated per kioc) -+ * @pthru32_h : physicall address of @pthru32 -+ * @list : for kioc free pool list maintenance -+ * @done : call back routine for llds to call when kioc is completed -+ * @buf_vaddr : dma pool buffer attached to kioc for data transfer -+ * @buf_paddr : physical address of the dma pool buffer -+ * @pool_index : index of the dma pool that @buf_vaddr is taken from -+ * @free_buf : indicates if buffer needs to be freed after kioc completes -+ * -+ * Note : All LSI drivers understand only this packet. Any other -+ * : format sent by applications would be converted to this. -+ */ -+typedef struct uioc { -+ -+/* User Apps: */ -+ -+ uint8_t signature[EXT_IOCTL_SIGN_SZ]; -+ uint16_t mb_type; -+ uint16_t app_type; -+ uint32_t opcode; -+ uint32_t adapno; -+ uint64_t cmdbuf; -+ uint32_t xferlen; -+ uint32_t data_dir; -+ int32_t status; -+ uint8_t reserved[128]; -+ -+/* Driver Data: */ -+ void __user * user_data; -+ uint32_t user_data_len; -+ mraid_passthru_t __user *user_pthru; -+ -+ mraid_passthru_t *pthru32; -+ dma_addr_t pthru32_h; -+ -+ struct list_head list; -+ void (*done)(struct uioc*); -+ -+ caddr_t buf_vaddr; -+ dma_addr_t buf_paddr; -+ int8_t pool_index; -+ uint8_t free_buf; -+ -+ uint8_t timedout; -+ -+} __attribute__ ((aligned(1024),packed)) uioc_t; -+ -+ -+/** -+ * struct mraid_hba_info - information about the controller -+ * -+ * @param pci_vendor_id : PCI vendor id -+ * @param pci_device_id : PCI device id -+ * @param subsystem_vendor_id : PCI subsystem vendor id -+ * @param subsystem_device_id : PCI subsystem device id -+ * @param baseport : base port of hba memory -+ * @param pci_bus : PCI bus -+ * @param pci_dev_fn : PCI device/function values -+ * @param irq : interrupt vector for the device -+ * -+ * Extended information of 256 bytes about the controller. Align on the single -+ * byte boundary so that 32-bit applications can be run on 64-bit platform -+ * drivers withoug re-compilation. -+ * NOTE: reduce the number of reserved bytes whenever new field are added, so -+ * that total size of the structure remains 256 bytes. -+ */ -+typedef struct mraid_hba_info { -+ -+ uint16_t pci_vendor_id; -+ uint16_t pci_device_id; -+ uint16_t subsys_vendor_id; -+ uint16_t subsys_device_id; -+ -+ uint64_t baseport; -+ uint8_t pci_bus; -+ uint8_t pci_dev_fn; -+ uint8_t pci_slot; -+ uint8_t irq; -+ -+ uint32_t unique_id; -+ uint32_t host_no; -+ -+ uint8_t num_ldrv; -+} __attribute__ ((aligned(256), packed)) mraid_hba_info_t; -+ -+ -+/** -+ * mcontroller : adapter info structure for old mimd_t apps -+ * -+ * @base : base address -+ * @irq : irq number -+ * @numldrv : number of logical drives -+ * @pcibus : pci bus -+ * @pcidev : pci device -+ * @pcifun : pci function -+ * @pciid : pci id -+ * @pcivendor : vendor id -+ * @pcislot : slot number -+ * @uid : unique id -+ */ -+typedef struct mcontroller { -+ -+ uint64_t base; -+ uint8_t irq; -+ uint8_t numldrv; -+ uint8_t pcibus; -+ uint16_t pcidev; -+ uint8_t pcifun; -+ uint16_t pciid; -+ uint16_t pcivendor; -+ uint8_t pcislot; -+ uint32_t uid; -+ -+} __attribute__ ((packed)) mcontroller_t; -+ -+ -+/** -+ * mm_dmapool_t : Represents one dma pool with just one buffer -+ * -+ * @vaddr : Virtual address -+ * @paddr : DMA physicall address -+ * @bufsize : In KB - 4 = 4k, 8 = 8k etc. -+ * @handle : Handle to the dma pool -+ * @lock : lock to synchronize access to the pool -+ * @in_use : If pool already in use, attach new block -+ */ -+typedef struct mm_dmapool { -+ caddr_t vaddr; -+ dma_addr_t paddr; -+ uint32_t buf_size; -+ struct dma_pool *handle; -+ spinlock_t lock; -+ uint8_t in_use; -+} mm_dmapool_t; -+ -+ -+/** -+ * mraid_mmadp_t: Structure that drivers pass during (un)registration -+ * -+ * @unique_id : Any unique id (usually PCI bus+dev+fn) -+ * @drvr_type : megaraid or hpe (DRVRTYPE_MBOX or DRVRTYPE_HPE) -+ * @drv_data : Driver specific; not touched by the common module -+ * @timeout : timeout for issued kiocs -+ * @max_kioc : Maximum ioctl packets acceptable by the lld -+ * @pdev : pci dev; used for allocating dma'ble memory -+ * @issue_uioc : Driver supplied routine to issue uioc_t commands -+ * : issue_uioc(drvr_data, kioc, ISSUE/ABORT, uioc_done) -+ * @quiescent : flag to indicate if ioctl can be issued to this adp -+ * @list : attach with the global list of adapters -+ * @kioc_list : block of mem for @max_kioc number of kiocs -+ * @kioc_pool : pool of free kiocs -+ * @kioc_pool_lock : protection for free pool -+ * @kioc_semaphore : so as not to exceed @max_kioc parallel ioctls -+ * @mbox_list : block of mem for @max_kioc number of mboxes -+ * @pthru_dma_pool : DMA pool to allocate passthru packets -+ * @dma_pool_list : array of dma pools -+ */ -+ -+typedef struct mraid_mmadp { -+ -+/* Filled by driver */ -+ -+ uint32_t unique_id; -+ uint32_t drvr_type; -+ unsigned long drvr_data; -+ uint16_t timeout; -+ uint8_t max_kioc; -+ -+ struct pci_dev *pdev; -+ -+ int(*issue_uioc)(unsigned long, uioc_t *, uint32_t); -+ -+/* Maintained by common module */ -+ uint32_t quiescent; -+ -+ struct list_head list; -+ uioc_t *kioc_list; -+ struct list_head kioc_pool; -+ spinlock_t kioc_pool_lock; -+ struct semaphore kioc_semaphore; -+ -+ mbox64_t *mbox_list; -+ struct dma_pool *pthru_dma_pool; -+ mm_dmapool_t dma_pool_list[MAX_DMA_POOLS]; -+ -+} mraid_mmadp_t; -+ -+int mraid_mm_register_adp(mraid_mmadp_t *); -+int mraid_mm_unregister_adp(uint32_t); -+uint32_t mraid_mm_adapter_app_handle(uint32_t); -+ -+#endif /* _MEGARAID_IOCTL_H_ */ ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid/megaraid_mbox.c 1970-01-01 03:00:00.000000000 +0300 -+++ rhel4u2/drivers/scsi/megaraid/megaraid_mbox.c 2005-10-20 14:45:58.746974688 +0400 -@@ -0,0 +1,4183 @@ -+/* -+ * -+ * Linux MegaRAID device driver -+ * -+ * Copyright (c) 2003-2004 LSI Logic Corporation. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * FILE : megaraid_mbox.c -+ * Version : v2.20.4.6 (Mar 07 2005) -+ * -+ * Authors: -+ * Atul Mukker <Atul.Mukker@lsil.com> -+ * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com> -+ * Manoj Jose <Manoj.Jose@lsil.com> -+ * -+ * List of supported controllers -+ * -+ * OEM Product Name VID DID SSVID SSID -+ * --- ------------ --- --- ---- ---- -+ * Dell PERC3/QC 101E 1960 1028 0471 -+ * Dell PERC3/DC 101E 1960 1028 0493 -+ * Dell PERC3/SC 101E 1960 1028 0475 -+ * Dell PERC3/Di 1028 1960 1028 0123 -+ * Dell PERC4/SC 1000 1960 1028 0520 -+ * Dell PERC4/DC 1000 1960 1028 0518 -+ * Dell PERC4/QC 1000 0407 1028 0531 -+ * Dell PERC4/Di 1028 000F 1028 014A -+ * Dell PERC 4e/Si 1028 0013 1028 016c -+ * Dell PERC 4e/Di 1028 0013 1028 016d -+ * Dell PERC 4e/Di 1028 0013 1028 016e -+ * Dell PERC 4e/Di 1028 0013 1028 016f -+ * Dell PERC 4e/Di 1028 0013 1028 0170 -+ * Dell PERC 4e/DC 1000 0408 1028 0002 -+ * Dell PERC 4e/SC 1000 0408 1028 0001 -+ * -+ * -+ * LSI MegaRAID SCSI 320-0 1000 1960 1000 A520 -+ * LSI MegaRAID SCSI 320-1 1000 1960 1000 0520 -+ * LSI MegaRAID SCSI 320-2 1000 1960 1000 0518 -+ * LSI MegaRAID SCSI 320-0X 1000 0407 1000 0530 -+ * LSI MegaRAID SCSI 320-2X 1000 0407 1000 0532 -+ * LSI MegaRAID SCSI 320-4X 1000 0407 1000 0531 -+ * LSI MegaRAID SCSI 320-1E 1000 0408 1000 0001 -+ * LSI MegaRAID SCSI 320-2E 1000 0408 1000 0002 -+ * LSI MegaRAID SATA 150-4 1000 1960 1000 4523 -+ * LSI MegaRAID SATA 150-6 1000 1960 1000 0523 -+ * LSI MegaRAID SATA 300-4X 1000 0409 1000 3004 -+ * LSI MegaRAID SATA 300-8X 1000 0409 1000 3008 -+ * -+ * INTEL RAID Controller SRCU42X 1000 0407 8086 0532 -+ * INTEL RAID Controller SRCS16 1000 1960 8086 0523 -+ * INTEL RAID Controller SRCU42E 1000 0408 8086 0002 -+ * INTEL RAID Controller SRCZCRX 1000 0407 8086 0530 -+ * INTEL RAID Controller SRCS28X 1000 0409 8086 3008 -+ * INTEL RAID Controller SROMBU42E 1000 0408 8086 3431 -+ * INTEL RAID Controller SROMBU42E 1000 0408 8086 3499 -+ * INTEL RAID Controller SRCU51L 1000 1960 8086 0520 -+ * -+ * FSC MegaRAID PCI Express ROMB 1000 0408 1734 1065 -+ * -+ * ACER MegaRAID ROMB-2E 1000 0408 1025 004D -+ * -+ * NEC MegaRAID PCI Express ROMB 1000 0408 1033 8287 -+ * -+ * For history of changes, see Documentation/ChangeLog.megaraid -+ */ -+ -+#include "megaraid_mbox.h" -+ -+static int megaraid_init(void); -+static void megaraid_exit(void); -+ -+static int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *); -+static void megaraid_detach_one(struct pci_dev *); -+static void megaraid_mbox_shutdown(struct device *); -+ -+static int megaraid_io_attach(adapter_t *); -+static void megaraid_io_detach(adapter_t *); -+ -+static int megaraid_init_mbox(adapter_t *); -+static void megaraid_fini_mbox(adapter_t *); -+ -+static int megaraid_alloc_cmd_packets(adapter_t *); -+static void megaraid_free_cmd_packets(adapter_t *); -+ -+static int megaraid_mbox_setup_dma_pools(adapter_t *); -+static void megaraid_mbox_teardown_dma_pools(adapter_t *); -+ -+static int megaraid_sysfs_alloc_resources(adapter_t *); -+static void megaraid_sysfs_free_resources(adapter_t *); -+ -+static int megaraid_abort_handler(struct scsi_cmnd *); -+static int megaraid_reset_handler(struct scsi_cmnd *); -+ -+static int mbox_post_sync_cmd(adapter_t *, uint8_t []); -+static int mbox_post_sync_cmd_fast(adapter_t *, uint8_t []); -+static int megaraid_busywait_mbox(mraid_device_t *); -+static int megaraid_mbox_product_info(adapter_t *); -+static int megaraid_mbox_extended_cdb(adapter_t *); -+static int megaraid_mbox_support_ha(adapter_t *, uint16_t *); -+static int megaraid_mbox_support_random_del(adapter_t *); -+static int megaraid_mbox_get_max_sg(adapter_t *); -+static void megaraid_mbox_enum_raid_scsi(adapter_t *); -+static void megaraid_mbox_flush_cache(adapter_t *); -+ -+static void megaraid_mbox_display_scb(adapter_t *, scb_t *); -+static void megaraid_mbox_setup_device_map(adapter_t *); -+ -+static int megaraid_queue_command(struct scsi_cmnd *, -+ void (*)(struct scsi_cmnd *)); -+static scb_t *megaraid_mbox_build_cmd(adapter_t *, struct scsi_cmnd *, int *); -+static void megaraid_mbox_runpendq(adapter_t *, scb_t *); -+static void megaraid_mbox_prepare_pthru(adapter_t *, scb_t *, -+ struct scsi_cmnd *); -+static void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *, -+ struct scsi_cmnd *); -+ -+static irqreturn_t megaraid_isr(int, void *, struct pt_regs *); -+ -+static void megaraid_mbox_dpc(unsigned long); -+ -+static ssize_t megaraid_sysfs_show_app_hndl(struct class_device *, char *); -+static ssize_t megaraid_sysfs_show_ldnum(struct device *, char *); -+ -+static int megaraid_cmm_register(adapter_t *); -+static int megaraid_cmm_unregister(adapter_t *); -+static int megaraid_mbox_mm_handler(unsigned long, uioc_t *, uint32_t); -+static int megaraid_mbox_mm_command(adapter_t *, uioc_t *); -+static void megaraid_mbox_mm_done(adapter_t *, scb_t *); -+static int gather_hbainfo(adapter_t *, mraid_hba_info_t *); -+static int wait_till_fw_empty(adapter_t *); -+ -+ -+ -+MODULE_AUTHOR("LSI Logic Corporation"); -+MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(MEGARAID_VERSION); -+ -+/* -+ * ### modules parameters for driver ### -+ */ -+ -+/** -+ * Set to enable driver to expose unconfigured disk to kernel -+ */ -+static int megaraid_expose_unconf_disks = 0; -+module_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0); -+MODULE_PARM_DESC(unconf_disks, -+ "Set to expose unconfigured disks to kernel (default=0)"); -+ -+/** -+ * driver wait time if the adapter's mailbox is busy -+ */ -+static unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT; -+module_param_named(busy_wait, max_mbox_busy_wait, int, 0); -+MODULE_PARM_DESC(busy_wait, -+ "Max wait for mailbox in microseconds if busy (default=10)"); -+ -+/** -+ * number of sectors per IO command -+ */ -+static unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS; -+module_param_named(max_sectors, megaraid_max_sectors, int, 0); -+MODULE_PARM_DESC(max_sectors, -+ "Maximum number of sectors per IO command (default=128)"); -+ -+/** -+ * number of commands per logical unit -+ */ -+static unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN; -+module_param_named(cmd_per_lun, megaraid_cmd_per_lun, int, 0); -+MODULE_PARM_DESC(cmd_per_lun, -+ "Maximum number of commands per logical unit (default=64)"); -+ -+ -+/** -+ * Fast driver load option, skip scanning for physical devices during load. -+ * This would result in non-disk devices being skipped during driver load -+ * time. These can be later added though, using /proc/scsi/scsi -+ */ -+static unsigned int megaraid_fast_load = 0; -+module_param_named(fast_load, megaraid_fast_load, int, 0); -+MODULE_PARM_DESC(fast_load, -+ "Faster loading of the driver, skips physical devices! (default=0)"); -+ -+ -+/** -+ * mraid_debug level - threshold for amount of information to be displayed by -+ * the driver. This level can be changed through modules parameters, ioctl or -+ * sysfs/proc interface. By default, print the announcement messages only. -+ */ -+int mraid_debug_level = CL_ANN; -+module_param_named(debug_level, mraid_debug_level, int, 0); -+MODULE_PARM_DESC(debug_level, "Debug level for driver (default=0)"); -+ -+/* -+ * ### global data ### -+ */ -+static uint8_t megaraid_mbox_version[8] = -+ { 0x02, 0x20, 0x04, 0x06, 3, 7, 20, 5 }; -+ -+ -+/* -+ * PCI table for all supported controllers. -+ */ -+static struct pci_device_id pci_id_table_g[] = { -+ { -+ PCI_VENDOR_ID_DELL, -+ PCI_DEVICE_ID_PERC4_DI_DISCOVERY, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC4_DI_DISCOVERY, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_PERC4_SC, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC4_SC, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_PERC4_DC, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC4_DC, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_VERDE, -+ PCI_ANY_ID, -+ PCI_ANY_ID, -+ }, -+ { -+ PCI_VENDOR_ID_DELL, -+ PCI_DEVICE_ID_PERC4_DI_EVERGLADES, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC4_DI_EVERGLADES, -+ }, -+ { -+ PCI_VENDOR_ID_DELL, -+ PCI_DEVICE_ID_PERC4E_SI_BIGBEND, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC4E_SI_BIGBEND, -+ }, -+ { -+ PCI_VENDOR_ID_DELL, -+ PCI_DEVICE_ID_PERC4E_DI_KOBUK, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC4E_DI_KOBUK, -+ }, -+ { -+ PCI_VENDOR_ID_DELL, -+ PCI_DEVICE_ID_PERC4E_DI_CORVETTE, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC4E_DI_CORVETTE, -+ }, -+ { -+ PCI_VENDOR_ID_DELL, -+ PCI_DEVICE_ID_PERC4E_DI_EXPEDITION, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION, -+ }, -+ { -+ PCI_VENDOR_ID_DELL, -+ PCI_DEVICE_ID_PERC4E_DI_GUADALUPE, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_DOBSON, -+ PCI_ANY_ID, -+ PCI_ANY_ID, -+ }, -+ { -+ PCI_VENDOR_ID_AMI, -+ PCI_DEVICE_ID_AMI_MEGARAID3, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC3_QC, -+ }, -+ { -+ PCI_VENDOR_ID_AMI, -+ PCI_DEVICE_ID_AMI_MEGARAID3, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC3_DC, -+ }, -+ { -+ PCI_VENDOR_ID_AMI, -+ PCI_DEVICE_ID_AMI_MEGARAID3, -+ PCI_VENDOR_ID_DELL, -+ PCI_SUBSYS_ID_PERC3_SC, -+ }, -+ { -+ PCI_VENDOR_ID_AMI, -+ PCI_DEVICE_ID_AMI_MEGARAID3, -+ PCI_VENDOR_ID_AMI, -+ PCI_SUBSYS_ID_PERC3_SC, -+ }, -+ { -+ PCI_VENDOR_ID_AMI, -+ PCI_DEVICE_ID_AMI_MEGARAID3, -+ PCI_VENDOR_ID_AMI, -+ PCI_SUBSYS_ID_PERC3_DC, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_MEGARAID_SCSI_320_0, -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_SUBSYS_ID_MEGARAID_SCSI_320_0, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_MEGARAID_SCSI_320_1, -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_SUBSYS_ID_MEGARAID_SCSI_320_1, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_MEGARAID_SCSI_320_2, -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_SUBSYS_ID_MEGARAID_SCSI_320_2, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_MEGARAID_I4_133_RAID, -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_SUBSYS_ID_MEGARAID_I4_133_RAID, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_MEGARAID_SATA_150_4, -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_SUBSYS_ID_MEGARAID_SATA_150_4, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_MEGARAID_SATA_150_6, -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_SUBSYS_ID_MEGARAID_SATA_150_6, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_LINDSAY, -+ PCI_ANY_ID, -+ PCI_ANY_ID, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_INTEL_RAID_SRCS16, -+ PCI_VENDOR_ID_INTEL, -+ PCI_SUBSYS_ID_INTEL_RAID_SRCS16, -+ }, -+ { -+ PCI_VENDOR_ID_LSI_LOGIC, -+ PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK, -+ PCI_VENDOR_ID_INTEL, -+ PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK, -+ }, -+ {0} /* Terminating entry */ -+}; -+MODULE_DEVICE_TABLE(pci, pci_id_table_g); -+ -+ -+static struct pci_driver megaraid_pci_driver_g = { -+ .name = "megaraid", -+ .id_table = pci_id_table_g, -+ .probe = megaraid_probe_one, -+ .remove = __devexit_p(megaraid_detach_one), -+ .driver = { -+ .shutdown = megaraid_mbox_shutdown, -+ } -+}; -+ -+ -+ -+// definitions for the device attributes for exporting logical drive number -+// for a scsi address (Host, Channel, Id, Lun) -+ -+CLASS_DEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl, -+ NULL); -+ -+// Host template initializer for megaraid mbox sysfs device attributes -+static struct class_device_attribute *megaraid_shost_attrs[] = { -+ &class_device_attr_megaraid_mbox_app_hndl, -+ NULL, -+}; -+ -+ -+DEVICE_ATTR(megaraid_mbox_ld, S_IRUSR, megaraid_sysfs_show_ldnum, NULL); -+ -+// Host template initializer for megaraid mbox sysfs device attributes -+static struct device_attribute *megaraid_sdev_attrs[] = { -+ &dev_attr_megaraid_mbox_ld, -+ NULL, -+}; -+ -+ -+/* -+ * Scsi host template for megaraid unified driver -+ */ -+static struct scsi_host_template megaraid_template_g = { -+ .module = THIS_MODULE, -+ .name = "LSI Logic MegaRAID driver", -+ .proc_name = "megaraid", -+ .queuecommand = megaraid_queue_command, -+ .eh_abort_handler = megaraid_abort_handler, -+ .eh_device_reset_handler = megaraid_reset_handler, -+ .eh_bus_reset_handler = megaraid_reset_handler, -+ .eh_host_reset_handler = megaraid_reset_handler, -+ .use_clustering = ENABLE_CLUSTERING, -+ .sdev_attrs = megaraid_sdev_attrs, -+ .shost_attrs = megaraid_shost_attrs, -+}; -+ -+ -+/** -+ * megaraid_init - module load hook -+ * -+ * We register ourselves as hotplug enabled module and let PCI subsystem -+ * discover our adaters -+ **/ -+static int __init -+megaraid_init(void) -+{ -+ int rval; -+ -+ // Announce the driver version -+ con_log(CL_ANN, (KERN_INFO "megaraid: %s %s\n", MEGARAID_VERSION, -+ MEGARAID_EXT_VERSION)); -+ -+ // check validity of module parameters -+ if (megaraid_cmd_per_lun > MBOX_MAX_SCSI_CMDS) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mailbox: max commands per lun reset to %d\n", -+ MBOX_MAX_SCSI_CMDS)); -+ -+ megaraid_cmd_per_lun = MBOX_MAX_SCSI_CMDS; -+ } -+ -+ -+ // register as a PCI hot-plug driver module -+ rval = pci_register_driver(&megaraid_pci_driver_g); -+ if (rval < 0) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: could not register hotplug support.\n")); -+ } -+ -+ return rval; -+} -+ -+ -+/** -+ * megaraid_exit - driver unload entry point -+ * -+ * We simply unwrap the megaraid_init routine here -+ */ -+static void __exit -+megaraid_exit(void) -+{ -+ con_log(CL_DLEVEL1, (KERN_NOTICE "megaraid: unloading framework\n")); -+ -+ // unregister as PCI hotplug driver -+ pci_unregister_driver(&megaraid_pci_driver_g); -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_probe_one - PCI hotplug entry point -+ * @param pdev : handle to this controller's PCI configuration space -+ * @param id : pci device id of the class of controllers -+ * -+ * This routine should be called whenever a new adapter is detected by the -+ * PCI hotplug susbsytem. -+ **/ -+static int __devinit -+megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ adapter_t *adapter; -+ -+ -+ // detected a new controller -+ con_log(CL_ANN, (KERN_INFO -+ "megaraid: probe new device %#4.04x:%#4.04x:%#4.04x:%#4.04x: ", -+ pdev->vendor, pdev->device, pdev->subsystem_vendor, -+ pdev->subsystem_device)); -+ -+ con_log(CL_ANN, ("bus %d:slot %d:func %d\n", pdev->bus->number, -+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn))); -+ -+ if (pci_enable_device(pdev)) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: pci_enable_device failed\n")); -+ -+ return -ENODEV; -+ } -+ -+ // Enable bus-mastering on this controller -+ pci_set_master(pdev); -+ -+ // Allocate the per driver initialization structure -+ adapter = kmalloc(sizeof(adapter_t), GFP_KERNEL); -+ -+ if (adapter == NULL) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: out of memory, %s %d.\n", __FUNCTION__, __LINE__)); -+ -+ goto out_probe_one; -+ } -+ memset(adapter, 0, sizeof(adapter_t)); -+ -+ -+ // set up PCI related soft state and other pre-known parameters -+ adapter->unique_id = pdev->bus->number << 8 | pdev->devfn; -+ adapter->irq = pdev->irq; -+ adapter->pdev = pdev; -+ -+ atomic_set(&adapter->being_detached, 0); -+ -+ // Setup the default DMA mask. This would be changed later on -+ // depending on hardware capabilities -+ if (pci_set_dma_mask(adapter->pdev, DMA_32BIT_MASK) != 0) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: pci_set_dma_mask failed:%d\n", __LINE__)); -+ -+ goto out_free_adapter; -+ } -+ -+ -+ // Initialize the synchronization lock for kernel and LLD -+ spin_lock_init(&adapter->lock); -+ adapter->host_lock = &adapter->lock; -+ -+ -+ // Initialize the command queues: the list of free SCBs and the list -+ // of pending SCBs. -+ INIT_LIST_HEAD(&adapter->kscb_pool); -+ spin_lock_init(SCSI_FREE_LIST_LOCK(adapter)); -+ -+ INIT_LIST_HEAD(&adapter->pend_list); -+ spin_lock_init(PENDING_LIST_LOCK(adapter)); -+ -+ INIT_LIST_HEAD(&adapter->completed_list); -+ spin_lock_init(COMPLETED_LIST_LOCK(adapter)); -+ -+ -+ // Start the mailbox based controller -+ if (megaraid_init_mbox(adapter) != 0) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: maibox adapter did not initialize\n")); -+ -+ goto out_free_adapter; -+ } -+ -+ // Register with LSI Common Management Module -+ if (megaraid_cmm_register(adapter) != 0) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: could not register with management module\n")); -+ -+ goto out_fini_mbox; -+ } -+ -+ // setup adapter handle in PCI soft state -+ pci_set_drvdata(pdev, adapter); -+ -+ // attach with scsi mid-layer -+ if (megaraid_io_attach(adapter) != 0) { -+ -+ con_log(CL_ANN, (KERN_WARNING "megaraid: io attach failed\n")); -+ -+ goto out_cmm_unreg; -+ } -+ -+ return 0; -+ -+out_cmm_unreg: -+ pci_set_drvdata(pdev, NULL); -+ megaraid_cmm_unregister(adapter); -+out_fini_mbox: -+ megaraid_fini_mbox(adapter); -+out_free_adapter: -+ kfree(adapter); -+out_probe_one: -+ pci_disable_device(pdev); -+ -+ return -ENODEV; -+} -+ -+ -+/** -+ * megaraid_detach_one - release the framework resources and call LLD release -+ * routine -+ * @param pdev : handle for our PCI cofiguration space -+ * -+ * This routine is called during driver unload. We free all the allocated -+ * resources and call the corresponding LLD so that it can also release all -+ * its resources. -+ * -+ * This routine is also called from the PCI hotplug system -+ **/ -+static void -+megaraid_detach_one(struct pci_dev *pdev) -+{ -+ adapter_t *adapter; -+ struct Scsi_Host *host; -+ -+ -+ // Start a rollback on this adapter -+ adapter = pci_get_drvdata(pdev); -+ -+ if (!adapter) { -+ con_log(CL_ANN, (KERN_CRIT -+ "megaraid: Invalid detach on %#4.04x:%#4.04x:%#4.04x:%#4.04x\n", -+ pdev->vendor, pdev->device, pdev->subsystem_vendor, -+ pdev->subsystem_device)); -+ -+ return; -+ } -+ else { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: detaching device %#4.04x:%#4.04x:%#4.04x:%#4.04x\n", -+ pdev->vendor, pdev->device, pdev->subsystem_vendor, -+ pdev->subsystem_device)); -+ } -+ -+ -+ host = adapter->host; -+ -+ // do not allow any more requests from the management module for this -+ // adapter. -+ // FIXME: How do we account for the request which might still be -+ // pending with us? -+ atomic_set(&adapter->being_detached, 1); -+ -+ // detach from the IO sub-system -+ megaraid_io_detach(adapter); -+ -+ // reset the device state in the PCI structure. We check this -+ // condition when we enter here. If the device state is NULL, -+ // that would mean the device has already been removed -+ pci_set_drvdata(pdev, NULL); -+ -+ // Unregister from common management module -+ // -+ // FIXME: this must return success or failure for conditions if there -+ // is a command pending with LLD or not. -+ megaraid_cmm_unregister(adapter); -+ -+ // finalize the mailbox based controller and release all resources -+ megaraid_fini_mbox(adapter); -+ -+ kfree(adapter); -+ -+ scsi_host_put(host); -+ -+ pci_disable_device(pdev); -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA -+ * @param device : generice driver model device -+ * -+ * Shutdown notification, perform flush cache -+ */ -+static void -+megaraid_mbox_shutdown(struct device *device) -+{ -+ adapter_t *adapter = pci_get_drvdata(to_pci_dev(device)); -+ static int counter; -+ -+ if (!adapter) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: null device in shutdown\n")); -+ return; -+ } -+ -+ // flush caches now -+ con_log(CL_ANN, (KERN_INFO "megaraid: flushing adapter %d...", -+ counter++)); -+ -+ megaraid_mbox_flush_cache(adapter); -+ -+ con_log(CL_ANN, ("done\n")); -+} -+ -+ -+/** -+ * megaraid_io_attach - attach a device with the IO subsystem -+ * @param adapter : controller's soft state -+ * -+ * Attach this device with the IO subsystem -+ **/ -+static int -+megaraid_io_attach(adapter_t *adapter) -+{ -+ struct Scsi_Host *host; -+ -+ // Initialize SCSI Host structure -+ host = scsi_host_alloc(&megaraid_template_g, 8); -+ if (!host) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mbox: scsi_register failed\n")); -+ -+ return -1; -+ } -+ -+ SCSIHOST2ADAP(host) = (caddr_t)adapter; -+ adapter->host = host; -+ -+ // export the parameters required by the mid-layer -+ scsi_assign_lock(host, adapter->host_lock); -+ scsi_set_device(host, &adapter->pdev->dev); -+ -+ host->irq = adapter->irq; -+ host->unique_id = adapter->unique_id; -+ host->can_queue = adapter->max_cmds; -+ host->this_id = adapter->init_id; -+ host->sg_tablesize = adapter->sglen; -+ host->max_sectors = adapter->max_sectors; -+ host->cmd_per_lun = adapter->cmd_per_lun; -+ host->max_channel = adapter->max_channel; -+ host->max_id = adapter->max_target; -+ host->max_lun = adapter->max_lun; -+ -+ -+ // notify mid-layer about the new controller -+ if (scsi_add_host(host, &adapter->pdev->dev)) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mbox: scsi_add_host failed\n")); -+ -+ scsi_host_put(host); -+ -+ return -1; -+ } -+ -+ scsi_scan_host(host); -+ -+ return 0; -+} -+ -+ -+/** -+ * megaraid_io_detach - detach a device from the IO subsystem -+ * @param adapter : controller's soft state -+ * -+ * Detach this device from the IO subsystem -+ **/ -+static void -+megaraid_io_detach(adapter_t *adapter) -+{ -+ struct Scsi_Host *host; -+ -+ con_log(CL_DLEVEL1, (KERN_INFO "megaraid: io detach\n")); -+ -+ host = adapter->host; -+ -+ scsi_remove_host(host); -+ -+ return; -+} -+ -+ -+/* -+ * START: Mailbox Low Level Driver -+ * -+ * This is section specific to the single mailbox based controllers -+ */ -+ -+/** -+ * megaraid_init_mbox - initialize controller -+ * @param adapter - our soft state -+ * -+ * . Allocate 16-byte aligned mailbox memory for firmware handshake -+ * . Allocate controller's memory resources -+ * . Find out all initialization data -+ * . Allocate memory required for all the commands -+ * . Use internal library of FW routines, build up complete soft state -+ */ -+static int __init -+megaraid_init_mbox(adapter_t *adapter) -+{ -+ struct pci_dev *pdev; -+ mraid_device_t *raid_dev; -+ int i; -+ -+ -+ adapter->ito = MBOX_TIMEOUT; -+ pdev = adapter->pdev; -+ -+ /* -+ * Allocate and initialize the init data structure for mailbox -+ * controllers -+ */ -+ raid_dev = kmalloc(sizeof(mraid_device_t), GFP_KERNEL); -+ if (raid_dev == NULL) return -1; -+ -+ memset(raid_dev, 0, sizeof(mraid_device_t)); -+ -+ /* -+ * Attach the adapter soft state to raid device soft state -+ */ -+ adapter->raid_device = (caddr_t)raid_dev; -+ raid_dev->fast_load = megaraid_fast_load; -+ -+ -+ // our baseport -+ raid_dev->baseport = pci_resource_start(pdev, 0); -+ -+ if (pci_request_regions(pdev, "MegaRAID: LSI Logic Corporation") != 0) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: mem region busy\n")); -+ -+ goto out_free_raid_dev; -+ } -+ -+ raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128); -+ -+ if (!raid_dev->baseaddr) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: could not map hba memory\n") ); -+ -+ goto out_release_regions; -+ } -+ -+ // -+ // Setup the rest of the soft state using the library of FW routines -+ // -+ -+ // request IRQ and register the interrupt service routine -+ if (request_irq(adapter->irq, megaraid_isr, SA_SHIRQ, "megaraid", -+ adapter)) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: Couldn't register IRQ %d!\n", adapter->irq)); -+ -+ goto out_iounmap; -+ } -+ -+ -+ // initialize the mutual exclusion lock for the mailbox -+ spin_lock_init(&raid_dev->mailbox_lock); -+ -+ // allocate memory required for commands -+ if (megaraid_alloc_cmd_packets(adapter) != 0) { -+ goto out_free_irq; -+ } -+ -+ // Product info -+ if (megaraid_mbox_product_info(adapter) != 0) { -+ goto out_alloc_cmds; -+ } -+ -+ // Do we support extended CDBs -+ adapter->max_cdb_sz = 10; -+ if (megaraid_mbox_extended_cdb(adapter) == 0) { -+ adapter->max_cdb_sz = 16; -+ } -+ -+ /* -+ * Do we support cluster environment, if we do, what is the initiator -+ * id. -+ * NOTE: In a non-cluster aware firmware environment, the LLD should -+ * return 7 as initiator id. -+ */ -+ adapter->ha = 0; -+ adapter->init_id = -1; -+ if (megaraid_mbox_support_ha(adapter, &adapter->init_id) == 0) { -+ adapter->ha = 1; -+ } -+ -+ /* -+ * Prepare the device ids array to have the mapping between the kernel -+ * device address and megaraid device address. -+ * We export the physical devices on their actual addresses. The -+ * logical drives are exported on a virtual SCSI channel -+ */ -+ megaraid_mbox_setup_device_map(adapter); -+ -+ // If the firmware supports random deletion, update the device id map -+ if (megaraid_mbox_support_random_del(adapter)) { -+ -+ // Change the logical drives numbers in device_ids array one -+ // slot in device_ids is reserved for target id, that's why -+ // "<=" below -+ for (i = 0; i <= MAX_LOGICAL_DRIVES_40LD; i++) { -+ adapter->device_ids[adapter->max_channel][i] += 0x80; -+ } -+ adapter->device_ids[adapter->max_channel][adapter->init_id] = -+ 0xFF; -+ -+ raid_dev->random_del_supported = 1; -+ } -+ -+ /* -+ * find out the maximum number of scatter-gather elements supported by -+ * this firmware -+ */ -+ adapter->sglen = megaraid_mbox_get_max_sg(adapter); -+ -+ // enumerate RAID and SCSI channels so that all devices on SCSI -+ // channels can later be exported, including disk devices -+ megaraid_mbox_enum_raid_scsi(adapter); -+ -+ /* -+ * Other parameters required by upper layer -+ * -+ * maximum number of sectors per IO command -+ */ -+ adapter->max_sectors = megaraid_max_sectors; -+ -+ /* -+ * number of queued commands per LUN. -+ */ -+ adapter->cmd_per_lun = megaraid_cmd_per_lun; -+ -+ /* -+ * Allocate resources required to issue FW calls, when sysfs is -+ * accessed -+ */ -+ if (megaraid_sysfs_alloc_resources(adapter) != 0) { -+ goto out_alloc_cmds; -+ } -+ -+ // Set the DMA mask to 64-bit. All supported controllers as capable of -+ // DMA in this range -+ if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK) != 0) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: could not set DMA mask for 64-bit.\n")); -+ -+ goto out_free_sysfs_res; -+ } -+ -+ // setup tasklet for DPC -+ tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc, -+ (unsigned long)adapter); -+ -+ con_log(CL_DLEVEL1, (KERN_INFO -+ "megaraid mbox hba successfully initialized\n")); -+ -+ return 0; -+ -+out_free_sysfs_res: -+ megaraid_sysfs_free_resources(adapter); -+out_alloc_cmds: -+ megaraid_free_cmd_packets(adapter); -+out_free_irq: -+ free_irq(adapter->irq, adapter); -+out_iounmap: -+ iounmap(raid_dev->baseaddr); -+out_release_regions: -+ pci_release_regions(pdev); -+out_free_raid_dev: -+ kfree(raid_dev); -+ -+ return -1; -+} -+ -+ -+/** -+ * megaraid_fini_mbox - undo controller initialization -+ * @param adapter : our soft state -+ */ -+static void -+megaraid_fini_mbox(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ -+ // flush all caches -+ megaraid_mbox_flush_cache(adapter); -+ -+ tasklet_kill(&adapter->dpc_h); -+ -+ megaraid_sysfs_free_resources(adapter); -+ -+ megaraid_free_cmd_packets(adapter); -+ -+ free_irq(adapter->irq, adapter); -+ -+ iounmap(raid_dev->baseaddr); -+ -+ pci_release_regions(adapter->pdev); -+ -+ kfree(raid_dev); -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_alloc_cmd_packets - allocate shared mailbox -+ * @param adapter : soft state of the raid controller -+ * -+ * Allocate and align the shared mailbox. This maibox is used to issue -+ * all the commands. For IO based controllers, the mailbox is also regsitered -+ * with the FW. Allocate memory for all commands as well. -+ * This is our big allocator -+ */ -+static int -+megaraid_alloc_cmd_packets(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ struct pci_dev *pdev; -+ unsigned long align; -+ scb_t *scb; -+ mbox_ccb_t *ccb; -+ struct mraid_pci_blk *epthru_pci_blk; -+ struct mraid_pci_blk *sg_pci_blk; -+ struct mraid_pci_blk *mbox_pci_blk; -+ int i; -+ -+ pdev = adapter->pdev; -+ -+ /* -+ * Setup the mailbox -+ * Allocate the common 16-byte aligned memory for the handshake -+ * mailbox. -+ */ -+ raid_dev->una_mbox64 = pci_alloc_consistent(adapter->pdev, -+ sizeof(mbox64_t), &raid_dev->una_mbox64_dma); -+ -+ if (!raid_dev->una_mbox64) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: out of memory, %s %d\n", __FUNCTION__, -+ __LINE__)); -+ return -1; -+ } -+ memset(raid_dev->una_mbox64, 0, sizeof(mbox64_t)); -+ -+ /* -+ * Align the mailbox at 16-byte boundary -+ */ -+ raid_dev->mbox = &raid_dev->una_mbox64->mbox32; -+ -+ raid_dev->mbox = (mbox_t *)((((unsigned long)raid_dev->mbox) + 15) & -+ (~0UL ^ 0xFUL)); -+ -+ raid_dev->mbox64 = (mbox64_t *)(((unsigned long)raid_dev->mbox) - 8); -+ -+ align = ((void *)raid_dev->mbox - -+ ((void *)&raid_dev->una_mbox64->mbox32)); -+ -+ raid_dev->mbox_dma = (unsigned long)raid_dev->una_mbox64_dma + 8 + -+ align; -+ -+ // Allocate memory for commands issued internally -+ adapter->ibuf = pci_alloc_consistent(pdev, MBOX_IBUF_SIZE, -+ &adapter->ibuf_dma_h); -+ if (!adapter->ibuf) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: out of memory, %s %d\n", __FUNCTION__, -+ __LINE__)); -+ -+ goto out_free_common_mbox; -+ } -+ memset(adapter->ibuf, 0, MBOX_IBUF_SIZE); -+ -+ // Allocate memory for our SCSI Command Blocks and their associated -+ // memory -+ -+ /* -+ * Allocate memory for the base list of scb. Later allocate memory for -+ * CCBs and embedded components of each CCB and point the pointers in -+ * scb to the allocated components -+ * NOTE: The code to allocate SCB will be duplicated in all the LLD -+ * since the calling routine does not yet know the number of available -+ * commands. -+ */ -+ adapter->kscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_SCSI_CMDS, -+ GFP_KERNEL); -+ -+ if (adapter->kscb_list == NULL) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: out of memory, %s %d\n", __FUNCTION__, -+ __LINE__)); -+ goto out_free_ibuf; -+ } -+ memset(adapter->kscb_list, 0, sizeof(scb_t) * MBOX_MAX_SCSI_CMDS); -+ -+ // memory allocation for our command packets -+ if (megaraid_mbox_setup_dma_pools(adapter) != 0) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: out of memory, %s %d\n", __FUNCTION__, -+ __LINE__)); -+ goto out_free_scb_list; -+ } -+ -+ // Adjust the scb pointers and link in the free pool -+ epthru_pci_blk = raid_dev->epthru_pool; -+ sg_pci_blk = raid_dev->sg_pool; -+ mbox_pci_blk = raid_dev->mbox_pool; -+ -+ for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { -+ scb = adapter->kscb_list + i; -+ ccb = raid_dev->ccb_list + i; -+ -+ ccb->mbox = (mbox_t *)(mbox_pci_blk[i].vaddr + 16); -+ ccb->raw_mbox = (uint8_t *)ccb->mbox; -+ ccb->mbox64 = (mbox64_t *)(mbox_pci_blk[i].vaddr + 8); -+ ccb->mbox_dma_h = (unsigned long)mbox_pci_blk[i].dma_addr + 16; -+ -+ // make sure the mailbox is aligned properly -+ if (ccb->mbox_dma_h & 0x0F) { -+ con_log(CL_ANN, (KERN_CRIT -+ "megaraid mbox: not aligned on 16-bytes\n")); -+ -+ goto out_teardown_dma_pools; -+ } -+ -+ ccb->epthru = (mraid_epassthru_t *) -+ epthru_pci_blk[i].vaddr; -+ ccb->epthru_dma_h = epthru_pci_blk[i].dma_addr; -+ ccb->pthru = (mraid_passthru_t *)ccb->epthru; -+ ccb->pthru_dma_h = ccb->epthru_dma_h; -+ -+ -+ ccb->sgl64 = (mbox_sgl64 *)sg_pci_blk[i].vaddr; -+ ccb->sgl_dma_h = sg_pci_blk[i].dma_addr; -+ ccb->sgl32 = (mbox_sgl32 *)ccb->sgl64; -+ -+ scb->ccb = (caddr_t)ccb; -+ scb->gp = 0; -+ -+ scb->sno = i; // command index -+ -+ scb->scp = NULL; -+ scb->state = SCB_FREE; -+ scb->dma_direction = PCI_DMA_NONE; -+ scb->dma_type = MRAID_DMA_NONE; -+ scb->dev_channel = -1; -+ scb->dev_target = -1; -+ -+ // put scb in the free pool -+ list_add_tail(&scb->list, &adapter->kscb_pool); -+ } -+ -+ return 0; -+ -+out_teardown_dma_pools: -+ megaraid_mbox_teardown_dma_pools(adapter); -+out_free_scb_list: -+ kfree(adapter->kscb_list); -+out_free_ibuf: -+ pci_free_consistent(pdev, MBOX_IBUF_SIZE, (void *)adapter->ibuf, -+ adapter->ibuf_dma_h); -+out_free_common_mbox: -+ pci_free_consistent(adapter->pdev, sizeof(mbox64_t), -+ (caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma); -+ -+ return -1; -+} -+ -+ -+/** -+ * megaraid_free_cmd_packets - free memory -+ * @param adapter : soft state of the raid controller -+ * -+ * Release memory resources allocated for commands -+ */ -+static void -+megaraid_free_cmd_packets(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ -+ megaraid_mbox_teardown_dma_pools(adapter); -+ -+ kfree(adapter->kscb_list); -+ -+ pci_free_consistent(adapter->pdev, MBOX_IBUF_SIZE, -+ (void *)adapter->ibuf, adapter->ibuf_dma_h); -+ -+ pci_free_consistent(adapter->pdev, sizeof(mbox64_t), -+ (caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma); -+ return; -+} -+ -+ -+/** -+ * megaraid_mbox_setup_dma_pools - setup dma pool for command packets -+ * @param adapter : HBA soft state -+ * -+ * setup the dma pools for mailbox, passthru and extended passthru structures, -+ * and scatter-gather lists -+ */ -+static int -+megaraid_mbox_setup_dma_pools(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ struct mraid_pci_blk *epthru_pci_blk; -+ struct mraid_pci_blk *sg_pci_blk; -+ struct mraid_pci_blk *mbox_pci_blk; -+ int i; -+ -+ -+ -+ // Allocate memory for 16-bytes aligned mailboxes -+ raid_dev->mbox_pool_handle = pci_pool_create("megaraid mbox pool", -+ adapter->pdev, -+ sizeof(mbox64_t) + 16, -+ 16, 0); -+ -+ if (raid_dev->mbox_pool_handle == NULL) { -+ goto fail_setup_dma_pool; -+ } -+ -+ mbox_pci_blk = raid_dev->mbox_pool; -+ for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { -+ mbox_pci_blk[i].vaddr = pci_pool_alloc( -+ raid_dev->mbox_pool_handle, -+ GFP_KERNEL, -+ &mbox_pci_blk[i].dma_addr); -+ if (!mbox_pci_blk[i].vaddr) { -+ goto fail_setup_dma_pool; -+ } -+ } -+ -+ /* -+ * Allocate memory for each embedded passthru strucuture pointer -+ * Request for a 128 bytes aligned structure for each passthru command -+ * structure -+ * Since passthru and extended passthru commands are exclusive, they -+ * share common memory pool. Passthru structures piggyback on memory -+ * allocted to extended passthru since passthru is smaller of the two -+ */ -+ raid_dev->epthru_pool_handle = pci_pool_create("megaraid mbox pthru", -+ adapter->pdev, sizeof(mraid_epassthru_t), 128, 0); -+ -+ if (raid_dev->epthru_pool_handle == NULL) { -+ goto fail_setup_dma_pool; -+ } -+ -+ epthru_pci_blk = raid_dev->epthru_pool; -+ for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { -+ epthru_pci_blk[i].vaddr = pci_pool_alloc( -+ raid_dev->epthru_pool_handle, -+ GFP_KERNEL, -+ &epthru_pci_blk[i].dma_addr); -+ if (!epthru_pci_blk[i].vaddr) { -+ goto fail_setup_dma_pool; -+ } -+ } -+ -+ -+ // Allocate memory for each scatter-gather list. Request for 512 bytes -+ // alignment for each sg list -+ raid_dev->sg_pool_handle = pci_pool_create("megaraid mbox sg", -+ adapter->pdev, -+ sizeof(mbox_sgl64) * MBOX_MAX_SG_SIZE, -+ 512, 0); -+ -+ if (raid_dev->sg_pool_handle == NULL) { -+ goto fail_setup_dma_pool; -+ } -+ -+ sg_pci_blk = raid_dev->sg_pool; -+ for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { -+ sg_pci_blk[i].vaddr = pci_pool_alloc( -+ raid_dev->sg_pool_handle, -+ GFP_KERNEL, -+ &sg_pci_blk[i].dma_addr); -+ if (!sg_pci_blk[i].vaddr) { -+ goto fail_setup_dma_pool; -+ } -+ } -+ -+ return 0; -+ -+fail_setup_dma_pool: -+ megaraid_mbox_teardown_dma_pools(adapter); -+ return -1; -+} -+ -+ -+/** -+ * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets -+ * @param adapter : HBA soft state -+ * -+ * teardown the dma pool for mailbox, passthru and extended passthru -+ * structures, and scatter-gather lists -+ */ -+static void -+megaraid_mbox_teardown_dma_pools(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ struct mraid_pci_blk *epthru_pci_blk; -+ struct mraid_pci_blk *sg_pci_blk; -+ struct mraid_pci_blk *mbox_pci_blk; -+ int i; -+ -+ -+ sg_pci_blk = raid_dev->sg_pool; -+ for (i = 0; i < MBOX_MAX_SCSI_CMDS && sg_pci_blk[i].vaddr; i++) { -+ pci_pool_free(raid_dev->sg_pool_handle, sg_pci_blk[i].vaddr, -+ sg_pci_blk[i].dma_addr); -+ } -+ if (raid_dev->sg_pool_handle) -+ pci_pool_destroy(raid_dev->sg_pool_handle); -+ -+ -+ epthru_pci_blk = raid_dev->epthru_pool; -+ for (i = 0; i < MBOX_MAX_SCSI_CMDS && epthru_pci_blk[i].vaddr; i++) { -+ pci_pool_free(raid_dev->epthru_pool_handle, -+ epthru_pci_blk[i].vaddr, epthru_pci_blk[i].dma_addr); -+ } -+ if (raid_dev->epthru_pool_handle) -+ pci_pool_destroy(raid_dev->epthru_pool_handle); -+ -+ -+ mbox_pci_blk = raid_dev->mbox_pool; -+ for (i = 0; i < MBOX_MAX_SCSI_CMDS && mbox_pci_blk[i].vaddr; i++) { -+ pci_pool_free(raid_dev->mbox_pool_handle, -+ mbox_pci_blk[i].vaddr, mbox_pci_blk[i].dma_addr); -+ } -+ if (raid_dev->mbox_pool_handle) -+ pci_pool_destroy(raid_dev->mbox_pool_handle); -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_alloc_scb - detach and return a scb from the free list -+ * @adapter : controller's soft state -+ * -+ * return the scb from the head of the free list. NULL if there are none -+ * available -+ **/ -+static inline scb_t * -+megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) -+{ -+ struct list_head *head = &adapter->kscb_pool; -+ scb_t *scb = NULL; -+ unsigned long flags; -+ -+ // detach scb from free pool -+ spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags); -+ -+ if (list_empty(head)) { -+ spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags); -+ return NULL; -+ } -+ -+ scb = list_entry(head->next, scb_t, list); -+ list_del_init(&scb->list); -+ -+ spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags); -+ -+ scb->state = SCB_ACTIVE; -+ scb->scp = scp; -+ scb->dma_type = MRAID_DMA_NONE; -+ -+ return scb; -+} -+ -+ -+/** -+ * megaraid_dealloc_scb - return the scb to the free pool -+ * @adapter : controller's soft state -+ * @scb : scb to be freed -+ * -+ * return the scb back to the free list of scbs. The caller must 'flush' the -+ * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc. -+ * NOTE NOTE: Make sure the scb is not on any list before calling this -+ * routine. -+ **/ -+static inline void -+megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) -+{ -+ unsigned long flags; -+ -+ // put scb in the free pool -+ scb->state = SCB_FREE; -+ scb->scp = NULL; -+ spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags); -+ -+ list_add(&scb->list, &adapter->kscb_pool); -+ -+ spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags); -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_mbox_mksgl - make the scatter-gather list -+ * @adapter - controller's soft state -+ * @scb - scsi control block -+ * -+ * prepare the scatter-gather list -+ */ -+static inline int -+megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) -+{ -+ struct scatterlist *sgl; -+ mbox_ccb_t *ccb; -+ struct page *page; -+ unsigned long offset; -+ struct scsi_cmnd *scp; -+ int sgcnt; -+ int i; -+ -+ -+ scp = scb->scp; -+ ccb = (mbox_ccb_t *)scb->ccb; -+ -+ // no mapping required if no data to be transferred -+ if (!scp->request_buffer || !scp->request_bufflen) -+ return 0; -+ -+ if (!scp->use_sg) { /* scatter-gather list not used */ -+ -+ page = virt_to_page(scp->request_buffer); -+ -+ offset = ((unsigned long)scp->request_buffer & ~PAGE_MASK); -+ -+ ccb->buf_dma_h = pci_map_page(adapter->pdev, page, offset, -+ scp->request_bufflen, -+ scb->dma_direction); -+ scb->dma_type = MRAID_DMA_WBUF; -+ -+ /* -+ * We need to handle special 64-bit commands that need a -+ * minimum of 1 SG -+ */ -+ sgcnt = 1; -+ ccb->sgl64[0].address = ccb->buf_dma_h; -+ ccb->sgl64[0].length = scp->request_bufflen; -+ -+ return sgcnt; -+ } -+ -+ sgl = (struct scatterlist *)scp->request_buffer; -+ -+ // The number of sg elements returned must not exceed our limit -+ sgcnt = pci_map_sg(adapter->pdev, sgl, scp->use_sg, -+ scb->dma_direction); -+ -+ if (sgcnt > adapter->sglen) { -+ con_log(CL_ANN, (KERN_CRIT -+ "megaraid critical: too many sg elements:%d\n", -+ sgcnt)); -+ BUG(); -+ } -+ -+ scb->dma_type = MRAID_DMA_WSG; -+ -+ for (i = 0; i < sgcnt; i++, sgl++) { -+ ccb->sgl64[i].address = sg_dma_address(sgl); -+ ccb->sgl64[i].length = sg_dma_len(sgl); -+ } -+ -+ // Return count of SG nodes -+ return sgcnt; -+} -+ -+ -+/** -+ * mbox_post_cmd - issue a mailbox command -+ * @adapter - controller's soft state -+ * @scb - command to be issued -+ * -+ * post the command to the controller if mailbox is availble. -+ */ -+static inline int -+mbox_post_cmd(adapter_t *adapter, scb_t *scb) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ mbox64_t *mbox64; -+ mbox_t *mbox; -+ mbox_ccb_t *ccb; -+ unsigned long flags; -+ unsigned int i = 0; -+ -+ -+ ccb = (mbox_ccb_t *)scb->ccb; -+ mbox = raid_dev->mbox; -+ mbox64 = raid_dev->mbox64; -+ -+ /* -+ * Check for busy mailbox. If it is, return failure - the caller -+ * should retry later. -+ */ -+ spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags); -+ -+ if (unlikely(mbox->busy)) { -+ do { -+ udelay(1); -+ i++; -+ rmb(); -+ } while(mbox->busy && (i < max_mbox_busy_wait)); -+ -+ if (mbox->busy) { -+ -+ spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags); -+ -+ return -1; -+ } -+ } -+ -+ -+ // Copy this command's mailbox data into "adapter's" mailbox -+ memcpy((caddr_t)mbox64, (caddr_t)ccb->mbox64, 22); -+ mbox->cmdid = scb->sno; -+ -+ adapter->outstanding_cmds++; -+ -+ if (scb->dma_direction == PCI_DMA_TODEVICE) { -+ if (!scb->scp->use_sg) { // sg list not used -+ pci_dma_sync_single_for_device(adapter->pdev, -+ ccb->buf_dma_h, -+ scb->scp->request_bufflen, -+ PCI_DMA_TODEVICE); -+ } -+ else { -+ pci_dma_sync_sg_for_device(adapter->pdev, -+ scb->scp->request_buffer, -+ scb->scp->use_sg, PCI_DMA_TODEVICE); -+ } -+ } -+ -+ mbox->busy = 1; // Set busy -+ mbox->poll = 0; -+ mbox->ack = 0; -+ wmb(); -+ -+ WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1); -+ -+ spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags); -+ -+ return 0; -+} -+ -+ -+/** -+ * megaraid_queue_command - generic queue entry point for all LLDs -+ * @scp : pointer to the scsi command to be executed -+ * @done : callback routine to be called after the cmd has be completed -+ * -+ * Queue entry point for mailbox based controllers. -+ */ -+static int -+megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *)) -+{ -+ adapter_t *adapter; -+ scb_t *scb; -+ int if_busy; -+ -+ adapter = SCP2ADAPTER(scp); -+ scp->scsi_done = done; -+ scp->result = 0; -+ -+ ASSERT(spin_is_locked(adapter->host_lock)); -+ -+ spin_unlock(adapter->host_lock); -+ -+ /* -+ * Allocate and build a SCB request -+ * if_busy flag will be set if megaraid_mbox_build_cmd() command could -+ * not allocate scb. We will return non-zero status in that case. -+ * NOTE: scb can be null even though certain commands completed -+ * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, it would -+ * return 0 in that case, and we would do the callback right away. -+ */ -+ if_busy = 0; -+ scb = megaraid_mbox_build_cmd(adapter, scp, &if_busy); -+ -+ if (scb) { -+ megaraid_mbox_runpendq(adapter, scb); -+ } -+ -+ spin_lock(adapter->host_lock); -+ -+ if (!scb) { // command already completed -+ done(scp); -+ return 0; -+ } -+ -+ return if_busy; -+} -+ -+ -+/** -+ * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid -+ * firmware lingua -+ * @adapter - controller's soft state -+ * @scp - mid-layer scsi command pointer -+ * @busy - set if request could not be completed because of lack of -+ * resources -+ * -+ * convert the command issued by mid-layer to format understood by megaraid -+ * firmware. We also complete certain command without sending them to firmware -+ */ -+static scb_t * -+megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) -+{ -+ mraid_device_t *rdev = ADAP2RAIDDEV(adapter); -+ int channel; -+ int target; -+ int islogical; -+ mbox_ccb_t *ccb; -+ mraid_passthru_t *pthru; -+ mbox64_t *mbox64; -+ mbox_t *mbox; -+ scb_t *scb; -+ char skip[] = "skipping"; -+ char scan[] = "scanning"; -+ char *ss; -+ -+ -+ /* -+ * Get the appropriate device map for the device this command is -+ * intended for -+ */ -+ MRAID_GET_DEVICE_MAP(adapter, scp, channel, target, islogical); -+ -+ /* -+ * Logical drive commands -+ */ -+ if (islogical) { -+ switch (scp->cmnd[0]) { -+ case TEST_UNIT_READY: -+ /* -+ * Do we support clustering and is the support enabled -+ * If no, return success always -+ */ -+ if (!adapter->ha) { -+ scp->result = (DID_OK << 16); -+ return NULL; -+ } -+ -+ if (!(scb = megaraid_alloc_scb(adapter, scp))) { -+ scp->result = (DID_ERROR << 16); -+ *busy = 1; -+ return NULL; -+ } -+ -+ scb->dma_direction = scp->sc_data_direction; -+ scb->dev_channel = 0xFF; -+ scb->dev_target = target; -+ ccb = (mbox_ccb_t *)scb->ccb; -+ -+ /* -+ * The command id will be provided by the command -+ * issuance routine -+ */ -+ ccb->raw_mbox[0] = CLUSTER_CMD; -+ ccb->raw_mbox[2] = RESERVATION_STATUS; -+ ccb->raw_mbox[3] = target; -+ -+ return scb; -+ -+ case MODE_SENSE: -+ if (scp->use_sg) { -+ struct scatterlist *sgl; -+ caddr_t vaddr; -+ -+ sgl = (struct scatterlist *)scp->request_buffer; -+ if (sgl->page) { -+ vaddr = (caddr_t) -+ (page_address((&sgl[0])->page) -+ + (&sgl[0])->offset); -+ -+ memset(vaddr, 0, scp->cmnd[4]); -+ } -+ else { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mailbox: invalid sg:%d\n", -+ __LINE__)); -+ } -+ } -+ else { -+ memset(scp->request_buffer, 0, scp->cmnd[4]); -+ } -+ scp->result = (DID_OK << 16); -+ return NULL; -+ -+ case INQUIRY: -+ /* -+ * Display the channel scan for logical drives -+ * Do not display scan for a channel if already done. -+ */ -+ if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) { -+ -+ con_log(CL_ANN, (KERN_INFO -+ "scsi[%d]: scanning scsi channel %d", -+ adapter->host->host_no, -+ SCP2CHANNEL(scp))); -+ -+ con_log(CL_ANN, ( -+ " [virtual] for logical drives\n")); -+ -+ rdev->last_disp |= (1L << SCP2CHANNEL(scp)); -+ } -+ -+ /* Fall through */ -+ -+ case READ_CAPACITY: -+ /* -+ * Do not allow LUN > 0 for logical drives and -+ * requests for more than 40 logical drives -+ */ -+ if (SCP2LUN(scp)) { -+ scp->result = (DID_BAD_TARGET << 16); -+ return NULL; -+ } -+ if ((target % 0x80) >= MAX_LOGICAL_DRIVES_40LD) { -+ scp->result = (DID_BAD_TARGET << 16); -+ return NULL; -+ } -+ -+ -+ /* Allocate a SCB and initialize passthru */ -+ if (!(scb = megaraid_alloc_scb(adapter, scp))) { -+ scp->result = (DID_ERROR << 16); -+ *busy = 1; -+ return NULL; -+ } -+ -+ ccb = (mbox_ccb_t *)scb->ccb; -+ scb->dev_channel = 0xFF; -+ scb->dev_target = target; -+ pthru = ccb->pthru; -+ mbox = ccb->mbox; -+ mbox64 = ccb->mbox64; -+ -+ pthru->timeout = 0; -+ pthru->ars = 1; -+ pthru->reqsenselen = 14; -+ pthru->islogical = 1; -+ pthru->logdrv = target; -+ pthru->cdblen = scp->cmd_len; -+ memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); -+ -+ mbox->cmd = MBOXCMD_PASSTHRU64; -+ scb->dma_direction = scp->sc_data_direction; -+ -+ pthru->dataxferlen = scp->request_bufflen; -+ pthru->dataxferaddr = ccb->sgl_dma_h; -+ pthru->numsge = megaraid_mbox_mksgl(adapter, -+ scb); -+ -+ mbox->xferaddr = 0xFFFFFFFF; -+ mbox64->xferaddr_lo = (uint32_t )ccb->pthru_dma_h; -+ mbox64->xferaddr_hi = 0; -+ -+ return scb; -+ -+ case READ_6: -+ case WRITE_6: -+ case READ_10: -+ case WRITE_10: -+ case READ_12: -+ case WRITE_12: -+ -+ /* -+ * Allocate a SCB and initialize mailbox -+ */ -+ if (!(scb = megaraid_alloc_scb(adapter, scp))) { -+ scp->result = (DID_ERROR << 16); -+ *busy = 1; -+ return NULL; -+ } -+ ccb = (mbox_ccb_t *)scb->ccb; -+ scb->dev_channel = 0xFF; -+ scb->dev_target = target; -+ mbox = ccb->mbox; -+ mbox64 = ccb->mbox64; -+ mbox->logdrv = target; -+ -+ /* -+ * A little HACK: 2nd bit is zero for all scsi read -+ * commands and is set for all scsi write commands -+ */ -+ mbox->cmd = (scp->cmnd[0] & 0x02) ? MBOXCMD_LWRITE64: -+ MBOXCMD_LREAD64 ; -+ -+ /* -+ * 6-byte READ(0x08) or WRITE(0x0A) cdb -+ */ -+ if (scp->cmd_len == 6) { -+ mbox->numsectors = (uint32_t)scp->cmnd[4]; -+ mbox->lba = -+ ((uint32_t)scp->cmnd[1] << 16) | -+ ((uint32_t)scp->cmnd[2] << 8) | -+ (uint32_t)scp->cmnd[3]; -+ -+ mbox->lba &= 0x1FFFFF; -+ } -+ -+ /* -+ * 10-byte READ(0x28) or WRITE(0x2A) cdb -+ */ -+ else if (scp->cmd_len == 10) { -+ mbox->numsectors = -+ (uint32_t)scp->cmnd[8] | -+ ((uint32_t)scp->cmnd[7] << 8); -+ mbox->lba = -+ ((uint32_t)scp->cmnd[2] << 24) | -+ ((uint32_t)scp->cmnd[3] << 16) | -+ ((uint32_t)scp->cmnd[4] << 8) | -+ (uint32_t)scp->cmnd[5]; -+ } -+ -+ /* -+ * 12-byte READ(0xA8) or WRITE(0xAA) cdb -+ */ -+ else if (scp->cmd_len == 12) { -+ mbox->lba = -+ ((uint32_t)scp->cmnd[2] << 24) | -+ ((uint32_t)scp->cmnd[3] << 16) | -+ ((uint32_t)scp->cmnd[4] << 8) | -+ (uint32_t)scp->cmnd[5]; -+ -+ mbox->numsectors = -+ ((uint32_t)scp->cmnd[6] << 24) | -+ ((uint32_t)scp->cmnd[7] << 16) | -+ ((uint32_t)scp->cmnd[8] << 8) | -+ (uint32_t)scp->cmnd[9]; -+ } -+ else { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: unsupported CDB length\n")); -+ -+ megaraid_dealloc_scb(adapter, scb); -+ -+ scp->result = (DID_ERROR << 16); -+ return NULL; -+ } -+ -+ scb->dma_direction = scp->sc_data_direction; -+ -+ // Calculate Scatter-Gather info -+ mbox64->xferaddr_lo = (uint32_t )ccb->sgl_dma_h; -+ mbox->numsge = megaraid_mbox_mksgl(adapter, -+ scb); -+ mbox->xferaddr = 0xFFFFFFFF; -+ mbox64->xferaddr_hi = 0; -+ -+ return scb; -+ -+ case RESERVE: -+ case RELEASE: -+ /* -+ * Do we support clustering and is the support enabled -+ */ -+ if (!adapter->ha) { -+ scp->result = (DID_BAD_TARGET << 16); -+ return NULL; -+ } -+ -+ /* -+ * Allocate a SCB and initialize mailbox -+ */ -+ if (!(scb = megaraid_alloc_scb(adapter, scp))) { -+ scp->result = (DID_ERROR << 16); -+ *busy = 1; -+ return NULL; -+ } -+ -+ ccb = (mbox_ccb_t *)scb->ccb; -+ scb->dev_channel = 0xFF; -+ scb->dev_target = target; -+ ccb->raw_mbox[0] = CLUSTER_CMD; -+ ccb->raw_mbox[2] = (scp->cmnd[0] == RESERVE) ? -+ RESERVE_LD : RELEASE_LD; -+ -+ ccb->raw_mbox[3] = target; -+ scb->dma_direction = scp->sc_data_direction; -+ -+ return scb; -+ -+ default: -+ scp->result = (DID_BAD_TARGET << 16); -+ return NULL; -+ } -+ } -+ else { // Passthru device commands -+ -+ // Do not allow access to target id > 15 or LUN > 7 -+ if (target > 15 || SCP2LUN(scp) > 7) { -+ scp->result = (DID_BAD_TARGET << 16); -+ return NULL; -+ } -+ -+ // if fast load option was set and scan for last device is -+ // over, reset the fast_load flag so that during a possible -+ // next scan, devices can be made available -+ if (rdev->fast_load && (target == 15) && -+ (SCP2CHANNEL(scp) == adapter->max_channel -1)) { -+ -+ con_log(CL_ANN, (KERN_INFO -+ "megaraid[%d]: physical device scan re-enabled\n", -+ adapter->host->host_no)); -+ rdev->fast_load = 0; -+ } -+ -+ /* -+ * Display the channel scan for physical devices -+ */ -+ if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) { -+ -+ ss = rdev->fast_load ? skip : scan; -+ -+ con_log(CL_ANN, (KERN_INFO -+ "scsi[%d]: %s scsi channel %d [Phy %d]", -+ adapter->host->host_no, ss, SCP2CHANNEL(scp), -+ channel)); -+ -+ con_log(CL_ANN, ( -+ " for non-raid devices\n")); -+ -+ rdev->last_disp |= (1L << SCP2CHANNEL(scp)); -+ } -+ -+ // disable channel sweep if fast load option given -+ if (rdev->fast_load) { -+ scp->result = (DID_BAD_TARGET << 16); -+ return NULL; -+ } -+ -+ // Allocate a SCB and initialize passthru -+ if (!(scb = megaraid_alloc_scb(adapter, scp))) { -+ scp->result = (DID_ERROR << 16); -+ *busy = 1; -+ return NULL; -+ } -+ -+ ccb = (mbox_ccb_t *)scb->ccb; -+ scb->dev_channel = channel; -+ scb->dev_target = target; -+ scb->dma_direction = scp->sc_data_direction; -+ mbox = ccb->mbox; -+ mbox64 = ccb->mbox64; -+ -+ // Does this firmware support extended CDBs -+ if (adapter->max_cdb_sz == 16) { -+ mbox->cmd = MBOXCMD_EXTPTHRU; -+ -+ megaraid_mbox_prepare_epthru(adapter, scb, scp); -+ -+ mbox64->xferaddr_lo = (uint32_t)ccb->epthru_dma_h; -+ mbox64->xferaddr_hi = 0; -+ mbox->xferaddr = 0xFFFFFFFF; -+ } -+ else { -+ mbox->cmd = MBOXCMD_PASSTHRU64; -+ -+ megaraid_mbox_prepare_pthru(adapter, scb, scp); -+ -+ mbox64->xferaddr_lo = (uint32_t)ccb->pthru_dma_h; -+ mbox64->xferaddr_hi = 0; -+ mbox->xferaddr = 0xFFFFFFFF; -+ } -+ return scb; -+ } -+ -+ // NOT REACHED -+} -+ -+ -+/** -+ * megaraid_mbox_runpendq - execute commands queued in the pending queue -+ * @adapter : controller's soft state -+ * @scb : SCB to be queued in the pending list -+ * -+ * scan the pending list for commands which are not yet issued and try to -+ * post to the controller. The SCB can be a null pointer, which would indicate -+ * no SCB to be queue, just try to execute the ones in the pending list. -+ * -+ * NOTE: We do not actually traverse the pending list. The SCBs are plucked -+ * out from the head of the pending list. If it is successfully issued, the -+ * next SCB is at the head now. -+ */ -+static void -+megaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q) -+{ -+ scb_t *scb; -+ unsigned long flags; -+ -+ spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); -+ -+ if (scb_q) { -+ scb_q->state = SCB_PENDQ; -+ list_add_tail(&scb_q->list, &adapter->pend_list); -+ } -+ -+ // if the adapter in not in quiescent mode, post the commands to FW -+ if (adapter->quiescent) { -+ spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); -+ return; -+ } -+ -+ while (!list_empty(&adapter->pend_list)) { -+ -+ ASSERT(spin_is_locked(PENDING_LIST_LOCK(adapter))); -+ -+ scb = list_entry(adapter->pend_list.next, scb_t, list); -+ -+ // remove the scb from the pending list and try to -+ // issue. If we are unable to issue it, put back in -+ // the pending list and return -+ -+ list_del_init(&scb->list); -+ -+ spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); -+ -+ // if mailbox was busy, return SCB back to pending -+ // list. Make sure to add at the head, since that's -+ // where it would have been removed from -+ -+ scb->state = SCB_ISSUED; -+ -+ if (mbox_post_cmd(adapter, scb) != 0) { -+ -+ spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); -+ -+ scb->state = SCB_PENDQ; -+ -+ list_add(&scb->list, &adapter->pend_list); -+ -+ spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), -+ flags); -+ -+ return; -+ } -+ -+ spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); -+ } -+ -+ spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); -+ -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_mbox_prepare_pthru - prepare a command for physical devices -+ * @adapter - pointer to controller's soft state -+ * @scb - scsi control block -+ * @scp - scsi command from the mid-layer -+ * -+ * prepare a command for the scsi physical devices -+ */ -+static void -+megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb, -+ struct scsi_cmnd *scp) -+{ -+ mbox_ccb_t *ccb; -+ mraid_passthru_t *pthru; -+ uint8_t channel; -+ uint8_t target; -+ -+ ccb = (mbox_ccb_t *)scb->ccb; -+ pthru = ccb->pthru; -+ channel = scb->dev_channel; -+ target = scb->dev_target; -+ -+ // 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout -+ pthru->timeout = 4; -+ pthru->ars = 1; -+ pthru->islogical = 0; -+ pthru->channel = 0; -+ pthru->target = (channel << 4) | target; -+ pthru->logdrv = SCP2LUN(scp); -+ pthru->reqsenselen = 14; -+ pthru->cdblen = scp->cmd_len; -+ -+ memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); -+ -+ if (scp->request_bufflen) { -+ pthru->dataxferlen = scp->request_bufflen; -+ pthru->dataxferaddr = ccb->sgl_dma_h; -+ pthru->numsge = megaraid_mbox_mksgl(adapter, scb); -+ } -+ else { -+ pthru->dataxferaddr = 0; -+ pthru->dataxferlen = 0; -+ pthru->numsge = 0; -+ } -+ return; -+} -+ -+ -+/** -+ * megaraid_mbox_prepare_epthru - prepare a command for physical devices -+ * @adapter - pointer to controller's soft state -+ * @scb - scsi control block -+ * @scp - scsi command from the mid-layer -+ * -+ * prepare a command for the scsi physical devices. This rountine prepares -+ * commands for devices which can take extended CDBs (>10 bytes) -+ */ -+static void -+megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, -+ struct scsi_cmnd *scp) -+{ -+ mbox_ccb_t *ccb; -+ mraid_epassthru_t *epthru; -+ uint8_t channel; -+ uint8_t target; -+ -+ ccb = (mbox_ccb_t *)scb->ccb; -+ epthru = ccb->epthru; -+ channel = scb->dev_channel; -+ target = scb->dev_target; -+ -+ // 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout -+ epthru->timeout = 4; -+ epthru->ars = 1; -+ epthru->islogical = 0; -+ epthru->channel = 0; -+ epthru->target = (channel << 4) | target; -+ epthru->logdrv = SCP2LUN(scp); -+ epthru->reqsenselen = 14; -+ epthru->cdblen = scp->cmd_len; -+ -+ memcpy(epthru->cdb, scp->cmnd, scp->cmd_len); -+ -+ if (scp->request_bufflen) { -+ epthru->dataxferlen = scp->request_bufflen; -+ epthru->dataxferaddr = ccb->sgl_dma_h; -+ epthru->numsge = megaraid_mbox_mksgl(adapter, scb); -+ } -+ else { -+ epthru->dataxferaddr = 0; -+ epthru->dataxferlen = 0; -+ epthru->numsge = 0; -+ } -+ return; -+} -+ -+ -+/** -+ * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs -+ * @adapter - controller's soft state -+ * -+ * Interrupt ackrowledgement sequence for memory mapped HBAs. Find out the -+ * completed command and put them on the completed list for later processing. -+ * -+ * Returns: 1 if the interrupt is valid, 0 otherwise -+ */ -+static inline int -+megaraid_ack_sequence(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ mbox_t *mbox; -+ scb_t *scb; -+ uint8_t nstatus; -+ uint8_t completed[MBOX_MAX_FIRMWARE_STATUS]; -+ struct list_head clist; -+ int handled; -+ uint32_t dword; -+ unsigned long flags; -+ int i, j; -+ -+ -+ mbox = raid_dev->mbox; -+ -+ // move the SCBs from the firmware completed array to our local list -+ INIT_LIST_HEAD(&clist); -+ -+ // loop till F/W has more commands for us to complete -+ handled = 0; -+ spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags); -+ do { -+ /* -+ * Check if a valid interrupt is pending. If found, force the -+ * interrupt line low. -+ */ -+ dword = RDOUTDOOR(raid_dev); -+ if (dword != 0x10001234) break; -+ -+ handled = 1; -+ -+ WROUTDOOR(raid_dev, 0x10001234); -+ -+ nstatus = 0; -+ // wait for valid numstatus to post -+ for (i = 0; i < 0xFFFFF; i++) { -+ if (mbox->numstatus != 0xFF) { -+ nstatus = mbox->numstatus; -+ break; -+ } -+ rmb(); -+ } -+ mbox->numstatus = 0xFF; -+ -+ adapter->outstanding_cmds -= nstatus; -+ -+ for (i = 0; i < nstatus; i++) { -+ -+ // wait for valid command index to post -+ for (j = 0; j < 0xFFFFF; j++) { -+ if (mbox->completed[i] != 0xFF) break; -+ rmb(); -+ } -+ completed[i] = mbox->completed[i]; -+ mbox->completed[i] = 0xFF; -+ -+ if (completed[i] == 0xFF) { -+ con_log(CL_ANN, (KERN_CRIT -+ "megaraid: command posting timed out\n")); -+ -+ BUG(); -+ continue; -+ } -+ -+ // Get SCB associated with this command id -+ if (completed[i] >= MBOX_MAX_SCSI_CMDS) { -+ // a cmm command -+ scb = adapter->uscb_list + (completed[i] - -+ MBOX_MAX_SCSI_CMDS); -+ } -+ else { -+ // an os command -+ scb = adapter->kscb_list + completed[i]; -+ } -+ -+ scb->status = mbox->status; -+ list_add_tail(&scb->list, &clist); -+ } -+ -+ // Acknowledge interrupt -+ WRINDOOR(raid_dev, 0x02); -+ -+ } while(1); -+ -+ spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags); -+ -+ -+ // put the completed commands in the completed list. DPC would -+ // complete these commands later -+ spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags); -+ -+ list_splice(&clist, &adapter->completed_list); -+ -+ spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags); -+ -+ -+ // schedule the DPC if there is some work for it -+ if (handled) -+ tasklet_schedule(&adapter->dpc_h); -+ -+ return handled; -+} -+ -+ -+/** -+ * megaraid_isr - isr for memory based mailbox based controllers -+ * @irq - irq -+ * @devp - pointer to our soft state -+ * @regs - unused -+ * -+ * Interrupt service routine for memory-mapped mailbox controllers. -+ */ -+static irqreturn_t -+megaraid_isr(int irq, void *devp, struct pt_regs *regs) -+{ -+ adapter_t *adapter = devp; -+ int handled; -+ -+ handled = megaraid_ack_sequence(adapter); -+ -+ /* Loop through any pending requests */ -+ if (!adapter->quiescent) { -+ megaraid_mbox_runpendq(adapter, NULL); -+ } -+ -+ return IRQ_RETVAL(handled); -+} -+ -+ -+/** -+ * megaraid_mbox_sync_scb - sync kernel buffers -+ * @adapter : controller's soft state -+ * @scb : pointer to the resource packet -+ * -+ * DMA sync if required. -+ */ -+static inline void -+megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) -+{ -+ mbox_ccb_t *ccb; -+ -+ ccb = (mbox_ccb_t *)scb->ccb; -+ -+ switch (scb->dma_type) { -+ -+ case MRAID_DMA_WBUF: -+ if (scb->dma_direction == PCI_DMA_FROMDEVICE) { -+ pci_dma_sync_single_for_cpu(adapter->pdev, -+ ccb->buf_dma_h, -+ scb->scp->request_bufflen, -+ PCI_DMA_FROMDEVICE); -+ } -+ -+ pci_unmap_page(adapter->pdev, ccb->buf_dma_h, -+ scb->scp->request_bufflen, scb->dma_direction); -+ -+ break; -+ -+ case MRAID_DMA_WSG: -+ if (scb->dma_direction == PCI_DMA_FROMDEVICE) { -+ pci_dma_sync_sg_for_cpu(adapter->pdev, -+ scb->scp->request_buffer, -+ scb->scp->use_sg, PCI_DMA_FROMDEVICE); -+ } -+ -+ pci_unmap_sg(adapter->pdev, scb->scp->request_buffer, -+ scb->scp->use_sg, scb->dma_direction); -+ -+ break; -+ -+ default: -+ break; -+ } -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_mbox_dpc - the tasklet to complete the commands from completed list -+ * @devp : pointer to HBA soft state -+ * -+ * Pick up the commands from the completed list and send back to the owners. -+ * This is a reentrant function and does not assume any locks are held while -+ * it is being called. -+ */ -+static void -+megaraid_mbox_dpc(unsigned long devp) -+{ -+ adapter_t *adapter = (adapter_t *)devp; -+ mraid_device_t *raid_dev; -+ struct list_head clist; -+ struct scatterlist *sgl; -+ scb_t *scb; -+ scb_t *tmp; -+ struct scsi_cmnd *scp; -+ mraid_passthru_t *pthru; -+ mraid_epassthru_t *epthru; -+ mbox_ccb_t *ccb; -+ int islogical; -+ int pdev_index; -+ int pdev_state; -+ mbox_t *mbox; -+ unsigned long flags; -+ uint8_t c; -+ int status; -+ -+ -+ if (!adapter) return; -+ -+ raid_dev = ADAP2RAIDDEV(adapter); -+ -+ // move the SCBs from the completed list to our local list -+ INIT_LIST_HEAD(&clist); -+ -+ spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags); -+ -+ list_splice_init(&adapter->completed_list, &clist); -+ -+ spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags); -+ -+ -+ list_for_each_entry_safe(scb, tmp, &clist, list) { -+ -+ status = scb->status; -+ scp = scb->scp; -+ ccb = (mbox_ccb_t *)scb->ccb; -+ pthru = ccb->pthru; -+ epthru = ccb->epthru; -+ mbox = ccb->mbox; -+ -+ // Make sure f/w has completed a valid command -+ if (scb->state != SCB_ISSUED) { -+ con_log(CL_ANN, (KERN_CRIT -+ "megaraid critical err: invalid command %d:%d:%p\n", -+ scb->sno, scb->state, scp)); -+ BUG(); -+ continue; // Must never happen! -+ } -+ -+ // check for the management command and complete it right away -+ if (scb->sno >= MBOX_MAX_SCSI_CMDS) { -+ scb->state = SCB_FREE; -+ scb->status = status; -+ -+ // remove from local clist -+ list_del_init(&scb->list); -+ -+ megaraid_mbox_mm_done(adapter, scb); -+ -+ continue; -+ } -+ -+ // Was an abort issued for this command earlier -+ if (scb->state & SCB_ABORT) { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: aborted cmd %lx[%x] completed\n", -+ scp->serial_number, scb->sno)); -+ } -+ -+ /* -+ * If the inquiry came of a disk drive which is not part of -+ * any RAID array, expose it to the kernel. For this to be -+ * enabled, user must set the "megaraid_expose_unconf_disks" -+ * flag to 1 by specifying it on module parameter list. -+ * This would enable data migration off drives from other -+ * configurations. -+ */ -+ islogical = MRAID_IS_LOGICAL(adapter, scp); -+ if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0 -+ && IS_RAID_CH(raid_dev, scb->dev_channel)) { -+ -+ if (scp->use_sg) { -+ sgl = (struct scatterlist *) -+ scp->request_buffer; -+ -+ if (sgl->page) { -+ c = *(unsigned char *) -+ (page_address((&sgl[0])->page) + -+ (&sgl[0])->offset); -+ } -+ else { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mailbox: invalid sg:%d\n", -+ __LINE__)); -+ c = 0; -+ } -+ } -+ else { -+ c = *(uint8_t *)scp->request_buffer; -+ } -+ -+ if ((c & 0x1F ) == TYPE_DISK) { -+ pdev_index = (scb->dev_channel * 16) + -+ scb->dev_target; -+ pdev_state = -+ raid_dev->pdrv_state[pdev_index] & 0x0F; -+ -+ if (pdev_state == PDRV_ONLINE || -+ pdev_state == PDRV_FAILED || -+ pdev_state == PDRV_RBLD || -+ pdev_state == PDRV_HOTSPARE || -+ megaraid_expose_unconf_disks == 0) { -+ -+ status = 0xF0; -+ } -+ } -+ } -+ -+ // Convert MegaRAID status to Linux error code -+ switch (status) { -+ -+ case 0x00: -+ -+ scp->result = (DID_OK << 16); -+ break; -+ -+ case 0x02: -+ -+ /* set sense_buffer and result fields */ -+ if (mbox->cmd == MBOXCMD_PASSTHRU || -+ mbox->cmd == MBOXCMD_PASSTHRU64) { -+ -+ memcpy(scp->sense_buffer, pthru->reqsensearea, -+ 14); -+ -+ scp->result = DRIVER_SENSE << 24 | -+ DID_OK << 16 | CHECK_CONDITION << 1; -+ } -+ else { -+ if (mbox->cmd == MBOXCMD_EXTPTHRU) { -+ -+ memcpy(scp->sense_buffer, -+ epthru->reqsensearea, 14); -+ -+ scp->result = DRIVER_SENSE << 24 | -+ DID_OK << 16 | -+ CHECK_CONDITION << 1; -+ } else { -+ scp->sense_buffer[0] = 0x70; -+ scp->sense_buffer[2] = ABORTED_COMMAND; -+ scp->result = CHECK_CONDITION << 1; -+ } -+ } -+ break; -+ -+ case 0x08: -+ -+ scp->result = DID_BUS_BUSY << 16 | status; -+ break; -+ -+ default: -+ -+ /* -+ * If TEST_UNIT_READY fails, we know RESERVATION_STATUS -+ * failed -+ */ -+ if (scp->cmnd[0] == TEST_UNIT_READY) { -+ scp->result = DID_ERROR << 16 | -+ RESERVATION_CONFLICT << 1; -+ } -+ else -+ /* -+ * Error code returned is 1 if Reserve or Release -+ * failed or the input parameter is invalid -+ */ -+ if (status == 1 && (scp->cmnd[0] == RESERVE || -+ scp->cmnd[0] == RELEASE)) { -+ -+ scp->result = DID_ERROR << 16 | -+ RESERVATION_CONFLICT << 1; -+ } -+ else { -+ scp->result = DID_BAD_TARGET << 16 | status; -+ } -+ } -+ -+ // print a debug message for all failed commands -+ if (status) { -+ megaraid_mbox_display_scb(adapter, scb); -+ } -+ -+ // Free our internal resources and call the mid-layer callback -+ // routine -+ megaraid_mbox_sync_scb(adapter, scb); -+ -+ // remove from local clist -+ list_del_init(&scb->list); -+ -+ // put back in free list -+ megaraid_dealloc_scb(adapter, scb); -+ -+ // send the scsi packet back to kernel -+ spin_lock(adapter->host_lock); -+ scp->scsi_done(scp); -+ spin_unlock(adapter->host_lock); -+ } -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_abort_handler - abort the scsi command -+ * @scp : command to be aborted -+ * -+ * Abort a previous SCSI request. Only commands on the pending list can be -+ * aborted. All the commands issued to the F/W must complete. -+ **/ -+static int -+megaraid_abort_handler(struct scsi_cmnd *scp) -+{ -+ adapter_t *adapter; -+ mraid_device_t *raid_dev; -+ scb_t *scb; -+ scb_t *tmp; -+ int found; -+ unsigned long flags; -+ int i; -+ -+ -+ adapter = SCP2ADAPTER(scp); -+ raid_dev = ADAP2RAIDDEV(adapter); -+ -+ ASSERT(spin_is_locked(adapter->host_lock)); -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n", -+ scp->serial_number, scp->cmnd[0], SCP2CHANNEL(scp), -+ SCP2TARGET(scp), SCP2LUN(scp))); -+ -+ // If FW has stopped responding, simply return failure -+ if (raid_dev->hw_error) { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: hw error, not aborting\n")); -+ return FAILED; -+ } -+ -+ // There might a race here, where the command was completed by the -+ // firmware and now it is on the completed list. Before we could -+ // complete the command to the kernel in dpc, the abort came. -+ // Find out if this is the case to avoid the race. -+ scb = NULL; -+ spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags); -+ list_for_each_entry_safe(scb, tmp, &adapter->completed_list, list) { -+ -+ if (scb->scp == scp) { // Found command -+ -+ list_del_init(&scb->list); // from completed list -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: %ld:%d[%d:%d], abort from completed list\n", -+ scp->serial_number, scb->sno, -+ scb->dev_channel, scb->dev_target)); -+ -+ scp->result = (DID_ABORT << 16); -+ scp->scsi_done(scp); -+ -+ megaraid_dealloc_scb(adapter, scb); -+ -+ spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), -+ flags); -+ -+ return SUCCESS; -+ } -+ } -+ spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags); -+ -+ -+ // Find out if this command is still on the pending list. If it is and -+ // was never issued, abort and return success. If the command is owned -+ // by the firmware, we must wait for it to complete by the FW. -+ spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); -+ list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) { -+ -+ if (scb->scp == scp) { // Found command -+ -+ list_del_init(&scb->list); // from pending list -+ -+ ASSERT(!(scb->state & SCB_ISSUED)); -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid abort: %ld[%d:%d], driver owner\n", -+ scp->serial_number, scb->dev_channel, -+ scb->dev_target)); -+ -+ scp->result = (DID_ABORT << 16); -+ scp->scsi_done(scp); -+ -+ megaraid_dealloc_scb(adapter, scb); -+ -+ spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), -+ flags); -+ -+ return SUCCESS; -+ } -+ } -+ spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); -+ -+ -+ // Check do we even own this command, in which case this would be -+ // owned by the firmware. The only way to locate the FW scb is to -+ // traverse through the list of all SCB, since driver does not -+ // maintain these SCBs on any list -+ found = 0; -+ for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { -+ scb = adapter->kscb_list + i; -+ -+ if (scb->scp == scp) { -+ -+ found = 1; -+ -+ if (!(scb->state & SCB_ISSUED)) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid abort: %ld%d[%d:%d], invalid state\n", -+ scp->serial_number, scb->sno, scb->dev_channel, -+ scb->dev_target)); -+ BUG(); -+ } -+ else { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid abort: %ld:%d[%d:%d], fw owner\n", -+ scp->serial_number, scb->sno, scb->dev_channel, -+ scb->dev_target)); -+ } -+ } -+ } -+ -+ if (!found) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid abort: scsi cmd:%ld, do now own\n", -+ scp->serial_number)); -+ -+ // FIXME: Should there be a callback for this command? -+ return SUCCESS; -+ } -+ -+ // We cannot actually abort a command owned by firmware, return -+ // failure and wait for reset. In host reset handler, we will find out -+ // if the HBA is still live -+ return FAILED; -+} -+ -+ -+/** -+ * megaraid_reset_handler - device reset hadler for mailbox based driver -+ * @scp : reference command -+ * -+ * Reset handler for the mailbox based controller. First try to find out if -+ * the FW is still live, in which case the outstanding commands counter mut go -+ * down to 0. If that happens, also issue the reservation reset command to -+ * relinquish (possible) reservations on the logical drives connected to this -+ * host -+ **/ -+static int -+megaraid_reset_handler(struct scsi_cmnd *scp) -+{ -+ adapter_t *adapter; -+ scb_t *scb; -+ scb_t *tmp; -+ mraid_device_t *raid_dev; -+ unsigned long flags; -+ uint8_t raw_mbox[sizeof(mbox_t)]; -+ int rval; -+ int recovery_window; -+ int recovering; -+ int i; -+ -+ adapter = SCP2ADAPTER(scp); -+ raid_dev = ADAP2RAIDDEV(adapter); -+ -+ ASSERT(spin_is_locked(adapter->host_lock)); -+ -+ con_log(CL_ANN, (KERN_WARNING "megaraid: resetting the host...\n")); -+ -+ // return failure if adapter is not responding -+ if (raid_dev->hw_error) { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: hw error, cannot reset\n")); -+ return FAILED; -+ } -+ -+ -+ // Under exceptional conditions, FW can take up to 3 minutes to -+ // complete command processing. Wait for additional 2 minutes for the -+ // pending commands counter to go down to 0. If it doesn't, let the -+ // controller be marked offline -+ // Also, reset all the commands currently owned by the driver -+ spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); -+ list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) { -+ -+ list_del_init(&scb->list); // from pending list -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: %ld:%d[%d:%d], reset from pending list\n", -+ scp->serial_number, scb->sno, -+ scb->dev_channel, scb->dev_target)); -+ -+ scp->result = (DID_RESET << 16); -+ if (scp->scsi_done) { -+ scp->scsi_done(scp); -+ } -+ -+ megaraid_dealloc_scb(adapter, scb); -+ } -+ spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); -+ -+ if (adapter->outstanding_cmds) { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: %d outstanding commands. Max wait %d sec\n", -+ adapter->outstanding_cmds, MBOX_RESET_WAIT)); -+ } -+ -+ spin_unlock(adapter->host_lock); -+ -+ recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT; -+ -+ recovering = adapter->outstanding_cmds; -+ -+ for (i = 0; i < recovery_window && adapter->outstanding_cmds; i++) { -+ -+ megaraid_ack_sequence(adapter); -+ -+ // print a message once every 5 seconds only -+ if (!(i % 5)) { -+ con_log(CL_ANN, ( -+ "megaraid mbox: Wait for %d commands to complete:%d\n", -+ adapter->outstanding_cmds, -+ MBOX_RESET_WAIT - i)); -+ } -+ -+ // bailout if no recovery happended in reset time -+ if ((i == MBOX_RESET_WAIT) && -+ (recovering == adapter->outstanding_cmds)) { -+ break; -+ } -+ -+ msleep(1000); -+ } -+ -+ spin_lock(adapter->host_lock); -+ -+ // If still outstanding commands, bail out -+ if (adapter->outstanding_cmds) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mbox: critical hardware error!\n")); -+ -+ raid_dev->hw_error = 1; -+ -+ return FAILED; -+ } -+ else { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid mbox: reset sequence completed successfully\n")); -+ } -+ -+ -+ // If the controller supports clustering, reset reservations -+ if (!adapter->ha) return SUCCESS; -+ -+ // clear reservations if any -+ raw_mbox[0] = CLUSTER_CMD; -+ raw_mbox[2] = RESET_RESERVATIONS; -+ -+ rval = SUCCESS; -+ if (mbox_post_sync_cmd_fast(adapter, raw_mbox) == 0) { -+ con_log(CL_ANN, -+ (KERN_INFO "megaraid: reservation reset\n")); -+ } -+ else { -+ rval = FAILED; -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: reservation reset failed\n")); -+ } -+ -+ return rval; -+} -+ -+ -+/* -+ * START: internal commands library -+ * -+ * This section of the driver has the common routine used by the driver and -+ * also has all the FW routines -+ */ -+ -+/** -+ * mbox_post_sync_cmd() - blocking command to the mailbox based controllers -+ * @adapter - controller's soft state -+ * @raw_mbox - the mailbox -+ * -+ * Issue a scb in synchronous and non-interrupt mode for mailbox based -+ * controllers -+ */ -+static int -+mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[]) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ mbox64_t *mbox64; -+ mbox_t *mbox; -+ uint8_t status; -+ int i; -+ -+ -+ mbox64 = raid_dev->mbox64; -+ mbox = raid_dev->mbox; -+ -+ /* -+ * Wait until mailbox is free -+ */ -+ if (megaraid_busywait_mbox(raid_dev) != 0) -+ goto blocked_mailbox; -+ -+ /* -+ * Copy mailbox data into host structure -+ */ -+ memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16); -+ mbox->cmdid = 0xFE; -+ mbox->busy = 1; -+ mbox->poll = 0; -+ mbox->ack = 0; -+ mbox->numstatus = 0xFF; -+ mbox->status = 0xFF; -+ -+ wmb(); -+ WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1); -+ -+ // wait for maximum 1 second for status to post. If the status is not -+ // available within 1 second, assume FW is initializing and wait -+ // for an extended amount of time -+ if (mbox->numstatus == 0xFF) { // status not yet available -+ udelay(25);; -+ -+ for (i = 0; mbox->numstatus == 0xFF && i < 1000; i++) { -+ rmb(); -+ msleep(1); -+ } -+ -+ -+ if (i == 1000) { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid mailbox: wait for FW to boot ")); -+ -+ for (i = 0; (mbox->numstatus == 0xFF) && -+ (i < MBOX_RESET_WAIT); i++) { -+ rmb(); -+ con_log(CL_ANN, ("\b\b\b\b\b[%03d]", -+ MBOX_RESET_WAIT - i)); -+ msleep(1000); -+ } -+ -+ if (i == MBOX_RESET_WAIT) { -+ -+ con_log(CL_ANN, ( -+ "\nmegaraid mailbox: status not available\n")); -+ -+ return -1; -+ } -+ con_log(CL_ANN, ("\b\b\b\b\b[ok] \n")); -+ } -+ } -+ -+ // wait for maximum 1 second for poll semaphore -+ if (mbox->poll != 0x77) { -+ udelay(25); -+ -+ for (i = 0; (mbox->poll != 0x77) && (i < 1000); i++) { -+ rmb(); -+ msleep(1); -+ } -+ -+ if (i == 1000) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mailbox: could not get poll semaphore\n")); -+ return -1; -+ } -+ } -+ -+ WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2); -+ wmb(); -+ -+ // wait for maximum 1 second for acknowledgement -+ if (RDINDOOR(raid_dev) & 0x2) { -+ udelay(25); -+ -+ for (i = 0; (RDINDOOR(raid_dev) & 0x2) && (i < 1000); i++) { -+ rmb(); -+ msleep(1); -+ } -+ -+ if (i == 1000) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mailbox: could not acknowledge\n")); -+ return -1; -+ } -+ } -+ mbox->poll = 0; -+ mbox->ack = 0x77; -+ -+ status = mbox->status; -+ -+ // invalidate the completed command id array. After command -+ // completion, firmware would write the valid id. -+ mbox->numstatus = 0xFF; -+ mbox->status = 0xFF; -+ for (i = 0; i < MBOX_MAX_FIRMWARE_STATUS; i++) { -+ mbox->completed[i] = 0xFF; -+ } -+ -+ return status; -+ -+blocked_mailbox: -+ -+ con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n") ); -+ return -1; -+} -+ -+ -+/** -+ * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers -+ * @adapter - controller's soft state -+ * @raw_mbox - the mailbox -+ * -+ * Issue a scb in synchronous and non-interrupt mode for mailbox based -+ * controllers. This is a faster version of the synchronous command and -+ * therefore can be called in interrupt-context as well -+ */ -+static int -+mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[]) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ mbox_t *mbox; -+ long i; -+ -+ -+ mbox = raid_dev->mbox; -+ -+ // return immediately if the mailbox is busy -+ if (mbox->busy) return -1; -+ -+ // Copy mailbox data into host structure -+ memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 14); -+ mbox->cmdid = 0xFE; -+ mbox->busy = 1; -+ mbox->poll = 0; -+ mbox->ack = 0; -+ mbox->numstatus = 0xFF; -+ mbox->status = 0xFF; -+ -+ wmb(); -+ WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1); -+ -+ for (i = 0; i < 0xFFFFF; i++) { -+ if (mbox->numstatus != 0xFF) break; -+ } -+ -+ if (i == 0xFFFFF) { -+ // We may need to re-calibrate the counter -+ con_log(CL_ANN, (KERN_CRIT -+ "megaraid: fast sync command timed out\n")); -+ } -+ -+ WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2); -+ wmb(); -+ -+ return mbox->status; -+} -+ -+ -+/** -+ * megaraid_busywait_mbox() - Wait until the controller's mailbox is available -+ * @raid_dev - RAID device (HBA) soft state -+ * -+ * wait until the controller's mailbox is available to accept more commands. -+ * wait for at most 1 second -+ */ -+static int -+megaraid_busywait_mbox(mraid_device_t *raid_dev) -+{ -+ mbox_t *mbox = raid_dev->mbox; -+ int i = 0; -+ -+ if (mbox->busy) { -+ udelay(25); -+ for (i = 0; mbox->busy && i < 1000; i++) -+ msleep(1); -+ } -+ -+ if (i < 1000) return 0; -+ else return -1; -+} -+ -+ -+/** -+ * megaraid_mbox_product_info - some static information about the controller -+ * @adapter - our soft state -+ * -+ * issue commands to the controller to grab some parameters required by our -+ * caller. -+ */ -+static int -+megaraid_mbox_product_info(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ mbox_t *mbox; -+ uint8_t raw_mbox[sizeof(mbox_t)]; -+ mraid_pinfo_t *pinfo; -+ dma_addr_t pinfo_dma_h; -+ mraid_inquiry3_t *mraid_inq3; -+ int i; -+ -+ -+ memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox)); -+ mbox = (mbox_t *)raw_mbox; -+ -+ /* -+ * Issue an ENQUIRY3 command to find out certain adapter parameters, -+ * e.g., max channels, max commands etc. -+ */ -+ pinfo = pci_alloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t), -+ &pinfo_dma_h); -+ -+ if (pinfo == NULL) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: out of memory, %s %d\n", __FUNCTION__, -+ __LINE__)); -+ -+ return -1; -+ } -+ memset(pinfo, 0, sizeof(mraid_pinfo_t)); -+ -+ mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; -+ memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); -+ -+ raw_mbox[0] = FC_NEW_CONFIG; -+ raw_mbox[2] = NC_SUBOP_ENQUIRY3; -+ raw_mbox[3] = ENQ3_GET_SOLICITED_FULL; -+ -+ // Issue the command -+ if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { -+ -+ con_log(CL_ANN, (KERN_WARNING "megaraid: Inquiry3 failed\n")); -+ -+ pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), -+ pinfo, pinfo_dma_h); -+ -+ return -1; -+ } -+ -+ /* -+ * Collect information about state of each physical drive -+ * attached to the controller. We will expose all the disks -+ * which are not part of RAID -+ */ -+ mraid_inq3 = (mraid_inquiry3_t *)adapter->ibuf; -+ for (i = 0; i < MBOX_MAX_PHYSICAL_DRIVES; i++) { -+ raid_dev->pdrv_state[i] = mraid_inq3->pdrv_state[i]; -+ } -+ -+ /* -+ * Get product info for information like number of channels, -+ * maximum commands supported. -+ */ -+ memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox)); -+ mbox->xferaddr = (uint32_t)pinfo_dma_h; -+ -+ raw_mbox[0] = FC_NEW_CONFIG; -+ raw_mbox[2] = NC_SUBOP_PRODUCT_INFO; -+ -+ if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: product info failed\n")); -+ -+ pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), -+ pinfo, pinfo_dma_h); -+ -+ return -1; -+ } -+ -+ /* -+ * Setup some parameters for host, as required by our caller -+ */ -+ adapter->max_channel = pinfo->nchannels; -+ -+ /* -+ * we will export all the logical drives on a single channel. -+ * Add 1 since inquires do not come for inititor ID -+ */ -+ adapter->max_target = MAX_LOGICAL_DRIVES_40LD + 1; -+ adapter->max_lun = 8; // up to 8 LUNs for non-disk devices -+ -+ /* -+ * These are the maximum outstanding commands for the scsi-layer -+ */ -+ adapter->max_cmds = MBOX_MAX_SCSI_CMDS; -+ -+ memset(adapter->fw_version, 0, VERSION_SIZE); -+ memset(adapter->bios_version, 0, VERSION_SIZE); -+ -+ memcpy(adapter->fw_version, pinfo->fw_version, 4); -+ adapter->fw_version[4] = 0; -+ -+ memcpy(adapter->bios_version, pinfo->bios_version, 4); -+ adapter->bios_version[4] = 0; -+ -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: fw version:[%s] bios version:[%s]\n", -+ adapter->fw_version, adapter->bios_version)); -+ -+ pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), pinfo, -+ pinfo_dma_h); -+ -+ return 0; -+} -+ -+ -+ -+/** -+ * megaraid_mbox_extended_cdb - check for support for extended CDBs -+ * @adapter - soft state for the controller -+ * -+ * this routine check whether the controller in question supports extended -+ * ( > 10 bytes ) CDBs -+ */ -+static int -+megaraid_mbox_extended_cdb(adapter_t *adapter) -+{ -+ mbox_t *mbox; -+ uint8_t raw_mbox[sizeof(mbox_t)]; -+ int rval; -+ -+ mbox = (mbox_t *)raw_mbox; -+ -+ memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox)); -+ mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; -+ -+ memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); -+ -+ raw_mbox[0] = MAIN_MISC_OPCODE; -+ raw_mbox[2] = SUPPORT_EXT_CDB; -+ -+ /* -+ * Issue the command -+ */ -+ rval = 0; -+ if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { -+ rval = -1; -+ } -+ -+ return rval; -+} -+ -+ -+/** -+ * megaraid_mbox_support_ha - Do we support clustering -+ * @adapter - soft state for the controller -+ * @init_id - ID of the initiator -+ * -+ * Determine if the firmware supports clustering and the ID of the initiator. -+ */ -+static int -+megaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id) -+{ -+ mbox_t *mbox; -+ uint8_t raw_mbox[sizeof(mbox_t)]; -+ int rval; -+ -+ -+ mbox = (mbox_t *)raw_mbox; -+ -+ memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox)); -+ -+ mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; -+ -+ memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); -+ -+ raw_mbox[0] = GET_TARGET_ID; -+ -+ // Issue the command -+ *init_id = 7; -+ rval = -1; -+ if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) { -+ -+ *init_id = *(uint8_t *)adapter->ibuf; -+ -+ con_log(CL_ANN, (KERN_INFO -+ "megaraid: cluster firmware, initiator ID: %d\n", -+ *init_id)); -+ -+ rval = 0; -+ } -+ -+ return rval; -+} -+ -+ -+/** -+ * megaraid_mbox_support_random_del - Do we support random deletion -+ * @adapter - soft state for the controller -+ * -+ * Determine if the firmware supports random deletion -+ * Return: 1 is operation supported, 0 otherwise -+ */ -+static int -+megaraid_mbox_support_random_del(adapter_t *adapter) -+{ -+ mbox_t *mbox; -+ uint8_t raw_mbox[sizeof(mbox_t)]; -+ int rval; -+ -+ -+ mbox = (mbox_t *)raw_mbox; -+ -+ memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); -+ -+ raw_mbox[0] = FC_DEL_LOGDRV; -+ raw_mbox[2] = OP_SUP_DEL_LOGDRV; -+ -+ // Issue the command -+ rval = 0; -+ if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) { -+ -+ con_log(CL_DLEVEL1, ("megaraid: supports random deletion\n")); -+ -+ rval = 1; -+ } -+ -+ return rval; -+} -+ -+ -+/** -+ * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware -+ * @adapter - soft state for the controller -+ * -+ * Find out the maximum number of scatter-gather elements supported by the -+ * firmware -+ */ -+static int -+megaraid_mbox_get_max_sg(adapter_t *adapter) -+{ -+ mbox_t *mbox; -+ uint8_t raw_mbox[sizeof(mbox_t)]; -+ int nsg; -+ -+ -+ mbox = (mbox_t *)raw_mbox; -+ -+ memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); -+ -+ mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; -+ -+ memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); -+ -+ raw_mbox[0] = MAIN_MISC_OPCODE; -+ raw_mbox[2] = GET_MAX_SG_SUPPORT; -+ -+ // Issue the command -+ if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) { -+ nsg = *(uint8_t *)adapter->ibuf; -+ } -+ else { -+ nsg = MBOX_DEFAULT_SG_SIZE; -+ } -+ -+ if (nsg > MBOX_MAX_SG_SIZE) nsg = MBOX_MAX_SG_SIZE; -+ -+ return nsg; -+} -+ -+ -+/** -+ * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels -+ * @adapter - soft state for the controller -+ * -+ * Enumerate the RAID and SCSI channels for ROMB platoforms so that channels -+ * can be exported as regular SCSI channels -+ */ -+static void -+megaraid_mbox_enum_raid_scsi(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ mbox_t *mbox; -+ uint8_t raw_mbox[sizeof(mbox_t)]; -+ -+ -+ mbox = (mbox_t *)raw_mbox; -+ -+ memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); -+ -+ mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; -+ -+ memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); -+ -+ raw_mbox[0] = CHNL_CLASS; -+ raw_mbox[2] = GET_CHNL_CLASS; -+ -+ // Issue the command. If the command fails, all channels are RAID -+ // channels -+ raid_dev->channel_class = 0xFF; -+ if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) { -+ raid_dev->channel_class = *(uint8_t *)adapter->ibuf; -+ } -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_mbox_flush_cache - flush adapter and disks cache -+ * @param adapter : soft state for the controller -+ * -+ * Flush adapter cache followed by disks cache -+ */ -+static void -+megaraid_mbox_flush_cache(adapter_t *adapter) -+{ -+ mbox_t *mbox; -+ uint8_t raw_mbox[sizeof(mbox_t)]; -+ -+ -+ mbox = (mbox_t *)raw_mbox; -+ -+ memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); -+ -+ raw_mbox[0] = FLUSH_ADAPTER; -+ -+ if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { -+ con_log(CL_ANN, ("megaraid: flush adapter failed\n")); -+ } -+ -+ raw_mbox[0] = FLUSH_SYSTEM; -+ -+ if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { -+ con_log(CL_ANN, ("megaraid: flush disks cache failed\n")); -+ } -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_mbox_display_scb - display SCB information, mostly debug purposes -+ * @param adapter : controllers' soft state -+ * @param scb : SCB to be displayed -+ * @param level : debug level for console print -+ * -+ * Diplay information about the given SCB iff the current debug level is -+ * verbose -+ */ -+static void -+megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb) -+{ -+ mbox_ccb_t *ccb; -+ struct scsi_cmnd *scp; -+ mbox_t *mbox; -+ int level; -+ int i; -+ -+ -+ ccb = (mbox_ccb_t *)scb->ccb; -+ scp = scb->scp; -+ mbox = ccb->mbox; -+ -+ level = CL_DLEVEL3; -+ -+ con_log(level, (KERN_NOTICE -+ "megaraid mailbox: status:%#x cmd:%#x id:%#x ", scb->status, -+ mbox->cmd, scb->sno)); -+ -+ con_log(level, ("sec:%#x lba:%#x addr:%#x ld:%d sg:%d\n", -+ mbox->numsectors, mbox->lba, mbox->xferaddr, mbox->logdrv, -+ mbox->numsge)); -+ -+ if (!scp) return; -+ -+ con_log(level, (KERN_NOTICE "scsi cmnd: ")); -+ -+ for (i = 0; i < scp->cmd_len; i++) { -+ con_log(level, ("%#2.02x ", scp->cmnd[i])); -+ } -+ -+ con_log(level, ("\n")); -+ -+ return; -+} -+ -+ -+/** -+ * megaraid_mbox_setup_device_map - manage device ids -+ * @adapter : Driver's soft state -+ * -+ * Manange the device ids to have an appropraite mapping between the kernel -+ * scsi addresses and megaraid scsi and logical drive addresses. We export -+ * scsi devices on their actual addresses, whereas the logical drives are -+ * exported on a virtual scsi channel. -+ **/ -+static void -+megaraid_mbox_setup_device_map(adapter_t *adapter) -+{ -+ uint8_t c; -+ uint8_t t; -+ -+ /* -+ * First fill the values on the logical drive channel -+ */ -+ for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++) -+ adapter->device_ids[adapter->max_channel][t] = -+ (t < adapter->init_id) ? t : t - 1; -+ -+ adapter->device_ids[adapter->max_channel][adapter->init_id] = 0xFF; -+ -+ /* -+ * Fill the values on the physical devices channels -+ */ -+ for (c = 0; c < adapter->max_channel; c++) -+ for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++) -+ adapter->device_ids[c][t] = (c << 8) | t; -+} -+ -+ -+/* -+ * END: internal commands library -+ */ -+ -+/* -+ * START: Interface for the common management module -+ * -+ * This is the module, which interfaces with the common mangement module to -+ * provide support for ioctl and sysfs -+ */ -+ -+/** -+ * megaraid_cmm_register - register with the mangement module -+ * @param adapter : HBA soft state -+ * -+ * Register with the management module, which allows applications to issue -+ * ioctl calls to the drivers. This interface is used by the management module -+ * to setup sysfs support as well. -+ */ -+static int -+megaraid_cmm_register(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ mraid_mmadp_t adp; -+ scb_t *scb; -+ mbox_ccb_t *ccb; -+ int rval; -+ int i; -+ -+ // Allocate memory for the base list of scb for management module. -+ adapter->uscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_USER_CMDS, -+ GFP_KERNEL); -+ -+ if (adapter->uscb_list == NULL) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: out of memory, %s %d\n", __FUNCTION__, -+ __LINE__)); -+ return -1; -+ } -+ memset(adapter->uscb_list, 0, sizeof(scb_t) * MBOX_MAX_USER_CMDS); -+ -+ -+ // Initialize the synchronization parameters for resources for -+ // commands for management module -+ INIT_LIST_HEAD(&adapter->uscb_pool); -+ -+ spin_lock_init(USER_FREE_LIST_LOCK(adapter)); -+ -+ -+ -+ // link all the packets. Note, CCB for commands, coming from the -+ // commom management module, mailbox physical address are already -+ // setup by it. We just need placeholder for that in our local command -+ // control blocks -+ for (i = 0; i < MBOX_MAX_USER_CMDS; i++) { -+ -+ scb = adapter->uscb_list + i; -+ ccb = raid_dev->uccb_list + i; -+ -+ scb->ccb = (caddr_t)ccb; -+ ccb->mbox64 = raid_dev->umbox64 + i; -+ ccb->mbox = &ccb->mbox64->mbox32; -+ ccb->raw_mbox = (uint8_t *)ccb->mbox; -+ -+ scb->gp = 0; -+ -+ // COMMAND ID 0 - (MBOX_MAX_SCSI_CMDS-1) ARE RESERVED FOR -+ // COMMANDS COMING FROM IO SUBSYSTEM (MID-LAYER) -+ scb->sno = i + MBOX_MAX_SCSI_CMDS; -+ -+ scb->scp = NULL; -+ scb->state = SCB_FREE; -+ scb->dma_direction = PCI_DMA_NONE; -+ scb->dma_type = MRAID_DMA_NONE; -+ scb->dev_channel = -1; -+ scb->dev_target = -1; -+ -+ // put scb in the free pool -+ list_add_tail(&scb->list, &adapter->uscb_pool); -+ } -+ -+ adp.unique_id = adapter->unique_id; -+ adp.drvr_type = DRVRTYPE_MBOX; -+ adp.drvr_data = (unsigned long)adapter; -+ adp.pdev = adapter->pdev; -+ adp.issue_uioc = megaraid_mbox_mm_handler; -+ adp.timeout = 300; -+ adp.max_kioc = MBOX_MAX_USER_CMDS; -+ -+ if ((rval = mraid_mm_register_adp(&adp)) != 0) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mbox: did not register with CMM\n")); -+ -+ kfree(adapter->uscb_list); -+ } -+ -+ return rval; -+} -+ -+ -+/** -+ * megaraid_cmm_unregister - un-register with the mangement module -+ * @param adapter : HBA soft state -+ * -+ * Un-register with the management module. -+ * FIXME: mgmt module must return failure for unregister if it has pending -+ * commands in LLD -+ */ -+static int -+megaraid_cmm_unregister(adapter_t *adapter) -+{ -+ kfree(adapter->uscb_list); -+ mraid_mm_unregister_adp(adapter->unique_id); -+ return 0; -+} -+ -+ -+/** -+ * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD -+ * @param drvr_data : LLD specific data -+ * @param kioc : CMM interface packet -+ * @param action : command action -+ * -+ * This routine is invoked whenever the Common Mangement Module (CMM) has a -+ * command for us. The 'action' parameter specifies if this is a new command -+ * or otherwise. -+ */ -+static int -+megaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action) -+{ -+ adapter_t *adapter; -+ -+ if (action != IOCTL_ISSUE) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: unsupported management action:%#2x\n", -+ action)); -+ return (-ENOTSUPP); -+ } -+ -+ adapter = (adapter_t *)drvr_data; -+ -+ // make sure this adapter is not being detached right now. -+ if (atomic_read(&adapter->being_detached)) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: reject management request, detaching\n")); -+ return (-ENODEV); -+ } -+ -+ switch (kioc->opcode) { -+ -+ case GET_ADAP_INFO: -+ -+ kioc->status = gather_hbainfo(adapter, (mraid_hba_info_t *) -+ (unsigned long)kioc->buf_vaddr); -+ -+ kioc->done(kioc); -+ -+ return kioc->status; -+ -+ case MBOX_CMD: -+ -+ return megaraid_mbox_mm_command(adapter, kioc); -+ -+ default: -+ kioc->status = (-EINVAL); -+ kioc->done(kioc); -+ return (-EINVAL); -+ } -+ -+ return 0; // not reached -+} -+ -+/** -+ * megaraid_mbox_mm_command - issues commands routed through CMM -+ * @param adapter : HBA soft state -+ * @param kioc : management command packet -+ * -+ * Issues commands, which are routed through the management module. -+ */ -+static int -+megaraid_mbox_mm_command(adapter_t *adapter, uioc_t *kioc) -+{ -+ struct list_head *head = &adapter->uscb_pool; -+ mbox64_t *mbox64; -+ uint8_t *raw_mbox; -+ scb_t *scb; -+ mbox_ccb_t *ccb; -+ unsigned long flags; -+ -+ // detach one scb from free pool -+ spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags); -+ -+ if (list_empty(head)) { // should never happen because of CMM -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid mbox: bug in cmm handler, lost resources\n")); -+ -+ spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags); -+ -+ return (-EINVAL); -+ } -+ -+ scb = list_entry(head->next, scb_t, list); -+ list_del_init(&scb->list); -+ -+ spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags); -+ -+ scb->state = SCB_ACTIVE; -+ scb->dma_type = MRAID_DMA_NONE; -+ scb->dma_direction = PCI_DMA_NONE; -+ -+ ccb = (mbox_ccb_t *)scb->ccb; -+ mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf; -+ raw_mbox = (uint8_t *)&mbox64->mbox32; -+ -+ memcpy(ccb->mbox64, mbox64, sizeof(mbox64_t)); -+ -+ scb->gp = (unsigned long)kioc; -+ -+ /* -+ * If it is a logdrv random delete operation, we have to wait till -+ * there are no outstanding cmds at the fw and then issue it directly -+ */ -+ if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) { -+ -+ if (wait_till_fw_empty(adapter)) { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid mbox: LD delete, timed out\n")); -+ -+ kioc->status = -ETIME; -+ -+ scb->status = -1; -+ -+ megaraid_mbox_mm_done(adapter, scb); -+ -+ return (-ETIME); -+ } -+ -+ INIT_LIST_HEAD(&scb->list); -+ -+ scb->state = SCB_ISSUED; -+ if (mbox_post_cmd(adapter, scb) != 0) { -+ -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid mbox: LD delete, mailbox busy\n")); -+ -+ kioc->status = -EBUSY; -+ -+ scb->status = -1; -+ -+ megaraid_mbox_mm_done(adapter, scb); -+ -+ return (-EBUSY); -+ } -+ -+ return 0; -+ } -+ -+ // put the command on the pending list and execute -+ megaraid_mbox_runpendq(adapter, scb); -+ -+ return 0; -+} -+ -+ -+static int -+wait_till_fw_empty(adapter_t *adapter) -+{ -+ unsigned long flags = 0; -+ int i; -+ -+ -+ /* -+ * Set the quiescent flag to stop issuing cmds to FW. -+ */ -+ spin_lock_irqsave(adapter->host_lock, flags); -+ adapter->quiescent++; -+ spin_unlock_irqrestore(adapter->host_lock, flags); -+ -+ /* -+ * Wait till there are no more cmds outstanding at FW. Try for at most -+ * 60 seconds -+ */ -+ for (i = 0; i < 60 && adapter->outstanding_cmds; i++) { -+ con_log(CL_DLEVEL1, (KERN_INFO -+ "megaraid: FW has %d pending commands\n", -+ adapter->outstanding_cmds)); -+ -+ msleep(1000); -+ } -+ -+ return adapter->outstanding_cmds; -+} -+ -+ -+/** -+ * megaraid_mbox_mm_done - callback for CMM commands -+ * @adapter : HBA soft state -+ * @scb : completed command -+ * -+ * Callback routine for internal commands originated from the management -+ * module. -+ */ -+static void -+megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb) -+{ -+ uioc_t *kioc; -+ mbox64_t *mbox64; -+ uint8_t *raw_mbox; -+ unsigned long flags; -+ -+ kioc = (uioc_t *)scb->gp; -+ kioc->status = 0; -+ mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf; -+ mbox64->mbox32.status = scb->status; -+ raw_mbox = (uint8_t *)&mbox64->mbox32; -+ -+ -+ // put scb in the free pool -+ scb->state = SCB_FREE; -+ scb->scp = NULL; -+ -+ spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags); -+ -+ list_add(&scb->list, &adapter->uscb_pool); -+ -+ spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags); -+ -+ // if a delete logical drive operation succeeded, restart the -+ // controller -+ if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) { -+ -+ adapter->quiescent--; -+ -+ megaraid_mbox_runpendq(adapter, NULL); -+ } -+ -+ kioc->done(kioc); -+ -+ return; -+} -+ -+ -+/** -+ * gather_hbainfo - HBA characteristics for the applications -+ * @param adapter : HBA soft state -+ * @param hinfo : pointer to the caller's host info strucuture -+ */ -+static int -+gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo) -+{ -+ uint8_t dmajor; -+ -+ dmajor = megaraid_mbox_version[0]; -+ -+ hinfo->pci_vendor_id = adapter->pdev->vendor; -+ hinfo->pci_device_id = adapter->pdev->device; -+ hinfo->subsys_vendor_id = adapter->pdev->subsystem_vendor; -+ hinfo->subsys_device_id = adapter->pdev->subsystem_device; -+ -+ hinfo->pci_bus = adapter->pdev->bus->number; -+ hinfo->pci_dev_fn = adapter->pdev->devfn; -+ hinfo->pci_slot = PCI_SLOT(adapter->pdev->devfn); -+ hinfo->irq = adapter->host->irq; -+ hinfo->baseport = ADAP2RAIDDEV(adapter)->baseport; -+ -+ hinfo->unique_id = (hinfo->pci_bus << 8) | adapter->pdev->devfn; -+ hinfo->host_no = adapter->host->host_no; -+ -+ return 0; -+} -+ -+/* -+ * END: Interface for the common management module -+ */ -+ -+ -+ -+/** -+ * megaraid_sysfs_alloc_resources - allocate sysfs related resources -+ * -+ * Allocate packets required to issue FW calls whenever the sysfs attributes -+ * are read. These attributes would require up-to-date information from the -+ * FW. Also set up resources for mutual exclusion to share these resources and -+ * the wait queue. -+ * -+ * @param adapter : controller's soft state -+ * -+ * @return 0 on success -+ * @return -ERROR_CODE on failure -+ */ -+static int -+megaraid_sysfs_alloc_resources(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ int rval = 0; -+ -+ raid_dev->sysfs_uioc = kmalloc(sizeof(uioc_t), GFP_KERNEL); -+ -+ raid_dev->sysfs_mbox64 = kmalloc(sizeof(mbox64_t), GFP_KERNEL); -+ -+ raid_dev->sysfs_buffer = pci_alloc_consistent(adapter->pdev, -+ PAGE_SIZE, &raid_dev->sysfs_buffer_dma); -+ -+ if (!raid_dev->sysfs_uioc || !raid_dev->sysfs_mbox64 || -+ !raid_dev->sysfs_buffer) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid: out of memory, %s %d\n", __FUNCTION__, -+ __LINE__)); -+ -+ rval = -ENOMEM; -+ -+ megaraid_sysfs_free_resources(adapter); -+ } -+ -+ sema_init(&raid_dev->sysfs_sem, 1); -+ -+ init_waitqueue_head(&raid_dev->sysfs_wait_q); -+ -+ return rval; -+} -+ -+ -+/** -+ * megaraid_sysfs_free_resources - free sysfs related resources -+ * -+ * Free packets allocated for sysfs FW commands -+ * -+ * @param adapter : controller's soft state -+ */ -+static void -+megaraid_sysfs_free_resources(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ -+ if (raid_dev->sysfs_uioc) kfree(raid_dev->sysfs_uioc); -+ -+ if (raid_dev->sysfs_mbox64) kfree(raid_dev->sysfs_mbox64); -+ -+ if (raid_dev->sysfs_buffer) { -+ pci_free_consistent(adapter->pdev, PAGE_SIZE, -+ raid_dev->sysfs_buffer, raid_dev->sysfs_buffer_dma); -+ } -+} -+ -+ -+/** -+ * megaraid_sysfs_get_ldmap_done - callback for get ldmap -+ * -+ * Callback routine called in the ISR/tasklet context for get ldmap call -+ * -+ * @param uioc : completed packet -+ */ -+static void -+megaraid_sysfs_get_ldmap_done(uioc_t *uioc) -+{ -+ adapter_t *adapter = (adapter_t *)uioc->buf_vaddr; -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ -+ uioc->status = 0; -+ -+ wake_up(&raid_dev->sysfs_wait_q); -+} -+ -+ -+/** -+ * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap -+ * -+ * Timeout routine to recover and return to application, in case the adapter -+ * has stopped responding. A timeout of 60 seconds for this command seem like -+ * a good value -+ * -+ * @param uioc : timed out packet -+ */ -+static void -+megaraid_sysfs_get_ldmap_timeout(unsigned long data) -+{ -+ uioc_t *uioc = (uioc_t *)data; -+ adapter_t *adapter = (adapter_t *)uioc->buf_vaddr; -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ -+ uioc->status = -ETIME; -+ -+ wake_up(&raid_dev->sysfs_wait_q); -+} -+ -+ -+/** -+ * megaraid_sysfs_get_ldmap - get update logical drive map -+ * -+ * This routine will be called whenever user reads the logical drive -+ * attributes, go get the current logical drive mapping table from the -+ * firmware. We use the managment API's to issue commands to the controller. -+ * -+ * NOTE: The commands issuance functionality is not generalized and -+ * implemented in context of "get ld map" command only. If required, the -+ * command issuance logical can be trivially pulled out and implemented as a -+ * standalone libary. For now, this should suffice since there is no other -+ * user of this interface. -+ * -+ * @param adapter : controller's soft state -+ * -+ * @return 0 on success -+ * @return -1 on failure -+ */ -+static int -+megaraid_sysfs_get_ldmap(adapter_t *adapter) -+{ -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ uioc_t *uioc; -+ mbox64_t *mbox64; -+ mbox_t *mbox; -+ char *raw_mbox; -+ struct timer_list sysfs_timer; -+ struct timer_list *timerp; -+ caddr_t ldmap; -+ int rval = 0; -+ -+ /* -+ * Allow only one read at a time to go through the sysfs attributes -+ */ -+ down(&raid_dev->sysfs_sem); -+ -+ uioc = raid_dev->sysfs_uioc; -+ mbox64 = raid_dev->sysfs_mbox64; -+ ldmap = raid_dev->sysfs_buffer; -+ -+ memset(uioc, 0, sizeof(uioc_t)); -+ memset(mbox64, 0, sizeof(mbox64_t)); -+ memset(ldmap, 0, sizeof(raid_dev->curr_ldmap)); -+ -+ mbox = &mbox64->mbox32; -+ raw_mbox = (char *)mbox; -+ uioc->cmdbuf = (uint64_t)(unsigned long)mbox64; -+ uioc->buf_vaddr = (caddr_t)adapter; -+ uioc->status = -ENODATA; -+ uioc->done = megaraid_sysfs_get_ldmap_done; -+ -+ /* -+ * Prepare the mailbox packet to get the current logical drive mapping -+ * table -+ */ -+ mbox->xferaddr = (uint32_t)raid_dev->sysfs_buffer_dma; -+ -+ raw_mbox[0] = FC_DEL_LOGDRV; -+ raw_mbox[2] = OP_GET_LDID_MAP; -+ -+ /* -+ * Setup a timer to recover from a non-responding controller -+ */ -+ timerp = &sysfs_timer; -+ init_timer(timerp); -+ -+ timerp->function = megaraid_sysfs_get_ldmap_timeout; -+ timerp->data = (unsigned long)uioc; -+ timerp->expires = jiffies + 60 * HZ; -+ -+ add_timer(timerp); -+ -+ /* -+ * Send the command to the firmware -+ */ -+ rval = megaraid_mbox_mm_command(adapter, uioc); -+ -+ if (rval == 0) { // command successfully issued -+ wait_event(raid_dev->sysfs_wait_q, (uioc->status != -ENODATA)); -+ -+ /* -+ * Check if the command timed out -+ */ -+ if (uioc->status == -ETIME) { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: sysfs get ld map timed out\n")); -+ -+ rval = -ETIME; -+ } -+ else { -+ rval = mbox->status; -+ } -+ -+ if (rval == 0) { -+ memcpy(raid_dev->curr_ldmap, ldmap, -+ sizeof(raid_dev->curr_ldmap)); -+ } -+ else { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: get ld map failed with %x\n", rval)); -+ } -+ } -+ else { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: could not issue ldmap command:%x\n", rval)); -+ } -+ -+ -+ del_timer_sync(timerp); -+ -+ up(&raid_dev->sysfs_sem); -+ -+ return rval; -+} -+ -+ -+/** -+ * megaraid_sysfs_show_app_hndl - display application handle for this adapter -+ * -+ * Display the handle used by the applications while executing management -+ * tasks on the adapter. We invoke a management module API to get the adapter -+ * handle, since we do not interface with applications directly. -+ * -+ * @param cdev : class device object representation for the host -+ * @param buf : buffer to send data to -+ */ -+static ssize_t -+megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf) -+{ -+ struct Scsi_Host *shost = class_to_shost(cdev); -+ adapter_t *adapter = (adapter_t *)SCSIHOST2ADAP(shost); -+ uint32_t app_hndl; -+ -+ app_hndl = mraid_mm_adapter_app_handle(adapter->unique_id); -+ -+ return snprintf(buf, 8, "%u\n", app_hndl); -+} -+ -+ -+/** -+ * megaraid_sysfs_show_ldnum - display the logical drive number for this device -+ * -+ * Display the logical drive number for the device in question, if it a valid -+ * logical drive. For physical devices, "-1" is returned -+ * The logical drive number is displayed in following format -+ * -+ * <SCSI ID> <LD NUM> <LD STICKY ID> <APP ADAPTER HANDLE> -+ * <int> <int> <int> <int> -+ * -+ * @param dev : device object representation for the scsi device -+ * @param buf : buffer to send data to -+ */ -+static ssize_t -+megaraid_sysfs_show_ldnum(struct device *dev, char *buf) -+{ -+ struct scsi_device *sdev = to_scsi_device(dev); -+ adapter_t *adapter = (adapter_t *)SCSIHOST2ADAP(sdev->host); -+ mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); -+ int scsi_id = -1; -+ int logical_drv = -1; -+ int ldid_map = -1; -+ uint32_t app_hndl = 0; -+ int mapped_sdev_id; -+ int rval; -+ int i; -+ -+ if (raid_dev->random_del_supported && -+ MRAID_IS_LOGICAL_SDEV(adapter, sdev)) { -+ -+ rval = megaraid_sysfs_get_ldmap(adapter); -+ if (rval == 0) { -+ -+ for (i = 0; i < MAX_LOGICAL_DRIVES_40LD; i++) { -+ -+ mapped_sdev_id = sdev->id; -+ -+ if (sdev->id > adapter->init_id) { -+ mapped_sdev_id -= 1; -+ } -+ -+ if (raid_dev->curr_ldmap[i] == mapped_sdev_id) { -+ -+ scsi_id = sdev->id; -+ -+ logical_drv = i; -+ -+ ldid_map = raid_dev->curr_ldmap[i]; -+ -+ app_hndl = mraid_mm_adapter_app_handle( -+ adapter->unique_id); -+ -+ break; -+ } -+ } -+ } -+ else { -+ con_log(CL_ANN, (KERN_NOTICE -+ "megaraid: sysfs get ld map failed: %x\n", -+ rval)); -+ } -+ } -+ -+ return snprintf(buf, 36, "%d %d %d %d\n", scsi_id, logical_drv, -+ ldid_map, app_hndl); -+} -+ -+ -+/* -+ * END: Mailbox Low Level Driver -+ */ -+module_init(megaraid_init); -+module_exit(megaraid_exit); -+ -+/* vim: set ts=8 sw=8 tw=78 ai si: */ ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid/megaraid_mbox.h 1970-01-01 03:00:00.000000000 +0300 -+++ rhel4u2/drivers/scsi/megaraid/megaraid_mbox.h 2005-10-19 11:47:15.000000000 +0400 -@@ -0,0 +1,234 @@ -+/* -+ * -+ * Linux MegaRAID device driver -+ * -+ * Copyright (c) 2003-2004 LSI Logic Corporation. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * FILE : megaraid_mbox.h -+ */ -+ -+#ifndef _MEGARAID_H_ -+#define _MEGARAID_H_ -+ -+ -+#include "mega_common.h" -+#include "mbox_defs.h" -+#include "megaraid_ioctl.h" -+ -+ -+#define MEGARAID_VERSION "2.20.4.6" -+#define MEGARAID_EXT_VERSION "(Release Date: Mon Mar 07 12:27:22 EST 2005)" -+ -+ -+/* -+ * Define some PCI values here until they are put in the kernel -+ */ -+#define PCI_DEVICE_ID_PERC4_DI_DISCOVERY 0x000E -+#define PCI_SUBSYS_ID_PERC4_DI_DISCOVERY 0x0123 -+ -+#define PCI_DEVICE_ID_PERC4_SC 0x1960 -+#define PCI_SUBSYS_ID_PERC4_SC 0x0520 -+ -+#define PCI_DEVICE_ID_PERC4_DC 0x1960 -+#define PCI_SUBSYS_ID_PERC4_DC 0x0518 -+ -+#define PCI_DEVICE_ID_VERDE 0x0407 -+ -+#define PCI_DEVICE_ID_PERC4_DI_EVERGLADES 0x000F -+#define PCI_SUBSYS_ID_PERC4_DI_EVERGLADES 0x014A -+ -+#define PCI_DEVICE_ID_PERC4E_SI_BIGBEND 0x0013 -+#define PCI_SUBSYS_ID_PERC4E_SI_BIGBEND 0x016c -+ -+#define PCI_DEVICE_ID_PERC4E_DI_KOBUK 0x0013 -+#define PCI_SUBSYS_ID_PERC4E_DI_KOBUK 0x016d -+ -+#define PCI_DEVICE_ID_PERC4E_DI_CORVETTE 0x0013 -+#define PCI_SUBSYS_ID_PERC4E_DI_CORVETTE 0x016e -+ -+#define PCI_DEVICE_ID_PERC4E_DI_EXPEDITION 0x0013 -+#define PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION 0x016f -+ -+#define PCI_DEVICE_ID_PERC4E_DI_GUADALUPE 0x0013 -+#define PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE 0x0170 -+ -+#define PCI_DEVICE_ID_DOBSON 0x0408 -+ -+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_0 0x1960 -+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0 0xA520 -+ -+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_1 0x1960 -+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_1 0x0520 -+ -+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2 0x1960 -+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2 0x0518 -+ -+#define PCI_DEVICE_ID_MEGARAID_I4_133_RAID 0x1960 -+#define PCI_SUBSYS_ID_MEGARAID_I4_133_RAID 0x0522 -+ -+#define PCI_DEVICE_ID_MEGARAID_SATA_150_4 0x1960 -+#define PCI_SUBSYS_ID_MEGARAID_SATA_150_4 0x4523 -+ -+#define PCI_DEVICE_ID_MEGARAID_SATA_150_6 0x1960 -+#define PCI_SUBSYS_ID_MEGARAID_SATA_150_6 0x0523 -+ -+#define PCI_DEVICE_ID_LINDSAY 0x0409 -+ -+#define PCI_DEVICE_ID_INTEL_RAID_SRCS16 0x1960 -+#define PCI_SUBSYS_ID_INTEL_RAID_SRCS16 0x0523 -+ -+#define PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK 0x1960 -+#define PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK 0x0520 -+ -+#define PCI_SUBSYS_ID_PERC3_QC 0x0471 -+#define PCI_SUBSYS_ID_PERC3_DC 0x0493 -+#define PCI_SUBSYS_ID_PERC3_SC 0x0475 -+ -+ -+#define MBOX_MAX_SCSI_CMDS 128 // number of cmds reserved for kernel -+#define MBOX_MAX_USER_CMDS 32 // number of cmds for applications -+#define MBOX_DEF_CMD_PER_LUN 64 // default commands per lun -+#define MBOX_DEFAULT_SG_SIZE 26 // default sg size supported by all fw -+#define MBOX_MAX_SG_SIZE 32 // maximum scatter-gather list size -+#define MBOX_MAX_SECTORS 128 // maximum sectors per IO -+#define MBOX_TIMEOUT 30 // timeout value for internal cmds -+#define MBOX_BUSY_WAIT 10 // max usec to wait for busy mailbox -+#define MBOX_RESET_WAIT 180 // wait these many seconds in reset -+#define MBOX_RESET_EXT_WAIT 120 // extended wait reset -+ -+/* -+ * maximum transfer that can happen through the firmware commands issued -+ * internnaly from the driver. -+ */ -+#define MBOX_IBUF_SIZE 4096 -+ -+ -+/** -+ * mbox_ccb_t - command control block specific to mailbox based controllers -+ * @raw_mbox : raw mailbox pointer -+ * @mbox : mailbox -+ * @mbox64 : extended mailbox -+ * @mbox_dma_h : maibox dma address -+ * @sgl64 : 64-bit scatter-gather list -+ * @sgl32 : 32-bit scatter-gather list -+ * @sgl_dma_h : dma handle for the scatter-gather list -+ * @pthru : passthru structure -+ * @pthru_dma_h : dma handle for the passthru structure -+ * @epthru : extended passthru structure -+ * @epthru_dma_h : dma handle for extended passthru structure -+ * @buf_dma_h : dma handle for buffers w/o sg list -+ * -+ * command control block specific to the mailbox based controllers -+ */ -+typedef struct { -+ uint8_t *raw_mbox; -+ mbox_t *mbox; -+ mbox64_t *mbox64; -+ dma_addr_t mbox_dma_h; -+ mbox_sgl64 *sgl64; -+ mbox_sgl32 *sgl32; -+ dma_addr_t sgl_dma_h; -+ mraid_passthru_t *pthru; -+ dma_addr_t pthru_dma_h; -+ mraid_epassthru_t *epthru; -+ dma_addr_t epthru_dma_h; -+ dma_addr_t buf_dma_h; -+} mbox_ccb_t; -+ -+ -+/** -+ * mraid_device_t - adapter soft state structure for mailbox controllers -+ * @param una_mbox64 : 64-bit mbox - unaligned -+ * @param una_mbox64_dma : mbox dma addr - unaligned -+ * @param mbox : 32-bit mbox - aligned -+ * @param mbox64 : 64-bit mbox - aligned -+ * @param mbox_dma : mbox dma addr - aligned -+ * @param mailbox_lock : exclusion lock for the mailbox -+ * @param baseport : base port of hba memory -+ * @param baseaddr : mapped addr of hba memory -+ * @param mbox_pool : pool of mailboxes -+ * @param mbox_pool_handle : handle for the mailbox pool memory -+ * @param epthru_pool : a pool for extended passthru commands -+ * @param epthru_pool_handle : handle to the pool above -+ * @param sg_pool : pool of scatter-gather lists for this driver -+ * @param sg_pool_handle : handle to the pool above -+ * @param ccb_list : list of our command control blocks -+ * @param uccb_list : list of cmd control blocks for mgmt module -+ * @param umbox64 : array of mailbox for user commands (cmm) -+ * @param pdrv_state : array for state of each physical drive. -+ * @param last_disp : flag used to show device scanning -+ * @param hw_error : set if FW not responding -+ * @param fast_load : If set, skip physical device scanning -+ * @channel_class : channel class, RAID or SCSI -+ * @sysfs_sem : semaphore to serialize access to sysfs res. -+ * @sysfs_uioc : management packet to issue FW calls from sysfs -+ * @sysfs_mbox64 : mailbox packet to issue FW calls from sysfs -+ * @sysfs_buffer : data buffer for FW commands issued from sysfs -+ * @sysfs_buffer_dma : DMA buffer for FW commands issued from sysfs -+ * @sysfs_wait_q : wait queue for sysfs operations -+ * @random_del_supported : set if the random deletion is supported -+ * @curr_ldmap : current LDID map -+ * -+ * Initialization structure for mailbox controllers: memory based and IO based -+ * All the fields in this structure are LLD specific and may be discovered at -+ * init() or start() time. -+ * -+ * NOTE: The fields of this structures are placed to minimize cache misses -+ */ -+#define MAX_LD_EXTENDED64 64 -+typedef struct { -+ mbox64_t *una_mbox64; -+ dma_addr_t una_mbox64_dma; -+ mbox_t *mbox; -+ mbox64_t *mbox64; -+ dma_addr_t mbox_dma; -+ spinlock_t mailbox_lock; -+ unsigned long baseport; -+ void __iomem * baseaddr; -+ struct mraid_pci_blk mbox_pool[MBOX_MAX_SCSI_CMDS]; -+ struct dma_pool *mbox_pool_handle; -+ struct mraid_pci_blk epthru_pool[MBOX_MAX_SCSI_CMDS]; -+ struct dma_pool *epthru_pool_handle; -+ struct mraid_pci_blk sg_pool[MBOX_MAX_SCSI_CMDS]; -+ struct dma_pool *sg_pool_handle; -+ mbox_ccb_t ccb_list[MBOX_MAX_SCSI_CMDS]; -+ mbox_ccb_t uccb_list[MBOX_MAX_USER_CMDS]; -+ mbox64_t umbox64[MBOX_MAX_USER_CMDS]; -+ -+ uint8_t pdrv_state[MBOX_MAX_PHYSICAL_DRIVES]; -+ uint32_t last_disp; -+ int hw_error; -+ int fast_load; -+ uint8_t channel_class; -+ struct semaphore sysfs_sem; -+ uioc_t *sysfs_uioc; -+ mbox64_t *sysfs_mbox64; -+ caddr_t sysfs_buffer; -+ dma_addr_t sysfs_buffer_dma; -+ wait_queue_head_t sysfs_wait_q; -+ int random_del_supported; -+ uint16_t curr_ldmap[MAX_LD_EXTENDED64]; -+} mraid_device_t; -+ -+// route to raid device from adapter -+#define ADAP2RAIDDEV(adp) ((mraid_device_t *)((adp)->raid_device)) -+ -+#define MAILBOX_LOCK(rdev) (&(rdev)->mailbox_lock) -+ -+// Find out if this channel is a RAID or SCSI -+#define IS_RAID_CH(rdev, ch) (((rdev)->channel_class >> (ch)) & 0x01) -+ -+ -+#define RDINDOOR(rdev) readl((rdev)->baseaddr + 0x20) -+#define RDOUTDOOR(rdev) readl((rdev)->baseaddr + 0x2C) -+#define WRINDOOR(rdev, value) writel(value, (rdev)->baseaddr + 0x20) -+#define WROUTDOOR(rdev, value) writel(value, (rdev)->baseaddr + 0x2C) -+ -+#endif // _MEGARAID_H_ -+ -+// vim: set ts=8 sw=8 tw=78: ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid/megaraid_mm.c 1970-01-01 03:00:00.000000000 +0300 -+++ rhel4u2/drivers/scsi/megaraid/megaraid_mm.c 2005-10-20 14:44:46.220000464 +0400 -@@ -0,0 +1,1256 @@ -+/* -+ * -+ * Linux MegaRAID device driver -+ * -+ * Copyright (c) 2003-2004 LSI Logic Corporation. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * FILE : megaraid_mm.c -+ * Version : v2.20.2.6 (Mar 7 2005) -+ * -+ * Common management module -+ */ -+ -+#include "megaraid_mm.h" -+ -+ -+// Entry points for char node driver -+static int mraid_mm_open(struct inode *, struct file *); -+static int mraid_mm_ioctl(struct inode *, struct file *, uint, unsigned long); -+ -+ -+// routines to convert to and from the old the format -+static int mimd_to_kioc(mimd_t __user *, mraid_mmadp_t *, uioc_t *); -+static int kioc_to_mimd(uioc_t *, mimd_t __user *); -+ -+ -+// Helper functions -+static int handle_drvrcmd(void __user *, uint8_t, int *); -+static int lld_ioctl(mraid_mmadp_t *, uioc_t *); -+static void ioctl_done(uioc_t *); -+static void lld_timedout(unsigned long); -+static void hinfo_to_cinfo(mraid_hba_info_t *, mcontroller_t *); -+static mraid_mmadp_t *mraid_mm_get_adapter(mimd_t __user *, int *); -+static uioc_t *mraid_mm_alloc_kioc(mraid_mmadp_t *); -+static void mraid_mm_dealloc_kioc(mraid_mmadp_t *, uioc_t *); -+static int mraid_mm_attach_buf(mraid_mmadp_t *, uioc_t *, int); -+static int mraid_mm_setup_dma_pools(mraid_mmadp_t *); -+static void mraid_mm_free_adp_resources(mraid_mmadp_t *); -+static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *); -+ -+#ifdef CONFIG_COMPAT -+static int mraid_mm_compat_ioctl(unsigned int, unsigned int, unsigned long, -+ struct file *); -+#endif -+ -+MODULE_AUTHOR("LSI Logic Corporation"); -+MODULE_DESCRIPTION("LSI Logic Management Module"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(LSI_COMMON_MOD_VERSION); -+ -+static int dbglevel = CL_ANN; -+module_param_named(dlevel, dbglevel, int, 0); -+MODULE_PARM_DESC(dlevel, "Debug level (default=0)"); -+ -+EXPORT_SYMBOL(mraid_mm_register_adp); -+EXPORT_SYMBOL(mraid_mm_unregister_adp); -+EXPORT_SYMBOL(mraid_mm_adapter_app_handle); -+ -+static int majorno; -+static uint32_t drvr_ver = 0x02200206; -+ -+static int adapters_count_g; -+static struct list_head adapters_list_g; -+ -+static wait_queue_head_t wait_q; -+ -+static struct file_operations lsi_fops = { -+ .open = mraid_mm_open, -+ .ioctl = mraid_mm_ioctl, -+ .owner = THIS_MODULE, -+}; -+ -+/** -+ * mraid_mm_open - open routine for char node interface -+ * @inod : unused -+ * @filep : unused -+ * -+ * allow ioctl operations by apps only if they superuser privilege -+ */ -+static int -+mraid_mm_open(struct inode *inode, struct file *filep) -+{ -+ /* -+ * Only allow superuser to access private ioctl interface -+ */ -+ if (!capable(CAP_SYS_ADMIN)) return (-EACCES); -+ -+ return 0; -+} -+ -+/** -+ * mraid_mm_ioctl - module entry-point for ioctls -+ * @inode : inode (ignored) -+ * @filep : file operations pointer (ignored) -+ * @cmd : ioctl command -+ * @arg : user ioctl packet -+ */ -+static int -+mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, -+ unsigned long arg) -+{ -+ uioc_t *kioc; -+ char signature[EXT_IOCTL_SIGN_SZ] = {0}; -+ int rval; -+ mraid_mmadp_t *adp; -+ uint8_t old_ioctl; -+ int drvrcmd_rval; -+ void __user *argp = (void __user *)arg; -+ -+ /* -+ * Make sure only USCSICMD are issued through this interface. -+ * MIMD application would still fire different command. -+ */ -+ -+ if ((_IOC_TYPE(cmd) != MEGAIOC_MAGIC) && (cmd != USCSICMD)) { -+ return (-EINVAL); -+ } -+ -+ /* -+ * Look for signature to see if this is the new or old ioctl format. -+ */ -+ if (copy_from_user(signature, argp, EXT_IOCTL_SIGN_SZ)) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid cmm: copy from usr addr failed\n")); -+ return (-EFAULT); -+ } -+ -+ if (memcmp(signature, EXT_IOCTL_SIGN, EXT_IOCTL_SIGN_SZ) == 0) -+ old_ioctl = 0; -+ else -+ old_ioctl = 1; -+ -+ /* -+ * At present, we don't support the new ioctl packet -+ */ -+ if (!old_ioctl ) -+ return (-EINVAL); -+ -+ /* -+ * If it is a driver ioctl (as opposed to fw ioctls), then we can -+ * handle the command locally. rval > 0 means it is not a drvr cmd -+ */ -+ rval = handle_drvrcmd(argp, old_ioctl, &drvrcmd_rval); -+ -+ if (rval < 0) -+ return rval; -+ else if (rval == 0) -+ return drvrcmd_rval; -+ -+ rval = 0; -+ if ((adp = mraid_mm_get_adapter(argp, &rval)) == NULL) { -+ return rval; -+ } -+ -+ /* -+ * Check if adapter can accept ioctl. We may have marked it offline -+ * if any previous kioc had timedout on this controller. -+ */ -+ if (!adp->quiescent) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid cmm: controller cannot accept cmds due to " -+ "earlier errors\n" )); -+ return -EFAULT; -+ } -+ -+ /* -+ * The following call will block till a kioc is available -+ */ -+ kioc = mraid_mm_alloc_kioc(adp); -+ -+ /* -+ * User sent the old mimd_t ioctl packet. Convert it to uioc_t. -+ */ -+ if ((rval = mimd_to_kioc(argp, adp, kioc))) { -+ mraid_mm_dealloc_kioc(adp, kioc); -+ return rval; -+ } -+ -+ kioc->done = ioctl_done; -+ -+ /* -+ * Issue the IOCTL to the low level driver. After the IOCTL completes -+ * release the kioc if and only if it was _not_ timedout. If it was -+ * timedout, that means that resources are still with low level driver. -+ */ -+ if ((rval = lld_ioctl(adp, kioc))) { -+ -+ if (!kioc->timedout) -+ mraid_mm_dealloc_kioc(adp, kioc); -+ -+ return rval; -+ } -+ -+ /* -+ * Convert the kioc back to user space -+ */ -+ rval = kioc_to_mimd(kioc, argp); -+ -+ /* -+ * Return the kioc to free pool -+ */ -+ mraid_mm_dealloc_kioc(adp, kioc); -+ -+ return rval; -+} -+ -+ -+/** -+ * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet -+ * @umimd : User space mimd_t ioctl packet -+ * @adapter : pointer to the adapter (OUT) -+ */ -+static mraid_mmadp_t * -+mraid_mm_get_adapter(mimd_t __user *umimd, int *rval) -+{ -+ mraid_mmadp_t *adapter; -+ mimd_t mimd; -+ uint32_t adapno; -+ int iterator; -+ -+ -+ if (copy_from_user(&mimd, umimd, sizeof(mimd_t))) { -+ *rval = -EFAULT; -+ return NULL; -+ } -+ -+ adapno = GETADAP(mimd.ui.fcs.adapno); -+ -+ if (adapno >= adapters_count_g) { -+ *rval = -ENODEV; -+ return NULL; -+ } -+ -+ adapter = NULL; -+ iterator = 0; -+ -+ list_for_each_entry(adapter, &adapters_list_g, list) { -+ if (iterator++ == adapno) break; -+ } -+ -+ if (!adapter) { -+ *rval = -ENODEV; -+ return NULL; -+ } -+ -+ return adapter; -+} -+ -+/* -+ * handle_drvrcmd - This routine checks if the opcode is a driver -+ * cmd and if it is, handles it. -+ * @arg : packet sent by the user app -+ * @old_ioctl : mimd if 1; uioc otherwise -+ */ -+static int -+handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval) -+{ -+ mimd_t __user *umimd; -+ mimd_t kmimd; -+ uint8_t opcode; -+ uint8_t subopcode; -+ -+ if (old_ioctl) -+ goto old_packet; -+ else -+ goto new_packet; -+ -+new_packet: -+ return (-ENOTSUPP); -+ -+old_packet: -+ *rval = 0; -+ umimd = arg; -+ -+ if (copy_from_user(&kmimd, umimd, sizeof(mimd_t))) -+ return (-EFAULT); -+ -+ opcode = kmimd.ui.fcs.opcode; -+ subopcode = kmimd.ui.fcs.subopcode; -+ -+ /* -+ * If the opcode is 0x82 and the subopcode is either GET_DRVRVER or -+ * GET_NUMADP, then we can handle. Otherwise we should return 1 to -+ * indicate that we cannot handle this. -+ */ -+ if (opcode != 0x82) -+ return 1; -+ -+ switch (subopcode) { -+ -+ case MEGAIOC_QDRVRVER: -+ -+ if (copy_to_user(kmimd.data, &drvr_ver, sizeof(uint32_t))) -+ return (-EFAULT); -+ -+ return 0; -+ -+ case MEGAIOC_QNADAP: -+ -+ *rval = adapters_count_g; -+ -+ if (copy_to_user(kmimd.data, &adapters_count_g, -+ sizeof(uint32_t))) -+ return (-EFAULT); -+ -+ return 0; -+ -+ default: -+ /* cannot handle */ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+ -+/** -+ * mimd_to_kioc - Converter from old to new ioctl format -+ * -+ * @umimd : user space old MIMD IOCTL -+ * @kioc : kernel space new format IOCTL -+ * -+ * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The -+ * new packet is in kernel space so that driver can perform operations on it -+ * freely. -+ */ -+ -+static int -+mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc) -+{ -+ mbox64_t *mbox64; -+ mbox_t *mbox; -+ mraid_passthru_t *pthru32; -+ uint32_t adapno; -+ uint8_t opcode; -+ uint8_t subopcode; -+ mimd_t mimd; -+ -+ if (copy_from_user(&mimd, umimd, sizeof(mimd_t))) -+ return (-EFAULT); -+ -+ /* -+ * Applications are not allowed to send extd pthru -+ */ -+ if ((mimd.mbox[0] == MBOXCMD_PASSTHRU64) || -+ (mimd.mbox[0] == MBOXCMD_EXTPTHRU)) -+ return (-EINVAL); -+ -+ opcode = mimd.ui.fcs.opcode; -+ subopcode = mimd.ui.fcs.subopcode; -+ adapno = GETADAP(mimd.ui.fcs.adapno); -+ -+ if (adapno >= adapters_count_g) -+ return (-ENODEV); -+ -+ kioc->adapno = adapno; -+ kioc->mb_type = MBOX_LEGACY; -+ kioc->app_type = APPTYPE_MIMD; -+ -+ switch (opcode) { -+ -+ case 0x82: -+ -+ if (subopcode == MEGAIOC_QADAPINFO) { -+ -+ kioc->opcode = GET_ADAP_INFO; -+ kioc->data_dir = UIOC_RD; -+ kioc->xferlen = sizeof(mraid_hba_info_t); -+ -+ if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen)) -+ return (-ENOMEM); -+ } -+ else { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid cmm: Invalid subop\n")); -+ return (-EINVAL); -+ } -+ -+ break; -+ -+ case 0x81: -+ -+ kioc->opcode = MBOX_CMD; -+ kioc->xferlen = mimd.ui.fcs.length; -+ kioc->user_data_len = kioc->xferlen; -+ kioc->user_data = mimd.ui.fcs.buffer; -+ -+ if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen)) -+ return (-ENOMEM); -+ -+ if (mimd.outlen) kioc->data_dir = UIOC_RD; -+ if (mimd.inlen) kioc->data_dir |= UIOC_WR; -+ -+ break; -+ -+ case 0x80: -+ -+ kioc->opcode = MBOX_CMD; -+ kioc->xferlen = (mimd.outlen > mimd.inlen) ? -+ mimd.outlen : mimd.inlen; -+ kioc->user_data_len = kioc->xferlen; -+ kioc->user_data = mimd.data; -+ -+ if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen)) -+ return (-ENOMEM); -+ -+ if (mimd.outlen) kioc->data_dir = UIOC_RD; -+ if (mimd.inlen) kioc->data_dir |= UIOC_WR; -+ -+ break; -+ -+ default: -+ return (-EINVAL); -+ } -+ -+ /* -+ * If driver command, nothing else to do -+ */ -+ if (opcode == 0x82) -+ return 0; -+ -+ /* -+ * This is a mailbox cmd; copy the mailbox from mimd -+ */ -+ mbox64 = (mbox64_t *)((unsigned long)kioc->cmdbuf); -+ mbox = &mbox64->mbox32; -+ memcpy(mbox, mimd.mbox, 14); -+ -+ if (mbox->cmd != MBOXCMD_PASSTHRU) { // regular DCMD -+ -+ mbox->xferaddr = (uint32_t)kioc->buf_paddr; -+ -+ if (kioc->data_dir & UIOC_WR) { -+ if (copy_from_user(kioc->buf_vaddr, kioc->user_data, -+ kioc->xferlen)) { -+ return (-EFAULT); -+ } -+ } -+ -+ return 0; -+ } -+ -+ /* -+ * This is a regular 32-bit pthru cmd; mbox points to pthru struct. -+ * Just like in above case, the beginning for memblk is treated as -+ * a mailbox. The passthru will begin at next 1K boundary. And the -+ * data will start 1K after that. -+ */ -+ pthru32 = kioc->pthru32; -+ kioc->user_pthru = &umimd->pthru; -+ mbox->xferaddr = (uint32_t)kioc->pthru32_h; -+ -+ if (copy_from_user(pthru32, kioc->user_pthru, -+ sizeof(mraid_passthru_t))) { -+ return (-EFAULT); -+ } -+ -+ pthru32->dataxferaddr = kioc->buf_paddr; -+ if (kioc->data_dir & UIOC_WR) { -+ if (copy_from_user(kioc->buf_vaddr, kioc->user_data, -+ pthru32->dataxferlen)) { -+ return (-EFAULT); -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * mraid_mm_attch_buf - Attach a free dma buffer for required size -+ * -+ * @adp : Adapter softstate -+ * @kioc : kioc that the buffer needs to be attached to -+ * @xferlen : required length for buffer -+ * -+ * First we search for a pool with smallest buffer that is >= @xferlen. If -+ * that pool has no free buffer, we will try for the next bigger size. If none -+ * is available, we will try to allocate the smallest buffer that is >= -+ * @xferlen and attach it the pool. -+ */ -+static int -+mraid_mm_attach_buf(mraid_mmadp_t *adp, uioc_t *kioc, int xferlen) -+{ -+ mm_dmapool_t *pool; -+ int right_pool = -1; -+ unsigned long flags; -+ int i; -+ -+ kioc->pool_index = -1; -+ kioc->buf_vaddr = NULL; -+ kioc->buf_paddr = 0; -+ kioc->free_buf = 0; -+ -+ /* -+ * We need xferlen amount of memory. See if we can get it from our -+ * dma pools. If we don't get exact size, we will try bigger buffer -+ */ -+ -+ for (i = 0; i < MAX_DMA_POOLS; i++) { -+ -+ pool = &adp->dma_pool_list[i]; -+ -+ if (xferlen > pool->buf_size) -+ continue; -+ -+ if (right_pool == -1) -+ right_pool = i; -+ -+ spin_lock_irqsave(&pool->lock, flags); -+ -+ if (!pool->in_use) { -+ -+ pool->in_use = 1; -+ kioc->pool_index = i; -+ kioc->buf_vaddr = pool->vaddr; -+ kioc->buf_paddr = pool->paddr; -+ -+ spin_unlock_irqrestore(&pool->lock, flags); -+ return 0; -+ } -+ else { -+ spin_unlock_irqrestore(&pool->lock, flags); -+ continue; -+ } -+ } -+ -+ /* -+ * If xferlen doesn't match any of our pools, return error -+ */ -+ if (right_pool == -1) -+ return -EINVAL; -+ -+ /* -+ * We did not get any buffer from the preallocated pool. Let us try -+ * to allocate one new buffer. NOTE: This is a blocking call. -+ */ -+ pool = &adp->dma_pool_list[right_pool]; -+ -+ spin_lock_irqsave(&pool->lock, flags); -+ -+ kioc->pool_index = right_pool; -+ kioc->free_buf = 1; -+ kioc->buf_vaddr = pci_pool_alloc(pool->handle, GFP_KERNEL, -+ &kioc->buf_paddr); -+ spin_unlock_irqrestore(&pool->lock, flags); -+ -+ if (!kioc->buf_vaddr) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+/** -+ * mraid_mm_alloc_kioc - Returns a uioc_t from free list -+ * @adp : Adapter softstate for this module -+ * -+ * The kioc_semaphore is initialized with number of kioc nodes in the -+ * free kioc pool. If the kioc pool is empty, this function blocks till -+ * a kioc becomes free. -+ */ -+static uioc_t * -+mraid_mm_alloc_kioc(mraid_mmadp_t *adp) -+{ -+ uioc_t *kioc; -+ struct list_head* head; -+ unsigned long flags; -+ -+ down(&adp->kioc_semaphore); -+ -+ spin_lock_irqsave(&adp->kioc_pool_lock, flags); -+ -+ head = &adp->kioc_pool; -+ -+ if (list_empty(head)) { -+ up(&adp->kioc_semaphore); -+ spin_unlock_irqrestore(&adp->kioc_pool_lock, flags); -+ -+ con_log(CL_ANN, ("megaraid cmm: kioc list empty!\n")); -+ return NULL; -+ } -+ -+ kioc = list_entry(head->next, uioc_t, list); -+ list_del_init(&kioc->list); -+ -+ spin_unlock_irqrestore(&adp->kioc_pool_lock, flags); -+ -+ memset((caddr_t)(unsigned long)kioc->cmdbuf, 0, sizeof(mbox64_t)); -+ memset((caddr_t) kioc->pthru32, 0, sizeof(mraid_passthru_t)); -+ -+ kioc->buf_vaddr = NULL; -+ kioc->buf_paddr = 0; -+ kioc->pool_index =-1; -+ kioc->free_buf = 0; -+ kioc->user_data = NULL; -+ kioc->user_data_len = 0; -+ kioc->user_pthru = NULL; -+ kioc->timedout = 0; -+ -+ return kioc; -+} -+ -+/** -+ * mraid_mm_dealloc_kioc - Return kioc to free pool -+ * -+ * @adp : Adapter softstate -+ * @kioc : uioc_t node to be returned to free pool -+ */ -+static void -+mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc) -+{ -+ mm_dmapool_t *pool; -+ unsigned long flags; -+ -+ if (kioc->pool_index != -1) { -+ pool = &adp->dma_pool_list[kioc->pool_index]; -+ -+ /* This routine may be called in non-isr context also */ -+ spin_lock_irqsave(&pool->lock, flags); -+ -+ /* -+ * While attaching the dma buffer, if we didn't get the -+ * required buffer from the pool, we would have allocated -+ * it at the run time and set the free_buf flag. We must -+ * free that buffer. Otherwise, just mark that the buffer is -+ * not in use -+ */ -+ if (kioc->free_buf == 1) -+ pci_pool_free(pool->handle, kioc->buf_vaddr, -+ kioc->buf_paddr); -+ else -+ pool->in_use = 0; -+ -+ spin_unlock_irqrestore(&pool->lock, flags); -+ } -+ -+ /* Return the kioc to the free pool */ -+ spin_lock_irqsave(&adp->kioc_pool_lock, flags); -+ list_add(&kioc->list, &adp->kioc_pool); -+ spin_unlock_irqrestore(&adp->kioc_pool_lock, flags); -+ -+ /* increment the free kioc count */ -+ up(&adp->kioc_semaphore); -+ -+ return; -+} -+ -+/** -+ * lld_ioctl - Routine to issue ioctl to low level drvr -+ * -+ * @adp : The adapter handle -+ * @kioc : The ioctl packet with kernel addresses -+ */ -+static int -+lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) -+{ -+ int rval; -+ struct timer_list timer; -+ struct timer_list *tp = NULL; -+ -+ kioc->status = -ENODATA; -+ rval = adp->issue_uioc(adp->drvr_data, kioc, IOCTL_ISSUE); -+ -+ if (rval) return rval; -+ -+ /* -+ * Start the timer -+ */ -+ if (adp->timeout > 0) { -+ tp = &timer; -+ init_timer(tp); -+ -+ tp->function = lld_timedout; -+ tp->data = (unsigned long)kioc; -+ tp->expires = jiffies + adp->timeout * HZ; -+ -+ add_timer(tp); -+ } -+ -+ /* -+ * Wait till the low level driver completes the ioctl. After this -+ * call, the ioctl either completed successfully or timedout. -+ */ -+ wait_event(wait_q, (kioc->status != -ENODATA)); -+ if (tp) { -+ del_timer_sync(tp); -+ } -+ -+ /* -+ * If the command had timedout, we mark the controller offline -+ * before returning -+ */ -+ if (kioc->timedout) { -+ adp->quiescent = 0; -+ } -+ -+ return kioc->status; -+} -+ -+ -+/** -+ * ioctl_done - callback from the low level driver -+ * -+ * @kioc : completed ioctl packet -+ */ -+static void -+ioctl_done(uioc_t *kioc) -+{ -+ uint32_t adapno; -+ int iterator; -+ mraid_mmadp_t* adapter; -+ -+ /* -+ * When the kioc returns from driver, make sure it still doesn't -+ * have ENODATA in status. Otherwise, driver will hang on wait_event -+ * forever -+ */ -+ if (kioc->status == -ENODATA) { -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid cmm: lld didn't change status!\n")); -+ -+ kioc->status = -EINVAL; -+ } -+ -+ /* -+ * Check if this kioc was timedout before. If so, nobody is waiting -+ * on this kioc. We don't have to wake up anybody. Instead, we just -+ * have to free the kioc -+ */ -+ if (kioc->timedout) { -+ iterator = 0; -+ adapter = NULL; -+ adapno = kioc->adapno; -+ -+ con_log(CL_ANN, ( KERN_WARNING "megaraid cmm: completed " -+ "ioctl that was timedout before\n")); -+ -+ list_for_each_entry(adapter, &adapters_list_g, list) { -+ if (iterator++ == adapno) break; -+ } -+ -+ kioc->timedout = 0; -+ -+ if (adapter) { -+ mraid_mm_dealloc_kioc( adapter, kioc ); -+ } -+ } -+ else { -+ wake_up(&wait_q); -+ } -+} -+ -+ -+/* -+ * lld_timedout : callback from the expired timer -+ * -+ * @ptr : ioctl packet that timed out -+ */ -+static void -+lld_timedout(unsigned long ptr) -+{ -+ uioc_t *kioc = (uioc_t *)ptr; -+ -+ kioc->status = -ETIME; -+ kioc->timedout = 1; -+ -+ con_log(CL_ANN, (KERN_WARNING "megaraid cmm: ioctl timed out\n")); -+ -+ wake_up(&wait_q); -+} -+ -+ -+/** -+ * kioc_to_mimd : Converter from new back to old format -+ * -+ * @kioc : Kernel space IOCTL packet (successfully issued) -+ * @mimd : User space MIMD packet -+ */ -+static int -+kioc_to_mimd(uioc_t *kioc, mimd_t __user *mimd) -+{ -+ mimd_t kmimd; -+ uint8_t opcode; -+ uint8_t subopcode; -+ -+ mbox64_t *mbox64; -+ mraid_passthru_t __user *upthru32; -+ mraid_passthru_t *kpthru32; -+ mcontroller_t cinfo; -+ mraid_hba_info_t *hinfo; -+ -+ -+ if (copy_from_user(&kmimd, mimd, sizeof(mimd_t))) -+ return (-EFAULT); -+ -+ opcode = kmimd.ui.fcs.opcode; -+ subopcode = kmimd.ui.fcs.subopcode; -+ -+ if (opcode == 0x82) { -+ switch (subopcode) { -+ -+ case MEGAIOC_QADAPINFO: -+ -+ hinfo = (mraid_hba_info_t *)(unsigned long) -+ kioc->buf_vaddr; -+ -+ hinfo_to_cinfo(hinfo, &cinfo); -+ -+ if (copy_to_user(kmimd.data, &cinfo, sizeof(cinfo))) -+ return (-EFAULT); -+ -+ return 0; -+ -+ default: -+ return (-EINVAL); -+ } -+ -+ return 0; -+ } -+ -+ mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf; -+ -+ if (kioc->user_pthru) { -+ -+ upthru32 = kioc->user_pthru; -+ kpthru32 = kioc->pthru32; -+ -+ if (copy_to_user(&upthru32->scsistatus, -+ &kpthru32->scsistatus, -+ sizeof(uint8_t))) { -+ return (-EFAULT); -+ } -+ } -+ -+ if (kioc->user_data) { -+ if (copy_to_user(kioc->user_data, kioc->buf_vaddr, -+ kioc->user_data_len)) { -+ return (-EFAULT); -+ } -+ } -+ -+ if (copy_to_user(&mimd->mbox[17], -+ &mbox64->mbox32.status, sizeof(uint8_t))) { -+ return (-EFAULT); -+ } -+ -+ return 0; -+} -+ -+ -+/** -+ * hinfo_to_cinfo - Convert new format hba info into old format -+ * -+ * @hinfo : New format, more comprehensive adapter info -+ * @cinfo : Old format adapter info to support mimd_t apps -+ */ -+static void -+hinfo_to_cinfo(mraid_hba_info_t *hinfo, mcontroller_t *cinfo) -+{ -+ if (!hinfo || !cinfo) -+ return; -+ -+ cinfo->base = hinfo->baseport; -+ cinfo->irq = hinfo->irq; -+ cinfo->numldrv = hinfo->num_ldrv; -+ cinfo->pcibus = hinfo->pci_bus; -+ cinfo->pcidev = hinfo->pci_slot; -+ cinfo->pcifun = PCI_FUNC(hinfo->pci_dev_fn); -+ cinfo->pciid = hinfo->pci_device_id; -+ cinfo->pcivendor = hinfo->pci_vendor_id; -+ cinfo->pcislot = hinfo->pci_slot; -+ cinfo->uid = hinfo->unique_id; -+} -+ -+ -+/* -+ * mraid_mm_register_adp - Registration routine for low level drvrs -+ * -+ * @adp : Adapter objejct -+ */ -+int -+mraid_mm_register_adp(mraid_mmadp_t *lld_adp) -+{ -+ mraid_mmadp_t *adapter; -+ mbox64_t *mbox_list; -+ uioc_t *kioc; -+ uint32_t rval; -+ int i; -+ -+ -+ if (lld_adp->drvr_type != DRVRTYPE_MBOX) -+ return (-EINVAL); -+ -+ adapter = kmalloc(sizeof(mraid_mmadp_t), GFP_KERNEL); -+ -+ if (!adapter) { -+ rval = -ENOMEM; -+ goto memalloc_error; -+ } -+ -+ memset(adapter, 0, sizeof(mraid_mmadp_t)); -+ -+ adapter->unique_id = lld_adp->unique_id; -+ adapter->drvr_type = lld_adp->drvr_type; -+ adapter->drvr_data = lld_adp->drvr_data; -+ adapter->pdev = lld_adp->pdev; -+ adapter->issue_uioc = lld_adp->issue_uioc; -+ adapter->timeout = lld_adp->timeout; -+ adapter->max_kioc = lld_adp->max_kioc; -+ adapter->quiescent = 1; -+ -+ /* -+ * Allocate single blocks of memory for all required kiocs, -+ * mailboxes and passthru structures. -+ */ -+ adapter->kioc_list = kmalloc(sizeof(uioc_t) * lld_adp->max_kioc, -+ GFP_KERNEL); -+ adapter->mbox_list = kmalloc(sizeof(mbox64_t) * lld_adp->max_kioc, -+ GFP_KERNEL); -+ adapter->pthru_dma_pool = pci_pool_create("megaraid mm pthru pool", -+ adapter->pdev, -+ sizeof(mraid_passthru_t), -+ 16, 0); -+ -+ if (!adapter->kioc_list || !adapter->mbox_list || -+ !adapter->pthru_dma_pool) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid cmm: out of memory, %s %d\n", __FUNCTION__, -+ __LINE__)); -+ -+ rval = (-ENOMEM); -+ -+ goto memalloc_error; -+ } -+ -+ /* -+ * Slice kioc_list and make a kioc_pool with the individiual kiocs -+ */ -+ INIT_LIST_HEAD(&adapter->kioc_pool); -+ spin_lock_init(&adapter->kioc_pool_lock); -+ sema_init(&adapter->kioc_semaphore, lld_adp->max_kioc); -+ -+ mbox_list = (mbox64_t *)adapter->mbox_list; -+ -+ for (i = 0; i < lld_adp->max_kioc; i++) { -+ -+ kioc = adapter->kioc_list + i; -+ kioc->cmdbuf = (uint64_t)(unsigned long)(mbox_list + i); -+ kioc->pthru32 = pci_pool_alloc(adapter->pthru_dma_pool, -+ GFP_KERNEL, &kioc->pthru32_h); -+ -+ if (!kioc->pthru32) { -+ -+ con_log(CL_ANN, (KERN_WARNING -+ "megaraid cmm: out of memory, %s %d\n", -+ __FUNCTION__, __LINE__)); -+ -+ rval = (-ENOMEM); -+ -+ goto pthru_dma_pool_error; -+ } -+ -+ list_add_tail(&kioc->list, &adapter->kioc_pool); -+ } -+ -+ // Setup the dma pools for data buffers -+ if ((rval = mraid_mm_setup_dma_pools(adapter)) != 0) { -+ goto dma_pool_error; -+ } -+ -+ list_add_tail(&adapter->list, &adapters_list_g); -+ -+ adapters_count_g++; -+ -+ return 0; -+ -+dma_pool_error: -+ /* Do nothing */ -+ -+pthru_dma_pool_error: -+ -+ for (i = 0; i < lld_adp->max_kioc; i++) { -+ kioc = adapter->kioc_list + i; -+ if (kioc->pthru32) { -+ pci_pool_free(adapter->pthru_dma_pool, kioc->pthru32, -+ kioc->pthru32_h); -+ } -+ } -+ -+memalloc_error: -+ -+ if (adapter->kioc_list) -+ kfree(adapter->kioc_list); -+ -+ if (adapter->mbox_list) -+ kfree(adapter->mbox_list); -+ -+ if (adapter->pthru_dma_pool) -+ pci_pool_destroy(adapter->pthru_dma_pool); -+ -+ if (adapter) -+ kfree(adapter); -+ -+ return rval; -+} -+ -+ -+/** -+ * mraid_mm_adapter_app_handle - return the application handle for this adapter -+ * -+ * For the given driver data, locate the adadpter in our global list and -+ * return the corresponding handle, which is also used by applications to -+ * uniquely identify an adapter. -+ * -+ * @param unique_id : adapter unique identifier -+ * -+ * @return adapter handle if found in the list -+ * @return 0 if adapter could not be located, should never happen though -+ */ -+uint32_t -+mraid_mm_adapter_app_handle(uint32_t unique_id) -+{ -+ mraid_mmadp_t *adapter; -+ mraid_mmadp_t *tmp; -+ int index = 0; -+ -+ list_for_each_entry_safe(adapter, tmp, &adapters_list_g, list) { -+ -+ if (adapter->unique_id == unique_id) { -+ -+ return MKADAP(index); -+ } -+ -+ index++; -+ } -+ -+ return 0; -+} -+ -+ -+/** -+ * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter -+ * -+ * @adp : Adapter softstate -+ * -+ * We maintain a pool of dma buffers per each adapter. Each pool has one -+ * buffer. E.g, we may have 5 dma pools - one each for 4k, 8k ... 64k buffers. -+ * We have just one 4k buffer in 4k pool, one 8k buffer in 8k pool etc. We -+ * dont' want to waste too much memory by allocating more buffers per each -+ * pool. -+ */ -+static int -+mraid_mm_setup_dma_pools(mraid_mmadp_t *adp) -+{ -+ mm_dmapool_t *pool; -+ int bufsize; -+ int i; -+ -+ /* -+ * Create MAX_DMA_POOLS number of pools -+ */ -+ bufsize = MRAID_MM_INIT_BUFF_SIZE; -+ -+ for (i = 0; i < MAX_DMA_POOLS; i++){ -+ -+ pool = &adp->dma_pool_list[i]; -+ -+ pool->buf_size = bufsize; -+ spin_lock_init(&pool->lock); -+ -+ pool->handle = pci_pool_create("megaraid mm data buffer", -+ adp->pdev, bufsize, 16, 0); -+ -+ if (!pool->handle) { -+ goto dma_pool_setup_error; -+ } -+ -+ pool->vaddr = pci_pool_alloc(pool->handle, GFP_KERNEL, -+ &pool->paddr); -+ -+ if (!pool->vaddr) -+ goto dma_pool_setup_error; -+ -+ bufsize = bufsize * 2; -+ } -+ -+ return 0; -+ -+dma_pool_setup_error: -+ -+ mraid_mm_teardown_dma_pools(adp); -+ return (-ENOMEM); -+} -+ -+ -+/* -+ * mraid_mm_unregister_adp - Unregister routine for low level drivers -+ * Assume no outstanding ioctls to llds. -+ * -+ * @unique_id : UID of the adpater -+ */ -+int -+mraid_mm_unregister_adp(uint32_t unique_id) -+{ -+ mraid_mmadp_t *adapter; -+ mraid_mmadp_t *tmp; -+ -+ list_for_each_entry_safe(adapter, tmp, &adapters_list_g, list) { -+ -+ -+ if (adapter->unique_id == unique_id) { -+ -+ adapters_count_g--; -+ -+ list_del_init(&adapter->list); -+ -+ mraid_mm_free_adp_resources(adapter); -+ -+ kfree(adapter); -+ -+ con_log(CL_ANN, ( -+ "megaraid cmm: Unregistered one adapter:%#x\n", -+ unique_id)); -+ -+ return 0; -+ } -+ } -+ -+ return (-ENODEV); -+} -+ -+/** -+ * mraid_mm_free_adp_resources - Free adapter softstate -+ * -+ * @adp : Adapter softstate -+ */ -+static void -+mraid_mm_free_adp_resources(mraid_mmadp_t *adp) -+{ -+ uioc_t *kioc; -+ int i; -+ -+ mraid_mm_teardown_dma_pools(adp); -+ -+ for (i = 0; i < adp->max_kioc; i++) { -+ -+ kioc = adp->kioc_list + i; -+ -+ pci_pool_free(adp->pthru_dma_pool, kioc->pthru32, -+ kioc->pthru32_h); -+ } -+ -+ kfree(adp->kioc_list); -+ -+ kfree(adp->mbox_list); -+ -+ pci_pool_destroy(adp->pthru_dma_pool); -+ -+ -+ return; -+} -+ -+ -+/** -+ * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers -+ * -+ * @adp : Adapter softstate -+ */ -+static void -+mraid_mm_teardown_dma_pools(mraid_mmadp_t *adp) -+{ -+ int i; -+ mm_dmapool_t *pool; -+ -+ for (i = 0; i < MAX_DMA_POOLS; i++) { -+ -+ pool = &adp->dma_pool_list[i]; -+ -+ if (pool->handle) { -+ -+ if (pool->vaddr) -+ pci_pool_free(pool->handle, pool->vaddr, -+ pool->paddr); -+ -+ pci_pool_destroy(pool->handle); -+ pool->handle = NULL; -+ } -+ } -+ -+ return; -+} -+ -+/** -+ * mraid_mm_init : Module entry point -+ */ -+static int __init -+mraid_mm_init(void) -+{ -+ // Announce the driver version -+ con_log(CL_ANN, (KERN_INFO "megaraid cmm: %s %s\n", -+ LSI_COMMON_MOD_VERSION, LSI_COMMON_MOD_EXT_VERSION)); -+ -+ majorno = register_chrdev(0, "megadev", &lsi_fops); -+ -+ if (majorno < 0) { -+ con_log(CL_ANN, ("megaraid cmm: cannot get major\n")); -+ return majorno; -+ } -+ -+ init_waitqueue_head(&wait_q); -+ -+ INIT_LIST_HEAD(&adapters_list_g); -+ -+ register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl); -+ -+ return 0; -+} -+ -+ -+/** -+ * mraid_mm_compat_ioctl : 32bit to 64bit ioctl conversion routine -+ */ -+#ifdef CONFIG_COMPAT -+static int -+mraid_mm_compat_ioctl(unsigned int fd, unsigned int cmd, -+ unsigned long arg, struct file *filep) -+{ -+ int err; -+ struct inode *inode = filep->f_dentry->d_inode; -+ -+ err = mraid_mm_ioctl(inode, filep, cmd, arg); -+ -+ return err; -+} -+#endif -+ -+/** -+ * mraid_mm_exit : Module exit point -+ */ -+static void __exit -+mraid_mm_exit(void) -+{ -+ con_log(CL_DLEVEL1 , ("exiting common mod\n")); -+ -+ unregister_chrdev(majorno, "megadev"); -+ unregister_ioctl32_conversion(MEGAIOCCMD); -+} -+ -+module_init(mraid_mm_init); -+module_exit(mraid_mm_exit); -+ -+/* vi: set ts=8 sw=8 tw=78: */ ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid/megaraid_mm.h 1970-01-01 03:00:00.000000000 +0300 -+++ rhel4u2/drivers/scsi/megaraid/megaraid_mm.h 2005-10-20 14:48:31.071817792 +0400 -@@ -0,0 +1,104 @@ -+/* -+ * -+ * Linux MegaRAID device driver -+ * -+ * Copyright (c) 2003-2004 LSI Logic Corporation. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * FILE : megaraid_mm.h -+ */ -+ -+#ifndef MEGARAID_MM_H -+#define MEGARAID_MM_H -+ -+#include <linux/spinlock.h> -+#include <linux/fs.h> -+#include <asm/uaccess.h> -+#include <linux/version.h> -+#include <linux/module.h> -+#include <linux/delay.h> -+#include <linux/moduleparam.h> -+#include <linux/pci.h> -+#include <linux/list.h> -+#include <linux/ioctl32.h> -+#include <scsi/scsi_device.h> -+ -+#include "mbox_defs.h" -+#include "megaraid_ioctl.h" -+ -+ -+#define LSI_COMMON_MOD_VERSION "2.20.2.6" -+#define LSI_COMMON_MOD_EXT_VERSION \ -+ "(Release Date: Mon Mar 7 00:01:03 EST 2005)" -+ -+ -+#define LSI_DBGLVL dbglevel -+ -+// The smallest dma pool -+#define MRAID_MM_INIT_BUFF_SIZE 4096 -+ -+/** -+ * mimd_t : Old style ioctl packet structure (deprecated) -+ * -+ * @inlen : -+ * @outlen : -+ * @fca : -+ * @opcode : -+ * @subopcode : -+ * @adapno : -+ * @buffer : -+ * @pad : -+ * @length : -+ * @mbox : -+ * @pthru : -+ * @data : -+ * @pad : -+ * -+ * Note : This structure is DEPRECATED. New applications must use -+ * : uioc_t structure instead. All new hba drivers use the new -+ * : format. If we get this mimd packet, we will convert it into -+ * : new uioc_t format and send it to the hba drivers. -+ */ -+ -+typedef struct mimd { -+ -+ uint32_t inlen; -+ uint32_t outlen; -+ -+ union { -+ uint8_t fca[16]; -+ struct { -+ uint8_t opcode; -+ uint8_t subopcode; -+ uint16_t adapno; -+#if BITS_PER_LONG == 32 -+ uint8_t __user *buffer; -+ uint8_t pad[4]; -+#endif -+#if BITS_PER_LONG == 64 -+ uint8_t __user *buffer; -+#endif -+ uint32_t length; -+ } __attribute__ ((packed)) fcs; -+ } __attribute__ ((packed)) ui; -+ -+ uint8_t mbox[18]; /* 16 bytes + 2 status bytes */ -+ mraid_passthru_t pthru; -+ -+#if BITS_PER_LONG == 32 -+ char __user *data; /* buffer <= 4096 for 0x80 commands */ -+ char pad[4]; -+#endif -+#if BITS_PER_LONG == 64 -+ char __user *data; -+#endif -+ -+} __attribute__ ((packed))mimd_t; -+ -+#endif // MEGARAID_MM_H -+ -+// vi: set ts=8 sw=8 tw=78: ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/megaraid.c 2005-10-20 14:47:51.579821488 +0400 -+++ rhel4u2/drivers/scsi/megaraid.c 2004-10-19 01:53:05.000000000 +0400 -@@ -25,11 +25,8 @@ - * 518, 520, 531, 532 - * - * This driver is supported by LSI Logic, with assistance from Red Hat, Dell, -- * and others. Please send updates to the public mailing list -- * linux-megaraid-devel@dell.com, and subscribe to and read archives of this -- * list at http://lists.us.dell.com/. -- * -- * For history of changes, see ChangeLog.megaraid. -+ * and others. Please send updates to the mailing list -+ * linux-scsi@vger.kernel.org . - * - */ - -@@ -53,9 +50,12 @@ - - #include "megaraid.h" - -+#define MEGARAID_MODULE_VERSION "2.00.3" -+ - MODULE_AUTHOR ("LSI Logic Corporation"); - MODULE_DESCRIPTION ("LSI Logic MegaRAID driver"); - MODULE_LICENSE ("GPL"); -+MODULE_VERSION(MEGARAID_MODULE_VERSION); - - static unsigned int max_cmd_per_lun = DEF_CMD_PER_LUN; - MODULE_PARM(max_cmd_per_lun, "i"); ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/Makefile 2005-10-20 14:47:51.580821336 +0400 -+++ rhel4u2/drivers/scsi/Makefile 2005-10-19 11:47:17.000000000 +0400 -@@ -95,7 +95,8 @@ obj-$(CONFIG_SCSI_IBMMCA) += ibmmca.o - obj-$(CONFIG_SCSI_EATA) += eata.o - obj-$(CONFIG_SCSI_DC395x) += dc395x.o - obj-$(CONFIG_SCSI_DC390T) += tmscsim.o --obj-$(CONFIG_SCSI_MEGARAID) += megaraid.o -+obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o -+obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ - obj-$(CONFIG_SCSI_ACARD) += atp870u.o - obj-$(CONFIG_SCSI_SUNESP) += esp.o - obj-$(CONFIG_SCSI_GDTH) += gdth.o ---- linux-2.6.8.1-t043-libata-update/drivers/scsi/Kconfig 2005-10-20 14:47:51.582821032 +0400 -+++ rhel4u2/drivers/scsi/Kconfig 2005-10-19 11:47:17.000000000 +0400 -@@ -395,15 +409,7 @@ config SCSI_IN2000 - To compile this driver as a module, choose M here: the - module will be called in2000. - --config SCSI_MEGARAID -- tristate "AMI MegaRAID support" -- depends on PCI && SCSI -- help -- This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490 -- and 467 SCSI host adapters. -- -- To compile this driver as a module, choose M here: the -- module will be called megaraid. -+source "drivers/scsi/megaraid/Kconfig.megaraid" - - config SCSI_SATA - bool "Serial ATA (SATA) support" |