* [PATCH] Promise 'stex' driver
@ 2006-06-10 16:08 Jeff Garzik
2006-06-10 16:10 ` Christoph Hellwig
` (2 more replies)
0 siblings, 3 replies; 33+ messages in thread
From: Jeff Garzik @ 2006-06-10 16:08 UTC (permalink / raw)
To: linux-scsi; +Cc: linux-kernel, akpm, promise_linux
Please review, and queue in scsi-misc for 2.6.18 if acceptable.
The 'stex' branch of
git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/misc-2.6.git
contains the following updates:
drivers/scsi/Kconfig | 7
drivers/scsi/Makefile | 1
drivers/scsi/stex.c | 1219 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1227 insertions(+)
Jeff Garzik:
[SCSI] Add Promise SuperTrak 'shasta' driver.
Rename drivers/scsi/shasta.c to stex.c ("SuperTrak EX").
[SCSI] stex: update with community comments from 'Promise SuperTrak' thread
[SCSI] stex: Fix warning, trim trailing whitespace.
[SCSI] stex: remove last remnants of "shasta" project code name
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index a480a37..5ead499 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1043,6 +1043,13 @@ config 53C700_LE_ON_BE
depends on SCSI_LASI700
default y
+config SCSI_STEX
+ tristate "Promise SuperTrak EX8350/8300/16350/16300 support"
+ depends on PCI && SCSI
+ ---help---
+ This driver supports Promise SuperTrak EX8350/8300/16350/16300
+ Storage controllers.
+
config SCSI_SYM53C8XX_2
tristate "SYM53C8XX Version 2 SCSI support"
depends on PCI && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 81803a1..6a382e5 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -121,6 +121,7 @@ obj-$(CONFIG_SCSI_LASI700) += 53c700.o l
obj-$(CONFIG_SCSI_NSP32) += nsp32.o
obj-$(CONFIG_SCSI_IPR) += ipr.o
obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/
+obj-$(CONFIG_SCSI_STEX) += stex.o
obj-$(CONFIG_SCSI_SATA_AHCI) += libata.o ahci.o
obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o
obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
new file mode 100644
index 0000000..40bd9ec
--- /dev/null
+++ b/drivers/scsi/stex.c
@@ -0,0 +1,1219 @@
+/*
+ * SuperTrak EX8350/8300/16350/16300 Storage Controller driver for Linux
+ *
+ * Copyright (C) 2005, 2006 Promise Technology Inc.
+ *
+ * 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.
+ *
+ * Written By:
+ * Ed Lin <promise_linux@promise.com>
+ *
+ * Version: 2.9.0.13
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/pci.h>
+#include <linux/blkdev.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/byteorder.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+
+#define DRV_NAME "stex"
+#define ST_DRIVER_VERSION "2.9.0.13"
+#define ST_VER_MAJOR 2
+#define ST_VER_MINOR 9
+#define ST_OEM 0
+#define ST_BUILD_VER 13
+
+enum{
+ /* MU register offset */
+ IMR0 = 0x10, /* MU_INBOUND_MESSAGE_REG0 */
+ IMR1 = 0x14, /* MU_INBOUND_MESSAGE_REG1 */
+ OMR0 = 0x18, /* MU_OUTBOUND_MESSAGE_REG0 */
+ OMR1 = 0x1c, /* MU_OUTBOUND_MESSAGE_REG1 */
+ IDBL = 0x20, /* MU_INBOUND_DOORBELL */
+ IIS = 0x24, /* MU_INBOUND_INTERRUPT_STATUS */
+ IIM = 0x28, /* MU_INBOUND_INTERRUPT_MASK */
+ ODBL = 0x2c, /* MU_OUTBOUND_DOORBELL */
+ OIS = 0x30, /* MU_OUTBOUND_INTERRUPT_STATUS */
+ OIM = 0x3c, /* MU_OUTBOUND_INTERRUPT_MASK */
+
+ /* MU register value */
+ MU_INBOUND_DOORBELL_HANDSHAKE = 1,
+ MU_INBOUND_DOORBELL_REQHEADCHANGED = 2,
+ MU_INBOUND_DOORBELL_STATUSTAILCHANGED = 4,
+ MU_INBOUND_DOORBELL_HMUSTOPPED = 8,
+ MU_INBOUND_DOORBELL_RESET = 16,
+
+ MU_OUTBOUND_DOORBELL_HANDSHAKE = 1,
+ MU_OUTBOUND_DOORBELL_REQUESTTAILCHANGED = 2,
+ MU_OUTBOUND_DOORBELL_STATUSHEADCHANGED = 4,
+ MU_OUTBOUND_DOORBELL_BUSCHANGE = 8,
+ MU_OUTBOUND_DOORBELL_HASEVENT = 16,
+
+ /* MU status code */
+ MU_STATE_STARTING = 1,
+ MU_STATE_FMU_READY_FOR_HANDSHAKE = 2,
+ MU_STATE_SEND_HANDSHAKE_FRAME = 3,
+ MU_STATE_STARTED = 4,
+ MU_STATE_RESETTING = 5,
+
+ MU_MAX_DELAY_TIME = 50000,
+ MU_HANDSHAKE_SIGNATURE = 0x55aaaa55,
+ HMU_PARTNER_TYPE = 2,
+
+ /* firmware returned values */
+ SRB_STATUS_SUCCESS = 0x01,
+ SRB_STATUS_ERROR = 0x04,
+ SRB_STATUS_BUSY = 0x05,
+ SRB_STATUS_INVALID_REQUEST = 0x06,
+ SRB_STATUS_SELECTION_TIMEOUT = 0x0A,
+ SRB_SEE_SENSE = 0x80,
+
+ /* task attribute */
+ TASK_ATTRIBUTE_SIMPLE = 0x0,
+ TASK_ATTRIBUTE_HEADOFQUEUE = 0x1,
+ TASK_ATTRIBUTE_ORDERED = 0x2,
+ TASK_ATTRIBUTE_ACA = 0x4,
+
+ /* request count, etc. */
+ MU_MAX_REQUEST = 32,
+ TAG_BITMAP_LENGTH = MU_MAX_REQUEST,
+
+ /* one message wasted, use MU_MAX_REQUEST+1
+ to handle MU_MAX_REQUEST messages */
+ MU_REQ_COUNT = (MU_MAX_REQUEST + 1),
+ MU_STATUS_COUNT = (MU_MAX_REQUEST + 1),
+
+ STEX_CDB_LENGTH = MAX_COMMAND_SIZE,
+ REQ_VARIABLE_LEN = 1024,
+ STATUS_VAR_LEN = 128,
+ ST_CAN_QUEUE = MU_MAX_REQUEST,
+ ST_CMD_PER_LUN = MU_MAX_REQUEST,
+ ST_MAX_SG = 32,
+
+ /* sg flags */
+ SG_CF_EOT = 0x80, /* end of table */
+ SG_CF_64B = 0x40, /* 64 bit item */
+ SG_CF_HOST = 0x20, /* sg in host memory */
+
+ ST_MAX_ARRAY_SUPPORTED = 16,
+ ST_MAX_TARGET_NUM = (ST_MAX_ARRAY_SUPPORTED+1),
+ ST_MAX_LUN_PER_TARGET = 16,
+
+ PASSTHRU_REQ_TYPE = 0x00000001,
+ PASSTHRU_REQ_NO_WAKEUP = 0x00000100,
+ ST_INTERNAL_TIMEOUT = 30,
+
+ /* vendor specific commands of Promise */
+ ARRAY_CMD = 0xe0,
+ CONTROLLER_CMD = 0xe1,
+ DEBUGGING_CMD = 0xe2,
+ PASSTHRU_CMD = 0xe3,
+
+ PASSTHRU_GET_ADAPTER = 0x05,
+ PASSTHRU_GET_DRVVER = 0x10,
+ CTLR_POWER_STATE_CHANGE = 0x0e,
+ CTLR_POWER_SAVING = 0x01,
+
+ PASSTHRU_SIGNATURE = 0x4e415041,
+
+ INQUIRY_EVPD = 0x01,
+};
+
+struct st_sgitem {
+ u8 ctrl; /* SG_CF_xxx */
+ u8 reserved[3];
+ __le32 count;
+ __le32 addr;
+ __le32 addr_hi;
+};
+
+struct st_sgtable {
+ __le16 sg_count;
+ __le16 max_sg_count;
+ __le32 sz_in_byte;
+ struct st_sgitem table[ST_MAX_SG];
+};
+
+struct handshake_frame {
+ __le32 rb_phy; /* request payload queue physical address */
+ __le32 rb_phy_hi;
+ __le16 req_sz; /* size of each request payload */
+ __le16 req_cnt; /* count of reqs the buffer can hold */
+ __le16 status_sz; /* size of each status payload */
+ __le16 status_cnt; /* count of status the buffer can hold */
+ __le32 hosttime; /* seconds from Jan 1, 1970 (GMT) */
+ __le32 hosttime_hi;
+ u8 partner_type; /* who sends this frame */
+ u8 reserved0[7];
+ __le32 partner_ver_major;
+ __le32 partner_ver_minor;
+ __le32 partner_ver_oem;
+ __le32 partner_ver_build;
+ u32 reserved1[4];
+};
+
+struct req_msg {
+ __le16 tag;
+ u8 lun;
+ u8 target;
+ u8 task_attr;
+ u8 task_manage;
+ u8 prd_entry;
+ u8 payload_sz; /* payload size in 4-byte */
+ u8 cdb[STEX_CDB_LENGTH];
+ u8 variable[REQ_VARIABLE_LEN];
+};
+
+struct status_msg {
+ __le16 tag;
+ u8 lun;
+ u8 target;
+ u8 srb_status;
+ u8 scsi_status;
+ u8 reserved;
+ u8 payload_sz; /* payload size in 4-byte */
+ u8 variable[STATUS_VAR_LEN];
+};
+
+#define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg))
+#define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg))
+#define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE)
+
+struct ver_info {
+ u32 major;
+ u32 minor;
+ u32 oem;
+ u32 build;
+ u32 reserved[2];
+};
+
+struct st_frame {
+ u32 base[6];
+ u32 rom_addr;
+
+ struct ver_info drv_ver;
+ struct ver_info bios_ver;
+
+ u32 bus;
+ u32 slot;
+ u32 irq_level;
+ u32 irq_vec;
+ u32 id;
+ u32 subid;
+
+ u32 dimm_size;
+ u8 dimm_type;
+ u8 reserved[3];
+
+ u32 channel;
+ u32 reserved1;
+};
+
+struct st_drvver {
+ u32 major;
+ u32 minor;
+ u32 oem;
+ u32 build;
+ u32 signature[2];
+ u8 console_id;
+ u8 host_no;
+ u8 reserved0[2];
+ u32 reserved[3];
+};
+
+struct st_ccb {
+ struct req_msg *req;
+ struct scsi_cmnd *cmd;
+
+ void *sense_buffer;
+ struct page *page;
+ unsigned int sense_bufflen;
+ unsigned int page_offset;
+
+ u32 req_type;
+ u8 srb_status;
+ u8 scsi_status;
+};
+
+struct st_hba {
+ void __iomem *mmio_base; /* iomapped PCI memory space */
+ void *dma_mem;
+ dma_addr_t dma_handle;
+
+ struct Scsi_Host *host;
+ struct pci_dev *pdev;
+
+ u32 tag;
+ u32 req_head;
+ u32 req_tail;
+ u32 status_head;
+ u32 status_tail;
+
+ struct status_msg *status_buffer;
+ struct st_ccb ccb[MU_MAX_REQUEST];
+ struct st_ccb *wait_ccb;
+ wait_queue_head_t waitq;
+
+ unsigned int mu_status;
+ int out_req_cnt;
+};
+
+static const char console_inq_page[] =
+{
+ 0x03,0x00,0x03,0x03,0xFA,0x00,0x00,0x30,
+ 0x50,0x72,0x6F,0x6D,0x69,0x73,0x65,0x20, /* "Promise " */
+ 0x52,0x41,0x49,0x44,0x20,0x43,0x6F,0x6E, /* "RAID Con" */
+ 0x73,0x6F,0x6C,0x65,0x20,0x20,0x20,0x20, /* "sole " */
+ 0x31,0x2E,0x30,0x30,0x20,0x20,0x20,0x20, /* "1.00 " */
+ 0x53,0x58,0x2F,0x52,0x53,0x41,0x46,0x2D, /* "SX/RSAF-" */
+ 0x54,0x45,0x31,0x2E,0x30,0x30,0x20,0x20, /* "TE1.00 " */
+ 0x0C,0x20,0x20,0x20,0x20,0x20,0x20,0x20
+};
+
+MODULE_AUTHOR("Ed Lin");
+MODULE_DESCRIPTION("Promise Technology SuperTrak EX Controllers");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ST_DRIVER_VERSION);
+
+static inline void stex_gettime(u32 *time)
+{
+ struct timeval tv;
+ do_gettimeofday(&tv);
+
+ *time = cpu_to_le32(tv.tv_sec & 0xffffffff);
+ *(time + 1) = cpu_to_le32((tv.tv_sec >> 16) >> 16);
+}
+
+static inline u16 stex_alloc_tag(unsigned long *bitmap)
+{
+ int i;
+ i = find_first_zero_bit(bitmap, TAG_BITMAP_LENGTH);
+ if (i < TAG_BITMAP_LENGTH)
+ __set_bit(i, bitmap);
+ return (u16)i;
+}
+
+static inline void stex_free_tag(unsigned long *bitmap, u16 tag)
+{
+ __clear_bit((int)tag, bitmap);
+}
+
+static inline struct status_msg *stex_get_status(struct st_hba *hba)
+{
+ struct status_msg *status =
+ hba->status_buffer + hba->status_tail;
+
+ ++hba->status_tail;
+ hba->status_tail %= MU_STATUS_COUNT;
+
+ return status;
+}
+
+static inline struct req_msg *stex_alloc_req(struct st_hba *hba)
+{
+ struct req_msg *req = ((struct req_msg *)hba->dma_mem) +
+ hba->req_head;
+
+ ++hba->req_head;
+ hba->req_head %= MU_REQ_COUNT;
+
+ return req;
+}
+
+static inline void stex_map_sg(struct st_hba *hba,
+ struct req_msg *req, struct scsi_cmnd *cmd)
+{
+ struct pci_dev *pdev = hba->pdev;
+ dma_addr_t dma_handle;
+ struct scatterlist *src;
+ struct st_sgtable *dst;
+ int i;
+
+ dst = (struct st_sgtable *)req->variable;
+ dst->max_sg_count = cpu_to_le16(ST_MAX_SG);
+ dst->sz_in_byte = cpu_to_le32(cmd->request_bufflen);
+
+ if (cmd->use_sg) {
+ src = (struct scatterlist *) cmd->request_buffer;
+ dst->sg_count = cpu_to_le16((u16)pci_map_sg(pdev, src,
+ cmd->use_sg, cmd->sc_data_direction));
+
+ for (i = 0; i < dst->sg_count; i++, src++) {
+ dst->table[i].count = cpu_to_le32((u32)sg_dma_len(src));
+ dst->table[i].addr =
+ cpu_to_le32(sg_dma_address(src) & 0xffffffff);
+ dst->table[i].addr_hi =
+ cpu_to_le32((sg_dma_address(src) >> 16) >> 16);
+ dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST;
+ }
+ dst->table[--i].ctrl |= SG_CF_EOT;
+ return;
+ }
+
+ dma_handle = pci_map_single(pdev, cmd->request_buffer,
+ cmd->request_bufflen, cmd->sc_data_direction);
+ cmd->SCp.dma_handle = dma_handle;
+
+ dst->sg_count = cpu_to_le16(1);
+ dst->table[0].addr = cpu_to_le32(dma_handle & 0xffffffff);
+ dst->table[0].addr_hi = cpu_to_le32((dma_handle >> 16) >> 16);
+ dst->table[0].count = cpu_to_le32((u32)cmd->request_bufflen);
+ dst->table[0].ctrl = SG_CF_EOT | SG_CF_64B | SG_CF_HOST;
+}
+
+static int stex_direct_cp(struct scsi_cmnd *cmd,
+ const void *src, unsigned int len)
+{
+ void *dest;
+ unsigned int cp_len;
+ struct scatterlist *sg = cmd->request_buffer;
+
+ if (cmd->use_sg) {
+ dest = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ cp_len = min(sg->length, len);
+ } else {
+ dest = cmd->request_buffer;
+ cp_len = min(cmd->request_bufflen, len);
+ }
+
+ memcpy(dest, src, cp_len);
+
+ if (cmd->use_sg)
+ kunmap_atomic(dest - sg->offset, KM_IRQ0);
+ return cp_len == len;
+}
+
+static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
+{
+ struct st_frame *p;
+ struct scsi_cmnd *cmd = ccb->cmd;
+
+ if (cmd->use_sg)
+ p = kmap_atomic(ccb->page, KM_IRQ0) + ccb->page_offset;
+ else
+ p = cmd->request_buffer;
+
+ memset(p->base, 0, sizeof(u32)*6);
+ *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
+ p->rom_addr = 0;
+
+ p->drv_ver.major = ST_VER_MAJOR;
+ p->drv_ver.minor = ST_VER_MINOR;
+ p->drv_ver.oem = ST_OEM;
+ p->drv_ver.build = ST_BUILD_VER;
+
+ p->bus = hba->pdev->bus->number;
+ p->slot = hba->pdev->devfn;
+ p->irq_level = 0;
+ p->irq_vec = hba->pdev->irq;
+ p->id = hba->pdev->vendor << 16 | hba->pdev->device;
+ p->subid =
+ hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
+ if (cmd->use_sg)
+ kunmap_atomic((void *)p - ccb->page_offset, KM_IRQ0);
+}
+
+static void
+stex_send_cmd(struct st_hba *hba, struct req_msg *req, u16 tag)
+{
+ req->tag = cpu_to_le16(tag);
+ req->task_attr = TASK_ATTRIBUTE_SIMPLE;
+ req->task_manage = 0; /* not supported yet */
+ req->payload_sz = (u8)(sizeof(struct req_msg)/sizeof(u32));
+
+ hba->ccb[tag].req = req;
+ hba->out_req_cnt++;
+
+ writel(hba->req_head, hba->mmio_base + IMR0);
+ writel(MU_INBOUND_DOORBELL_REQHEADCHANGED, hba->mmio_base + IDBL);
+ readl(hba->mmio_base + IDBL); /* flush */
+}
+
+static int
+stex_queuecommand(struct scsi_cmnd *cmd, void (* fn)(struct scsi_cmnd *))
+{
+ struct st_hba *hba;
+ struct Scsi_Host *host;
+ unsigned int id,lun;
+ struct req_msg *req;
+ u16 tag;
+ host = cmd->device->host;
+ id = cmd->device->id;
+ lun = cmd->device->channel; /* firmware lun issue work around */
+ hba = (struct st_hba *) &host->hostdata[0];
+
+ switch (cmd->cmnd[0]) {
+ case READ_6:
+ case WRITE_6:
+ cmd->cmnd[9] = 0;
+ cmd->cmnd[8] = cmd->cmnd[4];
+ cmd->cmnd[7] = 0;
+ cmd->cmnd[6] = 0;
+ cmd->cmnd[5] = cmd->cmnd[3];
+ cmd->cmnd[4] = cmd->cmnd[2];
+ cmd->cmnd[3] = cmd->cmnd[1] & 0x1f;
+ cmd->cmnd[2] = 0;
+ cmd->cmnd[1] &= 0xe0;
+ cmd->cmnd[0] += READ_10 - READ_6;
+ break;
+ case MODE_SENSE:
+ {
+ static char mode_sense[4] = { 3, 0, 0, 0 };
+
+ stex_direct_cp(cmd, mode_sense, sizeof(mode_sense));
+ cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ fn(cmd);
+ return 0;
+ }
+ case MODE_SENSE_10:
+ {
+ static char mode_sense10[8] = { 0, 6, 0, 0, 0, 0, 0, 0 };
+
+ stex_direct_cp(cmd, mode_sense10, sizeof(mode_sense10));
+ cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ fn(cmd);
+ return 0;
+ }
+ case INQUIRY:
+ if (id != ST_MAX_ARRAY_SUPPORTED || lun != 0)
+ break;
+ if((cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
+ stex_direct_cp(cmd, console_inq_page,
+ sizeof(console_inq_page));
+ cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ } else
+ cmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
+ fn(cmd);
+ return 0;
+ case PASSTHRU_CMD:
+ if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
+ struct st_drvver ver;
+ ver.major = ST_VER_MAJOR;
+ ver.minor = ST_VER_MINOR;
+ ver.oem = ST_OEM;
+ ver.build = ST_BUILD_VER;
+ ver.signature[0] = PASSTHRU_SIGNATURE;
+ ver.console_id = ST_MAX_ARRAY_SUPPORTED;
+ ver.host_no = hba->host->host_no;
+ cmd->result = stex_direct_cp(cmd, &ver, sizeof(ver)) ?
+ DID_OK << 16 | COMMAND_COMPLETE << 8 :
+ DID_ERROR << 16 | COMMAND_COMPLETE << 8;
+ fn(cmd);
+ return 0;
+ }
+ default:
+ break;
+ }
+
+ cmd->scsi_done = fn;
+
+ if (unlikely((tag = stex_alloc_tag((unsigned long *)&hba->tag))
+ == TAG_BITMAP_LENGTH))
+ return SCSI_MLQUEUE_HOST_BUSY;
+
+ req = stex_alloc_req(hba);
+ req->lun = lun;
+ req->target = id;
+
+ /* cdb */
+ memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH);
+
+ if (cmd->sc_data_direction != DMA_NONE)
+ stex_map_sg(hba, req, cmd);
+
+ hba->ccb[tag].cmd = cmd;
+ hba->ccb[tag].sense_bufflen = SCSI_SENSE_BUFFERSIZE;
+ hba->ccb[tag].sense_buffer = cmd->sense_buffer;
+ if (cmd->use_sg) {
+ hba->ccb[tag].page_offset =
+ ((struct scatterlist *)cmd->request_buffer)->offset;
+ hba->ccb[tag].page =
+ ((struct scatterlist *)cmd->request_buffer)->page;
+ }
+ hba->ccb[tag].req_type = 0;
+
+ stex_send_cmd(hba, req, tag);
+ return 0;
+}
+
+static inline void stex_unmap_sg(struct st_hba *hba, struct scsi_cmnd *cmd)
+{
+ if (cmd->sc_data_direction != DMA_NONE) {
+ if (cmd->use_sg)
+ pci_unmap_sg(hba->pdev, cmd->request_buffer,
+ cmd->use_sg, cmd->sc_data_direction);
+ else
+ pci_unmap_single(hba->pdev, cmd->SCp.dma_handle,
+ cmd->request_bufflen, cmd->sc_data_direction);
+ }
+}
+
+static inline void stex_scsi_done(struct st_ccb *ccb)
+{
+ struct scsi_cmnd *cmd = ccb->cmd;
+ int result;
+
+ if (ccb->srb_status == SRB_STATUS_SUCCESS || ccb->srb_status == 0) {
+ result = ccb->scsi_status;
+ switch (ccb->scsi_status) {
+ case SAM_STAT_GOOD:
+ result |= DID_OK << 16 | COMMAND_COMPLETE << 8;
+ break;
+ case SAM_STAT_CHECK_CONDITION:
+ result |= DRIVER_SENSE << 24;
+ break;
+ case SAM_STAT_BUSY:
+ result |= DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
+ break;
+ default:
+ result |= DID_ERROR << 16 | COMMAND_COMPLETE << 8;
+ break;
+ }
+ }
+ else if (ccb->srb_status & SRB_SEE_SENSE)
+ result = DRIVER_SENSE << 24 | SAM_STAT_CHECK_CONDITION;
+ else switch (ccb->srb_status) {
+ case SRB_STATUS_SELECTION_TIMEOUT:
+ result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
+ break;
+ case SRB_STATUS_BUSY:
+ result = DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
+ break;
+ case SRB_STATUS_INVALID_REQUEST:
+ case SRB_STATUS_ERROR:
+ default:
+ result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
+ break;
+ }
+
+ cmd->result = result;
+ cmd->scsi_done(cmd);
+}
+
+static inline void stex_copy_data(struct st_ccb *ccb,
+ struct status_msg *resp, unsigned int variable)
+{
+ void *p;
+ if (resp->scsi_status == SAM_STAT_GOOD) {
+ if (ccb->cmd == NULL)
+ return;
+ if (ccb->cmd->use_sg)
+ p = kmap_atomic(ccb->page, KM_IRQ0) + ccb->page_offset;
+ else
+ p = ccb->cmd->request_buffer;
+ memcpy(p, resp->variable, min(variable,
+ ccb->cmd->request_bufflen));
+ if (ccb->cmd->use_sg)
+ kunmap_atomic(p - ccb->page_offset, KM_IRQ0);
+ } else {
+ if (ccb->sense_buffer != NULL)
+ memcpy(ccb->sense_buffer, resp->variable,
+ min(variable, ccb->sense_bufflen));
+ }
+}
+
+static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
+{
+ void __iomem *base = hba->mmio_base;
+ struct status_msg *resp;
+ struct st_ccb *ccb;
+ unsigned int size;
+ u16 tag;
+
+ if (!(doorbell & MU_OUTBOUND_DOORBELL_STATUSHEADCHANGED))
+ return;
+
+ /* status payloads */
+ hba->status_head = readl(base + OMR1);
+ if (unlikely(hba->status_head >= MU_STATUS_COUNT)) {
+ printk(KERN_WARNING DRV_NAME "(%s): invalid status head\n",
+ pci_name(hba->pdev));
+ return;
+ }
+
+ if (unlikely(hba->mu_status != MU_STATE_STARTED ||
+ hba->out_req_cnt <= 0)) {
+ hba->status_tail = hba->status_head;
+ goto update_status;
+ }
+
+ while (hba->status_tail != hba->status_head) {
+ resp = stex_get_status(hba);
+ tag = le16_to_cpu(resp->tag);
+ if (unlikely(tag >= TAG_BITMAP_LENGTH)) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): invalid tag\n", pci_name(hba->pdev));
+ continue;
+ }
+ if (unlikely((hba->tag & (1 << tag)) == 0)) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): null tag\n", pci_name(hba->pdev));
+ continue;
+ }
+
+ hba->out_req_cnt--;
+ ccb = &hba->ccb[tag];
+ if (hba->wait_ccb == ccb)
+ hba->wait_ccb = NULL;
+ if (unlikely(ccb->req == NULL)) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): lagging req\n", pci_name(hba->pdev));
+ stex_free_tag((unsigned long *)&hba->tag, tag);
+ stex_unmap_sg(hba, ccb->cmd); /* ??? */
+ continue;
+ }
+
+ size = resp->payload_sz * sizeof(u32); /* payload size */
+ if (unlikely(size < sizeof(*resp) - STATUS_VAR_LEN ||
+ size > sizeof(*resp))) {
+ printk(KERN_WARNING DRV_NAME "(%s): bad status size\n",
+ pci_name(hba->pdev));
+ } else {
+ size -= sizeof(*resp) - STATUS_VAR_LEN; /* copy size */
+ if (size)
+ stex_copy_data(ccb, resp, size);
+ }
+
+ ccb->srb_status = resp->srb_status;
+ ccb->scsi_status = resp->scsi_status;
+
+ if (ccb->req_type & PASSTHRU_REQ_TYPE) {
+ if (ccb->req_type & PASSTHRU_REQ_NO_WAKEUP) {
+ ccb->req_type = 0;
+ continue;
+ }
+ ccb->req_type = 0;
+ if (waitqueue_active(&hba->waitq))
+ wake_up(&hba->waitq);
+ continue;
+ }
+ if (ccb->cmd->cmnd[0] == PASSTHRU_CMD &&
+ ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER)
+ stex_controller_info(hba, ccb);
+ stex_free_tag((unsigned long *)&hba->tag, tag);
+ stex_unmap_sg(hba, ccb->cmd);
+ stex_scsi_done(ccb);
+ }
+
+update_status:
+ writel(hba->status_head, base + IMR1);
+ readl(base + IMR1); /* flush */
+}
+
+static irqreturn_t stex_intr(int irq, void *__hba, struct pt_regs *regs)
+{
+ struct st_hba *hba = __hba;
+ void __iomem *base = hba->mmio_base;
+ u32 data;
+ unsigned long flags;
+ int handled = 0;
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+
+ data = readl(base + ODBL);
+
+ if (data && data != 0xffffffff) {
+ /* clear the interrupt */
+ writel(data, base + ODBL);
+ readl(base + ODBL); /* flush */
+ stex_mu_intr(hba, data);
+ handled = 1;
+ }
+
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ return IRQ_RETVAL(handled);
+}
+
+static int stex_handshake(struct st_hba *hba)
+{
+ void __iomem *base = hba->mmio_base;
+ struct handshake_frame *h;
+ dma_addr_t status_phys;
+ int i;
+
+ if (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) {
+ writel(MU_INBOUND_DOORBELL_HANDSHAKE, base + IDBL);
+ readl(base + IDBL);
+ for (i = 0; readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE
+ && i < MU_MAX_DELAY_TIME; i++) {
+ rmb();
+ msleep(1);
+ }
+
+ if (i == MU_MAX_DELAY_TIME) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): no handshake signature\n",
+ pci_name(hba->pdev));
+ return -1;
+ }
+ }
+
+ udelay(10);
+
+ h = (struct handshake_frame *)(hba->dma_mem + MU_REQ_BUFFER_SIZE);
+ h->rb_phy = cpu_to_le32(hba->dma_handle);
+ h->rb_phy_hi = cpu_to_le32((hba->dma_handle >> 16) >> 16);
+ h->req_sz = cpu_to_le16(sizeof(struct req_msg));
+ h->req_cnt = cpu_to_le16(MU_REQ_COUNT);
+ h->status_sz = cpu_to_le16(sizeof(struct status_msg));
+ h->status_cnt = cpu_to_le16(MU_STATUS_COUNT);
+ stex_gettime(&h->hosttime);
+ h->partner_type = HMU_PARTNER_TYPE;
+
+ status_phys = hba->dma_handle + MU_REQ_BUFFER_SIZE;
+ writel(status_phys, base + IMR0);
+ readl(base + IMR0);
+ writel((status_phys >> 16) >> 16, base + IMR1);
+ readl(base + IMR1);
+
+ writel((status_phys >> 16) >> 16, base + OMR0); /* old fw compatible */
+ readl(base + OMR0);
+ writel(MU_INBOUND_DOORBELL_HANDSHAKE, base + IDBL);
+ readl(base + IDBL); /* flush */
+
+ udelay(10);
+ for (i = 0; readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE
+ && i < MU_MAX_DELAY_TIME; i++) {
+ rmb();
+ msleep(1);
+ }
+
+ if (i == MU_MAX_DELAY_TIME) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): no signature after handshake frame\n",
+ pci_name(hba->pdev));
+ return -1;
+ }
+
+ writel(0, base + IMR0);
+ readl(base + IMR0);
+ writel(0, base + OMR0);
+ readl(base + OMR0);
+ writel(0, base + IMR1);
+ readl(base + IMR1);
+ writel(0, base + OMR1);
+ readl(base + OMR1); /* flush */
+ hba->mu_status = MU_STATE_STARTED;
+ return 0;
+}
+
+static int stex_abort(struct scsi_cmnd *cmd)
+{
+ struct Scsi_Host *host = cmd->device->host;
+ struct st_hba *hba = (struct st_hba *)host->hostdata;
+ u16 tag;
+ void __iomem *base;
+ u32 data;
+ int result = SUCCESS;
+ unsigned long flags;
+ base = hba->mmio_base;
+ spin_lock_irqsave(host->host_lock, flags);
+
+ for (tag = 0; tag < MU_MAX_REQUEST; tag++)
+ if (hba->ccb[tag].cmd == cmd && (hba->tag & (1 << tag))) {
+ hba->wait_ccb = &(hba->ccb[tag]);
+ break;
+ }
+ if (tag >= MU_MAX_REQUEST)
+ goto out;
+
+ data = readl(base + ODBL);
+ if (data == 0 || data == 0xffffffff)
+ goto fail_out;
+
+ writel(data, base + ODBL);
+ readl(base + ODBL); /* flush */
+
+ stex_mu_intr(hba, data);
+
+ if (hba->wait_ccb == NULL) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): lost interrupt\n", pci_name(hba->pdev));
+ goto out;
+ }
+
+fail_out:
+ hba->wait_ccb->req = NULL; /* nullify the req's future return */
+ hba->wait_ccb = NULL;
+ result = FAILED;
+out:
+ spin_unlock_irqrestore(host->host_lock, flags);
+ return result;
+}
+
+static int stex_reset(struct scsi_cmnd *cmd)
+{
+ struct st_hba *hba;
+ int tag;
+ int i = 0;
+ unsigned long flags;
+ hba = (struct st_hba *) &cmd->device->host->hostdata[0];
+
+wait_cmds:
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ for (tag = 0; tag < MU_MAX_REQUEST; tag++)
+ if ((hba->tag & (1 << tag)) && hba->ccb[tag].req != NULL)
+ break;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ if (tag < MU_MAX_REQUEST) {
+ msleep(1000);
+ if (++i < 10)
+ goto wait_cmds;
+ }
+
+ hba->mu_status = MU_STATE_RESETTING;
+ writel(MU_INBOUND_DOORBELL_HANDSHAKE, hba->mmio_base + IDBL);
+ readl(hba->mmio_base + IDBL);
+ msleep(3000);
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+
+ for (tag = 0; tag < MU_MAX_REQUEST; tag++)
+ if ((hba->tag & (1 << tag)) && hba->ccb[tag].req != NULL) {
+ stex_free_tag((unsigned long *)&hba->tag, tag);
+ stex_unmap_sg(hba, hba->ccb[tag].cmd);
+ hba->ccb[tag].cmd->result = DID_RESET << 16;
+ hba->ccb[tag].cmd->scsi_done(hba->ccb[tag].cmd);
+ }
+
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ if (stex_handshake(hba)) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): resetting: handshake failed\n",
+ pci_name(hba->pdev));
+ return FAILED;
+ }
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->tag = 0;
+ hba->req_head = 0;
+ hba->req_tail = 0;
+ hba->status_head = 0;
+ hba->status_tail = 0;
+ hba->out_req_cnt = 0;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ return SUCCESS;
+}
+
+static void stex_init_hba(struct st_hba *hba,
+ struct Scsi_Host * host, struct pci_dev *pdev)
+{
+ host->max_channel = ST_MAX_LUN_PER_TARGET; /* fw lun work around */
+ host->max_id = ST_MAX_TARGET_NUM;
+ host->max_lun = 1; /* fw lun work around */
+ host->unique_id = host->host_no;
+ host->max_cmd_len = STEX_CDB_LENGTH;
+
+ hba->host = host;
+ hba->pdev = pdev;
+ init_waitqueue_head(&hba->waitq);
+}
+
+static int stex_init_shm(struct st_hba *hba, struct pci_dev *pdev)
+{
+ hba->dma_mem = pci_alloc_consistent(pdev,
+ MU_BUFFER_SIZE, &hba->dma_handle);
+ if (!hba->dma_mem)
+ return -ENOMEM;
+
+ hba->status_buffer =
+ (struct status_msg *)(hba->dma_mem + MU_REQ_BUFFER_SIZE);
+ hba->mu_status = MU_STATE_STARTING;
+ return 0;
+}
+
+static void stex_internal_flush(struct st_hba *hba, int id, u16 tag)
+{
+ struct req_msg *req;
+
+ req = stex_alloc_req(hba);
+ memset(req->cdb, 0, STEX_CDB_LENGTH);
+
+ if (id < ST_MAX_ARRAY_SUPPORTED*ST_MAX_LUN_PER_TARGET) {
+ req->target = id/ST_MAX_LUN_PER_TARGET;
+ req->lun = id%ST_MAX_LUN_PER_TARGET;
+ req->cdb[0] = CONTROLLER_CMD;
+ req->cdb[1] = CTLR_POWER_STATE_CHANGE;
+ req->cdb[2] = CTLR_POWER_SAVING;
+ } else {
+ req->target = id/ST_MAX_LUN_PER_TARGET - ST_MAX_ARRAY_SUPPORTED;
+ req->lun = id%ST_MAX_LUN_PER_TARGET;
+ req->cdb[0] = SYNCHRONIZE_CACHE;
+ }
+
+ hba->ccb[tag].cmd = NULL;
+ hba->ccb[tag].page_offset = 0;
+ hba->ccb[tag].page = NULL;
+ hba->ccb[tag].sense_bufflen = 0;
+ hba->ccb[tag].sense_buffer = NULL;
+ hba->ccb[tag].req_type |= PASSTHRU_REQ_TYPE;
+
+ stex_send_cmd(hba, req, tag);
+}
+
+static int stex_biosparam(struct scsi_device *sdev,
+ struct block_device *bdev, sector_t capacity, int geom[])
+{
+ int heads = 255, sectors = 63, cylinders;
+
+ if (capacity < 0x200000) {
+ heads = 64;
+ sectors = 32;
+ }
+
+ cylinders = sector_div(capacity, heads * sectors);
+
+ geom[0] = heads;
+ geom[1] = sectors;
+ geom[2] = cylinders;
+
+ return 0;
+}
+
+static struct scsi_host_template driver_template = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .proc_name = DRV_NAME,
+ .bios_param = stex_biosparam,
+ .queuecommand = stex_queuecommand,
+ .eh_abort_handler = stex_abort,
+ .eh_host_reset_handler = stex_reset,
+ .can_queue = ST_CAN_QUEUE,
+ .this_id = -1,
+ .sg_tablesize = ST_MAX_SG,
+ .cmd_per_lun = ST_CMD_PER_LUN,
+};
+
+static int stex_set_dma_mask(struct pci_dev * pdev)
+{
+ int ret;
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)
+ && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
+ return 0;
+ ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (!ret)
+ ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ return ret;
+}
+
+static int __devinit
+stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct st_hba *hba;
+ struct Scsi_Host *host;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ pci_set_master(pdev);
+
+ host = scsi_host_alloc(&driver_template, sizeof(struct st_hba));
+
+ if (!host) {
+ printk(KERN_ERR DRV_NAME "(%s): scsi_host_alloc failed\n",
+ pci_name(pdev));
+ err = -ENOMEM;
+ goto out_disable;
+ }
+
+ hba = (struct st_hba *)host->hostdata;
+ memset(hba, 0, sizeof(struct st_hba));
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err < 0) {
+ printk(KERN_ERR DRV_NAME "(%s): request regions failed\n",
+ pci_name(pdev));
+ goto out_scsi_host_put;
+ }
+
+ hba->mmio_base = ioremap(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if ( !hba->mmio_base) {
+ printk(KERN_ERR DRV_NAME "(%s): memory map failed\n",
+ pci_name(pdev));
+ err = -ENOMEM;
+ goto out_release_regions;
+ }
+
+ err = stex_set_dma_mask(pdev);
+ if (err) {
+ printk(KERN_ERR DRV_NAME "(%s): set dma mask failed\n",
+ pci_name(pdev));
+ goto out_iounmap;
+ }
+
+ err = stex_init_shm(hba, pdev);
+ if (err) {
+ printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n",
+ pci_name(pdev));
+ goto out_iounmap;
+ }
+
+ stex_init_hba(hba, host, pdev);
+
+ err = request_irq(pdev->irq, stex_intr, SA_SHIRQ, DRV_NAME, hba);
+ if (err) {
+ printk(KERN_ERR DRV_NAME "(%s): request irq failed\n",
+ pci_name(pdev));
+ goto out_pci_free;
+ }
+
+ err = stex_handshake(hba);
+ if (err)
+ goto out_free_irq;
+
+ pci_set_drvdata(pdev, hba);
+
+ err = scsi_add_host(host, &pdev->dev);
+ if (err) {
+ printk(KERN_ERR DRV_NAME "(%s): scsi_add_host failed\n",
+ pci_name(pdev));
+ goto out_free_irq;
+ }
+
+ scsi_scan_host(host);
+
+ return 0;
+
+out_free_irq:
+ free_irq(pdev->irq, hba);
+out_pci_free:
+ pci_free_consistent(pdev, MU_BUFFER_SIZE,
+ hba->dma_mem, hba->dma_handle);
+out_iounmap:
+ iounmap(hba->mmio_base);
+out_release_regions:
+ pci_release_regions(pdev);
+out_scsi_host_put:
+ scsi_host_put(host);
+out_disable:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void stex_hba_stop(struct st_hba *hba)
+{
+ unsigned long flags;
+ int i;
+ u16 tag;
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ if ((tag = stex_alloc_tag((unsigned long *)&hba->tag))
+ == TAG_BITMAP_LENGTH) {
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ printk(KERN_ERR DRV_NAME "(%s): unable to alloc tag\n",
+ pci_name(hba->pdev));
+ return;
+ }
+ for (i=0; i<(ST_MAX_ARRAY_SUPPORTED*ST_MAX_LUN_PER_TARGET*2); i++) {
+ stex_internal_flush(hba, i, tag);
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ wait_event_timeout(hba->waitq,
+ !(hba->ccb[tag].req_type), ST_INTERNAL_TIMEOUT*HZ);
+ if (hba->ccb[tag].req_type & PASSTHRU_REQ_TYPE)
+ return;
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ }
+
+ stex_free_tag((unsigned long *)&hba->tag, tag);
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+}
+
+static void stex_hba_free(struct st_hba *hba)
+{
+ free_irq(hba->pdev->irq, hba);
+
+ iounmap(hba->mmio_base);
+
+ pci_release_regions(hba->pdev);
+
+ if (hba->dma_mem)
+ pci_free_consistent(hba->pdev, MU_BUFFER_SIZE,
+ hba->dma_mem, hba->dma_handle);
+}
+
+static void stex_remove(struct pci_dev *pdev)
+{
+ struct st_hba *hba = pci_get_drvdata(pdev);
+
+ scsi_remove_host(hba->host);
+
+ pci_set_drvdata(pdev, NULL);
+
+ stex_hba_stop(hba);
+
+ stex_hba_free(hba);
+
+ scsi_host_put(hba->host);
+
+ pci_disable_device(pdev);
+}
+
+static void stex_shutdown(struct pci_dev *pdev)
+{
+ struct st_hba *hba = pci_get_drvdata(pdev);
+
+ stex_hba_stop(hba);
+}
+
+static struct pci_device_id stex_pci_tbl[] = {
+ { PCI_VENDOR_ID_PROMISE, 0x8350, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_PROMISE, 0xf350, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_PROMISE, 0x4301, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_PROMISE, 0x4302, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_PROMISE, 0x8301, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_PROMISE, 0x8302, PCI_ANY_ID, PCI_ANY_ID, },
+ { } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, stex_pci_tbl);
+
+static struct pci_driver stex_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = stex_pci_tbl,
+ .probe = stex_probe,
+ .remove = __devexit_p(stex_remove),
+ .shutdown = stex_shutdown,
+};
+
+static int __init stex_init(void)
+{
+ printk(KERN_INFO DRV_NAME
+ ": Promise SuperTrak EX Driver version: %s\n",
+ ST_DRIVER_VERSION);
+
+ return pci_register_driver(&stex_pci_driver);
+}
+
+static void __exit stex_exit(void)
+{
+ pci_unregister_driver(&stex_pci_driver);
+}
+
+module_init(stex_init);
+module_exit(stex_exit);
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 16:08 [PATCH] Promise 'stex' driver Jeff Garzik
@ 2006-06-10 16:10 ` Christoph Hellwig
2006-06-10 16:29 ` James Bottomley
2006-06-10 16:30 ` Jeff Garzik
2006-06-10 17:06 ` Christoph Hellwig
2006-06-10 17:47 ` Alexey Dobriyan
2 siblings, 2 replies; 33+ messages in thread
From: Christoph Hellwig @ 2006-06-10 16:10 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linux-scsi, linux-kernel, akpm, promise_linux
On Sat, Jun 10, 2006 at 12:08:52PM -0400, Jeff Garzik wrote:
>
> Please review, and queue in scsi-misc for 2.6.18 if acceptable.
The driver is not for scsi hardware. Please implement it as block
driver.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 16:10 ` Christoph Hellwig
@ 2006-06-10 16:29 ` James Bottomley
2006-06-10 16:34 ` Christoph Hellwig
2006-06-10 16:30 ` Jeff Garzik
1 sibling, 1 reply; 33+ messages in thread
From: James Bottomley @ 2006-06-10 16:29 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jeff Garzik, linux-scsi, linux-kernel, akpm, promise_linux
On Sat, 2006-06-10 at 17:10 +0100, Christoph Hellwig wrote:
> The driver is not for scsi hardware. Please implement it as block
> driver.
Actually, I'm afraid it is ... look at the mailbox path ... it's one of
these increasingly prevalent raid HBAs that speaks SCSI at the firmware
level. Most commands are direct passthroughs, only INQUIRY and
MODE_SENSE are actually emulated in the driver.
James
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 16:10 ` Christoph Hellwig
2006-06-10 16:29 ` James Bottomley
@ 2006-06-10 16:30 ` Jeff Garzik
1 sibling, 0 replies; 33+ messages in thread
From: Jeff Garzik @ 2006-06-10 16:30 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-scsi, linux-kernel, akpm, promise_linux
Christoph Hellwig wrote:
> On Sat, Jun 10, 2006 at 12:08:52PM -0400, Jeff Garzik wrote:
>> Please review, and queue in scsi-misc for 2.6.18 if acceptable.
>
> The driver is not for scsi hardware. Please implement it as block
> driver.
That's a new requirement. The interface to the hardware is clearly SCSI.
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 16:29 ` James Bottomley
@ 2006-06-10 16:34 ` Christoph Hellwig
2006-06-10 16:50 ` Jeff Garzik
0 siblings, 1 reply; 33+ messages in thread
From: Christoph Hellwig @ 2006-06-10 16:34 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Jeff Garzik, linux-scsi, linux-kernel, akpm,
promise_linux
On Sat, Jun 10, 2006 at 11:29:12AM -0500, James Bottomley wrote:
> On Sat, 2006-06-10 at 17:10 +0100, Christoph Hellwig wrote:
> > The driver is not for scsi hardware. Please implement it as block
> > driver.
>
> Actually, I'm afraid it is ... look at the mailbox path ... it's one of
> these increasingly prevalent raid HBAs that speaks SCSI at the firmware
> level. Most commands are direct passthroughs, only INQUIRY and
> MODE_SENSE are actually emulated in the driver.
Oops, you're right. It emulates READ/WRITE6 at the top of the queuecommand
routine which made me thing it'll emulate more below.
So removing the READ/WRITE6 emulation and setting the flag so the midlayer
only uses READ/WRITE10+ is on top of the TODO list. Right after that is
using the scsi_kmap_atomic_sg/scsi_kunmap_atomic_sg for the remaining
emulated commands. More comments later.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 16:34 ` Christoph Hellwig
@ 2006-06-10 16:50 ` Jeff Garzik
2006-06-10 17:10 ` Christoph Hellwig
0 siblings, 1 reply; 33+ messages in thread
From: Jeff Garzik @ 2006-06-10 16:50 UTC (permalink / raw)
To: Christoph Hellwig
Cc: James Bottomley, linux-scsi, linux-kernel, akpm, promise_linux
Christoph Hellwig wrote:
> So removing the READ/WRITE6 emulation and setting the flag so the midlayer
> only uses READ/WRITE10+ is on top of the TODO list. Right after that is
Done and checked into 'stex' branch at URL given. I also removed 6-byte
MODE SENSE.
> using the scsi_kmap_atomic_sg/scsi_kunmap_atomic_sg for the remaining
> emulated commands. More comments later.
These functions don't appear to be in upstream yet.
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 16:08 [PATCH] Promise 'stex' driver Jeff Garzik
2006-06-10 16:10 ` Christoph Hellwig
@ 2006-06-10 17:06 ` Christoph Hellwig
2006-06-10 17:37 ` Jeff Garzik
2006-06-10 22:28 ` Jeff Garzik
2006-06-10 17:47 ` Alexey Dobriyan
2 siblings, 2 replies; 33+ messages in thread
From: Christoph Hellwig @ 2006-06-10 17:06 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linux-scsi, linux-kernel, akpm, promise_linux
> +#include <linux/config.h>
including config.h isn't needed anymore.
> +enum{
enum {
> +static inline u16 stex_alloc_tag(unsigned long *bitmap)
> +{
> + int i;
> + i = find_first_zero_bit(bitmap, TAG_BITMAP_LENGTH);
> + if (i < TAG_BITMAP_LENGTH)
> + __set_bit(i, bitmap);
> + return (u16)i;
> +}
Please use the block layer tag helpers from block/ll_rw_blk.c:
extern int blk_queue_start_tag(request_queue_t *, struct request *);
extern struct request *blk_queue_find_tag(request_queue_t *, int);
extern void blk_queue_end_tag(request_queue_t *, struct request *);
extern int blk_queue_init_tags(request_queue_t *, int, struct blk_queue_tag *);
extern void blk_queue_free_tags(request_queue_t *);
extern int blk_queue_resize_tags(request_queue_t *, int);
extern void blk_queue_invalidate_tags(request_queue_t *);
> +static inline struct req_msg *stex_alloc_req(struct st_hba *hba)
There's far too many inline functions here. In doubt I'd just remove all
the inline attributes and let the copiler handle it. Given the functions
in the driver are already in natural order even a current gcc will do
a pretty good job at that.
> +
> + if (cmd->use_sg) {
> + src = (struct scatterlist *) cmd->request_buffer;
> + dst->sg_count = cpu_to_le16((u16)pci_map_sg(pdev, src,
> + cmd->use_sg, cmd->sc_data_direction));
You need to handle an error return from pci_map_sg and bail out if it
returns zero segments.
> + dst->table[--i].ctrl |= SG_CF_EOT;
> + return;
> + }
> + dma_handle = pci_map_single(pdev, cmd->request_buffer,
> + cmd->request_bufflen, cmd->sc_data_direction);
> + cmd->SCp.dma_handle = dma_handle;
I've just posted a patch to kill the last non-sg codepath so this should't
be needed anymore.
> +static int stex_direct_cp(struct scsi_cmnd *cmd,
> + const void *src, unsigned int len)
> +{
> + void *dest;
> + unsigned int cp_len;
> + struct scatterlist *sg = cmd->request_buffer;
> +
> + if (cmd->use_sg) {
> + dest = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
> + cp_len = min(sg->length, len);
> + } else {
> + dest = cmd->request_buffer;
> + cp_len = min(cmd->request_bufflen, len);
> + }
> +
> + memcpy(dest, src, cp_len);
> +
> + if (cmd->use_sg)
> + kunmap_atomic(dest - sg->offset, KM_IRQ0);
> + return cp_len == len;
As mentioned before this should use scsi_kmap_atomic_sg/scsi_kunmap_atomic_sg.
> +static int
> +stex_queuecommand(struct scsi_cmnd *cmd, void (* fn)(struct scsi_cmnd *))
> +{
The callback argument to ->queuecommand is called one in almost every
driver. It would help to understand your driver more easily if it followed
that convention.
> + struct st_hba *hba;
> + struct Scsi_Host *host;
> + unsigned int id,lun;
> + struct req_msg *req;
> + u16 tag;
> + host = cmd->device->host;
> + id = cmd->device->id;
> + lun = cmd->device->channel; /* firmware lun issue work around */
Please explain the firmware issue in more detail, this looks rather odd.
> + hba = (struct st_hba *) &host->hostdata[0];
> +
> + switch (cmd->cmnd[0]) {
> + case READ_6:
> + case WRITE_6:
> + cmd->cmnd[9] = 0;
> + cmd->cmnd[8] = cmd->cmnd[4];
> + cmd->cmnd[7] = 0;
> + cmd->cmnd[6] = 0;
> + cmd->cmnd[5] = cmd->cmnd[3];
> + cmd->cmnd[4] = cmd->cmnd[2];
> + cmd->cmnd[3] = cmd->cmnd[1] & 0x1f;
> + cmd->cmnd[2] = 0;
> + cmd->cmnd[1] &= 0xe0;
> + cmd->cmnd[0] += READ_10 - READ_6;
> + break;
Please remove this emulation and set sdev->use_10_for_rw in ->slave_configure.
> + case MODE_SENSE:
> + {
> + static char mode_sense[4] = { 3, 0, 0, 0 };
> +
> + stex_direct_cp(cmd, mode_sense, sizeof(mode_sense));
> + cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
> + fn(cmd);
> + return 0;
> + }
I'd kill this aswell and set use_10_for_ms in slave_configure.
> + case MODE_SENSE_10:
> + {
> + static char mode_sense10[8] = { 0, 6, 0, 0, 0, 0, 0, 0 };
> +
> + stex_direct_cp(cmd, mode_sense10, sizeof(mode_sense10));
> + cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
> + fn(cmd);
> + return 0;
> + }
> + case INQUIRY:
> + if (id != ST_MAX_ARRAY_SUPPORTED || lun != 0)
> + break;
> + if((cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
> + stex_direct_cp(cmd, console_inq_page,
> + sizeof(console_inq_page));
> + cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
> + } else
> + cmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
> + fn(cmd);
> + return 0;
I'd suggest to kill INQUIRY completely
> + case PASSTHRU_CMD:
> + if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
> + struct st_drvver ver;
> + ver.major = ST_VER_MAJOR;
> + ver.minor = ST_VER_MINOR;
> + ver.oem = ST_OEM;
> + ver.build = ST_BUILD_VER;
> + ver.signature[0] = PASSTHRU_SIGNATURE;
> + ver.console_id = ST_MAX_ARRAY_SUPPORTED;
> + ver.host_no = hba->host->host_no;
> + cmd->result = stex_direct_cp(cmd, &ver, sizeof(ver)) ?
> + DID_OK << 16 | COMMAND_COMPLETE << 8 :
> + DID_ERROR << 16 | COMMAND_COMPLETE << 8;
> + fn(cmd);
> + return 0;
> + }
Please don't abuse passthru commands to expose driver data. Add a few
sysfs attributes instead respectively a MODULE_VERSION tag for the
version.
> + hba->ccb[tag].cmd = cmd;
> + hba->ccb[tag].sense_bufflen = SCSI_SENSE_BUFFERSIZE;
> + hba->ccb[tag].sense_buffer = cmd->sense_buffer;
> + if (cmd->use_sg) {
> + hba->ccb[tag].page_offset =
> + ((struct scatterlist *)cmd->request_buffer)->offset;
> + hba->ccb[tag].page =
> + ((struct scatterlist *)cmd->request_buffer)->page;
> + }
How does this work? The driver claims to accept sg lists up to 32 entries
but we only add the first here?
> +static void stex_init_hba(struct st_hba *hba,
> + struct Scsi_Host * host, struct pci_dev *pdev)
> +{
...
> +}
> +
> +static int stex_init_shm(struct st_hba *hba, struct pci_dev *pdev)
> +{
...
> +
Could you just merge these two functions into it's only caller so the
initialization path is easier to read without hopping forth and back?
> + scsi_scan_host(host);
Any chance you could add the targets directly using scsi_add_device
or scsi_scan_target instead of trying to emulate a SPI scanning sequence?
> +static void stex_hba_free(struct st_hba *hba)
> +{
> + free_irq(hba->pdev->irq, hba);
> +
> + iounmap(hba->mmio_base);
> +
> + pci_release_regions(hba->pdev);
> +
> + if (hba->dma_mem)
> + pci_free_consistent(hba->pdev, MU_BUFFER_SIZE,
> + hba->dma_mem, hba->dma_handle);
this check is not needed. stex_hba_free is never called with a NULL
hba->dma_mem. I'd also merge this function into it's only caller,
as that would increase readability.
Overall a very nice driver, thanks a lot!
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 16:50 ` Jeff Garzik
@ 2006-06-10 17:10 ` Christoph Hellwig
0 siblings, 0 replies; 33+ messages in thread
From: Christoph Hellwig @ 2006-06-10 17:10 UTC (permalink / raw)
To: Jeff Garzik
Cc: Christoph Hellwig, James Bottomley, linux-scsi, linux-kernel,
akpm, promise_linux
On Sat, Jun 10, 2006 at 12:50:18PM -0400, Jeff Garzik wrote:
> >using the scsi_kmap_atomic_sg/scsi_kunmap_atomic_sg for the remaining
> >emulated commands. More comments later.
>
> These functions don't appear to be in upstream yet.
It's in scsi-misc, against which new scsi drivers should be submitted.
It's fine if you delay that conversion and non-sg path removal until you
send it to James for scsi-misc.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 17:06 ` Christoph Hellwig
@ 2006-06-10 17:37 ` Jeff Garzik
2006-06-10 18:22 ` James Bottomley
2006-06-10 22:28 ` Jeff Garzik
1 sibling, 1 reply; 33+ messages in thread
From: Jeff Garzik @ 2006-06-10 17:37 UTC (permalink / raw)
To: Christoph Hellwig, linux-scsi, linux-kernel, akpm, promise_linux
Thanks, just did several of these and checked it into 'stex' branch.
commit 1b6f2a81e789ebef27107765656d425ab44a2f44
Author: Jeff Garzik <jeff@garzik.org>
Date: Sat Jun 10 13:36:54 2006 -0400
[SCSI] stex: minor cleanups
- fix endian bug found in s/g code (used a fixed-endian value
as a loop-terminating variable)
From a list of changes suggested by Christoph:
- don't include linux/config.h
- whitespace fix
- let compiler choose whether or not to inline
- eliminate unnecessary NULL test on hba->dma_mem
- handle pci_map_sg() error
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 16:08 [PATCH] Promise 'stex' driver Jeff Garzik
2006-06-10 16:10 ` Christoph Hellwig
2006-06-10 17:06 ` Christoph Hellwig
@ 2006-06-10 17:47 ` Alexey Dobriyan
2 siblings, 0 replies; 33+ messages in thread
From: Alexey Dobriyan @ 2006-06-10 17:47 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linux-scsi, linux-kernel, akpm, promise_linux
On Sat, Jun 10, 2006 at 12:08:52PM -0400, Jeff Garzik wrote:
> --- /dev/null
> +++ b/drivers/scsi/stex.c
> +static inline void stex_gettime(u32 *time)
__le32 *time
> +{
> + struct timeval tv;
> + do_gettimeofday(&tv);
> +
> + *time = cpu_to_le32(tv.tv_sec & 0xffffffff);
> + *(time + 1) = cpu_to_le32((tv.tv_sec >> 16) >> 16);
> +}
> +static void
> +stex_send_cmd(struct st_hba *hba, struct req_msg *req, u16 tag)
> +{
> + req->tag = cpu_to_le16(tag);
> + req->task_attr = TASK_ATTRIBUTE_SIMPLE;
> + req->task_manage = 0; /* not supported yet */
> + req->payload_sz = (u8)(sizeof(struct req_msg)/sizeof(u32));
sparse warns here. Is this OK?
drivers/scsi/stex.c:442:47: warning: cast truncates bits from constant value (106 becomes 6)
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 17:37 ` Jeff Garzik
@ 2006-06-10 18:22 ` James Bottomley
2006-06-10 18:43 ` Jeff Garzik
0 siblings, 1 reply; 33+ messages in thread
From: James Bottomley @ 2006-06-10 18:22 UTC (permalink / raw)
To: Jeff Garzik
Cc: Christoph Hellwig, linux-scsi, linux-kernel, akpm, promise_linux
On Sat, 2006-06-10 at 13:37 -0400, Jeff Garzik wrote:
> Thanks, just did several of these and checked it into 'stex' branch.
You forgot to attach the diff.
Thanks,
James
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 18:22 ` James Bottomley
@ 2006-06-10 18:43 ` Jeff Garzik
0 siblings, 0 replies; 33+ messages in thread
From: Jeff Garzik @ 2006-06-10 18:43 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, linux-scsi, linux-kernel, akpm, promise_linux
James Bottomley wrote:
> On Sat, 2006-06-10 at 13:37 -0400, Jeff Garzik wrote:
>> Thanks, just did several of these and checked it into 'stex' branch.
>
> You forgot to attach the diff.
No, I'm just waiting for further comments, rather than posting a diff
for each comment.
The diff is public if people want to grab it.
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-06-10 17:06 ` Christoph Hellwig
2006-06-10 17:37 ` Jeff Garzik
@ 2006-06-10 22:28 ` Jeff Garzik
1 sibling, 0 replies; 33+ messages in thread
From: Jeff Garzik @ 2006-06-10 22:28 UTC (permalink / raw)
To: Christoph Hellwig, Jeff Garzik, linux-scsi, linux-kernel, akpm,
promise_linux
Christoph Hellwig wrote:
> I've just posted a patch to kill the last non-sg codepath so this should't
> be needed anymore.
BTW, thanks for this. This will allow me to kill some libata-scsi code.
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
@ 2006-07-19 15:07 Ed Lin
2006-07-20 21:27 ` Jeff Garzik
0 siblings, 1 reply; 33+ messages in thread
From: Ed Lin @ 2006-07-19 15:07 UTC (permalink / raw)
To: linux-scsi@vger.kernel.org
Cc: James.Bottomley, jeff, hch, linux-kernel, akpm, promise_linux
Please review following patch based on the 'stex' branch of
git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/misc-2.6.git
Jeff Garzik already finished some changes, and these are the rest.
>From Christoph Hellwig's comments:
use scsi_kmap_atomic_sg/scsi_kunmap_atomic_sg
callback argument to ->queuecommand changed to 'done'
merge init functions into .probe
>From Alexey Dobriyan's comments:
__le32 *time
Promise code changes:
add hard reset function
extend reset wait time
add new device ids
white space/ minor fix(INQUIRY, max_channel)
Block layer tag:
It is not implemented because here tag is adapter wide,
not for single device.
Non-sg codepath:
It can be eliminated when Christoph Hellwig's patch
upstream.
Firmware lun issue:
Firmware uses an id/lun pair for a logical drive. But
lun could be always 0 in Linux(when you do not config
CONFIG_SCSI_MULTI_LUN).I use channel to map lun,
otherwise max_id will be 256.
INQUIRY, passthru command:
Needed by management software. The special handling of
INQUIRY is for management software to have a sg device
to issue commands.
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 1652e0c..9806f71 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1054,11 +1054,11 @@ config 53C700_LE_ON_BE
default y
config SCSI_STEX
- tristate "Promise SuperTrak EX8350/8300/16350/16300 support"
+ tristate "Promise SuperTrak EX Series support"
depends on PCI && SCSI
---help---
- This driver supports Promise SuperTrak EX8350/8300/16350/16300
- Storage controllers.
+ This driver supports Promise SuperTrak EX Series Storage
+ controllers.
config SCSI_SYM53C8XX_2
tristate "SYM53C8XX Version 2 SCSI support"
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 8c44d45..a72df00 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -1,5 +1,5 @@
/*
- * SuperTrak EX8350/8300/16350/16300 Storage Controller driver for Linux
+ * SuperTrak EX Series Storage Controller driver for Linux
*
* Copyright (C) 2005, 2006 Promise Technology Inc.
*
@@ -75,7 +75,7 @@ enum {
MU_STATE_STARTED = 4,
MU_STATE_RESETTING = 5,
- MU_MAX_DELAY_TIME = 50000,
+ MU_MAX_DELAY_TIME = 240000,
MU_HANDSHAKE_SIGNATURE = 0x55aaaa55,
HMU_PARTNER_TYPE = 2,
@@ -102,7 +102,7 @@ enum {
MU_REQ_COUNT = (MU_MAX_REQUEST + 1),
MU_STATUS_COUNT = (MU_MAX_REQUEST + 1),
- STEX_CDB_LENGTH = MAX_COMMAND_SIZE,
+ STEX_CDB_LENGTH = MAX_COMMAND_SIZE,
REQ_VARIABLE_LEN = 1024,
STATUS_VAR_LEN = 128,
ST_CAN_QUEUE = MU_MAX_REQUEST,
@@ -118,6 +118,9 @@ enum {
ST_MAX_TARGET_NUM = (ST_MAX_ARRAY_SUPPORTED+1),
ST_MAX_LUN_PER_TARGET = 16,
+ st_shasta = 0,
+ st_vsc = 1,
+
PASSTHRU_REQ_TYPE = 0x00000001,
PASSTHRU_REQ_NO_WAKEUP = 0x00000100,
ST_INTERNAL_TIMEOUT = 30,
@@ -194,10 +197,6 @@ struct status_msg {
u8 variable[STATUS_VAR_LEN];
};
-#define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg))
-#define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg))
-#define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE)
-
struct ver_info {
u32 major;
u32 minor;
@@ -240,14 +239,18 @@ struct st_drvver {
u32 reserved[3];
};
+#define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg))
+#define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg))
+#define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE)
+#define STEX_BUFFER_SIZE (MU_BUFFER_SIZE + sizeof(struct st_frame))
+
struct st_ccb {
struct req_msg *req;
struct scsi_cmnd *cmd;
void *sense_buffer;
- struct page *page;
unsigned int sense_bufflen;
- unsigned int page_offset;
+ int sg_count;
u32 req_type;
u8 srb_status;
@@ -261,6 +264,7 @@ struct st_hba {
struct Scsi_Host *host;
struct pci_dev *pdev;
+ struct pci_dev *bus0;
u32 tag;
u32 req_head;
@@ -269,12 +273,15 @@ struct st_hba {
u32 status_tail;
struct status_msg *status_buffer;
+ void *scratch;
struct st_ccb ccb[MU_MAX_REQUEST];
struct st_ccb *wait_ccb;
wait_queue_head_t waitq;
unsigned int mu_status;
int out_req_cnt;
+
+ unsigned int cardtype;
};
static const char console_inq_page[] =
@@ -294,7 +301,7 @@ MODULE_DESCRIPTION("Promise Technology S
MODULE_LICENSE("GPL");
MODULE_VERSION(ST_DRIVER_VERSION);
-static void stex_gettime(u32 *time)
+static void stex_gettime(__le32 *time)
{
struct timeval tv;
do_gettimeofday(&tv);
@@ -340,14 +347,16 @@ static struct req_msg *stex_alloc_req(st
}
static int stex_map_sg(struct st_hba *hba,
- struct req_msg *req, struct scsi_cmnd *cmd)
+ struct req_msg *req, struct st_ccb *ccb)
{
struct pci_dev *pdev = hba->pdev;
+ struct scsi_cmnd *cmd;
dma_addr_t dma_handle;
struct scatterlist *src;
struct st_sgtable *dst;
int i;
+ cmd = ccb->cmd;
dst = (struct st_sgtable *)req->variable;
dst->max_sg_count = cpu_to_le16(ST_MAX_SG);
dst->sz_in_byte = cpu_to_le32(cmd->request_bufflen);
@@ -361,6 +370,7 @@ static int stex_map_sg(struct st_hba *hb
if (n_elem <= 0)
return -EIO;
+ ccb->sg_count = n_elem;
dst->sg_count = cpu_to_le16((u16)n_elem);
for (i = 0; i < n_elem; i++, src++) {
@@ -370,7 +380,7 @@ static int stex_map_sg(struct st_hba *hb
dst->table[i].addr_hi =
cpu_to_le32((sg_dma_address(src) >> 16) >> 16);
dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST;
- }
+ }
dst->table[--i].ctrl |= SG_CF_EOT;
return 0;
}
@@ -379,6 +389,7 @@ static int stex_map_sg(struct st_hba *hb
cmd->request_bufflen, cmd->sc_data_direction);
cmd->SCp.dma_handle = dma_handle;
+ ccb->sg_count = 1;
dst->sg_count = cpu_to_le16(1);
dst->table[0].addr = cpu_to_le32(dma_handle & 0xffffffff);
dst->table[0].addr_hi = cpu_to_le32((dma_handle >> 16) >> 16);
@@ -388,38 +399,67 @@ static int stex_map_sg(struct st_hba *hb
return 0;
}
-static int stex_direct_cp(struct scsi_cmnd *cmd,
- const void *src, unsigned int len)
+static void stex_internal_copy(struct scsi_cmnd *cmd,
+ const void *src, size_t *count, int sg_count)
{
- void *dest;
- unsigned int cp_len;
- struct scatterlist *sg = cmd->request_buffer;
+ size_t lcount;
+ size_t len;
+ void *s, *d, *base = NULL;
+ if (*count > cmd->request_bufflen)
+ *count = cmd->request_bufflen;
+ lcount = *count;
+ while (lcount) {
+ len = lcount;
+ s = (void *)src;
+ if (cmd->use_sg) {
+ size_t offset = *count - lcount;
+ s += offset;
+ base = scsi_kmap_atomic_sg(cmd->request_buffer,
+ sg_count, &offset, &len);
+ if (base == NULL) {
+ *count -= lcount;
+ return;
+ }
+ d = base + offset;
+ } else
+ d = cmd->request_buffer;
+
+ memcpy(d, s, len);
+
+ lcount -= len;
+ if (cmd->use_sg)
+ scsi_kunmap_atomic_sg(base);
+ }
+}
+
+static int stex_direct_copy(struct scsi_cmnd *cmd,
+ const void *src, size_t count)
+{
+ struct st_hba *hba = (struct st_hba *) &cmd->device->host->hostdata[0];
+ size_t cp_len = count;
+ int n_elem = 0;
if (cmd->use_sg) {
- dest = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
- cp_len = min(sg->length, len);
- } else {
- dest = cmd->request_buffer;
- cp_len = min(cmd->request_bufflen, len);
+ n_elem = pci_map_sg(hba->pdev, cmd->request_buffer,
+ cmd->use_sg, cmd->sc_data_direction);
+ if (n_elem <= 0)
+ return 0;
}
- memcpy(dest, src, cp_len);
+ stex_internal_copy(cmd, src, &cp_len, n_elem);
if (cmd->use_sg)
- kunmap_atomic(dest - sg->offset, KM_IRQ0);
- return cp_len == len;
+ pci_unmap_sg(hba->pdev, cmd->request_buffer,
+ cmd->use_sg, cmd->sc_data_direction);
+ return cp_len == count;
}
static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
{
struct st_frame *p;
- struct scsi_cmnd *cmd = ccb->cmd;
-
- if (cmd->use_sg)
- p = kmap_atomic(ccb->page, KM_IRQ0) + ccb->page_offset;
- else
- p = cmd->request_buffer;
+ size_t count = sizeof(struct st_frame);
+ p = hba->scratch;
memset(p->base, 0, sizeof(u32)*6);
*(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
p->rom_addr = 0;
@@ -436,8 +476,8 @@ static void stex_controller_info(struct
p->id = hba->pdev->vendor << 16 | hba->pdev->device;
p->subid =
hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
- if (cmd->use_sg)
- kunmap_atomic((void *)p - ccb->page_offset, KM_IRQ0);
+
+ stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count);
}
static void
@@ -465,7 +505,7 @@ stex_slave_config(struct scsi_device *sd
}
static int
-stex_queuecommand(struct scsi_cmnd *cmd, void (* fn)(struct scsi_cmnd *))
+stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
{
struct st_hba *hba;
struct Scsi_Host *host;
@@ -482,21 +522,21 @@ stex_queuecommand(struct scsi_cmnd *cmd,
{
static char mode_sense10[8] = { 0, 6, 0, 0, 0, 0, 0, 0 };
- stex_direct_cp(cmd, mode_sense10, sizeof(mode_sense10));
+ stex_direct_copy(cmd, mode_sense10, sizeof(mode_sense10));
cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
- fn(cmd);
+ done(cmd);
return 0;
}
case INQUIRY:
- if (id != ST_MAX_ARRAY_SUPPORTED || lun != 0)
+ if (id != ST_MAX_ARRAY_SUPPORTED)
break;
- if((cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
- stex_direct_cp(cmd, console_inq_page,
+ if(lun == 0 && (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
+ stex_direct_copy(cmd, console_inq_page,
sizeof(console_inq_page));
cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
} else
cmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
- fn(cmd);
+ done(cmd);
return 0;
case PASSTHRU_CMD:
if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
@@ -508,17 +548,17 @@ stex_queuecommand(struct scsi_cmnd *cmd,
ver.signature[0] = PASSTHRU_SIGNATURE;
ver.console_id = ST_MAX_ARRAY_SUPPORTED;
ver.host_no = hba->host->host_no;
- cmd->result = stex_direct_cp(cmd, &ver, sizeof(ver)) ?
+ cmd->result = stex_direct_copy(cmd, &ver, sizeof(ver)) ?
DID_OK << 16 | COMMAND_COMPLETE << 8 :
DID_ERROR << 16 | COMMAND_COMPLETE << 8;
- fn(cmd);
+ done(cmd);
return 0;
}
default:
break;
}
- cmd->scsi_done = fn;
+ cmd->scsi_done = done;
if (unlikely((tag = stex_alloc_tag((unsigned long *)&hba->tag))
== TAG_BITMAP_LENGTH))
@@ -531,20 +571,14 @@ stex_queuecommand(struct scsi_cmnd *cmd,
/* cdb */
memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH);
- if (cmd->sc_data_direction != DMA_NONE)
- stex_map_sg(hba, req, cmd);
-
hba->ccb[tag].cmd = cmd;
hba->ccb[tag].sense_bufflen = SCSI_SENSE_BUFFERSIZE;
hba->ccb[tag].sense_buffer = cmd->sense_buffer;
- if (cmd->use_sg) {
- hba->ccb[tag].page_offset =
- ((struct scatterlist *)cmd->request_buffer)->offset;
- hba->ccb[tag].page =
- ((struct scatterlist *)cmd->request_buffer)->page;
- }
hba->ccb[tag].req_type = 0;
+ if (cmd->sc_data_direction != DMA_NONE)
+ stex_map_sg(hba, req, &hba->ccb[tag]);
+
stex_send_cmd(hba, req, tag);
return 0;
}
@@ -552,7 +586,7 @@ stex_queuecommand(struct scsi_cmnd *cmd,
static void stex_unmap_sg(struct st_hba *hba, struct scsi_cmnd *cmd)
{
if (cmd->sc_data_direction != DMA_NONE) {
- if (cmd->use_sg)
+ if (cmd->use_sg)
pci_unmap_sg(hba->pdev, cmd->request_buffer,
cmd->use_sg, cmd->sc_data_direction);
else
@@ -597,32 +631,26 @@ static void stex_scsi_done(struct st_ccb
default:
result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
break;
- }
+ }
- cmd->result = result;
- cmd->scsi_done(cmd);
+ cmd->result = result;
+ cmd->scsi_done(cmd);
}
static void stex_copy_data(struct st_ccb *ccb,
struct status_msg *resp, unsigned int variable)
{
- void *p;
- if (resp->scsi_status == SAM_STAT_GOOD) {
- if (ccb->cmd == NULL)
- return;
- if (ccb->cmd->use_sg)
- p = kmap_atomic(ccb->page, KM_IRQ0) + ccb->page_offset;
- else
- p = ccb->cmd->request_buffer;
- memcpy(p, resp->variable, min(variable,
- ccb->cmd->request_bufflen));
- if (ccb->cmd->use_sg)
- kunmap_atomic(p - ccb->page_offset, KM_IRQ0);
- } else {
+ size_t count = variable;
+ if (resp->scsi_status != SAM_STAT_GOOD) {
if (ccb->sense_buffer != NULL)
memcpy(ccb->sense_buffer, resp->variable,
min(variable, ccb->sense_bufflen));
+ return;
}
+
+ if (ccb->cmd == NULL)
+ return;
+ stex_internal_copy(ccb->cmd, resp->variable, &count, ccb->sg_count);
}
static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
@@ -672,7 +700,7 @@ static void stex_mu_intr(struct st_hba *
printk(KERN_WARNING DRV_NAME
"(%s): lagging req\n", pci_name(hba->pdev));
stex_free_tag((unsigned long *)&hba->tag, tag);
- stex_unmap_sg(hba, ccb->cmd); /* ??? */
+ stex_unmap_sg(hba, ccb->cmd); /* ??? */
continue;
}
@@ -704,7 +732,7 @@ static void stex_mu_intr(struct st_hba *
ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER)
stex_controller_info(hba, ccb);
stex_free_tag((unsigned long *)&hba->tag, tag);
- stex_unmap_sg(hba, ccb->cmd);
+ stex_unmap_sg(hba, ccb->cmd);
stex_scsi_done(ccb);
}
@@ -840,8 +868,8 @@ static int stex_abort(struct scsi_cmnd *
stex_mu_intr(hba, data);
- if (hba->wait_ccb == NULL) {
- printk(KERN_WARNING DRV_NAME
+ if (hba->wait_ccb == NULL) {
+ printk(KERN_WARNING DRV_NAME
"(%s): lost interrupt\n", pci_name(hba->pdev));
goto out;
}
@@ -855,6 +883,41 @@ out:
return result;
}
+static void stex_hard_reset(struct st_hba *hba)
+{
+ int i;
+ u16 pci_cmd;
+ u8 control;
+ for (i = 0; i < 16; i++)
+ pci_read_config_dword(hba->pdev, i * 4,
+ &hba->pdev->saved_config_space[i]);
+
+ if (!hba->bus0) {
+ pci_write_config_dword(hba->pdev, 4,
+ hba->pdev->saved_config_space[1] & 0xfffffff9);
+ pci_write_config_byte(hba->pdev, 0x84, 1 << 5);
+ } else {
+ pci_read_config_byte(hba->bus0, 0x3e, &control);
+ control |= (1<<6);
+ pci_write_config_byte(hba->bus0, 0x3e, control);
+ msleep(1);
+ control &= ~(1<<6);
+ pci_write_config_byte(hba->bus0, 0x3e, control);
+ }
+
+ for (i = 0; i < MU_MAX_DELAY_TIME; i++) {
+ pci_read_config_word(hba->pdev, PCI_COMMAND, &pci_cmd);
+ if (pci_cmd & PCI_COMMAND_MASTER)
+ break;
+ msleep(1);
+ }
+
+ msleep(5000);
+ for (i = 0; i < 16; i++)
+ pci_write_config_dword(hba->pdev, i * 4,
+ hba->pdev->saved_config_space[i]);
+}
+
static int stex_reset(struct scsi_cmnd *cmd)
{
struct st_hba *hba;
@@ -876,9 +939,6 @@ wait_cmds:
}
hba->mu_status = MU_STATE_RESETTING;
- writel(MU_INBOUND_DOORBELL_HANDSHAKE, hba->mmio_base + IDBL);
- readl(hba->mmio_base + IDBL);
- msleep(3000);
spin_lock_irqsave(hba->host->host_lock, flags);
@@ -892,6 +952,9 @@ wait_cmds:
spin_unlock_irqrestore(hba->host->host_lock, flags);
+ if (hba->cardtype == st_shasta)
+ stex_hard_reset(hba);
+
if (stex_handshake(hba)) {
printk(KERN_WARNING DRV_NAME
"(%s): resetting: handshake failed\n",
@@ -910,33 +973,6 @@ wait_cmds:
return SUCCESS;
}
-static void stex_init_hba(struct st_hba *hba,
- struct Scsi_Host * host, struct pci_dev *pdev)
-{
- host->max_channel = ST_MAX_LUN_PER_TARGET; /* fw lun work around */
- host->max_id = ST_MAX_TARGET_NUM;
- host->max_lun = 1; /* fw lun work around */
- host->unique_id = host->host_no;
- host->max_cmd_len = STEX_CDB_LENGTH;
-
- hba->host = host;
- hba->pdev = pdev;
- init_waitqueue_head(&hba->waitq);
-}
-
-static int stex_init_shm(struct st_hba *hba, struct pci_dev *pdev)
-{
- hba->dma_mem = pci_alloc_consistent(pdev,
- MU_BUFFER_SIZE, &hba->dma_handle);
- if (!hba->dma_mem)
- return -ENOMEM;
-
- hba->status_buffer =
- (struct status_msg *)(hba->dma_mem + MU_REQ_BUFFER_SIZE);
- hba->mu_status = MU_STATE_STARTING;
- return 0;
-}
-
static void stex_internal_flush(struct st_hba *hba, int id, u16 tag)
{
struct req_msg *req;
@@ -953,12 +989,11 @@ static void stex_internal_flush(struct s
} else {
req->target = id/ST_MAX_LUN_PER_TARGET - ST_MAX_ARRAY_SUPPORTED;
req->lun = id%ST_MAX_LUN_PER_TARGET;
- req->cdb[0] = SYNCHRONIZE_CACHE;
+ req->cdb[0] = SYNCHRONIZE_CACHE;
}
hba->ccb[tag].cmd = NULL;
- hba->ccb[tag].page_offset = 0;
- hba->ccb[tag].page = NULL;
+ hba->ccb[tag].sg_count = 0;
hba->ccb[tag].sense_bufflen = 0;
hba->ccb[tag].sense_buffer = NULL;
hba->ccb[tag].req_type |= PASSTHRU_REQ_TYPE;
@@ -1004,8 +1039,8 @@ static int stex_set_dma_mask(struct pci_
{
int ret;
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)
- && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
- return 0;
+ && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
+ return 0;
ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (!ret)
ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
@@ -1060,19 +1095,48 @@ stex_probe(struct pci_dev *pdev, const s
goto out_iounmap;
}
- err = stex_init_shm(hba, pdev);
- if (err) {
+ hba->dma_mem = pci_alloc_consistent(pdev,
+ STEX_BUFFER_SIZE, &hba->dma_handle);
+ if (!hba->dma_mem) {
+ err = -ENOMEM;
printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n",
- pci_name(pdev));
+ pci_name(pdev));
goto out_iounmap;
}
- stex_init_hba(hba, host, pdev);
+ hba->status_buffer =
+ (struct status_msg *)(hba->dma_mem + MU_REQ_BUFFER_SIZE);
+ hba->scratch = hba->dma_mem + MU_BUFFER_SIZE;
+ hba->mu_status = MU_STATE_STARTING;
+
+ hba->cardtype = (unsigned int) id->driver_data;
+ if (hba->cardtype == st_shasta) {
+ struct pci_dev *bus0 = NULL;
+ u8 atu_bus;
+ while ((bus0 = pci_get_device(0x8086, 0x0370, bus0)) != NULL) {
+ pci_read_config_byte(bus0, 0x19, &atu_bus);
+ pci_dev_put(bus0);
+ if (atu_bus == pdev->bus->number) {
+ hba->bus0 = bus0;
+ break;
+ }
+ }
+ }
+
+ host->max_channel = ST_MAX_LUN_PER_TARGET - 1; /* fw lun work around */
+ host->max_id = ST_MAX_TARGET_NUM;
+ host->max_lun = 1; /* fw lun work around */
+ host->unique_id = host->host_no;
+ host->max_cmd_len = STEX_CDB_LENGTH;
+
+ hba->host = host;
+ hba->pdev = pdev;
+ init_waitqueue_head(&hba->waitq);
err = request_irq(pdev->irq, stex_intr, SA_SHIRQ, DRV_NAME, hba);
if (err) {
printk(KERN_ERR DRV_NAME "(%s): request irq failed\n",
- pci_name(pdev));
+ pci_name(pdev));
goto out_pci_free;
}
@@ -1096,7 +1160,7 @@ stex_probe(struct pci_dev *pdev, const s
out_free_irq:
free_irq(pdev->irq, hba);
out_pci_free:
- pci_free_consistent(pdev, MU_BUFFER_SIZE,
+ pci_free_consistent(pdev, STEX_BUFFER_SIZE,
hba->dma_mem, hba->dma_handle);
out_iounmap:
iounmap(hba->mmio_base);
@@ -1147,7 +1211,7 @@ static void stex_hba_free(struct st_hba
pci_release_regions(hba->pdev);
- pci_free_consistent(hba->pdev, MU_BUFFER_SIZE,
+ pci_free_consistent(hba->pdev, STEX_BUFFER_SIZE,
hba->dma_mem, hba->dma_handle);
}
@@ -1176,12 +1240,14 @@ static void stex_shutdown(struct pci_dev
}
static struct pci_device_id stex_pci_tbl[] = {
- { PCI_VENDOR_ID_PROMISE, 0x8350, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_PROMISE, 0xf350, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_PROMISE, 0x4301, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_PROMISE, 0x4302, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_PROMISE, 0x8301, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_PROMISE, 0x8302, PCI_ANY_ID, PCI_ANY_ID, },
+ { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
+ { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
+ { 0x105a, 0xf350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
+ { 0x105a, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
+ { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
+ { 0x105a, 0x8301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
+ { 0x105a, 0x8302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
+ { 0x1725, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc },
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, stex_pci_tbl);
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-19 15:07 Ed Lin
@ 2006-07-20 21:27 ` Jeff Garzik
2006-07-20 23:55 ` James Bottomley
2006-07-21 1:06 ` Jens Axboe
0 siblings, 2 replies; 33+ messages in thread
From: Jeff Garzik @ 2006-07-20 21:27 UTC (permalink / raw)
To: Ed Lin
Cc: linux-scsi@vger.kernel.org, James.Bottomley, hch, linux-kernel,
akpm, promise_linux
Ed Lin wrote:
> Please review following patch based on the 'stex' branch of
> git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/misc-2.6.git
>
> Jeff Garzik already finished some changes, and these are the rest.
>
>>From Christoph Hellwig's comments:
> use scsi_kmap_atomic_sg/scsi_kunmap_atomic_sg
> callback argument to ->queuecommand changed to 'done'
> merge init functions into .probe
>
>>From Alexey Dobriyan's comments:
> __le32 *time
>
> Promise code changes:
> add hard reset function
> extend reset wait time
> add new device ids
> white space/ minor fix(INQUIRY, max_channel)
>
> Block layer tag:
> It is not implemented because here tag is adapter wide,
> not for single device.
> Non-sg codepath:
> It can be eliminated when Christoph Hellwig's patch
> upstream.
> Firmware lun issue:
> Firmware uses an id/lun pair for a logical drive. But
> lun could be always 0 in Linux(when you do not config
> CONFIG_SCSI_MULTI_LUN).I use channel to map lun,
> otherwise max_id will be 256.
> INQUIRY, passthru command:
> Needed by management software. The special handling of
> INQUIRY is for management software to have a sg device
> to issue commands.
Overall, the patch looks good. My quick review finds a couple nits, though:
1) [major] The Intel bridge code ("pci_get_device(0x8086, 0x0370, bus0),
...") is not the type of thing we normally put into a driver. If there
is a problem with a specific bridge, we would prefer to patch
drivers/pci/quirks.c.
Touching _another_ piece of hardware, other than your own, is a big deal
and generally unwise.
2) [minor] Adding "magic numbers" in stex_hard_reset(). Easy to fix:
convert "0x3e", "0x84", "1 << 5" etc. to named constants. The named
constants should have sufficiently good names to understand their
purpose, without being overly long C symbols.
3) [minor] For sleeping longer than one second, ssleep() is preferred to
msleep().
4) [minor] 'void *scratch' in struct st_hba tells us nothing about its
usage. At the very least, a comment, if not a better name, would be good.
5) [agreement/correction] The block tagging API supports adapter-wide
tags just fine. HOWEVER, I nonetheless feel that block tagging API use
should be considered post-merge. The 'stex' driver is working and
tested today. Since _no individual SCSI driver_ uses the block layer
tagging, it is likely that some instability and core kernel development
will occur, in order to make that work.
All your other changes look good to me.
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-20 21:27 ` Jeff Garzik
@ 2006-07-20 23:55 ` James Bottomley
2006-07-21 0:16 ` Jeff Garzik
2006-07-21 1:06 ` Jens Axboe
1 sibling, 1 reply; 33+ messages in thread
From: James Bottomley @ 2006-07-20 23:55 UTC (permalink / raw)
To: Jeff Garzik
Cc: Ed Lin, linux-scsi@vger.kernel.org, hch, linux-kernel, akpm,
promise_linux
On Thu, 2006-07-20 at 17:27 -0400, Jeff Garzik wrote:
> Since _no individual SCSI driver_ uses the block layer
> tagging, it is likely that some instability and core kernel
> development
> will occur, in order to make that work.
That's not quite true: 53c700 and tmscsim both use it ... I could with
the usage were wider, but at least 53c700 has pretty regular and
constant usage ... enough I think to validate the block tag code (it's
been using it for the last three years).
James
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-20 23:55 ` James Bottomley
@ 2006-07-21 0:16 ` Jeff Garzik
2006-07-21 1:07 ` Jens Axboe
0 siblings, 1 reply; 33+ messages in thread
From: Jeff Garzik @ 2006-07-21 0:16 UTC (permalink / raw)
To: James Bottomley
Cc: Ed Lin, linux-scsi@vger.kernel.org, hch, linux-kernel, akpm,
promise_linux
James Bottomley wrote:
> On Thu, 2006-07-20 at 17:27 -0400, Jeff Garzik wrote:
>> Since _no individual SCSI driver_ uses the block layer
>> tagging, it is likely that some instability and core kernel
>> development
>> will occur, in order to make that work.
>
> That's not quite true: 53c700 and tmscsim both use it ... I could with
> the usage were wider, but at least 53c700 has pretty regular and
> constant usage ... enough I think to validate the block tag code (it's
> been using it for the last three years).
Not for the case being discussed in this thread, adapter-wide tags.
AFAICS, no file in include/scsi/* or drivers/scsi/* ever calls
blk_queue_init_tags() with a non-NULL third arg.
The block tagging capability being discussed here is poorly validated
due to overall underuse, and its never been used in SCSI AFAIK.
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-20 21:27 ` Jeff Garzik
2006-07-20 23:55 ` James Bottomley
@ 2006-07-21 1:06 ` Jens Axboe
1 sibling, 0 replies; 33+ messages in thread
From: Jens Axboe @ 2006-07-21 1:06 UTC (permalink / raw)
To: Jeff Garzik
Cc: Ed Lin, linux-scsi@vger.kernel.org, James.Bottomley, hch,
linux-kernel, akpm, promise_linux
On Thu, Jul 20 2006, Jeff Garzik wrote:
> 5) [agreement/correction] The block tagging API supports adapter-wide
> tags just fine. HOWEVER, I nonetheless feel that block tagging API use
> should be considered post-merge. The 'stex' driver is working and
> tested today. Since _no individual SCSI driver_ uses the block layer
> tagging, it is likely that some instability and core kernel development
> will occur, in order to make that work.
I'd disagree. If the driver gets merged with the current tagging, I'll
get you two beers that it never gets changed.
And you are wrong, block layer tagging is used by at least one SCSI
driver. We definitely need to start pushing it more.
--
Jens Axboe
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 0:16 ` Jeff Garzik
@ 2006-07-21 1:07 ` Jens Axboe
2006-07-21 1:25 ` Jeff Garzik
0 siblings, 1 reply; 33+ messages in thread
From: Jens Axboe @ 2006-07-21 1:07 UTC (permalink / raw)
To: Jeff Garzik
Cc: James Bottomley, Ed Lin, linux-scsi@vger.kernel.org, hch,
linux-kernel, akpm, promise_linux
On Thu, Jul 20 2006, Jeff Garzik wrote:
> James Bottomley wrote:
> >On Thu, 2006-07-20 at 17:27 -0400, Jeff Garzik wrote:
> >>Since _no individual SCSI driver_ uses the block layer
> >>tagging, it is likely that some instability and core kernel
> >>development
> >>will occur, in order to make that work.
> >
> >That's not quite true: 53c700 and tmscsim both use it ... I could with
> >the usage were wider, but at least 53c700 has pretty regular and
> >constant usage ... enough I think to validate the block tag code (it's
> >been using it for the last three years).
>
> Not for the case being discussed in this thread, adapter-wide tags.
That just means the map is shared, otherwise there should be little if
any difference.
> AFAICS, no file in include/scsi/* or drivers/scsi/* ever calls
> blk_queue_init_tags() with a non-NULL third arg.
grpe again, it's in scsi_tcq.h.
> The block tagging capability being discussed here is poorly validated
> due to overall underuse, and its never been used in SCSI AFAIK.
It has and is, James uses it every day!
--
Jens Axboe
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 1:07 ` Jens Axboe
@ 2006-07-21 1:25 ` Jeff Garzik
2006-07-21 1:38 ` Jens Axboe
0 siblings, 1 reply; 33+ messages in thread
From: Jeff Garzik @ 2006-07-21 1:25 UTC (permalink / raw)
To: Jens Axboe
Cc: James Bottomley, Ed Lin, linux-scsi@vger.kernel.org, hch,
linux-kernel, akpm, promise_linux
Jens Axboe wrote:
> On Thu, Jul 20 2006, Jeff Garzik wrote:
>> James Bottomley wrote:
>>> On Thu, 2006-07-20 at 17:27 -0400, Jeff Garzik wrote:
>>>> Since _no individual SCSI driver_ uses the block layer
>>>> tagging, it is likely that some instability and core kernel
>>>> development
>>>> will occur, in order to make that work.
>>> That's not quite true: 53c700 and tmscsim both use it ... I could with
>>> the usage were wider, but at least 53c700 has pretty regular and
>>> constant usage ... enough I think to validate the block tag code (it's
>>> been using it for the last three years).
>> Not for the case being discussed in this thread, adapter-wide tags.
>
> That just means the map is shared, otherwise there should be little if
> any difference.
>
>> AFAICS, no file in include/scsi/* or drivers/scsi/* ever calls
>> blk_queue_init_tags() with a non-NULL third arg.
>
> grpe again, it's in scsi_tcq.h.
What tree are you looking at?
There is only one user in the entire tree, and NULL is hardcoded as the
third arg. This is 2.6.18-rc2:
> [jgarzik@pretzel linux-2.6]$ grep -r blk_queue_init_tags *
> block/ll_rw_blk.c: * blk_queue_init_tags - initialize the queue tag info
> block/ll_rw_blk.c:int blk_queue_init_tags(request_queue_t *q, int depth,
> block/ll_rw_blk.c:EXPORT_SYMBOL(blk_queue_init_tags);
> Documentation/block/biodoc.txt: blk_queue_init_tags(request_queue_t *q, int depth)
> include/linux/blkdev.h:extern int blk_queue_init_tags(request_queue_t *, int, struct blk_queue_tag *);
> include/scsi/scsi_tcq.h: blk_queue_init_tags(sdev->request_queue, depth, NULL);
Regards,
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 1:25 ` Jeff Garzik
@ 2006-07-21 1:38 ` Jens Axboe
2006-07-21 2:10 ` Jeff Garzik
0 siblings, 1 reply; 33+ messages in thread
From: Jens Axboe @ 2006-07-21 1:38 UTC (permalink / raw)
To: Jeff Garzik
Cc: James Bottomley, Ed Lin, linux-scsi@vger.kernel.org, hch,
linux-kernel, akpm, promise_linux
On Thu, Jul 20 2006, Jeff Garzik wrote:
> Jens Axboe wrote:
> >On Thu, Jul 20 2006, Jeff Garzik wrote:
> >>James Bottomley wrote:
> >>>On Thu, 2006-07-20 at 17:27 -0400, Jeff Garzik wrote:
> >>>>Since _no individual SCSI driver_ uses the block layer
> >>>>tagging, it is likely that some instability and core kernel
> >>>>development
> >>>>will occur, in order to make that work.
> >>>That's not quite true: 53c700 and tmscsim both use it ... I could with
> >>>the usage were wider, but at least 53c700 has pretty regular and
> >>>constant usage ... enough I think to validate the block tag code (it's
> >>>been using it for the last three years).
> >>Not for the case being discussed in this thread, adapter-wide tags.
> >
> >That just means the map is shared, otherwise there should be little if
> >any difference.
> >
> >>AFAICS, no file in include/scsi/* or drivers/scsi/* ever calls
> >>blk_queue_init_tags() with a non-NULL third arg.
> >
> >grpe again, it's in scsi_tcq.h.
>
> What tree are you looking at?
>
> There is only one user in the entire tree, and NULL is hardcoded as the
> third arg. This is 2.6.18-rc2:
Sorry, missed your non-NULL statement, I thought you meant in generel.
As long as you get the locking right for the map access, there's really
nothing that seperates shared vs non-shared tag mappings. So I don't
think it's a big deal.
If we don't encourage new drivers to use the block layer tagging, we
might as well not bother with it.
--
Jens Axboe
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 1:38 ` Jens Axboe
@ 2006-07-21 2:10 ` Jeff Garzik
2006-07-21 2:36 ` Jens Axboe
0 siblings, 1 reply; 33+ messages in thread
From: Jeff Garzik @ 2006-07-21 2:10 UTC (permalink / raw)
To: Jens Axboe
Cc: James Bottomley, Ed Lin, linux-scsi@vger.kernel.org, hch,
linux-kernel, akpm, promise_linux
Jens Axboe wrote:
> On Thu, Jul 20 2006, Jeff Garzik wrote:
>> Jens Axboe wrote:
>>> On Thu, Jul 20 2006, Jeff Garzik wrote:
>>>> James Bottomley wrote:
>>>>> On Thu, 2006-07-20 at 17:27 -0400, Jeff Garzik wrote:
>>>>>> Since _no individual SCSI driver_ uses the block layer
>>>>>> tagging, it is likely that some instability and core kernel
>>>>>> development
>>>>>> will occur, in order to make that work.
>>>>> That's not quite true: 53c700 and tmscsim both use it ... I could with
>>>>> the usage were wider, but at least 53c700 has pretty regular and
>>>>> constant usage ... enough I think to validate the block tag code (it's
>>>>> been using it for the last three years).
>>>> Not for the case being discussed in this thread, adapter-wide tags.
>>> That just means the map is shared, otherwise there should be little if
>>> any difference.
>>>
>>>> AFAICS, no file in include/scsi/* or drivers/scsi/* ever calls
>>>> blk_queue_init_tags() with a non-NULL third arg.
>>> grpe again, it's in scsi_tcq.h.
>> What tree are you looking at?
>>
>> There is only one user in the entire tree, and NULL is hardcoded as the
>> third arg. This is 2.6.18-rc2:
>
> Sorry, missed your non-NULL statement, I thought you meant in generel.
>
> As long as you get the locking right for the map access, there's really
> nothing that seperates shared vs non-shared tag mappings. So I don't
> think it's a big deal.
>
> If we don't encourage new drivers to use the block layer tagging, we
> might as well not bother with it.
I don't disagree it's a good thing to have.
I only assert that a --completely unused-- sub-feature cannot be a merge
requirement for a new driver. That's an unreasonable standard. We have
a driver that is clean and works with all well-known and well-used APIs.
As I discovered painfully via libata, using an unused API upstream
(->eh_strategy_handler) can often be a destabilizing or limiting factor.
You _hope_ that this feature works, but it's far better IMO to debug an
unused core feature upstream. If the upstream driver breaks when
host-wide blktag support is added, then it's trivial to find where the
breakage occurred: the stex blktag-update patch.
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 2:10 ` Jeff Garzik
@ 2006-07-21 2:36 ` Jens Axboe
2006-07-21 3:01 ` Jeff Garzik
2006-07-23 19:44 ` hch
0 siblings, 2 replies; 33+ messages in thread
From: Jens Axboe @ 2006-07-21 2:36 UTC (permalink / raw)
To: Jeff Garzik
Cc: James Bottomley, Ed Lin, linux-scsi@vger.kernel.org, hch,
linux-kernel, akpm, promise_linux
On Thu, Jul 20 2006, Jeff Garzik wrote:
> Jens Axboe wrote:
> >On Thu, Jul 20 2006, Jeff Garzik wrote:
> >>Jens Axboe wrote:
> >>>On Thu, Jul 20 2006, Jeff Garzik wrote:
> >>>>James Bottomley wrote:
> >>>>>On Thu, 2006-07-20 at 17:27 -0400, Jeff Garzik wrote:
> >>>>>>Since _no individual SCSI driver_ uses the block layer
> >>>>>>tagging, it is likely that some instability and core kernel
> >>>>>>development
> >>>>>>will occur, in order to make that work.
> >>>>>That's not quite true: 53c700 and tmscsim both use it ... I could with
> >>>>>the usage were wider, but at least 53c700 has pretty regular and
> >>>>>constant usage ... enough I think to validate the block tag code (it's
> >>>>>been using it for the last three years).
> >>>>Not for the case being discussed in this thread, adapter-wide tags.
> >>>That just means the map is shared, otherwise there should be little if
> >>>any difference.
> >>>
> >>>>AFAICS, no file in include/scsi/* or drivers/scsi/* ever calls
> >>>>blk_queue_init_tags() with a non-NULL third arg.
> >>>grpe again, it's in scsi_tcq.h.
> >>What tree are you looking at?
> >>
> >>There is only one user in the entire tree, and NULL is hardcoded as the
> >>third arg. This is 2.6.18-rc2:
> >
> >Sorry, missed your non-NULL statement, I thought you meant in generel.
> >
> >As long as you get the locking right for the map access, there's really
> >nothing that seperates shared vs non-shared tag mappings. So I don't
> >think it's a big deal.
> >
> >If we don't encourage new drivers to use the block layer tagging, we
> >might as well not bother with it.
>
> I don't disagree it's a good thing to have.
>
> I only assert that a --completely unused-- sub-feature cannot be a merge
> requirement for a new driver. That's an unreasonable standard. We have
> a driver that is clean and works with all well-known and well-used APIs.
The feature is used, by far the main part of it is just the tagging
itself, not the shared map feature.
> As I discovered painfully via libata, using an unused API upstream
> (->eh_strategy_handler) can often be a destabilizing or limiting factor.
>
> You _hope_ that this feature works, but it's far better IMO to debug an
> unused core feature upstream. If the upstream driver breaks when
> host-wide blktag support is added, then it's trivial to find where the
> breakage occurred: the stex blktag-update patch.
If I thought that it would ever be updated to use block tagging, I would
not care at all. The motivation to add it from the Promise end would be
zero, as it doesn't really bring any immediate improvements for them. So
it would have to be done by someone else, which means me or you. I don't
have the hardware to actually test it, so unless you do and would want
to do it, chances are looking slim :-)
It's a bit of a chicken and egg problem, unfortunately. The block layer
tagging _should_ be _the_ way to do it, and as such could be labelled a
requirement. I know that's a bit harsh for the Promise folks, but
unfortunately someone has to pay the price...
--
Jens Axboe
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 2:36 ` Jens Axboe
@ 2006-07-21 3:01 ` Jeff Garzik
2006-07-21 3:18 ` Jens Axboe
2006-07-23 19:45 ` hch
2006-07-23 19:44 ` hch
1 sibling, 2 replies; 33+ messages in thread
From: Jeff Garzik @ 2006-07-21 3:01 UTC (permalink / raw)
To: Jens Axboe
Cc: James Bottomley, Ed Lin, linux-scsi@vger.kernel.org, hch,
linux-kernel, akpm, promise_linux
Jens Axboe wrote:
> If I thought that it would ever be updated to use block tagging, I would
> not care at all. The motivation to add it from the Promise end would be
> zero, as it doesn't really bring any immediate improvements for them. So
> it would have to be done by someone else, which means me or you. I don't
> have the hardware to actually test it, so unless you do and would want
> to do it, chances are looking slim :-)
>
> It's a bit of a chicken and egg problem, unfortunately. The block layer
> tagging _should_ be _the_ way to do it, and as such could be labelled a
> requirement. I know that's a bit harsh for the Promise folks, but
> unfortunately someone has to pay the price...
I think it's highly rude to presume that someone who has so-far been
responsive, and responsible, will suddenly not be so. That is not the
way to encourage vendors to join the Linux process.
They set up an alias for Linux maintainer stuff and have been acting
like a maintainer that will stick around. Why punish them for good
behavior?
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 3:01 ` Jeff Garzik
@ 2006-07-21 3:18 ` Jens Axboe
2006-07-21 3:52 ` Jeff Garzik
2006-07-23 19:45 ` hch
1 sibling, 1 reply; 33+ messages in thread
From: Jens Axboe @ 2006-07-21 3:18 UTC (permalink / raw)
To: Jeff Garzik
Cc: James Bottomley, Ed Lin, linux-scsi@vger.kernel.org, hch,
linux-kernel, akpm, promise_linux
On Thu, Jul 20 2006, Jeff Garzik wrote:
> Jens Axboe wrote:
> >If I thought that it would ever be updated to use block tagging, I would
> >not care at all. The motivation to add it from the Promise end would be
> >zero, as it doesn't really bring any immediate improvements for them. So
> >it would have to be done by someone else, which means me or you. I don't
> >have the hardware to actually test it, so unless you do and would want
> >to do it, chances are looking slim :-)
> >
> >It's a bit of a chicken and egg problem, unfortunately. The block layer
> >tagging _should_ be _the_ way to do it, and as such could be labelled a
> >requirement. I know that's a bit harsh for the Promise folks, but
> >unfortunately someone has to pay the price...
>
> I think it's highly rude to presume that someone who has so-far been
> responsive, and responsible, will suddenly not be so. That is not the
> way to encourage vendors to join the Linux process.
>
> They set up an alias for Linux maintainer stuff and have been acting
> like a maintainer that will stick around. Why punish them for good
> behavior?
>
I'm not trying to be rude to annyone, sorry if that is the impression
you got. I'm just looking at things realistically - the fact is that
moving to block layer tagging is not something that will benefit
Promise, so it'd be fairly low on their agenda of things to do. I don't
mean that in any rude sense, I can completely understand that position.
Why would you want to change something that works? Hence it's
reasonable to assume that eg you or I would eventually have to convert
it.
No punishment intended.
--
Jens Axboe
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 3:18 ` Jens Axboe
@ 2006-07-21 3:52 ` Jeff Garzik
2006-07-21 12:13 ` Jens Axboe
0 siblings, 1 reply; 33+ messages in thread
From: Jeff Garzik @ 2006-07-21 3:52 UTC (permalink / raw)
To: Jens Axboe
Cc: James Bottomley, Ed Lin, linux-scsi@vger.kernel.org, hch,
linux-kernel, akpm, promise_linux
Jens Axboe wrote:
> On Thu, Jul 20 2006, Jeff Garzik wrote:
>> Jens Axboe wrote:
>>> If I thought that it would ever be updated to use block tagging, I would
>>> not care at all. The motivation to add it from the Promise end would be
>>> zero, as it doesn't really bring any immediate improvements for them. So
>>> it would have to be done by someone else, which means me or you. I don't
>>> have the hardware to actually test it, so unless you do and would want
>>> to do it, chances are looking slim :-)
>>>
>>> It's a bit of a chicken and egg problem, unfortunately. The block layer
>>> tagging _should_ be _the_ way to do it, and as such could be labelled a
>>> requirement. I know that's a bit harsh for the Promise folks, but
>>> unfortunately someone has to pay the price...
>> I think it's highly rude to presume that someone who has so-far been
>> responsive, and responsible, will suddenly not be so. That is not the
>> way to encourage vendors to join the Linux process.
>>
>> They set up an alias for Linux maintainer stuff and have been acting
>> like a maintainer that will stick around. Why punish them for good
>> behavior?
>>
>
> I'm not trying to be rude to annyone, sorry if that is the impression
> you got. I'm just looking at things realistically - the fact is that
> moving to block layer tagging is not something that will benefit
> Promise, so it'd be fairly low on their agenda of things to do. I don't
> mean that in any rude sense, I can completely understand that position.
> Why would you want to change something that works? Hence it's
> reasonable to assume that eg you or I would eventually have to convert
> it.
Did you read the patch that started this thread? Promise has already
demonstrated they are willing to add changes requested by the community,
on top of an already-working driver.
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 3:52 ` Jeff Garzik
@ 2006-07-21 12:13 ` Jens Axboe
0 siblings, 0 replies; 33+ messages in thread
From: Jens Axboe @ 2006-07-21 12:13 UTC (permalink / raw)
To: Jeff Garzik
Cc: James Bottomley, Ed Lin, linux-scsi@vger.kernel.org, hch,
linux-kernel, akpm, promise_linux
On Thu, Jul 20 2006, Jeff Garzik wrote:
> Jens Axboe wrote:
> >On Thu, Jul 20 2006, Jeff Garzik wrote:
> >>Jens Axboe wrote:
> >>>If I thought that it would ever be updated to use block tagging, I would
> >>>not care at all. The motivation to add it from the Promise end would be
> >>>zero, as it doesn't really bring any immediate improvements for them. So
> >>>it would have to be done by someone else, which means me or you. I don't
> >>>have the hardware to actually test it, so unless you do and would want
> >>>to do it, chances are looking slim :-)
> >>>
> >>>It's a bit of a chicken and egg problem, unfortunately. The block layer
> >>>tagging _should_ be _the_ way to do it, and as such could be labelled a
> >>>requirement. I know that's a bit harsh for the Promise folks, but
> >>>unfortunately someone has to pay the price...
> >>I think it's highly rude to presume that someone who has so-far been
> >>responsive, and responsible, will suddenly not be so. That is not the
> >>way to encourage vendors to join the Linux process.
> >>
> >>They set up an alias for Linux maintainer stuff and have been acting
> >>like a maintainer that will stick around. Why punish them for good
> >>behavior?
> >>
> >
> >I'm not trying to be rude to annyone, sorry if that is the impression
> >you got. I'm just looking at things realistically - the fact is that
> >moving to block layer tagging is not something that will benefit
> >Promise, so it'd be fairly low on their agenda of things to do. I don't
> >mean that in any rude sense, I can completely understand that position.
> >Why would you want to change something that works? Hence it's
> >reasonable to assume that eg you or I would eventually have to convert
> >it.
>
> Did you read the patch that started this thread? Promise has already
> demonstrated they are willing to add changes requested by the community,
> on top of an already-working driver.
Alright, then lets just get it merged and hope it works out.
--
Jens Axboe
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 2:36 ` Jens Axboe
2006-07-21 3:01 ` Jeff Garzik
@ 2006-07-23 19:44 ` hch
1 sibling, 0 replies; 33+ messages in thread
From: hch @ 2006-07-23 19:44 UTC (permalink / raw)
To: Jens Axboe
Cc: Jeff Garzik, James Bottomley, Ed Lin, linux-scsi@vger.kernel.org,
hch, linux-kernel, akpm, promise_linux
On Fri, Jul 21, 2006 at 04:36:47AM +0200, Jens Axboe wrote:
> If I thought that it would ever be updated to use block tagging, I would
> not care at all. The motivation to add it from the Promise end would be
> zero, as it doesn't really bring any immediate improvements for them. So
> it would have to be done by someone else, which means me or you. I don't
> have the hardware to actually test it, so unless you do and would want
> to do it, chances are looking slim :-)
>
> It's a bit of a chicken and egg problem, unfortunately. The block layer
> tagging _should_ be _the_ way to do it, and as such could be labelled a
> requirement. I know that's a bit harsh for the Promise folks, but
> unfortunately someone has to pay the price...
Exactly. And the only way to get folks to use shared infrastructure is to
force new users to use it. Helped for FC, helps for filesystem infrastructure.
It's a community model, everyone has to suffer a little upfront so that the
whole community benefits in the end.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-21 3:01 ` Jeff Garzik
2006-07-21 3:18 ` Jens Axboe
@ 2006-07-23 19:45 ` hch
2006-07-23 20:21 ` Jeff Garzik
1 sibling, 1 reply; 33+ messages in thread
From: hch @ 2006-07-23 19:45 UTC (permalink / raw)
To: Jeff Garzik
Cc: Jens Axboe, James Bottomley, Ed Lin, linux-scsi@vger.kernel.org,
hch, linux-kernel, akpm, promise_linux
On Thu, Jul 20, 2006 at 11:01:02PM -0400, Jeff Garzik wrote:
> I think it's highly rude to presume that someone who has so-far been
> responsive, and responsible, will suddenly not be so. That is not the
> way to encourage vendors to join the Linux process.
But it is like that in practice. I know more than enough examples where
there is no more incentive to fix things up once it's in, heck I'm guilty
of that myself. It has to do with beeing lazy and not wanting to change code
anymore once it has settled.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-23 19:45 ` hch
@ 2006-07-23 20:21 ` Jeff Garzik
0 siblings, 0 replies; 33+ messages in thread
From: Jeff Garzik @ 2006-07-23 20:21 UTC (permalink / raw)
To: hch, Jeff Garzik, Jens Axboe, James Bottomley, Ed Lin,
linux-scsi@vger.kernel.org, linux-kernel, akpm, promise_linux
hch wrote:
> On Thu, Jul 20, 2006 at 11:01:02PM -0400, Jeff Garzik wrote:
>> I think it's highly rude to presume that someone who has so-far been
>> responsive, and responsible, will suddenly not be so. That is not the
>> way to encourage vendors to join the Linux process.
>
> But it is like that in practice. I know more than enough examples where
> there is no more incentive to fix things up once it's in, heck I'm guilty
> of that myself. It has to do with beeing lazy and not wanting to change code
> anymore once it has settled.
I agree -- but in this case we have direct evidence to the contrary.
I'll stay on their back, if nothing else...
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
[not found] <NONAMEBFJ3sl3xbYiMC000000d4@nonameb.ptu.promise.com>
@ 2006-07-25 9:26 ` hch
2006-07-26 1:20 ` Alan Cox
2006-07-25 17:30 ` Jeff Garzik
1 sibling, 1 reply; 33+ messages in thread
From: hch @ 2006-07-25 9:26 UTC (permalink / raw)
To: Ed Lin
Cc: linux-scsi, James.Bottomley, hch, linux-kernel, akpm,
promise_linux, jeff
On Tue, Jul 25, 2006 at 12:41:11PM +0800, Ed Lin wrote:
>
> So it seems there are several possibilities here(regarding no.1 comment):
> 1.The bridge code is kept unchanged. And, as this is a violation to
> Linux tradition and requirement, it could not be admitted upstream.
We have more than enough precedence for poking the bridge that comes as
part of addon cards. As long as the code makes sure it never pokes a bridge
of the same type that is not on the card (and I don't have the code in front
of me right now to check whether it's true) we can keep this code. Please
make sure to add a big comment that explains what is going on in detail
and why it's okay in this special case.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
[not found] <NONAMEBFJ3sl3xbYiMC000000d4@nonameb.ptu.promise.com>
2006-07-25 9:26 ` hch
@ 2006-07-25 17:30 ` Jeff Garzik
1 sibling, 0 replies; 33+ messages in thread
From: Jeff Garzik @ 2006-07-25 17:30 UTC (permalink / raw)
To: Ed Lin; +Cc: linux-scsi, James.Bottomley, hch, linux-kernel, akpm,
promise_linux
Ed Lin wrote:
> So it seems there are several possibilities here(regarding no.1 comment):
> 1.The bridge code is kept unchanged. And, as this is a violation to
> Linux tradition and requirement, it could not be admitted upstream.
> 2.The code could be modified to be conforming to Linux standard. But,
> we are new to Linux. Maybe we need some specific instructions to know
> how to do it. Sorry if this request becomes annoying.
> 3.Remove the code.
>
> We are wondering what should we do next. We are seeking the community's
> help, and advice, something we definitely need.
The normal process for submitting changes to the Linux kernel is by
submitting a series of patches, each containing a single logical set of
changes. For example:
[PATCH 1/4] stex: white space/ minor fix(INQUIRY, max_channel)
[PATCH 2/4] stex: add new device ids
[PATCH 3/4] stex: update internal copy code path
[PATCH 4/4] stex: add hard reset function
Each patch may be dependent on prior patches. Each patch should produce
a usable driver, e.g.
patch #1 must produce a usable driver.
patch #1 + #2 must produce a usable driver.
patch #1 + #2 + #3 must produce a usable driver.
patch #2 + #3 (missing patch #1) need not produce a usable driver.
This is analogous to a mathematical proof: each step in the proof
describes a complete equation.
Therefore, to move forward, I would suggest that you break up your
submitted patch into multiple patches, ordered such that the PCI
bridge-related code is in the final patch. This permits me to
immediately merge patches not related to PCI bridge stuff, while
simultaneously discussing the hard reset/bridge change.
Note that this is standard iterative development:
1. 'stex' driver development, testing.
2. Post a set of 'stex' patches.
3. Community reviews patches.
4. Upstream maintainer merges some or all of the patches.
5. Go to step #1, perhaps to resend (changed or unchanged)
the patches that were not merged.
Regards,
Jeff
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH] Promise 'stex' driver
2006-07-25 9:26 ` hch
@ 2006-07-26 1:20 ` Alan Cox
0 siblings, 0 replies; 33+ messages in thread
From: Alan Cox @ 2006-07-26 1:20 UTC (permalink / raw)
To: hch
Cc: Ed Lin, linux-scsi, James.Bottomley, linux-kernel, akpm,
promise_linux, jeff
On Maw, 2006-07-25 at 10:26 +0100, hch wrote:
> We have more than enough precedence for poking the bridge that comes as
> part of addon cards. As long as the code makes sure it never pokes a bridge
> of the same type that is not on the card (and I don't have the code in front
> of me right now to check whether it's true) we can keep this code. Please
> make sure to add a big comment that explains what is going on in detail
> and why it's okay in this special case.
It does check the basic layout so looks robust. Checking subvendor stuff
is normally a good back-up. We do similar plumbing work in the Promise
IDE and I2O code to handle the old SuperTrak/SX6000 cards and it work
solidly.
Alan
^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2006-07-26 0:18 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-10 16:08 [PATCH] Promise 'stex' driver Jeff Garzik
2006-06-10 16:10 ` Christoph Hellwig
2006-06-10 16:29 ` James Bottomley
2006-06-10 16:34 ` Christoph Hellwig
2006-06-10 16:50 ` Jeff Garzik
2006-06-10 17:10 ` Christoph Hellwig
2006-06-10 16:30 ` Jeff Garzik
2006-06-10 17:06 ` Christoph Hellwig
2006-06-10 17:37 ` Jeff Garzik
2006-06-10 18:22 ` James Bottomley
2006-06-10 18:43 ` Jeff Garzik
2006-06-10 22:28 ` Jeff Garzik
2006-06-10 17:47 ` Alexey Dobriyan
-- strict thread matches above, loose matches on Subject: below --
2006-07-19 15:07 Ed Lin
2006-07-20 21:27 ` Jeff Garzik
2006-07-20 23:55 ` James Bottomley
2006-07-21 0:16 ` Jeff Garzik
2006-07-21 1:07 ` Jens Axboe
2006-07-21 1:25 ` Jeff Garzik
2006-07-21 1:38 ` Jens Axboe
2006-07-21 2:10 ` Jeff Garzik
2006-07-21 2:36 ` Jens Axboe
2006-07-21 3:01 ` Jeff Garzik
2006-07-21 3:18 ` Jens Axboe
2006-07-21 3:52 ` Jeff Garzik
2006-07-21 12:13 ` Jens Axboe
2006-07-23 19:45 ` hch
2006-07-23 20:21 ` Jeff Garzik
2006-07-23 19:44 ` hch
2006-07-21 1:06 ` Jens Axboe
[not found] <NONAMEBFJ3sl3xbYiMC000000d4@nonameb.ptu.promise.com>
2006-07-25 9:26 ` hch
2006-07-26 1:20 ` Alan Cox
2006-07-25 17:30 ` Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).