Commit 00f59701 authored by HighPoint Linux Team's avatar HighPoint Linux Team Committed by James Bottomley

[SCSI] hptiop: add more adapter models and other fixes

Most code changes were made to support adapters based on Marvell IOP, plus some
other fixes.

- add more PCI device IDs
- support for adapters based on Marvell IOP
- fix a result code translation error on big-endian systems
- fix resource releasing bug when scsi_host_alloc() fail in hptiop_probe()
- update scsi_cmnd.resid when finishing a request
- correct some coding style issues

[akpm@linux-foundation.org: type fixes]
Signed-off-by: default avatarHighPoint Linux Team <linux@highpoint-tech.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent a7ed0448
HIGHPOINT ROCKETRAID 3xxx RAID DRIVER (hptiop) HIGHPOINT ROCKETRAID 3xxx/4xxx ADAPTER DRIVER (hptiop)
Controller Register Map Controller Register Map
------------------------- -------------------------
The controller IOP is accessed via PCI BAR0. For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0:
BAR0 offset Register BAR0 offset Register
0x10 Inbound Message Register 0 0x10 Inbound Message Register 0
...@@ -18,6 +18,24 @@ The controller IOP is accessed via PCI BAR0. ...@@ -18,6 +18,24 @@ The controller IOP is accessed via PCI BAR0.
0x40 Inbound Queue Port 0x40 Inbound Queue Port
0x44 Outbound Queue Port 0x44 Outbound Queue Port
For Marvell IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
BAR0 offset Register
0x20400 Inbound Doorbell Register
0x20404 Inbound Interrupt Mask Register
0x20408 Outbound Doorbell Register
0x2040C Outbound Interrupt Mask Register
BAR1 offset Register
0x0 Inbound Queue Head Pointer
0x4 Inbound Queue Tail Pointer
0x8 Outbound Queue Head Pointer
0xC Outbound Queue Tail Pointer
0x10 Inbound Message Register
0x14 Outbound Message Register
0x40-0x1040 Inbound Queue
0x1040-0x2040 Outbound Queue
I/O Request Workflow I/O Request Workflow
---------------------- ----------------------
...@@ -73,15 +91,9 @@ The driver exposes following sysfs attributes: ...@@ -73,15 +91,9 @@ The driver exposes following sysfs attributes:
driver-version R driver version string driver-version R driver version string
firmware-version R firmware version string firmware-version R firmware version string
The driver registers char device "hptiop" to communicate with HighPoint RAID
management software. Its ioctl routine acts as a general binary interface
between the IOP firmware and HighPoint RAID management software. New management
functions can be implemented in application/firmware without modification
in driver code.
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved.
This file is distributed in the hope that it will be useful, This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
......
...@@ -573,10 +573,10 @@ config SCSI_ARCMSR_AER ...@@ -573,10 +573,10 @@ config SCSI_ARCMSR_AER
source "drivers/scsi/megaraid/Kconfig.megaraid" source "drivers/scsi/megaraid/Kconfig.megaraid"
config SCSI_HPTIOP config SCSI_HPTIOP
tristate "HighPoint RocketRAID 3xxx Controller support" tristate "HighPoint RocketRAID 3xxx/4xxx Controller support"
depends on SCSI && PCI depends on SCSI && PCI
help help
This option enables support for HighPoint RocketRAID 3xxx This option enables support for HighPoint RocketRAID 3xxx/4xxx
controllers. controllers.
To compile this driver as a module, choose M here; the module To compile this driver as a module, choose M here; the module
......
This diff is collapsed.
/* /*
* HighPoint RR3xxx controller driver for Linux * HighPoint RR3xxx/4xxx controller driver for Linux
* Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -18,8 +18,7 @@ ...@@ -18,8 +18,7 @@
#ifndef _HPTIOP_H_ #ifndef _HPTIOP_H_
#define _HPTIOP_H_ #define _HPTIOP_H_
struct hpt_iopmu struct hpt_iopmu_itl {
{
__le32 resrved0[4]; __le32 resrved0[4];
__le32 inbound_msgaddr0; __le32 inbound_msgaddr0;
__le32 inbound_msgaddr1; __le32 inbound_msgaddr1;
...@@ -54,6 +53,40 @@ struct hpt_iopmu ...@@ -54,6 +53,40 @@ struct hpt_iopmu
#define IOPMU_INBOUND_INT_ERROR 8 #define IOPMU_INBOUND_INT_ERROR 8
#define IOPMU_INBOUND_INT_POSTQUEUE 0x10 #define IOPMU_INBOUND_INT_POSTQUEUE 0x10
#define MVIOP_QUEUE_LEN 512
struct hpt_iopmu_mv {
__le32 inbound_head;
__le32 inbound_tail;
__le32 outbound_head;
__le32 outbound_tail;
__le32 inbound_msg;
__le32 outbound_msg;
__le32 reserve[10];
__le64 inbound_q[MVIOP_QUEUE_LEN];
__le64 outbound_q[MVIOP_QUEUE_LEN];
};
struct hpt_iopmv_regs {
__le32 reserved[0x20400 / 4];
__le32 inbound_doorbell;
__le32 inbound_intmask;
__le32 outbound_doorbell;
__le32 outbound_intmask;
};
#define MVIOP_MU_QUEUE_ADDR_HOST_MASK (~(0x1full))
#define MVIOP_MU_QUEUE_ADDR_HOST_BIT 4
#define MVIOP_MU_QUEUE_ADDR_IOP_HIGH32 0xffffffff
#define MVIOP_MU_QUEUE_REQUEST_RESULT_BIT 1
#define MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT 2
#define MVIOP_MU_INBOUND_INT_MSG 1
#define MVIOP_MU_INBOUND_INT_POSTQUEUE 2
#define MVIOP_MU_OUTBOUND_INT_MSG 1
#define MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2
enum hpt_iopmu_message { enum hpt_iopmu_message {
/* host-to-iop messages */ /* host-to-iop messages */
IOPMU_INBOUND_MSG0_NOP = 0, IOPMU_INBOUND_MSG0_NOP = 0,
...@@ -72,8 +105,7 @@ enum hpt_iopmu_message { ...@@ -72,8 +105,7 @@ enum hpt_iopmu_message {
IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff, IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff,
}; };
struct hpt_iop_request_header struct hpt_iop_request_header {
{
__le32 size; __le32 size;
__le32 type; __le32 type;
__le32 flags; __le32 flags;
...@@ -104,11 +136,10 @@ enum hpt_iop_result_type { ...@@ -104,11 +136,10 @@ enum hpt_iop_result_type {
IOP_RESULT_RESET, IOP_RESULT_RESET,
IOP_RESULT_INVALID_REQUEST, IOP_RESULT_INVALID_REQUEST,
IOP_RESULT_BAD_TARGET, IOP_RESULT_BAD_TARGET,
IOP_RESULT_MODE_SENSE_CHECK_CONDITION, IOP_RESULT_CHECK_CONDITION,
}; };
struct hpt_iop_request_get_config struct hpt_iop_request_get_config {
{
struct hpt_iop_request_header header; struct hpt_iop_request_header header;
__le32 interface_version; __le32 interface_version;
__le32 firmware_version; __le32 firmware_version;
...@@ -121,8 +152,7 @@ struct hpt_iop_request_get_config ...@@ -121,8 +152,7 @@ struct hpt_iop_request_get_config
__le32 sdram_size; __le32 sdram_size;
}; };
struct hpt_iop_request_set_config struct hpt_iop_request_set_config {
{
struct hpt_iop_request_header header; struct hpt_iop_request_header header;
__le32 iop_id; __le32 iop_id;
__le16 vbus_id; __le16 vbus_id;
...@@ -130,15 +160,13 @@ struct hpt_iop_request_set_config ...@@ -130,15 +160,13 @@ struct hpt_iop_request_set_config
__le32 reserve[6]; __le32 reserve[6];
}; };
struct hpt_iopsg struct hpt_iopsg {
{
__le32 size; __le32 size;
__le32 eot; /* non-zero: end of table */ __le32 eot; /* non-zero: end of table */
__le64 pci_address; __le64 pci_address;
}; };
struct hpt_iop_request_block_command struct hpt_iop_request_block_command {
{
struct hpt_iop_request_header header; struct hpt_iop_request_header header;
u8 channel; u8 channel;
u8 target; u8 target;
...@@ -156,8 +184,7 @@ struct hpt_iop_request_block_command ...@@ -156,8 +184,7 @@ struct hpt_iop_request_block_command
#define IOP_BLOCK_COMMAND_FLUSH 4 #define IOP_BLOCK_COMMAND_FLUSH 4
#define IOP_BLOCK_COMMAND_SHUTDOWN 5 #define IOP_BLOCK_COMMAND_SHUTDOWN 5
struct hpt_iop_request_scsi_command struct hpt_iop_request_scsi_command {
{
struct hpt_iop_request_header header; struct hpt_iop_request_header header;
u8 channel; u8 channel;
u8 target; u8 target;
...@@ -168,8 +195,7 @@ struct hpt_iop_request_scsi_command ...@@ -168,8 +195,7 @@ struct hpt_iop_request_scsi_command
struct hpt_iopsg sg_list[1]; struct hpt_iopsg sg_list[1];
}; };
struct hpt_iop_request_ioctl_command struct hpt_iop_request_ioctl_command {
{
struct hpt_iop_request_header header; struct hpt_iop_request_header header;
__le32 ioctl_code; __le32 ioctl_code;
__le32 inbuf_size; __le32 inbuf_size;
...@@ -182,10 +208,10 @@ struct hpt_iop_request_ioctl_command ...@@ -182,10 +208,10 @@ struct hpt_iop_request_ioctl_command
#define HPTIOP_MAX_REQUESTS 256u #define HPTIOP_MAX_REQUESTS 256u
struct hptiop_request { struct hptiop_request {
struct hptiop_request * next; struct hptiop_request *next;
void * req_virt; void *req_virt;
u32 req_shifted_phy; u32 req_shifted_phy;
struct scsi_cmnd * scp; struct scsi_cmnd *scp;
int index; int index;
}; };
...@@ -198,9 +224,21 @@ struct hpt_scsi_pointer { ...@@ -198,9 +224,21 @@ struct hpt_scsi_pointer {
#define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp) #define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp)
struct hptiop_hba { struct hptiop_hba {
struct hpt_iopmu __iomem * iop; struct hptiop_adapter_ops *ops;
struct Scsi_Host * host; union {
struct pci_dev * pcidev; struct {
struct hpt_iopmu_itl __iomem *iop;
} itl;
struct {
struct hpt_iopmv_regs *regs;
struct hpt_iopmu_mv __iomem *mu;
void *internal_req;
dma_addr_t internal_req_phy;
} mv;
} u;
struct Scsi_Host *host;
struct pci_dev *pcidev;
/* IOP config info */ /* IOP config info */
u32 interface_version; u32 interface_version;
...@@ -213,15 +251,15 @@ struct hptiop_hba { ...@@ -213,15 +251,15 @@ struct hptiop_hba {
u32 req_size; /* host-allocated request buffer size */ u32 req_size; /* host-allocated request buffer size */
int iopintf_v2: 1; u32 iopintf_v2: 1;
int initialized: 1; u32 initialized: 1;
int msg_done: 1; u32 msg_done: 1;
struct hptiop_request * req_list; struct hptiop_request * req_list;
struct hptiop_request reqs[HPTIOP_MAX_REQUESTS]; struct hptiop_request reqs[HPTIOP_MAX_REQUESTS];
/* used to free allocated dma area */ /* used to free allocated dma area */
void * dma_coherent; void *dma_coherent;
dma_addr_t dma_coherent_handle; dma_addr_t dma_coherent_handle;
atomic_t reset_count; atomic_t reset_count;
...@@ -231,19 +269,35 @@ struct hptiop_hba { ...@@ -231,19 +269,35 @@ struct hptiop_hba {
wait_queue_head_t ioctl_wq; wait_queue_head_t ioctl_wq;
}; };
struct hpt_ioctl_k struct hpt_ioctl_k {
{
struct hptiop_hba * hba; struct hptiop_hba * hba;
u32 ioctl_code; u32 ioctl_code;
u32 inbuf_size; u32 inbuf_size;
u32 outbuf_size; u32 outbuf_size;
void * inbuf; void *inbuf;
void * outbuf; void *outbuf;
u32 * bytes_returned; u32 *bytes_returned;
void (*done)(struct hpt_ioctl_k *); void (*done)(struct hpt_ioctl_k *);
int result; /* HPT_IOCTL_RESULT_ */ int result; /* HPT_IOCTL_RESULT_ */
}; };
struct hptiop_adapter_ops {
int (*iop_wait_ready)(struct hptiop_hba *hba, u32 millisec);
int (*internal_memalloc)(struct hptiop_hba *hba);
int (*internal_memfree)(struct hptiop_hba *hba);
int (*map_pci_bar)(struct hptiop_hba *hba);
void (*unmap_pci_bar)(struct hptiop_hba *hba);
void (*enable_intr)(struct hptiop_hba *hba);
void (*disable_intr)(struct hptiop_hba *hba);
int (*get_config)(struct hptiop_hba *hba,
struct hpt_iop_request_get_config *config);
int (*set_config)(struct hptiop_hba *hba,
struct hpt_iop_request_set_config *config);
int (*iop_intr)(struct hptiop_hba *hba);
void (*post_msg)(struct hptiop_hba *hba, u32 msg);
void (*post_req)(struct hptiop_hba *hba, struct hptiop_request *_req);
};
#define HPT_IOCTL_RESULT_OK 0 #define HPT_IOCTL_RESULT_OK 0
#define HPT_IOCTL_RESULT_FAILED (-1) #define HPT_IOCTL_RESULT_FAILED (-1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment