From: Jes Sorensen This one is a generic update for the qla1280 driver, basically a patch submitted by Christoph which I tweaked to fit the style of the driver. drivers/scsi/qla1280.c | 1041 +++++++++++++++++++------------------------------ drivers/scsi/qla1280.h | 22 - 2 files changed, 420 insertions(+), 643 deletions(-) diff -puN drivers/scsi/qla1280.c~qla1280-update drivers/scsi/qla1280.c --- 25/drivers/scsi/qla1280.c~qla1280-update 2003-12-29 02:33:41.000000000 -0800 +++ 25-akpm/drivers/scsi/qla1280.c 2003-12-29 02:34:23.000000000 -0800 @@ -4,6 +4,7 @@ * QLogic QLA1280 (Ultra2) and QLA12160 (Ultra3) SCSI driver * Copyright (C) 2000 Qlogic Corporation (www.qlogic.com) * Copyright (C) 2001-2003 Jes Sorensen, Wild Open Source Inc. +* Copyright (C) 2003 Christoph Hellwig * * 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 @@ -16,13 +17,17 @@ * General Public License for more details. * ******************************************************************************/ -#define QLA1280_VERSION "3.23.37.1" +#define QLA1280_VERSION "3.23.38.1" /***************************************************************************** Revision History: Rev 3.23.37.1 December 17, 2003, Jes Sorensen - Delete completion queue from srb if mailbox command failed to to avoid qla1280_done completeting qla1280_error_action's obsolete context + Rev 3.23.38 October 18, 2003, Christoph Hellwig + - Convert to new-style hotplugable driver for 2.6 + - Fix missing scsi_unregister/scsi_host_put on HBA removal + - Kill some of cruft Rev 3.23.37 October 1, 2003, Jes Sorensen - Make MMIO depend on CONFIG_X86_VISWS instead of yet another random CONFIG option @@ -341,9 +346,6 @@ * Compile time Options: * 0 - Disable and 1 - Enable */ -#define QL1280_LUN_SUPPORT 0 -#define WATCHDOGTIMER 0 - #define DEBUG_QLA1280_INTR 0 #define DEBUG_PRINT_NVRAM 0 #define DEBUG_QLA1280 0 @@ -423,6 +425,14 @@ scsi_adjust_queue_depth(Scsi_Device *dev } device->queue_depth = depth; } +static inline struct Scsi_Host *scsi_host_alloc(Scsi_Host_Template *t, size_t s) +{ + return scsi_register(t, s); +} +static inline void scsi_host_put(struct Scsi_Host *h) +{ + scsi_unregister(h); +} #else #define HOST_LOCK ha->host->host_lock #endif @@ -435,30 +445,23 @@ scsi_adjust_queue_depth(Scsi_Device *dev #define ia64_platform_is(foo) (!strcmp(x, platform_name)) #endif +static int qla1280_probe_one(struct pci_dev *, const struct pci_device_id *); +static void qla1280_remove_one(struct pci_dev *); + /* * QLogic Driver Support Function Prototypes. */ static void qla1280_done(struct scsi_qla_host *, struct srb **, struct srb **); -static void qla1280_done_q_put(struct srb *, struct srb **, struct srb **); -static int qla1280_slave_configure(Scsi_Device *); #if LINUX_VERSION_CODE < 0x020545 -static void qla1280_select_queue_depth(struct Scsi_Host *, Scsi_Device *); static void qla1280_get_target_options(struct scsi_cmnd *, struct scsi_qla_host *); #endif - -static int qla1280_return_status(struct response * sts, Scsi_Cmnd * cp); -static void qla1280_mem_free(struct scsi_qla_host *ha); static int qla1280_get_token(char *); static int qla1280_setup(char *s) __init; -static inline void qla1280_enable_intrs(struct scsi_qla_host *); -static inline void qla1280_disable_intrs(struct scsi_qla_host *); /* * QLogic ISP1280 Hardware Support Function Prototypes. */ -static int qla1280_initialize_adapter(struct scsi_qla_host *ha); static int qla1280_isp_firmware(struct scsi_qla_host *); -static int qla1280_pci_config(struct scsi_qla_host *); static int qla1280_chip_diag(struct scsi_qla_host *); static int qla1280_setup_chip(struct scsi_qla_host *); static int qla1280_init_rings(struct scsi_qla_host *); @@ -477,7 +480,6 @@ static void qla1280_poll(struct scsi_qla static void qla1280_reset_adapter(struct scsi_qla_host *); static void qla1280_marker(struct scsi_qla_host *, int, int, int, u8); static void qla1280_isp_cmd(struct scsi_qla_host *); -irqreturn_t qla1280_intr_handler(int, void *, struct pt_regs *); static void qla1280_isr(struct scsi_qla_host *, struct srb **, struct srb **); static void qla1280_rst_aen(struct scsi_qla_host *); static void qla1280_status_entry(struct scsi_qla_host *, struct response *, @@ -490,11 +492,9 @@ static uint16_t qla1280_debounce_registe static request_t *qla1280_req_pkt(struct scsi_qla_host *); static int qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *, unsigned int); -static int qla1280_mem_alloc(struct scsi_qla_host *ha); - -static void qla12160_get_target_parameters(struct scsi_qla_host *, +static void qla1280_get_target_parameters(struct scsi_qla_host *, Scsi_Device *); -static int qla12160_set_target_parameters(struct scsi_qla_host *, int, int); +static int qla1280_set_target_parameters(struct scsi_qla_host *, int, int); static struct qla_driver_setup driver_setup __initdata; @@ -529,10 +529,6 @@ qla1280_data_direction(struct scsi_cmnd return flags; } -#if QL1280_LUN_SUPPORT -static void qla1280_enable_lun(struct scsi_qla_host *, int, int); -#endif - #if DEBUG_QLA1280 static void __qla1280_print_scsi_cmd(Scsi_Cmnd * cmd); static void __qla1280_dump_buffer(char *, int); @@ -551,8 +547,6 @@ MODULE_PARM(qla1280, "s"); __setup("qla1280=", qla1280_setup); #endif -MODULE_LICENSE("GPL"); - /* We use the Scsi_Pointer structure that's included with each command * SCSI_Cmnd as a scratchpad for our SRB. @@ -576,28 +570,23 @@ MODULE_LICENSE("GPL"); #define CMD_RESULT(Cmnd) Cmnd->result #define CMD_HANDLE(Cmnd) Cmnd->host_scribble #if LINUX_VERSION_CODE < 0x020545 -#define CMD_HOST(Cmnd) Cmnd->host #define CMD_REQUEST(Cmnd) Cmnd->request.cmd -#define SCSI_BUS_32(Cmnd) Cmnd->channel -#define SCSI_TCN_32(Cmnd) Cmnd->target -#define SCSI_LUN_32(Cmnd) Cmnd->lun #else -#define CMD_HOST(Cmnd) Cmnd->device->host #define CMD_REQUEST(Cmnd) Cmnd->request->cmd +#endif + +#define CMD_HOST(Cmnd) Cmnd->device->host #define SCSI_BUS_32(Cmnd) Cmnd->device->channel #define SCSI_TCN_32(Cmnd) Cmnd->device->id #define SCSI_LUN_32(Cmnd) Cmnd->device->lun -#endif + /*****************************************/ /* ISP Boards supported by this driver */ /*****************************************/ -#define NUM_OF_ISP_DEVICES 6 - struct qla_boards { unsigned char name[9]; /* Board ID String */ - unsigned long device_id; /* Device PCI ID */ int numPorts; /* Number of SCSI ports */ unsigned short *fwcode; /* pointer to FW array */ unsigned short *fwlen; /* number of words in array */ @@ -605,28 +594,38 @@ struct qla_boards { unsigned char *fwver; /* Ptr to F/W version array */ }; -struct qla_boards ql1280_board_tbl[NUM_OF_ISP_DEVICES] = { - /* Name , Board PCI Device ID, Number of ports */ - {"QLA12160", PCI_DEVICE_ID_QLOGIC_ISP12160, 2, - &fw12160i_code01[0], &fw12160i_length01, +/* NOTE: qla1280_pci_tbl and ql1280_board_tbl must be in the same order */ +static struct pci_device_id qla1280_pci_tbl[] = { + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP12160, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1080, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1240, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1280, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP10160, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl); + +static struct qla_boards ql1280_board_tbl[] = { + /* Name , Number of ports, FW details */ + {"QLA12160", 2, &fw12160i_code01[0], &fw12160i_length01, &fw12160i_addr01, &fw12160i_version_str[0]}, - {"QLA1080", PCI_DEVICE_ID_QLOGIC_ISP1080, 1, - &fw1280ei_code01[0], &fw1280ei_length01, + {"QLA1080", 1, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, - {"QLA1240", PCI_DEVICE_ID_QLOGIC_ISP1240, 2, - &fw1280ei_code01[0], &fw1280ei_length01, + {"QLA1240", 2, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, - {"QLA1280", PCI_DEVICE_ID_QLOGIC_ISP1280, 2, - &fw1280ei_code01[0], &fw1280ei_length01, + {"QLA1280", 2, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, - {"QLA10160", PCI_DEVICE_ID_QLOGIC_ISP10160, 1, - &fw12160i_code01[0], &fw12160i_length01, + {"QLA10160", 1, &fw12160i_code01[0], &fw12160i_length01, &fw12160i_addr01, &fw12160i_version_str[0]}, - {" ", 0, 0} + {" ", 0} }; static int qla1280_verbose = 1; -static struct scsi_qla_host *qla1280_hostlist; static int qla1280_buffer_size; static char *qla1280_buffer; @@ -675,31 +674,19 @@ static int qla1280_proc_info(struct Scsi int size = 0; int len = 0; struct qla_boards *bdp; -#ifdef BOGUS_QUEUE - struct scsi_lu *up; - uint32_t b, t, l; -#endif -#if LINUX_VERSION_CODE >= 0x020600 - ha = (struct scsi_qla_host *)host->hostdata; -#else +#if LINUX_VERSION_CODE < 0x020600 struct Scsi_Host *host; - /* Find the host that was specified */ - for (ha = qla1280_hostlist; (ha != NULL) - && ha->host->host_no != hostno; ha = ha->next) ; - - /* if host wasn't found then exit */ - if (!ha) { - size = sprintf(buffer, "Can't find adapter for host " - "number %d\n", hostno); - if (size > length) { - return size; - } else { - return 0; - } + + for (host = scsi_hostlist; host; host = host->next) { + if (host->host_no == hostno) + goto found; } - host = ha->host; + return -ESRCH; + + found: #endif + ha = (struct scsi_qla_host *)host->hostdata; if (inout) return -ENOSYS; @@ -753,51 +740,6 @@ static int qla1280_proc_info(struct Scsi size = sprintf(PROC_BUF, "\n"); /* 1 */ len += size; - size = sprintf(PROC_BUF, "SCSI device Information:\n"); - len += size; -#ifdef BOGUS_QUEUE - /* scan for all equipment stats */ - for (b = 0; b < MAX_BUSES; b++) - for (t = 0; t < MAX_TARGETS; t++) { - for (l = 0; l < MAX_LUNS; l++) { - up = LU_Q(ha, b, t, l); - if (up == NULL) - continue; - /* unused device/lun */ - if (up->io_cnt == 0 || up->io_cnt < 2) - continue; - /* total reads since boot */ - /* total writes since boot */ - /* total requests since boot */ - size = sprintf (PROC_BUF, - "(%2d:%2d:%2d): Total reqs %ld,", - b, t, l, up->io_cnt); - len += size; - /* current number of pending requests */ - size = sprintf(PROC_BUF, " Pend reqs %d,", - up->q_outcnt); - len += size; -#if 0 - /* avg response time */ - size = sprintf(PROC_BUF, " Avg resp time %ld%%,", - (up->resp_time / up->io_cnt) * - 100); - len += size; - - /* avg active time */ - size = sprintf(PROC_BUF, - " Avg active time %ld%%\n", - (up->act_time / up->io_cnt) * 100); -#else - size = sprintf(PROC_BUF, "\n"); -#endif - len += size; - } - if (len >= qla1280_buffer_size) - break; - } -#endif - if (len >= qla1280_buffer_size) { printk(KERN_WARNING "qla1280: Overflow buffer in qla1280_proc.c\n"); @@ -875,312 +817,6 @@ static int qla1280_read_nvram(struct scs return chksum; } - -/************************************************************************** - * qla1280_do_device_init - * This routine will register the device with the SCSI subsystem, - * initialize the host adapter structure and call the device init - * routines. - * - * Input: - * pdev - pointer to struct pci_dev for adapter - * template - pointer to SCSI template - * devnum - the device number - * bdp - pointer to struct _qlaboards - * num_hosts - the host number - * - * Returns: - * host - pointer to SCSI host structure - **************************************************************************/ -struct Scsi_Host * -qla1280_do_device_init(struct pci_dev *pdev, Scsi_Host_Template * template, - int devnum, struct qla_boards *bdp, int num_hosts) -{ - struct Scsi_Host *host; - struct scsi_qla_host *ha; - - printk(KERN_INFO "qla1280: %s found on PCI bus %i, dev %i\n", - bdp->name, pdev->bus->number, PCI_SLOT(pdev->devfn)); - - host = scsi_register(template, sizeof(struct scsi_qla_host)); - if (!host) { - printk(KERN_WARNING - "qla1280: Failed to register host, aborting.\n"); - goto error; - } - -#if LINUX_VERSION_CODE < 0x020545 - scsi_set_pci_device(host, pdev); -#else - scsi_set_device(host, &pdev->dev); -#endif - ha = (struct scsi_qla_host *)host->hostdata; - /* Clear our data area */ - memset(ha, 0, sizeof(struct scsi_qla_host)); - /* Sanitize the information from PCI BIOS. */ - host->irq = pdev->irq; - ha->pci_bus = pdev->bus->number; - ha->pci_device_fn = pdev->devfn; - ha->pdev = pdev; - ha->device_id = bdp->device_id; - ha->devnum = devnum; /* specifies microcode load address */ - - if (qla1280_mem_alloc(ha)) { - printk(KERN_INFO "qla1x160: Failed to get memory\n"); - goto error_scsi_unregister; - } - - ha->ports = bdp->numPorts; - /* following needed for all cases of OS versions */ - ha->host = host; - ha->host_no = host->host_no; - - host->can_queue = 0xfffff; /* unlimited */ - host->cmd_per_lun = 1; - host->base = (unsigned long)ha->mmpbase; - host->max_channel = bdp->numPorts - 1; - host->max_lun = MAX_LUNS - 1; - host->max_id = MAX_TARGETS; - host->max_sectors = 1024; -#if LINUX_VERSION_CODE < 0x020545 - host->select_queue_depths = qla1280_select_queue_depth; -#endif - - ha->instance = num_hosts; - host->unique_id = ha->instance; - - if (qla1280_pci_config(ha)) { - printk(KERN_INFO "qla1x160: Unable to configure PCI\n"); - goto error_mem_alloced; - } - - /* Disable ISP interrupts. */ - qla1280_disable_intrs(ha); - - /* Register the IRQ with Linux (sharable) */ - if (request_irq(host->irq, qla1280_intr_handler, SA_SHIRQ, - "qla1280", ha)) { - printk("qla1280 : Failed to reserve interrupt %d already " - "in use\n", host->irq); - goto error_iounmap; - } -#if !MEMORY_MAPPED_IO - /* Register the I/O space with Linux */ - if (!request_region(host->io_port, 0xff, "qla1280")) { - printk("qla1280: Failed to reserve i/o region 0x%04lx-0x%04lx" - " already in use\n", - host->io_port, host->io_port + 0xff); - goto error_free_irq; - } -#endif - - /* load the F/W, read paramaters, and init the H/W */ - if (qla1280_initialize_adapter(ha)) { - printk(KERN_INFO "qla1x160: Failed to initialize adapter\n"); - goto error_release_region; - } - - /* set our host ID (need to do something about our two IDs) */ - host->this_id = ha->bus_settings[0].id; - - return host; - - error_release_region: -#if !MEMORY_MAPPED_IO - release_region(host->io_port, 0xff); - error_free_irq: -#endif - free_irq(host->irq, ha); - error_iounmap: -#if MEMORY_MAPPED_IO - if (ha->mmpbase) - iounmap((void *)(((unsigned long) ha->mmpbase) & PAGE_MASK)); -#endif - error_mem_alloced: - qla1280_mem_free(ha); - error_scsi_unregister: - scsi_unregister(host); - error: - return NULL; -} - -/************************************************************************** - * qla1280_detect - * This routine will probe for Qlogic 1280 SCSI host adapters. - * It returns the number of host adapters of a particular - * type that were found. It also initialize all data necessary for - * the driver. It is passed-in the host number, so that it - * knows where its first entry is in the scsi_hosts[] array. - * - * Input: - * template - pointer to SCSI template - * - * Returns: - * num - number of host adapters found. - **************************************************************************/ -static int -qla1280_detect(Scsi_Host_Template * template) -{ - struct pci_dev *pdev = NULL; - struct Scsi_Host *host; - struct scsi_qla_host *ha, *cur_ha; - struct qla_boards *bdp; - uint16_t subsys_vendor, subsys_device; - int num_hosts = 0; - int devnum = 0; - - ENTER("qla1280_detect"); - - if (sizeof(struct srb) > sizeof(Scsi_Pointer)) { - printk(KERN_WARNING - "qla1280_detect: [WARNING] struct srb too big\n"); - return 0; - } -#ifdef MODULE - /* - * If we are called as a module, the qla1280 pointer may not be null - * and it would point to our bootup string, just like on the lilo - * command line. IF not NULL, then process this config string with - * qla1280_setup - * - * Boot time Options - * To add options at boot time add a line to your lilo.conf file like: - * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}" - * which will result in the first four devices on the first two - * controllers being set to a tagged queue depth of 32. - */ - if (qla1280) - qla1280_setup(qla1280); -#endif - - bdp = &ql1280_board_tbl[0]; - qla1280_hostlist = NULL; - template->proc_name = "qla1280"; - - /* First Initialize QLA12160 on PCI Bus 1 Dev 2 */ - while ((pdev = pci_find_subsys(PCI_VENDOR_ID_QLOGIC, bdp->device_id, - PCI_ANY_ID, PCI_ANY_ID, pdev))) { - - /* find QLA12160 device on PCI bus=1 slot=2 */ - if ((pdev->bus->number != 1) || (PCI_SLOT(pdev->devfn) != 2)) - continue; - - /* Bypass all AMI SUBSYS VENDOR IDs */ - if (pdev->subsystem_vendor == PCI_VENDOR_ID_AMI) { - printk(KERN_INFO - "qla1x160: Skip AMI SubSys Vendor ID Chip\n"); - continue; - } - - if (pci_enable_device(pdev)) - goto find_devices; - - host = qla1280_do_device_init(pdev, template, devnum, - bdp, num_hosts); - if (!host) - continue; - ha = (struct scsi_qla_host *)host->hostdata; - - /* this preferred device will always be the first one found */ - cur_ha = qla1280_hostlist = ha; - num_hosts++; - } - - find_devices: - - pdev = NULL; - /* Try and find each different type of adapter we support */ - for (devnum = 0; bdp->device_id != 0 && devnum < NUM_OF_ISP_DEVICES; - devnum++, bdp++) { - /* PCI_SUBSYSTEM_IDS supported */ - while ((pdev = pci_find_subsys(PCI_VENDOR_ID_QLOGIC, - bdp->device_id, PCI_ANY_ID, - PCI_ANY_ID, pdev))) { - if (pci_enable_device(pdev)) - continue; - /* found an adapter */ - subsys_vendor = pdev->subsystem_vendor; - subsys_device = pdev->subsystem_device; - - /* - * skip QLA12160 already initialized on - * PCI Bus 1 Dev 2 since we already initialized - * and presented it - */ - if ((bdp->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160)&& - (pdev->bus->number == 1) && - (PCI_SLOT(pdev->devfn) == 2)) - continue; - - /* Bypass all AMI SUBSYS VENDOR IDs */ - if (subsys_vendor == PCI_VENDOR_ID_AMI) { - printk(KERN_INFO - "qla1x160: Skip AMI SubSys Vendor ID Chip\n"); - continue; - } - dprintk(1, "qla1x160: Supported Device Found VID=%x " - "DID=%x SSVID=%x SSDID=%x\n", pdev->vendor, - pdev->device, subsys_vendor, subsys_device); - - host = qla1280_do_device_init(pdev, template, - devnum, bdp, num_hosts); - if (!host) - continue; - ha = (struct scsi_qla_host *)host->hostdata; - - if (qla1280_hostlist == NULL) { - cur_ha = qla1280_hostlist = ha; - } else { - cur_ha = qla1280_hostlist; - while (cur_ha->next != NULL) - cur_ha = cur_ha->next; - cur_ha->next = ha; - } - num_hosts++; - } /* end of WHILE */ - } /* end of FOR */ - - LEAVE("qla1280_detect"); - return num_hosts; -} - -/************************************************************************** - * qla1280_release - * Free the passed in Scsi_Host memory structures prior to unloading the - * module. - **************************************************************************/ -static int -qla1280_release(struct Scsi_Host *host) -{ - struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; - - ENTER("qla1280_release"); - - if (!ha->flags.online) - return 0; - - /* turn-off interrupts on the card */ - WRT_REG_WORD(&ha->iobase->ictrl, 0); - - /* Detach interrupts */ - if (host->irq) - free_irq(host->irq, ha); - -#if MEMORY_MAPPED_IO - if (ha->mmpbase) - iounmap(ha->mmpbase); -#else - /* release io space registers */ - if (host->io_port) - release_region(host->io_port, 0xff); -#endif /* MEMORY_MAPPED_IO */ - - qla1280_mem_free(ha); - - ENTER("qla1280_release"); - return 0; -} - /************************************************************************** * qla1280_info * Return a string describing the driver. @@ -1197,11 +833,11 @@ qla1280_info(struct Scsi_Host *host) ha = (struct scsi_qla_host *)host->hostdata; bdp = &ql1280_board_tbl[ha->devnum]; memset(bp, 0, sizeof(qla1280_scsi_name_buffer)); + sprintf (bp, - "QLogic %s PCI to SCSI Host Adapter: bus %d device %d irq %d\n" + "QLogic %s PCI to SCSI Host Adapter\n" " Firmware version: %2d.%02d.%02d, Driver version %s", - &bdp->name[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, - host->irq, bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], + &bdp->name[0], bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], QLA1280_VERSION); return bp; } @@ -1220,38 +856,19 @@ qla1280_info(struct Scsi_Host *host) static int qla1280_queuecommand(Scsi_Cmnd * cmd, void (*fn) (Scsi_Cmnd *)) { - struct scsi_qla_host *ha; - struct srb *sp; - struct Scsi_Host *host; - int bus, target, lun; - int status; - - /*ENTER("qla1280_queuecommand"); - */ - dprintk(2, "qla1280_queuecommand(): jiffies %li\n", jiffies); - - host = CMD_HOST(cmd); - ha = (struct scsi_qla_host *)host->hostdata; + struct Scsi_Host *host = cmd->device->host; + struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; + struct srb *sp = (struct srb *)&cmd->SCp; - /* send command to adapter */ - sp = (struct srb *)CMD_SP(cmd); - sp->cmd = cmd; cmd->scsi_done = fn; + sp->cmd = cmd; sp->flags = 0; qla1280_print_scsi_cmd(5, cmd); - /* Generate LU queue on bus, target, LUN */ - bus = SCSI_BUS_32(cmd); - target = SCSI_TCN_32(cmd); - lun = SCSI_LUN_32(cmd); if (ha->flags.enable_64bit_addressing) - status = qla1280_64bit_start_scsi(ha, sp); - else - status = qla1280_32bit_start_scsi(ha, sp); - - /*LEAVE("qla1280_queuecommand"); */ - return status; + return qla1280_64bit_start_scsi(ha, sp); + return qla1280_32bit_start_scsi(ha, sp); } enum action { @@ -1564,29 +1181,105 @@ qla1280_biosparam(struct scsi_device *sd unsigned long capacity = disk->capacity; #endif - heads = 64; - sectors = 32; - cylinders = (unsigned long)capacity / (heads * sectors); - if (cylinders > 1024) { - heads = 255; - sectors = 63; - cylinders = (unsigned long)capacity / (heads * sectors); - /* if (cylinders > 1023) - cylinders = 1023; */ + heads = 64; + sectors = 32; + cylinders = (unsigned long)capacity / (heads * sectors); + if (cylinders > 1024) { + heads = 255; + sectors = 63; + cylinders = (unsigned long)capacity / (heads * sectors); + /* if (cylinders > 1023) + cylinders = 1023; */ + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return 0; +} + +#if LINUX_VERSION_CODE < 0x020600 +static int +qla1280_detect(Scsi_Host_Template *template) +{ + struct pci_device_id *id = &qla1280_pci_tbl[0]; + struct pci_dev *pdev = NULL; + int num_hosts = 0; + + if (sizeof(struct srb) > sizeof(Scsi_Pointer)) { + printk(KERN_WARNING + "qla1280: struct srb too big, aborting\n"); + return 0; + } + +#ifdef MODULE + /* + * If we are called as a module, the qla1280 pointer may not be null + * and it would point to our bootup string, just like on the lilo + * command line. IF not NULL, then process this config string with + * qla1280_setup + * + * Boot time Options + * To add options at boot time add a line to your lilo.conf file like: + * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}" + * which will result in the first four devices on the first two + * controllers being set to a tagged queue depth of 32. + */ + if (qla1280) + qla1280_setup(qla1280); +#endif + + /* First Initialize QLA12160 on PCI Bus 1 Dev 2 */ + while ((pdev = pci_find_device(id->vendor, id->device, pdev))) { + if (pdev->bus->number == 1 && PCI_SLOT(pdev->devfn) == 2) { + if (!qla1280_probe_one(pdev, id)) + num_hosts++; + } + } + + pdev = NULL; + /* Try and find each different type of adapter we support */ + for (id = &qla1280_pci_tbl[0]; id->device; id++) { + while ((pdev = pci_find_device(id->vendor, id->device, pdev))) { + /* + * skip QLA12160 already initialized on + * PCI Bus 1 Dev 2 since we already initialized + * and presented it + */ + if (id->device == PCI_DEVICE_ID_QLOGIC_ISP12160 && + pdev->bus->number == 1 && + PCI_SLOT(pdev->devfn) == 2) + continue; + + if (!qla1280_probe_one(pdev, id)) + num_hosts++; + } } - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; + return num_hosts; +} + +/* + * This looks a bit ugly as we could just pass down host to + * qla1280_remove_one, but I want to keep qla1280_release purely a wrapper + * around pci_driver::remove as used from 2.6 onwards. + */ +static int +qla1280_release(struct Scsi_Host *host) +{ + struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; + qla1280_remove_one(ha->pdev); return 0; } +#endif /************************************************************************** * qla1280_intr_handler * Handles the H/W interrupt **************************************************************************/ -irqreturn_t +static irqreturn_t qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { struct scsi_qla_host *ha; @@ -1624,7 +1317,7 @@ qla1280_intr_handler(int irq, void *dev_ static int -qla12160_set_target_parameters(struct scsi_qla_host *ha, int bus, int target) +qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target) { uint8_t mr; uint16_t mb[MAILBOX_REGISTER_COUNT]; @@ -1633,8 +1326,8 @@ qla12160_set_target_parameters(struct sc nv = &ha->nvram; - if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || - ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) + if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 || + ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160) is1x160 = 1; else is1x160 = 0; @@ -1721,8 +1414,8 @@ qla1280_slave_configure(Scsi_Device *dev (driver_setup.wide_mask && (~driver_setup.wide_mask & (1 << target)))) nv->bus[bus].target[target].parameter.f.enable_wide = 0; - if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || - ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) { + if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 || + ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160) { if (driver_setup.no_ppr || (driver_setup.ppr_mask && (~driver_setup.ppr_mask & (1 << target)))) @@ -1730,11 +1423,9 @@ qla1280_slave_configure(Scsi_Device *dev } spin_lock_irqsave(HOST_LOCK, flags); - if (nv->bus[bus].target[target].parameter.f.enable_sync) { - status = qla12160_set_target_parameters(ha, bus, target); - } - - qla12160_get_target_parameters(ha, device); + if (nv->bus[bus].target[target].parameter.f.enable_sync) + status = qla1280_set_target_parameters(ha, bus, target); + qla1280_get_target_parameters(ha, device); spin_unlock_irqrestore(HOST_LOCK, flags); return status; } @@ -1761,16 +1452,11 @@ qla1280_select_queue_depth(struct Scsi_H if (scsi_devs) qla1280_check_for_dead_scsi_bus(ha, scsi_devs->channel); - LEAVE("qla1280_select_queue_depth"); } #endif /* - * Driver Support Routines - */ - -/* * qla1280_done * Process completed commands. * @@ -1972,100 +1658,19 @@ qla1280_done_q_put(struct srb * sp, stru LEAVE("qla1280_put_done_q"); } - -/* -* qla1280_mem_alloc -* Allocates adapter memory. -* -* Returns: -* 0 = success. -* 1 = failure. -*/ -static int -qla1280_mem_alloc(struct scsi_qla_host *ha) -{ - int status = 1; - dma_addr_t dma_handle; - - ENTER("qla1280_mem_alloc"); - - /* get consistent memory allocated for request and response rings */ - ha->request_ring = pci_alloc_consistent(ha->pdev, - ((REQUEST_ENTRY_CNT + 1) * - (sizeof(request_t))), - &dma_handle); - if (!ha->request_ring) - goto error; - ha->request_dma = dma_handle; - ha->response_ring = pci_alloc_consistent(ha->pdev, - ((RESPONSE_ENTRY_CNT + 1) * - (sizeof(struct response))), - &dma_handle); - if (!ha->response_ring) - goto error; - ha->response_dma = dma_handle; - status = 0; - goto finish; - - error: - if (status) - dprintk(2, "qla1280_mem_alloc: **** FAILED ****\n"); - - if (ha->request_ring) - pci_free_consistent(ha->pdev, - ((REQUEST_ENTRY_CNT + 1) * - (sizeof(request_t))), - ha->request_ring, ha->request_dma); - finish: - LEAVE("qla1280_mem_alloc"); - return status; -} - -/* - * qla1280_mem_free - * Frees adapter allocated memory. - * - * Input: - * ha = adapter block pointer. - */ -static void -qla1280_mem_free(struct scsi_qla_host *ha) -{ - ENTER("qlc1280_mem_free"); - /* free consistent memory allocated for request and response rings */ - if (ha->request_ring) - pci_free_consistent(ha->pdev, - ((REQUEST_ENTRY_CNT + 1) * - (sizeof(request_t))), - ha->request_ring, ha->request_dma); - - if (ha->response_ring) - pci_free_consistent(ha->pdev, - ((RESPONSE_ENTRY_CNT + 1) * - (sizeof(struct response))), - ha->response_ring, ha->response_dma); - - if (qla1280_buffer) { - free_page((unsigned long) qla1280_buffer); - qla1280_buffer = NULL; - } - - LEAVE("qlc1280_mem_free"); -} - /****************************************************************************/ /* QLogic ISP1280 Hardware Support Functions. */ /****************************************************************************/ /* - * qla2100_enable_intrs - * qla2100_disable_intrs - * - * Input: - * ha = adapter block pointer. - * - * Returns: - * None + * qla2100_enable_intrs + * qla2100_disable_intrs + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * None */ static inline void qla1280_enable_intrs(struct scsi_qla_host *ha) @@ -2101,7 +1706,7 @@ qla1280_disable_intrs(struct scsi_qla_ho * Returns: * 0 = success */ -static int +static int __devinit qla1280_initialize_adapter(struct scsi_qla_host *ha) { struct device_reg *reg; @@ -2297,7 +1902,7 @@ qla1280_isp_firmware(struct scsi_qla_hos * Returns: * 0 = success. */ -static int +static int __devinit qla1280_pci_config(struct scsi_qla_host *ha) { #if MEMORY_MAPPED_IO @@ -2724,8 +2329,8 @@ qla1280_nvram_config(struct scsi_qla_hos ENTER("qla1280_nvram_config"); - if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || - ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) + if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 || + ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160) is1x160 = 1; else is1x160 = 0; @@ -4207,48 +3812,6 @@ qla1280_isp_cmd(struct scsi_qla_host *ha LEAVE("qla1280_isp_cmd"); } -#if QL1280_LUN_SUPPORT -/* - * qla1280_enable_lun - * Issue enable LUN entry IOCB. - * - * Input: - * ha = adapter block pointer. - * bus = SCSI BUS number. - * lun = LUN number. - */ -static void -qla1280_enable_lun(struct scsi_qla_host *ha, int bus, int lun) -{ - struct elun_entry *pkt; - - ENTER("qla1280_enable_lun"); - - /* Get request packet. */ - /* - if (pkt = (struct elun_entry *)qla1280_req_pkt(ha)) - { - pkt->entry_type = ENABLE_LUN_TYPE; - pkt->lun = cpu_to_le16(bus ? lun | BIT_15 : lun); - pkt->command_count = 32; - pkt->immed_notify_count = 1; - pkt->group_6_length = MAX_CMDSZ; - pkt->group_7_length = MAX_CMDSZ; - pkt->timeout = cpu_to_le16(0x30); - - qla1280_isp_cmd(ha); - } - */ - pkt = (struct elun_entry *) 1; - - if (!pkt) - dprintk(2, "qla1280_enable_lun: **** FAILED ****\n"); - else - dprintk(3, "qla1280_enable_lun: exiting normally\n"); -} -#endif - - /****************************************************************************/ /* Interrupt Service Routine. */ /****************************************************************************/ @@ -4894,7 +4457,7 @@ qla1280_check_for_dead_scsi_bus(struct s } static void -qla12160_get_target_parameters(struct scsi_qla_host *ha, Scsi_Device *device) +qla1280_get_target_parameters(struct scsi_qla_host *ha, Scsi_Device *device) { uint16_t mb[MAILBOX_REGISTER_COUNT]; int bus, target, lun; @@ -5136,34 +4699,270 @@ qla1280_get_token(char *str) return ret; } - -static Scsi_Host_Template driver_template = { - .proc_info = qla1280_proc_info, +static Scsi_Host_Template qla1280_driver_template = { + .proc_name = "qla1280", .name = "Qlogic ISP 1280/12160", +#if LINUX_VERSION_CODE >= 0x020545 + .slave_configure = qla1280_slave_configure, +#else .detect = qla1280_detect, .release = qla1280_release, +#endif .info = qla1280_info, .queuecommand = qla1280_queuecommand, -#if LINUX_VERSION_CODE >= 0x020545 - .slave_configure = qla1280_slave_configure, -#endif .eh_abort_handler = qla1280_eh_abort, .eh_device_reset_handler= qla1280_eh_device_reset, .eh_bus_reset_handler = qla1280_eh_bus_reset, .eh_host_reset_handler = qla1280_eh_adapter_reset, .bios_param = qla1280_biosparam, - .can_queue = 255, + .proc_info = qla1280_proc_info, + .can_queue = 0xfffff, .this_id = -1, .sg_tablesize = SG_ALL, - .cmd_per_lun = 3, + .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, #if LINUX_VERSION_CODE < 0x020545 .use_new_eh_code = 1, #endif }; -#include "scsi_module.c" +static int __devinit +qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int devnum = id->driver_data; + struct qla_boards *bdp = &ql1280_board_tbl[devnum]; + struct Scsi_Host *host; + struct scsi_qla_host *ha; + int error = -ENODEV; + + /* Bypass all AMI SUBSYS VENDOR IDs */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_AMI) { + printk(KERN_INFO + "qla1280: Skipping AMI SubSys Vendor ID Chip\n"); + goto error; + } + + printk(KERN_INFO "qla1280: %s found on PCI bus %i, dev %i\n", + bdp->name, pdev->bus->number, PCI_SLOT(pdev->devfn)); + + if (pci_enable_device(pdev)) { + printk(KERN_WARNING + "qla1280: Failed to enabled pci device, aborting.\n"); + goto error; + } + + error = -ENOMEM; + host = scsi_host_alloc(&qla1280_driver_template, sizeof(*ha)); + if (!host) { + printk(KERN_WARNING + "qla1280: Failed to register host, aborting.\n"); + goto error; + } + + ha = (struct scsi_qla_host *)host->hostdata; + memset(ha, 0, sizeof(struct scsi_qla_host)); + + ha->pdev = pdev; + ha->devnum = devnum; /* specifies microcode load address */ + + ha->request_ring = pci_alloc_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))), + &ha->request_dma); + if (!ha->request_ring) { + printk(KERN_INFO "qla1280: Failed to get request memory\n"); + goto error_put_host; + } + + ha->response_ring = pci_alloc_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))), + &ha->response_dma); + if (!ha->response_ring) { + printk(KERN_INFO "qla1280: Failed to get response memory\n"); + goto error_free_request_ring; + } + + ha->ports = bdp->numPorts; + + ha->host = host; + ha->host_no = host->host_no; + + host->irq = pdev->irq; + host->base = (unsigned long)ha->mmpbase; + host->max_channel = bdp->numPorts - 1; + host->max_lun = MAX_LUNS - 1; + host->max_id = MAX_TARGETS; + host->max_sectors = 1024; + host->unique_id = host->host_no; + +#if LINUX_VERSION_CODE < 0x020545 + host->select_queue_depths = qla1280_select_queue_depth; +#endif + + error = -ENODEV; + if (qla1280_pci_config(ha)) { + printk(KERN_INFO "qla1280: Unable to configure PCI\n"); + goto error_free_response_ring; + } + + /* Disable ISP interrupts. */ + qla1280_disable_intrs(ha); + + /* Register the IRQ with Linux (sharable) */ + if (request_irq(pdev->irq, qla1280_intr_handler, SA_SHIRQ, + "qla1280", ha)) { + printk("qla1280 : Failed to reserve interrupt %d already " + "in use\n", pdev->irq); + goto error_iounmap; + } + +#if !MEMORY_MAPPED_IO + /* Register the I/O space with Linux */ + if (!request_region(host->io_port, 0xff, "qla1280")) { + printk("qla1280: Failed to reserve i/o region 0x%04lx-0x%04lx" + " already in use\n", + host->io_port, host->io_port + 0xff); + goto error_free_irq; + } +#endif + + /* load the F/W, read paramaters, and init the H/W */ + if (qla1280_initialize_adapter(ha)) { + printk(KERN_INFO "qla1x160: Failed to initialize adapter\n"); + goto error_release_region; + } + + /* set our host ID (need to do something about our two IDs) */ + host->this_id = ha->bus_settings[0].id; + + pci_set_drvdata(pdev, host); + +#if LINUX_VERSION_CODE >= 0x020600 + error = scsi_add_host(host, &pdev->dev); + if (error) + goto error_disable_adapter; + scsi_scan_host(host); +#else + scsi_set_pci_device(host, pdev); +#endif + + return 0; + +#if LINUX_VERSION_CODE >= 0x020600 + error_disable_adapter: + WRT_REG_WORD(&ha->iobase->ictrl, 0); +#endif + error_release_region: +#if !MEMORY_MAPPED_IO + release_region(host->io_port, 0xff); + error_free_irq: +#endif + free_irq(pdev->irq, ha); + error_iounmap: +#if MEMORY_MAPPED_IO + iounmap((void *)(((unsigned long) ha->mmpbase) & PAGE_MASK)); +#endif + error_free_response_ring: + pci_free_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))), + ha->response_ring, ha->response_dma); + error_free_request_ring: + pci_free_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))), + ha->request_ring, ha->request_dma); + error_put_host: + scsi_host_put(host); + error: + return error; +} + +/* + * Older ia64 toolchains have problems with relative links when this + * goes into the .exit.text section + */ +static void +qla1280_remove_one(struct pci_dev *pdev) +{ + struct Scsi_Host *host = pci_get_drvdata(pdev); + struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; + +#if LINUX_VERSION_CODE >= 0x020600 + scsi_remove_host(host); +#endif + + WRT_REG_WORD(&ha->iobase->ictrl, 0); + + free_irq(pdev->irq, ha); + +#if MEMORY_MAPPED_IO + iounmap(ha->mmpbase); +#else + release_region(host->io_port, 0xff); +#endif + + pci_free_consistent(ha->pdev, + ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))), + ha->request_ring, ha->request_dma); + pci_free_consistent(ha->pdev, + ((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))), + ha->response_ring, ha->response_dma); + + scsi_host_put(host); +} + +#if LINUX_VERSION_CODE >= 0x020600 +static struct pci_driver qla1280_pci_driver = { + .name = "qla1280", + .id_table = qla1280_pci_tbl, + .probe = qla1280_probe_one, + .remove = __devexit_p(qla1280_remove_one), +}; + +static int __init +qla1280_init(void) +{ + if (sizeof(struct srb) > sizeof(Scsi_Pointer)) { + printk(KERN_WARNING + "qla1280: struct srb too big, aborting\n"); + return -EINVAL; + } + +#ifdef MODULE + /* + * If we are called as a module, the qla1280 pointer may not be null + * and it would point to our bootup string, just like on the lilo + * command line. IF not NULL, then process this config string with + * qla1280_setup + * + * Boot time Options + * To add options at boot time add a line to your lilo.conf file like: + * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}" + * which will result in the first four devices on the first two + * controllers being set to a tagged queue depth of 32. + */ + if (qla1280) + qla1280_setup(qla1280); +#endif + + return pci_module_init(&qla1280_pci_driver); +} +static void __exit +qla1280_exit(void) +{ + pci_unregister_driver(&qla1280_pci_driver); +} + +module_init(qla1280_init); +module_exit(qla1280_exit); + +#else +# define driver_template qla1280_driver_template +# include "scsi_module.c" +#endif + +MODULE_AUTHOR("Qlogic & Jes Sorensen"); +MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver"); +MODULE_LICENSE("GPL"); /* * Overrides for Emacs so that we almost follow Linus's tabbing style. diff -puN drivers/scsi/qla1280.h~qla1280-update drivers/scsi/qla1280.h --- 25/drivers/scsi/qla1280.h~qla1280-update 2003-12-29 02:33:41.000000000 -0800 +++ 25-akpm/drivers/scsi/qla1280.h 2003-12-29 02:33:41.000000000 -0800 @@ -1021,11 +1021,7 @@ struct scsi_qla_host { unsigned char *mmpbase; /* memory mapped address */ unsigned long host_no; - unsigned long instance; struct pci_dev *pdev; - uint32_t device_id; - uint8_t pci_bus; - uint8_t pci_device_fn; uint8_t devnum; uint8_t revision; uint8_t ports; @@ -1040,18 +1036,9 @@ struct scsi_qla_host { /* BUS configuration data */ struct bus_param bus_settings[MAX_BUSES]; -#if 0 - /* bottom half run queue */ - struct tq_struct run_qla_bh; -#endif - /* Received ISP mailbox data. */ volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; -#ifdef UNUSED - struct timer_list dev_timer[MAX_TARGETS]; -#endif - dma_addr_t request_dma; /* Physical Address */ request_t *request_ring; /* Base virtual address */ request_t *request_ring_ptr; /* Current address. */ @@ -1063,15 +1050,6 @@ struct scsi_qla_host { struct response *response_ring_ptr; /* Current address. */ uint16_t rsp_ring_index; /* Current index. */ -#if WATCHDOGTIMER - /* Watchdog queue, lock and total timer */ - uint8_t watchdog_q_lock; /* Lock for watchdog queue */ - struct srb *wdg_q_first; /* First job on watchdog queue */ - struct srb *wdg_q_last; /* Last job on watchdog queue */ - uint32_t total_timeout; /* Total timeout (quantum count) */ - uint32_t watchdogactive; -#endif - struct srb *done_q_first; /* First job on done queue */ struct srb *done_q_last; /* Last job on done queue */ _