/*
* sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware
*
* Copyright 2004-2005 Red Hat, Inc.
*
* Author/maintainer: Jeff Garzik <jgarzik@pobox.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/blk-mq.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/compiler.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/hdreg.h>
#include <linux/dma-mapping.h>
#include <linux/completion.h>
#include <linux/scatterlist.h>
#include <asm/io.h>
#include <linux/uaccess.h>
#if 0
#define CARM_DEBUG
#define CARM_VERBOSE_DEBUG
#else
#undef CARM_DEBUG
#undef CARM_VERBOSE_DEBUG
#endif
#undef CARM_NDEBUG
#define DRV_NAME "sx8"
#define DRV_VERSION "1.0"
#define PFX DRV_NAME ": "
MODULE_AUTHOR("Jeff Garzik");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Promise SATA SX8 block driver");
MODULE_VERSION(DRV_VERSION);
/*
* SX8 hardware has a single message queue for all ATA ports.
* When this driver was written, the hardware (firmware?) would
* corrupt data eventually, if more than one request was outstanding.
* As one can imagine, having 8 ports bottlenecking on a single
* command hurts performance.
*
* Based on user reports, later versions of the hardware (firmware?)
* seem to be able to survive with more than one command queued.
*
* Therefore, we default to the safe option -- 1 command -- but
* allow the user to increase this.
*
* SX8 should be able to support up to ~60 queued commands (CARM_MAX_REQ),
* but problems seem to occur when you exceed ~30, even on newer hardware.
*/
static int max_queue = 1;
module_param(max_queue, int, 0444);
MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30, safe==1)");
#define NEXT_RESP(idx) ((idx + 1) % RMSG_Q_LEN)
/* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */
#define TAG_ENCODE(tag) (((tag) << 16) | 0xf)
#define TAG_DECODE(tag) (((tag) >> 16) & 0x1f)
#define TAG_VALID(tag) ((((tag) & 0xf) == 0xf) && (TAG_DECODE(tag) < 32))
/* note: prints function name for you */
#ifdef CARM_DEBUG
#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
#ifdef CARM_VERBOSE_DEBUG
#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
#else
#define VPRINTK(fmt, args...)
#endif /* CARM_VERBOSE_DEBUG */
#else
#define DPRINTK(fmt, args...)
#define VPRINTK(fmt, args...)
#endif /* CARM_DEBUG */
#ifdef CARM_NDEBUG
#define assert(expr)
#else
#define assert(expr) \
if(unlikely(!(expr))) { \
printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
#expr, __FILE__, __func__, __LINE__); \
}
#endif
/* defines only for the constants which don't work well as enums */
struct carm_host;
enum {
/* adapter-wide limits */
CARM_MAX_PORTS = 8,
CARM_SHM_SIZE = (4096 << 7),
CARM_MINORS_PER_MAJOR = 256 / CARM_MAX_PORTS,
CARM_MAX_WAIT_Q = CARM_MAX_PORTS + 1,
/* command message queue limits */
CARM_MAX_REQ = 64, /* max command msgs per host */
CARM_MSG_LOW_WATER = (CARM_MAX_REQ / 4), /* refill mark */
/* S/G limits, host-wide and per-request */
CARM_MAX_REQ_SG = 32, /* max s/g entries per request */
CARM_MAX_HOST_SG = 600, /* max s/g entries per host */
CARM_SG_LOW_WATER = (CARM_MAX_HOST_SG / 4), /* re-fill mark */
/* hardware registers */
CARM_IHQP = 0x1c,
CARM_INT_STAT = 0x10, /* interrupt status */
CARM_INT_MASK = 0x14, /* interrupt mask */
CARM_HMUC = 0x18, /* host message unit control */
RBUF_ADDR_LO = 0x20, /* response msg DMA buf low 32 bits */
RBUF_ADDR_HI = 0x24, /* response msg DMA buf high 32 bits */
RBUF_BYTE_SZ = 0x28,
CARM_RESP_IDX = 0x2c,
CARM_CMS0 = 0x30, /* command message size reg 0 */
CARM_LMUC = 0x48,
CARM_HMPHA = 0x6c,
CARM_INITC = 0xb5,
/* bits in CARM_INT_{STAT,MASK} */
INT_RESERVED = 0xfffffff0,
INT_WATCHDOG = (1 << 3), /* watchdog timer */
INT_Q_OVERFLOW = (1 << 2), /* cmd msg q overflow */
INT_Q_AVAILABLE = (1 << 1), /* cmd msg q has free space */
INT_RESPONSE = (1 << 0), /* response msg available */
INT_ACK_MASK = INT_WATCHDOG | INT_Q_OVERFLOW,
INT_DEF_MASK = INT_RESERVED | INT_Q_OVERFLOW |
INT_RESPONSE,
/* command messages, and related register bits */
CARM_HAVE_RESP = 0x01,
CARM_MSG_READ = 1,
CARM_MSG_WRITE = 2,
CARM_MSG_VERIFY = 3,
CARM_MSG_GET_CAPACITY = 4,
CARM_MSG_FLUSH = 5,
CARM_MSG_IOCTL = 6,
CARM_MSG_ARRAY = 8,
CARM_MSG_MISC = 9,
CARM_CME = (1 << 2),
CARM_RME = (1 << 1),
CARM_WZBC = (1 << 0),
CARM_RMI = (1 << 0),
CARM_Q_FULL = (1 << 3),
CARM_MSG_SIZE = 288,
CARM_Q_LEN = 48,
/* CARM_MSG_IOCTL messages */
CARM_IOC_SCAN_CHAN = 5, /* scan channels for devices */
CARM_IOC_GET_TCQ = 13, /* get tcq/ncq depth */
CARM_IOC_SET_TCQ = 14, /* set tcq/ncq depth */
IOC_SCAN_CHAN_NODEV = 0x1f,
IOC_SCAN_CHAN_OFFSET = 0x40,
/* CARM_MSG_ARRAY messages */
CARM_ARRAY_INFO = 0,
ARRAY_NO_EXIST = (1 << 31),
/* response messages */
RMSG_SZ = 8, /* sizeof(struct car
|